Skip to content

Building a fractured-rock material

FracturedPoroelasticRock is the material of [71]: two gradients in, two fluxes out, plus a permeability that follows the fracture apertures. The equations it implements are on the coupled poroelastic problem; this page is how to build one and what it returns.

Ingredients

an RVE whose crack families are ConductiveCrackmechanics and hydraulics from one microstructure
ω₀the initial aspect ratios — what the cubic law is normalized on
k_matrixthe matrix conductivity: small, but not zero
a schemeSelfConsistent() for a connected network, MoriTanaka() for a dilute one
julia
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

julia
ε = 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 at the start of the step: fluid_content recomputes it from the stored state, so a driver never has to carry it alongside.

julia
Δφ = r.fluxes.φ - fluid_content(mat, st)
-0.00018749999999999984

Compression 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:

(GPa)00.0050.010
5.52·10⁻⁴6.35·10⁻⁴7.18·10⁻⁴
(m²)1.11·10⁻¹⁸1.15·10⁻¹⁸1.20·10⁻¹⁸

Once a family closes it leaves the intact matrix behind:  ,   and 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.