use std::sync::Arc;
use super::super::{
advecator::Advector,
integrator::{StepProducts, TimeIntegrator},
phasespace::PhaseSpaceRepr,
progress::{StepPhase, StepProgress},
solver::PoissonSolver,
types::*,
};
use super::helpers;
use crate::CausticError;
pub struct LieSplitting {
pub g: f64,
progress: Option<Arc<StepProgress>>,
}
impl LieSplitting {
pub fn new(g: f64) -> Self {
Self { g, progress: None }
}
}
impl TimeIntegrator for LieSplitting {
fn advance(
&mut self,
repr: &mut dyn PhaseSpaceRepr,
solver: &dyn PoissonSolver,
advector: &dyn Advector,
dt: f64,
) -> Result<StepProducts, CausticError> {
let _span = tracing::info_span!("lie_advance").entered();
if let Some(ref p) = self.progress {
p.start_step();
p.set_phase(StepPhase::DriftHalf1);
p.set_sub_step(0, 2);
}
advector.drift(repr, dt);
if let Some(ref p) = self.progress {
p.set_phase(StepPhase::Kick);
p.set_sub_step(1, 2);
}
let density = repr.compute_density();
let potential = solver.solve(&density, self.g);
let accel = solver.compute_acceleration(&potential);
advector.kick(repr, &accel, dt);
helpers::apply_hypercollision_if_spectral(repr, dt);
let density = repr.compute_density();
let potential = solver.solve(&density, self.g);
let acceleration = solver.compute_acceleration(&potential);
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 set_progress(&mut self, progress: Arc<StepProgress>) {
self.progress = Some(progress);
}
}