From 783070635b568b44b6902bfdc01bdadf12b86bc8 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Thu, 12 Dec 2024 15:23:01 +0100 Subject: feat: implement constraint system and PPM rendering --- src/solver/mod.rs | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'src/solver/mod.rs') diff --git a/src/solver/mod.rs b/src/solver/mod.rs index 4a5fec5..4bb8747 100644 --- a/src/solver/mod.rs +++ b/src/solver/mod.rs @@ -7,10 +7,10 @@ mod midpoint; #[derive(Debug, Clone)] pub struct PhaseSpace(DVector); type ParticleView<'a> = Matrix< - f32, + Scalar, Const<{ PhaseSpace::PARTICLE_DIM }>, Const<1>, - ViewStorage<'a, f32, Const<{ PhaseSpace::PARTICLE_DIM }>, Const<1>, Const<1>, Dyn>, + ViewStorage<'a, Scalar, Const<{ PhaseSpace::PARTICLE_DIM }>, Const<1>, Const<1>, Dyn>, >; impl PhaseSpace { @@ -63,7 +63,6 @@ impl ParticleSystem { fn scatter_phase_space(&mut self, phase_space: &PhaseSpace) { for (particle_index, particle) in &mut self.particles.iter_mut().enumerate() { let view = phase_space.particle_view(particle_index); - for i in 0..N { particle.position[i] = view[i]; particle.velocity[i] = view[i + N]; @@ -85,6 +84,7 @@ mod tests { fn test_collect_phase_space() { let system = ParticleSystem { particles: vec![Particle::new(Point::new(2.0, 3.0), 1.0)], + constraints: vec![], t: 0.0, }; let phase_space = system.collect_phase_space(); @@ -105,6 +105,7 @@ mod tests { Particle::new(Point::new(0.0, 0.0), 1.0), Particle::new(Point::new(0.0, 0.0), 1.0), ], + constraints: vec![], t: 0.0, }; @@ -120,11 +121,16 @@ mod tests { ); } - fn simulate_falling_ball(fall_time: Scalar, dt: Scalar) -> (Vector, Vector) { + fn simulate_falling_ball( + fall_time: Scalar, + dt: Scalar, + mass: Scalar, + ) -> (Vector, Vector, ParticleSystem) { let gravity = -9.8 * Vector::y(); let mut system = ParticleSystem { - particles: vec![Particle::new(Point::origin(), 1.0)], + particles: vec![Particle::new(Point::origin(), mass)], + constraints: vec![], t: 0.0, }; @@ -133,7 +139,7 @@ mod tests { for _ in 0..iterations { for particle in &mut system.particles { particle.reset_force(); - particle.apply_force(gravity); + particle.apply_force(gravity * particle.mass); } system.step(dt); } @@ -144,12 +150,13 @@ mod tests { ( system.particles[0].position.coords - expected_position, system.particles[0].velocity - expected_velocity, + system, ) } #[test] fn ball_should_fall() { - let (position_error, velocity_error) = simulate_falling_ball(10.0, 0.01); + let (position_error, velocity_error, _) = simulate_falling_ball(10.0, 0.01, 3.0); assert!( position_error.norm() < 0.01, "Position error is too high: {}", @@ -161,4 +168,17 @@ mod tests { velocity_error, ); } + + #[test] + fn freefall_different_masses() { + let (_, _, system1) = simulate_falling_ball(10.0, 0.01, 2.0); + let (_, _, system2) = simulate_falling_ball(10.0, 0.01, 10.0); + + let diff = system1.particles[0].position - system2.particles[0].position; + assert!( + diff.norm() < 0.01, + "Points with different masses should fall with the same speed, diff: {}", + diff + ); + } } -- cgit v1.2.3