Discrete aggregates in a 2D lattice transport mesh

Concrete is a matrix with low-permeability aggregates embedded in it. With OOFEM's aggregate-packer feeding the lattice mesher, the wetting front threads naturally around each disk.

The first two posts in this series (verification against the 1D analytical and lumped vs consistent capacity under van Genuchten) held the medium homogeneous and varied just one numerical knob at a time. Concrete is not homogeneous — at the meso-scale it is a cement paste matrix with stiff, almost impermeable aggregates packed inside. This third post puts those aggregates in explicitly and watches the wetting front go around them.

The mesh

A random aggregate packing is generated by the aggregate tool from a prescribed grading curve and target volume fraction, then handed to the generator mesh tool through the converter’s #@inclusionfile directive. The mesher places lattice nodes outside the aggregate boundaries and adds anchor pairs at the disk-boundary intersections so the Voronoi tessellation respects the inclusion outlines. Any lattice element that crosses into a disk is tagged as aggregate material; everything else stays matrix.

For this example: 100×100 mm specimen, 30% aggregate area fraction, diameters 5–12 mm. Matrix permeability 2×10⁻⁵, aggregate permeability 2×10⁻⁹ — a 10 000× contrast. The matrix permeability is chosen so the wetting front reaches the bottom ~45 mm of the specimen over the simulated 100 s; that’s deep enough to wrap around several rows of aggregates without the front blowing past them entirely. The capacity is constant and equal in both phases (we’re isolating heterogeneity here, not constitutive nonlinearity; see the previous post for the latter).

The wetting front

Bottom face saturated, dry initial condition. The pressure contour over the simulated time:

A few things are worth pointing out:

Why discrete (and not effective)

For coarse-scale predictions the effective-medium models work well. They’re fast and they’re enough when the question is “what’s the average diffusivity”. They aren’t enough when the question is “where does the front go” — for transport-driven durability (sulphate ingress, chloride penetration, carbonation, freeze-thaw), the front geometry is the engineering output. Modelling the aggregates discretely gives you that geometry directly.

The same mesh works for coupled mechanical-transport problems — the mechanical lattice (on the Delaunay edges) and the transport lattice (on the dual Voronoi edges) live on the same underlying Voronoi–Delaunay tessellation, so cracks and ingress can interact in one model. That’s the direction the next set of posts is heading.

Reproduce

git clone https://github.com/githubgrasp/oofem-examples.git
cd oofem-examples/lattice-aggregate-flow-2d
docker run --rm -v "$PWD":/work ghcr.io/githubgrasp/oofem-public:lattice-aggregate-flow-2d bash run.sh

The :lattice-aggregate-flow-2d image tag is immutable — use :latest instead to track the current OOFEM build.

The example folder is at github.com/githubgrasp/oofem-examples/lattice-aggregate-flow-2d; issues and questions go on the issue tracker.

Built with OOFEM.

← All posts