LCOV - code coverage report
Current view: top level - include/utils - RankThreeTensor.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 41 43 95.3 %
Date: 2025-07-17 01:28:37 Functions: 9 16 56.2 %
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 "ADRankThreeTensorForward.h"
      15             : #include "ADRankFourTensorForward.h"
      16             : 
      17             : #include "libmesh/libmesh.h"
      18             : #include "libmesh/int_range.h"
      19             : 
      20             : #include "metaphysicl/raw_type.h"
      21             : 
      22             : namespace libMesh
      23             : {
      24             : template <typename>
      25             : class TensorValue;
      26             : template <typename>
      27             : class TypeTensor;
      28             : template <typename>
      29             : class VectorValue;
      30             : }
      31             : 
      32             : // Forward declarations
      33             : class MooseEnum;
      34             : 
      35             : namespace MathUtils
      36             : {
      37             : template <typename T>
      38             : void mooseSetToZero(T & v);
      39             : 
      40             : /**
      41             :  * Helper function template specialization to set an object to zero.
      42             :  * Needed by DerivativeMaterialInterface
      43             :  */
      44             : template <>
      45             : void mooseSetToZero<RankThreeTensorTempl<Real>>(RankThreeTensorTempl<Real> & v);
      46             : template <>
      47             : void mooseSetToZero<RankThreeTensorTempl<ADReal>>(RankThreeTensorTempl<ADReal> & v);
      48             : }
      49             : 
      50             : /**
      51             :  * RankThreeTensor is designed to handle any N-dimensional third order tensor, r.
      52             :  *
      53             :  */
      54             : template <typename T>
      55             : class RankThreeTensorTempl
      56             : {
      57             : public:
      58             :   ///@{ tensor dimension and powers of the dimension
      59             :   static constexpr unsigned int N = Moose::dim;
      60             :   static constexpr unsigned int N2 = N * N;
      61             :   static constexpr unsigned int N3 = N * N * N;
      62             :   ///@}
      63             : 
      64             :   /// Initialization method
      65             :   enum InitMethod
      66             :   {
      67             :     initNone
      68             :   };
      69             : 
      70             :   /**
      71             :    * To fill up the 27 entries in the 3rd-order tensor, fillFromInputVector
      72             :    * is called with one of the following fill_methods.
      73             :    * See the fill*FromInputVector functions for more details
      74             :    */
      75             :   enum FillMethod
      76             :   {
      77             :     automatic,
      78             :     general,
      79             :     plane_normal
      80             :   };
      81             : 
      82             :   /// Default constructor; fills to zero
      83             :   RankThreeTensorTempl();
      84             : 
      85             :   /// Copy assignment operator must be defined if used
      86           0 :   RankThreeTensorTempl(const RankThreeTensorTempl<T> & a) = default;
      87             : 
      88             :   /**
      89             :    * Construct from other class template instantiation
      90             :    */
      91             :   template <typename T2>
      92             :   RankThreeTensorTempl(const RankThreeTensorTempl<T2> & copy);
      93             : 
      94             :   /// Select specific initialization pattern
      95             :   RankThreeTensorTempl(const InitMethod);
      96             : 
      97             :   /// Fill from vector
      98             :   RankThreeTensorTempl(const std::vector<T> &, FillMethod method = automatic);
      99             : 
     100             :   /// Gets the value for the index specified.  Takes index = 0,1,2
     101      113790 :   inline T & operator()(unsigned int i, unsigned int j, unsigned int k)
     102             :   {
     103      113790 :     return _vals[((i * N + j) * N + k)];
     104             :   }
     105             : 
     106             :   /// Gets the value for the index specified.  Takes index = 0,1,2. Used for const
     107        1996 :   inline T operator()(unsigned int i, unsigned int j, unsigned int k) const
     108             :   {
     109        1996 :     return _vals[((i * N + j) * N + k)];
     110             :   }
     111             : 
     112             :   /// Assignment-from-scalar operator.
     113             :   RankThreeTensorTempl<T> & operator=(const T & value);
     114             : 
     115             :   /// Zeros out the tensor.
     116             :   void zero();
     117             : 
     118             :   /// Print the rank three tensor
     119             :   void print(std::ostream & stm = Moose::out) const;
     120             : 
     121             :   friend std::ostream & operator<<(std::ostream & os, const RankThreeTensorTempl<T> & t)
     122             :   {
     123             :     t.print(os);
     124             :     return os;
     125             :   }
     126             : 
     127             :   /// copies values from "a" into this tensor
     128             :   RankThreeTensorTempl<T> & operator=(const RankThreeTensorTempl<T> & a);
     129             : 
     130             :   template <typename T2>
     131             :   RankThreeTensorTempl<T> & operator=(const RankThreeTensorTempl<T2> & a);
     132             : 
     133             :   /// b_i = r_ijk * a_jk
     134             :   libMesh::VectorValue<T> operator*(const RankTwoTensorTempl<T> & a) const;
     135             : 
     136             :   /// b_ij = r_ijk * a_k
     137             :   RankTwoTensorTempl<T> operator*(const libMesh::VectorValue<T> & a) const;
     138             : 
     139             :   /// r_ijk*a
     140             :   RankThreeTensorTempl<T> operator*(const T a) const;
     141             : 
     142             :   /// r_ijk *= a
     143             :   RankThreeTensorTempl<T> & operator*=(const T a);
     144             : 
     145             :   /// r_ijk/a
     146             :   RankThreeTensorTempl<T> operator/(const T a) const;
     147             : 
     148             :   /// r_ijk /= a  for all i, j, k
     149             :   RankThreeTensorTempl<T> & operator/=(const T a);
     150             : 
     151             :   /// r_ijk += a_ijk  for all i, j, k
     152             :   RankThreeTensorTempl<T> & operator+=(const RankThreeTensorTempl<T> & a);
     153             : 
     154             :   /// r_ijkl + a_ijk
     155             :   RankThreeTensorTempl<T> operator+(const RankThreeTensorTempl<T> & a) const;
     156             : 
     157             :   /// r_ijk -= a_ijk
     158             :   RankThreeTensorTempl<T> & operator-=(const RankThreeTensorTempl<T> & a);
     159             : 
     160             :   /// r_ijk - a_ijk
     161             :   RankThreeTensorTempl<T> operator-(const RankThreeTensorTempl<T> & a) const;
     162             : 
     163             :   /// -r_ijk
     164             :   RankThreeTensorTempl<T> operator-() const;
     165             : 
     166             :   /// \sqrt(r_ijk*r_ijk)
     167             :   T L2norm() const;
     168             : 
     169             :   /**
     170             :    * Rotate the tensor using
     171             :    * r_ijk = R_im R_in R_ko r_mno
     172             :    */
     173             :   template <class T2>
     174             :   void rotate(const T2 & R);
     175             : 
     176             :   /**
     177             :    * Rotate the tensor using
     178             :    * r_ijk = R_im R_in R_ko r_mno
     179             :    */
     180             :   void rotate(const libMesh::TensorValue<T> & R);
     181             : 
     182             :   /// Static method for use in validParams for getting the "fill_method"
     183             :   static MooseEnum fillMethodEnum();
     184             : 
     185             :   /**
     186             :    * fillFromInputVector takes some number of inputs to fill
     187             :    * the Rank-3 tensor.
     188             :    * @param input the numbers that will be placed in the tensor
     189             :    * @param fill_method this can be:
     190             :    *             general (use fillGeneralFromInputVector)
     191             :    *             more fill_methods to be implemented soon!
     192             :    */
     193             :   void fillFromInputVector(const std::vector<T> & input, FillMethod fill_method = automatic);
     194             : 
     195             :   /**
     196             :    * Fills RankThreeTensor from plane normal vectors
     197             :    * ref. Kuhl et. al. Int. J. Solids Struct. 38(2001) 2933-2952
     198             :    * @param input plane normal vector
     199             :    */
     200             :   void fillFromPlaneNormal(const libMesh::VectorValue<T> & input);
     201             : 
     202             :   /**
     203             :    * Creates fourth order tensor D_{ijkl}=A_{mij}*b_{mn}*A_{nkl} where A is rank 3 and b is rank 2
     204             :    * @param a RankThreeTensor A in the equation above
     205             :    */
     206             :   RankFourTensorTempl<T> mixedProductRankFour(const RankTwoTensorTempl<T> & a) const;
     207             : 
     208             :   /**
     209             :    * Creates a vector from the double contraction of a rank three and rank two tensor.
     210             :    *
     211             :    * c_i = A_{ijk} * b_{jk}
     212             :    */
     213             :   libMesh::VectorValue<T> doubleContraction(const RankTwoTensorTempl<T> & b) const;
     214             : 
     215             : protected:
     216             :   /// The values of the rank-three tensor stored by index=((i * LIBMESH_DIM + j) * LIBMESH_DIM + k)
     217             :   T _vals[N3];
     218             : 
     219             :   void fillGeneralFromInputVector(const std::vector<T> & input);
     220             : 
     221             :   template <class T2>
     222             :   friend void dataStore(std::ostream &, RankThreeTensorTempl<T2> &, void *);
     223             : 
     224             :   template <class T2>
     225             :   friend void dataLoad(std::istream &, RankThreeTensorTempl<T2> &, void *);
     226             : 
     227             :   template <class T2>
     228             :   friend class RankTwoTensorTempl;
     229             : 
     230             :   template <class T2>
     231             :   friend class RankThreeTensorTempl;
     232             : 
     233             :   template <class T2>
     234             :   friend class RankFourTensorTempl;
     235             : };
     236             : 
     237             : namespace MetaPhysicL
     238             : {
     239             : template <typename T>
     240             : struct RawType<RankThreeTensorTempl<T>>
     241             : {
     242             :   typedef RankThreeTensorTempl<typename RawType<T>::value_type> value_type;
     243             : 
     244           2 :   static value_type value(const RankThreeTensorTempl<T> & in)
     245             :   {
     246           2 :     value_type ret;
     247           8 :     for (const auto i : libMesh::make_range(RankThreeTensorTempl<T>::N))
     248          24 :       for (const auto j : libMesh::make_range(RankThreeTensorTempl<T>::N))
     249          72 :         for (const auto k : libMesh::make_range(RankThreeTensorTempl<T>::N))
     250          54 :           ret(i, j, k) = raw_value(in(i, j, k));
     251             : 
     252           2 :     return ret;
     253             :   }
     254             : };
     255             : }
     256             : 
     257             : template <typename T>
     258             : template <typename T2>
     259             : RankThreeTensorTempl<T>::RankThreeTensorTempl(const RankThreeTensorTempl<T2> & copy)
     260             : {
     261             :   for (const auto i : libMesh::make_range(N3))
     262             :     _vals[i] = copy._vals[i];
     263             : }
     264             : 
     265             : template <typename T>
     266             : template <class T2>
     267             : void
     268           1 : RankThreeTensorTempl<T>::rotate(const T2 & R)
     269             : {
     270           1 :   unsigned int index = 0;
     271           4 :   for (const auto i : libMesh::make_range(N))
     272          12 :     for (const auto j : libMesh::make_range(N))
     273          36 :       for (const auto k : libMesh::make_range(N))
     274             :       {
     275          27 :         unsigned int index2 = 0;
     276          27 :         T sum = 0.0;
     277         108 :         for (const auto m : libMesh::make_range(N))
     278             :         {
     279          81 :           T a = R(i, m);
     280         324 :           for (const auto n : libMesh::make_range(N))
     281             :           {
     282         243 :             T ab = a * R(j, n);
     283         972 :             for (const auto o : libMesh::make_range(N))
     284         729 :               sum += ab * R(k, o) * _vals[index2++];
     285             :           }
     286             :         }
     287          27 :         _vals[index++] = sum;
     288             :       }
     289           1 : }
     290             : 
     291             : template <typename T>
     292             : RankThreeTensorTempl<T>
     293           1 : operator*(T a, const RankThreeTensorTempl<T> & b)
     294             : {
     295           1 :   return b * a;
     296             : }
     297             : 
     298             : ///r=v*A where r is rank 2, v is vector and A is rank 3
     299             : template <typename T>
     300             : RankTwoTensorTempl<T>
     301           1 : operator*(const libMesh::VectorValue<T> & p, const RankThreeTensorTempl<T> & b)
     302             : {
     303             :   static_assert(RankThreeTensorTempl<T>::N == RankTwoTensorTempl<T>::N,
     304             :                 "RankTwoTensor and RankThreeTensor have to have the same dimension N.");
     305           1 :   RankTwoTensorTempl<T> result;
     306             : 
     307           4 :   for (const auto i : libMesh::make_range(RankThreeTensorTempl<T>::N))
     308          12 :     for (const auto j : libMesh::make_range(RankThreeTensorTempl<T>::N))
     309          36 :       for (const auto k : libMesh::make_range(RankThreeTensorTempl<T>::N))
     310          27 :         result(i, j) += p(k) * b(k, i, j);
     311             : 
     312           1 :   return result;
     313           0 : }
     314             : 
     315             : template <typename T>
     316             : template <typename T2>
     317             : RankThreeTensorTempl<T> &
     318           2 : RankThreeTensorTempl<T>::operator=(const RankThreeTensorTempl<T2> & a)
     319             : {
     320           8 :   for (const auto i : libMesh::make_range(N))
     321          24 :     for (const auto j : libMesh::make_range(N))
     322          72 :       for (const auto k : libMesh::make_range(N))
     323          54 :         (*this)(i, j, k) = a(i, j, k);
     324             : 
     325           2 :   return *this;
     326             : }

Generated by: LCOV version 1.14