1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use na::RealField;
use crate::object::Fluid;
pub struct TimestepManager<N: RealField> {
cfl_coeff: N,
min_substep_coeff: N,
}
impl<N: RealField> TimestepManager<N> {
pub fn new() -> Self {
Self {
cfl_coeff: na::convert(0.4),
min_substep_coeff: na::convert(1.0),
}
}
fn max_substep(&self, particle_radius: N, fluids: &[Fluid<N>]) -> N {
let mut max_sq_vel = N::zero();
for v in fluids.iter().flat_map(|f| f.velocities.iter()) {
max_sq_vel = max_sq_vel.max(v.norm_squared());
}
particle_radius * na::convert(2.0) / max_sq_vel.sqrt() * self.cfl_coeff
}
pub(crate) fn compute_substep(
&self,
total_step_size: N,
remaining_time: N,
particle_radius: N,
fluids: &[Fluid<N>],
) -> N {
let min_substep = total_step_size * self.min_substep_coeff;
let max_substep = self.max_substep(particle_radius, fluids);
if remaining_time - max_substep < min_substep {
remaining_time
} else {
max_substep
}
}
}