use crate::errors::QlResult;
use crate::require;
use crate::types::{Real, Size};
use crate::utilities::null::Null;
use super::fdm1dmesher::Fdm1dMesher;
#[allow(clippy::neg_cmp_op_on_partial_ord)]
pub fn uniform_1d_mesher(start: Real, end: Real, size: Size) -> QlResult<Fdm1dMesher> {
require!(end > start, "end must be larger than start");
let dx = (end - start) / (size - 1) as Real;
let mut locations = vec![0.0; size];
let mut dplus = vec![0.0; size];
let mut dminus = vec![0.0; size];
for i in 0..size - 1 {
locations[i] = start + i as Real * dx;
dplus[i] = dx;
dminus[i + 1] = dx;
}
locations[size - 1] = end;
dplus[size - 1] = Real::null();
dminus[0] = Real::null();
Ok(Fdm1dMesher::new(locations, dplus, dminus))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn grid_is_equidistant_with_null_gaps_at_the_boundaries() {
let size = 5;
let mesher = uniform_1d_mesher(0.0, 1.0, size).unwrap();
let dx = 0.25;
assert_eq!(mesher.size(), size);
assert_eq!(mesher.locations(), [0.0, 0.25, 0.5, 0.75, 1.0]);
for i in 0..size {
assert_eq!(mesher.location(i), i as Real * dx);
}
for i in 0..size - 1 {
assert_eq!(mesher.dplus(i), dx);
assert_eq!(mesher.dminus(i + 1), dx);
}
assert!(mesher.dplus(size - 1).is_null());
assert!(mesher.dminus(0).is_null());
}
#[test]
fn end_must_be_larger_than_start() {
let err = uniform_1d_mesher(1.0, 1.0, 5).unwrap_err();
assert_eq!(err.message(), "end must be larger than start");
}
}