///|
pub(all) struct PicDiagnostics {
time : Double
particles : Int
total_charge : Double
kinetic_energy : Double
field_energy : Double
center_of_mass : Double
mean_velocity : Double
velocity_variance : Double
} derive(Debug, ToJson)
///|
pub fn PicDiagnostics::from_state(state : PicState) -> PicDiagnostics {
{
time: state.time,
particles: state.particles.length(),
total_charge: total_particle_charge(state.particles),
kinetic_energy: kinetic_energy(state.particles),
field_energy: field_energy(state.field),
center_of_mass: center_of_mass(state.grid, state.particles),
mean_velocity: velocity_mean(state.particles),
velocity_variance: velocity_variance(state.particles),
}
}
///|
pub fn PicDiagnostics::total_energy(d : PicDiagnostics) -> Double {
d.kinetic_energy + d.field_energy
}
///|
pub fn diagnostics_to_csv(samples : ArrayView[PicDiagnostics]) -> String {
let out = StringBuilder()
out.write_string(
"time,particles,total_charge,kinetic_energy,field_energy,total_energy,center_of_mass,mean_velocity,velocity_variance\n",
)
for d in samples {
out.write_string(
"\{d.time},\{d.particles},\{d.total_charge},\{d.kinetic_energy},\{d.field_energy},\{d.total_energy()},\{d.center_of_mass},\{d.mean_velocity},\{d.velocity_variance}\n",
)
}
out.to_string()
}
///|
pub fn trace_pic(
state : PicState,
dt : Double,
steps : Int,
every? : Int = 1,
) -> Array[PicDiagnostics] {
let samples : Array[PicDiagnostics] = []
let mut current = state
for i in 0..<=steps {
if i % every == 0 {
samples.push(PicDiagnostics::from_state(current))
}
if i < steps {
current = current.step(dt)
}
}
samples
}