Source code for genesis.engine.materials.MPM.sand

import numpy as np
import gstaichi as ti

import genesis as gs

from .base import Base


[docs] @ti.data_oriented class Sand(Base): """ The sand material class for MPM. Parameters ---------- E: float, optional Young's modulus. Default is 1e6. nu: float, optional Poisson ratio. Default is 0.2. rho: float, optional Density (kg/m^3). Default is 1000. lam: float, optional The first Lame's parameter. Default is None, computed by E and nu. mu: float, optional The second Lame's parameter. Default is None, computed by E and nu. sampler: str, optional Particle sampler ('pbs', 'regular', 'random'). Note that 'pbs' is only supported on Linux for now. Defaults to 'random'. friction_angle: float, optional Friction angle in degrees, used to compute internal pressure-dependent plasticity. Default is 45. """ def __init__( self, E=1e6, nu=0.2, rho=1000.0, lam=None, mu=None, sampler="random", friction_angle=45, ): super().__init__(E, nu, rho, lam, mu, sampler) self._default_Jp = 0.0 self.friction_angle = np.deg2rad(friction_angle) sin_phi = np.sin(self.friction_angle) self.alpha = np.sqrt(2 / 3) * 2 * sin_phi / (3 - sin_phi)
[docs] @ti.func def sand_projection(self, S, Jp): S_out = ti.Matrix.zero(gs.ti_float, 3, 3) epsilon = ti.Vector.zero(gs.ti_float, 3) for i in ti.static(range(3)): epsilon[i] = ti.log(max(abs(S[i, i]), 1e-4)) S_out[i, i] = 1 tr = epsilon.sum() + Jp epsilon_hat = epsilon - tr / 3 epsilon_hat_norm = epsilon_hat.norm(gs.EPS) Jp_new = gs.ti_float(0.0) if tr >= 0.0: Jp_new = tr else: Jp_new = 0.0 delta_gamma = epsilon_hat_norm + (3 * self._lam + 2 * self._mu) / (2 * self._mu) * tr * self.alpha for i in ti.static(range(3)): S_out[i, i] = ti.exp(epsilon[i] - max(0, delta_gamma) / epsilon_hat_norm * epsilon_hat[i]) return S_out, Jp_new
[docs] @ti.func def update_F_S_Jp(self, J, F_tmp, U, S, V, Jp): S_new, Jp_new = self.sand_projection(S, Jp) F_new = U @ S_new @ V.transpose() return F_new, S_new, Jp_new
[docs] @ti.func def update_stress(self, U, S, V, F_tmp, F_new, J, Jp, actu, m_dir): log_S_sum = gs.ti_float(0.0) center = ti.Matrix.zero(gs.ti_float, 3, 3) for i in ti.static(range(3)): log_S_sum += ti.log(S[i, i]) center[i, i] = 2.0 * self._mu * ti.log(S[i, i]) * (1 / S[i, i]) for i in ti.static(range(3)): center[i, i] += self._lam * log_S_sum * (1 / S[i, i]) stress = U @ center @ V.transpose() @ F_new.transpose() return stress