use crate::coupling::CouplingReport;
pub fn total_exchanged_momentum(reports: &[CouplingReport]) -> [f64; 3] {
reports.iter().fold([0.0_f64; 3], |mut acc, r| {
acc[0] += r.momentum_a_to_b[0];
acc[1] += r.momentum_a_to_b[1];
acc[2] += r.momentum_a_to_b[2];
acc
})
}
pub fn momentum_drift_fraction(delta: [f64; 3], reference: [f64; 3]) -> f64 {
let ref_mag =
(reference[0] * reference[0] + reference[1] * reference[1] + reference[2] * reference[2])
.sqrt();
if ref_mag < f64::EPSILON {
return 0.0;
}
let delta_mag = (delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]).sqrt();
delta_mag / ref_mag
}
pub fn mean_rms_position_error(reports: &[CouplingReport]) -> f64 {
if reports.is_empty() {
return 0.0;
}
let sum: f64 = reports.iter().map(|r| r.rms_position_error).sum();
sum / reports.len() as f64
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn total_exchanged_momentum_zero_for_empty() {
let result = total_exchanged_momentum(&[]);
assert_eq!(result, [0.0, 0.0, 0.0]);
}
#[test]
fn momentum_drift_fraction_zero_reference() {
let drift = momentum_drift_fraction([1.0, 0.0, 0.0], [0.0, 0.0, 0.0]);
assert!((drift - 0.0).abs() < f64::EPSILON);
}
}