LCOV - code coverage report
Current view: top level - src/Numeric - Stencil.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 175 275 63.6 %
Date: 2024-11-18 05:28:54 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef NUMERIC_STENCIL_H_
       2             : #define NUMERIC_STENCIL_H_
       3             : 
       4             : #include <AMReX.H>
       5             : #include <AMReX_MultiFab.H>
       6             : #include "Set/Set.H"
       7             : 
       8             : /// \brief This namespace contains some numerical tools
       9             : namespace Numeric
      10             : {
      11             : 
      12             : enum StencilType { Lo, Hi, Central };
      13             : static std::array<StencilType, AMREX_SPACEDIM>
      14             : DefaultType = { AMREX_D_DECL(StencilType::Central, StencilType::Central, StencilType::Central) };
      15             : 
      16             : [[nodiscard]]
      17             : static
      18             : AMREX_FORCE_INLINE
      19             : std::array<StencilType, AMREX_SPACEDIM>
      20             : GetStencil(const int i, const int j, const int k, const amrex::Box domain)
      21             : {
      22             :     (void)i; (void)j; (void)k; // Suppress "unused variable" warnings.
      23             :     std::array<StencilType, AMREX_SPACEDIM> sten;
      24             :     const amrex::Dim3 lo = amrex::lbound(domain), hi = amrex::ubound(domain);
      25    28625233 :     AMREX_D_TERM(sten[0] = (i == lo.x ? Numeric::StencilType::Hi :
      26             :         i == hi.x ? Numeric::StencilType::Lo :
      27             :         Numeric::StencilType::Central);,
      28             :         sten[1] = (j == lo.y ? Numeric::StencilType::Hi :
      29             :             j == hi.y ? Numeric::StencilType::Lo :
      30             :             Numeric::StencilType::Central);,
      31             :         sten[2] = (k == lo.z ? Numeric::StencilType::Hi :
      32             :             k == hi.z ? Numeric::StencilType::Lo :
      33             :             Numeric::StencilType::Central););
      34    28625233 :     return sten;
      35             : }
      36             : 
      37             : template<class T, int x, int y, int z>
      38             : struct Stencil
      39             : {};
      40             : 
      41             : //
      42             : // FIRST order derivatives
      43             : //
      44             : 
      45             : template<class T>
      46             : struct Stencil<T, 1, 0, 0>
      47             : {
      48             :     [[nodiscard]] AMREX_FORCE_INLINE 
      49             :         static T D(const amrex::Array4<const T>& f,
      50             :             const int& i, const int& j, const int& k, const int& m,
      51             :             const Set::Scalar dx[AMREX_SPACEDIM],
      52             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
      53             :     {
      54   113833255 :         if (stencil[0] == StencilType::Lo)
      55    30667257 :             return (f(i, j, k, m) - f(i - 1, j, k, m)) / dx[0]; // 1st order stencil
      56   103610854 :         else if (stencil[0] == StencilType::Hi)
      57    30667167 :             return (f(i + 1, j, k, m) - f(i, j, k, m)) / dx[0]; // 1st order stencil
      58             :         else
      59   317268429 :             return (f(i + 1, j, k, m) - f(i - 1, j, k, m)) * 0.5 / dx[0];
      60             :     };
      61             :     [[nodiscard]] AMREX_FORCE_INLINE
      62             :     static std::pair<Set::Scalar,T>
      63             :     Dsplit( const amrex::Array4<const T>& f,
      64             :             const int& i, const int& j, const int& k, const int& m,
      65             :             const Set::Scalar dx[AMREX_SPACEDIM],
      66             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
      67             :     {
      68           0 :         if (stencil[0] == StencilType::Lo)
      69             :             return std::make_pair(
      70           0 :                 1.0 / dx[0],
      71           0 :                 -f(i - 1, j, k, m) / dx[0]
      72           0 :                 ); // 1st order
      73           0 :         else if (stencil[0] == StencilType::Hi)
      74             :             return std::make_pair(
      75           0 :                 -1.0 / dx[0],
      76           0 :                 f(i + 1, j, k, m) / dx[0]
      77           0 :                 ); // 1st order
      78             :         else
      79             :             return std::make_pair(
      80           0 :                 0.0,
      81           0 :                 (f(i + 1, j, k, m) - f(i - 1, j, k, m)) * 0.5 / dx[0]
      82           0 :                 );
      83             :     };
      84             : };
      85             : 
      86             : template<class T>
      87             : struct Stencil<T, 0, 1, 0>
      88             : {
      89             :     [[nodiscard]] AMREX_FORCE_INLINE
      90             :         static T D(const amrex::Array4<const T>& f,
      91             :             const int& i, const int& j, const int& k, const int& m,
      92             :             const Set::Scalar dx[AMREX_SPACEDIM],
      93             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
      94             :     {
      95   113833255 :         if (stencil[1] == StencilType::Lo)
      96    29696267 :             return (f(i, j, k, m) - f(i, j - 1, k, m)) / dx[1];
      97   103934552 :         else if (stencil[1] == StencilType::Hi)
      98    29696177 :             return (f(i, j + 1, k, m) - f(i, j, k, m)) / dx[1];
      99             :         else
     100   319210047 :             return (f(i, j + 1, k, m) - f(i, j - 1, k, m)) * 0.5 / dx[1];
     101             :     };
     102             :     [[nodiscard]] AMREX_FORCE_INLINE
     103             :     static std::pair<Set::Scalar,T>
     104             :     Dsplit(const amrex::Array4<const T>& f,
     105             :             const int& i, const int& j, const int& k, const int& m,
     106             :             const Set::Scalar dx[AMREX_SPACEDIM],
     107             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     108             :     {
     109           0 :         if (stencil[1] == StencilType::Lo)
     110             :             return std::make_pair(
     111           0 :                 1.0 / dx[1],
     112           0 :                 - f(i, j - 1, k, m) / dx[1]
     113           0 :                 );
     114           0 :         else if (stencil[1] == StencilType::Hi)
     115             :             return std::make_pair(
     116           0 :                 - 1.0 / dx[1],
     117           0 :                 f(i, j + 1, k, m) / dx[1]
     118           0 :                 );
     119             :         else
     120             :             return std::make_pair(
     121           0 :                 0.0,
     122           0 :                 (f(i, j + 1, k, m) - f(i, j - 1, k, m)) * 0.5 / dx[1]
     123           0 :                 );
     124             :     };
     125             : };
     126             : 
     127             : template<class T>
     128             : struct Stencil<T, 0, 0, 1>
     129             : {
     130             :     [[nodiscard]] AMREX_FORCE_INLINE
     131             :         static T D(const amrex::Array4<const T>& f,
     132             :             const int& i, const int& j, const int& k, const int& m,
     133             :             const Set::Scalar dx[AMREX_SPACEDIM],
     134             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     135             :     {
     136    35200721 :         if (stencil[2] == StencilType::Lo)
     137    24720000 :             return (f(i, j, k, m) - f(i, j, k - 1, m)) / dx[2];
     138    26960721 :         else if (stencil[2] == StencilType::Hi)
     139    24720000 :             return (f(i, j, k + 1, m) - f(i, j, k, m)) / dx[2];
     140             :         else
     141    61256463 :             return (f(i, j, k + 1, m) - f(i, j, k - 1, m)) * 0.5 / dx[2];
     142             :     };
     143             :     [[nodiscard]] AMREX_FORCE_INLINE
     144             :     static std::pair<Set::Scalar, T>
     145             :     Dsplit(const amrex::Array4<const T>& f,
     146             :             const int& i, const int& j, const int& k, const int& m,
     147             :             const Set::Scalar dx[AMREX_SPACEDIM],
     148             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     149             :     {
     150           0 :         if (stencil[2] == StencilType::Lo)
     151             :             return std::make_pair(
     152           0 :                 1.0 / dx[2],
     153           0 :                 -f(i, j, k - 1, m) / dx[2]
     154           0 :                 );
     155           0 :         else if (stencil[2] == StencilType::Hi)
     156             :             return std::make_pair(
     157           0 :                 -1.0 / dx[2],
     158           0 :                 f(i, j, k + 1, m) / dx[2]
     159           0 :                 );
     160             :         else
     161             :             return std::make_pair(
     162           0 :                 0.0,
     163           0 :                 (f(i, j, k + 1, m) - f(i, j, k - 1, m)) * 0.5 / dx[2]
     164           0 :                 );
     165             :     };
     166             : };
     167             : 
     168             : //
     169             : // SECOND order derivatives
     170             : //
     171             : 
     172             : template<class T>
     173             : struct Stencil<T, 2, 0, 0>
     174             : {
     175             :     [[nodiscard]] AMREX_FORCE_INLINE
     176             :         static T D(const amrex::Array4<const T>& f,
     177             :             const int& i, const int& j, const int& k, const int& m,
     178             :             const Set::Scalar dx[AMREX_SPACEDIM],
     179             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     180             :     {
     181   363410026 :         if (stencil[0] == StencilType::Central)
     182  1453473332 :             return (f(i + 1, j, k, m) - 2.0 * f(i, j, k, m) + f(i - 1, j, k, m)) / dx[0] / dx[0];
     183             :         else
     184       83728 :             return 0.0 * f(i, j, k, m); // TODO this is not a great way to do this
     185             :     };
     186             : };
     187             : 
     188             : template<class T>
     189             : struct Stencil<T, 0, 2, 0>
     190             : {
     191             :     [[nodiscard]] AMREX_FORCE_INLINE
     192             :         static T D(const amrex::Array4<const T>& f,
     193             :             const int& i, const int& j, const int& k, const int& m,
     194             :             const Set::Scalar dx[AMREX_SPACEDIM],
     195             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     196             :     {
     197   363447052 :         if (stencil[1] == StencilType::Central)
     198  1453619036 :             return (f(i, j + 1, k, m) - 2.0 * f(i, j, k, m) + f(i, j - 1, k, m)) / dx[1] / dx[1];
     199             :         else
     200       84928 :             return 0.0 * f(i, j, k, m); // TODO this is not a great way to do this
     201             :     };
     202             : };
     203             : 
     204             : template<class T>
     205             : struct Stencil<T, 0, 0, 2>
     206             : {
     207             :     [[nodiscard]] AMREX_FORCE_INLINE
     208             :         static T D(const amrex::Array4<const T>& f,
     209             :             const int& i, const int& j, const int& k, const int& m,
     210             :             const Set::Scalar dx[AMREX_SPACEDIM],
     211             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     212             :     {
     213     5965565 :         if (stencil[2] == StencilType::Central)
     214    23862258 :             return (f(i, j, k + 1, m) - 2.0 * f(i, j, k, m) + f(i, j, k - 1, m)) / dx[2] / dx[2];
     215             :         else
     216           0 :             return 0.0 * f(i, j, k, m); // TODO this is not a great way to do this
     217             :     };
     218             : };
     219             : 
     220             : template<class T>
     221             : struct Stencil<T, 1, 1, 0>
     222             : {
     223             :     [[nodiscard]] AMREX_FORCE_INLINE
     224             :         static T D(const amrex::Array4<const T>& f,
     225             :             const int& i, const int& j, const int& k, const int& m,
     226             :             const Set::Scalar dx[AMREX_SPACEDIM],
     227             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     228             :     {
     229    31077186 :         int ihi = 1, ilo = 1, jhi = 1, jlo = 1;
     230    31077186 :         Set::Scalar ifac = 0.5, jfac = 0.5;
     231    31077186 :         if (stencil[0] == StencilType::Hi) { ilo = 0; ifac = 1.0; }
     232    31077186 :         if (stencil[0] == StencilType::Lo) { ihi = 0; ifac = 1.0; }
     233    31077186 :         if (stencil[1] == StencilType::Hi) { jlo = 0; jfac = 1.0; }
     234    31077186 :         if (stencil[1] == StencilType::Lo) { jhi = 0; jfac = 1.0; }
     235             : 
     236   155386430 :         return ifac * jfac * (f(i + ihi, j + jhi, k, m) + f(i - ilo, j - jlo, k, m) - f(i + ihi, j - jlo, k, m) - f(i - ilo, j + jhi, k, m)) / (dx[0] * dx[1]);
     237             :     };
     238             : };
     239             : template<class T>
     240             : struct Stencil<T, 1, 0, 1>
     241             : {
     242             :     [[nodiscard]] AMREX_FORCE_INLINE
     243             :         static T D(const amrex::Array4<const T>& f,
     244             :             const int& i, const int& j, const int& k, const int& m,
     245             :             const Set::Scalar dx[AMREX_SPACEDIM],
     246             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     247             :     {
     248     5130237 :         int khi = 1, klo = 1, ihi = 1, ilo = 1;
     249     5130237 :         Set::Scalar kfac = 0.5, ifac = 0.5;
     250     5130237 :         if (stencil[0] == StencilType::Hi) { ilo = 0; ifac = 1.0; }
     251     5130237 :         if (stencil[0] == StencilType::Lo) { ihi = 0; ifac = 1.0; }
     252     5130237 :         if (stencil[2] == StencilType::Hi) { klo = 0; kfac = 1.0; }
     253     5130237 :         if (stencil[2] == StencilType::Lo) { khi = 0; kfac = 1.0; }
     254             : 
     255    25651185 :         return kfac * ifac * (f(i + ihi, j, k + khi, m) + f(i - ilo, j, k - klo, m) - f(i + ihi, j, k - klo, m) - f(i - ilo, j, k + khi, m)) / (dx[0] * dx[2]);
     256             :     };
     257             : };
     258             : template<class T>
     259             : struct Stencil<T, 0, 1, 1>
     260             : {
     261             :     [[nodiscard]] AMREX_FORCE_INLINE
     262             :         static T D(const amrex::Array4<const T>& f,
     263             :             const int& i, const int& j, const int& k, const int& m,
     264             :             const Set::Scalar dx[AMREX_SPACEDIM],
     265             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     266             :     {
     267     5130237 :         int jhi = 1, jlo = 1, khi = 1, klo = 1;
     268     5130237 :         Set::Scalar jfac = 0.5, kfac = 0.5;
     269     5130237 :         if (stencil[1] == StencilType::Hi) { jlo = 0; jfac = 1.0; }
     270     5130237 :         if (stencil[1] == StencilType::Lo) { jhi = 0; jfac = 1.0; }
     271     5130237 :         if (stencil[2] == StencilType::Hi) { klo = 0; kfac = 1.0; }
     272     5130237 :         if (stencil[2] == StencilType::Lo) { khi = 0; kfac = 1.0; }
     273             : 
     274    25651185 :         return jfac * kfac * (f(i, j + jhi, k + khi, m) + f(i, j - jlo, k - klo, m) - f(i, j + jhi, k - klo, m) - f(i, j - jlo, k + khi, m)) / (dx[1] * dx[2]);
     275             :     };
     276             : };
     277             : 
     278             : //
     279             : // FOURTH order derivatives
     280             : //
     281             : 
     282             : template<class T>
     283             : struct Stencil<T, 4, 0, 0>
     284             : {
     285             :     [[nodiscard]] AMREX_FORCE_INLINE
     286             :         static T D(const amrex::Array4<const T>& f,
     287             :             const int& i, const int& j, const int& k, const int& m,
     288             :             const Set::Scalar dx[AMREX_SPACEDIM])
     289             :     {
     290     6999430 :         return ((f(i + 2, j, k, m)) - 4. * (f(i + 1, j, k, m)) + 6. * (f(i, j, k, m)) - 4. * (f(i - 1, j, k, m)) + (f(i - 2, j, k, m))) /
     291     1399886 :             (dx[0] * dx[0] * dx[0] * dx[0]);
     292             :     };
     293             : };
     294             : template<class T>
     295             : struct Stencil<T, 0, 4, 0>
     296             : {
     297             :     [[nodiscard]] AMREX_FORCE_INLINE
     298             :         static T D(const amrex::Array4<const T>& f,
     299             :             const int& i, const int& j, const int& k, const int& m,
     300             :             const Set::Scalar dx[AMREX_SPACEDIM])
     301             :     {
     302     5636570 :         return ((f(i, j + 2, k, m)) - 4. * (f(i, j + 1, k, m)) + 6. * (f(i, j, k, m)) - 4. * (f(i, j - 1, k, m)) + (f(i, j - 2, k, m))) /
     303     1399886 :             (dx[1] * dx[1] * dx[1] * dx[1]);
     304             :     };
     305             : };
     306             : template<class T>
     307             : struct Stencil<T, 0, 0, 4>
     308             : {
     309             :     [[nodiscard]] AMREX_FORCE_INLINE
     310             :         static T D(const amrex::Array4<const T>& f,
     311             :             const int& i, const int& j, const int& k, const int& m,
     312             :             const Set::Scalar dx[AMREX_SPACEDIM])
     313             :     {
     314      179685 :         return ((f(i, j, k + 2, m)) - 4. * (f(i, j, k + 1, m)) + 6. * (f(i, j, k, m)) - 4. * (f(i, j, k - 1, m)) + (f(i, j, k - 2, m))) /
     315       35937 :             (dx[2] * dx[2] * dx[2] * dx[2]);
     316             :     };
     317             : };
     318             : 
     319             : /// Compute
     320             : /// \f[ \frac{\partial^4}{\partial^3 x_1\partial x_2\f]
     321             : template<class T>
     322             : struct Stencil<T, 3, 1, 0>
     323             : {
     324             :     [[nodiscard]] AMREX_FORCE_INLINE
     325             :         static T D(const amrex::Array4<const T>& f,
     326             :             const int& i, const int& j, const int& k, const int& m,
     327             :             const Set::Scalar dx[AMREX_SPACEDIM])
     328             :     {
     329     4236684 :         return    ((-f(i + 2, j + 2, k, m) + 8.0 * f(i + 2, j + 1, k, m) - 8.0 * f(i + 2, j - 1, k, m) + f(i + 2, j - 2, k, m))
     330     5599544 :             - 2 * (-f(i + 1, j + 2, k, m) + 8.0 * f(i + 1, j + 1, k, m) - 8.0 * f(i + 1, j - 1, k, m) + f(i + 1, j - 2, k, m))
     331     5599544 :             + 2 * (-f(i - 1, j + 2, k, m) + 8.0 * f(i - 1, j + 1, k, m) - 8.0 * f(i - 1, j - 1, k, m) + f(i - 1, j - 2, k, m))
     332     5599544 :             - (-f(i - 2, j + 2, k, m) + 8.0 * f(i - 2, j + 1, k, m) - 8.0 * f(i - 2, j - 1, k, m) + f(i - 2, j - 2, k, m))) /
     333     1399886 :             (24.0 * dx[0] * dx[0] * dx[0] * dx[1]);
     334             :     };
     335             : };
     336             : 
     337             : /// Compute
     338             : /// \f[ \frac{\partial^4}{\partial^3 x_2\partial x_1\f]
     339             : template<class T>
     340             : struct Stencil<T, 1, 3, 0>
     341             : {
     342             :     [[nodiscard]] AMREX_FORCE_INLINE
     343             :         static T D(const amrex::Array4<const T>& f,
     344             :             const int& i, const int& j, const int& k, const int& m,
     345             :             const Set::Scalar dx[AMREX_SPACEDIM])
     346             :     {
     347     4236684 :         return ((-f(i + 2, j + 2, k, m) + 8.0 * f(i + 1, j + 2, k, m) - 8.0 * f(i - 1, j + 2, k, m) + f(i - 2, j + 2, k, m))
     348     5599544 :             - 2 * (-f(i + 2, j + 1, k, m) + 8.0 * f(i + 1, j + 1, k, m) - 8.0 * f(i - 1, j + 1, k, m) + f(i - 2, j + 1, k, m))
     349     5599544 :             + 2 * (-f(i + 2, j - 1, k, m) + 8.0 * f(i + 1, j - 1, k, m) - 8.0 * f(i - 1, j - 1, k, m) + f(i - 2, j - 1, k, m))
     350     5599544 :             - (-f(i + 2, j - 2, k, m) + 8.0 * f(i + 1, j - 2, k, m) - 8.0 * f(i - 1, j - 2, k, m) + f(i - 2, j - 2, k, m))) /
     351     1399886 :             (24.0 * dx[0] * dx[1] * dx[1] * dx[1]);
     352             :     };
     353             : };
     354             : 
     355             : /// Compute
     356             : /// \f[ \frac{\partial^4}{\partial^3 x_2\partial x_3\f]
     357             : template<class T>
     358             : struct Stencil<T, 0, 3, 1>
     359             : {
     360             :     [[nodiscard]] AMREX_FORCE_INLINE
     361             :         static T D(const amrex::Array4<const T>& f,
     362             :             const int& i, const int& j, const int& k, const int& m,
     363             :             const Set::Scalar dx[AMREX_SPACEDIM])
     364             :     {
     365      143748 :         return    ((-f(i, j + 2, k + 2, m) + 8.0 * f(i, j + 2, k + 1, m) - 8.0 * f(i, j + 2, k - 1, m) + f(i, j + 2, k - 2, m))
     366      143748 :             - 2 * (-f(i, j + 1, k + 2, m) + 8.0 * f(i, j + 1, k + 1, m) - 8.0 * f(i, j + 1, k - 1, m) + f(i, j + 1, k - 2, m))
     367      143748 :             + 2 * (-f(i, j - 1, k + 2, m) + 8.0 * f(i, j - 1, k + 1, m) - 8.0 * f(i, j - 1, k - 1, m) + f(i, j - 1, k - 2, m))
     368      143748 :             - (-f(i, j - 2, k + 2, m) + 8.0 * f(i, j - 2, k + 1, m) - 8.0 * f(i, j - 2, k - 1, m) + f(i, j - 2, k - 2, m))) /
     369       35937 :             (24.0 * dx[1] * dx[1] * dx[1] * dx[2]);
     370             :     };
     371             : };
     372             : /// \brief Compute \f[ \frac{\partial^4}{\partial^3 x_3\partial x_2}\f]
     373             : template<class T>
     374             : struct Stencil<T, 0, 1, 3>
     375             : {
     376             :     [[nodiscard]] AMREX_FORCE_INLINE
     377             :         static T D(const amrex::Array4<const T>& f,
     378             :             const int& i, const int& j, const int& k, const int& m,
     379             :             const Set::Scalar dx[AMREX_SPACEDIM])
     380             :     {
     381      143748 :         return    ((-f(i, j + 2, k + 2, m) + 8.0 * f(i, j + 1, k + 2, m) - 8.0 * f(i, j - 1, k + 2, m) + f(i, j - 2, k + 2, m))
     382      143748 :             - 2 * (-f(i, j + 2, k + 1, m) + 8.0 * f(i, j + 1, k + 1, m) - 8.0 * f(i, j - 1, k + 1, m) + f(i, j - 2, k + 1, m))
     383      143748 :             + 2 * (-f(i, j + 2, k - 1, m) + 8.0 * f(i, j + 1, k - 1, m) - 8.0 * f(i, j - 1, k - 1, m) + f(i, j - 2, k - 1, m))
     384      143748 :             - (-f(i, j + 2, k - 2, m) + 8.0 * f(i, j + 1, k - 2, m) - 8.0 * f(i, j - 1, k - 2, m) + f(i, j - 2, k - 2, m))) /
     385       35937 :             (24.0 * dx[1] * dx[2] * dx[2] * dx[2]);
     386             :     };
     387             : };
     388             : /// \brief Compute \f[ \frac{\partial^4}{\partial^3 x_3\partial x_1}\f]
     389             : template<class T>
     390             : struct Stencil<T, 1, 0, 3>
     391             : {
     392             :     [[nodiscard]] AMREX_FORCE_INLINE
     393             :         static T D(const amrex::Array4<const T>& f,
     394             :             const int& i, const int& j, const int& k, const int& m,
     395             :             const Set::Scalar dx[AMREX_SPACEDIM])
     396             :     {
     397      143748 :         return    ((-f(i + 2, j, k + 2, m) + 8.0 * f(i + 1, j, k + 2, m) - 8.0 * f(i - 1, j, k + 2, m) + f(i - 2, j, k + 2, m))
     398      143748 :             - 2 * (-f(i + 2, j, k + 1, m) + 8.0 * f(i + 1, j, k + 1, m) - 8.0 * f(i - 1, j, k + 1, m) + f(i - 2, j, k + 1, m))
     399      143748 :             + 2 * (-f(i + 2, j, k - 1, m) + 8.0 * f(i + 1, j, k - 1, m) - 8.0 * f(i - 1, j, k - 1, m) + f(i - 2, j, k - 1, m))
     400      143748 :             - (-f(i + 2, j, k - 2, m) + 8.0 * f(i + 1, j, k - 2, m) - 8.0 * f(i - 1, j, k - 2, m) + f(i - 2, j, k - 2, m))) /
     401       35937 :             (24.0 * dx[0] * dx[2] * dx[2] * dx[2]);
     402             : 
     403             :     };
     404             : };
     405             : /// \brief Compute \f[ \frac{\partial^4}{\partial^3 x_1\partial x_3}\f]
     406             : template<class T>
     407             : struct Stencil<T, 3, 0, 1>
     408             : {
     409             :     [[nodiscard]] AMREX_FORCE_INLINE
     410             :         static T D(const amrex::Array4<const T>& f,
     411             :             const int& i, const int& j, const int& k, const int& m,
     412             :             const Set::Scalar dx[AMREX_SPACEDIM])
     413             :     {
     414      143748 :         return    ((-f(i + 2, j, k + 2, m) + 8.0 * f(i + 2, j, k + 1, m) - 8.0 * f(i + 2, j, k - 1, m) + f(i + 2, j, k - 2, m))
     415      143748 :             - 2 * (-f(i + 1, j, k + 2, m) + 8.0 * f(i + 1, j, k + 1, m) - 8.0 * f(i + 1, j, k - 1, m) + f(i + 1, j, k - 2, m))
     416      143748 :             + 2 * (-f(i - 1, j, k + 2, m) + 8.0 * f(i - 1, j, k + 1, m) - 8.0 * f(i - 1, j, k - 1, m) + f(i - 1, j, k - 2, m))
     417      143748 :             - (-f(i - 2, j, k + 2, m) + 8.0 * f(i - 2, j, k + 1, m) - 8.0 * f(i - 2, j, k - 1, m) + f(i - 2, j, k - 2, m))) /
     418       35937 :             (24.0 * dx[0] * dx[0] * dx[0] * dx[2]);
     419             : 
     420             :     };
     421             : };
     422             : /// \brief Compute \f[ \frac{\partial^4}{\partial^2 x_1\partial^2 x_2}\f]
     423             : template<class T>
     424             : struct Stencil<T, 2, 2, 0>
     425             : {
     426             :     [[nodiscard]] AMREX_FORCE_INLINE
     427             :         static T D(const amrex::Array4<const T>& f,
     428             :             const int& i, const int& j, const int& k, const int& m,
     429             :             const Set::Scalar dx[AMREX_SPACEDIM])
     430             :     {
     431     5599544 :         return     (-(-f(i + 2, j + 2, k, m) + 16.0 * f(i + 1, j + 2, k, m) - 30.0 * f(i, j + 2, k, m) + 16.0 * f(i - 1, j + 2, k, m) - f(i - 2, j + 2, k, m))
     432     7036456 :             + 16 * (-f(i + 2, j + 1, k, m) + 16.0 * f(i + 1, j + 1, k, m) - 30.0 * f(i, j + 1, k, m) + 16.0 * f(i - 1, j + 1, k, m) - f(i - 2, j + 1, k, m))
     433     6999430 :             - 30 * (-f(i + 2, j, k, m) + 16.0 * f(i + 1, j, k, m) - 30.0 * f(i, j, k, m) + 16.0 * f(i - 1, j, k, m) - f(i - 2, j, k, m))
     434     6999430 :             + 16 * (-f(i + 2, j - 1, k, m) + 16.0 * f(i + 1, j - 1, k, m) - 30.0 * f(i, j - 1, k, m) + 16.0 * f(i - 1, j - 1, k, m) - f(i - 2, j - 1, k, m))
     435     6999430 :             - (-f(i + 2, j - 2, k, m) + 16.0 * f(i + 1, j - 2, k, m) - 30.0 * f(i, j - 2, k, m) + 16.0 * f(i - 1, j - 2, k, m) - f(i - 2, j - 2, k, m))) /
     436     1399886 :             (144.0 * dx[0] * dx[0] * dx[1] * dx[1]);
     437             :     };
     438             : };
     439             : 
     440             : /// \brief Compute \f[ \frac{\partial^4}{\partial^2 x_2\partial^2 x_3}\f]
     441             : template<class T>
     442             : struct Stencil<T, 0, 2, 2>
     443             : {
     444             :     [[nodiscard]] AMREX_FORCE_INLINE
     445             :         static T D(const amrex::Array4<const T>& f,
     446             :             const int& i, const int& j, const int& k, const int& m,
     447             :             const Set::Scalar dx[AMREX_SPACEDIM])
     448             :     {
     449      143748 :         return     (-(-f(i, j + 2, k + 2, m) + 16.0 * f(i, j + 2, k + 1, m) - 30.0 * f(i, j + 2, k, m) + 16.0 * f(i, j + 2, k - 1, m) - f(i, j + 2, k - 2, m))
     450      215622 :             + 16 * (-f(i, j + 1, k + 2, m) + 16.0 * f(i, j + 1, k + 1, m) - 30.0 * f(i, j + 1, k, m) + 16.0 * f(i, j + 1, k - 1, m) - f(i, j + 1, k - 2, m))
     451      179685 :             - 30 * (-f(i, j, k + 2, m) + 16.0 * f(i, j, k + 1, m) - 30.0 * f(i, j, k, m) + 16.0 * f(i, j, k - 1, m) - f(i, j, k - 2, m))
     452      179685 :             + 16 * (-f(i, j - 1, k + 2, m) + 16.0 * f(i, j - 1, k + 1, m) - 30.0 * f(i, j - 1, k, m) + 16.0 * f(i, j - 1, k - 1, m) - f(i, j - 1, k - 2, m))
     453      179685 :             - (-f(i, j - 2, k + 2, m) + 16.0 * f(i, j - 2, k + 1, m) - 30.0 * f(i, j - 2, k, m) + 16.0 * f(i, j - 2, k - 1, m) - f(i, j - 2, k - 2, m))) /
     454       35937 :             (144.0 * dx[0] * dx[0] * dx[2] * dx[2]);
     455             :     };
     456             : };
     457             : /// \brief Compute \f[ \frac{\partial^4}{\partial^2 x_1\partial^2 x_3}\f]
     458             : template<class T>
     459             : struct Stencil<T, 2, 0, 2>
     460             : {
     461             :     [[nodiscard]] AMREX_FORCE_INLINE
     462             :         static T D(const amrex::Array4<const T>& f,
     463             :             const int& i, const int& j, const int& k, const int& m,
     464             :             const Set::Scalar dx[AMREX_SPACEDIM])
     465             :     {
     466      143748 :         return     (-(-f(i + 2, j, k + 2, m) + 16.0 * f(i + 2, j, k + 1, m) - 30.0 * f(i + 2, j, k, m) + 16.0 * f(i + 2, j, k - 1, m) - f(i + 2, j, k - 2, m))
     467      215622 :             + 16 * (-f(i + 1, j, k + 2, m) + 16.0 * f(i + 1, j, k + 1, m) - 30.0 * f(i + 1, j, k, m) + 16.0 * f(i + 1, j, k - 1, m) - f(i + 1, j, k - 2, m))
     468      179685 :             - 30 * (-f(i, j, k + 2, m) + 16.0 * f(i, j, k + 1, m) - 30.0 * f(i, j, k, m) + 16.0 * f(i, j, k - 1, m) - f(i, j, k - 2, m))
     469      179685 :             + 16 * (-f(i - 1, j, k + 2, m) + 16.0 * f(i - 1, j, k + 1, m) - 30.0 * f(i - 1, j, k, m) + 16.0 * f(i - 1, j, k - 1, m) - f(i - 1, j, k - 2, m))
     470      179685 :             - (-f(i - 2, j, k + 2, m) + 16.0 * f(i - 2, j, k + 1, m) - 30.0 * f(i - 2, j, k, m) + 16.0 * f(i - 2, j, k - 1, m) - f(i - 2, j, k - 2, m))) /
     471       35937 :             (144.0 * dx[0] * dx[0] * dx[2] * dx[2]);
     472             :     };
     473             : };
     474             : 
     475             : 
     476             : /// \brief Compute \f[ \frac{\partial^4}{\partial^2 x_1\partial x_2\partial x_3}\f]
     477             : template<class T>
     478             : struct Stencil<T, 2, 1, 1>
     479             : {
     480             :     [[nodiscard]] AMREX_FORCE_INLINE
     481             :         static T D(const amrex::Array4<const T>& f,
     482             :             const int& i, const int& j, const int& k, const int& m,
     483             :             const Set::Scalar dx[AMREX_SPACEDIM])
     484             :     {
     485      107811 :         return    (+(f(i + 1, j + 1, k + 1, m) - 2.0 * f(i, j + 1, k + 1, m) + f(i - 1, j + 1, k + 1, m))
     486      107811 :             - (f(i + 1, j - 1, k + 1, m) - 2.0 * f(i, j - 1, k + 1, m) + f(i - 1, j - 1, k + 1, m))
     487      107811 :             - (f(i + 1, j + 1, k - 1, m) - 2.0 * f(i, j + 1, k - 1, m) + f(i - 1, j + 1, k - 1, m))
     488      107811 :             + (f(i + 1, j - 1, k - 1, m) - 2.0 * f(i, j - 1, k - 1, m) + f(i - 1, j - 1, k - 1, m)))
     489       35937 :             / (4.0 * dx[0] * dx[0] * dx[1] * dx[2]);
     490             : 
     491             :     };
     492             : };
     493             : /// \brief Compute \f[ \frac{\partial^4}{\partial x_1\partial^2 x_2\partial x_3}\f]
     494             : template<class T>
     495             : struct Stencil<T, 1, 2, 1>
     496             : {
     497             :     [[nodiscard]] AMREX_FORCE_INLINE
     498             :         static T D(const amrex::Array4<const T>& f,
     499             :             const int& i, const int& j, const int& k, const int& m,
     500             :             const Set::Scalar dx[AMREX_SPACEDIM])
     501             :     {
     502      107811 :         return    (+(f(i + 1, j + 1, k + 1, m) - 2.0 * f(i + 1, j, k + 1, m) + f(i + 1, j - 1, k + 1, m))
     503      107811 :             - (f(i - 1, j + 1, k + 1, m) - 2.0 * f(i - 1, j, k + 1, m) + f(i - 1, j - 1, k + 1, m))
     504      107811 :             - (f(i + 1, j + 1, k - 1, m) - 2.0 * f(i + 1, j, k - 1, m) + f(i + 1, j - 1, k - 1, m))
     505      107811 :             + (f(i - 1, j + 1, k - 1, m) - 2.0 * f(i - 1, j, k - 1, m) + f(i - 1, j - 1, k - 1, m)))
     506       35937 :             / (4.0 * dx[0] * dx[1] * dx[1] * dx[2]);
     507             : 
     508             :     };
     509             : };
     510             : /// \brief Compute \f[ \frac{\partial^4}{\partial x_1\partial x_2\partial^2 x_3}\f]
     511             : template<class T>
     512             : struct Stencil<T, 1, 1, 2>
     513             : {
     514             :     [[nodiscard]] AMREX_FORCE_INLINE
     515             :         static T D(const amrex::Array4<const T>& f,
     516             :             const int& i, const int& j, const int& k, const int& m,
     517             :             const Set::Scalar dx[AMREX_SPACEDIM])
     518             :     {
     519      107811 :         return    (+(f(i + 1, j + 1, k + 1, m) - 2.0 * f(i + 1, j + 1, k, m) + f(i + 1, j + 1, k - 1, m))
     520      107811 :             - (f(i - 1, j + 1, k + 1, m) - 2.0 * f(i - 1, j + 1, k, m) + f(i - 1, j + 1, k - 1, m))
     521      107811 :             - (f(i + 1, j - 1, k + 1, m) - 2.0 * f(i + 1, j - 1, k, m) + f(i + 1, j - 1, k - 1, m))
     522      107811 :             + (f(i - 1, j - 1, k + 1, m) - 2.0 * f(i - 1, j - 1, k, m) + f(i - 1, j - 1, k - 1, m)))
     523       35937 :             / (4.0 * dx[0] * dx[1] * dx[1] * dx[2]);
     524             : 
     525             :     };
     526             : };
     527             : 
     528             : [[nodiscard]] AMREX_FORCE_INLINE
     529             : Set::Scalar
     530             : Laplacian(const amrex::Array4<const Set::Scalar>& f,
     531             :     const int& i, const int& j, const int& k, const int& m,
     532             :     const Set::Scalar dx[AMREX_SPACEDIM])
     533             : {
     534   332332840 :     Set::Scalar ret = 0.0;
     535   332332840 :     ret += (Numeric::Stencil<Set::Scalar, 2, 0, 0>::D(f, i, j, k, m, dx));
     536             : #if AMREX_SPACEDIM > 1
     537   332332840 :     ret += (Numeric::Stencil<Set::Scalar, 0, 2, 0>::D(f, i, j, k, m, dx));
     538             : #if AMREX_SPACEDIM > 2
     539      835328 :     ret += (Numeric::Stencil<Set::Scalar, 0, 0, 2>::D(f, i, j, k, m, dx));
     540             : #endif
     541             : #endif
     542   332332840 :     return ret;
     543             : }
     544             : 
     545             : [[nodiscard]] AMREX_FORCE_INLINE
     546             : Set::Vector
     547             : Laplacian(const amrex::Array4<const Set::Vector>& f,
     548             :     const int& i, const int& j, const int& k,
     549             :     const Set::Scalar dx[AMREX_SPACEDIM])
     550             : {
     551           0 :     Set::Vector ret = Set::Vector::Zero();
     552           0 :     ret += (Numeric::Stencil<Set::Vector, 2, 0, 0>::D(f, i, j, k, 0, dx));
     553             : #if AMREX_SPACEDIM > 1
     554           0 :     ret += (Numeric::Stencil<Set::Vector, 0, 2, 0>::D(f, i, j, k, 0, dx));
     555             : #if AMREX_SPACEDIM > 2
     556           0 :     ret += (Numeric::Stencil<Set::Vector, 0, 0, 2>::D(f, i, j, k, 0, dx));
     557             : #endif
     558             : #endif
     559           0 :     return ret;
     560             : }
     561             : 
     562             : [[nodiscard]] AMREX_FORCE_INLINE
     563             : Set::Vector
     564             : Divergence(const amrex::Array4<const Set::Matrix>& dw,
     565             :     const int& i, const int& j, const int& k,
     566             :     const Set::Scalar DX[AMREX_SPACEDIM],
     567             :     std::array<StencilType, AMREX_SPACEDIM>& stencil = DefaultType)
     568             : {
     569      160392 :     Set::Vector ret = Set::Vector::Zero();
     570             : 
     571      160392 :     if (stencil[0] == StencilType::Central)
     572             :     {
     573      782610 :         AMREX_D_TERM(ret(0) += (dw(i + 1, j, k)(0, 0) - dw(i - 1, j, k)(0, 0)) / 2. / DX[0];,
     574             :             ret(1) += (dw(i + 1, j, k)(1, 0) - dw(i - 1, j, k)(1, 0)) / 2. / DX[0];,
     575             :             ret(2) += (dw(i + 1, j, k)(2, 0) - dw(i - 1, j, k)(2, 0)) / 2. / DX[0];)
     576             :     }
     577        7110 :     else if (stencil[0] == StencilType::Lo)
     578             :     {
     579       17700 :         AMREX_D_TERM(ret(0) += (dw(i, j, k)(0, 0) - dw(i - 1, j, k)(0, 0)) / DX[0];,
     580             :             ret(1) += (dw(i, j, k)(1, 0) - dw(i - 1, j, k)(1, 0)) / DX[0];,
     581             :             ret(2) += (dw(i, j, k)(2, 0) - dw(i - 1, j, k)(2, 0)) / DX[0];)
     582             :     }
     583        3570 :     else if (stencil[0] == StencilType::Hi)
     584             :     {
     585       17850 :         AMREX_D_TERM(ret(0) += (dw(i + 1, j, k)(0, 0) - dw(i, j, k)(0, 0)) / DX[0];,
     586             :             ret(1) += (dw(i + 1, j, k)(1, 0) - dw(i, j, k)(1, 0)) / DX[0];,
     587             :             ret(2) += (dw(i + 1, j, k)(2, 0) - dw(i, j, k)(2, 0)) / DX[0];)
     588             :     }
     589             : 
     590             : #if AMREX_SPACEDIM > 1
     591      160392 :     if (stencil[1] == StencilType::Central)
     592             :     {
     593      770010 :         AMREX_D_TERM(ret(0) += (dw(i, j + 1, k)(0, 1) - dw(i, j - 1, k)(0, 1)) / 2. / DX[1];,
     594             :             ret(1) += (dw(i, j + 1, k)(1, 1) - dw(i, j - 1, k)(1, 1)) / 2. / DX[1];,
     595             :             ret(2) += (dw(i, j + 1, k)(2, 1) - dw(i, j - 1, k)(2, 1)) / 2. / DX[1];)
     596             :     }
     597        9630 :     else if (stencil[1] == StencilType::Lo)
     598             :     {
     599       24000 :         AMREX_D_TERM(ret(0) += (dw(i, j, k)(0, 1) - dw(i, j - 1, k)(0, 1)) / DX[1];,
     600             :             ret(1) += (dw(i, j, k)(1, 1) - dw(i, j - 1, k)(1, 1)) / DX[1];,
     601             :             ret(2) += (dw(i, j, k)(2, 1) - dw(i, j - 1, k)(2, 1)) / DX[1];)
     602             :     }
     603        4830 :     else if (stencil[1] == StencilType::Hi)
     604             :     {
     605       24150 :         AMREX_D_TERM(ret(0) += (dw(i, j + 1, k)(0, 1) - dw(i, j, k)(0, 1)) / DX[1];,
     606             :             ret(1) += (dw(i, j + 1, k)(1, 1) - dw(i, j, k)(1, 1)) / DX[1];,
     607             :             ret(2) += (dw(i, j + 1, k)(2, 1) - dw(i, j, k)(2, 1)) / DX[1];)
     608             :     }
     609             : #endif         
     610             : #if AMREX_SPACEDIM > 2
     611        8100 :     if (stencil[2] == StencilType::Central)
     612             :     {
     613       56700 :         AMREX_D_TERM(ret(0) += (dw(i, j, k + 1)(0, 2) - dw(i, j, k - 1)(0, 2)) / 2. / DX[2];,
     614             :             ret(1) += (dw(i, j, k + 1)(1, 2) - dw(i, j, k - 1)(1, 2)) / 2. / DX[2];,
     615             :             ret(2) += (dw(i, j, k + 1)(2, 2) - dw(i, j, k - 1)(2, 2)) / 2. / DX[2];)
     616             :     }
     617           0 :     else if (stencil[2] == StencilType::Lo)
     618             :     {
     619           0 :         AMREX_D_TERM(ret(0) += (dw(i, j, k)(0, 2) - dw(i, j, k - 1)(0, 2)) / DX[2];,
     620             :             ret(1) += (dw(i, j, k)(1, 2) - dw(i, j, k - 1)(1, 2)) / DX[2];,
     621             :             ret(2) += (dw(i, j, k)(2, 2) - dw(i, j, k - 1)(2, 2)) / DX[2];)
     622             :     }
     623           0 :     else if (stencil[2] == StencilType::Hi)
     624             :     {
     625           0 :         AMREX_D_TERM(ret(0) += (dw(i, j, k + 1)(0, 2) - dw(i, j, k)(0, 2)) / DX[2];,
     626             :             ret(1) += (dw(i, j, k + 1)(1, 2) - dw(i, j, k)(1, 2)) / DX[2];,
     627             :             ret(2) += (dw(i, j, k + 1)(2, 2) - dw(i, j, k)(2, 2)) / DX[2];)
     628             :     }
     629             : #endif
     630      160392 :     return ret;
     631             : }
     632             : 
     633             : 
     634             : [[nodiscard]] AMREX_FORCE_INLINE
     635             : Set::Scalar
     636             : Divergence(const amrex::Array4<const Set::Scalar>& f,
     637             :     const int& i, const int& j, const int& k, const int& m,
     638             :     const Set::Scalar dx[AMREX_SPACEDIM],
     639             :     std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     640             : {
     641             :     Set::Scalar ret;
     642             :     ret = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, m, dx, stencil));
     643             : #if AMREX_SPACEDIM > 1
     644             :     ret += (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, m, dx, stencil));
     645             : #endif
     646             : #if AMREX_SPACEDIM > 2
     647             :     ret += (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, m, dx, stencil));
     648             : #endif
     649             :     return ret;
     650             : }
     651             : 
     652             : 
     653             : [[nodiscard]] AMREX_FORCE_INLINE
     654             : Set::Vector
     655             : Gradient(const amrex::Array4<const Set::Scalar>& f,
     656             :     const int& i, const int& j, const int& k, const int& m,
     657             :     const Set::Scalar dx[AMREX_SPACEDIM],
     658             :     std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     659             : {
     660    38417648 :     Set::Vector ret;
     661    38417648 :     ret(0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, m, dx, stencil));
     662             : #if AMREX_SPACEDIM > 1
     663    38417648 :     ret(1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, m, dx, stencil));
     664             : #if AMREX_SPACEDIM > 2
     665       78784 :     ret(2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, m, dx, stencil));
     666             : #endif
     667             : #endif
     668    38417648 :     return ret;
     669             : }
     670             : 
     671             : [[nodiscard]] AMREX_FORCE_INLINE
     672             : Set::Vector
     673             : CellGradientOnNode(const amrex::Array4<const Set::Scalar>& f,
     674             :     const int& i, const int& j, const int& k, const int& m,
     675             :     const Set::Scalar dx[AMREX_SPACEDIM])
     676             : {
     677     4358180 :     Set::Vector ret;
     678             : #if AMREX_SPACEDIM == 1
     679             :     ret(0) = (f(i, j, k, m) - f(i - 1, j, k, m)) / dx[0];
     680             : #elif AMREX_SPACEDIM == 2
     681    21790850 :     ret(0) = 0.5 * (f(i, j, k, m) - f(i - 1, j, k, m) + f(i, j - 1, k, m) - f(i - 1, j - 1, k, m)) / dx[0];
     682    21790850 :     ret(1) = 0.5 * (f(i, j, k, m) - f(i, j - 1, k, m) + f(i - 1, j, k, m) - f(i - 1, j - 1, k, m)) / dx[1];
     683             : #elif AMREX_SPACEDIM == 3
     684           0 :     ret(0) = 0.25 * (f(i, j, k, m) - f(i - 1, j, k, m) + f(i, j - 1, k, m) - f(i - 1, j - 1, k, m) + f(i, j, k - 1, m) - f(i - 1, j, k - 1, m) + f(i, j - 1, k - 1, m) - f(i - 1, j - 1, k - 1, m)) / dx[0];
     685           0 :     ret(1) = 0.25 * (f(i, j, k, m) - f(i, j - 1, k, m) + f(i - 1, j, k, m) - f(i - 1, j - 1, k, m) + f(i, j, k - 1, m) - f(i, j - 1, k - 1, m) + f(i - 1, j, k - 1, m) - f(i - 1, j - 1, k - 1, m)) / dx[1];
     686           0 :     ret(2) = 0.25 * (f(i, j, k, m) - f(i, j, k - 1, m) + f(i - 1, j, k, m) - f(i - 1, j, k - 1, m) + f(i, j - 1, k, m) - f(i, j - 1, k - 1, m) + f(i - 1, j - 1, k, m) - f(i - 1, j - 1, k - 1, m)) / dx[2];
     687             : #endif
     688     4358180 :     return ret;
     689             : }
     690             : 
     691             : 
     692             : template<class T>
     693             : [[nodiscard]] AMREX_FORCE_INLINE
     694             : std::array<T, AMREX_SPACEDIM>
     695             : CellGradientOnNode(const amrex::Array4<const T>& f,
     696             :     const int& i, const int& j, const int& k, const int& m,
     697             :     const Set::Scalar dx[AMREX_SPACEDIM])
     698             : {
     699             :     std::array<T, AMREX_SPACEDIM> ret;
     700             :     Util::Abort(INFO);
     701             : #if AMREX_SPACEDIM == 1
     702             :     ret[0] = (f(i, j, k, m) - f(i - 1, j, k, m)) / dx[0];
     703             : #elif AMREX_SPACEDIM == 2
     704             :     ret[0] = (f(i, j, k, m) - f(i - 1, j, k, m) + f(i, j - 1, k, m) - f(i - 1, j - 1, k, m)) * 0.5 / dx[0];
     705             :     ret[1] = (f(i, j, k, m) - f(i, j - 1, k, m) + f(i - 1, j, k, m) - f(i - 1, j - 1, k, m)) * 0.5 / dx[1];
     706             : #elif AMREX_SPACEDIM == 3
     707             :     ret[0] = (f(i, j, k, m) - f(i - 1, j, k, m) + f(i, j - 1, k, m) - f(i - 1, j - 1, k, m) + f(i, j, k - 1, m) - f(i - 1, j, k - 1, m) + f(i, j - 1, k - 1, m) - f(i - 1, j - 1, k - 1, m)) * 0.25 / dx[0];
     708             :     ret[1] = (f(i, j, k, m) - f(i, j - 1, k, m) + f(i - 1, j, k, m) - f(i - 1, j - 1, k, m) + f(i, j, k - 1, m) - f(i, j - 1, k - 1, m) + f(i - 1, j, k - 1, m) - f(i - 1, j - 1, k - 1, m)) * 0.25 / dx[1];
     709             :     ret[2] = (f(i, j, k, m) - f(i, j, k - 1, m) + f(i - 1, j, k, m) - f(i - 1, j, k - 1, m) + f(i, j - 1, k, m) - f(i, j - 1, k - 1, m) + f(i - 1, j - 1, k, m) - f(i - 1, j - 1, k - 1, m)) * 0.25 / dx[2];
     710             : #endif
     711             :     return ret;
     712             : }
     713             : 
     714             : 
     715             : 
     716             : [[nodiscard]] AMREX_FORCE_INLINE
     717             : Set::Matrix
     718             : Gradient(const amrex::Array4<const Set::Scalar>& f,
     719             :     const int& i, const int& j, const int& k,
     720             :     const Set::Scalar dx[AMREX_SPACEDIM],
     721             :     std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     722             : {
     723           0 :     Set::Matrix ret;
     724           0 :     ret(0, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 0, dx, stencil));
     725             : #if AMREX_SPACEDIM > 1
     726           0 :     ret(0, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 0, dx, stencil));
     727           0 :     ret(1, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 1, dx, stencil));
     728           0 :     ret(1, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 1, dx, stencil));
     729             : #if AMREX_SPACEDIM > 2
     730           0 :     ret(0, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 0, dx, stencil));
     731           0 :     ret(2, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 2, dx, stencil));
     732           0 :     ret(1, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 1, dx, stencil));
     733           0 :     ret(2, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 2, dx, stencil));
     734           0 :     ret(2, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 2, dx, stencil));
     735             : #endif
     736             : #endif
     737           0 :     return ret;
     738             : }
     739             : 
     740             : [[nodiscard]] AMREX_FORCE_INLINE
     741             : Set::Matrix
     742             : Gradient(const amrex::Array4<const Set::Vector>& f,
     743             :     const int& i, const int& j, const int& k,
     744             :     const Set::Scalar dx[AMREX_SPACEDIM],
     745             :     std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     746             : {
     747      446379 :     Set::Matrix ret;
     748             : 
     749             : #if AMREX_SPACEDIM > 0
     750      892758 :     ret.col(0) = Numeric::Stencil<Set::Vector, 1, 0, 0>::D(f, i, j, k, 0, dx, stencil);
     751             : #endif
     752             : #if AMREX_SPACEDIM > 1
     753      892758 :     ret.col(1) = Numeric::Stencil<Set::Vector, 0, 1, 0>::D(f, i, j, k, 0, dx, stencil);
     754             : #endif
     755             : #if AMREX_SPACEDIM > 2
     756      208800 :     ret.col(2) = Numeric::Stencil<Set::Vector, 0, 0, 1>::D(f, i, j, k, 0, dx, stencil);
     757             : #endif
     758             : 
     759      446379 :     return ret;
     760             : }
     761             : 
     762             : [[nodiscard]] AMREX_FORCE_INLINE
     763             : std::pair<Set::Vector,Set::Matrix>
     764             : GradientSplit(  const amrex::Array4<const Set::Vector>& f,
     765             :                 const int& i, const int& j, const int& k,
     766             :                 const Set::Scalar dx[AMREX_SPACEDIM],
     767             :                 std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     768             : {
     769           0 :     Set::Vector diag;
     770           0 :     Set::Matrix offdiag;
     771             : 
     772           0 :     std::pair<Set::Scalar,Set::Vector> ret;
     773             : #if AMREX_SPACEDIM > 0
     774           0 :     ret = Numeric::Stencil<Set::Vector, 1, 0, 0>::Dsplit(f, i, j, k, 0, dx, stencil);
     775           0 :     diag(0)        = ret.first;
     776           0 :     offdiag.col(0) = ret.second;
     777             : #endif
     778             : #if AMREX_SPACEDIM > 1
     779           0 :     ret = Numeric::Stencil<Set::Vector, 0, 1, 0>::Dsplit(f, i, j, k, 0, dx, stencil);
     780           0 :     diag(1)        = ret.first;
     781           0 :     offdiag.col(1) = ret.second;
     782             : #endif
     783             : #if AMREX_SPACEDIM > 2
     784           0 :     ret = Numeric::Stencil<Set::Vector, 0, 0, 1>::Dsplit(f, i, j, k, 0, dx, stencil);
     785           0 :     diag(2)        = ret.first;
     786           0 :     offdiag.col(2) = ret.second;
     787             : #endif
     788           0 :     return std::make_pair(diag,offdiag);
     789             : }
     790             : 
     791             : 
     792             : [[nodiscard]] AMREX_FORCE_INLINE
     793             : Set::Matrix
     794             : NodeGradientOnCell(const amrex::Array4<const Set::Vector>& f,
     795             :     const int& i, const int& j, const int& k,
     796             :     const Set::Scalar dx[AMREX_SPACEDIM])
     797             : {
     798             :     Set::Matrix ret;
     799             : #if AMREX_SPACEDIM == 1
     800             :     ret.col(0) = (f(i + 1, j, k) - f(i, j, k)) / dx[0];
     801             : #elif AMREX_SPACEDIM == 2
     802             :     ret.col(0) = (f(i + 1, j, k) - f(i, j, k) + f(i + 1, j + 1, k) - f(i, j + 1, k)) * 0.5 / dx[0];
     803             :     ret.col(1) = (f(i, j + 1, k) - f(i, j, k) + f(i + 1, j + 1, k) - f(i + 1, j, k)) * 0.5 / dx[1];
     804             : #elif AMREX_SPACEDIM == 3
     805             :     ret.col(0) = (f(i + 1, j, k) - f(i, j, k) + f(i + 1, j + 1, k) - f(i, j + 1, k) + f(i + 1, j, k + 1) - f(i, j, k + 1) + f(i + 1, j + 1, k + 1) - f(i, j + 1, k + 1)) * 0.25 / dx[0];
     806             :     ret.col(1) = (f(i, j + 1, k) - f(i, j, k) + f(i + 1, j + 1, k) - f(i + 1, j, k) + f(i, j + 1, k + 1) - f(i, j, k + 1) + f(i + 1, j + 1, k + 1) - f(i + 1, j, k + 1)) * 0.25 / dx[1];
     807             :     ret.col(2) = (f(i, j, k + 1) - f(i, j, k) + f(i, j + 1, k + 1) - f(i, j + 1, k) + f(i + 1, j, k + 1) - f(i + 1, j, k) + f(i + 1, j + 1, k + 1) - f(i + 1, j + 1, k)) * 0.25 / dx[2];
     808             : #endif
     809             :     return ret;
     810             : }
     811             : 
     812             : [[nodiscard]] AMREX_FORCE_INLINE
     813             : Set::Matrix3
     814             : Gradient(const amrex::Array4<const Set::Matrix>& f,
     815             :     const int& i, const int& j, const int& k,
     816             :     const Set::Scalar dx[AMREX_SPACEDIM],
     817             :     std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     818             : {
     819             :     Set::Matrix3 ret;
     820             : 
     821             : #if AMREX_SPACEDIM > 0
     822             :     ret[0] = Numeric::Stencil<Set::Matrix, 1, 0, 0>::D(f, i, j, k, 0, dx, stencil);
     823             : #endif
     824             : #if AMREX_SPACEDIM > 1
     825             :     ret[1] = Numeric::Stencil<Set::Matrix, 0, 1, 0>::D(f, i, j, k, 0, dx, stencil);
     826             : #endif
     827             : #if AMREX_SPACEDIM > 2
     828             :     ret[2] = Numeric::Stencil<Set::Matrix, 0, 0, 1>::D(f, i, j, k, 0, dx, stencil);
     829             : #endif
     830             : 
     831             :     return ret;
     832             : }
     833             : [[nodiscard]] AMREX_FORCE_INLINE
     834             : Set::Matrix3
     835             : NodeGradientOnCell(const amrex::Array4<const Set::Matrix>& f,
     836             :     const int& i, const int& j, const int& k,
     837             :     const Set::Scalar dx[AMREX_SPACEDIM])
     838             : {
     839      371408 :     Set::Matrix3 ret;
     840             : 
     841             : #if AMREX_SPACEDIM > 0
     842     1485628 :     ret[0] = (f(i+1,j,k) - f(i,j,k)) / dx[0];
     843             : #endif
     844             : #if AMREX_SPACEDIM > 1
     845     1485628 :     ret[1] = (f(i,j+1,k) - f(i,j,k)) / dx[1];
     846             : #endif
     847             : #if AMREX_SPACEDIM > 2
     848           0 :     ret[2] = (f(i,j,k+1) - f(i,j,k)) / dx[2];
     849             : #endif
     850             : 
     851      371408 :     return ret;
     852             : }
     853             : 
     854             : 
     855             : [[nodiscard]] AMREX_FORCE_INLINE
     856             : Set::Matrix3
     857             : MatrixGradient(const amrex::Array4<const Set::Scalar>& f,
     858             :     const int& i, const int& j, const int& k,
     859             :     const Set::Scalar dx[AMREX_SPACEDIM],
     860             :     std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     861             : {
     862             :     Set::Matrix3 ret;
     863             : #if AMREX_SPACEDIM == 1
     864             :     ret[0](0, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 0, dx, stencil));
     865             : #elif AMREX_SPACEDIM == 2
     866             :     ret[0](0, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 0, dx, stencil));
     867             :     ret[0](0, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 0, dx, stencil));
     868             :     ret[0](1, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 1, dx, stencil));
     869             :     ret[0](1, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 1, dx, stencil));
     870             :     ret[1](0, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 2, dx, stencil));
     871             :     ret[1](0, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 2, dx, stencil));
     872             :     ret[1](1, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 3, dx, stencil));
     873             :     ret[1](1, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 3, dx, stencil));
     874             : #elif AMREX_SPACEDIM == 3
     875             :     ret[0](0, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 0, dx, stencil));
     876             :     ret[0](1, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 1, dx, stencil));
     877             :     ret[0](2, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 2, dx, stencil));
     878             :     ret[1](0, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 3, dx, stencil));
     879             :     ret[1](1, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 4, dx, stencil));
     880             :     ret[1](2, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 5, dx, stencil));
     881             :     ret[2](0, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 6, dx, stencil));
     882             :     ret[2](1, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 7, dx, stencil));
     883             :     ret[2](2, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 0>::D(f, i, j, k, 8, dx, stencil));
     884             :     ret[0](0, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 0, dx, stencil));
     885             :     ret[0](1, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 1, dx, stencil));
     886             :     ret[0](2, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 2, dx, stencil));
     887             :     ret[1](0, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 3, dx, stencil));
     888             :     ret[1](1, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 4, dx, stencil));
     889             :     ret[1](2, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 5, dx, stencil));
     890             :     ret[2](0, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 6, dx, stencil));
     891             :     ret[2](1, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 7, dx, stencil));
     892             :     ret[2](2, 1) = (Numeric::Stencil<Set::Scalar, 0, 1, 0>::D(f, i, j, k, 8, dx, stencil));
     893             :     ret[0](0, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 0, dx, stencil));
     894             :     ret[0](1, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 1, dx, stencil));
     895             :     ret[0](2, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 2, dx, stencil));
     896             :     ret[1](0, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 3, dx, stencil));
     897             :     ret[1](1, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 4, dx, stencil));
     898             :     ret[1](2, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 5, dx, stencil));
     899             :     ret[2](0, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 6, dx, stencil));
     900             :     ret[2](1, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 7, dx, stencil));
     901             :     ret[2](2, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 1>::D(f, i, j, k, 8, dx, stencil));
     902             : #endif
     903             :     return ret;
     904             : }
     905             : 
     906             : 
     907             : [[nodiscard]] AMREX_FORCE_INLINE
     908             : Set::Matrix
     909             : Hessian(const amrex::Array4<const Set::Scalar>& f,
     910             :     const int& i, const int& j, const int& k, const int& m,
     911             :     const Set::Scalar dx[AMREX_SPACEDIM],
     912             :     std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType
     913             : )
     914             : {
     915     2401960 :     Set::Matrix ret;
     916     2401960 :     ret(0, 0) = (Numeric::Stencil<Set::Scalar, 2, 0, 0>::D(f, i, j, k, m, dx, stencil));
     917             : #if AMREX_SPACEDIM > 1
     918     2401960 :     ret(1, 1) = (Numeric::Stencil<Set::Scalar, 0, 2, 0>::D(f, i, j, k, m, dx, stencil));
     919     2401960 :     ret(0, 1) = (Numeric::Stencil<Set::Scalar, 1, 1, 0>::D(f, i, j, k, m, dx, stencil));
     920     2401960 :     ret(1, 0) = ret(0, 1);
     921             : #if AMREX_SPACEDIM > 2
     922           0 :     ret(2, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 2>::D(f, i, j, k, m, dx, stencil));
     923           0 :     ret(1, 2) = (Numeric::Stencil<Set::Scalar, 0, 1, 1>::D(f, i, j, k, m, dx, stencil));
     924           0 :     ret(2, 0) = (Numeric::Stencil<Set::Scalar, 1, 0, 1>::D(f, i, j, k, m, dx, stencil));
     925           0 :     ret(2, 1) = ret(1, 2);
     926           0 :     ret(0, 2) = ret(2, 0);
     927             : #endif
     928             : #endif
     929     2401960 :     return ret;
     930             : }
     931             : 
     932             : [[nodiscard]] AMREX_FORCE_INLINE
     933             : Set::Matrix3
     934             : Hessian(const amrex::Array4<const Set::Scalar>& f,
     935             :     const int& i, const int& j, const int& k,
     936             :     const Set::Scalar DX[AMREX_SPACEDIM],
     937             :     std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     938             : {
     939             :     Set::Matrix3 ret;
     940             :     // 1D 
     941             : #if AMREX_SPACEDIM>0
     942             :     ret(0, 0, 0) = (Numeric::Stencil<Set::Scalar, 2, 0, 0>::D(f, i, j, k, 0, DX, stencil));
     943             : #endif
     944             :     // 2D
     945             : #if AMREX_SPACEDIM>1
     946             :     ret(0, 0, 1) = (Numeric::Stencil<Set::Scalar, 1, 1, 0>::D(f, i, j, k, 0, DX, stencil));
     947             :     ret(0, 1, 0) = ret(0, 0, 1);
     948             :     ret(0, 1, 1) = (Numeric::Stencil<Set::Scalar, 0, 2, 0>::D(f, i, j, k, 0, DX, stencil));
     949             :     ret(1, 0, 0) = (Numeric::Stencil<Set::Scalar, 2, 0, 0>::D(f, i, j, k, 1, DX, stencil));
     950             :     ret(1, 0, 1) = (Numeric::Stencil<Set::Scalar, 1, 1, 0>::D(f, i, j, k, 1, DX, stencil));
     951             :     ret(1, 1, 0) = ret(1, 0, 1);
     952             :     ret(1, 1, 1) = (Numeric::Stencil<Set::Scalar, 0, 2, 0>::D(f, i, j, k, 1, DX, stencil));
     953             : #endif 
     954             :     // 3D
     955             : #if AMREX_SPACEDIM>2
     956             :     ret(0, 2, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 2>::D(f, i, j, k, 0, DX, stencil));
     957             :     ret(0, 0, 2) = (Numeric::Stencil<Set::Scalar, 1, 0, 1>::D(f, i, j, k, 0, DX, stencil));
     958             :     ret(0, 1, 2) = (Numeric::Stencil<Set::Scalar, 0, 1, 1>::D(f, i, j, k, 0, DX, stencil));
     959             :     ret(0, 2, 0) = ret(0, 0, 2);
     960             :     ret(0, 2, 1) = ret(0, 1, 2);;
     961             :     ret(1, 2, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 2>::D(f, i, j, k, 1, DX, stencil));
     962             :     ret(1, 0, 2) = (Numeric::Stencil<Set::Scalar, 1, 0, 1>::D(f, i, j, k, 1, DX, stencil));
     963             :     ret(1, 1, 2) = (Numeric::Stencil<Set::Scalar, 0, 1, 1>::D(f, i, j, k, 1, DX, stencil));
     964             :     ret(1, 2, 0) = ret(1, 0, 2);
     965             :     ret(1, 2, 1) = ret(1, 1, 2);;
     966             :     ret(2, 0, 0) = (Numeric::Stencil<Set::Scalar, 2, 0, 0>::D(f, i, j, k, 2, DX, stencil));
     967             :     ret(2, 1, 1) = (Numeric::Stencil<Set::Scalar, 0, 2, 0>::D(f, i, j, k, 2, DX, stencil));
     968             :     ret(2, 2, 2) = (Numeric::Stencil<Set::Scalar, 0, 0, 2>::D(f, i, j, k, 2, DX, stencil));
     969             :     ret(2, 0, 1) = (Numeric::Stencil<Set::Scalar, 1, 1, 0>::D(f, i, j, k, 2, DX, stencil));
     970             :     ret(2, 1, 0) = ret(2, 0, 1);
     971             :     ret(2, 0, 2) = (Numeric::Stencil<Set::Scalar, 1, 0, 1>::D(f, i, j, k, 2, DX, stencil));
     972             :     ret(2, 1, 2) = (Numeric::Stencil<Set::Scalar, 0, 1, 1>::D(f, i, j, k, 2, DX, stencil));
     973             :     ret(2, 2, 0) = ret(2, 0, 2);
     974             :     ret(2, 2, 1) = ret(2, 1, 2);;
     975             : #endif
     976             :     return ret;
     977             : }
     978             : 
     979             : 
     980             : // Returns Hessian of a vector field.
     981             : // Return value: ret[i](j,k) = ret_{i,jk}
     982             : [[nodiscard]] AMREX_FORCE_INLINE
     983             : Set::Matrix3
     984             : Hessian(const amrex::Array4<const Set::Vector>& f,
     985             :     const int& i, const int& j, const int& k,
     986             :     const Set::Scalar dx[AMREX_SPACEDIM],
     987             :     std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
     988             : {
     989             :     Set::Matrix3 ret;
     990             : 
     991             : #if AMREX_SPACEDIM>0    
     992             :     Set::Vector f_11 = Numeric::Stencil<Set::Vector, 2, 0, 0>::D(f, i, j, k, 0, dx, stencil);
     993             :     ret[0](0, 0) = f_11(0);
     994             : #endif
     995             : #if AMREX_SPACEDIM>1
     996             :     ret[1](0, 0) = f_11(1);
     997             :     Set::Vector f_12 = Numeric::Stencil<Set::Vector, 1, 1, 0>::D(f, i, j, k, 0, dx, stencil);
     998             :     ret[0](1, 0) = ret[0](0, 1) = f_12(0);
     999             :     ret[1](1, 0) = ret[1](0, 1) = f_12(1);
    1000             :     Set::Vector f_22 = Numeric::Stencil<Set::Vector, 0, 2, 0>::D(f, i, j, k, 0, dx, stencil);
    1001             :     ret[0](1, 1) = f_22(0);
    1002             :     ret[1](1, 1) = f_22(1);
    1003             : #endif
    1004             : #if AMREX_SPACEDIM>2
    1005             :     ret[2](0, 0) = f_11(2);
    1006             :     ret[2](1, 0) = ret[2](0, 1) = f_12(2);
    1007             :     Set::Vector f_13 = Numeric::Stencil<Set::Vector, 1, 0, 1>::D(f, i, j, k, 0, dx, stencil);
    1008             :     ret[0](2, 0) = ret[0](0, 2) = f_13(0);
    1009             :     ret[1](2, 0) = ret[1](0, 2) = f_13(1);
    1010             :     ret[2](2, 0) = ret[2](0, 2) = f_13(2);
    1011             :     ret[2](1, 1) = f_22(2);
    1012             :     Set::Vector f_23 = Numeric::Stencil<Set::Vector, 0, 1, 1>::D(f, i, j, k, 0, dx, stencil);
    1013             :     ret[0](1, 2) = ret[0](2, 1) = f_23(0);
    1014             :     ret[1](1, 2) = ret[1](2, 1) = f_23(1);
    1015             :     ret[2](1, 2) = ret[2](2, 1) = f_23(2);
    1016             :     Set::Vector f_33 = Numeric::Stencil<Set::Vector, 0, 0, 2>::D(f, i, j, k, 0, dx, stencil);
    1017             :     ret[0](2, 2) = f_33(0);
    1018             :     ret[1](2, 2) = f_33(1);
    1019             :     ret[2](2, 2) = f_33(2);
    1020             : #endif
    1021             :     return ret;
    1022             : }
    1023             : 
    1024             : 
    1025             : [[nodiscard]] AMREX_FORCE_INLINE
    1026             : Set::Matrix
    1027             : FieldToMatrix(const amrex::Array4<const Set::Scalar>& f,
    1028             :     const int& i, const int& j, const int& k)
    1029             : {
    1030           0 :     Set::Matrix ret;
    1031             : #if AMREX_SPACEDIM == 1
    1032             :     ret(0, 0) = f(i, j, k, 0);
    1033             : 
    1034             : #elif AMREX_SPACEDIM == 2
    1035           0 :     ret(0, 0) = f(i, j, k, 0); ret(0, 1) = f(i, j, k, 1);
    1036           0 :     ret(1, 0) = f(i, j, k, 2); ret(1, 1) = f(i, j, k, 3);
    1037             : 
    1038             : #elif AMREX_SPACEDIM == 3
    1039           0 :     ret(0, 0) = f(i, j, k, 0); ret(0, 1) = f(i, j, k, 1); ret(0, 2) = f(i, j, k, 2);
    1040           0 :     ret(1, 0) = f(i, j, k, 3); ret(1, 1) = f(i, j, k, 4); ret(1, 2) = f(i, j, k, 5);
    1041           0 :     ret(2, 0) = f(i, j, k, 6); ret(2, 1) = f(i, j, k, 7); ret(2, 2) = f(i, j, k, 8);
    1042             : #endif
    1043             : 
    1044           0 :     return ret;
    1045             : }
    1046             : 
    1047             : [[nodiscard]] AMREX_FORCE_INLINE
    1048             : Set::Matrix
    1049             : FieldToMatrix(const amrex::Array4<Set::Scalar>& f,
    1050             :     const int& i, const int& j, const int& k)
    1051             : {
    1052             :     Set::Matrix ret;
    1053             : #if AMREX_SPACEDIM == 1
    1054             :     ret(0, 0) = f(i, j, k, 0);
    1055             : 
    1056             : #elif AMREX_SPACEDIM == 2
    1057             :     ret(0, 0) = f(i, j, k, 0); ret(0, 1) = f(i, j, k, 1);
    1058             :     ret(1, 0) = f(i, j, k, 2); ret(1, 1) = f(i, j, k, 3);
    1059             : 
    1060             : #elif AMREX_SPACEDIM == 3
    1061             :     ret(0, 0) = f(i, j, k, 0); ret(0, 1) = f(i, j, k, 1); ret(0, 2) = f(i, j, k, 2);
    1062             :     ret(1, 0) = f(i, j, k, 3); ret(1, 1) = f(i, j, k, 4); ret(1, 2) = f(i, j, k, 5);
    1063             :     ret(2, 0) = f(i, j, k, 6); ret(2, 1) = f(i, j, k, 7); ret(2, 2) = f(i, j, k, 8);
    1064             : #endif
    1065             : 
    1066             :     return ret;
    1067             : }
    1068             : 
    1069             : [[nodiscard]] AMREX_FORCE_INLINE
    1070             : Set::Vector
    1071             : FieldToVector(const amrex::Array4<const Set::Scalar>& f,
    1072             :     const int& i, const int& j, const int& k)
    1073             : {
    1074             :     Set::Vector ret;
    1075             :     ret(0) = f(i, j, k, 0);
    1076             : #if AMREX_SPACEDIM > 1
    1077             :     ret(1) = f(i, j, k, 1);
    1078             : #if AMREX_SPACEDIM > 2
    1079             :     ret(2) = f(i, j, k, 2);
    1080             : #endif
    1081             : #endif
    1082             :     return ret;
    1083             : }
    1084             : 
    1085             : [[nodiscard]] AMREX_FORCE_INLINE
    1086             : Set::Vector
    1087             : FieldToVector(const amrex::Array4<Set::Scalar>& f,
    1088             :     const int& i, const int& j, const int& k)
    1089             : {
    1090             :     Set::Vector ret;
    1091             :     ret(0) = f(i, j, k, 0);
    1092             : #if AMREX_SPACEDIM > 1
    1093             :     ret(1) = f(i, j, k, 1);
    1094             : #if AMREX_SPACEDIM > 2
    1095             :     ret(2) = f(i, j, k, 2);
    1096             : #endif
    1097             : #endif
    1098             :     return ret;
    1099             : }
    1100             : 
    1101             : AMREX_FORCE_INLINE
    1102             : void
    1103             : MatrixToField(const amrex::Array4<Set::Scalar>& f,
    1104             :     const int& i, const int& j, const int& k,
    1105             :     Set::Matrix matrix)
    1106             : {
    1107             : #if AMREX_SPACEDIM == 1
    1108             :     f(i, j, k, 0) = matrix(0, 0);
    1109             : #elif AMREX_SPACEDIM == 2
    1110             :     f(i, j, k, 0) = matrix(0, 0); f(i, j, k, 1) = matrix(0, 1);
    1111             :     f(i, j, k, 2) = matrix(1, 0); f(i, j, k, 3) = matrix(1, 1);
    1112             : #elif AMREX_SPACEDIM == 3
    1113             :     f(i, j, k, 0) = matrix(0, 0); f(i, j, k, 1) = matrix(0, 1); f(i, j, k, 2) = matrix(0, 2);
    1114             :     f(i, j, k, 3) = matrix(1, 0); f(i, j, k, 4) = matrix(1, 1); f(i, j, k, 5) = matrix(1, 2);
    1115             :     f(i, j, k, 6) = matrix(2, 0); f(i, j, k, 7) = matrix(2, 1); f(i, j, k, 8) = matrix(2, 2);
    1116             : #endif
    1117             : }
    1118             : 
    1119             : AMREX_FORCE_INLINE
    1120             : void
    1121             : VectorToField(const amrex::Array4<Set::Scalar>& f,
    1122             :     const int& i, const int& j, const int& k,
    1123             :     Set::Vector vector)
    1124             : {
    1125             :     f(i, j, k, 0) = vector(0);
    1126             : #if AMREX_SPACEDIM > 1
    1127             :     f(i, j, k, 1) = vector(1);
    1128             : #if AMREX_SPACEDIM > 2
    1129             :     f(i, j, k, 2) = vector(2);
    1130             : #endif
    1131             : #endif
    1132             : }
    1133             : 
    1134             : template<int index, int SYM>
    1135             : [[nodiscard]] 
    1136             : Set::Matrix3
    1137             : Divergence(const amrex::Array4<const Set::Matrix4<AMREX_SPACEDIM, SYM>>&,
    1138             :     const int, const int, const int, const Set::Scalar[AMREX_SPACEDIM],
    1139             :     std::array<StencilType, AMREX_SPACEDIM> /*stecil*/ = DefaultType)
    1140             : {
    1141             :     Util::Abort(INFO, "Not implemented yet"); return Set::Matrix3::Zero();
    1142             : }
    1143             : 
    1144             : template<>
    1145             : [[nodiscard]] AMREX_FORCE_INLINE
    1146             : Set::Matrix3 Divergence<2, Set::Sym::Isotropic>(const amrex::Array4<const Set::Matrix4<AMREX_SPACEDIM, Set::Sym::Isotropic>>& C,
    1147             :     const int i, const int j, const int k, const Set::Scalar dx[AMREX_SPACEDIM],
    1148             :     std::array<StencilType, AMREX_SPACEDIM> stencil)
    1149             : {
    1150             :     Set::Matrix3 ret;
    1151             : 
    1152             :     Set::Matrix4<AMREX_SPACEDIM, Set::Sym::Isotropic> gradCx =
    1153             :         Numeric::Stencil<Set::Matrix4<AMREX_SPACEDIM, Set::Sym::Isotropic>, 1, 0, 0>::D(C, i, j, k, 0, dx, stencil);
    1154             : #if AMREX_SPACEDIM>1
    1155             :     Set::Matrix4<AMREX_SPACEDIM, Set::Sym::Isotropic> gradCy =
    1156             :         Numeric::Stencil<Set::Matrix4<AMREX_SPACEDIM, Set::Sym::Isotropic>, 0, 1, 0>::D(C, i, j, k, 0, dx, stencil);
    1157             : #endif
    1158             : #if AMREX_SPACEDIM>2
    1159             :     Set::Matrix4<AMREX_SPACEDIM, Set::Sym::Isotropic> gradCz =
    1160             :         Numeric::Stencil<Set::Matrix4<AMREX_SPACEDIM, Set::Sym::Isotropic>, 0, 0, 1>::D(C, i, j, k, 0, dx, stencil);
    1161             : #endif
    1162             : 
    1163             :     for (int i = 0; i < AMREX_SPACEDIM; i++)
    1164             :         for (int k = 0; k < AMREX_SPACEDIM; k++)
    1165             :             for (int l = 0; l < AMREX_SPACEDIM; l++)
    1166             :             {
    1167             :                 ret(i, k, l) = 0.0;
    1168             :                 ret(i, k, l) = gradCx(i, 0, k, l);
    1169             : #if AMREX_SPACEDIM>1
    1170             :                 ret(i, k, l) = gradCy(i, 1, k, l);
    1171             : #endif
    1172             : #if AMREX_SPACEDIM>2
    1173             :                 ret(i, k, l) = gradCz(i, 2, k, l);
    1174             : #endif
    1175             :             }
    1176             :     return ret;
    1177             : }
    1178             : 
    1179             : 
    1180             : 
    1181             : 
    1182             : template<int dim>
    1183             : [[nodiscard]] AMREX_FORCE_INLINE
    1184             : Set::Matrix4<dim, Set::Sym::Full>
    1185             : DoubleHessian(const amrex::Array4<const Set::Scalar>& f,
    1186             :     const int& i, const int& j, const int& k, const int& m,
    1187             :     const Set::Scalar dx[AMREX_SPACEDIM]);
    1188             : 
    1189             : template<>
    1190             : [[nodiscard]] AMREX_FORCE_INLINE
    1191             : Set::Matrix4<2, Set::Sym::Full>
    1192             : DoubleHessian<2>(const amrex::Array4<const Set::Scalar>& f,
    1193             :     const int& i, const int& j, const int& k, const int& m,
    1194             :     const Set::Scalar dx[AMREX_SPACEDIM])
    1195             : {
    1196     1362860 :     Set::Matrix4<2, Set::Sym::Full> ret;
    1197             :     // [0,0,0,0]
    1198     2725720 :     ret(0, 0, 0, 0) = Stencil<Set::Scalar, 4, 0, 0>::D(f, i, j, k, m, dx);
    1199             :     // [0, 0, 0, 1]
    1200     2725720 :     ret(0, 0, 0, 1) = Stencil<Set::Scalar, 3, 1, 0>::D(f, i, j, k, m, dx);
    1201             :     // [0, 0, 1, 1]
    1202     2725720 :     ret(0, 0, 1, 1) = Stencil<Set::Scalar, 2, 2, 0>::D(f, i, j, k, m, dx);
    1203             :     // [0, 1, 1, 1]
    1204     2725720 :     ret(0, 1, 1, 1) = Stencil<Set::Scalar, 1, 3, 0>::D(f, i, j, k, m, dx);
    1205             :     // [1, 1, 1, 1]
    1206     1362860 :     ret(1, 1, 1, 1) = Stencil<Set::Scalar, 0, 4, 0>::D(f, i, j, k, m, dx);
    1207     1362860 :     return ret;
    1208             : }
    1209             : 
    1210             : template<>
    1211             : [[nodiscard]] AMREX_FORCE_INLINE
    1212             : Set::Matrix4<3, Set::Sym::Full>
    1213             : DoubleHessian<3>(const amrex::Array4<const Set::Scalar>& f,
    1214             :     const int& i, const int& j, const int& k, const int& m,
    1215             :     const Set::Scalar dx[AMREX_SPACEDIM])
    1216             : {
    1217           0 :     Set::Matrix4<3, Set::Sym::Full> ret;
    1218             :     // [0,0,0,0]
    1219           0 :     ret(0, 0, 0, 0) = Stencil<Set::Scalar, 4, 0, 0>::D(f, i, j, k, m, dx);
    1220             :     // [0, 0, 0, 1]
    1221           0 :     ret(0, 0, 0, 1) = Stencil<Set::Scalar, 3, 1, 0>::D(f, i, j, k, m, dx);
    1222             :     // [0, 0, 0, 2]
    1223           0 :     ret(0, 0, 0, 2) = Stencil<Set::Scalar, 3, 0, 1>::D(f, i, j, k, m, dx);
    1224             :     // [0, 0, 1, 1]
    1225           0 :     ret(0, 0, 1, 1) = Stencil<Set::Scalar, 2, 2, 0>::D(f, i, j, k, m, dx);
    1226             :     // [0, 0, 1, 2]
    1227           0 :     ret(0, 0, 1, 2) = Stencil<Set::Scalar, 2, 1, 1>::D(f, i, j, k, m, dx);
    1228             :     // [0, 0, 2, 2]
    1229           0 :     ret(0, 0, 2, 2) = Stencil<Set::Scalar, 2, 0, 2>::D(f, i, j, k, m, dx);
    1230             :     // [0, 1, 1, 1]
    1231           0 :     ret(0, 1, 1, 1) = Stencil<Set::Scalar, 1, 3, 0>::D(f, i, j, k, m, dx);
    1232             :     // [0, 1, 1, 2]
    1233           0 :     ret(0, 1, 1, 2) = Stencil<Set::Scalar, 1, 2, 1>::D(f, i, j, k, m, dx);
    1234             :     // [0, 1, 2, 2]
    1235           0 :     ret(0, 1, 2, 2) = Stencil<Set::Scalar, 1, 1, 2>::D(f, i, j, k, m, dx);
    1236             :     // [0, 2, 2, 2]
    1237           0 :     ret(0, 2, 2, 2) = Stencil<Set::Scalar, 1, 0, 3>::D(f, i, j, k, m, dx);
    1238             :     // [1, 1, 1, 1]
    1239           0 :     ret(1, 1, 1, 1) = Stencil<Set::Scalar, 0, 4, 0>::D(f, i, j, k, m, dx);
    1240             :     // [1, 1, 1, 2]
    1241           0 :     ret(1, 1, 1, 2) = Stencil<Set::Scalar, 0, 3, 1>::D(f, i, j, k, m, dx);
    1242             :     // [1, 1, 2, 2]
    1243           0 :     ret(1, 1, 2, 2) = Stencil<Set::Scalar, 0, 2, 2>::D(f, i, j, k, m, dx);
    1244             :     // [1, 2, 2, 2]
    1245           0 :     ret(1, 2, 2, 2) = Stencil<Set::Scalar, 0, 1, 3>::D(f, i, j, k, m, dx);
    1246             :     // [2, 2, 2, 2]
    1247           0 :     ret(2, 2, 2, 2) = Stencil<Set::Scalar, 0, 0, 4>::D(f, i, j, k, m, dx);
    1248           0 :     return ret;
    1249             : }
    1250             : 
    1251             : struct Interpolate
    1252             : {
    1253             : public:
    1254             :     template<class T>
    1255             :     [[nodiscard]] AMREX_FORCE_INLINE
    1256             :         static T CellToNodeAverage(const amrex::Array4<const T>& f,
    1257             :             const int& i, const int& j, const int& k, const int& m,
    1258             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
    1259             :     {
    1260      184516 :         int AMREX_D_DECL(
    1261             :             ilo = (stencil[0] == Numeric::StencilType::Lo ? 0 : 1),
    1262             :             jlo = (stencil[1] == Numeric::StencilType::Lo ? 0 : 1),
    1263             :             klo = (stencil[2] == Numeric::StencilType::Lo ? 0 : 1));
    1264             : 
    1265      738064 :         return (AMREX_D_TERM(f(i, j, k, m) + f(i - ilo, j, k, m)
    1266             :             ,
    1267             :             +f(i, j - jlo, k, m) + f(i - ilo, j - jlo, k, m)
    1268             :             ,
    1269             :             +f(i, j, k - klo, m) + f(i - ilo, j, k - klo, m)
    1270             :             + f(i, j - jlo, k - klo, m) + f(i - ilo, j - jlo, k - klo, m)
    1271      184516 :         )) * fac;
    1272             :     }
    1273             :     template<class T>
    1274             :     [[nodiscard]] AMREX_FORCE_INLINE
    1275             :         static T CellToNodeAverage(const amrex::Array4<T>& f,
    1276             :             const int& i, const int& j, const int& k, const int& m,
    1277             :             std::array<StencilType, AMREX_SPACEDIM> stencil = DefaultType)
    1278             :     {
    1279     4620090 :         int AMREX_D_DECL(
    1280             :             ilo = (stencil[0] == Numeric::StencilType::Lo ? 0 : 1),
    1281             :             jlo = (stencil[1] == Numeric::StencilType::Lo ? 0 : 1),
    1282             :             klo = (stencil[2] == Numeric::StencilType::Lo ? 0 : 1));
    1283             : 
    1284    18480400 :         return (AMREX_D_TERM(f(i, j, k, m) + f(i - ilo, j, k, m)
    1285             :             ,
    1286             :             +f(i, j - jlo, k, m) + f(i - ilo, j - jlo, k, m)
    1287             :             ,
    1288             :             +f(i, j, k - klo, m) + f(i - ilo, j, k - klo, m)
    1289             :             + f(i, j - jlo, k - klo, m) + f(i - ilo, j - jlo, k - klo, m)
    1290     4620090 :         )) * fac;
    1291             :     }
    1292             :     template<class T>
    1293             :     [[nodiscard]] AMREX_FORCE_INLINE
    1294             :         static T NodeToCellAverage(const amrex::Array4<const T>& f,
    1295             :             const int& i, const int& j, const int& k, const int& m)
    1296             :     {
    1297    21110164 :         return (AMREX_D_TERM(f(i, j, k, m) + f(i + 1, j, k, m)
    1298             :             ,
    1299             :             +f(i, j + 1, k, m) + f(i + 1, j + 1, k, m)
    1300             :             ,
    1301             :             +f(i, j, k + 1, m) + f(i + 1, j, k + 1, m)
    1302             :             + f(i, j + 1, k + 1, m) + f(i + 1, j + 1, k + 1, m)
    1303     5277536 :         )) * fac;
    1304             :     }
    1305             :     template<class T>
    1306             :     [[nodiscard]] AMREX_FORCE_INLINE
    1307             :         static T NodeToCellAverage(const amrex::Array4<T>& f,
    1308             :             const int& i, const int& j, const int& k, const int& m)
    1309             :     {
    1310             :         return (AMREX_D_TERM(f(i, j, k, m) + f(i + 1, j, k, m)
    1311             :             ,
    1312             :             +f(i, j + 1, k, m) + f(i + 1, j + 1, k, m)
    1313             :             ,
    1314             :             +f(i, j, k + 1, m) + f(i + 1, j, k + 1, m)
    1315             :             + f(i, j + 1, k + 1, m) + f(i + 1, j + 1, k + 1, m)
    1316             :         )) * fac;
    1317             :     }
    1318             :     constexpr static Set::Scalar fac = AMREX_D_PICK(0.5, 0.25, 0.125);
    1319             : };
    1320             : 
    1321             : }
    1322             : #endif

Generated by: LCOV version 1.14