Materials
A material bundles a microstructure, a scheme and its internal state. The FE driver builds it once, allocates one state per quadrature point, and calls material_response in its element loop.
The contract
Two methods make a material:
initial_state(m) # the state a fresh point starts from
material_response(m, ε, state_old, Δt; cache) # -> MaterialResponseand a response carries three things:
| accessor | |
|---|---|
stress | the flux |
tangent | the consistent tangent |
state | the new internal state |
state_old is never mutated. That is what lets a rejected Newton iteration be retried by simply keeping the old state, and what makes a threaded element loop safe.
A linear material, end to end
using MeanFieldHomogenization, TensND
C₀ = TensISO{3}(3 * 30.0, 2 * 18.0) # matrix: k = 30, μ = 18
rve = RVE()
add_phase!(rve, :M, Ellipsoid(1.0), Dict(:C => C₀); fraction = :rest)
add_phase!(rve, :I, Ellipsoid(1.0), Dict(:C => TensISO{3}(3 * 90.0, 2 * 60.0));
fraction = 0.2)
mat = HomogenizedElastic(rve, MoriTanaka())
st = initial_state(mat)
ε = from_tensors(TensND.Tensors.SymmetricTensor{2, 3}((i, j) -> i == j ? 1.0e-3 : 0.0))
r = material_response(mat, ε, st, 0.0)
σ = to_tensors(stress(r)) # Tensors.SymmetricTensor{2,3}, global frame
ℂ = to_tensors(tangent(r)) # Tensors.SymmetricTensor{4,3}, global frame
σ[1, 1]0.10905882352941176to_tensors is the only sanctioned way out — see the frame rule.
Checking a material
check_material_interface exercises the contract and, crucially, compares the declared tangent against a central finite difference:
check_material_interface(mat)trueMaking the scheme solve affordable
A self-consistent solve on a cracked, anisotropic RVE costs milliseconds — far too much per quadrature point, per Newton iteration, per step. But for flat cracks the compliance contribution MaterialCache and every point sharing a configuration pays once:
cache = MaterialCache()
for _ in 1:1000
material_response(mat, ε, st, 0.0; cache = cache)
end
cache_stats(cache)(hits = 0, misses = 0, entries = 0)One cache per thread
A MaterialCache is an unlocked Dict. Sharing one across threads is a data race whose symptom would be a wrong stiffness, not an error.
Shipped materials
HomogenizedElastic | linear, from any cell and scheme — the control case for a new coupling |
MicrocrackedMaterial | crack families that open and close; piecewise linear, so the tangent is exact |
FracturedPoroelasticRock | the same, saturated: two gradients |
MicrocrackedMaterial carries the aperture
with crack_family_compliances). Steps are split at every closure and reopening, so the result does not depend on how the loading was subdivided. See it at work on the thick-walled cylinder.