use crate::{Grid2d, Side};
use std::sync::Arc;
pub struct NaturalBcs2d<'a> {
pub(crate) functions: Vec<Arc<dyn Fn(f64, f64) -> f64 + Send + Sync + 'a>>,
pub(crate) sides: [bool; 4], }
impl<'a> NaturalBcs2d<'a> {
pub fn new() -> Self {
NaturalBcs2d {
functions: vec![
Arc::new(|_, _| 0.0), Arc::new(|_, _| 0.0), Arc::new(|_, _| 0.0), Arc::new(|_, _| 0.0), ],
sides: [false; 4],
}
}
pub fn set(&mut self, side: Side, f: impl Fn(f64, f64) -> f64 + Send + Sync + 'a) {
let index = side as usize;
self.functions[index] = Arc::new(f);
self.sides[index] = true;
}
pub(crate) fn enabled_ij(&self, i: usize, j: usize, grid: &Grid2d) -> bool {
if i == 0 {
self.sides[0]
} else if i == grid.nx() - 1 {
self.sides[1]
} else if j == 0 {
self.sides[2]
} else if j == grid.ny() - 1 {
self.sides[3]
}
else if i == 0 && j == 0 {
self.sides[0] || self.sides[2]
} else if i == 0 && j == grid.ny() - 1 {
self.sides[0] || self.sides[3]
} else if i == grid.nx() - 1 && j == 0 {
self.sides[1] || self.sides[2]
} else if i == grid.nx() - 1 && j == grid.ny() - 1 {
self.sides[1] || self.sides[3]
}
else {
false
}
}
}
#[cfg(test)]
mod tests {
use super::NaturalBcs2d;
use crate::{Grid2d, Side};
#[test]
fn new_works() {
let natural_bcs = NaturalBcs2d::new();
assert_eq!(natural_bcs.sides, [false, false, false, false]);
assert_eq!((natural_bcs.functions[0])(0.0, 0.0), 0.0);
assert_eq!((natural_bcs.functions[1])(0.0, 0.0), 0.0);
assert_eq!((natural_bcs.functions[2])(0.0, 0.0), 0.0);
assert_eq!((natural_bcs.functions[3])(0.0, 0.0), 0.0);
}
#[test]
fn set_works() {
let mut natural_bcs = NaturalBcs2d::new();
natural_bcs.set(Side::Xmin, |_, _| -10.0);
natural_bcs.set(Side::Xmax, |_, _| 10.0);
natural_bcs.set(Side::Ymin, |_, _| -20.0);
natural_bcs.set(Side::Ymax, |_, _| 20.0);
assert_eq!(natural_bcs.sides, [true, true, true, true]);
assert_eq!((natural_bcs.functions[0])(0.0, 0.0), -10.0);
assert_eq!((natural_bcs.functions[1])(0.0, 0.0), 10.0);
assert_eq!((natural_bcs.functions[2])(0.0, 0.0), -20.0);
assert_eq!((natural_bcs.functions[3])(0.0, 0.0), 20.0);
}
#[test]
fn enabled_ij_works() {
let grid = Grid2d::new_uniform(0.0, 1.0, 0.0, 1.0, 3, 3).unwrap();
let mut natural_bcs = NaturalBcs2d::new();
natural_bcs.set(Side::Xmin, |_, _| -10.0);
assert!(natural_bcs.enabled_ij(0, 0, &grid)); assert!(natural_bcs.enabled_ij(0, 1, &grid));
assert!(natural_bcs.enabled_ij(0, 2, &grid)); assert!(!natural_bcs.enabled_ij(1, 0, &grid));
assert!(!natural_bcs.enabled_ij(1, 1, &grid));
assert!(!natural_bcs.enabled_ij(1, 2, &grid));
assert!(!natural_bcs.enabled_ij(2, 0, &grid));
assert!(!natural_bcs.enabled_ij(2, 1, &grid));
assert!(!natural_bcs.enabled_ij(2, 2, &grid));
natural_bcs.set(Side::Xmax, |_, _| 10.0);
assert!(natural_bcs.enabled_ij(2, 0, &grid)); assert!(natural_bcs.enabled_ij(2, 1, &grid));
assert!(natural_bcs.enabled_ij(2, 2, &grid));
natural_bcs.set(Side::Ymin, |_, _| -20.0);
assert!(natural_bcs.enabled_ij(0, 0, &grid)); assert!(natural_bcs.enabled_ij(1, 0, &grid));
assert!(natural_bcs.enabled_ij(2, 0, &grid));
natural_bcs.set(Side::Ymax, |_, _| 20.0);
assert!(natural_bcs.enabled_ij(0, 2, &grid)); assert!(natural_bcs.enabled_ij(1, 2, &grid));
assert!(natural_bcs.enabled_ij(2, 2, &grid)); }
}