Matrix for Upwind4
This commit is contained in:
parent
45e4d51513
commit
c660354c3f
|
@ -178,6 +178,71 @@ pub(crate) mod constmatrix {
|
||||||
let m3 = m1 * m2;
|
let m3 = m1 * m2;
|
||||||
assert_eq!(m3, Matrix::new([[74, 80, 86, 92], [173, 188, 203, 218]]));
|
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;
|
*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()) {
|
for (bl, f) in blockend.iter_rows().zip(fut.iter_mut().rev().take(M).rev()) {
|
||||||
let diff = bl
|
let diff = bl
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -240,8 +240,5 @@ fn block_equality() {
|
||||||
let mut flipped_inverted = SBP4::BLOCK_MATRIX.flip();
|
let mut flipped_inverted = SBP4::BLOCK_MATRIX.flip();
|
||||||
flipped_inverted *= -1.0;
|
flipped_inverted *= -1.0;
|
||||||
|
|
||||||
assert!(flipped_inverted
|
approx::assert_ulps_eq!(SBP4::BLOCKEND_MATRIX, flipped_inverted, max_ulps = 1);
|
||||||
.iter()
|
|
||||||
.zip(SBP4::BLOCKEND_MATRIX.iter())
|
|
||||||
.all(|(x, y)| (x - y).abs() < 1e-3))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,8 +221,5 @@ fn block_equality() {
|
||||||
let mut flipped_inverted = SBP8::BLOCK_MATRIX.flip();
|
let mut flipped_inverted = SBP8::BLOCK_MATRIX.flip();
|
||||||
flipped_inverted *= -1.0;
|
flipped_inverted *= -1.0;
|
||||||
|
|
||||||
assert!(flipped_inverted
|
approx::assert_ulps_eq!(SBP8::BLOCKEND_MATRIX, flipped_inverted, max_ulps = 1);
|
||||||
.iter()
|
|
||||||
.zip(SBP8::BLOCKEND_MATRIX.iter())
|
|
||||||
.all(|(x, y)| (x - y).abs() < 1e-12))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::{
|
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 crate::Float;
|
||||||
use ndarray::{ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2, Axis};
|
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
|
-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]
|
#[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]] = &[
|
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],
|
&[ -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],
|
&[-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],
|
&[ 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],
|
&[ 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]
|
#[rustfmt::skip]
|
||||||
const DISS_BLOCK: &'static [&'static [Float]] = &[
|
const DISS_BLOCK: &'static [&'static [Float]] = &[
|
||||||
|
@ -197,10 +216,10 @@ impl Upwind4 {
|
||||||
|
|
||||||
impl SbpOperator1d for Upwind4 {
|
impl SbpOperator1d for Upwind4 {
|
||||||
fn diff(&self, prev: ArrayView1<Float>, fut: ArrayViewMut1<Float>) {
|
fn diff(&self, prev: ArrayView1<Float>, fut: ArrayViewMut1<Float>) {
|
||||||
super::diff_op_1d(
|
super::diff_op_1d_matrix(
|
||||||
Self::BLOCK,
|
&Self::BLOCK_MATRIX,
|
||||||
Self::DIAG,
|
&Self::BLOCKEND_MATRIX,
|
||||||
super::Symmetry::AntiSymmetric,
|
&Self::DIAG_MATRIX,
|
||||||
super::OperatorType::Normal,
|
super::OperatorType::Normal,
|
||||||
prev,
|
prev,
|
||||||
fut,
|
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 {
|
impl SbpOperator2d for Upwind4 {
|
||||||
fn diffxi(&self, prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
fn diffxi(&self, prev: ArrayView2<Float>, mut fut: ArrayViewMut2<Float>) {
|
||||||
assert_eq!(prev.shape(), fut.shape());
|
assert_eq!(prev.shape(), fut.shape());
|
||||||
assert!(prev.shape()[1] >= 2 * Upwind4::BLOCK.len());
|
assert!(prev.shape()[1] >= 2 * Upwind4::BLOCK.len());
|
||||||
|
|
||||||
match (prev.strides(), fut.strides()) {
|
match (prev.strides(), fut.strides()) {
|
||||||
([_, 1], [_, 1]) => diff_op_row(
|
([_, 1], [_, 1]) => diff_op_row_local(prev, fut),
|
||||||
Upwind4::BLOCK,
|
|
||||||
Upwind4::DIAG,
|
|
||||||
super::Symmetry::AntiSymmetric,
|
|
||||||
super::OperatorType::Normal,
|
|
||||||
)(prev, fut),
|
|
||||||
([1, _], [1, _]) if prev.len_of(Axis(0)) % SimdT::lanes() == 0 => {
|
([1, _], [1, _]) if prev.len_of(Axis(0)) % SimdT::lanes() == 0 => {
|
||||||
diff_simd_col(prev, fut)
|
diff_simd_col(prev, fut)
|
||||||
}
|
}
|
||||||
|
@ -465,3 +495,11 @@ fn upwind4_test2() {
|
||||||
1e-1,
|
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);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue