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

Generated by: LCOV version 1.14