21#ifndef __B2_TENSOR_CALCULUS_H__ 
   22#define __B2_TENSOR_CALCULUS_H__ 
   60    return mat_a[0][0] * (mat_a[1][1] * mat_a[2][2] - mat_a[1][2] * mat_a[2][1])
 
   61           + mat_a[1][0] * (mat_a[0][2] * mat_a[2][1] - mat_a[0][1] * mat_a[2][2])
 
   62           + mat_a[2][0] * (mat_a[0][1] * mat_a[1][2] - mat_a[0][2] * mat_a[1][1]);
 
 
   72    return mat_a[0][0] * mat_a[1][1] - mat_a[0][1] * mat_a[1][0];
 
 
   87      const std::array<std::array<T, 3>, 3>& mat_a, std::array<std::array<T, 3>, 3>& mat_b) {
 
   89    if (determinant == T(0)) {
 
   90        mat_b.fill({T(0), T(0), T(0)});
 
   93    const T inv_det = T(1) / determinant;
 
   94    mat_b[0][0] = (mat_a[1][1] * mat_a[2][2] - mat_a[1][2] * mat_a[2][1]) * inv_det;
 
   95    mat_b[0][1] = (mat_a[0][2] * mat_a[2][1] - mat_a[0][1] * mat_a[2][2]) * inv_det;
 
   96    mat_b[0][2] = (mat_a[0][1] * mat_a[1][2] - mat_a[0][2] * mat_a[1][1]) * inv_det;
 
   97    mat_b[1][0] = (mat_a[1][2] * mat_a[2][0] - mat_a[1][0] * mat_a[2][2]) * inv_det;
 
   98    mat_b[1][1] = (mat_a[0][0] * mat_a[2][2] - mat_a[0][2] * mat_a[2][0]) * inv_det;
 
   99    mat_b[1][2] = (mat_a[0][2] * mat_a[1][0] - mat_a[0][0] * mat_a[1][2]) * inv_det;
 
  100    mat_b[2][0] = (mat_a[1][0] * mat_a[2][1] - mat_a[1][1] * mat_a[2][0]) * inv_det;
 
  101    mat_b[2][1] = (mat_a[0][1] * mat_a[2][0] - mat_a[0][0] * mat_a[2][1]) * inv_det;
 
  102    mat_b[2][2] = (mat_a[0][0] * mat_a[1][1] - mat_a[0][1] * mat_a[1][0]) * inv_det;
 
 
  118      const std::array<std::array<T, 2>, 2>& mat_a, std::array<std::array<T, 2>, 2>& mat_b) {
 
  120    if (determinant == T(0)) {
 
  121        mat_b.fill({T(0), T(0)});
 
  124    const T inv_det = T(1) / determinant;
 
  125    mat_b[0][0] = +mat_a[1][1] * inv_det;
 
  126    mat_b[0][1] = -mat_a[0][1] * inv_det;
 
  127    mat_b[1][0] = -mat_a[1][0] * inv_det;
 
  128    mat_b[1][1] = +mat_a[0][0] * inv_det;
 
 
  142inline std::array<T, 2> 
eigenvalues_2(
const std::array<std::array<T, 2>, 2>& matrix) {
 
  143    const T trace = matrix[0][0] + matrix[1][1];
 
  144    const T determinant = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
 
  145    const T discriminant = trace * trace / 4 - determinant;
 
  148    std::array<T, 2> eigenvalues;
 
  153    if constexpr (std::is_floating_point<T>::value) {
 
  154        if (discriminant >= 0) {
 
  155            s = std::sqrt(discriminant);
 
  156        } 
else if (std::fabs(discriminant) <= 4096 * std::numeric_limits<T>::epsilon()) {
 
  162        s = std::sqrt(discriminant);
 
  165    eigenvalues[0] = trace / 2 + s;
 
  166    eigenvalues[1] = trace / 2 - s;
 
 
  182      const std::array<std::array<T, 2>, 2>& matrix, std::array<T, 2>& eigenvalues,
 
  183      std::array<std::array<T, 2>, 2>& eigenvector) {
 
  186    if (std::abs(matrix[0][1]) > std::numeric_limits<T>::epsilon()) {
 
  187        eigenvector[0][0] = eigenvalues[0] - matrix[1][1];
 
  188        eigenvector[1][0] = eigenvalues[1] - matrix[1][1];
 
  189        eigenvector[0][1] = eigenvector[1][1] = matrix[0][1];
 
  190    } 
else if (std::abs(matrix[1][0]) > std::numeric_limits<T>::epsilon()) {
 
  191        eigenvector[0][0] = eigenvector[1][0] = matrix[1][0];
 
  192        eigenvector[0][1] = eigenvalues[0] - matrix[0][0];
 
  193        eigenvector[1][1] = eigenvalues[1] - matrix[0][0];
 
  195        eigenvector[0][0] = eigenvector[1][1] = 1;
 
  196        eigenvector[1][0] = eigenvector[0][1] = 0;
 
 
  201template <
typename T1>
 
  203    std::fill_n(a, 3, T1(0));
 
 
  207template <
typename T1>
 
  209    std::fill_n(a, 2, T1(0));
 
 
  213template <
typename T1>
 
  214inline void copy_3(
const T1 a[3], T1 b[3]) {
 
  215    std::copy(a, a + 3, b);
 
 
  219template <
typename T1, 
typename T2>
 
  220inline void copy_3(
const T1 a[3], T2 b[3]) {
 
  221    for (
int i = 0; i != 3; ++i) { b[i] = a[i]; }
 
 
  225template <
typename T1>
 
  226inline void copy_2(
const T1 a[2], T1 b[2]) {
 
  227    std::copy(a, a + 2, b);
 
 
  231template <
typename T1, 
typename T2>
 
  232inline void copy_2(
const T1 a[2], T2 b[2]) {
 
  233    for (
int i = 0; i != 2; ++i) { b[i] = a[i]; }
 
 
  238template <
typename T1, 
typename T2, 
typename T3>
 
  239inline void sub_3(
const T1 v1[3], 
const T2 v2[3], T3 dest[3]) {
 
  240    dest[0] = v1[0] - v2[0];
 
  241    dest[1] = v1[1] - v2[1];
 
  242    dest[2] = v1[2] - v2[2];
 
 
  247template <
typename T1, 
typename T2, 
typename T3>
 
  248inline void sub_2(
const T1 v1[2], 
const T2 v2[2], T3 dest[2]) {
 
  249    dest[0] = v1[0] - v2[0];
 
  250    dest[1] = v1[1] - v2[1];
 
 
  255template <
typename T1, 
typename T2, 
typename T3>
 
  256inline void add_3(
const T1 v1[3], 
const T2 v2[3], T3 dest[3]) {
 
  257    dest[0] = v1[0] + v2[0];
 
  258    dest[1] = v1[1] + v2[1];
 
  259    dest[2] = v1[2] + v2[2];
 
 
  264template <
typename T1, 
typename T2, 
typename T3>
 
  265inline void add_2(
const T1 v1[2], 
const T2 v2[2], T3 dest[2]) {
 
  266    dest[0] = v1[0] + v2[0];
 
  267    dest[1] = v1[1] + v2[1];
 
 
  272template <
typename T1, 
typename T2, 
typename T3, 
typename T4, 
typename T5>
 
  273inline void add_scale_3(
const T1 s1, 
const T2 v1[3], 
const T3 s2, 
const T4 v2[3], T5 dest[3]) {
 
  274    dest[0] = s1 * v1[0] + s2 * v2[0];
 
  275    dest[1] = s1 * v1[1] + s2 * v2[1];
 
  276    dest[2] = s1 * v1[2] + s2 * v2[2];
 
 
  281template <
typename T1, 
typename T2, 
typename T3, 
typename T4, 
typename T5>
 
  282inline void add_scale_2(
const T1 s1, 
const T2 v1[2], 
const T3 s2, 
const T4 v2[2], T5 dest[2]) {
 
  283    dest[0] = s1 * v1[0] + s2 * v2[0];
 
  284    dest[1] = s1 * v1[1] + s2 * v2[1];
 
 
  288template <
typename T1, 
typename T2>
 
  296template <
typename T1, 
typename T2>
 
  303template <
typename T1, 
typename T2>
 
  304inline void add_3(T1 a[3], 
const T2 b[3]) {
 
  305    for (
int i = 0; i != 3; ++i) { a[i] += b[i]; }
 
 
  309template <
typename T1, 
typename T2>
 
  310inline void add_2(T1 a[2], 
const T2 b[2]) {
 
  311    for (
int i = 0; i != 2; ++i) { a[i] += b[i]; }
 
 
  315template <
typename T1, 
typename T2, 
typename T3>
 
  317    for (
int i = 0; i != 3; ++i) { a[i] += s * b[i]; }
 
 
  321template <
typename T1, 
typename T2, 
typename T3>
 
  323    for (
int i = 0; i != 2; ++i) { a[i] += s * b[i]; }
 
 
  328inline T 
dot_3(
const T a[3], 
const T b[3]) {
 
  329    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
 
 
  334inline std::complex<T> 
dot_3(
const std::complex<T> a[3], 
const std::complex<T> b[3]) {
 
  335    return a[0] * std::conj(b[0]) + a[1] * std::conj(b[1]) + a[2] * std::conj(b[2]);
 
 
  340inline b2000::csda<T> 
dot_3(
const b2000::csda<T> a[3], 
const b2000::csda<T> b[3]) {
 
  341    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
 
 
  346inline T 
dot_2(
const T a[2], 
const T b[2]) {
 
  347    return a[0] * b[0] + a[1] * b[1];
 
 
  352inline std::complex<T> 
dot_2(
const std::complex<T> a[2], 
const std::complex<T> b[2]) {
 
  353    return a[0] * std::conj(b[0]) + a[1] * std::conj(b[1]);
 
 
  358inline b2000::csda<T> 
dot_2(
const b2000::csda<T> a[2], 
const b2000::csda<T> b[2]) {
 
  359    return a[0] * b[0] + a[1] * b[1];
 
 
  365    return std::sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
 
 
  371    return std::sqrt(std::norm(a[0]) + std::norm(a[1]) + std::norm(a[2]));
 
 
  377    return std::sqrt(a[0] * a[0] + a[1] * a[1]);
 
 
  383    return std::sqrt(std::norm(a[0]) + std::norm(a[1]));
 
 
  388template <
typename T1, 
typename T2, 
typename T3>
 
  390    c[0] = a[1] * b[2] - a[2] * b[1];
 
  391    c[1] = a[2] * b[0] - a[0] * b[2];
 
  392    c[2] = a[0] * b[1] - a[1] * b[0];
 
 
  397template <
typename T1, 
typename T2, 
typename T3>
 
  399    c[0] += a[1] * b[2] - a[2] * b[1];
 
  400    c[1] += a[2] * b[0] - a[0] * b[2];
 
  401    c[2] += a[0] * b[1] - a[1] * b[0];
 
 
  409    c[0] = a[1] * b[2] - a[2] * b[1];
 
  410    c[1] = a[2] * b[0] - a[0] * b[2];
 
  411    c[2] = a[0] * b[1] - a[1] * b[0];
 
 
  447    const b2000::csda<T> n = 
norm_3(a);
 
  449        b2000::csda<T> s = b2000::csda<T>(1) / n;
 
 
  487    const b2000::csda<T> n = 
norm_2(a);
 
  489        b2000::csda<T> s = b2000::csda<T>(1) / n;
 
 
  497template <
typename T1>
 
  499    std::fill_n(&a[0][0], 9, T1(0));
 
 
  503template <
typename T1>
 
  505    a[0][0] = a[0][1] = T1(0);
 
  506    a[1][0] = a[1][1] = T1(0);
 
 
  510template <
typename T1>
 
  512    std::fill_n(&a[0][0], 9, T1(0));
 
  513    a[0][0] = a[1][1] = a[2][2] = T1(1);
 
 
  517template <
typename T1>
 
  519    a[0][0] = a[1][1] = T1(1);
 
  520    a[0][1] = a[1][0] = T1(0);
 
 
  524template <
typename T1>
 
  525inline void copy_3_3(
const T1 a[3][3], T1 b[3][3]) {
 
  526    std::copy(&a[0][0], &a[0][0] + 9, &b[0][0]);
 
 
  530template <
typename T1, 
typename T2>
 
  531inline void copy_3_3(
const T1 a[3][3], T2 b[3][3]) {
 
  532    for (
int i = 0; i != 3; ++i) {
 
  533        for (
int j = 0; j != 3; ++j) { b[i][j] = a[i][j]; }
 
 
  538template <
typename T1>
 
  539inline void copy_2_2(
const T1 a[2][2], T1 b[2][2]) {
 
  540    std::copy(&a[0][0], &a[0][0] + 4, &b[0][0]);
 
 
  544template <
typename T1, 
typename T2>
 
  545inline void copy_2_2(
const T1 a[2][2], T2 b[2][2]) {
 
  546    for (
int i = 0; i != 2; ++i) {
 
  547        for (
int j = 0; j != 2; ++j) { b[i][j] = a[i][j]; }
 
 
  553inline void scale_3_3(
const T a, 
const T b[3][3], T c[3][3]) {
 
  554    c[0][0] = a * b[0][0];
 
  555    c[0][1] = a * b[0][1];
 
  556    c[0][2] = a * b[0][2];
 
  557    c[1][0] = a * b[1][0];
 
  558    c[1][1] = a * b[1][1];
 
  559    c[1][2] = a * b[1][2];
 
  560    c[2][0] = a * b[2][0];
 
  561    c[2][1] = a * b[2][1];
 
  562    c[2][2] = a * b[2][2];
 
 
  567inline void scale_2_2(
const T a, 
const T b[2][2], T c[2][2]) {
 
  568    c[0][0] = a * b[0][0];
 
  569    c[0][1] = a * b[0][1];
 
  570    c[1][0] = a * b[1][0];
 
  571    c[1][1] = a * b[1][1];
 
 
  575template <
typename T1, 
typename T2>
 
  576inline void add_3_3(T1 a[3][3], 
const T2 b[3][3]) {
 
  579    for (
int i = 0; i != 9; ++i) { aa[i] += bb[i]; }
 
 
  583template <
typename T1, 
typename T2>
 
  584inline void add_2_2(T1 a[2][2], 
const T2 b[2][2]) {
 
  587    for (
int i = 0; i != 4; ++i) { aa[i] += bb[i]; }
 
 
  593    c[0][0] += a * b[0][0];
 
  594    c[0][1] += a * b[0][1];
 
  595    c[0][2] += a * b[0][2];
 
  596    c[1][0] += a * b[1][0];
 
  597    c[1][1] += a * b[1][1];
 
  598    c[1][2] += a * b[1][2];
 
  599    c[2][0] += a * b[2][0];
 
  600    c[2][1] += a * b[2][1];
 
  601    c[2][2] += a * b[2][2];
 
 
  607    c[0][0] += a * b[0][0];
 
  608    c[0][1] += a * b[0][1];
 
  609    c[1][0] += a * b[1][0];
 
  610    c[1][1] += a * b[1][1];
 
 
  614template <
typename T1>
 
  616    std::swap(a[0][1], a[1][0]);
 
  617    std::swap(a[0][2], a[2][0]);
 
  618    std::swap(a[1][2], a[2][1]);
 
 
  622template <
typename T1>
 
  624    std::swap(a[0][1], a[1][0]);
 
 
  628template <
typename T1>
 
  630    for (
int i = 0; i != 3; ++i) {
 
  631        for (
int j = 0; j != 3; ++j) { b[i][j] = a[j][i]; }
 
 
  636template <
typename T1>
 
  638    for (
int i = 0; i != 2; ++i) {
 
  639        for (
int j = 0; j != 2; ++j) { b[i][j] = a[j][i]; }
 
 
  644template <
typename T1>
 
  648    for (
int i = 0; i < 9; i++) { res = std::max(res, aa[i]); }
 
 
  653template <
typename T1>
 
  657    for (
int i = 0; i < 4; i++) { res = std::max(res, aa[i]); }
 
 
  670    return a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1])
 
  671           + a[1][0] * (a[0][2] * a[2][1] - a[0][1] * a[2][2])
 
  672           + a[2][0] * (a[0][1] * a[1][2] - a[0][2] * a[1][1]);
 
 
  684    return a[0][0] * a[1][1] - a[0][1] * a[1][0];
 
 
  702        std::fill(b[0], b[3], T(0));
 
  705    const T inv_det = T(1) / det;
 
  706    b[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) * inv_det;
 
  707    b[0][1] = (a[0][2] * a[2][1] - a[0][1] * a[2][2]) * inv_det;
 
  708    b[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) * inv_det;
 
  709    b[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) * inv_det;
 
  710    b[1][1] = (a[0][0] * a[2][2] - a[0][2] * a[2][0]) * inv_det;
 
  711    b[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) * inv_det;
 
  712    b[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) * inv_det;
 
  713    b[2][1] = (a[0][1] * a[2][0] - a[0][0] * a[2][1]) * inv_det;
 
  714    b[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) * inv_det;
 
 
  732    const T inv_det = T(1) / det;
 
  733    b[0][0] = +a[1][1] * inv_det;
 
  734    b[0][1] = -a[0][1] * inv_det;
 
  735    b[1][0] = -a[1][0] * inv_det;
 
  736    b[1][1] = +a[0][0] * inv_det;
 
 
  767        std::fill(b[0], b[3], T(0));
 
  770    const T inv_det = T(1) / det;
 
  771    b[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) * inv_det;
 
  772    b[1][0] = (a[0][2] * a[2][1] - a[0][1] * a[2][2]) * inv_det;
 
  773    b[2][0] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) * inv_det;
 
  774    b[0][1] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) * inv_det;
 
  775    b[1][1] = (a[0][0] * a[2][2] - a[0][2] * a[2][0]) * inv_det;
 
  776    b[2][1] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) * inv_det;
 
  777    b[0][2] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) * inv_det;
 
  778    b[1][2] = (a[0][1] * a[2][0] - a[0][0] * a[2][1]) * inv_det;
 
  779    b[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) * inv_det;
 
 
  797    const T inv_det = T(1) / det;
 
  798    b[0][0] = +a[1][1] * inv_det;
 
  799    b[1][0] = -a[0][1] * inv_det;
 
  800    b[0][1] = -a[1][0] * inv_det;
 
  801    b[1][1] = +a[0][0] * inv_det;
 
 
  809    c[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
 
  810    c[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
 
  811    c[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
 
  812    c[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
 
  813    c[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
 
  814    c[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
 
  815    c[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
 
  816    c[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
 
  817    c[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
 
 
  824    c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[0][1] + a[0][2] * b[0][2];
 
  825    c[0][1] = a[1][0] * b[0][0] + a[1][1] * b[0][1] + a[1][2] * b[0][2];
 
  826    c[0][2] = a[2][0] * b[0][0] + a[2][1] * b[0][1] + a[2][2] * b[0][2];
 
  827    c[1][0] = a[0][0] * b[1][0] + a[0][1] * b[1][1] + a[0][2] * b[1][2];
 
  828    c[1][1] = a[1][0] * b[1][0] + a[1][1] * b[1][1] + a[1][2] * b[1][2];
 
  829    c[1][2] = a[2][0] * b[1][0] + a[2][1] * b[1][1] + a[2][2] * b[1][2];
 
  830    c[2][0] = a[0][0] * b[2][0] + a[0][1] * b[2][1] + a[0][2] * b[2][2];
 
  831    c[2][1] = a[1][0] * b[2][0] + a[1][1] * b[2][1] + a[1][2] * b[2][2];
 
  832    c[2][2] = a[2][0] * b[2][0] + a[2][1] * b[2][1] + a[2][2] * b[2][2];
 
 
  839    c[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1];
 
  840    c[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1];
 
  841    c[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1];
 
  842    c[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1];
 
 
  849    c[0][0] = a[0][0] * b[0][0] + a[1][0] * b[1][0] + a[2][0] * b[2][0];
 
  850    c[0][1] = a[0][1] * b[0][0] + a[1][1] * b[1][0] + a[2][1] * b[2][0];
 
  851    c[0][2] = a[0][2] * b[0][0] + a[1][2] * b[1][0] + a[2][2] * b[2][0];
 
  852    c[1][0] = a[0][0] * b[0][1] + a[1][0] * b[1][1] + a[2][0] * b[2][1];
 
  853    c[1][1] = a[0][1] * b[0][1] + a[1][1] * b[1][1] + a[2][1] * b[2][1];
 
  854    c[1][2] = a[0][2] * b[0][1] + a[1][2] * b[1][1] + a[2][2] * b[2][1];
 
  855    c[2][0] = a[0][0] * b[0][2] + a[1][0] * b[1][2] + a[2][0] * b[2][2];
 
  856    c[2][1] = a[0][1] * b[0][2] + a[1][1] * b[1][2] + a[2][1] * b[2][2];
 
  857    c[2][2] = a[0][2] * b[0][2] + a[1][2] * b[1][2] + a[2][2] * b[2][2];
 
 
  864    c[0][0] = a[0][0] * b[0][0] + a[1][0] * b[1][0];
 
  865    c[0][1] = a[0][1] * b[0][0] + a[1][1] * b[1][0];
 
  866    c[1][0] = a[0][0] * b[0][1] + a[1][0] * b[1][1];
 
  867    c[1][1] = a[0][1] * b[0][1] + a[1][1] * b[1][1];
 
 
  874    c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0];
 
  875    c[0][1] = a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0];
 
  876    c[0][2] = a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0];
 
  877    c[1][0] = a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1];
 
  878    c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1];
 
  879    c[1][2] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1];
 
  880    c[2][0] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2];
 
  881    c[2][1] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2];
 
  882    c[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2];
 
 
  889    c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0];
 
  890    c[0][1] = a[1][0] * b[0][0] + a[1][1] * b[1][0];
 
  891    c[1][0] = a[0][0] * b[0][1] + a[0][1] * b[1][1];
 
  892    c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1];
 
 
  900    c[0] = a[0][0] * b[0] + a[1][0] * b[1];
 
  901    c[1] = a[0][1] * b[0] + a[1][1] * b[1];
 
 
  909    c[0] = a[0][0] * b[0] + a[0][1] * b[1];
 
  910    c[1] = a[1][0] * b[0] + a[1][1] * b[1];
 
 
  917    c[0][0] += a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
 
  918    c[0][1] += a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
 
  919    c[0][2] += a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
 
  920    c[1][0] += a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
 
  921    c[1][1] += a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
 
  922    c[1][2] += a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
 
  923    c[2][0] += a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
 
  924    c[2][1] += a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
 
  925    c[2][2] += a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
 
 
  932    c[0][0] += a[0][0] * b[0][0] + a[1][0] * b[0][1];
 
  933    c[0][1] += a[0][1] * b[0][0] + a[1][1] * b[0][1];
 
  934    c[1][0] += a[0][0] * b[1][0] + a[1][0] * b[1][1];
 
  935    c[1][1] += a[0][1] * b[1][0] + a[1][1] * b[1][1];
 
 
  942    c[0][0] += a[0][0] * b[0][0] + a[0][1] * b[0][1] + a[0][2] * b[0][2];
 
  943    c[0][1] += a[1][0] * b[0][0] + a[1][1] * b[0][1] + a[1][2] * b[0][2];
 
  944    c[0][2] += a[2][0] * b[0][0] + a[2][1] * b[0][1] + a[2][2] * b[0][2];
 
  945    c[1][0] += a[0][0] * b[1][0] + a[0][1] * b[1][1] + a[0][2] * b[1][2];
 
  946    c[1][1] += a[1][0] * b[1][0] + a[1][1] * b[1][1] + a[1][2] * b[1][2];
 
  947    c[1][2] += a[2][0] * b[1][0] + a[2][1] * b[1][1] + a[2][2] * b[1][2];
 
  948    c[2][0] += a[0][0] * b[2][0] + a[0][1] * b[2][1] + a[0][2] * b[2][2];
 
  949    c[2][1] += a[1][0] * b[2][0] + a[1][1] * b[2][1] + a[1][2] * b[2][2];
 
  950    c[2][2] += a[2][0] * b[2][0] + a[2][1] * b[2][1] + a[2][2] * b[2][2];
 
 
  957    c[0][0] += a[0][0] * b[0][0] + a[0][1] * b[0][1];
 
  958    c[0][1] += a[1][0] * b[0][0] + a[1][1] * b[0][1];
 
  959    c[1][0] += a[0][0] * b[1][0] + a[0][1] * b[1][1];
 
  960    c[1][1] += a[1][0] * b[1][0] + a[1][1] * b[1][1];
 
 
  967    c[0][0] += a[0][0] * b[0][0] + a[1][0] * b[1][0] + a[2][0] * b[2][0];
 
  968    c[0][1] += a[0][1] * b[0][0] + a[1][1] * b[1][0] + a[2][1] * b[2][0];
 
  969    c[0][2] += a[0][2] * b[0][0] + a[1][2] * b[1][0] + a[2][2] * b[2][0];
 
  970    c[1][0] += a[0][0] * b[0][1] + a[1][0] * b[1][1] + a[2][0] * b[2][1];
 
  971    c[1][1] += a[0][1] * b[0][1] + a[1][1] * b[1][1] + a[2][1] * b[2][1];
 
  972    c[1][2] += a[0][2] * b[0][1] + a[1][2] * b[1][1] + a[2][2] * b[2][1];
 
  973    c[2][0] += a[0][0] * b[0][2] + a[1][0] * b[1][2] + a[2][0] * b[2][2];
 
  974    c[2][1] += a[0][1] * b[0][2] + a[1][1] * b[1][2] + a[2][1] * b[2][2];
 
  975    c[2][2] += a[0][2] * b[0][2] + a[1][2] * b[1][2] + a[2][2] * b[2][2];
 
 
  982    c[0][0] += a[0][0] * b[0][0] + a[1][0] * b[1][0];
 
  983    c[0][1] += a[0][1] * b[0][0] + a[1][1] * b[1][0];
 
  984    c[1][0] += a[0][0] * b[0][1] + a[1][0] * b[1][1];
 
  985    c[1][1] += a[0][1] * b[0][1] + a[1][1] * b[1][1];
 
 
  992    c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[0][1];
 
  993    c[0][1] = a[1][0] * b[0][0] + a[1][1] * b[0][1];
 
  994    c[1][0] = a[0][0] * b[1][0] + a[0][1] * b[1][1];
 
  995    c[1][1] = a[1][0] * b[1][0] + a[1][1] * b[1][1];
 
 
 1000template <
typename T>
 
 1002    c[0][0] += a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0];
 
 1003    c[0][1] += a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0];
 
 1004    c[0][2] += a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0];
 
 1005    c[1][0] += a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1];
 
 1006    c[1][1] += a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1];
 
 1007    c[1][2] += a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1];
 
 1008    c[2][0] += a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2];
 
 1009    c[2][1] += a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2];
 
 1010    c[2][2] += a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2];
 
 
 1015template <
typename T>
 
 1017    c[0][0] += a[0][0] * b[0][0] + a[0][1] * b[1][0];
 
 1018    c[0][1] += a[1][0] * b[0][0] + a[1][1] * b[1][0];
 
 1019    c[1][0] += a[0][0] * b[0][1] + a[0][1] * b[1][1];
 
 1020    c[1][1] += a[1][0] * b[0][1] + a[1][1] * b[1][1];
 
 
 1026template <
typename T>
 
 1028    c[0] = a[0][0] * b[0] + a[1][0] * b[1] + a[2][0] * b[2];
 
 1029    c[1] = a[0][1] * b[0] + a[1][1] * b[1] + a[2][1] * b[2];
 
 1030    c[2] = a[0][2] * b[0] + a[1][2] * b[1] + a[2][2] * b[2];
 
 
 1036template <
typename T>
 
 1038    c[0] = a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2];
 
 1039    c[1] = a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2];
 
 1040    c[2] = a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2];
 
 
 1046template <
typename T>
 
 1048    c[0] += a[0][0] * b[0] + a[1][0] * b[1] + a[2][0] * b[2];
 
 1049    c[1] += a[0][1] * b[0] + a[1][1] * b[1] + a[2][1] * b[2];
 
 1050    c[2] += a[0][2] * b[0] + a[1][2] * b[1] + a[2][2] * b[2];
 
 
 1055template <
typename T>
 
 1057    c[0] += a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2];
 
 1058    c[1] += a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2];
 
 1059    c[2] += a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2];
 
 
 1074template <
typename T>
 
 1075inline bool solve_2_2(
const T a[2][2], 
const T y[2], T x[2]) {
 
 1078        std::fill(x, x + 2, T(0));
 
 1081    const T inv_det = T(1) / det;
 
 1082    x[0] = (y[0] * a[1][1] - y[1] * a[1][0]) * inv_det;
 
 1083    x[1] = (y[1] * a[0][0] - y[0] * a[0][1]) * inv_det;
 
 
 1096template <
typename T>
 
 1098    const T t = m[0][0] + m[1][1];
 
 1099    const T d = m[0][0] * m[1][1] - m[0][1] * m[1][0];
 
 1100    const T s = std::sqrt(t * t / 4 - d);
 
 1101    value[0] = t / 2 + s;
 
 1102    value[1] = t / 2 - s;
 
 1104        if (std::abs(m[0][1]) > std::numeric_limits<T>::epsilon()) {
 
 1105            vector[0][0] = value[0] - m[1][1];
 
 1106            vector[1][0] = value[1] - m[1][1];
 
 1107            vector[0][1] = vector[1][1] = m[0][1];
 
 1108        } 
else if (std::abs(m[1][0]) > std::numeric_limits<T>::epsilon()) {
 
 1109            vector[0][0] = vector[1][0] = m[1][0];
 
 1110            vector[0][1] = value[0] - m[0][0];
 
 1111            vector[1][1] = value[1] - m[0][0];
 
 1113            vector[0][0] = vector[1][1] = 1;
 
 1114            vector[1][0] = vector[0][1] = 0;
 
 
 1121template <
typename T>
 
 1123    i1 = t[0] + t[1] + t[2];
 
 1124    i2 = t[0] * t[1] + t[1] * t[2] + t[0] * t[2] - t[3] * t[3] - t[4] * t[4] - t[5] * t[5];
 
 1125    i3 = t[0] * t[1] * t[2] + 2 * t[3] * t[4] * t[5] - t[0] * t[4] * t[4] - t[1] * t[5] * t[5]
 
 1126         - t[2] * t[3] * t[3];
 
 
 1130template <
typename T>
 
 1140        if (nsol == T(2)) { s3 = i1 - s1 - s2; }
 
 1141        if (s1 < s2) { std::swap(s1, s2); }
 
 1142        if (s1 < s3) { std::swap(s1, s3); }
 
 1143        if (s2 < s3) { std::swap(s2, s3); }
 
 
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
 
void inner_product_3_3_TT(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:873
 
void set_zero_3_3(T1 a[3][3])
Definition b2tensor_calculus.H:498
 
void add_2(const T1 v1[2], const T2 v2[2], T3 dest[2])
Definition b2tensor_calculus.H:265
 
void set_identity_3_3(T1 a[3][3])
Definition b2tensor_calculus.H:511
 
bool solve_2_2(const T a[2][2], const T y[2], T x[2])
Definition b2tensor_calculus.H:1075
 
void add_3(const T1 v1[3], const T2 v2[3], T3 dest[3])
Definition b2tensor_calculus.H:256
 
void inner_product_2_2_NT(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:863
 
void inner_product_2_2_TT(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:888
 
void inner_product_add_2_2_TN(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:956
 
T invert_2_2(const T a[2][2], T b[2][2])
Definition b2tensor_calculus.H:730
 
void inner_product_add_2_2_NT(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:981
 
void sub_2(const T1 v1[2], const T2 v2[2], T3 dest[2])
Definition b2tensor_calculus.H:248
 
T norm_outer_product_3(const T a[3], const T b[3])
Definition b2tensor_calculus.H:407
 
void add_scale_2_2(const T a, const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:606
 
T norm_3(T a[3])
Definition b2tensor_calculus.H:364
 
void copy_3(const T1 a[3], T1 b[3])
Definition b2tensor_calculus.H:214
 
void inner_product_3_3_NN(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:808
 
void set_zero_2(T1 a[2])
Definition b2tensor_calculus.H:208
 
void inner_product_2_1_TN(const T a[2][2], const T b[2], T c[2])
Definition b2tensor_calculus.H:908
 
void inner_product_add_3_3_TT(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:1001
 
void inner_product_add_3_3_NT(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:966
 
T determinant_3x3(const std::array< std::array< T, 3 >, 3 > &mat_a)
Definition b2tensor_calculus.H:59
 
T determinant_3_3(const T a[3][3])
Definition b2tensor_calculus.H:669
 
void inner_product_3_1_TN(const T a[3][3], const T b[3], T c[3])
Definition b2tensor_calculus.H:1037
 
T invert_x_x(const T a[2][2], T b[2][2])
Definition b2tensor_calculus.H:742
 
void add_scale_3_3(const T a, const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:592
 
void sub_3(const T1 v1[3], const T2 v2[3], T3 dest[3])
Definition b2tensor_calculus.H:239
 
void set_identity_2_2(T1 a[2][2])
Definition b2tensor_calculus.H:518
 
void add_scale_3(const T1 s1, const T2 v1[3], const T3 s2, const T4 v2[3], T5 dest[3])
Definition b2tensor_calculus.H:273
 
void set_zero_2_2(T1 a[2][2])
Definition b2tensor_calculus.H:504
 
void eigenvector_2(const std::array< std::array< T, 2 >, 2 > &matrix, std::array< T, 2 > &eigenvalues, std::array< std::array< T, 2 >, 2 > &eigenvector)
Definition b2tensor_calculus.H:181
 
T transposed_invert_3_3(const T a[3][3], T b[3][3])
Definition b2tensor_calculus.H:764
 
T normalise_3(T a[3])
Definition b2tensor_calculus.H:418
 
std::array< T, 2 > eigenvalues_2(const std::array< std::array< T, 2 >, 2 > &matrix)
Definition b2tensor_calculus.H:142
 
void add_scale_2(const T1 s1, const T2 v1[2], const T3 s2, const T4 v2[2], T5 dest[2])
Definition b2tensor_calculus.H:282
 
void outer_product_3(const T1 a[3], const T2 b[3], T3 c[3])
Definition b2tensor_calculus.H:389
 
void transpose_2_2(T1 a[2][2])
Definition b2tensor_calculus.H:623
 
T determinant_2x2(const std::array< std::array< T, 2 >, 2 > &mat_a)
Definition b2tensor_calculus.H:71
 
void copy_2_2(const T1 a[2][2], T1 b[2][2])
Definition b2tensor_calculus.H:539
 
void inner_product_add_3_3_NN(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:916
 
void inner_product_add_2_2_NN(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:931
 
void solve_cubic_equation(const T a, const T b, const T c, const T d, int &nsol, T &x1, T &x2, T &x3)
Definition b2util.H:770
 
void inner_product_add_3_3_TN(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:941
 
void stress_invariants(const T t[6], T &i1, T &i2, T &i3)
Definition b2tensor_calculus.H:1122
 
void inner_product_3_3_NT(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:848
 
void add_3_3(T1 a[3][3], const T2 b[3][3])
Definition b2tensor_calculus.H:576
 
void inner_product_add_3_1_TN(const T a[3][3], const T b[3], T c[3])
Definition b2tensor_calculus.H:1056
 
void inner_product_2_2_NN(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:838
 
void inner_product_3_1_NN(const T a[3][3], const T b[3], T c[3])
Definition b2tensor_calculus.H:1027
 
void add_2_2(T1 a[2][2], const T2 b[2][2])
Definition b2tensor_calculus.H:584
 
void copy_2(const T1 a[2], T1 b[2])
Definition b2tensor_calculus.H:226
 
void set_zero_3(T1 a[3])
Definition b2tensor_calculus.H:202
 
T transposed_invert_2_2(const T a[2][2], T b[2][2])
Definition b2tensor_calculus.H:795
 
T invert_3_3(const T a[3][3], T b[3][3])
Definition b2tensor_calculus.H:699
 
T norm_2(T a[2])
Definition b2tensor_calculus.H:376
 
T1 norm_inf_3_3(const T1 a[3][3])
Definition b2tensor_calculus.H:645
 
T normalise_2(T a[2])
Definition b2tensor_calculus.H:460
 
void outer_product_add_3(const T1 a[3], const T2 b[3], T3 c[3])
Definition b2tensor_calculus.H:398
 
void copy_3_3(const T1 a[3][3], T1 b[3][3])
Definition b2tensor_calculus.H:525
 
T1 norm_inf_2_2(const T1 a[3][3])
Definition b2tensor_calculus.H:654
 
void scale_2(T1 v[2], const T2 s)
Definition b2tensor_calculus.H:297
 
T dot_3(const T a[3], const T b[3])
Definition b2tensor_calculus.H:328
 
void inner_product_3_3_TN(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:823
 
void inner_product_add_2_2_TT(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:1016
 
void scale_3(T1 v[3], const T2 s)
Definition b2tensor_calculus.H:289
 
T invert_3x3(const std::array< std::array< T, 3 >, 3 > &mat_a, std::array< std::array< T, 3 >, 3 > &mat_b)
Definition b2tensor_calculus.H:86
 
void inner_product_2_2_TN(const T a[2][2], const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:991
 
void scale_2_2(const T a, const T b[2][2], T c[2][2])
Definition b2tensor_calculus.H:567
 
T invert_2x2(const std::array< std::array< T, 2 >, 2 > &mat_a, std::array< std::array< T, 2 >, 2 > &mat_b)
Definition b2tensor_calculus.H:117
 
T determinant_2_2(const T a[2][2])
Definition b2tensor_calculus.H:683
 
T dot_2(const T a[2], const T b[2])
Definition b2tensor_calculus.H:346
 
void transpose_3_3(T1 a[3][3])
Definition b2tensor_calculus.H:615
 
void inner_product_add_3_1_NN(const T a[3][3], const T b[3], T c[3])
Definition b2tensor_calculus.H:1047
 
void inner_product_2_1_NN(const T a[2][2], const T b[2], T c[2])
Definition b2tensor_calculus.H:899
 
void scale_3_3(const T a, const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:553
 
void stress_principals(const T i1, const T i2, const T i3, T &s1, T &s2, T &s3)
Calculate the stress principals from the stress invariants.
Definition b2tensor_calculus.H:1131