LCOV - code coverage report
Current view: top level - src/Set - Matrix4_MajorMinor.H (source / functions) Coverage Total Hit
Test: coverage_merged.info Lines: 83.8 % 345 289
Test Date: 2025-06-26 20:08:28 Functions: 84.2 % 19 16

            Line data    Source code
       1              : #ifndef SET_MATRIX4_MAJORMINOR_H
       2              : #define SET_MATRIX4_MAJORMINOR_H
       3              : 
       4              : #include "Base.H"
       5              : #include <math.h>
       6              : 
       7              : namespace Set
       8              : {
       9              : /// \brief Data structure for a 4th order 3D tensor with major and minor symmetry
      10              : ///
      11              : /// 2D version. See full explanation below.
      12              : ///
      13              : template<>
      14              : class Matrix4<2,Sym::MajorMinor>
      15              : {
      16              :     Scalar data[6] = {NAN,NAN,NAN,NAN,NAN,NAN};
      17              : 
      18              : public:
      19         1360 :     AMREX_GPU_HOST_DEVICE Matrix4() {};
      20              :     //Matrix4(const Matrix4<2,Sym::MajorMinor> &in)
      21              :     //{
      22              :     //    for (int i = 0; i < 6; i++) data[i] =  in.data[i];
      23              :     //}
      24              :     AMREX_FORCE_INLINE
      25              :     const Scalar & operator () (const int i, const int j, const int k, const int l) const
      26              :     {
      27         1600 :         int uid = i + 2*j + 4*k + 8*l;
      28         1600 :         if      (uid==0 )                                  return data[0]; // [0000]
      29         1500 :         else if (uid==8  || uid==4 || uid==2 || uid==1 )   return data[1]; // [0001] [0010] [0100] [1000]
      30         1100 :         else if (uid==12 || uid==3 )                       return data[2]; // [0011] [1100]
      31          900 :         else if (uid==10 || uid==6 || uid==9 || uid==5 )   return data[3]; // [0101] [1001] [0110] [1010]
      32          500 :         else if (uid==14 || uid==13 || uid==11 || uid==7 ) return data[4]; // [0111] [1011] [1101] [1110]
      33          100 :         else if (uid==15 )                                 return data[5]; // [1111]
      34            0 :         else Util::Abort(INFO,"Index out of range");
      35            0 :         return Set::Garbage;
      36              :     }
      37              :     AMREX_FORCE_INLINE
      38              :     Scalar & operator () (const int i, const int j, const int k, const int l)
      39              :     {
      40      1565280 :         int uid = i + 2*j + 4*k + 8*l;
      41       193545 :         if      (uid==0 )                                  return data[0]; // [0000]
      42      1467450 :         else if (uid==8  || uid==4 || uid==2 || uid==1 )   return data[1]; // [0001] [0010] [0100] [1000]
      43      1076130 :         else if (uid==12 || uid==3 )                       return data[2]; // [0011] [1100]
      44       880470 :         else if (uid==10 || uid==6 || uid==9 || uid==5 )   return data[3]; // [0101] [1001] [0110] [1010]
      45       489150 :         else if (uid==14 || uid==13 || uid==11 || uid==7 ) return data[4]; // [0111] [1011] [1101] [1110]
      46        97830 :         else if (uid==15 )                                 return data[5]; // [1111]
      47            0 :         else Util::Abort(INFO,"Index out of range");
      48            0 :         return Set::Garbage; 
      49              :     }
      50            0 :     void Print (std::ostream& os)
      51              :     {
      52            0 :         os.precision(4);
      53            0 :         for (int k = 0; k < 2; k++)
      54              :         {
      55            0 :             for (int i = -1; i < 3; i++)
      56              :             {
      57            0 :                 for (int l = 0; l < 2; l++)
      58              :                 {
      59            0 :                     if (i==-1)       os << "┌                         ┐ ";
      60            0 :                     else if (i == 2) os << "└                         ┘ ";
      61              :                     else 
      62              :                     {
      63            0 :                         os << "│ ";
      64            0 :                         for (int j = 0; j < 2; j++)
      65              :                         {
      66            0 :                             const Set::Scalar &val = (*this)(i,j,k,l);
      67            0 :                             os << std::scientific << std::setw(11) << val ; //(fabs(val)>1E-10 ? val : 0);
      68            0 :                             os << " "; 
      69              :                         }
      70            0 :                         os << "│ ";
      71              :                     }
      72              :                 }
      73            0 :                 os<<std::endl;
      74              :             }
      75              :         }
      76            0 :     }
      77              : 
      78              :     Set::Scalar Norm()
      79              :     {
      80              :         return std::sqrt(data[0]*data[0] + data[1]*data[1] + data[2]*data[2] + data[3]*data[3] + data[4]*data[4] + data[5]*data[5]);
      81              :     }
      82              :     bool contains_nan() const
      83              :     {
      84              :         if (std::isnan(data[ 0])) return true;
      85              :         if (std::isnan(data[ 1])) return true;
      86              :         if (std::isnan(data[ 2])) return true;
      87              :         if (std::isnan(data[ 3])) return true;
      88              :         if (std::isnan(data[ 4])) return true;
      89              :         if (std::isnan(data[ 5])) return true;
      90              :         return false;
      91              :     }
      92              : 
      93            0 :     AMREX_GPU_HOST_DEVICE void operator += (Matrix4<2,Sym::MajorMinor> a) {for (int i = 0; i < 6; i++) data[i] += a.data[i];}
      94              :     AMREX_GPU_HOST_DEVICE void operator -= (Matrix4<2,Sym::MajorMinor> a) {for (int i = 0; i < 6; i++) data[i] -= a.data[i];}
      95              :     AMREX_GPU_HOST_DEVICE void operator *= (Matrix4<2,Sym::MajorMinor> a) {for (int i = 0; i < 6; i++) data[i] *= a.data[i];}
      96              :     AMREX_GPU_HOST_DEVICE void operator /= (Matrix4<2,Sym::MajorMinor> a) {for (int i = 0; i < 6; i++) data[i] /= a.data[i];}
      97              :     AMREX_GPU_HOST_DEVICE void operator *= (Set::Scalar alpha)            {for (int i = 0; i < 6; i++) data[i] *= alpha;}
      98              :     AMREX_GPU_HOST_DEVICE void operator /= (Set::Scalar alpha)            {for (int i = 0; i < 6; i++) data[i] /= alpha;}
      99              : 
     100              :     static Matrix4<2,Sym::MajorMinor> Increment()
     101              :     {
     102              :         Matrix4<2,Sym::MajorMinor> ret;
     103              :         for (int i = 0 ; i < 6; i++) ret.data[i] = (Set::Scalar)i;
     104              :         return ret;
     105              :     }
     106              :     static Matrix4<2,Sym::MajorMinor> Randomize()
     107              :     {
     108              :         Matrix4<2,Sym::MajorMinor> ret;
     109              :         for (int i = 0 ; i < 6; i++) ret.data[i] = (Util::Random());
     110              :         return ret;
     111              :     }
     112           96 :     static Matrix4<2,Sym::MajorMinor> Zero()
     113              :     {
     114           96 :         Matrix4<2,Sym::MajorMinor> ret;
     115          672 :         for (int i = 0 ; i < 6; i++) ret.data[i] = 0.0;
     116           96 :         return ret;
     117              :     }
     118         1106 :     static Matrix4<2,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44, 
     119              :                                             Eigen::Matrix3d R = Eigen::Matrix3d::Identity())
     120              :     {
     121         1106 :         Set::Matrix4<2,Sym::MajorMinor> ret;
     122              :         Set::Scalar Ctmp[3][3][3][3];
     123              : 
     124         4424 :         for(int i = 0; i < 3; i++) 
     125        13272 :             for(int j = 0; j < 3; j++) 
     126        39816 :                 for(int k = 0; k < 3; k++) 
     127       119448 :                     for(int l = 0; l < 3; l++)
     128              :                     {
     129        89586 :                         if(i == j && j == k && k == l)  Ctmp[i][j][k][l] = C11;
     130        86268 :                         else if (i==k && j==l) Ctmp[i][j][k][l] = C44;
     131        79632 :                         else if (i==j && k==l) Ctmp[i][j][k][l] = C12;
     132        72996 :                         else Ctmp[i][j][k][l] = 0.0;
     133              :                     }
     134         3318 :         for(int p = 0; p < 2; p++) 
     135         6636 :             for(int q = 0; q < 2; q++) 
     136        13272 :                 for(int s = 0; s < 2; s++) 
     137        26544 :                     for(int t = 0; t < 2; t++)
     138              :                     {
     139        17696 :                         ret(p,q,s,t) = 0.0;
     140        70784 :                         for(int i = 0; i < 3; i++) 
     141       212352 :                             for(int j = 0; j < 3; j++) 
     142       637056 :                                 for(int k = 0; k < 3; k++) 
     143      1911168 :                                     for(int l = 0; l < 3; l++) 
     144      2866752 :                                         ret(p,q,s,t) += R(p,i)*R(s,k)*Ctmp[i][j][k][l]*R(q,j)*R(t,l);
     145              :                     }                
     146         2212 :         return ret;
     147              :     }
     148           46 :     static Matrix4<2,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44, 
     149              :                                             Set::Scalar phi1, Set::Scalar Phi, Set::Scalar phi2)
     150              :     {
     151           46 :         Eigen::Matrix3d R;
     152           46 :         R = Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
     153           92 :             Eigen::AngleAxisd(Phi,  Eigen::Vector3d::UnitZ()) *
     154           92 :             Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
     155           46 :         return Matrix4<2,Sym::MajorMinor>::Cubic(C11,C12,C44,R);
     156              :     }
     157         1060 :     static Matrix4<2,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44, 
     158              :                                             Set::Quaternion q)
     159              :     {
     160         1060 :         Eigen::Matrix3d R = q.normalized().toRotationMatrix();
     161         1060 :         return Cubic(C11,C12,C44,R);
     162              :     }
     163              : 
     164              : 
     165           23 :     static Matrix4<2,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Eigen::Matrix3d R = Eigen::Matrix3d::Identity())
     166              :     {
     167           23 :         Set::Matrix4<2,Sym::MajorMinor> ret;
     168           23 :         Set::Scalar Ctmp[3][3][3][3] = {{{{0.0}}}};
     169              : 
     170           92 :         for(int i = 0; i < 3; i++)
     171          276 :             for(int j = 0; j < 3; j++)
     172          828 :                 for(int k = 0; k < 3; k++)
     173         2484 :                     for(int l = 0; l < 3; l++)
     174              :                     {
     175         1863 :                         if(i==j && j==k && k==l)
     176              :                         {
     177           69 :                             if      (i < 2)   Ctmp[i][j][k][l] = C11;
     178           23 :                             else              Ctmp[i][j][k][l] = C33;
     179              :                         }
     180         1794 :                         else if(i==j && k==l)
     181              :                         {
     182          138 :                             if      (i<2 && k<2 && i!=k) Ctmp[i][j][k][l] = C12;
     183           92 :                             else if ((i<2 && k==2) || (i==2 && k<2)) Ctmp[i][j][k][l] = C13;
     184              :                         }
     185         1656 :                         else if((i==k && j==l) && (i!=j))
     186              :                         {
     187          138 :                             Ctmp[i][j][k][l] = C44;
     188              :                         }
     189              :                         else
     190              :                         {
     191         1518 :                             Ctmp[i][j][k][l] = 0.0;
     192              :                         }
     193              :                     }
     194              : 
     195              :         // C66 = 0.5*(C11 - C12)
     196           23 :         Ctmp[0][1][0][1] = 0.5 * (C11 - C12);
     197           23 :         Ctmp[1][0][1][0] = 0.5 * (C11 - C12);
     198              : 
     199           69 :         for(int p = 0; p < 2; p++)
     200          138 :             for(int q = 0; q < 2; q++)
     201          276 :                 for(int s = 0; s < 2; s++)
     202          552 :                     for(int t = 0; t < 2; t++)
     203              :                     {
     204          368 :                         ret(p,q,s,t) = 0.0;
     205         1472 :                         for(int i = 0; i < 3; i++)
     206         4416 :                             for(int j = 0; j < 3; j++)
     207        13248 :                                 for(int k = 0; k < 3; k++)
     208        39744 :                                     for(int l = 0; l < 3; l++)
     209        59616 :                                         ret(p,q,s,t) += R(p,i)*R(s,k)*Ctmp[i][j][k][l]*R(q,j)*R(t,l);
     210              :                     }
     211           46 :         return ret;
     212              :     }
     213           22 :     static Matrix4<2,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Set::Scalar phi1, Set::Scalar Phi, Set::Scalar phi2)
     214              :     {
     215              :         Eigen::Quaterniond q =
     216           22 :             Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
     217           22 :             Eigen::AngleAxisd(Phi,  Eigen::Vector3d::UnitZ()) *
     218           44 :             Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
     219           22 :         Eigen::Matrix3d R = q.toRotationMatrix();
     220           22 :         return Matrix4<2,Sym::MajorMinor>::Transverse(C11,C12,C13,C33,C44,R);
     221              :     }
     222              :     static Matrix4<2,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Set::Quaternion q)
     223              :     {
     224              :         Eigen::Matrix3d R = q.normalized().toRotationMatrix();
     225              :         return Transverse(C11,C12,C13,C33,C44,R);
     226              :     }
     227              : 
     228              : 
     229              :     friend Eigen::Matrix<Set::Scalar,2,2> operator * (Matrix4<2,Sym::MajorMinor> a, Eigen::Matrix<Set::Scalar,2,2> b);
     230              :     friend bool operator == (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b);
     231              :     friend Matrix4<2,Sym::MajorMinor> operator + (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b);
     232              :     friend Matrix4<2,Sym::MajorMinor> operator - (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b);
     233              :     friend Matrix4<2,Sym::MajorMinor> operator * (Matrix4<2,Sym::MajorMinor> a, Set::Scalar b);
     234              :     friend Matrix4<2,Sym::MajorMinor> operator * (Set::Scalar b, Matrix4<2,Sym::MajorMinor> a);
     235              :     friend Matrix4<2,Sym::MajorMinor> operator / (Matrix4<2,Sym::MajorMinor> a, Set::Scalar b);
     236              :     friend Set::Vector operator * (Matrix4<2,Sym::MajorMinor> a, Set::Matrix3 b);
     237              : };
     238              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     239              : bool operator == (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b)
     240              : {
     241          175 :     for (int i = 0 ; i < 6 ; i++) if (a.data[i] != b.data[i]) return false;
     242           25 :     return true;
     243              : }
     244              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     245              : Matrix4<2,Sym::MajorMinor> operator + (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b)
     246              : {
     247            0 :     Matrix4<2,Sym::MajorMinor> ret;
     248            0 :     for (int i = 0 ; i < 6 ; i++) ret.data[i] = a.data[i] + b.data[i];
     249            0 :     return ret;
     250              : }
     251              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     252              : Matrix4<2,Sym::MajorMinor> operator - (Matrix4<2,Sym::MajorMinor> a, Matrix4<2,Sym::MajorMinor> b)
     253              : {
     254            0 :     Matrix4<2,Sym::MajorMinor> ret;
     255            0 :     for (int i = 0 ; i < 6 ; i++) ret.data[i] = a.data[i] - b.data[i];
     256            0 :     return ret;
     257              : }
     258              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     259              : Matrix4<2,Sym::MajorMinor> operator * (Matrix4<2,Sym::MajorMinor> a, Set::Scalar b)
     260              : {
     261           10 :     Matrix4<2,Sym::MajorMinor> ret;
     262           70 :     for (int i = 0 ; i < 6 ; i++) ret.data[i] = a.data[i] * b;
     263           10 :     return ret;
     264              : }
     265              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     266              : Matrix4<2,Sym::MajorMinor> operator * (Set::Scalar b,Matrix4<2,Sym::MajorMinor> a)
     267              : {
     268            0 :     return a*b;
     269              : }
     270              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     271              : Matrix4<2,Sym::MajorMinor> operator / (Matrix4<2,Sym::MajorMinor> a, Set::Scalar b)
     272              : {
     273            0 :     Matrix4<2,Sym::MajorMinor> ret;
     274            0 :     for (int i = 0 ; i < 6 ; i++) ret.data[i] = a.data[i] / b;
     275            0 :     return ret;
     276              : }
     277              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     278              : Eigen::Matrix<Set::Scalar,2,2> operator * (Matrix4<2,Sym::MajorMinor> a, Eigen::Matrix<Set::Scalar,2,2> b)
     279              : {
     280         2430 :         Eigen::Matrix<Set::Scalar,2,2> ret = Eigen::Matrix<Set::Scalar,2,2>::Zero();
     281         2430 :     ret(0,0) = a.data[0]*b(0,0) + a.data[1]*(b(0,1) + b(1,0)) + a.data[2]*b(1,1);
     282         2430 :     ret(0,1) = a.data[1]*b(0,0) + a.data[3]*(b(0,1) + b(1,0)) + a.data[4]*b(1,1);
     283         2430 :     ret(1,1) = a.data[2]*b(0,0) + a.data[4]*(b(0,1) + b(1,0)) + a.data[5]*b(1,1);
     284         2430 :     ret(1,0) = ret(0,1);
     285         2430 :     return ret;
     286              : }
     287              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     288              : Eigen::Matrix<amrex::Real,2,1> operator * (Matrix4<2,Sym::MajorMinor> a, std::array<Eigen::Matrix<amrex::Real,2,2>,2> b);
     289              : 
     290              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     291              : Set::Vector operator * (Matrix4<2,Sym::MajorMinor> a, Set::Matrix3 b)
     292              : {
     293            0 :     Set::Vector ret = Set::Vector::Zero();
     294            0 :     ret(0) = a.data[0]*b(0,0,0) + a.data[1]*(b(0,1,0) + b(1,0,0) + b(0,0,1)) + a.data[2]*b(1,1,0)  + a.data[3]*(b(0,1,1) + b(1,0,1)) + a.data[4]*b(1,1,1);
     295            0 :     ret(1) = a.data[1]*b(0,0,0) + a.data[2]*b(0,0,1) + a.data[3]*(b(0,1,0) + b(1,0,0)) + a.data[4]*(b(1,1,0)  + b(0,1,1) + b(1,0,1)) + a.data[5]*b(1,1,1);
     296            0 :     return ret;
     297              : }
     298              :     
     299              : /// \brief Data structure for a 4th order 3D tensor with major and minor symmetry
     300              : ///
     301              : /// Let the tensor
     302              : /// \f$\mathbb{C}\in\mathbb{R}^3\times\mathbb{R}^3\times\mathbb{R}^3\times\mathbb{R}^3\f$
     303              : /// be have major symmetry (\f$\mathbb{C}_{ijkl}=\mathbb{C}_{klij}\f$)
     304              : /// and minor symmetry (\f$\mathbb{C}_{ijkl}=\mathbb{C}_{jikl}=\mathbb{C}_{ijlk}\f$)
     305              : /// Then there are only 21 unique elements (rather than 81).
     306              : ///
     307              : /// This object acts like a 4D array such that `C(i,j,k,l)` returns the corresponding
     308              : /// element, but symmetry is always obeyed. This allows the user code to be much prettier, 
     309              : /// while maintaining a relatively small object size.
     310              : ///
     311              : template<>
     312              : class Matrix4<3,Sym::MajorMinor>
     313              : {
     314              :     Scalar data[21] = { NAN,NAN,NAN,NAN,NAN,NAN,NAN,
     315              :                         NAN,NAN,NAN,NAN,NAN,NAN,NAN,
     316              :                         NAN,NAN,NAN,NAN,NAN,NAN,NAN };
     317              : 
     318              : public:
     319      1425086 :     AMREX_GPU_HOST_DEVICE Matrix4() {};
     320              :     AMREX_FORCE_INLINE
     321              :     const Scalar & operator () (const int i, const int j, const int k, const int l) const
     322              :     {
     323         9475 :         int uid = i + 3*j + 9*k + 27*l;
     324              :         // [0000]
     325         9475 :         if (uid==0 ) return data[0];
     326              :         // [0001] [0010] [0100] [1000]
     327         8000 :         else if (uid==27 || uid==9 || uid==3 || uid==1 ) return data[1];
     328              :         // [0002] [0020] [0200] [2000]
     329         7600 :         else if (uid==54 || uid==18 || uid==6 || uid==2 ) return data[2];
     330              :         // [0011] [1100]
     331         7200 :         else if (uid==36 || uid==4 ) return data[3];
     332              :         // [0012] [0021] [1200] [2100]
     333         7000 :         else if (uid==63 || uid==45 || uid==7 || uid==5 ) return data[4];
     334              :         // [0022] [2200]
     335         6600 :         else if (uid==72 || uid==8 ) return data[5];
     336              :         // [0101] [0110] [1001] [1010]
     337         6400 :         else if (uid==30 || uid==12 || uid==28 || uid==10 ) return data[6];
     338              :         // [0102] [0120] [1002] [1020] [0201] [2001] [0210] [2010]
     339         6000 :         else if (uid==57 || uid==21 || uid==33 || uid==15 || uid==55 || uid==19 || uid==29 || uid==11 ) return data[7];
     340              :         // [0111] [1011] [1101] [1110]
     341         5200 :         else if (uid==39 || uid==37 || uid==31 || uid==13 ) return data[8];
     342              :         // [0112] [1012] [0121] [1021] [1201] [1210] [2101] [2110]
     343         4800 :         else if (uid==66 || uid==48 || uid==64 || uid==46 || uid==34 || uid==16 || uid==32 || uid==14 ) return data[9];
     344              :         // [0122] [1022] [2201] [2210]
     345         4000 :         else if (uid==75 || uid==73 || uid==35 || uid==17 ) return data[10];
     346              :         // [0202] [2002] [0220] [2020]
     347         3600 :         else if (uid==60 || uid==24 || uid==56 || uid==20 ) return data[11];
     348              :         // [0211] [2011] [1102] [1120]
     349         3200 :         else if (uid==42 || uid==58 || uid==22 || uid==38 ) return data[12];
     350              :         // [0212] [2012] [0221] [2021] [1202] [1220] [2102] [2120]
     351         2800 :         else if (uid==69 || uid==51 || uid==61 || uid==25 || uid==65 || uid==47 || uid==59 || uid==23 ) return data[13];
     352              :         // [0222] [2022] [2202] [2220]
     353         2000 :         else if (uid==78 || uid==74 || uid==62 || uid==26 ) return data[14];
     354              :         // [1111]
     355         1600 :         else if (uid==40 ) return data[15];
     356              :         // [1112] [1121] [1211] [2111]
     357         1500 :         else if (uid==67 || uid==49 || uid==43 || uid==41 ) return data[16];
     358              :         // [1122] [2211]
     359         1100 :         else if (uid==76 || uid==44 ) return data[17];
     360              :         // [1212] [2112] [1221] [2121]
     361          900 :         else if (uid==70 || uid==52 || uid==68 || uid==50 ) return data[18];
     362              :         // [1222] [2122] [2212] [2221]
     363          500 :         else if (uid==79 || uid==77 || uid==71 || uid==53 ) return data[19];
     364              :         // [2222]
     365          100 :         else if (uid==80 ) return data[20];
     366            0 :         else Util::Abort(INFO,"Index out of range");
     367            0 :         return Set::Garbage; 
     368              :     }
     369              :     AMREX_FORCE_INLINE
     370              :     Scalar & operator () (const int i, const int j, const int k, const int l)
     371              :     {
     372     28067796 :         int uid = i + 3*j + 9*k + 27*l;
     373              :         // [0000]
     374      2607870 :         if (uid==0 ) return data[0];
     375              :         // [0001] [0010] [0100] [1000]
     376     27721280 :         else if (uid==27 || uid==9 || uid==3 || uid==1 ) return data[1];
     377              :         // [0002] [0020] [0200] [2000]
     378     26335216 :         else if (uid==54 || uid==18 || uid==6 || uid==2 ) return data[2];
     379              :         // [0011] [1100]
     380     24949152 :         else if (uid==36 || uid==4 ) return data[3];
     381              :         // [0012] [0021] [1200] [2100]
     382     24256120 :         else if (uid==63 || uid==45 || uid==7 || uid==5 ) return data[4];
     383              :         // [0022] [2200]
     384     22870056 :         else if (uid==72 || uid==8 ) return data[5];
     385              :         // [0101] [0110] [1001] [1010]
     386     22177024 :         else if (uid==30 || uid==12 || uid==28 || uid==10 ) return data[6];
     387              :         // [0102] [0120] [1002] [1020] [0201] [2001] [0210] [2010]
     388     20790960 :         else if (uid==57 || uid==21 || uid==33 || uid==15 || uid==55 || uid==19 || uid==29 || uid==11 ) return data[7];
     389              :         // [0111] [1011] [1101] [1110]
     390     18018832 :         else if (uid==39 || uid==37 || uid==31 || uid==13 ) return data[8];
     391              :         // [0112] [1012] [0121] [1021] [1201] [1210] [2101] [2110]
     392     16632768 :         else if (uid==66 || uid==48 || uid==64 || uid==46 || uid==34 || uid==16 || uid==32 || uid==14 ) return data[9];
     393              :         // [0122] [1022] [2201] [2210]
     394     13860640 :         else if (uid==75 || uid==73 || uid==35 || uid==17 ) return data[10];
     395              :         // [0202] [2002] [0220] [2020]
     396     12474576 :         else if (uid==60 || uid==24 || uid==56 || uid==20 ) return data[11];
     397              :         // [0211] [2011] [1102] [1120]
     398     11088512 :         else if (uid==42 || uid==58 || uid==22 || uid==38 ) return data[12];
     399              :         // [0212] [2012] [0221] [2021] [1202] [1220] [2102] [2120]
     400      9702448 :         else if (uid==69 || uid==51 || uid==61 || uid==25 || uid==65 || uid==47 || uid==59 || uid==23 ) return data[13];
     401              :         // [0222] [2022] [2202] [2220]
     402      6930320 :         else if (uid==78 || uid==74 || uid==62 || uid==26 ) return data[14];
     403              :         // [1111]
     404      5544256 :         else if (uid==40 ) return data[15];
     405              :         // [1112] [1121] [1211] [2111]
     406      5197740 :         else if (uid==67 || uid==49 || uid==43 || uid==41 ) return data[16];
     407              :         // [1122] [2211]
     408      3811676 :         else if (uid==76 || uid==44 ) return data[17];
     409              :         // [1212] [2112] [1221] [2121]
     410      3118644 :         else if (uid==70 || uid==52 || uid==68 || uid==50 ) return data[18];
     411              :         // [1222] [2122] [2212] [2221]
     412      1732580 :         else if (uid==79 || uid==77 || uid==71 || uid==53 ) return data[19];
     413              :         // [2222]
     414       346516 :         else if (uid==80 ) return data[20];
     415            0 :         else Util::Abort(INFO,"Index out of range");
     416            0 :         return Set::Garbage; 
     417              :     }
     418            0 :     void Print (std::ostream& os)
     419              :     {
     420            0 :         for (int i = 0; i < 21; i++)
     421            0 :             os << "i = " << i << " " << data[i] << std::endl;
     422              :         
     423            0 :         os.precision(4);
     424            0 :         for (int k = 0; k < 3; k++)
     425              :         {
     426            0 :             for (int i = -1; i < 4; i++)
     427              :             {
     428            0 :                 for (int l = 0; l < 3; l++)
     429              :                 {
     430            0 :                     if (i==-1)       os << "┌                                     ┐ ";
     431            0 :                     else if (i == 3) os << "└                                     ┘ ";
     432              :                     else 
     433              :                     {
     434            0 :                         os << "│ ";
     435            0 :                         for (int j = 0; j < 3; j++)
     436              :                         {
     437            0 :                             const Set::Scalar &val = (*this)(i,j,k,l);
     438            0 :                             os << std::scientific << std::setw(11) << val ; //(fabs(val)>1E-10 ? val : 0);
     439            0 :                             os << " "; 
     440              :                         }
     441            0 :                         os << "│ ";
     442              :                     }
     443              :                 }
     444            0 :                 os<<std::endl;
     445              :             }
     446              :         }
     447            0 :     }
     448              : 
     449              :     Set::Scalar Norm()
     450              :     {
     451              :         Set::Scalar retsq = 0;
     452              :         for (int i = 0; i < 21; i++) retsq += data[i];
     453              :         return std::sqrt(retsq);
     454              :     }
     455              :     bool contains_nan() const
     456              :     {
     457              :         if (std::isnan(data[ 0])) return true;
     458              :         if (std::isnan(data[ 1])) return true;
     459              :         if (std::isnan(data[ 2])) return true;
     460              :         if (std::isnan(data[ 3])) return true;
     461              :         if (std::isnan(data[ 4])) return true;
     462              :         if (std::isnan(data[ 5])) return true;
     463              :         if (std::isnan(data[ 6])) return true;
     464              :         if (std::isnan(data[ 7])) return true;
     465              :         if (std::isnan(data[ 8])) return true;
     466              :         if (std::isnan(data[ 9])) return true;
     467              :         if (std::isnan(data[10])) return true;
     468              :         if (std::isnan(data[11])) return true;
     469              :         if (std::isnan(data[12])) return true;
     470              :         if (std::isnan(data[13])) return true;
     471              :         if (std::isnan(data[14])) return true;
     472              :         if (std::isnan(data[15])) return true;
     473              :         if (std::isnan(data[16])) return true;
     474              :         if (std::isnan(data[17])) return true;
     475              :         if (std::isnan(data[18])) return true;
     476              :         if (std::isnan(data[19])) return true;
     477              :         if (std::isnan(data[20])) return true;
     478              :         return false;
     479              :     }
     480              : 
     481              :     //AMREX_GPU_HOST_DEVICE void operator  = (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] = a.data[i];}
     482         2750 :     AMREX_GPU_HOST_DEVICE void operator += (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] += a.data[i];}
     483              :     AMREX_GPU_HOST_DEVICE void operator -= (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] -= a.data[i];}
     484              :     AMREX_GPU_HOST_DEVICE void operator *= (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] *= a.data[i];}
     485              :     AMREX_GPU_HOST_DEVICE void operator /= (Matrix4<3,Sym::MajorMinor> a) {for (int i = 0; i < 21; i++) data[i] /= a.data[i];}
     486              :     AMREX_GPU_HOST_DEVICE void operator *= (Set::Scalar alpha) {for (int i = 0; i < 21; i++) data[i] *= alpha;}
     487              :     AMREX_GPU_HOST_DEVICE void operator /= (Set::Scalar alpha) {for (int i = 0; i < 21; i++) data[i] /= alpha;}
     488              : 
     489              :     static Matrix4<3,Sym::MajorMinor> Increment()
     490              :     {
     491              :         Matrix4<3,Sym::MajorMinor> ret;
     492              :         for (int i = 0 ; i < 21; i++) ret.data[i] = (Set::Scalar)i;
     493              :         return ret;
     494              :     }
     495            2 :     static Matrix4<3,Sym::MajorMinor> Randomize()
     496              :     {
     497            2 :         Matrix4<3,Sym::MajorMinor> ret;
     498           44 :         for (int i = 0 ; i < 21; i++) ret.data[i] = (Util::Random());
     499            2 :         return ret;
     500              :     }
     501          323 :     static Matrix4<3,Sym::MajorMinor> Zero()
     502              :     {
     503          323 :         Matrix4<3,Sym::MajorMinor> ret;
     504         7106 :         for (int i = 0 ; i < 21; i++) ret.data[i] = 0.0;
     505          323 :         return ret;
     506              :     }
     507         3906 :     static Matrix4<3,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44, 
     508              :                                             Eigen::Matrix3d R = Eigen::Matrix3d::Identity())
     509              :     {
     510         3906 :         Set::Matrix4<3,Sym::MajorMinor> ret;
     511              :         Set::Scalar Ctmp[3][3][3][3];
     512              : 
     513        15624 :         for(int i = 0; i < 3; i++) 
     514        46872 :             for(int j = 0; j < 3; j++) 
     515       140616 :                 for(int k = 0; k < 3; k++) 
     516       421848 :                     for(int l = 0; l < 3; l++)
     517              :                     {
     518       316386 :                         if(i == j && j == k && k == l)  Ctmp[i][j][k][l] = C11;
     519       304668 :                         else if (i==k && j==l) Ctmp[i][j][k][l] = C44;
     520       281232 :                         else if (i==j && k==l) Ctmp[i][j][k][l] = C12;
     521       257796 :                         else Ctmp[i][j][k][l] = 0.0;
     522              :                     }
     523        15624 :         for(int p = 0; p < 3; p++) 
     524        46872 :             for(int q = 0; q < 3; q++) 
     525       140616 :                 for(int s = 0; s < 3; s++) 
     526       421848 :                     for(int t = 0; t < 3; t++)
     527              :                     {
     528       316386 :                         ret(p,q,s,t) = 0.0;
     529      1265544 :                         for(int i = 0; i < 3; i++) 
     530      3796632 :                             for(int j = 0; j < 3; j++) 
     531     11389896 :                                 for(int k = 0; k < 3; k++) 
     532     34169688 :                                     for(int l = 0; l < 3; l++) 
     533     51254532 :                                         ret(p,q,s,t) += R(p,i)*R(s,k)*Ctmp[i][j][k][l]*R(q,j)*R(t,l);
     534              :                     }                
     535         7812 :         return ret;
     536              :     }
     537           46 :     static Matrix4<3,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44, 
     538              :                                             Set::Scalar phi1, Set::Scalar Phi, Set::Scalar phi2)
     539              :     {
     540           46 :         Eigen::Matrix3d R;
     541           46 :         R = Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
     542           92 :             Eigen::AngleAxisd(Phi,  Eigen::Vector3d::UnitZ()) *
     543           92 :             Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
     544           46 :         return Matrix4<3,Sym::MajorMinor>::Cubic(C11,C12,C44,R);
     545              :     }
     546         3860 :     static Matrix4<3,Sym::MajorMinor> Cubic(Set::Scalar C11, Set::Scalar C12, Set::Scalar C44, 
     547              :                                             Set::Quaternion q)
     548              :     {
     549         3860 :         Eigen::Matrix3d R = q.normalized().toRotationMatrix();
     550         3860 :         return Cubic(C11,C12,C44,R);
     551              :     }
     552              : 
     553           23 :     static Matrix4<3,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Eigen::Matrix3d R = Eigen::Matrix3d::Identity())
     554              :     {
     555           23 :         Set::Matrix4<3,Sym::MajorMinor> ret;
     556           23 :         Set::Scalar Ctmp[3][3][3][3] = {{{{0.0}}}};
     557              : 
     558           92 :         for(int i = 0; i < 3; i++)
     559          276 :             for(int j = 0; j < 3; j++)
     560          828 :                 for(int k = 0; k < 3; k++)
     561         2484 :                     for(int l = 0; l < 3; l++)
     562              :                     {
     563         1863 :                         if(i==j && j==k && k==l)
     564              :                         {
     565           69 :                             if      (i < 2)   Ctmp[i][j][k][l] = C11;
     566           23 :                             else              Ctmp[i][j][k][l] = C33;
     567              :                         }
     568         1794 :                         else if(i==j && k==l)
     569              :                         {
     570          138 :                             if      (i<2 && k<2 && i!=k) Ctmp[i][j][k][l] = C12;
     571           92 :                             else if ((i<2 && k==2) || (i==2 && k<2)) Ctmp[i][j][k][l] = C13;
     572              :                         }
     573         1656 :                         else if((i==k && j==l) && (i!=j))
     574              :                         {
     575          138 :                             Ctmp[i][j][k][l] = C44;
     576              :                         }
     577              :                         else
     578              :                         {
     579         1518 :                             Ctmp[i][j][k][l] = 0.0;
     580              :                         }
     581              :                     }
     582              : 
     583              :         // C66 = 0.5*(C11 - C12)
     584           23 :         Ctmp[0][1][0][1] = 0.5 * (C11 - C12);
     585           23 :         Ctmp[1][0][1][0] = 0.5 * (C11 - C12);
     586              : 
     587           92 :         for(int p = 0; p < 3; p++)
     588          276 :             for(int q = 0; q < 3; q++)
     589          828 :                 for(int s = 0; s < 3; s++)
     590         2484 :                     for(int t = 0; t < 3; t++)
     591              :                     {
     592         1863 :                         ret(p,q,s,t) = 0.0;
     593         7452 :                         for(int i = 0; i < 3; i++)
     594        22356 :                             for(int j = 0; j < 3; j++)
     595        67068 :                                 for(int k = 0; k < 3; k++)
     596       201204 :                                     for(int l = 0; l < 3; l++)
     597       301806 :                                         ret(p,q,s,t) += R(p,i)*R(s,k)*Ctmp[i][j][k][l]*R(q,j)*R(t,l);
     598              :                     }
     599           46 :         return ret;
     600              :     }
     601           22 :     static Matrix4<3,Sym::MajorMinor> Transverse(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Set::Scalar phi1, Set::Scalar Phi, Set::Scalar phi2)
     602              :     {
     603              :         Eigen::Quaterniond q =
     604           22 :             Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
     605           22 :             Eigen::AngleAxisd(Phi,  Eigen::Vector3d::UnitZ()) *
     606           44 :             Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
     607           22 :         Eigen::Matrix3d R = q.toRotationMatrix();
     608           22 :         return Matrix4<3,Sym::MajorMinor>::Transverse(C11,C12,C13,C33,C44,R);
     609              :     }
     610              :     static Matrix4<3,Sym::MajorMinor> Trans(Set::Scalar C11, Set::Scalar C12, Set::Scalar C13, Set::Scalar C33, Set::Scalar C44, Set::Quaternion q)
     611              :     {
     612              :         Eigen::Matrix3d R = q.normalized().toRotationMatrix();
     613              :         return Transverse(C11,C12,C13,C33,C44,R);
     614              :     }
     615              : 
     616              :     friend bool operator == (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b);
     617              :     friend Matrix4<3,Sym::MajorMinor> operator + (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b);
     618              :     friend Matrix4<3,Sym::MajorMinor> operator - (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b);
     619              :     friend Matrix4<3,Sym::MajorMinor> operator * (Matrix4<3,Sym::MajorMinor> a, Set::Scalar b);
     620              :     friend Matrix4<3,Sym::MajorMinor> operator * (Set::Scalar b, Matrix4<3,Sym::MajorMinor> a);
     621              :     friend Matrix4<3,Sym::MajorMinor> operator / (Matrix4<3,Sym::MajorMinor> a, Set::Scalar b);
     622              :     friend Set::Vector operator * (Matrix4<3,Sym::MajorMinor> a, Set::Matrix3 b);
     623              :     friend Eigen::Matrix<amrex::Real,3,3> operator * (Matrix4<3,Sym::MajorMinor> a, Eigen::Matrix<amrex::Real,3,3> b);
     624              : };
     625              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     626              : bool operator == (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b)
     627              : {
     628          550 :     for (int i = 0 ; i < 21 ; i++) if (a.data[i] != b.data[i]) return false;
     629           25 :     return true;
     630              : }
     631              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     632              : Matrix4<3,Sym::MajorMinor> operator + (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b)
     633              : {
     634         9800 :     Matrix4<3,Sym::MajorMinor> ret;
     635       215600 :     for (int i = 0 ; i < 21 ; i++) ret.data[i] = a.data[i] + b.data[i];
     636         9800 :     return ret;
     637              : }
     638              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     639              : Matrix4<3,Sym::MajorMinor> operator - (Matrix4<3,Sym::MajorMinor> a, Matrix4<3,Sym::MajorMinor> b)
     640              : {
     641       294597 :     Matrix4<3,Sym::MajorMinor> ret;
     642      6481134 :     for (int i = 0 ; i < 21 ; i++) ret.data[i] = a.data[i] - b.data[i];
     643       294597 :     return ret;
     644              : }
     645              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     646              : Matrix4<3,Sym::MajorMinor> operator * (Matrix4<3,Sym::MajorMinor> a, Set::Scalar b)
     647              : {
     648       301332 :     Matrix4<3,Sym::MajorMinor> ret;
     649      6629304 :     for (int i = 0 ; i < 21 ; i++) ret.data[i] = a.data[i] * b;
     650       301332 :     return ret;
     651              : }
     652              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     653              : Matrix4<3,Sym::MajorMinor> operator * (Set::Scalar b,Matrix4<3,Sym::MajorMinor> a)
     654              : {
     655            0 :     return a*b;
     656              : }
     657              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     658              : Matrix4<3,Sym::MajorMinor> operator / (Matrix4<3,Sym::MajorMinor> a, Set::Scalar b)
     659              : {
     660       295597 :     Matrix4<3,Sym::MajorMinor> ret;
     661      6503134 :     for (int i = 0 ; i < 21 ; i++) ret.data[i] = a.data[i] / b;
     662       295597 :     return ret;
     663              : }
     664              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     665              : Eigen::Matrix<amrex::Real,3,3> operator * (Matrix4<3,Sym::MajorMinor> a, Eigen::Matrix<amrex::Real,3,3> b)
     666              : {
     667      1413576 :     Eigen::Matrix<amrex::Real,3,3> ret = Eigen::Matrix<amrex::Real,3,3>::Zero();
     668      1413576 :     ret(0,0) += a.data[   0]*b(0,0) + a.data[   1]*(b(0,1) + b(1,0)) + a.data[   2]*(b(0,2) + b(2,0)) + a.data[   3]*b(1,1) + a.data[   4]*(b(1,2) + b(2,1)) + a.data[   5]*b(2,2);
     669      1413576 :         ret(1,1) += a.data[   3]*b(0,0) + a.data[   8]*(b(0,1) + b(1,0)) + a.data[  12]*(b(0,2) + b(2,0)) + a.data[  15]*b(1,1) + a.data[  16]*(b(1,2) + b(2,1)) + a.data[  17]*b(2,2);
     670      1413576 :     ret(2,2) += a.data[   5]*b(0,0) + a.data[  10]*(b(0,1) + b(1,0)) + a.data[  14]*(b(0,2) + b(2,0)) + a.data[  17]*b(1,1) + a.data[  19]*(b(1,2) + b(2,1)) + a.data[  20]*b(2,2);
     671      1413576 :     ret(1,2) += a.data[   4]*b(0,0) + a.data[   9]*(b(0,1) + b(1,0)) + a.data[  13]*(b(0,2) + b(2,0)) + a.data[  16]*b(1,1) + a.data[  18]*(b(1,2) + b(2,1)) + a.data[  19]*b(2,2);
     672      1413576 :     ret(2,0) += a.data[   2]*b(0,0) + a.data[   7]*(b(0,1) + b(1,0)) + a.data[  11]*(b(0,2) + b(2,0)) + a.data[  12]*b(1,1) + a.data[  13]*(b(1,2) + b(2,1)) + a.data[  14]*b(2,2);
     673      1413576 :     ret(0,1) += a.data[   1]*b(0,0) + a.data[   6]*(b(0,1) + b(1,0)) + a.data[   7]*(b(0,2) + b(2,0)) + a.data[   8]*b(1,1) + a.data[   9]*(b(1,2) + b(2,1)) + a.data[  10]*b(2,2);
     674              : 
     675      1413576 :     ret(2,1) = ret(1,2);
     676      1413576 :     ret(0,2) = ret(2,0);
     677      1413576 :     ret(1,0) = ret(0,1);
     678              : 
     679      1413576 :     return ret;
     680              : }
     681              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     682              : Eigen::Matrix<amrex::Real,2,2> operator * (Matrix4<3,Sym::MajorMinor> a, Eigen::Matrix<amrex::Real,2,2> b)
     683              : {
     684              :         Eigen::Matrix<amrex::Real,2,2> ret = Eigen::Matrix<amrex::Real,2,2>::Zero();
     685              :     for (int i = 0; i < 2; i++)
     686              :         for (int j = 0; j < 2; j++)
     687              :             for (int k = 0; k < 2; k++)
     688              :                 for (int l = 0; l < 2; l++)
     689              :                     ret(i,j) += a(i,j,k,l)*b(k,l);
     690              :     return ret;
     691              : }
     692              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     693              : Eigen::Matrix<amrex::Real,3,1> operator * (Matrix4<3,Sym::MajorMinor> a, std::array<Eigen::Matrix<amrex::Real,3,3>,3> b);
     694              : 
     695              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     696              : Eigen::Matrix<amrex::Real,2,1> operator * (Matrix4<3,Sym::MajorMinor> a, std::array<Eigen::Matrix<amrex::Real,2,2>,2> b);
     697              : 
     698              : AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE 
     699              : Set::Vector operator * (Matrix4<3,Sym::MajorMinor> a, Set::Matrix3 b)
     700              : {
     701              :     // TODO: improve efficiency of this method
     702       106599 :     Set::Vector ret = Set::Vector::Zero();
     703              :     
     704       213198 :     ret(0) += 
     705       106599 :     a.data[   0]*b(0,0,0) + 
     706       319797 :     a.data[   1]*(b(0,1,0) + b(1,0,0) + b(0,0,1)) + 
     707       319797 :     a.data[   2]*(b(0,2,0) + b(2,0,0) + b(0,0,2)) + 
     708       106599 :     a.data[   3]*b(1,1,0) + 
     709       213198 :     a.data[   4]*(b(1,2,0) + b(2,1,0)) + 
     710       106599 :     a.data[   5]*b(2,2,0) + 
     711       213198 :     a.data[   6]*(b(0,1,1) + b(1,0,1)) + 
     712       426396 :     a.data[   7]*(b(0,2,1) + b(2,0,1) + b(0,1,2) + b(1,0,2)) + 
     713       106599 :     a.data[   8]*b(1,1,1) + 
     714       213198 :     a.data[   9]*(b(1,2,1) + b(2,1,1)) + 
     715       106599 :     a.data[  10]*b(2,2,1) + 
     716       213198 :     a.data[  11]*(b(0,2,2) + b(2,0,2)) + 
     717       106599 :     a.data[  12]*b(1,1,2) + 
     718       213198 :     a.data[  13]*(b(1,2,2) + b(2,1,2)) + 
     719       213198 :     a.data[  14]*b(2,2,2);
     720              :     
     721       213198 :     ret(1) += 
     722       106599 :     a.data[   1]*b(0,0,0) + 
     723       106599 :     a.data[   4]*b(0,0,2) + 
     724       106599 :     a.data[   3]*b(0,0,1) + 
     725       213198 :     a.data[   6]*(b(0,1,0) + b(1,0,0)) + 
     726       213198 :     a.data[   7]*(b(0,2,0) + b(2,0,0)) + 
     727       319797 :     a.data[   8]*(b(1,1,0) + b(0,1,1) + b(1,0,1)) + 
     728       426396 :     a.data[   9]*(b(1,2,0) + b(2,1,0) + b(0,1,2) + b(1,0,2)) + 
     729       106599 :     a.data[  10]*b(2,2,0) + 
     730       213198 :     a.data[  12]*(b(0,2,1) + b(2,0,1)) + 
     731       213198 :     a.data[  13]*(b(0,2,2) + b(2,0,2)) + 
     732       106599 :     a.data[  15]*b(1,1,1) + 
     733       319797 :     a.data[  16]*(b(1,2,1) + b(2,1,1) + b(1,1,2)) + 
     734       106599 :     a.data[  17]*b(2,2,1) + 
     735       213198 :     a.data[  18]*(b(1,2,2) + b(2,1,2)) + 
     736       213198 :     a.data[  19]*b(2,2,2);
     737              : 
     738       213198 :     ret(2) += 
     739       106599 :     a.data[   2]*b(0,0,0) + 
     740       106599 :     a.data[   4]*b(0,0,1) + 
     741       106599 :     a.data[   5]*b(0,0,2) + 
     742       213198 :     a.data[   7]*(b(0,1,0) + b(1,0,0)) + 
     743       213198 :     a.data[   9]*(b(0,1,1) + b(1,0,1)) + 
     744       213198 :     a.data[  10]*(b(0,1,2) + b(1,0,2)) + 
     745       213198 :     a.data[  11]*(b(0,2,0) + b(2,0,0)) + 
     746       106599 :     a.data[  12]*b(1,1,0) + 
     747       426396 :     a.data[  13]*(b(1,2,0) + b(2,1,0) + b(0,2,1) + b(2,0,1)) + 
     748       319797 :     a.data[  14]*(b(2,2,0) + b(0,2,2) + b(2,0,2)) + 
     749       106599 :     a.data[  16]*b(1,1,1) + 
     750       106599 :     a.data[  17]*b(1,1,2) + 
     751       213198 :     a.data[  18]*(b(1,2,1) + b(2,1,1)) + 
     752       319797 :     a.data[  19]*(b(2,2,1) + b(1,2,2) + b(2,1,2)) + 
     753       213198 :     a.data[  20]*b(2,2,2);
     754              : 
     755       106599 :     return ret;
     756              : }
     757              : 
     758              : }
     759              : #endif
        

Generated by: LCOV version 2.0-1