Mixture Laws

In a PLIC (Piecewise-Linear Interface Calculation) workflow the interface is reconstructed independently inside each cell, so any quantity that lives on a shared entity — a face aperture A — may receive two inconsistent candidate values, one from each adjacent cell.

  • V (cell volumes) and B (centroid-line apertures) are cell-local and need no post-processing.
  • W (staggered volumes) is already face-unique due to plic reconstruction.
  • A (face apertures) must be face-unique for correct div/grad assembly.

CartesianGeometry.mix_apertures! and CartesianGeometry.mix_staggers! collapse two candidate arrays into one shared-value array via a configurable mixture law, without touching any reconstruction backend.

Supported laws (pass as law=:symbol):

SymbolFormula
:meanarithmetic mean (xL + xR) / 2
:geomgeometric mean √(xL · xR)
:harmonicharmonic mean 2 xL xR / (xL + xR)
:minmin(xL, xR)
:maxmax(xL, xR)
:closest05whichever candidate is closer to 0.5
:softclosest05soft weighted average (weights 1/(abs(x−0.5)+ε)^p)
:pull05regularised mean pulled toward 0.5 by strength λ
:mixednessweighted by r(f)=4f(1−f) using per-cell fractions

Usage example:

using CartesianGeometry

# Suppose Penguin / your PLIC layer has produced two candidate arrays:
#   AL, AR   – left/right aperture candidates for each face
#   WL, WR   – left/right staggered-volume candidates

A = similar(AL)
W = similar(WL)

mix_apertures!(A, AL, AR; law=:softclosest05, p=2.0)
mix_staggers!(W, WL, WR; law=:mixedness, fL=fracL, fR=fracR)

# Use the unique A, W in divergence / gradient operators.

Scalar versions (mix_aperture, mix_stagger, mix01) and physical-unit helpers (mix_aperture_phys, mix_stagger_phys) are also exported.

CartesianGeometry.mix01Function
mix01(xL, xR; law=:mean, eps=eps(T), p=2, beta=10,
      lambda=zero(T), fL=nothing, fR=nothing, clamp=true)

Mix two normalised candidate values xL, xR ∈ [0,1] into a single shared value using the specified law.

Supported laws

SymbolFormula
:mean(xL + xR) / 2
:geom√(max(xL,0) · max(xR,0))
:harmonic2 xL xR / (xL + xR + ε)
:minmin(xL, xR)
:maxmax(xL, xR)
:closest05whichever of xL, xR is closer to 0.5 (mean on tie)
:softclosest05weighted average with `w = 1/(
:pull05minimiser of (x−xL)² + (x−xR)² + λ(x−0.5)²
:mixednessweighted average r(f) = 4f(1−f) using fL, fR

When clamp=true (default) the result is clamped to [0, 1].

source
CartesianGeometry.mix_apertures!Function
mix_apertures!(A, AL, AR; law=:mean, kwargs...)

Fill A[f] = mix_aperture(AL[f], AR[f]; ...) for every face index.

source
mix_apertures!(As, ALs, ARs; law=:mean, kwargs...)

Direction-tuple overload: As[d], ALs[d], ARs[d] are the face arrays for direction d.

source
CartesianGeometry.mix_staggers!Function
mix_staggers!(W, WL, WR; law=:mean, kwargs...)

Fill W[s] = mix_stagger(WL[s], WR[s]; ...) for every stagger index.

source
mix_staggers!(Ws, WLs, WRs; law=:mean, kwargs...)

Direction-tuple overload.

source
CartesianGeometry.mix_aperture_physFunction
mix_aperture_phys(AL, AR, ℓf; kwargs...) -> Af

Mix two physical face-aperture candidates (AL, AR) on a face of length ℓf. Normalises to [0,1], applies mix01, then scales back.

source

These helpers collapse two candidate values from adjacent cells into one shared face/stagger quantity using configurable laws (:mean, :geom, :harmonic, :closest05, :softclosest05, :pull05, :mixedness, ...).