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 YOSHIDA_W1: f64 = 1.3512071919596578;
const YOSHIDA_W0: f64 = -1.7024143839193153;
pub struct YoshidaSplitting {
pub g: f64,
last_timings: StepTimings,
progress: Option<Arc<StepProgress>>,
}
impl YoshidaSplitting {
pub fn new(g: f64) -> Self {
Self {
g,
last_timings: StepTimings::default(),
progress: None,
}
}
}
impl TimeIntegrator for YoshidaSplitting {
fn advance(
&mut self,
repr: &mut dyn PhaseSpaceRepr,
solver: &dyn PoissonSolver,
advector: &dyn Advector,
dt: f64,
) -> Result<StepProducts, CausticError> {
let _span = tracing::info_span!("yoshida_advance").entered();
let mut timings = StepTimings::default();
if let Some(ref p) = self.progress {
p.start_step();
}
helpers::report_phase!(self.progress, StepPhase::YoshidaDrift1, 0, 7);
{
let _s = tracing::info_span!("yoshida_drift_1").entered();
helpers::time_ms!(
timings,
drift_ms,
advector.drift(repr, YOSHIDA_W1 * dt / 2.0)
);
}
helpers::report_phase!(self.progress, StepPhase::YoshidaKick1, 1, 7);
{
let _s = tracing::info_span!("yoshida_kick_1").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, YOSHIDA_W1 * dt)
);
}
helpers::apply_hypercollision_if_spectral(repr, YOSHIDA_W1 * dt);
helpers::report_phase!(self.progress, StepPhase::YoshidaDrift2, 2, 7);
{
let _s = tracing::info_span!("yoshida_drift_2").entered();
helpers::time_ms!(
timings,
drift_ms,
advector.drift(repr, (YOSHIDA_W1 + YOSHIDA_W0) * dt / 2.0)
);
}
helpers::report_phase!(self.progress, StepPhase::YoshidaKick2, 3, 7);
{
let _s = tracing::info_span!("yoshida_kick_2").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, YOSHIDA_W0 * dt)
);
}
helpers::apply_hypercollision_if_spectral(repr, YOSHIDA_W0 * dt);
helpers::report_phase!(self.progress, StepPhase::YoshidaDrift3, 4, 7);
{
let _s = tracing::info_span!("yoshida_drift_3").entered();
helpers::time_ms!(
timings,
drift_ms,
advector.drift(repr, (YOSHIDA_W0 + YOSHIDA_W1) * dt / 2.0)
);
}
helpers::report_phase!(self.progress, StepPhase::YoshidaKick3, 5, 7);
{
let _s = tracing::info_span!("yoshida_kick_3").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, YOSHIDA_W1 * dt)
);
}
helpers::apply_hypercollision_if_spectral(repr, YOSHIDA_W1 * dt);
helpers::report_phase!(self.progress, StepPhase::YoshidaDrift4, 6, 7);
{
let _s = tracing::info_span!("yoshida_drift_4").entered();
helpers::time_ms!(
timings,
drift_ms,
advector.drift(repr, YOSHIDA_W1 * dt / 2.0)
);
}
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);
}
}