basic_particle/
basic_particle.rs1use physics_in_parallel::prelude::basic::{ReflectBox, ResolvedRng, RngMethod, set_max_threads};
5use physics_in_parallel::prelude::models::*;
6
7fn simulate() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
8 let mut particles = create_template(2, 2)?;
9 particles.set_attribute_vector(ATTR_R, 0, &[0.25, 0.5])?;
10 particles.set_attribute_vector(ATTR_R, 1, &[0.75, 0.5])?;
11 set_mass(&mut particles, 0, 2.0)?;
12 let mut springs = SpringNetwork::new();
13 springs.insert((0, 1), Spring::new(1.0, 0.4, None)?)?;
14 let boundary = ReflectBox::new(&[0.0, 0.0], &[1.0, 1.0])?;
15 let mut thermostat = LangevinThermostat::new(
16 0.01,
17 0.1,
18 ResolvedRng::new(42, RngMethod::IndexedSplitMix64),
19 ParticleSelection::AliveOnly,
20 )?;
21 let mut integrator = SemiImplicitEuler;
22 for step in 0..20 {
23 particles.attribute_mut::<f64>(ATTR_A)?.fill(0.0);
25 springs.apply(&mut particles, ParticleSelection::AliveOnly)?;
26 integrator.apply(&mut particles, 0.01)?;
27 boundary.apply_to_particles(&mut particles)?;
28 thermostat.apply(&mut particles, 0.01)?;
29 if (step + 1) % 10 == 0 {
30 let summary = kinetic_summary(&particles, ParticleSelection::AliveOnly)?;
31 println!(
32 "step {}: KE={}, temperature={}",
33 step + 1,
34 summary.energy,
35 summary.temperature
36 );
37 }
38 }
39 Ok(())
40}
41fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
42 let pool = rayon::ThreadPoolBuilder::new().num_threads(4).build()?;
43 set_max_threads(Some(4))?;
44 pool.install(simulate)
45}