Scale transition
Before this page
Finite-element coupling, for the role a homogenized microstructure plays at a quadrature point, and Homogenization schemes, whose effective stiffness is the material response below. The poroelastic blocks use the Biot coefficients of Poromechanics.
This page states what a finite-element code asks of a material at each quadrature point and how a homogenization scheme answers it: a stress, a consistent tangent and an updated state, then the blocks of that tangent when the material takes several gradients. It closes on the convention a coupling cannot afford to get wrong, the basis in which a TensND tensor stores its components.
What the FE code needs
At each quadrature point a finite-element code solving a nonlinear problem needs two things from the material, per step:
the stress and the consistent tangent, together with the updated internal state
Where homogenization enters
The material response is a homogenization: the strain drives an RVE, the scheme returns its effective stiffness, and
All the nonlinearity sits in
is exact, not an approximation. No numerical differentiation is needed, and no algorithmic tangent has to be derived: the scheme already returns it.
This is what makes the coupling affordable
Because MaterialCache.
Several gradients, several fluxes
A poroelastic material takes a strain and a pore pressure, and returns a stress and a variation of fluid content:
The contract is therefore written with named gradients and fluxes, and the tangent as a set of blocks keyed flux then gradient:
| block | value | key |
|---|---|---|
:σε | ||
:σp | ||
:φε | ||
:φp |
A purely mechanical law declares only :σε and never sees the rest. This is the same shape MGIS uses for MFront's generic behaviors.
The one rule that bites
A Tensors.jl tensor — what Ferrite and every Julia FE code speaks — has no basis: its components are always global.
A TensND tensor returns its components in its own basis, and a homogenized stiffness whose RVE carries tilted crack families comes back in a rotated basis. Handing its raw array to an FE assembler rotates the material silently. Cross the boundary with to_tensors and from_tensors, never with get_array.
using MeanFieldHomogenization, TensND
C₀ = TensISO{3}(3 * 30.0, 2 * 18.0)
rve = RVE()
add_phase!(rve, :M, Ellipsoid(1.0), Dict(:C => C₀); fraction = :rest)
add_phase!(rve, :F, PennyCrack(1.0; euler_angles = (π / 4, 0.0)), Dict(:C => C₀);
density = 0.08)
C_hom = homogenize(rve, MoriTanaka())
raw = get_array(C_hom)[1, 1, 1, 1] # components in ITS OWN basis
global_ = to_tensors(C_hom)[1, 1, 1, 1] # components an FE code expects
(raw, global_)(52.054054054054056, 43.43360752056405)The two differ: the first is expressed in the crack frame, the second in the global one.
Where to go next
The coupled poroelastic problem writes the balance equations that consume the four tangent blocks above, and Materials turns the contract of this page into code.