use crate::{GravityParticle, GravitySolver};
use phyz_math::Vec3;
#[derive(Debug, Clone)]
pub struct ConstantGravity {
pub g: Vec3,
}
impl ConstantGravity {
pub fn new(g: Vec3) -> Self {
Self { g }
}
pub fn earth() -> Self {
Self {
g: Vec3::new(0.0, 0.0, -crate::G_EARTH),
}
}
}
impl GravitySolver for ConstantGravity {
fn compute_forces(&mut self, particles: &mut [GravityParticle]) {
for p in particles.iter_mut() {
p.reset_force();
p.add_force(self.g * p.m);
}
}
fn potential_energy(&self, particles: &[GravityParticle]) -> f64 {
particles.iter().map(|p| -p.m * self.g.dot(&p.x)).sum()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_constant_gravity() {
let mut solver = ConstantGravity::earth();
let mut particles = vec![GravityParticle::new(
Vec3::new(0.0, 0.0, 10.0),
Vec3::zeros(),
1.0,
)];
solver.compute_forces(&mut particles);
assert!((particles[0].f.z + crate::G_EARTH).abs() < 1e-10);
assert!(particles[0].f.x.abs() < 1e-10);
assert!(particles[0].f.y.abs() < 1e-10);
}
#[test]
fn test_potential_energy() {
let solver = ConstantGravity::earth();
let particles = vec![GravityParticle::new(
Vec3::new(0.0, 0.0, 10.0),
Vec3::zeros(),
2.0,
)];
let u = solver.potential_energy(&particles);
assert!((u - 196.133).abs() < 1e-3);
}
}