use std::sync::Arc;
use super::super::{
advecator::Advector,
integrator::{StepProducts, StepTimings, TimeIntegrator},
phasespace::PhaseSpaceRepr,
progress::{StepPhase, StepProgress},
solver::PoissonSolver,
types::*,
};
use super::helpers;
use crate::CausticError;
const BM4_A: [f64; 6] = [
0.0502627644003922,
0.4134651224174328,
0.0362721131821750,
0.0362721131821750,
0.4134651224174328,
0.0502627644003922,
];
const BM4_B: [f64; 5] = [
0.1488177424796559,
0.527_753_876_542_476,
-0.3531432380442638,
0.527_753_876_542_476,
0.1488177424796559,
];
pub struct BlanesMoanSplitting {
pub g: f64,
last_timings: StepTimings,
progress: Option<Arc<StepProgress>>,
}
impl BlanesMoanSplitting {
pub fn new(g: f64) -> Self {
Self {
g,
last_timings: StepTimings::default(),
progress: None,
}
}
}
impl TimeIntegrator for BlanesMoanSplitting {
fn advance(
&mut self,
repr: &mut dyn PhaseSpaceRepr,
solver: &dyn PoissonSolver,
advector: &dyn Advector,
dt: f64,
) -> Result<StepProducts, CausticError> {
let _span = tracing::info_span!("bm4_advance").entered();
let mut timings = StepTimings::default();
let n_sub: u8 = 11;
if let Some(ref p) = self.progress {
p.start_step();
}
for i in 0..6 {
helpers::report_phase!(self.progress, StepPhase::DriftHalf1, 2 * i as u8, n_sub);
{
let _s = tracing::info_span!("bm4_drift", stage = i).entered();
helpers::time_ms!(timings, drift_ms, advector.drift(repr, BM4_A[i] * dt));
}
if i < 5 {
helpers::report_phase!(self.progress, StepPhase::Kick, 2 * i as u8 + 1, n_sub);
{
let _s = tracing::info_span!("bm4_kick", stage = i).entered();
let (_density, _potential, accel) = helpers::time_ms!(
timings,
poisson_ms,
helpers::solve_poisson(repr, solver, self.g)
);
helpers::time_ms!(timings, kick_ms, advector.kick(repr, &accel, BM4_B[i] * dt));
}
}
}
helpers::report_phase!(self.progress, StepPhase::StepComplete, n_sub, n_sub);
let (density, potential, acceleration) = helpers::time_ms!(
timings,
density_ms,
helpers::solve_poisson(repr, solver, self.g)
);
self.last_timings = timings;
Ok(StepProducts {
density,
potential,
acceleration,
})
}
fn max_dt(&self, repr: &dyn PhaseSpaceRepr, cfl_factor: f64) -> f64 {
helpers::dynamical_timestep(repr, self.g, cfl_factor)
}
fn last_step_timings(&self) -> Option<&StepTimings> {
Some(&self.last_timings)
}
fn set_progress(&mut self, progress: Arc<StepProgress>) {
self.progress = Some(progress);
}
}