Expand description
dualis-core: the kernel a simulated world’s physics is built on.
This crate knows nothing about any particular physics. It knows that a quantity can vary over space and time, that a process must answer for what it conserves, that a system with no closed form has to be rolled forward, that matter has properties several domains need at once, and that several domains sharing a clock is a scheduling problem with real failure modes. What any of that is about — light, heat, contact, sound — belongs to a domain crate.
That separation is the point. dualis-optics depends on this crate; this crate
must never depend on it, or anything else that models a specific physics. If a
new domain needs the kernel changed, the kernel was wrong.
§The two invariants
Both survive the generalisation, and both are now enforced rather than promised:
- Nothing is created or destroyed without being noticed. A
Ledgeris what a process claims to hold andauditis the check; energy crossing between domains goes throughExchange, which refuses to let a transfer silently lose some. This generalises whatSurfaceOpticsdid for one quantity at one kind of boundary. Where a boundary is resolved into faces, the audit is per face — a redistribution that keeps the total but moves it to the wrong part of a mirror is the one bug a total-only check cannot see. - Nothing is random.
Rng::for_indexgives every piece of work its own stateless stream, so a parallel simulation is still bit-reproducible — which is when the guarantee starts to matter, and when a single shared generator would have quietly lost it.
§What is here
| Module | |
|---|---|
conserved | Conservation as an audit: ledgers, violations, tolerances |
integrator | Fixed-step time evolution, and why symplectic beats accurate |
sim | Several domains on one clock: quasi-static, multirate, iterative coupling |
scene | Where two domains meet: shared boundaries, and flux that knows its place |
field | Scalar and vector fields, with gradient, divergence, curl, Laplacian |
substance | Thermal, mechanical and acoustic properties of matter |
motion | Closed-form rigid motion and time gating |
rng | A deterministic generator, and the sampling built on it |
transform | The discrete Fourier transform, accurate rather than fast |
vector | Basis construction and reflection — the vector maths no domain owns |
§A domain, and the audit that checks it
use dualis_core::conserved::quantity;
use dualis_core::{Domain, Exchange, Kind, Ledger, Schedule, Simulation, Violation};
use dualis_core::units::Time;
/// A source that pays out a watt, and says so in its books.
struct Lamp { paid: f64 }
impl Domain for Lamp {
fn name(&self) -> &str { "lamp" }
fn kind(&self) -> Kind { Kind::QuasiStatic }
fn step(&mut self, _t: Time, dt: Time, bus: &mut Exchange) -> Result<(), Violation> {
let joules = 1.0 * dt.to_si();
bus.publish(quantity::ENERGY, joules);
self.paid += joules;
Ok(())
}
// Negative: it is holding a debt, having handed the energy away.
fn ledger(&self) -> Ledger { Ledger::new().with(quantity::ENERGY, -self.paid) }
}
/// A sink that takes whatever is offered and keeps it.
struct Block { held: f64 }
impl Domain for Block {
fn name(&self) -> &str { "block" }
fn step(&mut self, _t: Time, _dt: Time, bus: &mut Exchange) -> Result<(), Violation> {
self.held += bus.take(quantity::ENERGY);
Ok(())
}
fn ledger(&self) -> Ledger { Ledger::new().with(quantity::ENERGY, self.held) }
// Opt in to being readable from outside. Without this, `domain_as` returns `None`:
// the coupling never needs the concrete type, so it is not given away by default.
fn as_any(&self) -> Option<&dyn std::any::Any> { Some(self) }
fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> { Some(self) }
}
let mut sim = Simulation::new(Schedule::Staggered)
.with(Lamp { paid: 0.0 })
.with(Block { held: 0.0 });
for _ in 0..10 {
sim.advance(Time::ms(100.0)).expect("the books balance");
}
// A joule went across, and the two ledgers cancel because nothing was lost.
let block: &Block = sim.domain_as("block").unwrap();
assert!((block.held - 1.0).abs() < 1e-12);
assert!(sim.ledger().get(quantity::ENERGY).unwrap().abs() < 1e-12);Had Block consumed only half of what was published, advance would have returned a
Violation naming the channel rather than quietly losing the rest.
Units come from dualis-units and are re-exported below, so a domain crate
needs one dependency rather than two.
Re-exports§
pub use conserved::audit;pub use conserved::Conserves;pub use conserved::Ledger;pub use conserved::Violation;pub use ensemble::Ensemble;pub use ensemble::Estimate;pub use field::ScalarField;pub use field::VectorField;pub use integrator::velocity_verlet;pub use integrator::Dynamics;pub use integrator::Integrator;pub use integrator::Newtonian;pub use integrator::State;pub use motion::Motion;pub use motion::Strobe;pub use rng::Rng;pub use scene::Flux;pub use scene::Interface;pub use sim::Domain;pub use sim::Exchange;pub use sim::Kind;pub use sim::Report;pub use sim::Schedule;pub use sim::Simulation;pub use substance::Substance;pub use transform::fft;pub use transform::fft2;pub use transform::fftshift;pub use transform::ifft;pub use transform::ifft2;pub use vector::basis_for;pub use vector::oriented_against;pub use vector::reflect;
Modules§
- conserved
- Conservation, as a thing a process must answer for rather than a property it is trusted to have.
- ensemble
- Many independent samples, run in parallel, with an answer that does not depend on how many threads did the work.
- field
- Quantities that vary over space and time.
- integrator
- Time evolution for systems that have no closed form.
- motion
- How a scene changes with time, where it changes in closed form.
- rng
- A deterministic pseudo-random generator, and the sampling built on it.
- scene
- Where two domains meet, and how a quantity crosses with its place intact.
- sim
- Running several domains at once.
- substance
- What a piece of matter is, across every domain that cares.
- transform
- The discrete Fourier transform, as a kernel utility.
- units
- Everything from
dualis-units, so thatuse dualis_core::units::*is enough to write dimensioned physics. - vector
- Vector arithmetic that no single domain owns.