use super::{IJKL_TO_MN, IJKL_TO_MN_SYM, MN_TO_IJKL, SQRT_2};
use crate::{AsMatrix9x9, Mandel, StrError, ONE_BY_3, TWO_BY_3};
use russell_lab::{mat_update, Matrix};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Tensor4 {
pub(crate) mat: Matrix,
pub(crate) mandel: Mandel,
}
impl Tensor4 {
pub fn new(mandel: Mandel) -> Self {
let dim = mandel.dim();
Tensor4 {
mat: Matrix::new(dim, dim),
mandel,
}
}
pub fn new_sym(two_dim: bool) -> Self {
if two_dim {
Tensor4::new(Mandel::Symmetric2D)
} else {
Tensor4::new(Mandel::Symmetric)
}
}
pub fn new_sym_ndim(space_ndim: usize) -> Self {
if space_ndim == 2 {
Tensor4::new(Mandel::Symmetric2D)
} else {
Tensor4::new(Mandel::Symmetric)
}
}
pub fn mandel(&self) -> Mandel {
self.mandel
}
pub fn dim(&self) -> usize {
self.mat.dims().0
}
pub fn matrix(&self) -> &Matrix {
&self.mat
}
pub fn matrix_mut(&mut self) -> &mut Matrix {
&mut self.mat
}
pub fn from_array(inp: &[[[[f64; 3]; 3]; 3]; 3], mandel: Mandel) -> Result<Self, StrError> {
let dim = mandel.dim();
let mut mat = Matrix::new(dim, dim);
if dim == 4 || dim == 6 {
let max = if dim == 4 { 3 } else { 6 };
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
if i > j || k > l {
if inp[i][j][k][l] != inp[j][i][k][l]
|| inp[i][j][k][l] != inp[i][j][l][k]
|| inp[i][j][k][l] != inp[j][i][l][k]
{
return Err("the input data does not correspond to a symmetric tensor");
}
} else {
let (m, n) = IJKL_TO_MN[i][j][k][l];
if m > max || n > max {
if inp[i][j][k][l] != 0.0 {
return Err("the input data does not correspond to a 2D symmetric tensor");
}
continue;
} else if m < 3 && n < 3 {
mat.set(m, n, inp[i][j][k][l]);
} else if m > 2 && n > 2 {
mat.set(m, n, 2.0 * inp[i][j][k][l]);
} else {
mat.set(m, n, SQRT_2 * inp[i][j][k][l]);
}
}
}
}
}
}
} else {
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
let (m, n) = IJKL_TO_MN[i][j][k][l];
if i == j && k == l {
mat.set(m, n, inp[i][j][k][l]);
} else if i == j && k < l {
mat.set(m, n, (inp[i][j][k][l] + inp[i][j][l][k]) / SQRT_2);
} else if i == j && k > l {
mat.set(m, n, (inp[i][j][l][k] - inp[i][j][k][l]) / SQRT_2);
} else if i < j && k == l {
mat.set(m, n, (inp[i][j][k][l] + inp[j][i][k][l]) / SQRT_2);
} else if i < j && k < l {
mat.set(
m,
n,
(inp[i][j][k][l] + inp[i][j][l][k] + inp[j][i][k][l] + inp[j][i][l][k]) / 2.0,
);
} else if i < j && k > l {
mat.set(
m,
n,
(inp[i][j][l][k] - inp[i][j][k][l] + inp[j][i][l][k] - inp[j][i][k][l]) / 2.0,
);
} else if i > j && k == l {
mat.set(m, n, (inp[j][i][k][l] - inp[i][j][k][l]) / SQRT_2);
} else if i > j && k < l {
mat.set(
m,
n,
(inp[j][i][k][l] + inp[j][i][l][k] - inp[i][j][k][l] - inp[i][j][l][k]) / 2.0,
);
} else if i > j && k > l {
mat.set(
m,
n,
(inp[j][i][l][k] - inp[j][i][k][l] - inp[i][j][l][k] + inp[i][j][k][l]) / 2.0,
);
}
}
}
}
}
}
Ok(Tensor4 { mat, mandel })
}
pub fn from_matrix(inp: &dyn AsMatrix9x9, mandel: Mandel) -> Result<Self, StrError> {
let dim = mandel.dim();
let mut mat = Matrix::new(dim, dim);
if dim == 4 || dim == 6 {
let max = if dim == 4 { 3 } else { 6 };
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
let (m, n) = IJKL_TO_MN[i][j][k][l];
let (p, q) = IJKL_TO_MN[i][j][l][k];
let (r, s) = IJKL_TO_MN[j][i][k][l];
let (u, v) = IJKL_TO_MN[j][i][l][k];
if i > j || k > l {
if inp.at(m, n) != inp.at(p, q)
|| inp.at(m, n) != inp.at(r, s)
|| inp.at(m, n) != inp.at(u, v)
{
return Err("the input data does not correspond to a symmetric tensor");
}
} else {
if m > max || n > max {
if inp.at(m, n) != 0.0 {
return Err("the input data does not correspond to a 2D symmetric tensor");
}
continue;
} else if m < 3 && n < 3 {
mat.set(m, n, inp.at(m, n));
} else if m > 2 && n > 2 {
mat.set(m, n, 2.0 * inp.at(m, n));
} else {
mat.set(m, n, SQRT_2 * inp.at(m, n));
}
}
}
}
}
}
} else {
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
let (m, n) = IJKL_TO_MN[i][j][k][l];
if i == j && k == l {
mat.set(m, n, inp.at(m, n));
} else if i == j && k < l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
mat.set(m, n, (inp.at(m, n) + inp.at(p, q)) / SQRT_2);
} else if i == j && k > l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
mat.set(m, n, (inp.at(p, q) - inp.at(m, n)) / SQRT_2);
} else if i < j && k == l {
let (r, s) = IJKL_TO_MN[j][i][k][l];
mat.set(m, n, (inp.at(m, n) + inp.at(r, s)) / SQRT_2);
} else if i < j && k < l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let (r, s) = IJKL_TO_MN[j][i][k][l];
let (u, v) = IJKL_TO_MN[j][i][l][k];
mat.set(m, n, (inp.at(m, n) + inp.at(p, q) + inp.at(r, s) + inp.at(u, v)) / 2.0);
} else if i < j && k > l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let (r, s) = IJKL_TO_MN[j][i][k][l];
let (u, v) = IJKL_TO_MN[j][i][l][k];
mat.set(m, n, (inp.at(p, q) - inp.at(m, n) + inp.at(u, v) - inp.at(r, s)) / 2.0);
} else if i > j && k == l {
let (r, s) = IJKL_TO_MN[j][i][k][l];
mat.set(m, n, (inp.at(r, s) - inp.at(m, n)) / SQRT_2);
} else if i > j && k < l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let (r, s) = IJKL_TO_MN[j][i][k][l];
let (u, v) = IJKL_TO_MN[j][i][l][k];
mat.set(m, n, (inp.at(r, s) + inp.at(u, v) - inp.at(m, n) - inp.at(p, q)) / 2.0);
} else if i > j && k > l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let (r, s) = IJKL_TO_MN[j][i][k][l];
let (u, v) = IJKL_TO_MN[j][i][l][k];
mat.set(m, n, (inp.at(u, v) - inp.at(r, s) - inp.at(p, q) + inp.at(m, n)) / 2.0);
}
}
}
}
}
}
Ok(Tensor4 { mat, mandel })
}
pub fn get(&self, i: usize, j: usize, k: usize, l: usize) -> f64 {
match self.mat.dims().0 {
4 => {
let (m, n) = IJKL_TO_MN_SYM[i][j][k][l];
if m > 3 || n > 3 {
0.0
} else if m < 3 && n < 3 {
self.mat.get(m, n)
} else if m > 2 && n > 2 {
self.mat.get(m, n) / 2.0
} else {
self.mat.get(m, n) / SQRT_2
}
}
6 => {
let (m, n) = IJKL_TO_MN_SYM[i][j][k][l];
if m < 3 && n < 3 {
self.mat.get(m, n)
} else if m > 2 && n > 2 {
self.mat.get(m, n) / 2.0
} else {
self.mat.get(m, n) / SQRT_2
}
}
_ => {
let (m, n) = IJKL_TO_MN[i][j][k][l];
let val = self.mat.get(m, n);
if i == j && k == l {
val
} else if i == j && k < l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let right = self.mat.get(p, q);
(val + right) / SQRT_2
} else if i == j && k > l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let left = self.mat.get(p, q);
(left - val) / SQRT_2
} else if i < j && k == l {
let (r, s) = IJKL_TO_MN[j][i][k][l];
let down = self.mat.get(r, s);
(val + down) / SQRT_2
} else if i < j && k < l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let (r, s) = IJKL_TO_MN[j][i][k][l];
let (u, v) = IJKL_TO_MN[j][i][l][k];
let right = self.mat.get(p, q);
let down = self.mat.get(r, s);
let diag = self.mat.get(u, v);
(val + right + down + diag) / 2.0
} else if i < j && k > l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let (r, s) = IJKL_TO_MN[j][i][k][l];
let (u, v) = IJKL_TO_MN[j][i][l][k];
let left = self.mat.get(p, q);
let diag = self.mat.get(u, v);
let down = self.mat.get(r, s);
(left - val + diag - down) / 2.0
} else if i > j && k == l {
let (r, s) = IJKL_TO_MN[j][i][k][l];
let up = self.mat.get(r, s);
(up - val) / SQRT_2
} else if i > j && k < l {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let (r, s) = IJKL_TO_MN[j][i][k][l];
let (u, v) = IJKL_TO_MN[j][i][l][k];
let up = self.mat.get(r, s);
let diag = self.mat.get(u, v);
let right = self.mat.get(p, q);
(up + diag - val - right) / 2.0
} else {
let (p, q) = IJKL_TO_MN[i][j][l][k];
let (r, s) = IJKL_TO_MN[j][i][k][l];
let (u, v) = IJKL_TO_MN[j][i][l][k];
let diag = self.mat.get(u, v);
let up = self.mat.get(r, s);
let left = self.mat.get(p, q);
(diag - up - left + val) / 2.0
}
}
}
}
pub fn update(&mut self, alpha: f64, other: &Tensor4) {
assert_eq!(other.mandel, self.mandel);
mat_update(&mut self.mat, alpha, &other.mat).unwrap();
}
pub fn as_array(&self) -> Vec<Vec<Vec<Vec<f64>>>> {
let mut dd = vec![vec![vec![vec![0.0; 3]; 3]; 3]; 3];
self.to_array(&mut dd);
dd
}
pub fn to_array(&self, dd: &mut Vec<Vec<Vec<Vec<f64>>>>) {
let dim = self.mat.dims().0;
if dim < 9 {
for m in 0..dim {
for n in 0..dim {
let (i, j, k, l) = MN_TO_IJKL[m][n];
dd[i][j][k][l] = self.get(i, j, k, l);
if i != j || k != l {
dd[j][i][k][l] = dd[i][j][k][l];
dd[i][j][l][k] = dd[i][j][k][l];
dd[j][i][l][k] = dd[i][j][k][l];
}
}
}
} else {
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
dd[i][j][k][l] = self.get(i, j, k, l);
}
}
}
}
}
}
pub fn as_matrix(&self) -> Matrix {
let mut mat = Matrix::new(9, 9);
self.to_matrix(&mut mat);
mat
}
pub fn to_matrix(&self, mat: &mut Matrix) {
assert_eq!(mat.dims(), (9, 9));
for m in 0..9 {
for n in 0..9 {
let (i, j, k, l) = MN_TO_IJKL[m][n];
mat.set(m, n, self.get(i, j, k, l));
}
}
}
pub fn sym_set(&mut self, i: usize, j: usize, k: usize, l: usize, value: f64) {
assert!(self.mandel != Mandel::General);
let (m, n) = IJKL_TO_MN_SYM[i][j][k][l];
if m < 3 && n < 3 {
self.mat.set(m, n, value);
} else if m > 2 && n > 2 {
self.mat.set(m, n, value * 2.0);
} else {
self.mat.set(m, n, value * SQRT_2);
}
}
pub fn set_tensor(&mut self, alpha: f64, other: &Tensor4) {
assert_eq!(other.mandel, self.mandel);
let dim = self.mat.dims().0;
for i in 0..dim {
for j in 0..dim {
self.mat.set(i, j, alpha * other.mat.get(i, j));
}
}
}
pub fn constant_ii() -> Self {
Tensor4 {
mat: Matrix::diagonal(&[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]),
mandel: Mandel::General,
}
}
pub fn constant_tt() -> Self {
let mut tt = Tensor4 {
mat: Matrix::new(9, 9),
mandel: Mandel::General,
};
tt.mat.set(0, 0, 1.0);
tt.mat.set(1, 1, 1.0);
tt.mat.set(2, 2, 1.0);
tt.mat.set(3, 3, 1.0);
tt.mat.set(4, 4, 1.0);
tt.mat.set(5, 5, 1.0);
tt.mat.set(6, 6, -1.0);
tt.mat.set(7, 7, -1.0);
tt.mat.set(8, 8, -1.0);
tt
}
pub fn constant_jj(reduced_6x6: bool) -> Self {
let (n, mandel) = if reduced_6x6 {
(6, Mandel::Symmetric)
} else {
(9, Mandel::General)
};
let mut jj = Tensor4 {
mat: Matrix::new(n, n),
mandel,
};
jj.mat.set(0, 0, 1.0);
jj.mat.set(0, 1, 1.0);
jj.mat.set(0, 2, 1.0);
jj.mat.set(1, 0, 1.0);
jj.mat.set(1, 1, 1.0);
jj.mat.set(1, 2, 1.0);
jj.mat.set(2, 0, 1.0);
jj.mat.set(2, 1, 1.0);
jj.mat.set(2, 2, 1.0);
jj
}
pub fn constant_pp_iso(reduced_6x6: bool) -> Self {
let (n, mandel) = if reduced_6x6 {
(6, Mandel::Symmetric)
} else {
(9, Mandel::General)
};
let mut pp_iso = Tensor4 {
mat: Matrix::new(n, n),
mandel,
};
pp_iso.mat.set(0, 0, ONE_BY_3);
pp_iso.mat.set(0, 1, ONE_BY_3);
pp_iso.mat.set(0, 2, ONE_BY_3);
pp_iso.mat.set(1, 0, ONE_BY_3);
pp_iso.mat.set(1, 1, ONE_BY_3);
pp_iso.mat.set(1, 2, ONE_BY_3);
pp_iso.mat.set(2, 0, ONE_BY_3);
pp_iso.mat.set(2, 1, ONE_BY_3);
pp_iso.mat.set(2, 2, ONE_BY_3);
pp_iso
}
pub fn constant_pp_sym(reduced_6x6: bool) -> Self {
let (n, mandel) = if reduced_6x6 {
(6, Mandel::Symmetric)
} else {
(9, Mandel::General)
};
let mut pp_sym = Tensor4 {
mat: Matrix::new(n, n),
mandel,
};
pp_sym.mat.set(0, 0, 1.0);
pp_sym.mat.set(1, 1, 1.0);
pp_sym.mat.set(2, 2, 1.0);
pp_sym.mat.set(3, 3, 1.0);
pp_sym.mat.set(4, 4, 1.0);
pp_sym.mat.set(5, 5, 1.0);
pp_sym
}
pub fn constant_pp_skew() -> Self {
let mut pp_skew = Tensor4 {
mat: Matrix::new(9, 9),
mandel: Mandel::General,
};
pp_skew.mat.set(6, 6, 1.0);
pp_skew.mat.set(7, 7, 1.0);
pp_skew.mat.set(8, 8, 1.0);
pp_skew
}
pub fn constant_pp_dev() -> Self {
let mut pp_dev = Tensor4 {
mat: Matrix::new(9, 9),
mandel: Mandel::General,
};
pp_dev.mat.set(0, 0, TWO_BY_3);
pp_dev.mat.set(0, 1, -ONE_BY_3);
pp_dev.mat.set(0, 2, -ONE_BY_3);
pp_dev.mat.set(1, 0, -ONE_BY_3);
pp_dev.mat.set(1, 1, TWO_BY_3);
pp_dev.mat.set(1, 2, -ONE_BY_3);
pp_dev.mat.set(2, 0, -ONE_BY_3);
pp_dev.mat.set(2, 1, -ONE_BY_3);
pp_dev.mat.set(2, 2, TWO_BY_3);
pp_dev.mat.set(3, 3, 1.0);
pp_dev.mat.set(4, 4, 1.0);
pp_dev.mat.set(5, 5, 1.0);
pp_dev.mat.set(6, 6, 1.0);
pp_dev.mat.set(7, 7, 1.0);
pp_dev.mat.set(8, 8, 1.0);
pp_dev
}
pub fn constant_pp_symdev(reduced_6x6: bool) -> Self {
let (n, mandel) = if reduced_6x6 {
(6, Mandel::Symmetric)
} else {
(9, Mandel::General)
};
let mut pp_symdev = Tensor4 {
mat: Matrix::new(n, n),
mandel,
};
pp_symdev.mat.set(0, 0, TWO_BY_3);
pp_symdev.mat.set(0, 1, -ONE_BY_3);
pp_symdev.mat.set(0, 2, -ONE_BY_3);
pp_symdev.mat.set(1, 0, -ONE_BY_3);
pp_symdev.mat.set(1, 1, TWO_BY_3);
pp_symdev.mat.set(1, 2, -ONE_BY_3);
pp_symdev.mat.set(2, 0, -ONE_BY_3);
pp_symdev.mat.set(2, 1, -ONE_BY_3);
pp_symdev.mat.set(2, 2, TWO_BY_3);
pp_symdev.mat.set(3, 3, 1.0);
pp_symdev.mat.set(4, 4, 1.0);
pp_symdev.mat.set(5, 5, 1.0);
pp_symdev
}
pub fn set_pp_symdev(&mut self) {
self.mat.fill(0.0);
self.mat.set(0, 0, TWO_BY_3);
self.mat.set(0, 1, -ONE_BY_3);
self.mat.set(0, 2, -ONE_BY_3);
self.mat.set(1, 0, -ONE_BY_3);
self.mat.set(1, 1, TWO_BY_3);
self.mat.set(1, 2, -ONE_BY_3);
self.mat.set(2, 0, -ONE_BY_3);
self.mat.set(2, 1, -ONE_BY_3);
self.mat.set(2, 2, TWO_BY_3);
self.mat.set(3, 3, 1.0);
if self.mandel.dim() > 4 {
self.mat.set(4, 4, 1.0);
self.mat.set(5, 5, 1.0);
}
}
}
#[cfg(test)]
mod tests {
use super::{Tensor4, MN_TO_IJKL};
use crate::{Mandel, SamplesTensor4};
use crate::{IDENTITY4, P_DEV, P_ISO, P_SKEW, P_SYM, P_SYMDEV, TRACE_PROJECTION, TRANSPOSITION};
use russell_lab::{approx_eq, mat_approx_eq, Matrix};
#[test]
fn new_and_getters_work() {
let mut dd = Tensor4::new(Mandel::General);
assert_eq!(dd.matrix().as_data().len(), 81);
assert_eq!(dd.dim(), 9);
assert_eq!(dd.mandel(), Mandel::General);
dd.matrix_mut().set(0, 0, 1.0);
let dd = Tensor4::new(Mandel::Symmetric);
assert_eq!(dd.mandel(), Mandel::Symmetric);
assert_eq!(dd.dim(), 6);
assert_eq!(dd.matrix().as_data().len(), 36);
let dd = Tensor4::new_sym(false);
assert_eq!(dd.mandel(), Mandel::Symmetric);
assert_eq!(dd.dim(), 6);
assert_eq!(dd.matrix().as_data().len(), 36);
let dd = Tensor4::new_sym_ndim(3);
assert_eq!(dd.mandel(), Mandel::Symmetric);
assert_eq!(dd.dim(), 6);
assert_eq!(dd.matrix().as_data().len(), 36);
let dd = Tensor4::new(Mandel::Symmetric2D);
assert_eq!(dd.mandel(), Mandel::Symmetric2D);
assert_eq!(dd.dim(), 4);
assert_eq!(dd.matrix().as_data().len(), 16);
let dd = Tensor4::new_sym(true);
assert_eq!(dd.mandel(), Mandel::Symmetric2D);
assert_eq!(dd.dim(), 4);
assert_eq!(dd.matrix().as_data().len(), 16);
let dd = Tensor4::new_sym_ndim(2);
assert_eq!(dd.mandel(), Mandel::Symmetric2D);
assert_eq!(dd.dim(), 4);
assert_eq!(dd.matrix().as_data().len(), 16);
}
#[test]
fn from_array_fails_captures_errors() {
let res = Tensor4::from_array(&SamplesTensor4::SAMPLE1, Mandel::Symmetric);
assert_eq!(
res.err(),
Some("the input data does not correspond to a symmetric tensor")
);
let res = Tensor4::from_array(&SamplesTensor4::SYM_SAMPLE1, Mandel::Symmetric2D);
assert_eq!(
res.err(),
Some("the input data does not correspond to a 2D symmetric tensor")
);
}
#[test]
fn from_array_works() {
let dd = Tensor4::from_array(&SamplesTensor4::SAMPLE1, Mandel::General).unwrap();
for m in 0..9 {
for n in 0..9 {
assert_eq!(dd.mat.get(m, n), SamplesTensor4::SAMPLE1_MANDEL_MATRIX[m][n]);
}
}
let dd = Tensor4::from_array(&SamplesTensor4::SYM_SAMPLE1, Mandel::Symmetric).unwrap();
for m in 0..6 {
for n in 0..6 {
assert_eq!(dd.mat.get(m, n), SamplesTensor4::SYM_SAMPLE1_MANDEL_MATRIX[m][n]);
}
}
let dd = Tensor4::from_array(&SamplesTensor4::SYM_2D_SAMPLE1, Mandel::Symmetric2D).unwrap();
for m in 0..4 {
for n in 0..4 {
assert_eq!(dd.mat.get(m, n), SamplesTensor4::SYM_2D_SAMPLE1_MANDEL_MATRIX[m][n]);
}
}
}
#[test]
fn from_matrix_fails_captures_errors() {
let mut inp = [[0.0; 9]; 9];
inp[0][3] = 1e-15;
let res = Tensor4::from_matrix(&inp, Mandel::Symmetric);
assert_eq!(
res.err(),
Some("the input data does not correspond to a symmetric tensor")
);
inp[0][3] = 0.0;
inp[0][4] = 1.0;
inp[0][7] = 1.0;
let res = Tensor4::from_matrix(&inp, Mandel::Symmetric2D);
assert_eq!(
res.err(),
Some("the input data does not correspond to a 2D symmetric tensor")
);
}
#[test]
fn from_matrix_works() {
let dd = Tensor4::from_matrix(&SamplesTensor4::SAMPLE1_STD_MATRIX, Mandel::General).unwrap();
for m in 0..9 {
for n in 0..9 {
approx_eq(dd.mat.get(m, n), SamplesTensor4::SAMPLE1_MANDEL_MATRIX[m][n], 1e-15);
}
}
let dd = Tensor4::from_matrix(&SamplesTensor4::SYM_SAMPLE1_STD_MATRIX, Mandel::Symmetric).unwrap();
for m in 0..6 {
for n in 0..6 {
approx_eq(dd.mat.get(m, n), SamplesTensor4::SYM_SAMPLE1_MANDEL_MATRIX[m][n], 1e-14);
}
}
let dd = Tensor4::from_matrix(&SamplesTensor4::SYM_2D_SAMPLE1_STD_MATRIX, Mandel::Symmetric2D).unwrap();
for m in 0..4 {
for n in 0..4 {
approx_eq(
dd.mat.get(m, n),
SamplesTensor4::SYM_2D_SAMPLE1_MANDEL_MATRIX[m][n],
1e-14,
);
}
}
}
#[test]
fn get_works() {
let dd = Tensor4::from_array(&SamplesTensor4::SAMPLE1, Mandel::General).unwrap();
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
approx_eq(dd.get(i, j, k, l), SamplesTensor4::SAMPLE1[i][j][k][l], 1e-13);
}
}
}
}
let dd = Tensor4::from_array(&SamplesTensor4::SYM_SAMPLE1, Mandel::Symmetric).unwrap();
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
approx_eq(dd.get(i, j, k, l), SamplesTensor4::SYM_SAMPLE1[i][j][k][l], 1e-14);
}
}
}
}
let dd = Tensor4::from_array(&SamplesTensor4::SYM_2D_SAMPLE1, Mandel::Symmetric2D).unwrap();
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
approx_eq(dd.get(i, j, k, l), SamplesTensor4::SYM_2D_SAMPLE1[i][j][k][l], 1e-14);
}
}
}
}
}
#[test]
#[should_panic]
fn update_panics_on_incorrect_input() {
let mut dd = Tensor4::new(Mandel::Symmetric2D);
let ee = Tensor4::new(Mandel::Symmetric);
dd.update(2.0, &ee);
}
#[test]
fn update_works() {
let mut dd = Tensor4::new(Mandel::Symmetric2D);
let ee = Tensor4::from_array(&SamplesTensor4::SYM_2D_SAMPLE1, Mandel::Symmetric2D).unwrap();
dd.update(2.0, &ee);
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
approx_eq(
dd.get(i, j, k, l),
2.0 * SamplesTensor4::SYM_2D_SAMPLE1[i][j][k][l],
1e-14,
);
}
}
}
}
}
#[test]
fn as_array_and_to_array_work() {
let dd = Tensor4::from_array(&SamplesTensor4::SAMPLE1, Mandel::General).unwrap();
let res = dd.as_array();
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
approx_eq(res[i][j][k][l], SamplesTensor4::SAMPLE1[i][j][k][l], 1e-13);
}
}
}
}
let dd = Tensor4::from_array(&SamplesTensor4::SYM_SAMPLE1, Mandel::Symmetric).unwrap();
let res = dd.as_array();
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
approx_eq(res[i][j][k][l], SamplesTensor4::SYM_SAMPLE1[i][j][k][l], 1e-14);
}
}
}
}
let dd = Tensor4::from_array(&SamplesTensor4::SYM_2D_SAMPLE1, Mandel::Symmetric2D).unwrap();
let res = dd.as_array();
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
for l in 0..3 {
approx_eq(res[i][j][k][l], SamplesTensor4::SYM_2D_SAMPLE1[i][j][k][l], 1e-14);
}
}
}
}
}
#[test]
fn as_matrix_and_to_matrix_work() {
let dd = Tensor4::from_array(&SamplesTensor4::SAMPLE1, Mandel::General).unwrap();
let mat = dd.as_matrix();
for m in 0..9 {
for n in 0..9 {
approx_eq(mat.get(m, n), SamplesTensor4::SAMPLE1_STD_MATRIX[m][n], 1e-13);
}
}
let dd = Tensor4::from_array(&SamplesTensor4::SYM_SAMPLE1, Mandel::Symmetric).unwrap();
let mat = dd.as_matrix();
assert_eq!(mat.dims(), (9, 9));
for m in 0..9 {
for n in 0..9 {
approx_eq(mat.get(m, n), SamplesTensor4::SYM_SAMPLE1_STD_MATRIX[m][n], 1e-13);
}
}
let dd = Tensor4::from_array(&SamplesTensor4::SYM_2D_SAMPLE1, Mandel::Symmetric2D).unwrap();
let mat = dd.as_matrix();
assert_eq!(mat.dims(), (9, 9));
for m in 0..9 {
for n in 0..9 {
approx_eq(mat.get(m, n), SamplesTensor4::SYM_2D_SAMPLE1_STD_MATRIX[m][n], 1e-13);
}
}
}
#[test]
fn from_array_to_matrix_from_matrix_work() {
let data = &[
[
[[18.0, 16.0, 14.0], [12.0, 10.0, 8.0], [6.0, 4.0, 2.0]],
[[36.0, 32.0, 28.0], [24.0, 20.0, 16.0], [12.0, 8.0, 4.0]],
[[54.0, 48.0, 42.0], [36.0, 30.0, 24.0], [18.0, 12.0, 6.0]],
],
[
[[72.0, 64.0, 56.0], [48.0, 40.0, 32.0], [24.0, 16.0, 8.0]],
[[90.0, 80.0, 70.0], [60.0, 50.0, 40.0], [30.0, 20.0, 10.0]],
[[108.0, 96.0, 84.0], [72.0, 60.0, 48.0], [36.0, 24.0, 12.0]],
],
[
[[126.0, 112.0, 98.0], [84.0, 70.0, 56.0], [42.0, 28.0, 14.0]],
[[144.0, 128.0, 112.0], [96.0, 80.0, 64.0], [48.0, 32.0, 16.0]],
[[162.0, 144.0, 126.0], [108.0, 90.0, 72.0], [54.0, 36.0, 18.0]],
],
];
let dd = Tensor4::from_array(data, Mandel::General).unwrap();
let m1 = dd.as_matrix();
let correct = &[
[18.0, 10.0, 2.0, 16.0, 8.0, 14.0, 12.0, 4.0, 6.0],
[90.0, 50.0, 10.0, 80.0, 40.0, 70.0, 60.0, 20.0, 30.0],
[162.0, 90.0, 18.0, 144.0, 72.0, 126.0, 108.0, 36.0, 54.0],
[36.0, 20.0, 4.0, 32.0, 16.0, 28.0, 24.0, 8.0, 12.0],
[108.0, 60.0, 12.0, 96.0, 48.0, 84.0, 72.0, 24.0, 36.0],
[54.0, 30.0, 6.0, 48.0, 24.0, 42.0, 36.0, 12.0, 18.0],
[72.0, 40.0, 8.0, 64.0, 32.0, 56.0, 48.0, 16.0, 24.0],
[144.0, 80.0, 16.0, 128.0, 64.0, 112.0, 96.0, 32.0, 48.0],
[126.0, 70.0, 14.0, 112.0, 56.0, 98.0, 84.0, 28.0, 42.0],
];
mat_approx_eq(&m1, correct, 1e-13);
let ee = Tensor4::from_matrix(correct, Mandel::General).unwrap();
let m2 = ee.as_matrix();
mat_approx_eq(&m2, correct, 1e-13);
let data = &[
[
[[6.0, 10.0, 12.0], [10.0, 4.0, 8.0], [12.0, 8.0, 2.0]],
[[24.0, 40.0, 48.0], [40.0, 16.0, 32.0], [48.0, 32.0, 8.0]],
[[36.0, 60.0, 72.0], [60.0, 24.0, 48.0], [72.0, 48.0, 12.0]],
],
[
[[24.0, 40.0, 48.0], [40.0, 16.0, 32.0], [48.0, 32.0, 8.0]],
[[12.0, 20.0, 24.0], [20.0, 8.0, 16.0], [24.0, 16.0, 4.0]],
[[30.0, 50.0, 60.0], [50.0, 20.0, 40.0], [60.0, 40.0, 10.0]],
],
[
[[36.0, 60.0, 72.0], [60.0, 24.0, 48.0], [72.0, 48.0, 12.0]],
[[30.0, 50.0, 60.0], [50.0, 20.0, 40.0], [60.0, 40.0, 10.0]],
[[18.0, 30.0, 36.0], [30.0, 12.0, 24.0], [36.0, 24.0, 6.0]],
],
];
let dd = Tensor4::from_array(data, Mandel::Symmetric).unwrap();
let m1 = dd.as_matrix();
let correct = &[
[6.0, 4.0, 2.0, 10.0, 8.0, 12.0, 10.0, 8.0, 12.0],
[12.0, 8.0, 4.0, 20.0, 16.0, 24.0, 20.0, 16.0, 24.0],
[18.0, 12.0, 6.0, 30.0, 24.0, 36.0, 30.0, 24.0, 36.0],
[24.0, 16.0, 8.0, 40.0, 32.0, 48.0, 40.0, 32.0, 48.0],
[30.0, 20.0, 10.0, 50.0, 40.0, 60.0, 50.0, 40.0, 60.0],
[36.0, 24.0, 12.0, 60.0, 48.0, 72.0, 60.0, 48.0, 72.0],
[24.0, 16.0, 8.0, 40.0, 32.0, 48.0, 40.0, 32.0, 48.0],
[30.0, 20.0, 10.0, 50.0, 40.0, 60.0, 50.0, 40.0, 60.0],
[36.0, 24.0, 12.0, 60.0, 48.0, 72.0, 60.0, 48.0, 72.0],
];
mat_approx_eq(&m1, correct, 1e-13);
let ee = Tensor4::from_matrix(correct, Mandel::Symmetric).unwrap();
let m2 = ee.as_matrix();
mat_approx_eq(&m2, correct, 1e-13);
let data = &[
[
[[6.0, 8.0, 0.0], [8.0, 4.0, 0.0], [0.0, 0.0, 2.0]],
[[24.0, 32.0, 0.0], [32.0, 16.0, 0.0], [0.0, 0.0, 8.0]],
[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
],
[
[[24.0, 32.0, 0.0], [32.0, 16.0, 0.0], [0.0, 0.0, 8.0]],
[[12.0, 16.0, 0.0], [16.0, 8.0, 0.0], [0.0, 0.0, 4.0]],
[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
],
[
[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
[[18.0, 24.0, 0.0], [24.0, 12.0, 0.0], [0.0, 0.0, 6.0]],
],
];
let dd = Tensor4::from_array(data, Mandel::Symmetric2D).unwrap();
let m1 = dd.as_matrix();
let correct = &[
[6.0, 4.0, 2.0, 8.0, 0.0, 0.0, 8.0, 0.0, 0.0],
[12.0, 8.0, 4.0, 16.0, 0.0, 0.0, 16.0, 0.0, 0.0],
[18.0, 12.0, 6.0, 24.0, 0.0, 0.0, 24.0, 0.0, 0.0],
[24.0, 16.0, 8.0, 32.0, 0.0, 0.0, 32.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[24.0, 16.0, 8.0, 32.0, 0.0, 0.0, 32.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
];
mat_approx_eq(&m1, correct, 1e-13);
let ee = Tensor4::from_matrix(correct, Mandel::Symmetric2D).unwrap();
let m2 = ee.as_matrix();
mat_approx_eq(&m2, correct, 1e-13);
}
fn generate_dd() -> Tensor4 {
let mut dd = Tensor4::new(Mandel::Symmetric);
for m in 0..6 {
for n in 0..6 {
let (i, j, k, l) = MN_TO_IJKL[m][n];
let value = (1000 * (i + 1) + 100 * (j + 1) + 10 * (k + 1) + (l + 1)) as f64;
dd.sym_set(i, j, k, l, value);
}
}
dd
}
#[test]
#[should_panic(expected = "self.mandel != Mandel::General")]
fn sym_set_panics_on_non_sym() {
let mut dd = Tensor4::new(Mandel::General);
dd.sym_set(0, 0, 0, 0, 1.0);
}
#[test]
#[should_panic(expected = "the len is 3 but the index is 3")]
fn sym_set_panics_on_incorrect_indices() {
let mut dd = Tensor4::new(Mandel::Symmetric2D);
dd.sym_set(0, 0, 0, 3, 5.0);
}
#[test]
fn sym_set_works() {
let dd = generate_dd();
assert_eq!(
format!("{:.0}", dd.as_matrix()),
"┌ ┐\n\
│ 1111 1122 1133 1112 1123 1113 1112 1123 1113 │\n\
│ 2211 2222 2233 2212 2223 2213 2212 2223 2213 │\n\
│ 3311 3322 3333 3312 3323 3313 3312 3323 3313 │\n\
│ 1211 1222 1233 1212 1223 1213 1212 1223 1213 │\n\
│ 2311 2322 2333 2312 2323 2313 2312 2323 2313 │\n\
│ 1311 1322 1333 1312 1323 1313 1312 1323 1313 │\n\
│ 1211 1222 1233 1212 1223 1213 1212 1223 1213 │\n\
│ 2311 2322 2333 2312 2323 2313 2312 2323 2313 │\n\
│ 1311 1322 1333 1312 1323 1313 1312 1323 1313 │\n\
└ ┘"
);
}
#[test]
#[should_panic]
fn set_tensor_panics_on_incorrect_input() {
let dd = Tensor4::new(Mandel::Symmetric);
let mut ee = Tensor4::new(Mandel::General);
ee.set_tensor(2.0, &dd);
}
#[test]
fn set_tensor_works() {
#[rustfmt::skip]
let dd = Tensor4::from_matrix(&[
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
[5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0],
[9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0],
[2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0],
[6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0],
[3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0],
[2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0],
[6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0],
[3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0],
], Mandel::General).unwrap();
let mut ee = Tensor4::new(Mandel::General);
ee.set_tensor(2.0, &dd);
#[rustfmt::skip]
let correct = Matrix::from(&[
[ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0],
[10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0],
[18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0],
[ 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0],
[12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0],
[ 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0],
[ 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0],
[12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0],
[ 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0],
]);
mat_approx_eq(&ee.as_matrix(), &correct, 1e-14);
}
#[test]
fn clone_and_serialize_work() {
let dd = generate_dd();
let mut cloned = dd.clone();
cloned.mat.set(0, 0, 9999.0);
assert_eq!(
format!("{:.0}", dd.as_matrix()),
"┌ ┐\n\
│ 1111 1122 1133 1112 1123 1113 1112 1123 1113 │\n\
│ 2211 2222 2233 2212 2223 2213 2212 2223 2213 │\n\
│ 3311 3322 3333 3312 3323 3313 3312 3323 3313 │\n\
│ 1211 1222 1233 1212 1223 1213 1212 1223 1213 │\n\
│ 2311 2322 2333 2312 2323 2313 2312 2323 2313 │\n\
│ 1311 1322 1333 1312 1323 1313 1312 1323 1313 │\n\
│ 1211 1222 1233 1212 1223 1213 1212 1223 1213 │\n\
│ 2311 2322 2333 2312 2323 2313 2312 2323 2313 │\n\
│ 1311 1322 1333 1312 1323 1313 1312 1323 1313 │\n\
└ ┘"
);
assert_eq!(
format!("{:.0}", cloned.as_matrix()),
"┌ ┐\n\
│ 9999 1122 1133 1112 1123 1113 1112 1123 1113 │\n\
│ 2211 2222 2233 2212 2223 2213 2212 2223 2213 │\n\
│ 3311 3322 3333 3312 3323 3313 3312 3323 3313 │\n\
│ 1211 1222 1233 1212 1223 1213 1212 1223 1213 │\n\
│ 2311 2322 2333 2312 2323 2313 2312 2323 2313 │\n\
│ 1311 1322 1333 1312 1323 1313 1312 1323 1313 │\n\
│ 1211 1222 1233 1212 1223 1213 1212 1223 1213 │\n\
│ 2311 2322 2333 2312 2323 2313 2312 2323 2313 │\n\
│ 1311 1322 1333 1312 1323 1313 1312 1323 1313 │\n\
└ ┘"
);
let json = serde_json::to_string(&dd).unwrap();
assert!(json.len() > 0);
let from_json: Tensor4 = serde_json::from_str(&json).unwrap();
assert_eq!(
format!("{:.0}", from_json.as_matrix()),
"┌ ┐\n\
│ 1111 1122 1133 1112 1123 1113 1112 1123 1113 │\n\
│ 2211 2222 2233 2212 2223 2213 2212 2223 2213 │\n\
│ 3311 3322 3333 3312 3323 3313 3312 3323 3313 │\n\
│ 1211 1222 1233 1212 1223 1213 1212 1223 1213 │\n\
│ 2311 2322 2333 2312 2323 2313 2312 2323 2313 │\n\
│ 1311 1322 1333 1312 1323 1313 1312 1323 1313 │\n\
│ 1211 1222 1233 1212 1223 1213 1212 1223 1213 │\n\
│ 2311 2322 2333 2312 2323 2313 2312 2323 2313 │\n\
│ 1311 1322 1333 1312 1323 1313 1312 1323 1313 │\n\
└ ┘"
);
}
#[test]
fn debug_works() {
let dd = Tensor4::new(Mandel::General);
assert!(format!("{:?}", dd).len() > 0);
}
#[test]
fn constant_ii_works() {
let ii = Tensor4::constant_ii();
assert_eq!(ii.mat.dims(), (9, 9));
assert_eq!(ii.mandel, Mandel::General);
for i in 0..9 {
for j in 0..9 {
assert_eq!(ii.mat.get(i, j), IDENTITY4[i][j]);
}
}
}
#[test]
fn constant_tt_works() {
let tt = Tensor4::constant_tt();
assert_eq!(tt.mat.dims(), (9, 9));
assert_eq!(tt.mandel, Mandel::General);
for i in 0..9 {
for j in 0..9 {
assert_eq!(tt.mat.get(i, j), TRANSPOSITION[i][j]);
}
}
}
#[test]
fn constant_jj_works() {
let jj = Tensor4::constant_jj(false);
assert_eq!(jj.mat.dims(), (9, 9));
assert_eq!(jj.mandel, Mandel::General);
for i in 0..9 {
for j in 0..9 {
assert_eq!(jj.mat.get(i, j), TRACE_PROJECTION[i][j]);
}
}
let jj = Tensor4::constant_jj(true);
for i in 0..6 {
for j in 0..6 {
assert_eq!(jj.mat.get(i, j), TRACE_PROJECTION[i][j]);
}
}
}
#[test]
fn constant_pp_iso_works() {
let pp_iso = Tensor4::constant_pp_iso(false);
assert_eq!(pp_iso.mat.dims(), (9, 9));
assert_eq!(pp_iso.mandel, Mandel::General);
for i in 0..9 {
for j in 0..9 {
assert_eq!(pp_iso.mat.get(i, j), P_ISO[i][j]);
}
}
let pp_iso = Tensor4::constant_pp_iso(true);
assert_eq!(pp_iso.mat.dims(), (6, 6));
assert_eq!(pp_iso.mandel, Mandel::Symmetric);
for i in 0..6 {
for j in 0..6 {
assert_eq!(pp_iso.mat.get(i, j), P_ISO[i][j]);
}
}
}
#[test]
fn constant_pp_sym_works() {
let pp_sym = Tensor4::constant_pp_sym(false);
assert_eq!(pp_sym.mat.dims(), (9, 9));
assert_eq!(pp_sym.mandel, Mandel::General);
for i in 0..9 {
for j in 0..9 {
assert_eq!(pp_sym.mat.get(i, j), P_SYM[i][j]);
}
}
let pp_sym = Tensor4::constant_pp_sym(true);
assert_eq!(pp_sym.mat.dims(), (6, 6));
assert_eq!(pp_sym.mandel, Mandel::Symmetric);
for i in 0..6 {
for j in 0..6 {
assert_eq!(pp_sym.mat.get(i, j), P_SYM[i][j]);
}
}
}
#[test]
fn constant_pp_skew_works() {
let pp_skew = Tensor4::constant_pp_skew();
assert_eq!(pp_skew.mat.dims(), (9, 9));
assert_eq!(pp_skew.mandel, Mandel::General);
for i in 0..9 {
for j in 0..9 {
assert_eq!(pp_skew.mat.get(i, j), P_SKEW[i][j]);
}
}
}
#[test]
fn constant_pp_dev_works() {
let pp_dev = Tensor4::constant_pp_dev();
assert_eq!(pp_dev.mat.dims(), (9, 9));
assert_eq!(pp_dev.mandel, Mandel::General);
for i in 0..9 {
for j in 0..9 {
assert_eq!(pp_dev.mat.get(i, j), P_DEV[i][j]);
}
}
}
#[test]
fn constant_pp_symdev_works() {
let pp_symdev = Tensor4::constant_pp_symdev(false);
assert_eq!(pp_symdev.mat.dims(), (9, 9));
assert_eq!(pp_symdev.mandel, Mandel::General);
for i in 0..9 {
for j in 0..9 {
assert_eq!(pp_symdev.mat.get(i, j), P_SYMDEV[i][j]);
}
}
let pp_symdev = Tensor4::constant_pp_symdev(true);
assert_eq!(pp_symdev.mat.dims(), (6, 6));
assert_eq!(pp_symdev.mandel, Mandel::Symmetric);
for i in 0..6 {
for j in 0..6 {
assert_eq!(pp_symdev.mat.get(i, j), P_SYMDEV[i][j]);
}
}
}
#[test]
fn set_pp_symdev_works() {
let mut pp_symdev = Tensor4::new(Mandel::General);
pp_symdev.set_pp_symdev();
assert_eq!(pp_symdev.mat.dims(), (9, 9));
assert_eq!(pp_symdev.mandel, Mandel::General);
for i in 0..9 {
for j in 0..9 {
assert_eq!(pp_symdev.mat.get(i, j), P_SYMDEV[i][j]);
}
}
let mut pp_symdev = Tensor4::new(Mandel::Symmetric);
pp_symdev.set_pp_symdev();
assert_eq!(pp_symdev.mat.dims(), (6, 6));
assert_eq!(pp_symdev.mandel, Mandel::Symmetric);
for i in 0..6 {
for j in 0..6 {
assert_eq!(pp_symdev.mat.get(i, j), P_SYMDEV[i][j]);
}
}
let mut pp_symdev = Tensor4::new(Mandel::Symmetric2D);
pp_symdev.set_pp_symdev();
assert_eq!(pp_symdev.mat.dims(), (4, 4));
assert_eq!(pp_symdev.mandel, Mandel::Symmetric2D);
for i in 0..4 {
for j in 0..4 {
assert_eq!(pp_symdev.mat.get(i, j), P_SYMDEV[i][j]);
}
}
}
}