| """The 5-material zoo from W4-5 and its analytic admissible-set rules. |
| |
| Single source of truth for material definitions and the analytic local |
| projection they imply (mirrors PDSolver3D._project_local); W7's fluid |
| token extends this list with "water" at index 5. |
| """ |
| import numpy as np |
|
|
| MATERIALS = { |
| "steel": dict(stiffness=5e6, strain_limit=0.012), |
| "rubber": dict(stiffness=1e5, strain_limit=0.35, incompressible=True), |
| "foam": dict(stiffness=2e5, |
| strain_limit=[0.30, 0.30, 0.30, 0.06, 0.06, 0.06]), |
| "composite": dict(stiffness=8e5, |
| strain_limit=[0.20, 0.02, 0.02, 0.12, 0.02, 0.12]), |
| "gel": dict(stiffness=1.2e5, strain_limit=0.15), |
| } |
|
|
|
|
| def apply_limit(e, mat): |
| """The material's admissible-set projection on (N,6) strain.""" |
| lim = mat.get("strain_limit") |
| if np.ndim(lim) > 0: |
| e = np.clip(e, -np.asarray(lim), np.asarray(lim)) |
| elif lim is not None: |
| norm = np.linalg.norm(e, axis=1) |
| e = e * np.minimum(1.0, lim / np.maximum(norm, 1e-12))[:, None] |
| if mat.get("incompressible"): |
| e = e.copy() |
| e[:, :3] -= e[:, :3].mean(axis=1, keepdims=True) |
| return e |
|
|