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

Generated by: LCOV version 2.0-1