LCOV - code coverage report
Current view: top level - include/utils - RankThreeTensorImplementation.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 8601ad Lines: 166 190 87.4 %
Date: 2025-07-18 13:27:08 Functions: 26 78 33.3 %
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 "RankThreeTensor.h"
      13             : #include "RankTwoTensor.h"
      14             : #include "RankFourTensor.h"
      15             : 
      16             : // MOOSE includes
      17             : #include "MooseEnum.h"
      18             : #include "MooseException.h"
      19             : #include "MooseUtils.h"
      20             : #include "MatrixTools.h"
      21             : #include "PermutationTensor.h"
      22             : 
      23             : #include "libmesh/utility.h"
      24             : #include "libmesh/vector_value.h"
      25             : #include "libmesh/tensor_value.h"
      26             : 
      27             : // C++ includes
      28             : #include <iomanip>
      29             : #include <ostream>
      30             : 
      31             : namespace MathUtils
      32             : {
      33             : template <>
      34             : void mooseSetToZero<RankThreeTensor>(RankThreeTensor & v);
      35             : template <>
      36             : void mooseSetToZero<ADRankThreeTensor>(ADRankThreeTensor & v);
      37             : }
      38             : 
      39             : template <typename T>
      40             : MooseEnum
      41           1 : RankThreeTensorTempl<T>::fillMethodEnum()
      42             : {
      43           1 :   return MooseEnum("general plane_normal");
      44             : }
      45             : 
      46             : template <typename T>
      47         494 : RankThreeTensorTempl<T>::RankThreeTensorTempl()
      48             : {
      49             :   mooseAssert(N == 3, "RankThreeTensor is currently only tested for 3 dimensions.");
      50             : 
      51       12320 :   for (auto i : make_range(N3))
      52       11880 :     _vals[i] = 0;
      53         440 : }
      54             : 
      55             : template <typename T>
      56           1 : RankThreeTensorTempl<T>::RankThreeTensorTempl(const InitMethod init)
      57             : {
      58           1 :   switch (init)
      59             :   {
      60           1 :     case initNone:
      61           1 :       break;
      62             : 
      63           0 :     default:
      64           0 :       mooseError("Unknown RankThreeTensor initialization pattern.");
      65             :   }
      66           1 : }
      67             : 
      68             : template <typename T>
      69          21 : RankThreeTensorTempl<T>::RankThreeTensorTempl(const std::vector<T> & input, FillMethod fill_method)
      70             : {
      71          21 :   fillFromInputVector(input, fill_method);
      72          18 : }
      73             : 
      74             : template <typename T>
      75             : void
      76          66 : RankThreeTensorTempl<T>::zero()
      77             : {
      78        1848 :   for (auto i : make_range(N3))
      79        1782 :     _vals[i] = 0;
      80          66 : }
      81             : 
      82             : template <typename T>
      83             : RankThreeTensorTempl<T> &
      84           1 : RankThreeTensorTempl<T>::operator=(const T & value)
      85             : {
      86          28 :   for (auto i : make_range(N3))
      87          27 :     _vals[i] = value;
      88           1 :   return *this;
      89             : }
      90             : 
      91             : template <typename T>
      92             : RankThreeTensorTempl<T> &
      93           3 : RankThreeTensorTempl<T>::operator=(const RankThreeTensorTempl<T> & a)
      94             : {
      95          84 :   for (auto i : make_range(N3))
      96          81 :     _vals[i] = a._vals[i];
      97             : 
      98           3 :   return *this;
      99             : }
     100             : 
     101             : template <typename T>
     102             : libMesh::VectorValue<T>
     103           1 : RankThreeTensorTempl<T>::operator*(const RankTwoTensorTempl<T> & a) const
     104             : {
     105           1 :   libMesh::VectorValue<T> result;
     106             : 
     107           4 :   for (auto i : make_range(N))
     108             :   {
     109           3 :     T sum = 0;
     110           3 :     unsigned int i1 = i * N2;
     111          12 :     for (unsigned int j1 = 0; j1 < N2; j1 += N)
     112          36 :       for (auto k : make_range(N))
     113          27 :         sum += _vals[i1 + j1 + k] * a._coords[j1 + k];
     114           3 :     result(i) = sum;
     115             :   }
     116             : 
     117           1 :   return result;
     118           0 : }
     119             : 
     120             : template <typename T>
     121             : RankTwoTensorTempl<T>
     122           0 : RankThreeTensorTempl<T>::operator*(const libMesh::VectorValue<T> & a) const
     123             : {
     124           0 :   RankTwoTensorTempl<T> result;
     125             : 
     126           0 :   for (auto i : make_range(N))
     127           0 :     for (auto j : make_range(N))
     128             :     {
     129           0 :       T sum = 0;
     130           0 :       unsigned int i1 = i * N2;
     131           0 :       unsigned int j1 = j * N;
     132           0 :       for (auto k : make_range(N))
     133           0 :         sum += _vals[i1 + j1 + k] * a(k);
     134           0 :       result(i, j) = sum;
     135             :     }
     136             : 
     137           0 :   return result;
     138           0 : }
     139             : 
     140             : template <typename T>
     141             : RankThreeTensorTempl<T>
     142           2 : RankThreeTensorTempl<T>::operator*(const T b) const
     143             : {
     144           2 :   RankThreeTensorTempl<T> result;
     145             : 
     146          56 :   for (auto i : make_range(N3))
     147          54 :     result._vals[i] = _vals[i] * b;
     148             : 
     149           2 :   return result;
     150           0 : }
     151             : 
     152             : template <typename T>
     153             : RankThreeTensorTempl<T> &
     154           1 : RankThreeTensorTempl<T>::operator*=(const T a)
     155             : {
     156          28 :   for (auto i : make_range(N3))
     157          27 :     _vals[i] *= a;
     158             : 
     159           1 :   return *this;
     160             : }
     161             : 
     162             : template <typename T>
     163             : RankThreeTensorTempl<T>
     164           1 : RankThreeTensorTempl<T>::operator/(const T b) const
     165             : {
     166           1 :   RankThreeTensorTempl<T> result;
     167             : 
     168          28 :   for (auto i : make_range(N3))
     169          27 :     result._vals[i] = _vals[i] / b;
     170             : 
     171           1 :   return result;
     172           0 : }
     173             : 
     174             : template <typename T>
     175             : RankThreeTensorTempl<T> &
     176           1 : RankThreeTensorTempl<T>::operator/=(const T a)
     177             : {
     178          28 :   for (auto i : make_range(N3))
     179          27 :     _vals[i] /= a;
     180             : 
     181           1 :   return *this;
     182             : }
     183             : 
     184             : template <typename T>
     185             : RankThreeTensorTempl<T> &
     186           1 : RankThreeTensorTempl<T>::operator+=(const RankThreeTensorTempl<T> & a)
     187             : {
     188          28 :   for (auto i : make_range(N3))
     189          27 :     _vals[i] += a._vals[i];
     190             : 
     191           1 :   return *this;
     192             : }
     193             : 
     194             : template <typename T>
     195             : RankThreeTensorTempl<T>
     196           1 : RankThreeTensorTempl<T>::operator+(const RankThreeTensorTempl<T> & b) const
     197             : {
     198           1 :   RankThreeTensorTempl<T> result;
     199             : 
     200          28 :   for (auto i : make_range(N3))
     201          27 :     result._vals[i] = _vals[i] + b._vals[i];
     202             : 
     203           1 :   return result;
     204           0 : }
     205             : 
     206             : template <typename T>
     207             : RankThreeTensorTempl<T> &
     208           1 : RankThreeTensorTempl<T>::operator-=(const RankThreeTensorTempl<T> & a)
     209             : {
     210          28 :   for (auto i : make_range(N3))
     211          27 :     _vals[i] -= a._vals[i];
     212             : 
     213           1 :   return *this;
     214             : }
     215             : 
     216             : template <typename T>
     217             : RankThreeTensorTempl<T>
     218           1 : RankThreeTensorTempl<T>::operator-(const RankThreeTensorTempl<T> & b) const
     219             : {
     220           1 :   RankThreeTensorTempl<T> result;
     221             : 
     222          28 :   for (auto i : make_range(N3))
     223          27 :     result._vals[i] = _vals[i] - b._vals[i];
     224             : 
     225           1 :   return result;
     226           0 : }
     227             : 
     228             : template <typename T>
     229             : RankThreeTensorTempl<T>
     230           1 : RankThreeTensorTempl<T>::operator-() const
     231             : {
     232           1 :   RankThreeTensorTempl<T> result;
     233             : 
     234          28 :   for (auto i : make_range(N3))
     235          27 :     result._vals[i] = -_vals[i];
     236             : 
     237           1 :   return result;
     238           0 : }
     239             : 
     240             : template <typename T>
     241             : T
     242           1 : RankThreeTensorTempl<T>::L2norm() const
     243             : {
     244           1 :   T l2 = 0;
     245             : 
     246          28 :   for (auto i : make_range(N3))
     247          27 :     l2 += Utility::pow<2>(_vals[i]);
     248             : 
     249           1 :   return std::sqrt(l2);
     250           0 : }
     251             : 
     252             : template <typename T>
     253             : void
     254          64 : RankThreeTensorTempl<T>::fillFromInputVector(const std::vector<T> & input, FillMethod fill_method)
     255             : {
     256          64 :   zero();
     257             : 
     258          64 :   if (fill_method == automatic)
     259             :   {
     260          20 :     if (input.size() == 27)
     261          18 :       fill_method = general;
     262           2 :     else if (input.size() == 3)
     263           1 :       fill_method = plane_normal;
     264             :     else
     265           1 :       mooseError("Unsupported automatic fill method, use 27 values for 'general' and 3 for "
     266             :                  "'plane_normal', the supplied size was ",
     267           1 :                  input.size(),
     268             :                  ".");
     269             :   }
     270             : 
     271          63 :   if (fill_method == general)
     272          61 :     fillGeneralFromInputVector(input);
     273             : 
     274           2 :   else if (fill_method == plane_normal)
     275             :   {
     276           2 :     if (input.size() != 3)
     277           1 :       mooseError("To use fillFromPlaneNormal, your input must have size 3, the supplied size was ",
     278           1 :                  input.size(),
     279             :                  ".");
     280           1 :     fillFromPlaneNormal(libMesh::VectorValue<T>(input[0], input[1], input[2]));
     281             :   }
     282             : 
     283             :   else
     284             :     // This is un-reachable unless a FillMethod is added and the if statement is not updated
     285           0 :     mooseError("fillFromInputVector called with unknown fill_method of ", fill_method);
     286          61 : }
     287             : 
     288             : template <typename T>
     289             : void
     290           2 : RankThreeTensorTempl<T>::fillFromPlaneNormal(const libMesh::VectorValue<T> & input)
     291             : {
     292           2 :   unsigned int index = 0;
     293           8 :   for (auto i : make_range(N))
     294             :   {
     295           6 :     const T a = input(i);
     296          24 :     for (auto j : make_range(N))
     297             :     {
     298          18 :       const T b = input(j);
     299          72 :       for (auto k : make_range(N))
     300             :       {
     301          54 :         const T c = input(k);
     302          54 :         T sum = 0;
     303          54 :         sum = -2.0 * a * b * c;
     304          54 :         if (i == j)
     305          18 :           sum += c;
     306          54 :         if (i == k)
     307          18 :           sum += b;
     308          54 :         _vals[index++] = sum / 2.0;
     309             :       }
     310             :     }
     311             :   }
     312           2 : }
     313             : 
     314             : template <typename T>
     315             : RankFourTensorTempl<T>
     316           1 : RankThreeTensorTempl<T>::mixedProductRankFour(const RankTwoTensorTempl<T> & a) const
     317             : {
     318           1 :   RankFourTensorTempl<T> result;
     319             : 
     320           1 :   unsigned int index = 0;
     321           4 :   for (auto i : make_range(N))
     322          12 :     for (auto j : make_range(N))
     323          36 :       for (auto k : make_range(N))
     324         108 :         for (auto l : make_range(N))
     325             :         {
     326         324 :           for (auto m : make_range(N))
     327         972 :             for (auto n : make_range(N))
     328         729 :               result._vals[index] += (*this)(m, i, j) * a(m, n) * (*this)(n, k, l);
     329          81 :           index++;
     330             :         }
     331             : 
     332           1 :   return result;
     333           0 : }
     334             : 
     335             : template <typename T>
     336             : void
     337           1 : RankThreeTensorTempl<T>::rotate(const libMesh::TensorValue<T> & R)
     338             : {
     339           1 :   RankThreeTensorTempl<T> old = *this;
     340             : 
     341           1 :   unsigned int index = 0;
     342           4 :   for (auto i : make_range(N))
     343          12 :     for (auto j : make_range(N))
     344          36 :       for (auto k : make_range(N))
     345             :       {
     346          27 :         T sum = 0.0;
     347          27 :         unsigned int index2 = 0;
     348         108 :         for (auto m : make_range(N))
     349             :         {
     350          81 :           T a = R(i, m);
     351         324 :           for (auto n : make_range(N))
     352             :           {
     353         243 :             T ab = a * R(j, n);
     354         972 :             for (auto o : make_range(N))
     355         729 :               sum += ab * R(k, o) * old._vals[index2++];
     356             :           }
     357             :         }
     358          27 :         _vals[index++] = sum;
     359             :       }
     360           1 : }
     361             : 
     362             : template <typename T>
     363             : void
     364          61 : RankThreeTensorTempl<T>::fillGeneralFromInputVector(const std::vector<T> & input)
     365             : {
     366          61 :   if (input.size() != 27)
     367           1 :     mooseError(
     368             :         "To use fillGeneralFromInputVector, your input must have size 27, the supplied size was ",
     369           1 :         input.size(),
     370             :         ".");
     371             : 
     372        1680 :   for (auto i : make_range(N3))
     373        1620 :     _vals[i] = input[i];
     374          60 : }
     375             : 
     376             : template <typename T>
     377             : libMesh::VectorValue<T>
     378           1 : RankThreeTensorTempl<T>::doubleContraction(const RankTwoTensorTempl<T> & b) const
     379             : {
     380           1 :   libMesh::VectorValue<T> result;
     381             : 
     382           4 :   for (auto i : make_range(N))
     383          30 :     for (auto j : make_range(N2))
     384          27 :       result(i) += _vals[i * N2 + j] * b._coords[j];
     385             : 
     386           1 :   return result;
     387           0 : }
     388             : 
     389             : template <typename T>
     390             : void
     391           1 : RankThreeTensorTempl<T>::print(std::ostream & stm) const
     392             : {
     393           4 :   for (auto i : make_range(N))
     394             :   {
     395           3 :     stm << "a(" << i << ", j, k) = \n";
     396          12 :     for (auto j : make_range(N))
     397             :     {
     398          36 :       for (auto k : make_range(N))
     399          27 :         stm << std::setw(15) << (*this)(i, j, k) << ' ';
     400           9 :       stm << "\n";
     401             :     }
     402           3 :     stm << "\n";
     403             :   }
     404             : 
     405           1 :   stm << std::flush;
     406           1 : }

Generated by: LCOV version 1.14