pub trait Simulation<M: Model>: Sized {
type StepError: Error + Send + Sync + 'static + From<M::Error>;
// Required methods
fn model(&self) -> &M;
fn advance_time(
&mut self,
state: &State<M>,
dt: Duration,
) -> Result<M::Input, Self::StepError>;
// Provided methods
fn step(
&mut self,
input: M::Input,
dt: Duration,
) -> Result<State<M>, Self::StepError>
where M::Input: Clone { ... }
fn step_from_state(
&mut self,
state: &State<M>,
dt: Duration,
) -> Result<State<M>, Self::StepError>
where M::Input: Clone { ... }
fn step_many(
&mut self,
initial_input: M::Input,
steps: usize,
dt: Duration,
) -> Result<Vec<State<M>>, Self::StepError>
where M::Input: Clone,
M::Output: Clone { ... }
fn into_step_iter(
self,
initial_input: M::Input,
dt: Duration,
) -> impl Iterator<Item = Result<State<M>, Self::StepError>>
where M::Input: Clone,
M::Output: Clone { ... }
}Expand description
Trait for defining a transient simulation in Twine.
A Simulation advances a Model forward in time by computing its next
input with [advance_time] and then calling the model to produce a new
State representing the system at the corresponding future moment.
§Stepping Methods
After implementing [advance_time], the following methods are available for
advancing the simulation:
Simulation::step: Takes a single step from an initial input.Simulation::step_from_state: Takes a single step from a known state.Simulation::step_many: Takes multiple steps and collects all resulting states.Simulation::into_step_iter: Consumes the simulation and returns an iterator over its steps.
Required Associated Types§
Sourcetype StepError: Error + Send + Sync + 'static + From<M::Error>
type StepError: Error + Send + Sync + 'static + From<M::Error>
The error type returned if a simulation step fails.
This type must implement From<M::Error> so errors produced by the model
(via Model::call) can be automatically converted using the ? operator.
This requirement allows simulations to propagate model errors cleanly
when calling the model during a step or within [advance_time].
Implementations may:
- Reuse the model’s error type directly (
type StepError = M::Error). - Wrap it in a custom enum with additional error variants.
- Use boxed dynamic errors for maximum flexibility.
Required Methods§
Sourcefn advance_time(
&mut self,
state: &State<M>,
dt: Duration,
) -> Result<M::Input, Self::StepError>
fn advance_time( &mut self, state: &State<M>, dt: Duration, ) -> Result<M::Input, Self::StepError>
Computes the next input for the model, advancing the simulation in time.
Given the current State and a proposed time step dt, this method
generates the next Model::Input to drive the simulation forward.
This method is the primary customization point for incrementing time,
integrating state variables, enforcing constraints, applying control
logic, or incorporating external events.
It takes &mut self to support stateful integration algorithms such as
adaptive time stepping, multistep methods, or PID controllers that need
to record history.
Implementations may interpret or adapt the proposed time step dt as
needed (e.g., for adaptive time stepping), and are free to update any
fields of the input required to continue the simulation.
§Parameters
state: The current simulation state.dt: The proposed time step.
§Returns
The next input, computed from the current State and proposed dt.
§Errors
Returns a [StepError] if computing the next input fails.
Provided Methods§
Sourcefn step(
&mut self,
input: M::Input,
dt: Duration,
) -> Result<State<M>, Self::StepError>
fn step( &mut self, input: M::Input, dt: Duration, ) -> Result<State<M>, Self::StepError>
Advances the simulation by one step, starting from an initial input.
This method first calls the model with the given input to compute
the initial output, forming a complete State.
It then delegates to [step_from_state] to compute the next state.
As a result, the model is called twice: once to initialize the
state, and once after advancing.
§Parameters
input: The model input at the start of the step.dt: The proposed time step.
§Errors
Returns a [StepError] if computing the next input or calling the model fails.
Sourcefn step_from_state(
&mut self,
state: &State<M>,
dt: Duration,
) -> Result<State<M>, Self::StepError>
fn step_from_state( &mut self, state: &State<M>, dt: Duration, ) -> Result<State<M>, Self::StepError>
Advances the simulation by one step from a known State.
This method computes the next input using [advance_time],
then calls the model to produce the resulting State.
§Parameters
state: The current simulation state.dt: The proposed time step.
§Errors
Returns a [StepError] if computing the next input or calling the model fails.
Sourcefn step_many(
&mut self,
initial_input: M::Input,
steps: usize,
dt: Duration,
) -> Result<Vec<State<M>>, Self::StepError>
fn step_many( &mut self, initial_input: M::Input, steps: usize, dt: Duration, ) -> Result<Vec<State<M>>, Self::StepError>
Runs the simulation for a fixed number of steps and collects the results.
Starting from the given input, this method advances the simulation by
steps iterations using the proposed time step dt.
§Parameters
initial_input: The model input at the start of the simulation.steps: The number of steps to run.dt: The proposed time step for each iteration.
§Returns
A Vec of length steps + 1 containing each State computed during
the run, including the initial one.
§Errors
Returns a [StepError] if any step fails.
No further steps are taken after an error.
Sourcefn into_step_iter(
self,
initial_input: M::Input,
dt: Duration,
) -> impl Iterator<Item = Result<State<M>, Self::StepError>>
fn into_step_iter( self, initial_input: M::Input, dt: Duration, ) -> impl Iterator<Item = Result<State<M>, Self::StepError>>
Consumes the simulation and creates an iterator that advances it repeatedly.
The iterator calls the simulation’s stepping logic with a constant dt,
yielding each resulting State in sequence.
If a step fails, the error is returned and iteration stops.
This method supports lazy or streaming evaluation and integrates cleanly
with iterator adapters such as .take(n), .map(...), or .find(...).
It is memory-efficient and performs no intermediate allocations.
§Parameters
initial_input: The model input at the start of the simulation.dt: The proposed time step for each iteration.
§Returns
An iterator over Result<State<M>, StepError> steps.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.