Multiphase Interfaces: VOF and PLIC Reconstruction
using RasmahOverview
In two-phase flow a volume fraction F ∈ [0,1] marks where each fluid is. The volume-of-fluid (VOF) method advects F conservatively; PLIC (piecewise-linear interface construction) then rebuilds a sharp interface inside each cell from F and its gradient, exactly matching the cell volume. Rasmah implements the analytic 2D PLIC (Scardovelli & Zaleski 2000) and verifies it.
The PLIC offset
For a unit cell and a normal n = (n₁, n₂) (fluid → void), the interface line n₁x + n₂y = α cuts off a volume F. Rasmah inverts this exactly:
# the diagonal interface F = 0.5, normal (1,1): α must equal 1
println("α(F=0.5, n=(1,1)) = ", plic_alpha(0.5, 1.0, 1.0))
# round-trip: volume(α(F)) == F for any normal
println("round-trip max err = ",
maximum(abs(plic_volume_fraction(plic_alpha(F, 1.0, 2.0), 1.0, 2.0) - F) for F in 0:0.01:1))α(F=0.5, n=(1,1)) = 1.0
round-trip max err = 1.1102230246251565e-16
Reconstructing a circle
Build an area-weighted volume fraction of a circle, then reconstruct the interface segments in every mixed cell:
n = 64
F = zeros(n, n)
for j in 1:n, i in 1:n
# area-weighted (anti-aliased) fraction inside a circle of radius 0.3
hits = 0
for sj in 1:4, si in 1:4
cx = (i - 1 + (si - 0.5)/4) / n
cy = (j - 1 + (sj - 0.5)/4) / n
(cx - 0.5)^2 + (cy - 0.5)^2 < 0.3^2 && (hits += 1)
end
F[j, i] = hits / 16
end
segs = plic_reconstruct(F)
println("area = ", round(sum(F)/n^2; digits=4), " (analytic π·0.3² = ", round(pi*0.3^2; digits=4), ")")
println("reconstructed ", length(segs), " interface segments")area = 0.283 (analytic π·0.3² = 0.2827)
reconstructed 108 interface segments
The reconstructed area matches the circle, and every mixed cell gets a straight segment whose normal follows −∇F.
Next steps
- Two-phase flow — the level-set interface counterpart
- Navier–Stokes — the flow that advects the interface
- Compressible flow — shock-capturing transport
