124 lines
3.3 KiB
Rust
124 lines
3.3 KiB
Rust
use crate::Float;
|
|
|
|
#[cfg(feature = "sparse")]
|
|
mod jacobi;
|
|
#[cfg(feature = "sparse")]
|
|
pub use jacobi::*;
|
|
#[cfg(feature = "serde")]
|
|
use serde::{Deserialize, Serialize};
|
|
#[cfg(feature = "sparse")]
|
|
pub use sprs::kronecker_product;
|
|
|
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
#[derive(Copy, Clone, Debug, Default)]
|
|
/// struct to hold output for four directions
|
|
pub struct Direction<T> {
|
|
pub north: T,
|
|
pub south: T,
|
|
pub west: T,
|
|
pub east: T,
|
|
}
|
|
|
|
impl<T> Direction<T> {
|
|
pub fn as_ref(&self) -> Direction<&T> {
|
|
Direction {
|
|
north: &self.north,
|
|
south: &self.south,
|
|
west: &self.west,
|
|
east: &self.east,
|
|
}
|
|
}
|
|
pub fn as_mut(&mut self) -> Direction<&mut T> {
|
|
Direction {
|
|
north: &mut self.north,
|
|
south: &mut self.south,
|
|
west: &mut self.west,
|
|
east: &mut self.east,
|
|
}
|
|
}
|
|
pub fn map<U>(self, f: impl Fn(T) -> U) -> Direction<U> {
|
|
Direction {
|
|
north: f(self.north),
|
|
south: f(self.south),
|
|
west: f(self.west),
|
|
east: f(self.east),
|
|
}
|
|
}
|
|
/// Combines two [`Direction`] into one
|
|
pub fn zip<U>(self, other: Direction<U>) -> Direction<(T, U)> {
|
|
Direction {
|
|
north: (self.north, other.north),
|
|
south: (self.south, other.south),
|
|
west: (self.west, other.west),
|
|
east: (self.east, other.east),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> Direction<Option<T>> {
|
|
/// Partially unwrap individual components in `self` or replace with
|
|
/// `other`
|
|
pub fn unwrap_or(self, other: Direction<T>) -> Direction<T> {
|
|
Direction {
|
|
north: self.north.unwrap_or(other.north),
|
|
south: self.south.unwrap_or(other.south),
|
|
west: self.west.unwrap_or(other.west),
|
|
east: self.east.unwrap_or(other.east),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Methods for borrowing
|
|
impl<T> Direction<T> {
|
|
pub fn north(&self) -> &T {
|
|
&self.north
|
|
}
|
|
pub fn north_mut(&mut self) -> &mut T {
|
|
&mut self.north
|
|
}
|
|
pub fn south(&self) -> &T {
|
|
&self.south
|
|
}
|
|
pub fn south_mut(&mut self) -> &mut T {
|
|
&mut self.south
|
|
}
|
|
pub fn east(&self) -> &T {
|
|
&self.east
|
|
}
|
|
pub fn east_mut(&mut self) -> &mut T {
|
|
&mut self.east
|
|
}
|
|
pub fn west(&self) -> &T {
|
|
&self.west
|
|
}
|
|
pub fn west_mut(&mut self) -> &mut T {
|
|
&mut self.west
|
|
}
|
|
}
|
|
|
|
/// Linearly spaced parameters, apart from the boundaries which
|
|
/// only have a distance of `h/2` from the boundary
|
|
pub fn h2linspace(start: Float, end: Float, n: usize) -> ndarray::Array1<Float> {
|
|
let h = (end - start) / (n - 2) as Float;
|
|
ndarray::Array1::from_shape_fn(n, |i| match i {
|
|
0 => start,
|
|
i if i == n - 1 => end,
|
|
i => start + h * (i as Float - 0.5),
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn test_h2linspace() {
|
|
let x = h2linspace(-1.0, 1.0, 50);
|
|
println!("{}", x);
|
|
approx::assert_abs_diff_eq!(x[0], -1.0, epsilon = 1e-6);
|
|
approx::assert_abs_diff_eq!(x[49], 1.0, epsilon = 1e-6);
|
|
let hend = x[1] - x[0];
|
|
let h = x[2] - x[1];
|
|
approx::assert_abs_diff_eq!(x[49] - x[48], hend, epsilon = 1e-6);
|
|
approx::assert_abs_diff_eq!(2.0 * hend, h, epsilon = 1e-6);
|
|
for i in 1..48 {
|
|
approx::assert_abs_diff_eq!(x[i + 1] - x[i], h, epsilon = 1e-6);
|
|
}
|
|
}
|