salva2d/solver/surface_tension/
wcsph_surface_tension.rs1#[cfg(feature = "parallel")]
2use rayon::prelude::*;
3
4use crate::geometry::ParticlesContacts;
5
6use crate::math::Real;
7use crate::object::{Boundary, Fluid};
8use crate::solver::NonPressureForce;
9use crate::TimestepManager;
10
11#[derive(Clone)]
16pub struct WCSPHSurfaceTension {
17 fluid_tension_coefficient: Real,
18 boundary_tension_coefficient: Real,
19}
20
21impl WCSPHSurfaceTension {
22 pub fn new(fluid_tension_coefficient: Real, boundary_tension_coefficient: Real) -> Self {
24 Self {
25 fluid_tension_coefficient,
26 boundary_tension_coefficient,
27 }
28 }
29}
30
31impl NonPressureForce for WCSPHSurfaceTension {
32 fn solve(
33 &mut self,
34 _timestep: &TimestepManager,
35 _kernel_radius: Real,
36 fluid_fluid_contacts: &ParticlesContacts,
37 _fluid_boundaries_contacts: &ParticlesContacts,
38 fluid: &mut Fluid,
39 boundaries: &[Boundary],
40 _densities: &[Real],
41 ) {
42 let fluid_tension_coefficient = self.fluid_tension_coefficient;
43 let boundary_tension_coefficient = self.boundary_tension_coefficient;
44 let positions = &fluid.positions;
45 let volumes = &fluid.volumes;
46 let density0 = fluid.density0;
47
48 par_iter_mut!(fluid.accelerations)
49 .enumerate()
50 .for_each(|(i, acceleration_i)| {
51 if fluid_tension_coefficient != na::zero::<Real>() {
52 for c in fluid_fluid_contacts
53 .particle_contacts(i)
54 .read()
55 .unwrap()
56 .iter()
57 {
58 if c.i_model == c.j_model {
59 let dpos = positions[c.i] - positions[c.j];
60 let cohesion_acc = dpos
61 * (-fluid_tension_coefficient * c.weight * volumes[c.j] * density0
62 / (volumes[c.i] * density0));
63 *acceleration_i += cohesion_acc;
64 }
65 }
66 }
67
68 if boundary_tension_coefficient != na::zero::<Real>() {
69 for c in fluid_fluid_contacts
70 .particle_contacts(i)
71 .read()
72 .unwrap()
73 .iter()
74 {
75 let dpos = positions[c.i] - boundaries[c.j_model].positions[c.j];
76 let mi = volumes[c.i] * density0;
77 let cohesion_force = dpos
78 * (boundary_tension_coefficient
79 * c.weight
80 * boundaries[c.j_model].volumes[c.j]
81 * density0);
82 *acceleration_i -= cohesion_force / mi;
83 boundaries[c.j_model].apply_force(c.j, cohesion_force);
84 }
85 }
86 })
87 }
88
89 fn apply_permutation(&mut self, _: &[usize]) {}
90}