LCOV - code coverage report
Current view: top level - include/utils - SymmetricRankTwoTensor.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 67 87 77.0 %
Date: 2025-07-17 01:28:37 Functions: 17 55 30.9 %
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 "ADSymmetricRankTwoTensorForward.h"
      15             : #include "ADSymmetricRankFourTensorForward.h"
      16             : #include "MooseUtils.h"
      17             : #include "MathUtils.h"
      18             : 
      19             : #include "libmesh/libmesh.h"
      20             : #include "libmesh/tensor_value.h"
      21             : 
      22             : #include "metaphysicl/raw_type.h"
      23             : 
      24             : #include <petscsys.h>
      25             : #include <vector>
      26             : 
      27             : // Forward declarations
      28             : class MooseEnum;
      29             : template <typename T>
      30             : class MooseArray;
      31             : typedef MooseArray<Real> VariableValue;
      32             : template <typename>
      33             : class ColumnMajorMatrixTempl;
      34             : namespace libMesh
      35             : {
      36             : template <typename>
      37             : class VectorValue;
      38             : template <typename>
      39             : class TypeVector;
      40             : template <typename>
      41             : class TypeTensor;
      42             : template <typename>
      43             : class TensorValue;
      44             : }
      45             : 
      46             : namespace boostcopy = libMesh::boostcopy;
      47             : 
      48             : namespace MathUtils
      49             : {
      50             : template <typename T>
      51             : void mooseSetToZero(T & v);
      52             : 
      53             : /**
      54             :  * Helper function template specialization to set an object to zero.
      55             :  * Needed by DerivativeMaterialInterface
      56             :  */
      57             : template <>
      58             : void mooseSetToZero<SymmetricRankTwoTensor>(SymmetricRankTwoTensor & v);
      59             : 
      60             : /**
      61             :  * Helper function template specialization to set an object to zero.
      62             :  * Needed by DerivativeMaterialInterface
      63             :  */
      64             : template <>
      65             : void mooseSetToZero<ADSymmetricRankTwoTensor>(ADSymmetricRankTwoTensor & v);
      66             : }
      67             : 
      68             : /**
      69             :  * SymmetricRankTwoTensorTempl is designed to handle the Stress or Strain Tensor for
      70             :  * an anisotropic material. It is designed to reduce the redundancies of the
      71             :  * Complete tensor classes for regular mechanics problems and to enable use of the
      72             :  * Mandel notation.
      73             :  */
      74             : template <typename T>
      75             : class SymmetricRankTwoTensorTempl
      76             : {
      77             : public:
      78             :   /// For generic programming
      79             :   typedef T value_type;
      80             : 
      81             :   ///@{ tensor dimension and Mandel vector length
      82             :   static constexpr unsigned int Ndim = Moose::dim;
      83             :   static constexpr unsigned int N = Ndim + (Ndim * (Ndim - 1)) / 2;
      84             :   ///@}
      85             : 
      86             :   // Full tensor indices in the Mandel/Voigt representation
      87             :   static constexpr unsigned int full_index[6][2] = {{0, 0}, {1, 1}, {2, 2}, {1, 2}, {0, 2}, {0, 1}};
      88             : 
      89             :   // Reverse tensor indices in the Mandel/Voigt representation
      90             :   static constexpr unsigned int reverse_index[3][3] = {{0, 5, 4}, {5, 1, 3}, {4, 3, 2}};
      91             : 
      92             :   /// returns the 1 or sqrt(2) prefactor in the Mandel notation for the index i ranging from 0-5.
      93       14590 :   static constexpr Real mandelFactor(unsigned int i) { return i < Ndim ? 1.0 : MathUtils::sqrt2; }
      94             : 
      95             :   // Select initialization
      96             :   enum InitMethod
      97             :   {
      98             :     initNone,
      99             :     initIdentity
     100             :   };
     101             : 
     102             :   /// Default constructor; fills to zero
     103             :   SymmetricRankTwoTensorTempl();
     104             : 
     105             :   /// Select specific initialization pattern
     106             :   SymmetricRankTwoTensorTempl(const InitMethod);
     107             : 
     108             :   /**
     109             :    * To fill up the 6 entries in the 2nd-order tensor, fillFromInputVector
     110             :    * is called with one of the following fill_methods.
     111             :    * See the fill*FromInputVector functions for more details
     112             :    */
     113             :   enum FillMethod
     114             :   {
     115             :     autodetect = 0,
     116             :     isotropic1 = 1,
     117             :     diagonal3 = 3,
     118             :     symmetric6 = 6
     119             :   };
     120             : 
     121             :   /// Constructor that proxies the fillFromInputVector method
     122           0 :   SymmetricRankTwoTensorTempl(const std::vector<T> & input) { this->fillFromInputVector(input); };
     123             : 
     124             :   /// Initialization list replacement constructors, 6 arguments
     125             :   SymmetricRankTwoTensorTempl(
     126             :       const T & S11, const T & S22, const T & S33, const T & S23, const T & S13, const T & S12);
     127             : 
     128             :   // explicit cast to a full tensor
     129             :   explicit operator RankTwoTensorTempl<T>();
     130             : 
     131             : private:
     132             :   /// Initialization list replacement constructors, 9 arguments (for internal use only)
     133             :   SymmetricRankTwoTensorTempl(const T & S11,
     134             :                               const T & S21,
     135             :                               const T & S31,
     136             :                               const T & S12,
     137             :                               const T & S22,
     138             :                               const T & S32,
     139             :                               const T & S13,
     140             :                               const T & S23,
     141             :                               const T & S33);
     142             : 
     143             :   // internal use named constructor that does not apply the sqrt(2) factors
     144             :   static SymmetricRankTwoTensorTempl fromRawComponents(
     145             :       const T & S11, const T & S22, const T & S33, const T & S23, const T & S13, const T & S12);
     146             : 
     147             : public:
     148             :   /// Copy constructor from TensorValue<T>
     149             :   explicit SymmetricRankTwoTensorTempl(const TensorValue<T> & a);
     150             : 
     151             :   /// Copy constructor from TypeTensor<T>
     152             :   explicit SymmetricRankTwoTensorTempl(const TypeTensor<T> & a);
     153             : 
     154             :   /// Construct from other template
     155             :   template <typename T2>
     156             :   SymmetricRankTwoTensorTempl(const SymmetricRankTwoTensorTempl<T2> & a)
     157             :   {
     158             :     for (const auto i : make_range(N))
     159             :       _vals[i] = a(i);
     160             :   }
     161             : 
     162             :   // Named constructors
     163           0 :   static SymmetricRankTwoTensorTempl identity()
     164             :   {
     165           0 :     return SymmetricRankTwoTensorTempl(initIdentity);
     166             :   }
     167             : 
     168             :   /// named constructor for initializing symmetrically
     169             :   static SymmetricRankTwoTensorTempl
     170             :   initializeSymmetric(const TypeVector<T> & v0, const TypeVector<T> & v1, const TypeVector<T> & v2);
     171             : 
     172             :   /// Static method for use in validParams for getting the "fill_method"
     173             :   static MooseEnum fillMethodEnum();
     174             : 
     175             :   /// fillFromInputVector takes 1, 3, or 6 inputs to fill in the symmmetric Rank-2 tensor.
     176             :   void fillFromInputVector(const std::vector<T> & input, FillMethod fill_method = autodetect);
     177             : 
     178             :   /**
     179             :    * fillFromScalarVariable takes FIRST/THIRD/SIXTH order scalar variable to fill in the Rank-2
     180             :    * tensor.
     181             :    */
     182             :   void fillFromScalarVariable(const VariableValue & scalar_variable);
     183             : 
     184             :   /// Gets the raw value for the index specified.  Takes index = 0,1,2,3,4,5
     185     2254440 :   inline T & operator()(unsigned int i) { return _vals[i]; }
     186             : 
     187             :   /**
     188             :    * Gets the raw value for the index specified.  Takes index = 0,1,2
     189             :    * used for const
     190             :    */
     191         567 :   inline T operator()(unsigned int i) const { return _vals[i]; }
     192             : 
     193             :   /**
     194             :    * Gets the value for the index specified.  Takes index = 0,1,2
     195             :    */
     196         873 :   inline T operator()(unsigned int i, unsigned int j) const
     197             :   {
     198         873 :     const auto a = reverse_index[i][j];
     199         873 :     return _vals[a] / mandelFactor(a);
     200             :   }
     201             : 
     202             :   /// get the specified row of the tensor
     203             :   libMesh::VectorValue<T> row(const unsigned int n) const;
     204             : 
     205             :   /// get the specified column of the tensor
     206           0 :   libMesh::VectorValue<T> column(const unsigned int n) const { return row(n); }
     207             : 
     208             :   /// return the matrix multiplied with its transpose A*A^T (guaranteed symmetric)
     209             :   [[nodiscard]] static SymmetricRankTwoTensorTempl<T> timesTranspose(const RankTwoTensorTempl<T> &);
     210             :   [[nodiscard]] static SymmetricRankTwoTensorTempl<T>
     211             :   timesTranspose(const SymmetricRankTwoTensorTempl<T> &);
     212             : 
     213             :   /// return the matrix multiplied with its transpose A^T*A (guaranteed symmetric)
     214             :   [[nodiscard]] static SymmetricRankTwoTensorTempl<T> transposeTimes(const RankTwoTensorTempl<T> &);
     215             :   [[nodiscard]] static SymmetricRankTwoTensorTempl<T>
     216             :   transposeTimes(const SymmetricRankTwoTensorTempl<T> &);
     217             : 
     218             :   /// return the matrix plus its transpose A-A^T (guaranteed symmetric)
     219             :   [[nodiscard]] static SymmetricRankTwoTensorTempl<T> plusTranspose(const RankTwoTensorTempl<T> &);
     220             :   [[nodiscard]] static SymmetricRankTwoTensorTempl<T>
     221             :   plusTranspose(const SymmetricRankTwoTensorTempl<T> &);
     222             : 
     223             :   /// Returns the matrix squared
     224             :   SymmetricRankTwoTensorTempl<T> square() const;
     225             : 
     226             :   /// Returns the trace
     227          15 :   T tr() const { return _vals[0] + _vals[1] + _vals[2]; }
     228             : 
     229             :   /// Set all components to zero
     230             :   void zero();
     231             : 
     232             :   /**
     233             :    * rotates the tensor data given a rank two tensor rotation tensor
     234             :    * _vals[i][j] = R_ij * R_jl * _vals[k][l]
     235             :    * @param R rotation matrix as a TypeTensor
     236             :    */
     237             :   void rotate(const TypeTensor<T> & R);
     238             : 
     239             :   /**
     240             :    * Returns a matrix that is the transpose of the matrix this
     241             :    * was called on. This is a non-operation.
     242             :    */
     243             :   SymmetricRankTwoTensorTempl<T> transpose() const;
     244             : 
     245             :   /// sets _vals to a, and returns _vals
     246             :   template <typename T2>
     247             :   SymmetricRankTwoTensorTempl<T> & operator=(const SymmetricRankTwoTensorTempl<T2> & a);
     248             : 
     249             :   /**
     250             :    * Assignment-from-scalar operator.  Used only to zero out vectors.
     251             :    */
     252             :   template <typename Scalar>
     253             :   typename boostcopy::enable_if_c<libMesh::ScalarTraits<Scalar>::value,
     254             :                                   SymmetricRankTwoTensorTempl &>::type
     255             :   operator=(const Scalar & libmesh_dbg_var(p))
     256             :   {
     257             :     libmesh_assert_equal_to(p, Scalar(0));
     258             :     this->zero();
     259             :     return *this;
     260             :   }
     261             : 
     262             :   /// adds a to _vals
     263             :   SymmetricRankTwoTensorTempl<T> & operator+=(const SymmetricRankTwoTensorTempl<T> & a);
     264             : 
     265             :   /// returns _vals + a
     266             :   template <typename T2>
     267             :   SymmetricRankTwoTensorTempl<typename libMesh::CompareTypes<T, T2>::supertype>
     268             :   operator+(const SymmetricRankTwoTensorTempl<T2> & a) const;
     269             : 
     270             :   /// sets _vals -= a and returns vals
     271             :   SymmetricRankTwoTensorTempl<T> & operator-=(const SymmetricRankTwoTensorTempl<T> & a);
     272             : 
     273             :   /// returns _vals - a
     274             :   template <typename T2>
     275             :   SymmetricRankTwoTensorTempl<typename libMesh::CompareTypes<T, T2>::supertype>
     276             :   operator-(const SymmetricRankTwoTensorTempl<T2> & a) const;
     277             : 
     278             :   /// returns -_vals
     279             :   SymmetricRankTwoTensorTempl<T> operator-() const;
     280             : 
     281             :   /// performs _vals *= a
     282             :   SymmetricRankTwoTensorTempl<T> & operator*=(const T & a);
     283             : 
     284             :   /// returns _vals*a
     285             :   template <typename T2>
     286             :   auto operator*(const T2 & a) const ->
     287             :       typename std::enable_if<libMesh::ScalarTraits<T2>::value,
     288             :                               SymmetricRankTwoTensorTempl<decltype(T() * T2())>>::type;
     289             : 
     290             :   /// performs _vals /= a
     291             :   SymmetricRankTwoTensorTempl<T> & operator/=(const T & a);
     292             : 
     293             :   /// returns _vals/a
     294             :   template <typename T2>
     295             :   auto operator/(const T2 & a) const ->
     296             :       typename std::enable_if<libMesh::ScalarTraits<T2>::value,
     297             :                               SymmetricRankTwoTensorTempl<decltype(T() / T2())>>::type;
     298             : 
     299             :   /// Defines multiplication with a vector to get a vector
     300             :   template <typename T2>
     301             :   TypeVector<typename libMesh::CompareTypes<T, T2>::supertype>
     302             :   operator*(const TypeVector<T2> & a) const;
     303             : 
     304             :   /// Defines logical equality with another SymmetricRankTwoTensorTempl<T2>
     305             :   template <typename T2>
     306             :   bool operator==(const SymmetricRankTwoTensorTempl<T2> & a) const;
     307             : 
     308             :   /// Test for symmetry. Surprisingly this is always true.
     309           0 :   bool isSymmetric() const { return true; }
     310             : 
     311             :   /// Defines logical inequality with another SymmetricRankTwoTensorTempl<T2>
     312             :   template <typename T2>
     313             :   bool operator!=(const SymmetricRankTwoTensorTempl<T2> & a) const;
     314             : 
     315             :   /// Sets _vals to the values in a ColumnMajorMatrix (must be 3x3)
     316             :   SymmetricRankTwoTensorTempl<T> & operator=(const ColumnMajorMatrixTempl<T> & a);
     317             : 
     318             :   /// returns _vals_ij * a_ij (sum on i, j)
     319             :   T doubleContraction(const SymmetricRankTwoTensorTempl<T> & a) const;
     320             : 
     321             :   /// returns C_ijkl = a_ij * b_kl
     322             :   SymmetricRankFourTensorTempl<T> outerProduct(const SymmetricRankTwoTensorTempl<T> & a) const;
     323             : 
     324             :   /// return positive projection tensor of eigen-decomposition
     325             :   SymmetricRankFourTensorTempl<T>
     326             :   positiveProjectionEigenDecomposition(std::vector<T> &, RankTwoTensorTempl<T> &) const;
     327             : 
     328             :   /// returns A_ij - de_ij*tr(A)/3, where A are the _vals
     329             :   SymmetricRankTwoTensorTempl<T> deviatoric() const;
     330             : 
     331             :   /// returns the trace of the tensor, ie _vals[i][i] (sum i = 0, 1, 2)
     332             :   T trace() const;
     333             : 
     334             :   /// retuns the inverse of the tensor
     335             :   SymmetricRankTwoTensorTempl<T> inverse() const;
     336             : 
     337             :   /**
     338             :    * Denote the _vals[i][j] by A_ij, then this returns
     339             :    * d(trace)/dA_ij
     340             :    */
     341             :   SymmetricRankTwoTensorTempl<T> dtrace() const;
     342             : 
     343             :   /**
     344             :    * Calculates the second invariant (I2) of a tensor
     345             :    */
     346             :   T generalSecondInvariant() const;
     347             : 
     348             :   /**
     349             :    * Denote the _vals[i][j] by A_ij, then
     350             :    * S_ij = A_ij - de_ij*tr(A)/3
     351             :    * Then this returns (S_ij + S_ji)*(S_ij + S_ji)/8
     352             :    * Note the explicit symmeterisation
     353             :    */
     354             :   T secondInvariant() const;
     355             : 
     356             :   /**
     357             :    * Denote the _vals[i][j] by A_ij, then this returns
     358             :    * d(secondInvariant)/dA_ij
     359             :    */
     360             :   SymmetricRankTwoTensorTempl<T> dsecondInvariant() const;
     361             : 
     362             :   /**
     363             :    * Denote the _vals[i][j] by A_ij, then this returns
     364             :    * d^2(secondInvariant)/dA_ij/dA_kl
     365             :    */
     366             :   SymmetricRankFourTensorTempl<T> d2secondInvariant() const;
     367             : 
     368             :   /**
     369             :    * Sin(3*Lode_angle)
     370             :    * If secondInvariant() <= r0 then return r0_value
     371             :    * This is to gaurd against precision-loss errors.
     372             :    * Note that sin(3*Lode_angle) is not defined for secondInvariant() = 0
     373             :    */
     374             :   T sin3Lode(const T & r0, const T & r0_value) const;
     375             : 
     376             :   /**
     377             :    * d(sin3Lode)/dA_ij
     378             :    * If secondInvariant() <= r0 then return zero
     379             :    * This is to gaurd against precision-loss errors.
     380             :    * Note that sin(3*Lode_angle) is not defined for secondInvariant() = 0
     381             :    */
     382             :   SymmetricRankTwoTensorTempl<T> dsin3Lode(const T & r0) const;
     383             : 
     384             :   /**
     385             :    * Denote the _vals[i][j] by A_ij, then
     386             :    * S_ij = A_ij - de_ij*tr(A)/3
     387             :    * Then this returns det(S + S.transpose())/2
     388             :    * Note the explicit symmeterisation
     389             :    */
     390             :   T thirdInvariant() const;
     391             : 
     392             :   /**
     393             :    * Denote the _vals[i][j] by A_ij, then
     394             :    * this returns d(thirdInvariant()/dA_ij
     395             :    */
     396             :   SymmetricRankTwoTensorTempl<T> dthirdInvariant() const;
     397             : 
     398             :   /**
     399             :    * Denote the _vals[i][j] by A_ij, then this returns
     400             :    * d^2(thirdInvariant)/dA_ij/dA_kl
     401             :    */
     402             :   SymmetricRankFourTensorTempl<T> d2thirdInvariant() const;
     403             : 
     404             :   // determinant of the tensor
     405             :   T det() const;
     406             : 
     407             :   /**
     408             :    * Denote the _vals[i][j] by A_ij, then this returns
     409             :    * d(det)/dA_ij
     410             :    */
     411             :   SymmetricRankTwoTensorTempl<T> ddet() const;
     412             : 
     413             :   /// Print the rank two tensor
     414             :   void print(std::ostream & stm = Moose::out) const;
     415             : 
     416             :   /// Print the Real part of the ADReal rank two tensor
     417             :   void printReal(std::ostream & stm = Moose::out) const;
     418             : 
     419             :   /// Print the Real part of the ADReal rank two tensor along with its first nDual dual numbers
     420             :   void printADReal(unsigned int nDual, std::ostream & stm = Moose::out) const;
     421             : 
     422             :   friend std::ostream & operator<<(std::ostream & os, const SymmetricRankTwoTensorTempl<T> & t)
     423             :   {
     424             :     t.print(os);
     425             :     return os;
     426             :   }
     427             : 
     428             :   /// Add identity times a to _vals
     429             :   void addIa(const T & a);
     430             : 
     431             :   /// Sqrt(_vals[i][j]*_vals[i][j])
     432             :   T L2norm() const;
     433             : 
     434             :   /**
     435             :    * sets _vals[0][0], _vals[0][1], _vals[1][0], _vals[1][1] to input,
     436             :    * and the remainder to zero
     437             :    */
     438             :   void surfaceFillFromInputVector(const std::vector<T> & input);
     439             : 
     440             :   /**
     441             :    * computes eigenvalues, assuming tens is symmetric, and places them
     442             :    * in ascending order in eigvals
     443             :    */
     444             :   void symmetricEigenvalues(std::vector<T> & eigvals) const;
     445             : 
     446             :   /**
     447             :    * computes eigenvalues and eigenvectors, assuming tens is symmetric, and places them
     448             :    * in ascending order in eigvals.  eigvecs is a matrix with the first column
     449             :    * being the first eigenvector, the second column being the second, etc.
     450             :    */
     451             :   void symmetricEigenvaluesEigenvectors(std::vector<T> & eigvals,
     452             :                                         RankTwoTensorTempl<T> & eigvecs) const;
     453             : 
     454             :   /**
     455             :    * This function initializes random seed based on a user-defined number.
     456             :    */
     457             :   static void initRandom(unsigned int);
     458             : 
     459             :   /**
     460             :    * This function generates a random symmetric rank two tensor.
     461             :    * The first real scales the random number.
     462             :    * The second real offsets the uniform random number
     463             :    */
     464             :   [[nodiscard]] static SymmetricRankTwoTensorTempl<T> genRandomSymmTensor(T, T);
     465             : 
     466             :   /// SymmetricRankTwoTensorTempl<T> from outer product of a vector with itself
     467             :   [[nodiscard]] static SymmetricRankTwoTensorTempl<T> selfOuterProduct(const TypeVector<T> &);
     468             : 
     469             :   /// returns this_ij * b_ijkl
     470             :   SymmetricRankTwoTensorTempl<T>
     471             :   initialContraction(const SymmetricRankFourTensorTempl<T> & b) const;
     472             : 
     473             :   /// set the tensor to the identity matrix
     474             :   void setToIdentity();
     475             : 
     476             : protected:
     477             :   /**
     478             :    * Uses the petscblaslapack.h LAPACKsyev_ routine to find, for symmetric _vals:
     479             :    *  (1) the eigenvalues (if calculation_type == "N")
     480             :    *  (2) the eigenvalues and eigenvectors (if calculation_type == "V")
     481             :    * @param calculation_type If "N" then calculation eigenvalues only
     482             :    * @param eigvals Eigenvalues are placed in this array, in ascending order
     483             :    * @param a Eigenvectors are placed in this array if calculation_type == "V".
     484             :    * See code in dsymmetricEigenvalues for extracting eigenvectors from the a output.
     485             :    */
     486             :   void syev(const char * calculation_type, std::vector<T> & eigvals, std::vector<T> & a) const;
     487             : 
     488             : private:
     489             :   static constexpr std::array<Real, N> identityCoords = {{1, 1, 1, 0, 0, 0}};
     490             : 
     491             :   // tensor components
     492             :   std::array<T, N> _vals;
     493             : 
     494             :   template <class T2>
     495             :   friend void dataStore(std::ostream &, SymmetricRankTwoTensorTempl<T2> &, void *);
     496             : 
     497             :   template <class T2>
     498             :   friend void dataLoad(std::istream &, SymmetricRankTwoTensorTempl<T2> &, void *);
     499             :   template <class T2>
     500             :   friend class SymmetricRankFourTensorTempl;
     501             : };
     502             : 
     503             : namespace MetaPhysicL
     504             : {
     505             : template <typename T>
     506             : struct RawType<SymmetricRankTwoTensorTempl<T>>
     507             : {
     508             :   typedef SymmetricRankTwoTensorTempl<typename RawType<T>::value_type> value_type;
     509             : 
     510           1 :   static value_type value(const SymmetricRankTwoTensorTempl<T> & in)
     511             :   {
     512           1 :     value_type ret;
     513           7 :     for (unsigned int i = 0; i < SymmetricRankTwoTensorTempl<T>::N; ++i)
     514           6 :       ret(i) = raw_value(in(i));
     515             : 
     516           1 :     return ret;
     517             :   }
     518             : };
     519             : }
     520             : 
     521             : template <typename T>
     522             : template <typename T2>
     523             : auto
     524          25 : SymmetricRankTwoTensorTempl<T>::operator*(const T2 & a) const ->
     525             :     typename std::enable_if<libMesh::ScalarTraits<T2>::value,
     526             :                             SymmetricRankTwoTensorTempl<decltype(T() * T2())>>::type
     527             : {
     528          25 :   SymmetricRankTwoTensorTempl<decltype(T() * T2())> result;
     529         175 :   for (const auto i : make_range(N))
     530         150 :     result._vals[i] = _vals[i] * a;
     531          25 :   return result;
     532           0 : }
     533             : 
     534             : template <typename T>
     535             : template <typename T2>
     536             : auto
     537           4 : SymmetricRankTwoTensorTempl<T>::operator/(const T2 & a) const ->
     538             :     typename std::enable_if<libMesh::ScalarTraits<T2>::value,
     539             :                             SymmetricRankTwoTensorTempl<decltype(T() / T2())>>::type
     540             : {
     541           4 :   SymmetricRankTwoTensorTempl<decltype(T() / T2())> result;
     542          28 :   for (const auto i : make_range(N))
     543          24 :     result._vals[i] = _vals[i] / a;
     544           4 :   return result;
     545           0 : }
     546             : 
     547             : /// Defines multiplication with a vector to get a vector
     548             : template <typename T>
     549             : template <typename T2>
     550             : TypeVector<typename libMesh::CompareTypes<T, T2>::supertype>
     551             : SymmetricRankTwoTensorTempl<T>::operator*(const TypeVector<T2> & a) const
     552             : {
     553             :   TypeVector<typename libMesh::CompareTypes<T, T2>::supertype> ret;
     554             :   ret(0) = a(0) * _vals[0] + a(1) * _vals[5] + a(2) * _vals[4];
     555             :   ret(1) = a(0) * _vals[5] + a(1) * _vals[1] + a(2) * _vals[3];
     556             :   ret(2) = a(0) * _vals[4] + a(1) * _vals[3] + a(2) * _vals[2];
     557             : }
     558             : 
     559             : template <typename T>
     560             : template <typename T2>
     561             : bool
     562           0 : SymmetricRankTwoTensorTempl<T>::operator==(const SymmetricRankTwoTensorTempl<T2> & a) const
     563             : {
     564           0 :   for (std::size_t i = 0; i < N; ++i)
     565           0 :     if (_vals[i] != a._vals[i])
     566           0 :       return false;
     567           0 :   return true;
     568             : }
     569             : 
     570             : template <typename T>
     571             : template <typename T2>
     572             : bool
     573             : SymmetricRankTwoTensorTempl<T>::operator!=(const SymmetricRankTwoTensorTempl<T2> & a) const
     574             : {
     575             :   for (std::size_t i = 0; i < N; ++i)
     576             :     if (_vals[i] != a._vals[i])
     577             :       return true;
     578             :   return false;
     579             : }
     580             : 
     581             : template <typename T>
     582             : SymmetricRankFourTensorTempl<T>
     583           1 : SymmetricRankTwoTensorTempl<T>::positiveProjectionEigenDecomposition(
     584             :     std::vector<T> & eigval, RankTwoTensorTempl<T> & eigvec) const
     585             : {
     586             :   // The calculate of projection tensor follows
     587             :   // C. Miehe and M. Lambrecht, Commun. Numer. Meth. Engng 2001; 17:337~353
     588             : 
     589             :   // Compute eigenvectors and eigenvalues of this tensor
     590             :   if (MooseUtils::IsLikeReal<T>::value)
     591             :   {
     592           1 :     this->symmetricEigenvaluesEigenvectors(eigval, eigvec);
     593             : 
     594             :     // Separate out positive and negative eigen values
     595           0 :     std::array<T, N> epos;
     596           0 :     std::array<T, N> d;
     597           7 :     for (unsigned int i = 0; i < N; ++i)
     598             :     {
     599           6 :       epos[i] = (std::abs(eigval[i]) + eigval[i]) / 2.0;
     600           6 :       d[i] = 0 < eigval[i] ? 1.0 : 0.0;
     601             :     }
     602             : 
     603             :     // projection tensor
     604           1 :     SymmetricRankFourTensorTempl<T> proj_pos;
     605             : 
     606           4 :     for (unsigned int a = 0; a < Ndim; ++a)
     607             :     {
     608           3 :       const auto Ma = SymmetricRankTwoTensorTempl<T>::selfOuterProduct(eigvec.column(a));
     609           3 :       proj_pos += d[a] * Ma.outerProduct(Ma);
     610             :     }
     611             : 
     612           4 :     for (const auto a : make_range(Ndim))
     613           6 :       for (const auto b : make_range(a))
     614             :       {
     615           3 :         const auto Ma = SymmetricRankTwoTensorTempl<T>::selfOuterProduct(eigvec.column(a));
     616           3 :         const auto Mb = SymmetricRankTwoTensorTempl<T>::selfOuterProduct(eigvec.column(b));
     617             : 
     618           3 :         SymmetricRankFourTensorTempl<T> Gabba(SymmetricRankFourTensorTempl<T>::initNone);
     619          21 :         for (const auto aa : make_range(N))
     620         126 :           for (const auto bb : make_range(N))
     621             :           {
     622         108 :             const auto i = SymmetricRankFourTensorTempl<T>::full_index[aa][bb][0];
     623         108 :             const auto j = SymmetricRankFourTensorTempl<T>::full_index[aa][bb][1];
     624         108 :             const auto k = SymmetricRankFourTensorTempl<T>::full_index[aa][bb][2];
     625         108 :             const auto l = SymmetricRankFourTensorTempl<T>::full_index[aa][bb][3];
     626             : 
     627         216 :             Gabba(aa, bb) = (Ma(i, k) * Mb(j, l) + Ma(i, l) * Mb(j, k) + Ma(j, l) * Mb(i, k) +
     628         108 :                              Ma(j, k) * Mb(i, l)) *
     629         108 :                             SymmetricRankFourTensorTempl<T>::mandelFactor(aa, bb);
     630             :           }
     631             : 
     632           0 :         T theta_ab;
     633           3 :         if (!MooseUtils::relativeFuzzyEqual(eigval[a], eigval[b]))
     634           3 :           theta_ab = 0.5 * (epos[a] - epos[b]) / (eigval[a] - eigval[b]);
     635             :         else
     636           0 :           theta_ab = 0.25 * (d[a] + d[b]);
     637             : 
     638           3 :         proj_pos += theta_ab * Gabba;
     639             :       }
     640           1 :     return proj_pos;
     641           0 :   }
     642             :   else
     643             :     mooseError("positiveProjectionEigenDecomposition is only available for ordered tensor "
     644             :                "component types");
     645             : }
     646             : 
     647             : template <typename T>
     648             : T
     649           2 : SymmetricRankTwoTensorTempl<T>::sin3Lode(const T & r0, const T & r0_value) const
     650             : {
     651             :   if (MooseUtils::IsLikeReal<T>::value)
     652             :   {
     653           2 :     T bar = secondInvariant();
     654           2 :     if (bar <= r0)
     655             :       // in this case the Lode angle is not defined
     656           1 :       return r0_value;
     657             :     else
     658             :       // the min and max here gaurd against precision-loss when bar is tiny but nonzero.
     659           1 :       return std::max(std::min(thirdInvariant() * -1.5 * std::sqrt(3.0) / std::pow(bar, 1.5), 1.0),
     660           2 :                       -1.0);
     661           0 :   }
     662             :   else
     663             :     mooseError("sin3Lode is only available for ordered tensor component types");
     664             : }
     665             : 
     666             : template <typename T>
     667             : SymmetricRankTwoTensorTempl<T>
     668           1 : SymmetricRankTwoTensorTempl<T>::dsin3Lode(const T & r0) const
     669             : {
     670             :   if (MooseUtils::IsLikeReal<T>::value)
     671             :   {
     672           1 :     T bar = secondInvariant();
     673           1 :     if (bar <= r0)
     674           0 :       return SymmetricRankTwoTensorTempl<T>();
     675             :     else
     676           1 :       return -1.5 * std::sqrt(3.0) *
     677           1 :              (dthirdInvariant() / std::pow(bar, 1.5) -
     678           2 :               1.5 * dsecondInvariant() * thirdInvariant() / std::pow(bar, 2.5));
     679           0 :   }
     680             :   else
     681             :     mooseError("dsin3Lode is only available for ordered tensor component types");
     682             : }
     683             : 
     684             : template <typename T>
     685             : template <typename T2>
     686             : SymmetricRankTwoTensorTempl<T> &
     687          34 : SymmetricRankTwoTensorTempl<T>::operator=(const SymmetricRankTwoTensorTempl<T2> & a)
     688             : {
     689         238 :   for (const auto i : make_range(N))
     690         204 :     (*this)(i) = a(i);
     691          34 :   return *this;
     692             : }
     693             : 
     694             : // non-member operators
     695             : 
     696             : template <typename T, typename Scalar>
     697             : inline typename std::enable_if_t<
     698             :     libMesh::ScalarTraits<Scalar>::value,
     699             :     SymmetricRankTwoTensorTempl<typename libMesh::CompareTypes<T, Scalar>::supertype>>
     700           2 : operator*(const Scalar & factor, const SymmetricRankTwoTensorTempl<T> & t)
     701             : {
     702           2 :   return t * factor;
     703             : }

Generated by: LCOV version 1.14