|
| 1 | +extern crate arrayfire as af; |
| 2 | + |
| 3 | +use af::*; |
| 4 | +use std::f64::consts::*; |
| 5 | + |
| 6 | +fn main() { |
| 7 | + set_device(0); |
| 8 | + info(); |
| 9 | + |
| 10 | + acoustic_wave_simulation(); |
| 11 | +} |
| 12 | + |
| 13 | +fn normalise(a: &Array) -> Array { |
| 14 | + (a/(max_all(&abs(a)).0 as f32 * 2.0f32)) + 0.5f32 |
| 15 | +} |
| 16 | +fn acoustic_wave_simulation() { |
| 17 | + // Speed of sound |
| 18 | + let c = 0.1; |
| 19 | + // Distance step |
| 20 | + let dx = 0.5; |
| 21 | + // Time step |
| 22 | + let dt = 1.0; |
| 23 | + |
| 24 | + // Grid size. |
| 25 | + let nx = 1500; |
| 26 | + let ny = 1500; |
| 27 | + |
| 28 | + // Grid dimensions. |
| 29 | + let dims = Dim4::new(&[nx, ny, 1, 1]); |
| 30 | + |
| 31 | + // Pressure field |
| 32 | + let mut p = constant::<f32>(0.0, dims); |
| 33 | + // d(pressure)/dt field |
| 34 | + let mut p_dot = p.clone(); |
| 35 | + |
| 36 | + // Laplacian (Del^2) convolution kernel. |
| 37 | + let laplacian_values = [0.0f32, 1.0, 0.0, |
| 38 | + 1.0, -4.0, 1.0, |
| 39 | + 0.0, 1.0, 0.0]; |
| 40 | + let laplacian_kernel = Array::new(&laplacian_values, Dim4::new(&[3, 3, 1, 1])) / (dx * dx); |
| 41 | + |
| 42 | + // Create a window to show the waves. |
| 43 | + let mut win = Window::new(1000, 1000, "Waves".to_string()); |
| 44 | + |
| 45 | + // Hann windowed pulse. |
| 46 | + let pulse_time = 100.0f64; |
| 47 | + let centre_freq = 0.05; |
| 48 | + |
| 49 | + // Number of samples in pulse. |
| 50 | + let pulse_n = (pulse_time/dt).floor() as u64; |
| 51 | + |
| 52 | + let i = range::<f32>(Dim4::new(&[pulse_n, 1, 1, 1]), 0); |
| 53 | + let t = i.clone() * dt; |
| 54 | + let hamming_window = cos(&(i * (2.0 * PI / pulse_n as f64))) * -0.46 + 0.54; |
| 55 | + let wave = sin(&(&t * centre_freq * 2.0 * PI)); |
| 56 | + let pulse = wave * hamming_window; |
| 57 | + |
| 58 | + // Iteration count. |
| 59 | + let mut it = 0; |
| 60 | + |
| 61 | + while !win.is_closed() { |
| 62 | + // Convole with laplacian to get spacial second derivative. |
| 63 | + let lap_p = convolve2(&p, &laplacian_kernel, ConvMode::DEFAULT, ConvDomain::SPATIAL); |
| 64 | + // Calculate the updated pressure and d(pressure)/dt fields. |
| 65 | + p_dot += lap_p * (c * dt); |
| 66 | + p += &p_dot * dt; |
| 67 | + |
| 68 | + if it < pulse_n { |
| 69 | + // Location of the source. |
| 70 | + let seqs = &[Seq::new(700.0, 800.0, 1.0), Seq::new(800.0, 800.0, 1.0)]; |
| 71 | + // Set the pressure there. |
| 72 | + p = assign_seq(&p, seqs, &index(&pulse, &[Seq::new(it as f64, it as f64, 1.0)])); |
| 73 | + } |
| 74 | + |
| 75 | + // Draw the image. |
| 76 | + win.set_colormap(af::ColorMap::BLUE); |
| 77 | + win.draw_image(&normalise(&p), None); |
| 78 | + |
| 79 | + it += 1; |
| 80 | + } |
| 81 | +} |
0 commit comments