ringkernel_wavesim/simulation/
physics.rs1#[derive(Debug, Clone)]
8pub struct AcousticParams {
9 pub speed_of_sound: f32,
11
12 pub cell_size: f32,
14
15 pub time_step: f32,
17
18 pub damping: f32,
20}
21
22impl Default for AcousticParams {
23 fn default() -> Self {
24 Self::new(343.0, 1.0)
25 }
26}
27
28impl AcousticParams {
29 pub fn new(speed_of_sound: f32, cell_size: f32) -> Self {
38 let dt = cell_size / (speed_of_sound * 1.5);
41
42 Self {
43 speed_of_sound,
44 cell_size,
45 time_step: dt,
46 damping: 0.001,
47 }
48 }
49
50 pub fn with_damping(mut self, damping: f32) -> Self {
52 self.damping = damping.clamp(0.0, 1.0);
53 self
54 }
55
56 pub fn courant_number(&self) -> f32 {
60 self.speed_of_sound * self.time_step / self.cell_size
61 }
62
63 pub fn is_stable(&self) -> bool {
65 self.courant_number() <= 1.0 / std::f32::consts::SQRT_2
66 }
67
68 pub fn set_speed_of_sound(&mut self, speed: f32) {
70 self.speed_of_sound = speed.max(1.0); self.time_step = self.cell_size / (self.speed_of_sound * 1.5);
72 }
73
74 pub fn set_cell_size(&mut self, size: f32) {
76 self.cell_size = size.max(0.001); self.time_step = self.cell_size / (self.speed_of_sound * 1.5);
78 }
79
80 pub fn wavelength(&self, frequency: f32) -> f32 {
82 self.speed_of_sound / frequency
83 }
84
85 pub fn cells_per_wavelength(&self, frequency: f32) -> f32 {
87 self.wavelength(frequency) / self.cell_size
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_default_params() {
97 let params = AcousticParams::default();
98 assert_eq!(params.speed_of_sound, 343.0);
99 assert_eq!(params.cell_size, 1.0);
100 }
101
102 #[test]
103 fn test_stability() {
104 let params = AcousticParams::new(343.0, 1.0);
105 assert!(params.is_stable(), "Default parameters should be stable");
106 assert!(
107 params.courant_number() <= 1.0 / std::f32::consts::SQRT_2,
108 "Courant number should satisfy CFL condition"
109 );
110 }
111
112 #[test]
113 fn test_speed_change() {
114 let mut params = AcousticParams::new(343.0, 1.0);
115 params.set_speed_of_sound(1000.0);
116 assert_eq!(params.speed_of_sound, 1000.0);
117 assert!(
118 params.is_stable(),
119 "Should remain stable after speed change"
120 );
121 }
122
123 #[test]
124 fn test_wavelength() {
125 let params = AcousticParams::new(343.0, 1.0);
126 let wavelength = params.wavelength(343.0);
128 assert!((wavelength - 1.0).abs() < 0.01);
129 }
130
131 #[test]
132 fn test_courant_number() {
133 let params = AcousticParams::new(343.0, 1.0);
134 let c = params.courant_number();
135 assert!((c - 1.0 / 1.5).abs() < 0.01);
137 }
138}