123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- """Cauchy-Green and Green-Lagrange strain tensors on a 2D grid."""
- import numpy as np
- import vedo
- # Define a simple deformation function
- def deform(x, y):
- xd = np.array([x + 0.25 * x * x,
- y + 0.25 * x * y])
- # Add rotation to the deformation.
- # note that the rotation is applied to the deformed configuration
- # and it has no effect on the deformation gradient tensor C and E
- rotation_angle_degrees = 10
- rotation_angle_radians = np.radians(rotation_angle_degrees)
- cos_angle = np.cos(rotation_angle_radians)
- sin_angle = np.sin(rotation_angle_radians)
- x_def, y_def = xd
- x_rot = x_def * cos_angle - y_def * sin_angle
- y_rot = x_def * sin_angle + y_def * cos_angle
- return np.array([x_rot, y_rot])
- # Compute the deformation gradient tensor F
- def deformation_gradient(x, y, ds=0.001):
- # Compute the deformation gradient tensor F
- # F = (df/dx, df/dy)
- fxy = deform(x, y)
- fxy_x = deform(x + ds, y)
- fxy_y = deform(x, y + ds)
- F = np.zeros((2, 2))
- F[0, 0] = (fxy_x[0] - fxy[0]) / ds
- F[0, 1] = (fxy_y[0] - fxy[0]) / ds
- F[1, 0] = (fxy_x[1] - fxy[1]) / ds
- F[1, 1] = (fxy_y[1] - fxy[1]) / ds
- return F
- # Compute the right Cauchy-Green deformation tensor C
- def cauchy_green(F):
- return F.T @ F
- # Right Cauchy-Green tensor (C) is used to define the Green-Lagrange
- # strain tensor (E), which is a measure of deformation in the reference
- # (undeformed) configuration:
- def green_lagrange(C):
- return 0.5 * (C - np.eye(2))
- # Left Cauchy-Green tensor (B) is used to define the Almansi strain tensor (e),
- # which is a measure of deformation in the current (deformed) configuration:
- # e = 0.5 * (I - B^-1) (this is less used in practice)
- def almansi(F):
- B = F @ F.T
- return 0.5 * (np.eye(2) - np.linalg.inv(B))
- # Compute the principal stretches and directions
- def principal_stretches_directions(T):
- # T is a symmetric tensor
- # eigenvalues are sorted in ascending order
- eigenvalues, eigenvectors = np.linalg.eigh(T)
- principal_stretches = np.sqrt(np.abs(eigenvalues))*np.sign(eigenvalues)
- return principal_stretches, eigenvectors
- ######################################################################
- # Define the original grid (undeformed configuration)
- x, y = np.meshgrid(np.linspace(-1, 1, 8), np.linspace(-1, 1, 8))
- grid = vedo.Grid(s=(x[0], y.T[0]))
- grid_pts = grid.points
- grid_pts_defo = deform(grid_pts[:, 0], grid_pts[:, 1])
- grid_defo = grid.clone()
- grid_defo.points = grid_pts_defo.T
- # Initialize the vedo plotter
- plotter = vedo.Plotter()
- for i in range(x.shape[0]):
- for j in range(y.shape[1]):
- pt = x[i, j], y[i, j]
- displaced_pt = deform(*pt)
- F = deformation_gradient(*pt)
- C = cauchy_green(F)
- stretches, directions = principal_stretches_directions(C)
- ellipsoid_axes = np.diag(stretches) @ directions.T / 8
- ellipsoid_C = vedo.Ellipsoid(
- axis1=ellipsoid_axes[0],
- axis2=ellipsoid_axes[1],
- axis3=[0, 0, 0.01],
- pos=(*pt, 0),
- )
- ellipsoid_C.lighting("off").color("blue5")
- E = green_lagrange(C)
- # E = almansi(F)
- stretches, directions = principal_stretches_directions(E)
- ellipsoid_axes = np.diag(stretches) @ directions.T / 8
- ellipsoid_E = vedo.Ellipsoid(
- axis1=ellipsoid_axes[0],
- axis2=ellipsoid_axes[1],
- axis3=[0, 0, 0.01],
- pos=(*pt, 0),
- ).z(0.01)
- ellipsoid_E.lighting("off").color("purple5")
- if stretches[0] < 0 or stretches[1] < 0:
- ellipsoid_E.c("red4")
- # Plot the deformation gradient tensor, we cannot compute the
- # principal stretches and directions of the deformation gradient
- # tensor because it is not a symmetric tensor.
- # F = deformation_gradient(*pt)
- # circle = vedo.Circle(r=0.05).pos(*pt).color("black")
- # cpts = circle.points
- # cpts_defo = F @ cpts.T[:2]
- # circle.points = cpts_defo.T
- # Same as:
- circle = vedo.Circle(r=0.06).pos(*pt).color("black")
- cpts = circle.points
- cpts_defo = deform(cpts[:,0], cpts[:,1])
- circle.points = cpts_defo.T
- plotter += [ellipsoid_C, ellipsoid_E, circle]
- pts = np.array([x, y]).T.reshape(-1, 2)
- defo_pts = deform(x, y).T.reshape(-1, 2)
- plotter += vedo.Arrows2D(pts, defo_pts, s=0.2).color("blue5")
- plotter += grid_defo
- plotter += __doc__
- plotter.show(axes=8, zoom=1.2)
- #####################################################################
- # Resources:
- # https://en.wikipedia.org/wiki/Deformation_gradient
- # https://en.wikipedia.org/wiki/Almansi_strain_tensor
- # https://en.wikipedia.org/wiki/Principal_stretch
- # https://www.continuummechanics.org/deformationstrainintro.html
|