Building a fractured-rock material
FracturedPoroelasticRock is the material of [71]: two gradients
Ingredients
an RVE whose crack families are ConductiveCrack | mechanics and hydraulics from one microstructure |
ω₀ | the initial aspect ratios — what the cubic law is normalized on |
k_matrix | the matrix conductivity: small, but not zero |
| a scheme | SelfConsistent() for a connected network, MoriTanaka() for a dilute one |
using MeanFieldHomogenization, TensND
C₀, kₛ, C_f = TensISO{3}(3 * 30.0, 2 * 18.0), 1.0e-18, 4.0e-18
props = Dict(:C => C₀, :K => TensISO{3}(kₛ))
rve = RVE()
add_phase!(rve, :M, Ellipsoid(1.0), props; fraction = :rest)
add_phase!(rve, :F, ConductiveCrack(1.0; conductivity = C_f), props; density = 0.1)
mat = FracturedPoroelasticRock(rve, MoriTanaka(); ω₀ = (1.0e-3,), k_matrix = kₛ)
cache = MaterialCache()
st = initial_state(mat)One call, everything the FE code needs
ε = from_tensors(TensND.Tensors.SymmetricTensor{2,3}((i,j) -> i == j == 3 ? -5.0e-4 : 0.0))
r = material_response(mat, (; ε = ε, p = 0.0), st, 0.0; cache = cache)
(σ₃₃ = r.fluxes.σ[3,3], φ = r.fluxes.φ,
B₃₃ = -r.tangents.σp[3,3], invM = r.tangents.φp,
ω = apertures(state(r))[1], k = transport_property(mat, state(r))[1,1])(σ₃₃ = -0.016875000000000005, φ = -0.00018749999999999984, B₃₃ = 0.37499999999999967, invM = 0.006944444444444439, ω = 0.0005523767225540443, k = 1.1128708042848248e-18)The gradients go in as a NamedTuple, the fluxes and the four tangent blocks come out of one response, and the permeability is read off the new state — transport_property rather than a flux, because it feeds a different balance equation.
A transient flow problem also needs fluid_content recomputes it from the stored state, so a driver never has to carry it alongside.
Δφ = r.fluxes.φ - fluid_content(mat, st)-0.00018749999999999984Compression closes the fracture, pressure reopens it
Holding that compressive strain and raising the pore pressure reopens the fracture, and the permeability recovers with it — the coupling the model exists to capture:
| 0 | 0.005 | 0.010 | |
|---|---|---|---|
| 5.52·10⁻⁴ | 6.35·10⁻⁴ | 7.18·10⁻⁴ | |
| 1.11·10⁻¹⁸ | 1.15·10⁻¹⁸ | 1.20·10⁻¹⁸ |
Once a family closes it leaves the intact matrix behind: transport_property returns nothing — the fracture carries no flow at all.
Returning nothing is an answer, not a failure
A driver that forwards it straight into a mobility gets a MethodError at the worst possible moment. Test for it — the well test does.