mod euler;
mod euler_maruyama;
mod rk4;
use crate::{
core::{scheduler::Scheduler, scratch::ScratchPool, state::State, storage::StorageBackend},
geometry::grid::Grid,
physics::model::{Model, RhsContext},
};
pub use euler::ForwardEuler;
pub use euler_maruyama::EulerMaruyama;
pub use rk4::RungeKutta4;
#[derive(Debug, Clone, Copy)]
pub struct StageLayout {
pub tendency: usize,
pub stage_state: usize,
}
pub trait Integrator<G: Grid, D>: Send + Sync {
fn stage_layout(&self) -> StageLayout;
#[allow(clippy::too_many_arguments)]
fn step<M, S, Sch>(
&self,
model: &M,
grid: &G,
disc: &D,
scheduler: &Sch,
pool: &ScratchPool<M::Scalar, S>,
state: &mut State<M::Scalar, S>,
stages: &mut [State<M::Scalar, S>],
t: f64,
dt: f64,
) where
M: Model<G, D>,
S: StorageBackend<M::Scalar>,
Sch: Scheduler;
}
#[allow(clippy::too_many_arguments)]
fn eval_rhs<G, D, M, S, Sch>(
model: &M,
grid: &G,
disc: &D,
scheduler: &Sch,
pool: &ScratchPool<M::Scalar, S>,
state: &mut State<M::Scalar, S>,
out: &mut State<M::Scalar, S>,
t: f64,
) where
G: Grid,
M: Model<G, D>,
S: StorageBackend<M::Scalar>,
Sch: Scheduler,
D: Sync,
{
model.fill_ghosts(grid, state, t);
let (layout, blocks) = out.split_blocks_mut();
scheduler.for_each_block_mut(
blocks,
|| pool.checkout(),
|block, storage, sc| {
let ctx = RhsContext {
grid,
disc,
block,
t,
};
model.rhs_block(&ctx, state, &mut storage.bind_mut(layout), &mut *sc);
},
);
}
#[allow(clippy::too_many_arguments)]
fn eval_noise<G, D, M, S, Sch>(
model: &M,
grid: &G,
disc: &D,
scheduler: &Sch,
pool: &ScratchPool<M::Scalar, S>,
state: &State<M::Scalar, S>,
amp: &mut State<M::Scalar, S>,
t: f64,
) where
G: Grid,
M: Model<G, D>,
S: StorageBackend<M::Scalar>,
Sch: Scheduler,
D: Sync,
{
amp.fill_zero_with(scheduler);
let (layout, blocks) = amp.split_blocks_mut();
scheduler.for_each_block_mut(
blocks,
|| pool.checkout(),
|block, storage, sc| {
let ctx = RhsContext {
grid,
disc,
block,
t,
};
model.noise_block(&ctx, state, &mut storage.bind_mut(layout), &mut *sc);
},
);
}