use ndarray::ArrayView2;
pub type Real = f64;
pub fn du2dx(u_view: ArrayView2<Real>, delx: Real, gamma: Real) -> Real {
let u_i_m1 = u_view[(0, 1)]; let u_i = u_view[(1, 1)]; let u_i_p1 = u_view[(2, 1)];
let inner_left1 = (u_i + u_i_p1).powi(2);
let inner_right1 = (u_i_m1 + u_i).powi(2);
let left_side = inner_left1 - inner_right1;
let inner_left2 = (u_i + u_i_p1).abs() * (u_i - u_i_p1);
let inner_right2 = (u_i_m1 + u_i).abs() * (u_i_m1 - u_i);
(left_side + (gamma * (inner_left2 - inner_right2))) / (4.0 * delx)
}
pub fn duvdx(
u_view: ArrayView2<Real>,
v_view: ArrayView2<Real>,
delx: Real,
gamma: Real,
) -> Real {
let u_i_j = u_view[(1, 1)]; let u_i_j_p1 = u_view[(1, 2)]; let u_i_m1_j = u_view[(0, 1)]; let u_i_m1_j_p1 = u_view[(0, 2)];
let v_i_j = v_view[(1, 1)]; let v_i_p1_j = v_view[(2, 1)]; let v_i_m1_j = v_view[(0, 1)];
let inner_left1 = (u_i_j + u_i_j_p1) * (v_i_j + v_i_p1_j);
let inner_right1 = (u_i_m1_j + u_i_m1_j_p1) * (v_i_m1_j + v_i_j);
let left_side = inner_left1 - inner_right1;
let inner_left2 = (u_i_j + u_i_j_p1).abs() * (v_i_j - v_i_p1_j);
let inner_right2 = (u_i_m1_j + u_i_m1_j_p1).abs() * (v_i_m1_j - v_i_j);
(left_side + (gamma * (inner_left2 - inner_right2))) / (4.0 * delx)
}
pub fn duvdy(
u_view: ArrayView2<Real>,
v_view: ArrayView2<Real>,
dely: Real,
gamma: Real,
) -> Real {
let u_i_j = u_view[(1, 1)]; let u_i_j_m1 = u_view[(1, 0)]; let u_i_j_p1 = u_view[(1, 2)];
let v_i_j = v_view[(1, 1)]; let v_i_j_m1 = v_view[(1, 0)]; let v_i_p1_j = v_view[(2, 1)]; let v_i_p1_j_m1 = v_view[(2, 0)];
let inner_left1 = (v_i_j + v_i_p1_j) * (u_i_j + u_i_j_p1);
let inner_right1 = (v_i_j_m1 + v_i_p1_j_m1) * (u_i_j_m1 + u_i_j);
let left_side = inner_left1 - inner_right1;
let inner_left2 = (v_i_j + v_i_p1_j).abs() * (u_i_j - u_i_j_p1);
let inner_right2 = (v_i_j_m1 + v_i_p1_j_m1).abs() * (u_i_j_m1 - u_i_j);
(left_side + (gamma * (inner_left2 - inner_right2))) / (4.0 * dely)
}
pub fn dv2dy(v_view: ArrayView2<Real>, dely: Real, gamma: Real) -> Real {
let v_i_j = v_view[(1, 1)]; let v_i_j_p1 = v_view[(1, 2)]; let v_i_j_m1 = v_view[(1, 0)];
let inner_left1 = (v_i_j + v_i_j_p1).powi(2);
let inner_right1 = (v_i_j_m1 + v_i_j).powi(2);
let left_side = inner_left1 - inner_right1;
let inner_left2 = (v_i_j + v_i_j_p1).abs() * (v_i_j - v_i_j_p1);
let inner_right2 = (v_i_j_m1 + v_i_j).abs() * (v_i_j_m1 - v_i_j);
(left_side + (gamma * (inner_left2 - inner_right2))) / (4.0 * dely)
}
pub fn laplacian(view: ArrayView2<Real>, delx: Real, dely: Real) -> Real {
let e_i_j = view[(1, 1)]; let e_i_j_m1 = view[(1, 0)]; let e_i_j_p1 = view[(1, 2)]; let e_i_m1_j = view[(0, 1)]; let e_i_p1_j = view[(2, 1)];
let d2edx2 = (e_i_p1_j - (2. * e_i_j) + e_i_m1_j) / delx.powi(2);
let d2edy2 = (e_i_j_p1 - (2. * e_i_j) + e_i_j_m1) / dely.powi(2);
d2edx2 + d2edy2
}
pub fn residual(p_view: ArrayView2<Real>, delx: Real, dely: Real, rhs: Real) -> Real {
let p_i_p1_j = p_view[(2, 1)];
let p_i_j = p_view[(1, 1)];
let p_i_m1_j = p_view[(0, 1)];
let p_i_j_p1 = p_view[(1, 2)];
let p_i_j_m1 = p_view[(1, 0)];
let part1 = ((p_i_p1_j - p_i_j) - (p_i_j - p_i_m1_j)) / delx.powi(2);
let part2 = ((p_i_j_p1 - p_i_j) - (p_i_j - p_i_j_m1)) / dely.powi(2);
part1 + part2 - rhs
}
#[cfg(test)]
mod tests {
use super::*;
use ndarray::{array, ArrayView2};
#[test]
fn test_du2dx() {
let test_cases = [
(
array![[0., 1., 0.], [0., 2., 0.], [0., 3., 0.]],
1.,
1.7,
3.15,
),
(
array![[0., -1., 0.], [0., 2., 0.], [0., 3., 0.]],
1.,
1.7,
5.15,
),
(
array![[0., 1., 0.], [0., 1., 0.], [0., 1., 0.]],
1.,
1.7,
0.,
),
(
array![[0., 1., 0.], [0., 2., 0.], [0., 3., 0.]],
1.,
1.3,
3.35,
),
(
array![[0., 1., 0.], [0., 2., 0.], [0., 3., 0.]],
1.5,
1.7,
2.1,
),
(
array![[0., 10., 0.], [0., 20., 0.], [0., 30., 0.]],
1.5,
1.7,
210.,
),
];
for (u, delx, gamma, expected) in test_cases {
assert_eq!(du2dx(ArrayView2::from(&u), delx, gamma), expected);
}
}
#[test]
fn test_duvdx() {
let test_cases = [
(
array![[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]],
array![[8., 9., 10.], [11., 12., 13.], [14., 15., 16.]],
1.,
1.7,
40.35,
),
(
array![[1., 2., 3.], [4., 5., -6.], [-7., 8., 9.]],
array![[8., 9., 10.], [11., -12., 13.], [14., 15., -16.]],
1.,
1.7,
-53.1,
),
(
array![[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]],
array![[8., 9., 10.], [11., 12., 13.], [14., 15., 16.]],
1.6,
1.7,
25.218750,
),
(
array![[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]],
array![[8., 9., 10.], [11., 12., 13.], [14., 15., 16.]],
1.,
1.5,
41.25,
),
];
for (u, v, delx, gamma, expected) in test_cases {
assert_eq!(
duvdx(ArrayView2::from(&u), ArrayView2::from(&v), delx, gamma),
expected
);
}
}
#[test]
fn test_duvdy() {
let test_cases = [
(
array![[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]],
array![[8., 9., 10.], [11., 12., 13.], [14., 15., 16.]],
1.,
1.7,
17.15,
),
(
array![[1., 2., 3.], [4., 5., -6.], [-7., 8., 9.]],
array![[8., 9., 10.], [11., -12., 13.], [14., 15., -16.]],
1.,
1.7,
-32.35,
),
(
array![[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]],
array![[8., 9., 10.], [11., 12., 13.], [14., 15., 16.]],
1.6,
1.7,
10.718749999999998,
),
(
array![[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]],
array![[8., 9., 10.], [11., 12., 13.], [14., 15., 16.]],
1.,
1.5,
17.25,
),
];
for (u, v, dely, gamma, expected) in test_cases {
assert_eq!(
duvdy(ArrayView2::from(&u), ArrayView2::from(&v), dely, gamma),
expected
);
}
}
#[test]
fn test_dv2dy() {
let test_cases = [
(
array![[0., 0., 0.], [1., 2., 3.], [0., 0., 0.]],
1.,
1.7,
3.15,
),
(
array![[0., 0., 0.], [-1., 2., 3.], [0., 0., 0.]],
1.,
1.7,
5.15,
),
(
array![[0., 0., 0.], [1., 1., 1.], [0., 0., 0.]],
1.,
1.7,
0.,
),
(
array![[0., 0., 0.], [1., 2., 3.], [0., 0., 0.]],
1.,
1.3,
3.35,
),
(
array![[0., 0., 0.], [1., 2., 3.], [0., 0., 0.]],
1.5,
1.7,
2.1,
),
(
array![[0., 0., 0.], [10., 20., 30.], [0., 0., 0.]],
1.5,
1.7,
210.,
),
];
for (v, dely, gamma, expected) in test_cases {
assert_eq!(dv2dy(ArrayView2::from(&v), dely, gamma), expected);
}
}
#[test]
fn test_lapacian() {
let test_cases = [
(
array![[1., 4., 1.], [1., 5., 3.], [2., 1., 1.]],
1.,
1.,
-11.,
),
(
array![[-1., -1., -1.], [-1., -5., -1.], [-1., -1., -1.]],
1.,
1.,
16.,
),
(
array![[1., 4., 1.], [1., 5., 3.], [2., 1., 1.]],
1.6,
1.3,
-5.503420857988164,
),
(
array![[1., 4., 1.], [1., 5., 3.], [2., 1., 1.]],
1.3,
0.7,
-15.20347784084048,
),
];
for (e, delx, dely, expected) in test_cases {
assert_eq!(laplacian(ArrayView2::from(&e), delx, dely), expected);
}
}
}