Matrix for Upwind4
This commit is contained in:
		@@ -178,6 +178,71 @@ pub(crate) mod constmatrix {
 | 
			
		||||
            let m3 = m1 * m2;
 | 
			
		||||
            assert_eq!(m3, Matrix::new([[74, 80, 86, 92], [173, 188, 203, 218]]));
 | 
			
		||||
        }
 | 
			
		||||
        #[test]
 | 
			
		||||
        fn iter() {
 | 
			
		||||
            let m = Matrix::new([[1_u8, 2, 3], [4, 5, 6]]);
 | 
			
		||||
            let mut iter = m.iter();
 | 
			
		||||
            assert_eq!(iter.next(), Some(&1));
 | 
			
		||||
            assert_eq!(iter.next(), Some(&2));
 | 
			
		||||
            assert_eq!(iter.next(), Some(&3));
 | 
			
		||||
            assert_eq!(iter.next(), Some(&4));
 | 
			
		||||
            assert_eq!(iter.next(), Some(&5));
 | 
			
		||||
            assert_eq!(iter.next(), Some(&6));
 | 
			
		||||
            assert_eq!(iter.next(), None);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mod approx {
 | 
			
		||||
        use super::Matrix;
 | 
			
		||||
        use ::approx::{AbsDiffEq, RelativeEq, UlpsEq};
 | 
			
		||||
 | 
			
		||||
        impl<T, const M: usize, const N: usize> AbsDiffEq for Matrix<T, M, N>
 | 
			
		||||
        where
 | 
			
		||||
            T: AbsDiffEq,
 | 
			
		||||
        {
 | 
			
		||||
            type Epsilon = T::Epsilon;
 | 
			
		||||
            fn default_epsilon() -> Self::Epsilon {
 | 
			
		||||
                T::default_epsilon()
 | 
			
		||||
            }
 | 
			
		||||
            fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
 | 
			
		||||
                self.iter()
 | 
			
		||||
                    .zip(other.iter())
 | 
			
		||||
                    .all(|(r, l)| r.abs_diff_eq(l, T::default_epsilon()))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        impl<T, const M: usize, const N: usize> RelativeEq for Matrix<T, M, N>
 | 
			
		||||
        where
 | 
			
		||||
            T: RelativeEq,
 | 
			
		||||
            Self::Epsilon: Copy,
 | 
			
		||||
        {
 | 
			
		||||
            fn default_max_relative() -> Self::Epsilon {
 | 
			
		||||
                T::default_max_relative()
 | 
			
		||||
            }
 | 
			
		||||
            fn relative_eq(
 | 
			
		||||
                &self,
 | 
			
		||||
                other: &Self,
 | 
			
		||||
                epsilon: Self::Epsilon,
 | 
			
		||||
                max_relative: Self::Epsilon,
 | 
			
		||||
            ) -> bool {
 | 
			
		||||
                self.iter()
 | 
			
		||||
                    .zip(other.iter())
 | 
			
		||||
                    .all(|(r, l)| r.relative_eq(l, epsilon, max_relative))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        impl<T, const M: usize, const N: usize> UlpsEq for Matrix<T, M, N>
 | 
			
		||||
        where
 | 
			
		||||
            T: UlpsEq,
 | 
			
		||||
            Self::Epsilon: Copy,
 | 
			
		||||
        {
 | 
			
		||||
            fn default_max_ulps() -> u32 {
 | 
			
		||||
                T::default_max_ulps()
 | 
			
		||||
            }
 | 
			
		||||
            fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
 | 
			
		||||
                self.iter()
 | 
			
		||||
                    .zip(other.iter())
 | 
			
		||||
                    .all(|(r, l)| r.ulps_eq(l, epsilon, max_ulps))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -228,6 +293,7 @@ pub(crate) fn diff_op_1d_matrix<const M: usize, const N: usize, const D: usize>(
 | 
			
		||||
        *f = diff * idx;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let prev = prev.slice(ndarray::s![nx - N..]);
 | 
			
		||||
    for (bl, f) in blockend.iter_rows().zip(fut.iter_mut().rev().take(M).rev()) {
 | 
			
		||||
        let diff = bl
 | 
			
		||||
            .iter()
 | 
			
		||||
 
 | 
			
		||||
@@ -240,8 +240,5 @@ fn block_equality() {
 | 
			
		||||
    let mut flipped_inverted = SBP4::BLOCK_MATRIX.flip();
 | 
			
		||||
    flipped_inverted *= -1.0;
 | 
			
		||||
 | 
			
		||||
    assert!(flipped_inverted
 | 
			
		||||
        .iter()
 | 
			
		||||
        .zip(SBP4::BLOCKEND_MATRIX.iter())
 | 
			
		||||
        .all(|(x, y)| (x - y).abs() < 1e-3))
 | 
			
		||||
    approx::assert_ulps_eq!(SBP4::BLOCKEND_MATRIX, flipped_inverted, max_ulps = 1);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -221,8 +221,5 @@ fn block_equality() {
 | 
			
		||||
    let mut flipped_inverted = SBP8::BLOCK_MATRIX.flip();
 | 
			
		||||
    flipped_inverted *= -1.0;
 | 
			
		||||
 | 
			
		||||
    assert!(flipped_inverted
 | 
			
		||||
        .iter()
 | 
			
		||||
        .zip(SBP8::BLOCKEND_MATRIX.iter())
 | 
			
		||||
        .all(|(x, y)| (x - y).abs() < 1e-12))
 | 
			
		||||
    approx::assert_ulps_eq!(SBP8::BLOCKEND_MATRIX, flipped_inverted, max_ulps = 1);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
use super::{
 | 
			
		||||
    diff_op_col, diff_op_row, SbpOperator1d, SbpOperator2d, UpwindOperator1d, UpwindOperator2d,
 | 
			
		||||
    diff_op_col, diff_op_row, Matrix, RowVector, SbpOperator1d, SbpOperator2d, UpwindOperator1d,
 | 
			
		||||
    UpwindOperator2d,
 | 
			
		||||
};
 | 
			
		||||
use crate::Float;
 | 
			
		||||
use ndarray::{ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2, Axis};
 | 
			
		||||
@@ -174,12 +175,30 @@ impl Upwind4 {
 | 
			
		||||
        -1.0 / 24.0, 1.0 / 4.0, -7.0 / 8.0, 0.0, 7.0 / 8.0, -1.0 / 4.0, 1.0 / 24.0
 | 
			
		||||
    ];
 | 
			
		||||
    #[rustfmt::skip]
 | 
			
		||||
    const DIAG_MATRIX : RowVector<Float, 7> = RowVector::new([
 | 
			
		||||
        [-1.0 / 24.0, 1.0 / 4.0, -7.0 / 8.0, 0.0, 7.0 / 8.0, -1.0 / 4.0, 1.0 / 24.0]
 | 
			
		||||
    ]);
 | 
			
		||||
    #[rustfmt::skip]
 | 
			
		||||
    const BLOCK: &'static [&'static [Float]] = &[
 | 
			
		||||
        &[  -72.0 / 49.0, 187.0 / 98.0,   -20.0 / 49.0,   -3.0 / 98.0,           0.0,           0.0,         0.0],
 | 
			
		||||
        &[-187.0 / 366.0,          0.0,   69.0 / 122.0, -16.0 / 183.0,    2.0 / 61.0,           0.0,         0.0],
 | 
			
		||||
        &[  20.0 / 123.0, -69.0 / 82.0,            0.0, 227.0 / 246.0,  -12.0 / 41.0,    2.0 / 41.0,         0.0],
 | 
			
		||||
        &[   3.0 / 298.0, 16.0 / 149.0, -227.0 / 298.0,           0.0, 126.0 / 149.0, -36.0 / 149.0, 6.0 / 149.0],
 | 
			
		||||
    ];
 | 
			
		||||
    #[rustfmt::skip]
 | 
			
		||||
    const BLOCK_MATRIX: Matrix<Float, 4, 7> = Matrix::new([
 | 
			
		||||
        [  -72.0 / 49.0, 187.0 / 98.0,   -20.0 / 49.0,   -3.0 / 98.0,           0.0,           0.0,         0.0],
 | 
			
		||||
        [-187.0 / 366.0,          0.0,   69.0 / 122.0, -16.0 / 183.0,    2.0 / 61.0,           0.0,         0.0],
 | 
			
		||||
        [  20.0 / 123.0, -69.0 / 82.0,            0.0, 227.0 / 246.0,  -12.0 / 41.0,    2.0 / 41.0,         0.0],
 | 
			
		||||
        [   3.0 / 298.0, 16.0 / 149.0, -227.0 / 298.0,           0.0, 126.0 / 149.0, -36.0 / 149.0, 6.0 / 149.0],
 | 
			
		||||
    ]);
 | 
			
		||||
    #[rustfmt::skip]
 | 
			
		||||
    const BLOCKEND_MATRIX: Matrix<Float, 4, 7> = Matrix::new([
 | 
			
		||||
        [ -6.0 / 149.0, 36.0 / 149.0, -126.0 / 149.0, 0.0, 227.0 / 298.0, -16.0 / 149.0, -3.0 / 298.0],
 | 
			
		||||
        [ 0.0, -2.0/41.0, 12.0/41.0, -227.0/246.0, 0.0, 69.0/82.0,  -20.0/123.0],
 | 
			
		||||
        [ 0.0, 0.0, -2.0/61.0, 16.0/183.0, -69.0/122.0, 0.0, 187.0/366.0],
 | 
			
		||||
        [  0.0, 0.0, 0.0, 3.0 / 98.0, 20.0 / 49.0, -187.0 / 98.0, 72.0/49.0],
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    #[rustfmt::skip]
 | 
			
		||||
    const DISS_BLOCK: &'static [&'static [Float]] = &[
 | 
			
		||||
@@ -197,10 +216,10 @@ impl Upwind4 {
 | 
			
		||||
 | 
			
		||||
impl SbpOperator1d for Upwind4 {
 | 
			
		||||
    fn diff(&self, prev: ArrayView1<Float>, fut: ArrayViewMut1<Float>) {
 | 
			
		||||
        super::diff_op_1d(
 | 
			
		||||
            Self::BLOCK,
 | 
			
		||||
            Self::DIAG,
 | 
			
		||||
            super::Symmetry::AntiSymmetric,
 | 
			
		||||
        super::diff_op_1d_matrix(
 | 
			
		||||
            &Self::BLOCK_MATRIX,
 | 
			
		||||
            &Self::BLOCKEND_MATRIX,
 | 
			
		||||
            &Self::DIAG_MATRIX,
 | 
			
		||||
            super::OperatorType::Normal,
 | 
			
		||||
            prev,
 | 
			
		||||
            fut,
 | 
			
		||||
@@ -229,18 +248,29 @@ impl SbpOperator1d for Upwind4 {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn diff_op_row_local(prev: ndarray::ArrayView2<Float>, mut fut: ndarray::ArrayViewMut2<Float>) {
 | 
			
		||||
    for (p, mut f) in prev
 | 
			
		||||
        .axis_iter(ndarray::Axis(0))
 | 
			
		||||
        .zip(fut.axis_iter_mut(ndarray::Axis(0)))
 | 
			
		||||
    {
 | 
			
		||||
        super::diff_op_1d_slice_matrix(
 | 
			
		||||
            &Upwind4::BLOCK_MATRIX,
 | 
			
		||||
            &Upwind4::BLOCKEND_MATRIX,
 | 
			
		||||
            &Upwind4::DIAG_MATRIX,
 | 
			
		||||
            super::OperatorType::Normal,
 | 
			
		||||
            p.as_slice().unwrap(),
 | 
			
		||||
            f.as_slice_mut().unwrap(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl SbpOperator2d for Upwind4 {
 | 
			
		||||
    fn diffxi(&self, prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
 | 
			
		||||
        assert_eq!(prev.shape(), fut.shape());
 | 
			
		||||
        assert!(prev.shape()[1] >= 2 * Upwind4::BLOCK.len());
 | 
			
		||||
 | 
			
		||||
        match (prev.strides(), fut.strides()) {
 | 
			
		||||
            ([_, 1], [_, 1]) => diff_op_row(
 | 
			
		||||
                Upwind4::BLOCK,
 | 
			
		||||
                Upwind4::DIAG,
 | 
			
		||||
                super::Symmetry::AntiSymmetric,
 | 
			
		||||
                super::OperatorType::Normal,
 | 
			
		||||
            )(prev, fut),
 | 
			
		||||
            ([_, 1], [_, 1]) => diff_op_row_local(prev, fut),
 | 
			
		||||
            ([1, _], [1, _]) if prev.len_of(Axis(0)) % SimdT::lanes() == 0 => {
 | 
			
		||||
                diff_simd_col(prev, fut)
 | 
			
		||||
            }
 | 
			
		||||
@@ -465,3 +495,11 @@ fn upwind4_test2() {
 | 
			
		||||
        1e-1,
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn block_equality() {
 | 
			
		||||
    let mut flipped_inverted = Upwind4::BLOCK_MATRIX.flip();
 | 
			
		||||
    flipped_inverted *= -1.0;
 | 
			
		||||
 | 
			
		||||
    approx::assert_ulps_eq!(Upwind4::BLOCKEND_MATRIX, flipped_inverted, max_ulps = 1);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user