#[test]
fn isochrone_equilibrium() {
use crate::tooling::core::init::{
domain::{Domain, SpatialBoundType, VelocityBoundType},
isolated::{IsochroneIC, sample_on_grid},
};
use crate::tooling::core::phasespace::PhaseSpaceRepr as _;
use crate::tooling::validation::helpers::{
assert_valid_output, build_standard_sim, density_mass, relative_drift, snapshot_density,
};
let domain = Domain::builder()
.spatial_extent(8.0) .velocity_extent(2.5) .spatial_resolution(8)
.velocity_resolution(8)
.t_final(4.0) .spatial_bc(SpatialBoundType::Periodic)
.velocity_bc(VelocityBoundType::Truncated)
.build()
.unwrap();
let ic = IsochroneIC::new(1.0, 1.0, 1.0);
let snap = sample_on_grid(&ic, &domain);
assert!(
!snap.data.iter().any(|v| v.is_nan()),
"Isochrone IC must not contain NaN"
);
let dx = domain.dx();
let dv = domain.dv();
let dv6 = dx[0] * dx[1] * dx[2] * dv[0] * dv[1] * dv[2];
let m_ic: f64 = snap.data.iter().sum::<f64>() * dv6;
assert!(
m_ic > 0.0,
"Isochrone IC must have positive mass, got {m_ic}"
);
let initial_density = snapshot_density(&snap, &domain);
let mut sim = build_standard_sim(domain, snap, 4.0);
let pkg = sim.run().unwrap();
let final_density = sim.repr.compute_density();
let dx = sim.domain.dx();
let m_init = density_mass(&initial_density, dx);
let m_final = density_mass(&final_density, dx);
assert!(m_final > 0.0, "Final mass should be positive");
assert_valid_output(&final_density, pkg.diagnostics_history.len());
let e0 = pkg.diagnostics_history[0].total_energy;
let e_final = pkg.diagnostics_history.last().unwrap().total_energy;
let e_drift = relative_drift(e_final, e0);
let c2_0 = pkg.diagnostics_history[0].casimir_c2;
let c2_f = pkg.diagnostics_history.last().unwrap().casimir_c2;
let c2_drift = relative_drift(c2_f, c2_0);
let mass_drift = relative_drift(m_final, m_init);
println!(
"Isochrone equilibrium: m_init={:.4}, m_final={:.4}, mass_drift={:.2}%, E_drift={:.2e}, C2_drift={:.2e}, steps={}",
m_init,
m_final,
mass_drift * 100.0,
e_drift,
c2_drift,
pkg.total_steps
);
}