Skip to main content

oxiphysics_gpu/fluid_sim_gpu/
functions_2.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5#[cfg(test)]
6mod tests {
7    use super::super::functions::*;
8    use crate::fluid_sim_gpu::FlipParticle;
9    use crate::fluid_sim_gpu::FluidSimConfig;
10    use crate::fluid_sim_gpu::FluidSimulation;
11    use crate::fluid_sim_gpu::GpuBoundaryBox;
12    use crate::fluid_sim_gpu::GpuNeighborList;
13    use crate::fluid_sim_gpu::LbmCellType;
14    use crate::fluid_sim_gpu::LbmD2Q9;
15    use crate::fluid_sim_gpu::MacGrid;
16    use crate::fluid_sim_gpu::MultiGpuDomain;
17    use crate::fluid_sim_gpu::SphConfig;
18    use crate::fluid_sim_gpu::SphKernels;
19    use crate::fluid_sim_gpu::SphParticle;
20    #[test]
21    fn test_poly6_inside() {
22        let w = SphKernels::poly6(0.0, 0.1);
23        assert!(w > 0.0);
24    }
25    #[test]
26    fn test_poly6_outside() {
27        let w = SphKernels::poly6(0.2, 0.1);
28        assert!((w).abs() < 1e-15);
29    }
30    #[test]
31    fn test_spiky_grad_inside() {
32        let r_vec = [0.05, 0.0, 0.0];
33        let g = SphKernels::spiky_grad(r_vec, 0.05, 0.1);
34        assert!(g[0] != 0.0);
35    }
36    #[test]
37    fn test_viscosity_laplacian() {
38        let lap = SphKernels::viscosity_laplacian(0.05, 0.1);
39        assert!(lap > 0.0);
40    }
41    #[test]
42    fn test_sph_compute_density_single_particle() {
43        let mut particles = vec![SphParticle::new([0.0; 3], 1.0)];
44        let config = SphConfig::default();
45        sph_compute_density(&mut particles, &config);
46        assert!(particles[0].density > 0.0);
47    }
48    #[test]
49    fn test_sph_step_does_not_panic() {
50        let mut particles = vec![
51            SphParticle::new([0.0, 0.0, 0.0], 0.001),
52            SphParticle::new([0.05, 0.0, 0.0], 0.001),
53        ];
54        let config = SphConfig::default();
55        sph_step(&mut particles, &config);
56    }
57    #[test]
58    fn test_lbm_d2q9_new() {
59        let lbm = LbmD2Q9::new(8, 8, 1.0);
60        assert_eq!(lbm.nx, 8);
61        assert_eq!(lbm.ny, 8);
62    }
63    #[test]
64    fn test_lbm_density_initial() {
65        let lbm = LbmD2Q9::new(4, 4, 1.0);
66        let rho = lbm.density(2, 2);
67        assert!((rho - 1.0).abs() < 1e-10);
68    }
69    #[test]
70    fn test_lbm_velocity_initial_zero() {
71        let lbm = LbmD2Q9::new(4, 4, 1.0);
72        let [ux, uy] = lbm.velocity(2, 2);
73        assert!(ux.abs() < 1e-10);
74        assert!(uy.abs() < 1e-10);
75    }
76    #[test]
77    fn test_lbm_f_equilibrium_rest() {
78        let f_eq = LbmD2Q9::f_equilibrium(1.0, 0.0, 0.0, 0);
79        assert!((f_eq - D2Q9_W[0]).abs() < 1e-12);
80    }
81    #[test]
82    fn test_lbm_step_does_not_panic() {
83        let mut lbm = LbmD2Q9::new(8, 8, 0.6);
84        lbm.set_inlet_velocity(0.05, 0.0);
85        lbm.step();
86    }
87    #[test]
88    fn test_lbm_bounce_back_solid() {
89        let mut lbm = LbmD2Q9::new(4, 4, 1.0);
90        lbm.cell_type[0] = LbmCellType::Solid;
91        lbm.apply_bounce_back();
92    }
93    #[test]
94    fn test_mac_grid_new() {
95        let g = MacGrid::new(4, 4, 4, 0.1);
96        assert_eq!(g.nx, 4);
97        assert_eq!(g.u.len(), 5 * 4 * 4);
98    }
99    #[test]
100    fn test_mac_grid_set_get_u() {
101        let mut g = MacGrid::new(4, 4, 4, 0.1);
102        g.set_u(2, 1, 1, 3.125);
103        assert!((g.get_u(2, 1, 1) - 3.125).abs() < 1e-12);
104    }
105    #[test]
106    fn test_mac_grid_compute_divergence_zero() {
107        let mut g = MacGrid::new(4, 4, 4, 0.1);
108        g.flags = vec![1u8; 4 * 4 * 4];
109        g.compute_divergence();
110        for &d in &g.div {
111            assert!(d.abs() < 1e-12);
112        }
113    }
114    #[test]
115    fn test_jacobi_pressure_solve() {
116        let mut g = MacGrid::new(4, 4, 4, 0.1);
117        g.flags = vec![1u8; 4 * 4 * 4];
118        g.jacobi_pressure_solve(1000.0, 0.01, 5);
119    }
120    #[test]
121    fn test_compute_vorticity_zero_vel() {
122        let g = MacGrid::new(8, 8, 8, 0.1);
123        let vort = compute_vorticity(&g);
124        assert_eq!(vort.len(), 8 * 8 * 8);
125        for v in &vort {
126            assert!(v[0].abs() < 1e-12);
127        }
128    }
129    #[test]
130    fn test_surface_tension_csf() {
131        let nx = 4;
132        let ny = 4;
133        let nz = 4;
134        let phi = vec![-1.0f64; nx * ny * nz];
135        let forces = surface_tension_csf(&phi, nx, ny, nz, 0.1, 0.0728);
136        assert_eq!(forces.len(), nx * ny * nz);
137    }
138    #[test]
139    fn test_flip_particle_new() {
140        let p = FlipParticle::new([1.0, 2.0, 3.0]);
141        assert_eq!(p.position, [1.0, 2.0, 3.0]);
142        assert_eq!(p.velocity, [0.0; 3]);
143    }
144    #[test]
145    fn test_p2g_g2p_roundtrip() {
146        let mut particles = vec![FlipParticle::new([0.25, 0.25, 0.25])];
147        particles[0].velocity = [1.0, 0.0, 0.0];
148        let mut grid = MacGrid::new(4, 4, 4, 0.1);
149        p2g_transfer(&particles, &mut grid);
150    }
151    #[test]
152    fn test_fluid_simulation_new() {
153        let config = FluidSimConfig::default();
154        let sim = FluidSimulation::new(config);
155        assert_eq!(sim.particles.len(), 0);
156        assert!((sim.time).abs() < 1e-15);
157    }
158    #[test]
159    fn test_fluid_simulation_add_block() {
160        let config = FluidSimConfig::default();
161        let mut sim = FluidSimulation::new(config);
162        sim.add_fluid_block([0.1; 3], [0.9; 3], 8);
163        assert!(sim.particles.len() >= 8);
164    }
165    #[test]
166    fn test_fluid_simulation_step() {
167        let config = FluidSimConfig {
168            grid_size: [8, 8, 8],
169            pressure_iters: 5,
170            ..Default::default()
171        };
172        let mut sim = FluidSimulation::new(config);
173        sim.add_fluid_block([0.1; 3], [0.5; 3], 4);
174        sim.step();
175        assert_eq!(sim.step_count, 1);
176        assert!(sim.time > 0.0);
177    }
178    #[test]
179    fn test_fluid_kinetic_energy_increases_under_gravity() {
180        let config = FluidSimConfig {
181            grid_size: [8, 8, 8],
182            pressure_iters: 5,
183            ..Default::default()
184        };
185        let mut sim = FluidSimulation::new(config);
186        sim.add_fluid_block([0.4; 3], [0.6; 3], 4);
187        let ke0 = sim.kinetic_energy();
188        sim.step();
189        let ke1 = sim.kinetic_energy();
190        assert!(ke1 >= ke0);
191    }
192    #[test]
193    fn test_advect_scalar_uniform_field() {
194        let nx = 4;
195        let ny = 4;
196        let nz = 4;
197        let grid = MacGrid::new(nx, ny, nz, 0.1);
198        let phi = vec![1.0f64; nx * ny * nz];
199        let result = advect_scalar(&phi, &grid, 0.01, [0.0, -9.81, 0.0]);
200        assert_eq!(result.len(), nx * ny * nz);
201        for v in &result {
202            assert!((v - 1.0).abs() < 1e-10);
203        }
204    }
205    #[test]
206    fn test_sph_particle_gravity_descent() {
207        let mut p = vec![SphParticle::new([0.0, 1.0, 0.0], 0.001)];
208        let config = SphConfig {
209            gravity: [0.0, -9.81, 0.0],
210            ..Default::default()
211        };
212        let y0 = p[0].position[1];
213        for _ in 0..100 {
214            sph_step(&mut p, &config);
215        }
216        assert!(p[0].position[1] < y0);
217    }
218    #[test]
219    fn test_lbm_outlet_pressure() {
220        let mut lbm = LbmD2Q9::new(8, 8, 0.8);
221        lbm.set_outlet_pressure(1.0);
222        assert_eq!(lbm.cell_type[7], LbmCellType::Outlet);
223    }
224    #[test]
225    fn test_mac_grid_pressure_project_no_panic() {
226        let mut g = MacGrid::new(4, 4, 4, 0.1);
227        g.flags = vec![1u8; 64];
228        g.pressure_project(1000.0, 0.01);
229    }
230    #[test]
231    fn test_gpu_sph_density_summation_parallel() {
232        let mut particles = vec![
233            SphParticle::new([0.0, 0.0, 0.0], 0.01),
234            SphParticle::new([0.05, 0.0, 0.0], 0.01),
235        ];
236        let config = SphConfig::default();
237        gpu_sph_density_parallel(&mut particles, &config);
238        assert!(particles[0].density > 0.0);
239        assert!(particles[1].density > 0.0);
240    }
241    #[test]
242    fn test_gpu_pressure_jacobi_single_iter() {
243        let mut g = MacGrid::new(4, 4, 4, 0.1);
244        g.flags = vec![1u8; 64];
245        gpu_jacobi_pressure_solve(&mut g, 1000.0, 0.01, 3);
246        assert_eq!(g.p.len(), 64);
247    }
248    #[test]
249    fn test_gpu_neighbor_list_update() {
250        let positions = vec![[0.0f64, 0.0, 0.0], [0.05, 0.0, 0.0], [0.3, 0.0, 0.0]];
251        let nl = GpuNeighborList::build(&positions, 0.1, [0.5, 0.5, 0.5]);
252        let neighbors = nl.neighbors_of(0);
253        assert!(neighbors.contains(&1));
254        assert!(!neighbors.contains(&2));
255    }
256    #[test]
257    fn test_gpu_lbm_bgk_collision() {
258        let mut lbm = LbmD2Q9::new(8, 8, 0.8);
259        gpu_lbm_bgk_collide(&mut lbm);
260        let rho = lbm.density(4, 4);
261        assert!((rho - 1.0).abs() < 1e-9);
262    }
263    #[test]
264    fn test_morton_sort_particles() {
265        let mut particles = vec![
266            SphParticle::new([0.9, 0.9, 0.9], 1.0),
267            SphParticle::new([0.0, 0.0, 0.0], 1.0),
268            SphParticle::new([0.5, 0.5, 0.5], 1.0),
269        ];
270        morton_sort_particles(&mut particles, [1.0, 1.0, 1.0]);
271        assert!(particles[0].position[0] < 0.2);
272    }
273    #[test]
274    fn test_gpu_particle_integrate_euler() {
275        let mut particles = vec![SphParticle::new([0.0, 0.0, 0.0], 1.0)];
276        particles[0].force = [1.0, 0.0, 0.0];
277        particles[0].density = 1.0;
278        gpu_particle_integrate_euler(&mut particles, 0.01);
279        assert!(particles[0].velocity[0] > 0.0);
280        assert!(particles[0].position[0] > 0.0);
281    }
282    #[test]
283    fn test_gpu_particle_integrate_verlet() {
284        let mut particles = vec![SphParticle::new([0.0, 1.0, 0.0], 1.0)];
285        particles[0].force = [0.0, -9.81, 0.0];
286        particles[0].density = 1.0;
287        let dt = 0.01;
288        let y0 = particles[0].position[1];
289        gpu_particle_integrate_verlet(&mut particles, dt, dt);
290        assert!(particles[0].position[1] < y0);
291    }
292    #[test]
293    fn test_gpu_boundary_condition_box() {
294        let mut particles = vec![SphParticle::new([1.5, 0.5, 0.5], 1.0)];
295        particles[0].velocity = [1.0, 0.0, 0.0];
296        let bounds = GpuBoundaryBox {
297            min: [0.0; 3],
298            max: [1.0; 3],
299            restitution: 0.5,
300        };
301        gpu_apply_boundary_box(&mut particles, &bounds);
302        assert!(particles[0].position[0] <= 1.0);
303        assert!(particles[0].velocity[0] <= 0.0);
304    }
305    #[test]
306    fn test_multi_gpu_domain_decomp_2_devices() {
307        let positions: Vec<[f64; 3]> = (0..8).map(|i| [i as f64 * 0.1, 0.0, 0.0]).collect();
308        let domains = MultiGpuDomain::decompose_x(&positions, 2);
309        assert_eq!(domains.len(), 2);
310        let total: usize = domains.iter().map(|d| d.particle_indices.len()).sum();
311        assert_eq!(total, 8);
312    }
313    #[test]
314    fn test_gpu_reduce_energy() {
315        let particles = [
316            SphParticle::new([0.0; 3], 1.0),
317            SphParticle::new([0.0; 3], 1.0),
318        ];
319        let mut p0 = particles[0].clone();
320        let mut p1 = particles[1].clone();
321        p0.velocity = [2.0, 0.0, 0.0];
322        p1.velocity = [0.0, 1.0, 0.0];
323        let particles2 = vec![p0, p1];
324        let ke = gpu_reduce_kinetic_energy(&particles2, 0.5);
325        assert!((ke - 1.25).abs() < 1e-10);
326    }
327    #[test]
328    fn test_gpu_reduce_momentum() {
329        let mut p = SphParticle::new([0.0; 3], 1.0);
330        p.velocity = [3.0, 0.0, 0.0];
331        let particles = vec![p];
332        let mom = gpu_reduce_momentum(&particles, 2.0);
333        assert!((mom[0] - 6.0).abs() < 1e-10);
334    }
335    #[test]
336    fn test_gpu_advect_field() {
337        let nx = 4usize;
338        let ny = 4;
339        let field: Vec<f64> = (0..nx * ny).map(|i| i as f64).collect();
340        let vel = vec![[0.0f64; 2]; nx * ny];
341        let result = gpu_advect_2d(&field, &vel, nx, ny, 0.1, 0.01);
342        assert_eq!(result.len(), nx * ny);
343    }
344    #[test]
345    fn test_gpu_pressure_poisson_staggered() {
346        let mut p_grid = vec![0.0f64; 4 * 4];
347        let div = vec![0.0f64; 4 * 4];
348        gpu_pressure_poisson_jacobi_2d(&mut p_grid, &div, 4, 4, 0.1, 5);
349        for &v in &p_grid {
350            assert!(v.abs() < 1e-10);
351        }
352    }
353    #[test]
354    fn test_neighbor_list_cell_counts() {
355        let positions: Vec<[f64; 3]> = (0..4).map(|i| [i as f64 * 0.02, 0.0, 0.0]).collect();
356        let nl = GpuNeighborList::build(&positions, 0.1, [0.5, 0.5, 0.5]);
357        let n0 = nl.neighbors_of(0);
358        assert_eq!(n0.len(), 3);
359    }
360    #[test]
361    fn test_morton_code_ordering() {
362        let a = morton_encode_3d(0, 0, 0);
363        let b = morton_encode_3d(1, 0, 0);
364        let c = morton_encode_3d(0, 1, 0);
365        assert!(a < b);
366        assert!(a < c);
367    }
368    #[test]
369    fn test_gpu_sph_verlet_energy_conservation_approx() {
370        let mut particles = vec![SphParticle::new([0.0, 0.5, 0.0], 0.01)];
371        let config = SphConfig {
372            gravity: [0.0, 0.0, 0.0],
373            ..Default::default()
374        };
375        sph_compute_density(&mut particles, &config);
376        sph_compute_pressure(&mut particles, &config);
377        let v_before = particles[0].velocity;
378        gpu_particle_integrate_verlet(&mut particles, 0.001, 0.001);
379        let v_after = particles[0].velocity;
380        assert!((v_before[1] - v_after[1]).abs() < 1e-8);
381    }
382    #[test]
383    fn test_domain_decomp_particles_go_to_correct_half() {
384        let positions: Vec<[f64; 3]> = vec![
385            [0.1, 0.0, 0.0],
386            [0.2, 0.0, 0.0],
387            [0.6, 0.0, 0.0],
388            [0.8, 0.0, 0.0],
389        ];
390        let domains = MultiGpuDomain::decompose_x(&positions, 2);
391        assert_eq!(domains[0].particle_indices.len(), 2);
392        assert_eq!(domains[1].particle_indices.len(), 2);
393    }
394}