use crate::fdtd::config::{Dimensions, GridSpacing};
use crate::units::conversion::SPEED_OF_LIGHT;
pub fn courant_dt(dims: Dimensions, spacing: GridSpacing, n_min: f64) -> f64 {
let c = SPEED_OF_LIGHT / n_min;
match dims {
Dimensions::OneD { .. } => spacing.dz / c,
Dimensions::TwoD { .. } => {
let inv_sum = 1.0 / (spacing.dx * spacing.dx) + 1.0 / (spacing.dy * spacing.dy);
1.0 / (c * inv_sum.sqrt())
}
Dimensions::ThreeD { .. } => {
let inv_sum = 1.0 / (spacing.dx * spacing.dx)
+ 1.0 / (spacing.dy * spacing.dy)
+ 1.0 / (spacing.dz * spacing.dz);
1.0 / (c * inv_sum.sqrt())
}
}
}
pub fn courant_number(dt: f64, dx: f64, n_min: f64) -> f64 {
SPEED_OF_LIGHT / n_min * dt / dx
}
#[cfg(test)]
mod tests {
use super::*;
use approx::assert_relative_eq;
#[test]
fn courant_1d_vacuum() {
let spacing = GridSpacing::uniform(10e-9); let dt = courant_dt(Dimensions::OneD { nz: 100 }, spacing, 1.0);
let s = courant_number(dt, spacing.dz, 1.0);
assert_relative_eq!(s, 1.0, epsilon = 1e-12);
}
#[test]
fn courant_2d_vacuum() {
let spacing = GridSpacing::uniform(10e-9);
let dt = courant_dt(Dimensions::TwoD { nx: 100, ny: 100 }, spacing, 1.0);
let s = courant_number(dt, spacing.dx, 1.0);
assert_relative_eq!(s, 1.0 / 2.0_f64.sqrt(), epsilon = 1e-12);
}
}