LCOV - code coverage report
Current view: top level - include/utils - SymmetricRankFourTensor.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 73 82 89.0 %
Date: 2025-07-17 01:28:37 Functions: 25 58 43.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include "Moose.h"
      13             : #include "ADRankTwoTensorForward.h"
      14             : #include "ADRankFourTensorForward.h"
      15             : #include "ADSymmetricRankTwoTensorForward.h"
      16             : #include "ADSymmetricRankFourTensorForward.h"
      17             : #include "MooseUtils.h"
      18             : #include "MathUtils.h"
      19             : 
      20             : #include "libmesh/libmesh.h"
      21             : #include "libmesh/tuple_of.h"
      22             : #include "libmesh/int_range.h"
      23             : 
      24             : #include "metaphysicl/raw_type.h"
      25             : 
      26             : #include <petscsys.h>
      27             : 
      28             : // Eigen includes
      29             : #include <Eigen/Core>
      30             : #include <Eigen/Dense>
      31             : 
      32             : #include <array>
      33             : 
      34             : using libMesh::Real;
      35             : using libMesh::tuple_of;
      36             : namespace libMesh
      37             : {
      38             : template <typename>
      39             : class TensorValue;
      40             : template <typename>
      41             : class TypeTensor;
      42             : template <typename>
      43             : class VectorValue;
      44             : }
      45             : 
      46             : // Forward declarations
      47             : class MooseEnum;
      48             : 
      49             : namespace boostcopy = libMesh::boostcopy;
      50             : 
      51             : namespace MathUtils
      52             : {
      53             : /**
      54             :  * Helper function template specialization to set an object to zero.
      55             :  * Needed by DerivativeMaterialInterface
      56             :  */
      57             : template <>
      58             : void mooseSetToZero<SymmetricRankFourTensor>(SymmetricRankFourTensor & v);
      59             : template <>
      60             : void mooseSetToZero<ADSymmetricRankFourTensor>(ADSymmetricRankFourTensor & v);
      61             : }
      62             : 
      63             : /**
      64             :  * SymmetricRankFourTensorTempl is designed to handle an N-dimensional fourth order tensor with
      65             :  * minor symmetry, C. Since N is hard-coded to 3, SymmetricRankFourTensorTempl holds 36 separate
      66             :  * C_ij entries. Within the code i,j = 0, .., 5.
      67             :  */
      68             : template <typename T>
      69             : class SymmetricRankFourTensorTempl
      70             : {
      71             : public:
      72             :   ///@{ tensor dimension, Mandel matrix dimension, and Mandel matrix size
      73             :   static constexpr unsigned int Ndim = LIBMESH_DIM;
      74             :   static constexpr unsigned int N = Ndim + Ndim * (Ndim - 1) / 2;
      75             :   static constexpr unsigned int N2 = N * N;
      76             :   ///@}
      77             : 
      78             :   // Full tensor indices in the Mandel/Voigt representation
      79             :   static constexpr unsigned int full_index[6][6][4] = {
      80             :       {{0, 0, 0, 0}, {0, 0, 1, 1}, {0, 0, 2, 2}, {0, 0, 1, 2}, {0, 0, 0, 2}, {0, 0, 0, 1}},
      81             :       {{1, 1, 0, 0}, {1, 1, 1, 1}, {1, 1, 2, 2}, {1, 1, 1, 2}, {1, 1, 0, 2}, {1, 1, 0, 1}},
      82             :       {{2, 2, 0, 0}, {2, 2, 1, 1}, {2, 2, 2, 2}, {2, 2, 1, 2}, {2, 2, 0, 2}, {2, 2, 0, 1}},
      83             :       {{1, 2, 0, 0}, {1, 2, 1, 1}, {1, 2, 2, 2}, {1, 2, 1, 2}, {1, 2, 0, 2}, {1, 2, 0, 1}},
      84             :       {{0, 2, 0, 0}, {0, 2, 1, 1}, {0, 2, 2, 2}, {0, 2, 1, 2}, {0, 2, 0, 2}, {0, 2, 0, 1}},
      85             :       {{0, 1, 0, 0}, {0, 1, 1, 1}, {0, 1, 2, 2}, {0, 1, 1, 2}, {0, 1, 0, 2}, {0, 1, 0, 1}}};
      86             : 
      87             :   /// returns the 1, sqrt(2), or 2 prefactor in the Mandel notation for the indices i,j ranging from 0-5.
      88        6192 :   static constexpr Real mandelFactor(unsigned int i, unsigned int j)
      89             :   {
      90        6192 :     return SymmetricRankTwoTensorTempl<T>::mandelFactor(i) *
      91        6192 :            SymmetricRankTwoTensorTempl<T>::mandelFactor(j);
      92             :   }
      93             : 
      94             :   /// Initialization method
      95             :   enum InitMethod
      96             :   {
      97             :     initNone,
      98             :     initIdentity,
      99             :     initIdentitySymmetricFour
     100             :   };
     101             : 
     102             :   /**
     103             :    * To fill up the 36 entries in the 4th-order tensor, fillFromInputVector
     104             :    * is called with one of the following fill_methods.
     105             :    * See the fill*FromInputVector functions for more details
     106             :    */
     107             :   enum FillMethod
     108             :   {
     109             :     symmetric9,               // fillSymmetric9FromInputVector
     110             :     symmetric21,              // fillSymmetric21FromInputVector
     111             :     symmetric_isotropic,      // fillSymmetricIsotropicFromInputVector
     112             :     symmetric_isotropic_E_nu, // fillSymmetricIsotropicEandNu
     113             :     axisymmetric_rz,          // fillAxisymmetricRZFromInputVector
     114             :     principal,                // fillPrincipalFromInputVector
     115             :     orthotropic               // fillGeneralOrthotropicFromInputVector
     116             :   };
     117             : 
     118             :   template <template <typename> class Tensor, typename Scalar>
     119             :   struct TwoTensorMultTraits
     120             :   {
     121             :     static const bool value = false;
     122             :   };
     123             :   template <typename Scalar>
     124             :   struct TwoTensorMultTraits<SymmetricRankTwoTensorTempl, Scalar>
     125             :   {
     126             :     static const bool value = libMesh::ScalarTraits<Scalar>::value;
     127             :   };
     128             :   template <typename Scalar>
     129             :   struct TwoTensorMultTraits<TensorValue, Scalar>
     130             :   {
     131             :     static const bool value = libMesh::ScalarTraits<Scalar>::value;
     132             :   };
     133             :   template <typename Scalar>
     134             :   struct TwoTensorMultTraits<TypeTensor, Scalar>
     135             :   {
     136             :     static const bool value = libMesh::ScalarTraits<Scalar>::value;
     137             :   };
     138             : 
     139             :   /// Default constructor; fills to zero
     140             :   SymmetricRankFourTensorTempl();
     141             : 
     142             :   /// Select specific initialization pattern
     143             :   SymmetricRankFourTensorTempl(const InitMethod);
     144             : 
     145             :   /// Fill from vector
     146             :   SymmetricRankFourTensorTempl(const std::vector<T> &, FillMethod);
     147             : 
     148             :   /// Copy assignment operator must be defined if used
     149           0 :   SymmetricRankFourTensorTempl(const SymmetricRankFourTensorTempl<T> & a) = default;
     150             : 
     151             :   /**
     152             :    * Copy constructor
     153             :    */
     154             :   template <typename T2>
     155             :   SymmetricRankFourTensorTempl(const SymmetricRankFourTensorTempl<T2> & copy);
     156             : 
     157             :   /// Copy constructor from RankFourTensorTempl<T>
     158             :   explicit SymmetricRankFourTensorTempl(const RankFourTensorTempl<T> & a);
     159             : 
     160             :   /// The conversion operator to `RankFourTensorTempl`
     161             :   explicit operator RankFourTensorTempl<T>();
     162             : 
     163             :   // Named constructors
     164           0 :   static SymmetricRankFourTensorTempl<T> identity()
     165             :   {
     166           0 :     return SymmetricRankFourTensorTempl<T>(initIdentity);
     167             :   }
     168           0 :   static SymmetricRankFourTensorTempl<T> identitySymmetricFour()
     169             :   {
     170           0 :     return SymmetricRankFourTensorTempl<T>(initIdentitySymmetricFour);
     171             :   };
     172             : 
     173             :   /// Gets the value for the indices specified. Takes indices ranging from 0-5 for i and j.
     174    13530306 :   inline T & operator()(unsigned int i, unsigned int j) { return _vals[i * N + j]; }
     175             : 
     176             :   /**
     177             :    * Gets the value for the indices specified. Takes indices ranging from 0-5 for i and j.
     178             :    * used for const
     179             :    */
     180        1521 :   inline const T & operator()(unsigned int i, unsigned int j) const { return _vals[i * N + j]; }
     181             : 
     182             :   /// Zeros out the tensor.
     183             :   void zero();
     184             : 
     185             :   /// Print the rank four tensor
     186             :   void print(std::ostream & stm = Moose::out) const;
     187             : 
     188             :   /// Print the values of the rank four tensor
     189             :   void printReal(std::ostream & stm = Moose::out) const;
     190             : 
     191             :   friend std::ostream & operator<<(std::ostream & os, const SymmetricRankFourTensorTempl<T> & t)
     192             :   {
     193             :     t.print(os);
     194             :     return os;
     195             :   }
     196             : 
     197             :   /// copies values from a into this tensor
     198      345601 :   SymmetricRankFourTensorTempl<T> & operator=(const SymmetricRankFourTensorTempl<T> & a) = default;
     199             : 
     200             :   /**
     201             :    * Assignment-from-scalar operator.  Used only to zero out the tensor.
     202             :    *
     203             :    * \returns A reference to *this.
     204             :    */
     205             :   template <typename Scalar>
     206             :   typename boostcopy::enable_if_c<libMesh::ScalarTraits<Scalar>::value,
     207             :                                   SymmetricRankFourTensorTempl &>::type
     208             :   operator=(const Scalar & libmesh_dbg_var(p))
     209             :   {
     210             :     libmesh_assert_equal_to(p, Scalar(0));
     211             :     this->zero();
     212             :     return *this;
     213             :   }
     214             : 
     215             :   /// C_ijkl*a_kl
     216             :   template <typename T2>
     217             :   auto operator*(const SymmetricRankTwoTensorTempl<T2> & b) const
     218             :       -> SymmetricRankTwoTensorTempl<decltype(T() * T2())>;
     219             : 
     220             :   /// C_ijkl*a
     221             :   template <typename T2>
     222             :   auto operator*(const T2 & a) const ->
     223             :       typename std::enable_if<libMesh::ScalarTraits<T2>::value,
     224             :                               SymmetricRankFourTensorTempl<decltype(T() * T2())>>::type;
     225             : 
     226             :   /// C_ijkl *= a
     227             :   SymmetricRankFourTensorTempl<T> & operator*=(const T & a);
     228             : 
     229             :   /// C_ijkl/a
     230             :   template <typename T2>
     231             :   auto operator/(const T2 & a) const ->
     232             :       typename std::enable_if<libMesh::ScalarTraits<T2>::value,
     233             :                               SymmetricRankFourTensorTempl<decltype(T() / T2())>>::type;
     234             : 
     235             :   /// C_ijkl /= a  for all i, j, k, l
     236             :   SymmetricRankFourTensorTempl<T> & operator/=(const T & a);
     237             : 
     238             :   /// C_ijkl += a_ijkl  for all i, j, k, l
     239             :   SymmetricRankFourTensorTempl<T> & operator+=(const SymmetricRankFourTensorTempl<T> & a);
     240             : 
     241             :   /// C_ijkl + a_ijkl
     242             :   template <typename T2>
     243             :   auto operator+(const SymmetricRankFourTensorTempl<T2> & a) const
     244             :       -> SymmetricRankFourTensorTempl<decltype(T() + T2())>;
     245             : 
     246             :   /// C_ijkl -= a_ijkl
     247             :   SymmetricRankFourTensorTempl<T> & operator-=(const SymmetricRankFourTensorTempl<T> & a);
     248             : 
     249             :   /// C_ijkl - a_ijkl
     250             :   template <typename T2>
     251             :   auto operator-(const SymmetricRankFourTensorTempl<T2> & a) const
     252             :       -> SymmetricRankFourTensorTempl<decltype(T() - T2())>;
     253             : 
     254             :   /// -C_ijkl
     255             :   SymmetricRankFourTensorTempl<T> operator-() const;
     256             : 
     257             :   /// C_ijpq*a_pqkl
     258             :   template <typename T2>
     259             :   auto operator*(const SymmetricRankFourTensorTempl<T2> & a) const
     260             :       -> SymmetricRankFourTensorTempl<decltype(T() * T2())>;
     261             : 
     262             :   /// sqrt(C_ijkl*C_ijkl)
     263             :   T L2norm() const;
     264             : 
     265             :   /**
     266             :    * This returns A_ijkl such that C_ijkl*A_klmn = 0.5*(de_im de_jn + de_in de_jm)
     267             :    * This routine assumes that C_ijkl = C_jikl = C_ijlk
     268             :    */
     269             :   SymmetricRankFourTensorTempl<T> invSymm() const;
     270             : 
     271             :   /**
     272             :    * Build a 6x6 rotation matrix
     273             :    * MEHRABADI, MORTEZA M.; COWIN, STEPHEN C.  (1990). EIGENTENSORS OF LINEAR ANISOTROPIC ELASTIC
     274             :    * MATERIALS. The Quarterly Journal of Mechanics and Applied Mathematics, 43(1), 15-41.
     275             :    * doi:10.1093/qjmam/43.1.15
     276             :    */
     277             :   static SymmetricRankFourTensorTempl<T> rotationMatrix(const TypeTensor<T> & R);
     278             : 
     279             :   /**
     280             :    * Rotate the tensor using
     281             :    * C_ijkl = R_im R_jn R_ko R_lp C_mnop
     282             :    */
     283             :   void rotate(const TypeTensor<T> & R);
     284             : 
     285             :   /**
     286             :    * Transpose the tensor by swapping the first pair with the second pair of indices
     287             :    * This amounts to a regular transpose of the 6x6 matrix
     288             :    * @return C_klji
     289             :    */
     290             :   SymmetricRankFourTensorTempl<T> transposeMajor() const;
     291             : 
     292             :   /**
     293             :    * Transpose the tensor by swapping the first two indices - a no-op
     294             :    */
     295           0 :   SymmetricRankFourTensorTempl<T> transposeIj() const { return *this; }
     296             : 
     297             :   /// Static method for use in validParams for getting the "fill_method"
     298             :   static MooseEnum fillMethodEnum();
     299             : 
     300             :   /**
     301             :    * fillFromInputVector takes some number of inputs to fill
     302             :    * the Rank-4 tensor.
     303             :    * @param input the numbers that will be placed in the tensor
     304             :    * @param fill_method See FillMethod
     305             :    */
     306             :   void fillFromInputVector(const std::vector<T> & input, FillMethod fill_method);
     307             : 
     308             :   ///@{ Vector-less fill API functions. See docs of the corresponding ...FromInputVector methods
     309             :   void fillSymmetricIsotropic(const T & i0, const T & i1);
     310             :   void fillSymmetricIsotropicEandNu(const T & E, const T & nu);
     311             :   ///@}
     312             : 
     313             :   /**
     314             :    * fillSymmetric9FromInputVector takes 9 inputs to fill in
     315             :    * the Rank-4 tensor with the appropriate crystal symmetries maintained. I.e., C_ijkl = C_klij,
     316             :    * C_ijkl = C_ijlk, C_ijkl = C_jikl
     317             :    * @param input is:
     318             :    *                C1111 C1122 C1133 C2222 C2233 C3333 C2323 C1313 C1212
     319             :    *                In the isotropic case this is (la is first Lame constant, mu is second (shear)
     320             :    * Lame constant)
     321             :    *                la+2mu la la la+2mu la la+2mu mu mu mu
     322             :    */
     323             :   template <typename T2>
     324             :   void fillSymmetric9FromInputVector(const T2 & input);
     325             : 
     326             :   /**
     327             :    * fillSymmetric21FromInputVector takes 21 inputs to fill in the Rank-4 tensor with the
     328             :    * appropriate crystal symmetries maintained.
     329             :    * I.e., C_ijkl = C_klij, C_ijkl = C_ijlk, C_ijkl = C_jikl
     330             :    *
     331             :    * @param input is C1111 C1122 C1133 C1123 C1113 C1112 C2222 C2233 C2223 C2213 C2212 C3333 C3323
     332             :    * C3313 C3312 C2323 C2313 C2312 C1313 C1312 C1212
     333             :    */
     334             :   template <typename T2>
     335             :   void fillSymmetric21FromInputVector(const T2 & input);
     336             : 
     337             :   /// Calculates the sum of Ciijj for i and j varying from 0 to 2
     338             :   T sum3x3() const;
     339             : 
     340             :   /// Calculates the vector a[i] = sum over j Ciijj for i and j varying from 0 to 2
     341             :   libMesh::VectorValue<T> sum3x1() const;
     342             : 
     343             :   /// checks if the tensor is symmetric
     344             :   bool isSymmetric() const;
     345             : 
     346             :   /// checks if the tensor is isotropic
     347             :   bool isIsotropic() const;
     348             : 
     349             : protected:
     350             :   /// The values of the rank-four tensor
     351             :   std::array<T, N2> _vals;
     352             : 
     353             :   /**
     354             :    * fillSymmetricIsotropicFromInputVector takes 2 inputs to fill the
     355             :    * the symmetric Rank-4 tensor with the appropriate symmetries maintained.
     356             :    * C_ijkl = lambda*de_ij*de_kl + mu*(de_ik*de_jl + de_il*de_jk)
     357             :    * where lambda is the first Lame modulus, mu is the second (shear) Lame modulus,
     358             :    * @param input this is lambda and mu in the above formula
     359             :    */
     360             :   void fillSymmetricIsotropicFromInputVector(const std::vector<T> & input);
     361             : 
     362             :   /**
     363             :    * fillSymmetricIsotropicEandNuFromInputVector is a variation of the
     364             :    * fillSymmetricIsotropicFromInputVector which takes as inputs the
     365             :    * more commonly used Young's modulus (E) and Poisson's ratio (nu)
     366             :    * constants to fill the isotropic elasticity tensor. Using well-known formulas,
     367             :    * E and nu are used to calculate lambda and mu and then the vector is passed
     368             :    * to fillSymmetricIsotropicFromInputVector.
     369             :    * @param input Young's modulus (E) and Poisson's ratio (nu)
     370             :    */
     371             :   void fillSymmetricIsotropicEandNuFromInputVector(const std::vector<T> & input);
     372             : 
     373             :   /**
     374             :    * fillAxisymmetricRZFromInputVector takes 5 inputs to fill the axisymmetric
     375             :    * Rank-4 tensor with the appropriate symmetries maintatined for use with
     376             :    * axisymmetric problems using coord_type = RZ.
     377             :    * I.e. C1111 = C2222, C1133 = C2233, C2323 = C3131 and C1212 = 0.5*(C1111-C1122)
     378             :    * @param input this is C1111, C1122, C1133, C3333, C2323.
     379             :    */
     380             :   void fillAxisymmetricRZFromInputVector(const std::vector<T> & input);
     381             : 
     382             :   /**
     383             :    * fillPrincipalFromInputVector takes 9 inputs to fill a Rank-4 tensor
     384             :    * C1111 = input0
     385             :    * C1122 = input1
     386             :    * C1133 = input2
     387             :    * C2211 = input3
     388             :    * C2222 = input4
     389             :    * C2233 = input5
     390             :    * C3311 = input6
     391             :    * C3322 = input7
     392             :    * C3333 = input8
     393             :    * with all other components being zero
     394             :    */
     395             : 
     396             :   void fillPrincipalFromInputVector(const std::vector<T> & input);
     397             : 
     398             :   /**
     399             :    * fillGeneralOrhotropicFromInputVector takes 10  inputs to fill the Rank-4 tensor
     400             :    * It defines a general orthotropic tensor for which some constraints among
     401             :    * elastic parameters exist
     402             :    * @param input  Ea, Eb, Ec, Gab, Gbc, Gca, nuba, nuca, nucb, nuab, nuac, nubc
     403             :    */
     404             :   void fillGeneralOrthotropicFromInputVector(const std::vector<T> & input);
     405             : 
     406             :   template <class T2>
     407             :   friend void dataStore(std::ostream &, SymmetricRankFourTensorTempl<T2> &, void *);
     408             : 
     409             :   template <class T2>
     410             :   friend void dataLoad(std::istream &, SymmetricRankFourTensorTempl<T2> &, void *);
     411             : 
     412             :   template <typename T2>
     413             :   friend class SymmetricRankTwoTensorTempl;
     414             :   template <typename T2>
     415             :   friend class SymmetricRankFourTensorTempl;
     416             :   template <typename T2>
     417             :   friend class RankThreeTensorTempl;
     418             : };
     419             : 
     420             : namespace MetaPhysicL
     421             : {
     422             : template <typename T>
     423             : struct RawType<SymmetricRankFourTensorTempl<T>>
     424             : {
     425             :   typedef SymmetricRankFourTensorTempl<typename RawType<T>::value_type> value_type;
     426             : 
     427           4 :   static value_type value(const SymmetricRankFourTensorTempl<T> & in)
     428             :   {
     429           4 :     value_type ret;
     430          28 :     for (unsigned int i = 0; i < SymmetricRankFourTensorTempl<T>::N; ++i)
     431         168 :       for (unsigned int j = 0; j < SymmetricRankFourTensorTempl<T>::N; ++j)
     432         144 :         ret(i, j) = raw_value(in(i, j));
     433             : 
     434           4 :     return ret;
     435             :   }
     436             : };
     437             : }
     438             : 
     439             : template <typename T1, typename T2>
     440             : inline auto
     441           6 : operator*(const T1 & a, const SymmetricRankFourTensorTempl<T2> & b) ->
     442             :     typename std::enable_if<libMesh::ScalarTraits<T1>::value,
     443             :                             SymmetricRankFourTensorTempl<decltype(T1() * T2())>>::type
     444             : {
     445           6 :   return b * a;
     446             : }
     447             : 
     448             : template <typename T>
     449             : template <typename T2>
     450           3 : SymmetricRankFourTensorTempl<T>::SymmetricRankFourTensorTempl(
     451           3 :     const SymmetricRankFourTensorTempl<T2> & copy)
     452             : {
     453         111 :   for (const auto i : make_range(N2))
     454         108 :     _vals[i] = copy._vals[i];
     455           3 : }
     456             : 
     457             : template <typename T>
     458             : template <typename T2>
     459             : auto
     460           7 : SymmetricRankFourTensorTempl<T>::operator*(const T2 & b) const ->
     461             :     typename std::enable_if<libMesh::ScalarTraits<T2>::value,
     462             :                             SymmetricRankFourTensorTempl<decltype(T() * T2())>>::type
     463             : {
     464             :   typedef decltype(T() * T2()) ValueType;
     465           7 :   SymmetricRankFourTensorTempl<ValueType> result;
     466             : 
     467         259 :   for (const auto i : make_range(N2))
     468         252 :     result._vals[i] = _vals[i] * b;
     469             : 
     470           7 :   return result;
     471           0 : }
     472             : 
     473             : template <typename T>
     474             : template <typename T2>
     475             : auto
     476           2 : SymmetricRankFourTensorTempl<T>::operator*(const SymmetricRankTwoTensorTempl<T2> & b) const
     477             :     -> SymmetricRankTwoTensorTempl<decltype(T() * T2())>
     478             : {
     479             :   typedef decltype(T() * T2()) ValueType;
     480           2 :   SymmetricRankTwoTensorTempl<ValueType> result;
     481             : 
     482           2 :   std::size_t index = 0;
     483          14 :   for (const auto i : make_range(N))
     484             :   {
     485          12 :     ValueType tmp = 0.0;
     486          84 :     for (const auto j : make_range(N))
     487          72 :       tmp += _vals[index++] * b._vals[j];
     488          12 :     result._vals[i] = tmp;
     489             :   }
     490             : 
     491           2 :   return result;
     492           0 : }
     493             : 
     494             : template <typename T>
     495             : template <typename T2>
     496             : auto
     497           1 : SymmetricRankFourTensorTempl<T>::operator/(const T2 & b) const ->
     498             :     typename std::enable_if<libMesh::ScalarTraits<T2>::value,
     499             :                             SymmetricRankFourTensorTempl<decltype(T() / T2())>>::type
     500             : {
     501           1 :   SymmetricRankFourTensorTempl<decltype(T() / T2())> result;
     502          37 :   for (const auto i : make_range(N2))
     503          36 :     result._vals[i] = _vals[i] / b;
     504           1 :   return result;
     505             : }
     506             : 
     507             : template <typename T>
     508             : template <typename T2>
     509             : void
     510          21 : SymmetricRankFourTensorTempl<T>::fillSymmetric9FromInputVector(const T2 & input)
     511             : {
     512             :   mooseAssert(LIBMESH_DIM == 3, "This method assumes LIBMESH_DIM == 3");
     513             :   mooseAssert(input.size() == 9,
     514             :               "To use fillSymmetric9FromInputVector, your input must have size 9.");
     515          21 :   zero();
     516             : 
     517          21 :   _vals[0] = input[0];  // C1111
     518          21 :   _vals[7] = input[3];  // C2222
     519          21 :   _vals[14] = input[5]; // C3333
     520             : 
     521          21 :   _vals[1] = _vals[6] = input[1];  // C1122
     522          21 :   _vals[2] = _vals[12] = input[2]; // C1133
     523          21 :   _vals[8] = _vals[13] = input[4]; // C2233
     524             : 
     525             :   static constexpr std::size_t C2323 = 21;
     526             :   static constexpr std::size_t C1313 = 28;
     527             :   static constexpr std::size_t C1212 = 35;
     528             : 
     529          21 :   _vals[C2323] = 2.0 * input[6];
     530          21 :   _vals[C1313] = 2.0 * input[7];
     531          21 :   _vals[C1212] = 2.0 * input[8];
     532          21 : }
     533             : 
     534             : template <typename T>
     535             : template <typename T2>
     536             : void
     537          24 : SymmetricRankFourTensorTempl<T>::fillSymmetric21FromInputVector(const T2 & input)
     538             : {
     539             :   // C1111 C1122 C1133 C1123 C1113 C1112
     540             :   //       C2222 C2233 C2223 C2213 C2212
     541             :   //             C3333 C3323 C3313 C3312
     542             :   //                   C2323 C2313 C2312
     543             :   //                         C1313 C1312
     544             :   //                               C1212
     545             : 
     546             :   mooseAssert(LIBMESH_DIM == 3, "This method assumes LIBMESH_DIM == 3");
     547             :   mooseAssert(input.size() == 21,
     548             :               "To use fillSymmetric21FromInputVector, your input must have size 21.");
     549          24 :   std::size_t index = 0;
     550         168 :   for (const auto i : make_range(N))
     551         648 :     for (const auto j : make_range(i, N))
     552             :     {
     553         504 :       _vals[i + N * j] = mandelFactor(i, j) * input[index];
     554         504 :       _vals[j + N * i] = mandelFactor(j, i) * input[index];
     555         504 :       index++;
     556             :     }
     557          24 : }
     558             : 
     559             : template <typename T>
     560             : SymmetricRankFourTensorTempl<T>
     561           4 : SymmetricRankFourTensorTempl<T>::invSymm() const
     562             : {
     563           4 :   SymmetricRankFourTensorTempl<T> result(initNone);
     564             : 
     565             :   if constexpr (SymmetricRankFourTensorTempl<T>::N2 * sizeof(T) > EIGEN_STACK_ALLOCATION_LIMIT)
     566             :   {
     567           1 :     Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> mat(N, N);
     568           7 :     for (const auto i : make_range(N))
     569          42 :       for (const auto j : make_range(N))
     570          36 :         mat(i, j) = (*this)(i, j);
     571           1 :     mat = mat.inverse();
     572           7 :     for (const auto i : make_range(N))
     573          42 :       for (const auto j : make_range(N))
     574          36 :         result(i, j) = mat(i, j);
     575           1 :   }
     576             :   else
     577             :   {
     578           3 :     const Eigen::Map<const Eigen::Matrix<T, N, N, Eigen::RowMajor>> mat(&_vals[0]);
     579           3 :     Eigen::Map<Eigen::Matrix<T, N, N, Eigen::RowMajor>> res(&result._vals[0]);
     580           3 :     res = mat.inverse();
     581             :   }
     582             : 
     583           4 :   return result;
     584           0 : }

Generated by: LCOV version 1.14