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

from typing import Any

import quadrants as qd
from pydantic import StrictBool

import genesis as gs
from genesis.typing import NonNegativeFloat, PositiveFloat, ValidFloat

from .base import Base


[docs]@qd.data_oriented class ElastoPlastic(Base): """ The elasto-plastic 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³). Default is 1000. yield_lower : float, optional Lower bound for the yield clamp (ignored if using von Mises). Default is 2.5e-2. yield_higher : float, optional Upper bound for the yield clamp (ignored if using von Mises). Default is 4.5e-3. use_von_mises : bool, optional Whether to use von Mises yield criterion. Default is True. von_mises_yield_stress : float, optional Yield stress for von Mises criterion. Default is 10000. """ yield_lower: NonNegativeFloat = 2.5e-2 yield_higher: NonNegativeFloat = 4.5e-3 use_von_mises: StrictBool = True von_mises_yield_stress: PositiveFloat = 10000.0
[docs] def model_post_init(self, context: Any) -> None: super().model_post_init(context) self.update_F_S_Jp = self._update_F_S_Jp_elasto_plastic
@qd.func def _update_F_S_Jp_elasto_plastic(self, J, F_tmp, U, S, V, Jp): F_new = qd.Matrix.zero(gs.qd_float, 3, 3) S_new = qd.Matrix.zero(gs.qd_float, 3, 3) if qd.static(self.use_von_mises): S_new = qd.max(S, 0.05) # to prevent NaN epsilon = qd.Vector([qd.log(S_new[0, 0]), qd.log(S_new[1, 1]), qd.log(S_new[2, 2])]) epsilon_hat = epsilon - (epsilon.sum() / 3) epsilon_hat_norm = epsilon_hat.norm(gs.EPS) delta_gamma = epsilon_hat_norm - self.von_mises_yield_stress / (2 * self.mu) if delta_gamma > 0: # Yields epsilon -= (delta_gamma / epsilon_hat_norm) * epsilon_hat S_new = qd.Matrix.zero(gs.qd_float, 3, 3) for d in qd.static(range(3)): S_new[d, d] = qd.exp(epsilon[d]) F_new = U @ S_new @ V.transpose() else: F_new = F_tmp else: S_new = qd.Matrix.zero(gs.qd_float, 3, 3) for d in qd.static(range(3)): S_new[d, d] = min(max(S[d, d], 1 - self.yield_lower), 1 + self.yield_higher) F_new = U @ S_new @ V.transpose() Jp_new = Jp return F_new, S_new, Jp_new