pub struct Flux { /* private fields */ }Expand description
A quantity spread over an interface’s faces, in SI units.
An amount per face rather than a density, so that summing is meaningful and the total is a total. A density would need the areas to be carried alongside every arithmetic operation, and the one thing this type must make easy is adding up.
Implementations§
Source§impl Flux
impl Flux
Sourcepub fn zeros(faces: usize) -> Flux
pub fn zeros(faces: usize) -> Flux
Nothing, spread over the given number of faces. At least one face, so an empty flux is not a special case every consumer has to handle.
Sourcepub fn from_faces(per_face: Vec<f64>) -> Flux
pub fn from_faces(per_face: Vec<f64>) -> Flux
Amounts per face, in SI base units and in the interface’s own order.
Sourcepub fn spread_over(total: f64, interface: &Interface) -> Flux
pub fn spread_over(total: f64, interface: &Interface) -> Flux
One number spread over an interface in proportion to face area.
The honest way to turn a lumped quantity into a distributed one: it says “evenly, because I do not know better” rather than silently putting everything on the first face. Which is what the lumped coupling was doing.
Sourcepub fn profiled<F>(total: f64, interface: &Interface, profile: F) -> Flux
pub fn profiled<F>(total: f64, interface: &Interface, profile: F) -> Flux
Distribute a total over an interface following a shape.
profile is called with each face’s centre as a fraction of the way along the
boundary, from 0 to 1 in cumulative area, and returns an unnormalised weight. So a
beam of waist w centred on a boundary of length l is
|u| (-2.0 * (((u - 0.5) * l / w).powi(2))).exp(), written the way the physics is
written rather than as a table of numbers.
The weights are scaled so the faces sum to total exactly. Which splits the two
claims deliberately: the total is exact, because a coupling that loses energy is
a bug the audit must be able to trust, and the shape is midpoint-accurate,
because a face gets its centre’s weight rather than the profile’s integral over it.
The shape error falls as the boundary is refined; the total’s does not exist.
A profile summing to zero — all weights zero, or positives and negatives
cancelling — has no scale to normalise against, so it falls back to spreading by
area. That is a defined answer rather than infinities, and it is the same answer
Flux::spread_over gives.
Sourcepub fn faces(&self) -> usize
pub fn faces(&self) -> usize
How many faces this flux covers. Must match the interface it is published on.
Sourcepub fn total(&self) -> f64
pub fn total(&self) -> f64
Summed in index order, so the total is a function of the data and not of how it was visited.
Sourcepub fn largest(&self) -> f64
pub fn largest(&self) -> f64
Largest single face’s amount, which is the scale a rounding tolerance should be
judged against for the same reason Ledger records one.
Sourcepub fn add(&mut self, other: &Flux) -> Result<(), Violation>
pub fn add(&mut self, other: &Flux) -> Result<(), Violation>
Add another flux face by face. Refuses a mismatched face count rather than truncating or padding.
Sourcepub fn resample(
&self,
from: &Interface,
to: &Interface,
) -> Result<Flux, Violation>
pub fn resample( &self, from: &Interface, to: &Interface, ) -> Result<Flux, Violation>
Redistribute onto a different interface, conserving the total.
Faces are treated as consecutive intervals in cumulative area, and each source face’s amount is divided among the target faces it overlaps in proportion to how much of it each covers. The overlap fractions of any source face sum to one, so the total survives by construction rather than by a corrective scaling afterwards — which is the difference between a resampling that conserves and one that is checked and then adjusted.
It conserves to summation rounding, not to the last bit: the pieces are added in a
different order than they were split. That is a part in 10¹⁵, and it is why the
audit’s tolerance is relative.
Note what this cannot do. Redistributing by area assumes the two interfaces cover the same boundary in the same order, which is a statement about the geometry that this type has no way to check. It is a remap, not a projection between arbitrary meshes.