///|
/// Conservative piecewise-constant overlap remapping on the exact same domain.
/// Integrated mass/momentum/energy are preserved to floating-point summation error.
pub fn Gas::remap(
self : Gas,
source : Mesh,
cells : Array[Conserved],
target : Mesh,
) -> Array[Conserved] raise GasError {
self.validate_cells(source, cells)
if source.left != target.left || source.right != target.right {
raise Invalid("remap domains must have identical edges")
}
let output = []
let mut from = 0
for j in 0.. 0.0 {
total = total.plus(cells[i].scaled(overlap))
covered = covered + overlap
}
i = i + 1
}
let width = b - a
if covered <= 0.0 || (covered - width).abs() > 1.0e-10 * width {
raise Numerical("remap overlap coverage failed")
}
let u = total.scaled(1.0 / target.dx)
ignore(self.primitive(u))
output.push(u)
}
output
}
///|
/// Remapping starts a new conservation ledger at the same physical time.
/// Accepted-step/retry counters restart; source checkpoint remains unchanged.
pub fn Simulation::remeshed(
self : Simulation,
target : Mesh,
) -> Simulation raise GasError {
Simulation::new(
self.gas,
target,
self.gas.remap(self.mesh, self.cells, target),
time=self.time,
)
}
///|
/// Integrate an interval of piecewise constant conserved cell averages.
pub fn Gas::integrate(
self : Gas,
mesh : Mesh,
cells : Array[Conserved],
left : Double,
right : Double,
) -> Conserved raise GasError {
self.validate_cells(mesh, cells)
if !finite(left) ||
!finite(right) ||
left < mesh.left ||
right > mesh.right ||
right < left {
raise Invalid("invalid integration interval")
}
let mut total = Conserved::zero()
for i in 0.. 0.0 {
total = total.plus(cells[i].scaled(overlap))
}
}
if !finite(total.mass) || !finite(total.momentum) || !finite(total.energy) {
raise Numerical("interval integral overflow")
}
total
}