pub trait Domain {
// Required methods
fn name(&self) -> &'static str;
fn step(
&mut self,
t: Time,
dt: Time,
bus: &mut Exchange,
) -> Result<(), Violation>;
// Provided methods
fn kind(&self) -> Kind { ... }
fn max_stable_dt(&self, now: Time) -> Time { ... }
fn residual(&self) -> f64 { ... }
fn ledger(&self) -> Ledger { ... }
fn checkpoint(&mut self) { ... }
fn restore(&mut self) { ... }
fn supports_restore(&self) -> bool { ... }
fn as_any(&self) -> Option<&dyn Any> { ... }
}Expand description
One piece of physics.
The only required methods are the name and the step; the rest have defaults that describe a well-behaved evolving domain with no stability limit and no books to keep.
Required Methods§
Sourcefn name(&self) -> &'static str
fn name(&self) -> &'static str
What this domain is called. Used to look it up and to name it in a violation.
Sourcefn step(
&mut self,
t: Time,
dt: Time,
bus: &mut Exchange,
) -> Result<(), Violation>
fn step( &mut self, t: Time, dt: Time, bus: &mut Exchange, ) -> Result<(), Violation>
Advance by dt from t, reading inputs from bus and publishing outputs
to it. A quasi-static domain ignores dt.
Must be a pure function of its state and its inputs: no wall clock, no
unordered reduction, no shared generator. Rng::for_index
is how a domain gets randomness without giving that up.
Provided Methods§
Sourcefn kind(&self) -> Kind
fn kind(&self) -> Kind
Whether it has state to roll forward. Defaults to Kind::Evolving.
Sourcefn max_stable_dt(&self, now: Time) -> Time
fn max_stable_dt(&self, now: Time) -> Time
The largest step this domain can take from now and stay stable — a CFL
condition, a diffusion limit, a contact penetration budget.
Infinite means “no limit”, which is the honest answer for a quasi-static domain and for a linear one being solved implicitly.
Sourcefn residual(&self) -> f64
fn residual(&self) -> f64
How far this domain still is from agreeing with its neighbours, for
Schedule::Iterative. Zero means converged.
Sourcefn checkpoint(&mut self)
fn checkpoint(&mut self)
Save state so an iterative sweep can be re-run from the same starting
point. A domain that does not implement this cannot take part in
Schedule::Iterative, and Simulation::advance says so rather than
silently iterating from the wrong state.
Sourcefn restore(&mut self)
fn restore(&mut self)
Restore the last Domain::checkpoint.
Sourcefn supports_restore(&self) -> bool
fn supports_restore(&self) -> bool
Whether Domain::checkpoint and Domain::restore actually do something.
Schedule::Iterative refuses to run a domain that says no, rather than iterating
from the wrong state and reporting a residual that means nothing.
Sourcefn as_any(&self) -> Option<&dyn Any>
fn as_any(&self) -> Option<&dyn Any>
This domain as Any, so a caller can get the concrete type back out of a
Simulation — see Simulation::domain_as.
Opt-in, and returning None by default, because it cannot be automatic. Deriving it
from the trait would need Domain: Any plus upcasting dyn Domain to dyn Any,
which is a newer Rust than this crate promises. A domain that wants to be inspected
writes fn as_any(&self) -> Option<&dyn Any> { Some(self) } and is done.
The coupling never needs this: domains meet through Exchange and nothing else,
which is the property the whole design rests on. What needs it is everything around
the simulation — a test asserting a temperature profile, a visualiser drawing one —
and that is a reader, not a participant.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".