Building a fractured-rock material
Before this page
Materials, for the contract the material below fulfills, and Fractured permeability, for the conductive cracks it is built from.
FracturedPoroelasticRock is the material of (Barthélémy and Daniel, 2011): 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.006944444444444436, ω = 0.0005523767225540443, k = 1.1128708042848304e-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: its contributions to the Biot tensor and to the inverse Biot modulus vanish, 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.
Where to go next
Ferrite backend provides the element routines that call this material inside a finite-element loop, and A fractured-reservoir well test runs it on a fractured reservoir.