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

Generated by: LCOV version 1.14