LCOV - code coverage report
Current view: top level - ext/amrex/2d-coverage-g++-24.08/include - AMReX_Array.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 1 1 100.0 %
Date: 2024-11-18 05:28:54 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef AMREX_ARRAY_H_
       2             : #define AMREX_ARRAY_H_
       3             : #include <AMReX_Config.H>
       4             : 
       5             : #include <AMReX.H>
       6             : #include <AMReX_GpuQualifiers.H>
       7             : #include <AMReX_GpuControl.H>
       8             : #include <AMReX_BLassert.H>
       9             : #include <AMReX_SPACE.H>
      10             : #include <AMReX_REAL.H>
      11             : #include <AMReX_Algorithm.H>
      12             : #include <AMReX_Dim3.H>
      13             : 
      14             : #include <array>
      15             : #include <memory>
      16             : #include <utility>
      17             : #include <string>
      18             : #include <type_traits>
      19             : 
      20             : namespace amrex {
      21             : 
      22             :     template <class T, std::size_t N>
      23             :     using Array = std::array<T,N>;
      24             : 
      25             :     using RealArray = Array<Real, AMREX_SPACEDIM>;
      26             :     using IntArray  = Array<int , AMREX_SPACEDIM>;
      27             : 
      28             : }
      29             : 
      30             : namespace amrex {
      31             :     template <class T, unsigned int N>
      32             :     struct GpuArray
      33             :     {
      34             :         using value_type = T;
      35             :         using reference_type = T&;
      36             : 
      37             :         /**
      38             :          * GpuArray elements are indexed using square brackets, as with any
      39             :          * other array.
      40             :          */
      41             :         AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
      42             :         const T& operator [] (int i) const noexcept { return arr[i]; }
      43             : 
      44             :         /**
      45             :          * GpuArray elements are indexed using square brackets, as with any
      46             :          * other array.
      47             :          */
      48             :         AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
      49             :         T& operator [] (int i) noexcept { return arr[i]; }
      50             : 
      51             :         /**
      52             :          * Returns a \c const pointer to the underlying data of a GpuArray object.
      53             :          */
      54             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
      55             :         const T* data () const noexcept { return arr; }
      56             : 
      57             :         /**
      58             :          * Returns a pointer to the underlying data of a GpuArray object.
      59             :          */
      60             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
      61       29376 :         T* data () noexcept { return arr; }
      62             : 
      63             :         /**
      64             :          * Returns the number of elements in the GpuArray object as an
      65             :          * unsigned integer.
      66             :          */
      67             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
      68             :         static constexpr unsigned int size () noexcept { return N; }
      69             : 
      70             :         /**
      71             :          * Returns a \c const pointer address to the first element of the
      72             :          * GpuArray object.
      73             :          */
      74             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
      75             :         const T* begin () const noexcept { return arr; }
      76             : 
      77             :         /**
      78             :          * Returns a const pointer address right after the last element of the
      79             :          * GpuArray object.
      80             :          */
      81             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
      82             :         const T* end () const noexcept { return arr + N; }
      83             : 
      84             :         /**
      85             :          * Returns a pointer address to the first element of the
      86             :          * GpuArray object.
      87             :          */
      88             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
      89             :         T* begin () noexcept { return arr; }
      90             : 
      91             :         /**
      92             :          * Returns a pointer address right after the last element of the
      93             :          * GpuArray object.
      94             :          */
      95             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
      96             :         T* end () noexcept { return arr + N; }
      97             : 
      98             :         /**
      99             :          * Fills in all of the elements in the GpuArray object to the same
     100             :          * value.
     101             :          *
     102             :          * \param value The fill value
     103             :          */
     104             :         AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     105             :         void fill ( const T& value ) noexcept
     106             :         { for (unsigned int i = 0; i < N; ++i) { arr[i] = value; } }
     107             : 
     108             :         /**
     109             :          * Returns the sum of all elements in the GpuArray object.
     110             :          */
     111             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     112             :         constexpr T sum () const noexcept
     113             :         {
     114             :             T s = 0;
     115             :             for (unsigned int i = 0; i < N; ++i) { s += arr[i]; }
     116             :             return s;
     117             :         }
     118             : 
     119             :         /**
     120             :          * Returns the product of all elements in the GpuArray object.
     121             :          */
     122             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     123             :         T product () const noexcept
     124             :         {
     125             :             T p = 1;
     126             :             for (unsigned int i = 0; i < N; ++i) { p *= arr[i]; }
     127             :             return p;
     128             :         }
     129             : 
     130             :         AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     131             :         GpuArray<T,N>& operator+= (GpuArray<T,N> const& a) noexcept
     132             :         {
     133             :             for (unsigned int i = 0; i < N; ++i) {
     134             :                 arr[i] += a.arr[i];
     135             :             }
     136             :             return *this;
     137             :         }
     138             : 
     139             :         T arr[amrex::max(N,1U)];
     140             :     };
     141             : }
     142             : 
     143             : namespace amrex {
     144             : 
     145             :     /**
     146             :      * Array2D and Array3D objects can be indexed according to Fortran
     147             :      * column-major order (first index moving fastest) or C/C++ row-major
     148             :      * order (last index moving fastest). If not specified, Fortran order is
     149             :      * assumed.
     150             :      */
     151             :     namespace Order {
     152             :         struct C {};
     153             :         struct F {};
     154             :     }
     155             : 
     156             :     /**
     157             :      * A GPU-compatible one-dimensional array.
     158             :      *
     159             :      * \tparam XLO Index for lower bound. Can be other than 0.
     160             :      * \tparam XHI Index for upper bound.
     161             :      */
     162             :     template <class T, int XLO, int XHI>
     163             :     struct Array1D
     164             :     {
     165             :         /**
     166             :          * Returns the number of elements in the Array1D object as an unsigned
     167             :          * integer.
     168             :          */
     169             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     170             :         static constexpr unsigned int size () noexcept { return (XHI-XLO+1); }
     171             : 
     172             :         /**
     173             :          * Returns the index of the lower bound of the Array1D object.
     174             :          * Can be other than 0.
     175             :          */
     176             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     177             :         static constexpr int lo () noexcept { return XLO; }
     178             : 
     179             :         /**
     180             :          * Returns the index of the upper bound of the Array1D object.
     181             :          */
     182             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     183             :         static constexpr int hi () noexcept { return XHI; }
     184             : 
     185             :         /**
     186             :          * Returns the number of elements in the Array1D object as an unsigned
     187             :          * integer.
     188             :          */
     189             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     190             :         static constexpr unsigned int len () noexcept { return (XHI-XLO+1); }
     191             : 
     192             :         /**
     193             :          * Returns a \c const pointer address to the first element of the
     194             :          * Array1D object.
     195             :          */
     196             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     197             :         const T* begin () const noexcept { return arr; }
     198             : 
     199             :         /**
     200             :          * Returns a \c const pointer address right after the last element of the
     201             :          * Array1D object.
     202             :          */
     203             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     204             :         const T* end () const noexcept { return arr + XHI-XLO+1; }
     205             : 
     206             :         /**
     207             :          * Returns a pointer address to the first element of the
     208             :          * Array1D object.
     209             :          */
     210             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     211             :         T* begin () noexcept { return arr; }
     212             : 
     213             :         /**
     214             :          * Returns a pointer address right after the last element of the
     215             :          * Array1D object.
     216             :          */
     217             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     218             :         T* end () noexcept { return arr + XHI-XLO+1; }
     219             : 
     220             :         /**
     221             :          * The elements of an Array1D object are accessed using parentheses,
     222             :          * e.g. \c array(i), instead of using square brackets.
     223             :          */
     224             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     225             :         const T& operator() (int i) const noexcept {
     226             :             AMREX_ASSERT(i >= XLO && i <= XHI);
     227             :             return arr[i-XLO];
     228             :         }
     229             : 
     230             :         /**
     231             :          * The elements of an Array1D object are accessed using parentheses,
     232             :          * e.g. array(i), instead of using square brackets.
     233             :          */
     234             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     235             :         T& operator() (int i) noexcept {
     236             :             AMREX_ASSERT(i >= XLO && i <= XHI);
     237             :             return arr[i-XLO];
     238             :         }
     239             : 
     240             :         /**
     241             :          * Returns the sum of all elements in the Array1D object.
     242             :          */
     243             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     244             :         constexpr T sum () const noexcept
     245             :         {
     246             :             T s = 0;
     247             :             for (int i = XLO; i <= XHI; ++i) { s += arr[i-XLO]; }
     248             :             return s;
     249             :         }
     250             : 
     251             :         /**
     252             :          * Returns the product of all elements in the Array1D object.
     253             :          */
     254             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     255             :         constexpr T product() const noexcept
     256             :         {
     257             :             T p = 1;
     258             :             for (int i = 0; i < (XHI-XLO+1); ++i) {
     259             :                 p *= arr[i];
     260             :             }
     261             :             return p;
     262             :         }
     263             : 
     264             :         /**
     265             :          * Array1D is implemented as a fixed-size array.
     266             :          * Hence, no constructor or destructor is given.
     267             :          */
     268             :         T arr[(XHI-XLO+1)];
     269             :     };
     270             : 
     271             :     /**
     272             :      * A GPU-compatible two-dimensional array.
     273             :      *
     274             :      * \tparam XLO Index for lower bound in \a x dimension. Can be other than 0.
     275             :      * \tparam XHI Index for upper bound in \a x dimension.
     276             :      * \tparam YLO Index for lower bound in \a y dimension. Can be other than 0.
     277             :      * \tparam YHI Index for upper bound in \a y dimension.
     278             :      * \tparam ORDER Either Order::C (C/C++ row-major order) or
     279             :      *               Order::F (Fortran column-major order, which is the
     280             :      *               default if not given)
     281             :      */
     282             :     template <class T, int XLO, int XHI, int YLO, int YHI,
     283             :               class ORDER=Order::F>
     284             :     struct Array2D
     285             :     {
     286             :         /**
     287             :          * Returns the total number of elements of the Array2D object as an
     288             :          * unsigned integer.
     289             :          */
     290             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     291             :         static constexpr unsigned int size() noexcept { return (XHI-XLO+1)*(YHI-YLO+1); }
     292             : 
     293             :         /**
     294             :          * Returns the index of the lower bound of the Array2D object in the
     295             :          * \a x direction.
     296             :          * Can be other than 0.
     297             :          */
     298             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     299             :         static constexpr int xlo () noexcept { return XLO; }
     300             : 
     301             :         /**
     302             :          * Returns the index of the upper bound of the Array2D object in the
     303             :          * \a x direction.
     304             :          */
     305             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     306             :         static constexpr int xhi () noexcept { return XHI; }
     307             : 
     308             : 
     309             :         /**
     310             :          * Returns the number of elements of the Array2D object in the
     311             :          * \a x direction as an unsigned integer.
     312             :          */
     313             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     314             :         static constexpr unsigned int xlen () noexcept { return (XHI-XLO+1); }
     315             : 
     316             :         /**
     317             :          * Returns the index of the lower bound of the Array2D object in the
     318             :          * \a y direction.
     319             :          * Can be other than 0.
     320             :          */
     321             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     322             :         static constexpr int ylo () noexcept { return YLO; }
     323             : 
     324             :         /**
     325             :          * Returns the index of the upper bound of the Array2D object in the
     326             :          * \a y direction.
     327             :          */
     328             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     329             :         static constexpr int yhi () noexcept { return YHI; }
     330             : 
     331             : 
     332             :         /**
     333             :          * Returns the number of elements of the Array2D object in the
     334             :          * \a y direction as an unsigned integer.
     335             :          */
     336             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     337             :         static constexpr unsigned int ylen () noexcept { return (YHI-YLO+1); }
     338             : 
     339             :         /**
     340             :          * Returns a \c const pointer address to the first element of the
     341             :          * Array2D object, as if the object is treated as one-dimensional.
     342             :          */
     343             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     344             :         const T* begin () const noexcept { return arr; }
     345             : 
     346             :         /**
     347             :          * Returns a \c const pointer address right after the last element of the
     348             :          * Array2D object, as if the object is treated as one-dimensional.
     349             :          */
     350             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     351             :         const T* end () const noexcept { return arr + (XHI-XLO+1)*(YHI-YLO+1); }
     352             : 
     353             :         /**
     354             :          * Returns a pointer address to the first element of the
     355             :          * Array2D object, as if the object is treated as one-dimensional.
     356             :          */
     357             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     358             :         T* begin () noexcept { return arr; }
     359             : 
     360             :         /**
     361             :          * Returns a pointer address right after the last element of the
     362             :          * Array2D object, as if the object is treated as one-dimensional.
     363             :          */
     364             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     365             :         T* end () noexcept { return arr + (XHI-XLO+1)*(YHI-YLO+1); }
     366             : 
     367             :         /**
     368             :          * The elements of an Array2D object are accessed using parentheses,
     369             :          * e.g. \c array(i,j), instead of using square brackets.
     370             :          * If the order is not specified, Fortran column-major order is assumed
     371             :          * (the index \c i moves the fastest)
     372             :          */
     373             :         template <typename O=ORDER,
     374             :                   std::enable_if_t<std::is_same_v<O,Order::F>,int> = 0>
     375             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     376             :         const T& operator() (int i, int j) const noexcept {
     377             :             AMREX_ASSERT(i >= XLO && i <= XHI && j >= YLO && j <= YHI);
     378             :             return arr[i+j*(XHI-XLO+1)-(YLO*(XHI-XLO+1)+XLO)];
     379             :         }
     380             : 
     381             :         /**
     382             :          * The elements of an Array2D object are accessed using parentheses,
     383             :          * e.g. \c array(i,j), instead of using square brackets.
     384             :          * If the order is not specified, Fortran column-major order is assumed
     385             :          * (the index \c i moves the fastest)
     386             :          */
     387             :         template <typename O=ORDER,
     388             :                   std::enable_if_t<std::is_same_v<O,Order::F>,int> = 0>
     389             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     390             :         T& operator() (int i, int j) noexcept {
     391             :             AMREX_ASSERT(i >= XLO && i <= XHI && j >= YLO && j <= YHI);
     392             :             return arr[i+j*(XHI-XLO+1)-(YLO*(XHI-XLO+1)+XLO)];
     393             :         }
     394             : 
     395             :         /**
     396             :          * The elements of an Array2D object are accessed using parentheses,
     397             :          * e.g. \c array(i,j), instead of using square brackets.
     398             :          * When the order is manually specified as Order::C, row-major order
     399             :          * is used (the index \c j moves the fastest).
     400             :          */
     401             :         template <typename O=ORDER,
     402             :                   std::enable_if_t<std::is_same_v<O,Order::C>,int> = 0>
     403             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     404             :         const T& operator() (int i, int j) const noexcept {
     405             :             AMREX_ASSERT(i >= XLO && i <= XHI && j >= YLO && j <= YHI);
     406             :             return arr[j+i*(YHI-YLO+1)-(XLO*(YHI-YLO+1)+YLO)];
     407             :         }
     408             : 
     409             :         /**
     410             :          * The elements of an Array2D object are accessed using parentheses,
     411             :          * e.g. \c array(i,j), instead of using square brackets.
     412             :          * When the order is manually specified as Order::C, row-major order
     413             :          * is used (the index \c j moves the fastest).
     414             :          */
     415             :         template <typename O=ORDER,
     416             :                   std::enable_if_t<std::is_same_v<O,Order::C>,int> = 0>
     417             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     418             :         T& operator() (int i, int j) noexcept {
     419             :             AMREX_ASSERT(i >= XLO && i <= XHI && j >= YLO && j <= YHI);
     420             :             return arr[j+i*(YHI-YLO+1)-(XLO*(YHI-YLO+1)+YLO)];
     421             :         }
     422             : 
     423             :         /**
     424             :          * When called without any arguments, returns the sum of all
     425             :          * elements in the Array2D object.
     426             :          */
     427             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     428             :         constexpr T sum () const noexcept
     429             :         {
     430             :             T s = 0;
     431             :             for (int i = 0; i < (XHI-XLO+1)*(YHI-YLO+1); ++i) {
     432             :                 s += arr[i];
     433             :             }
     434             :             return s;
     435             :         }
     436             : 
     437             :         /**
     438             :          * When called with two arguments, performs a sum reduction over
     439             :          * the specified \c axis, for a particular location index \c loc.
     440             :          *
     441             :          * \param axis The dimension to reduce (0 for \a x dimension,
     442             :          *             1 for \a y dimension)
     443             :          * \param loc  The appropriate location index
     444             :          *
     445             :          * This can be used, for instance, to calculate the sum over the \a y
     446             :          * dimension of an Array2D object that was instantiated as
     447             :          * \verbatim Array2D<amrex::Real, 1, M, 1, N> array; \endverbatim
     448             :          *
     449             :          * One could instantiate an Array1D object to hold the results,
     450             :          * \verbatim Array1D<amrex::Real, 1, M> vec; \endverbatim
     451             :          * and then perform the summation for each element of the resulting
     452             :          * vector.
     453             :          * \verbatim
     454             :          for (int i = 1; i <= M; ++i) {
     455             :              vec(i) = array.sum(1,i)
     456             :          }
     457             :          \endverbatim
     458             :          * In this example, the axis is 1 and the location index is \c i.
     459             :          *
     460             :          */
     461             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     462             :         constexpr T sum (int axis, int loc) const noexcept
     463             :         {
     464             :             T s = 0;
     465             :             if        (axis == 0) {
     466             :                 int j = loc;
     467             :                 for (int i = XLO; i <= XHI; ++i) {
     468             :                     s += this->operator()(i,j);
     469             :                 }
     470             :             } else if (axis == 1) {
     471             :                 int i = loc;
     472             :                 for (int j = YLO; j <= YHI; ++j) {
     473             :                     s += this->operator()(i,j);
     474             :                 }
     475             :             }
     476             :             return s;
     477             :         }
     478             : 
     479             :         /**
     480             :          * When called without any arguments, returns the product of all
     481             :          * elements in the Array2D object.
     482             :          */
     483             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     484             :         constexpr T product () const noexcept
     485             :         {
     486             :             T p = 1;
     487             :             for (int i = 0; i < (XHI-XLO+1)*(YHI-YLO+1); ++i) {
     488             :                 p *= arr[i];
     489             :             }
     490             :             return p;
     491             :         }
     492             : 
     493             :         /**
     494             :          * When called with two arguments, performs a product reduction over
     495             :          * the specified \c axis, for a particular location index \c loc.
     496             :          *
     497             :          * \param axis The dimension to reduce (0 for \a x dimension,
     498             :          *             1 for \a y dimension)
     499             :          * \param loc  The appropriate location index
     500             :          *
     501             :          * This can be used, for instance, to calculate the product over the \a x
     502             :          * dimension of an Array2D object that was instantiated as
     503             :          * \verbatim Array2D<amrex::Real, 1, M, 1, N> array; \endverbatim
     504             :          *
     505             :          * One could instantiate an Array1D object to hold the results with,
     506             :          * \verbatim Array1D<amrex::Real, 1, N> vec; \endverbatim
     507             :          * and then perform the product for each element of the resulting
     508             :          * vector.
     509             :          *
     510             :          * \verbatim
     511             :          for (int j = 1; j <= N; ++j) {
     512             :              vec(j) = array.sum(0,j)
     513             :          }
     514             :          \endverbatim
     515             :          * In this example, the axis is 0 and the location index is \c j.
     516             :          *
     517             :          */
     518             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     519             :         constexpr T product (int axis, int loc) const noexcept
     520             :         {
     521             :             T p = 1;
     522             :             if        (axis == 0) {
     523             :                 int j = loc;
     524             :                 for (int i = XLO; i <= XHI; ++i) {
     525             :                     p *= this->operator()(i,j);
     526             :                 }
     527             :             } else if (axis == 1) {
     528             :                 int i = loc;
     529             :                 for (int j = YLO; j <= YHI; ++j) {
     530             :                     p *= this->operator()(i,j);
     531             :                 }
     532             :             }
     533             :             return p;
     534             :         }
     535             : 
     536             :         T arr[(XHI-XLO+1)*(YHI-YLO+1)];
     537             :     };
     538             : 
     539             : 
     540             :     /**
     541             :      * A GPU-compatible three-dimensional array.
     542             :      *
     543             :      * \tparam XLO Index for lower bound in \a x dimension. Can be other than 0.
     544             :      * \tparam XHI Index for upper bound in \a x dimension.
     545             :      * \tparam YLO Index for lower bound in \a y dimension. Can be other than 0.
     546             :      * \tparam YHI Index for upper bound in \a y dimension.
     547             :      * \tparam ZLO Index for lower bound in \a z dimension. Can be other than 0.
     548             :      * \tparam ZHI Index for upper bound in \a z dimension.
     549             :      * \tparam ORDER Either Order::C (C/C++ row-major order) or
     550             :      *               Order::F (Fortran column-major order, which is the
     551             :      *               default if not given)
     552             :      */
     553             :     template <class T, int XLO, int XHI, int YLO, int YHI, int ZLO, int ZHI,
     554             :               class ORDER=Order::F>
     555             :     struct Array3D
     556             :     {
     557             :         /**
     558             :          * Returns the total number of elements in the Array3D object as an
     559             :          * unsigned integer.
     560             :          */
     561             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     562             :         static constexpr unsigned int size () noexcept { return (XHI-XLO+1)*(YHI-YLO+1)*(ZHI-ZLO+1); }
     563             : 
     564             :         /**
     565             :          * Returns the index of the lower bound of the Array3D object in the
     566             :          * \a x direction.
     567             :          * Can be other than 0.
     568             :          */
     569             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     570             :         static constexpr int xlo () noexcept { return XLO; }
     571             : 
     572             :         /**
     573             :          * Returns the index of the upper bound of the Array3D object in the
     574             :          * \a x direction.
     575             :          */
     576             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     577             :         static constexpr int xhi () noexcept { return XHI; }
     578             : 
     579             :         /**
     580             :          * Returns the number of elements of the Array3D object in the
     581             :          * \a x direction as an unsigned integer.
     582             :          */
     583             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     584             :         static constexpr unsigned int xlen () noexcept { return (XHI-XLO+1); }
     585             : 
     586             :         /**
     587             :          * Returns the index of the lower bound of the Array3D object in the
     588             :          * \a y direction.
     589             :          * Can be other than 0.
     590             :          */
     591             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     592             :         static constexpr int ylo () noexcept { return YLO; }
     593             : 
     594             :         /**
     595             :          * Returns the index of the upper bound of the Array3D object in the
     596             :          * \a y direction.
     597             :          */
     598             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     599             :         static constexpr int yhi () noexcept { return YHI; }
     600             : 
     601             : 
     602             :         /**
     603             :          * Returns the number of elements of the Array3D object in the
     604             :          * \a y direction as an unsigned integer.
     605             :          */
     606             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     607             :         static constexpr unsigned int ylen () noexcept { return (YHI-YLO+1); }
     608             : 
     609             :         /**
     610             :          * Returns the index of the lower bound of the Array3D object in the
     611             :          * \a z direction.
     612             :          * Can be other than 0.
     613             :          */
     614             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     615             :         static constexpr int zlo () noexcept { return ZLO; }
     616             : 
     617             :         /**
     618             :          * Returns the index of the upper bound of the Array3D object in the
     619             :          * \a z direction.
     620             :          */
     621             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     622             :         static constexpr int zhi () noexcept { return ZHI; }
     623             : 
     624             :         /**
     625             :          * Returns the number of elements of the Array3D object in the
     626             :          * \a z direction as an unsigned integer.
     627             :          */
     628             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     629             :         static constexpr unsigned int zlen () noexcept { return (ZHI-ZLO+1); }
     630             : 
     631             :         /**
     632             :          * Returns a \c const pointer address to the first element of the
     633             :          * Array3D object, as if the object is treated as one-dimensional.
     634             :          */
     635             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     636             :         const T* begin () const noexcept { return arr; }
     637             : 
     638             :         /**
     639             :          * Returns a \c const pointer address right after the last element of the
     640             :          * Array3D object, as if the object is treated as one-dimensional.
     641             :          */
     642             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     643             :         const T* end () const noexcept { return arr + (XHI-XLO+1)*(YHI-YLO+1)*(ZHI-ZLO+1); }
     644             : 
     645             :         /**
     646             :          * Returns a pointer address to the first element of the
     647             :          * Array3D object, as if the object is treated as one-dimensional.
     648             :          */
     649             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     650             :         T* begin () noexcept { return arr; }
     651             : 
     652             :         /**
     653             :          * Returns a pointer address right after the last element of the
     654             :          * Array3D object, as if the object is treated as one-dimensional.
     655             :          */
     656             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     657             :         T* end () noexcept { return arr + (XHI-XLO+1)*(YHI-YLO+1)*(ZHI-ZLO+1); }
     658             : 
     659             :         /**
     660             :          * The elements of an Array3D object are accessed using parentheses,
     661             :          * e.g. \c array(i,j,k), instead of using square brackets.
     662             :          * If the order is not specified, Fortran column-major order is assumed
     663             :          * (the index \c i moves the fastest)
     664             :          */
     665             :         template <typename O=ORDER,
     666             :                   std::enable_if_t<std::is_same_v<O,Order::F>,int> = 0>
     667             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     668             :         const T& operator() (int i, int j, int k) const noexcept {
     669             :             return arr[i+j*(XHI-XLO+1)+k*((XHI-XLO+1)*(YHI-YLO+1))
     670             :                        -(ZLO*((XHI-XLO+1)*(YHI-YLO+1))+YLO*(XHI-XLO+1)+XLO)];
     671             :         }
     672             : 
     673             :         /**
     674             :          * The elements of an Array3D object are accessed using parentheses,
     675             :          * e.g. \c array(i,j,k), instead of using square brackets.
     676             :          * If the order is not specified, Fortran column-major order is assumed
     677             :          * (the index \c i moves the fastest)
     678             :          */
     679             :         template <typename O=ORDER,
     680             :                   std::enable_if_t<std::is_same_v<O,Order::F>,int> = 0>
     681             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     682             :         T& operator() (int i, int j, int k) noexcept {
     683             :             return arr[i+j*(XHI-XLO+1)+k*((XHI-XLO+1)*(YHI-YLO+1))
     684             :                        -(ZLO*((XHI-XLO+1)*(YHI-YLO+1))+YLO*(XHI-XLO+1)+XLO)];
     685             :         }
     686             : 
     687             :         /**
     688             :          * The elements of an Array3D object are accessed using parentheses,
     689             :          * e.g. \c array(i,j,k), instead of using square brackets.
     690             :          * When the order is manually specified as Order::C, row-major order
     691             :          * is used (the index \c k moves the fastest).
     692             :          */
     693             :         template <typename O=ORDER,
     694             :                   std::enable_if_t<std::is_same_v<O,Order::C>,int> = 0>
     695             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     696             :         const T& operator() (int i, int j, int k) const noexcept {
     697             :             return arr[k+j*(ZHI-ZLO+1)+i*((ZHI-ZLO+1)*(YHI-YLO+1))
     698             :                        -(XLO*((ZHI-ZLO+1)*(YHI-YLO+1))+YLO*(ZHI-ZLO+1)+ZLO)];
     699             :         }
     700             : 
     701             :         /**
     702             :          * The elements of an Array3D object are accessed using parentheses,
     703             :          * e.g. \c array(i,j,k), instead of using square brackets.
     704             :          * When the order is manually specified as Order::C, row-major order
     705             :          * is used (the index \c k moves the fastest).
     706             :          */
     707             :         template <typename O=ORDER,
     708             :                   std::enable_if_t<std::is_same_v<O,Order::C>,int> = 0>
     709             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     710             :         T& operator() (int i, int j, int k) noexcept {
     711             :             return arr[k+j*(ZHI-ZLO+1)+i*((ZHI-ZLO+1)*(YHI-YLO+1))
     712             :                        -(XLO*((ZHI-ZLO+1)*(YHI-YLO+1))+YLO*(ZHI-ZLO+1)+ZLO)];
     713             :         }
     714             : 
     715             :         /**
     716             :          * When called without any arguments, returns the sum of all
     717             :          * elements in the Array3D object.
     718             :          */
     719             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     720             :         constexpr T sum () const noexcept
     721             :         {
     722             :             T s = 0;
     723             :             for (int i = 0; i < (XHI-XLO+1)*(YHI-YLO+1)*(ZHI-ZLO+1); ++i) {
     724             :                 s += arr[i];
     725             :             }
     726             :             return s;
     727             :         }
     728             : 
     729             :         /**
     730             :          * When called with three arguments, performs a sum reduction over
     731             :          * the specified \c axis, for a particular set of location indices \c loc0
     732             :          * and \c loc1.
     733             :          *
     734             :          * \param axis The dimension to reduce (0 for \a x dimension,
     735             :          *             1 for \a y dimension, 2 for \a z dimension)
     736             :          * \param loc0 The appropriate location index (either \c i or \c j)
     737             :          * \param loc1 The appropriate location index (either \c j or \c k)
     738             :          *
     739             :          * This can be used, for instance, to calculate the sum over the \a x
     740             :          * dimension of an Array3D object that was instantiated as
     741             :          * \verbatim Array3D<amrex::Real, 1, M, 1, N, 1, K> array; \endverbatim
     742             :          *
     743             :          * One could instantiate an Array2D object to hold the results,
     744             :          * \verbatim Array2D<amrex::Real, 1, N, 1, K> mat; \endverbatim
     745             :          * and then perform the summation for each element of the resulting
     746             :          * matrix.
     747             :          * \verbatim
     748             :          for     (int j = 1; j <= N; ++j) {
     749             :              for (int k = 1; k <= K; ++k) {
     750             :                  mat(j,k) = array.sum(0,j,k)
     751             :              }
     752             :          }
     753             :          \endverbatim
     754             :          * In this example, the axis is 0 and the location indices are \c loc0 = \c j
     755             :          * and \c loc1 = \c k. For axis = 1, the location indices are treated as
     756             :          * \c loc0 = \c i and \c loc1 = \c k; for axis = 2, \c loc0 = \c j and \c loc1 = \c k.
     757             :          *
     758             :          */
     759             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     760             :         constexpr T sum (int axis, int loc0, int loc1) const noexcept
     761             :         {
     762             :             T s = 0;
     763             :             if        (axis == 0) {
     764             :                 int j = loc0;
     765             :                 int k = loc1;
     766             :                 for (int i = XLO; i <= XHI; ++i) {
     767             :                     s += this->operator()(i,j,k);
     768             :                 }
     769             :             } else if (axis == 1) {
     770             :                 int i = loc0;
     771             :                 int k = loc1;
     772             :                 for (int j = YLO; j <= YHI; ++j) {
     773             :                     s += this->operator()(i,j,k);
     774             :                 }
     775             :             } else if (axis == 2) {
     776             :                 int i = loc0;
     777             :                 int j = loc1;
     778             :                 for (int k = ZLO; k <= ZHI; ++k) {
     779             :                     s += this->operator()(i,j,k);
     780             :                 }
     781             :             }
     782             :             return s;
     783             :         }
     784             : 
     785             :         /**
     786             :          * When called without any arguments, returns the product of all
     787             :          * elements in the Array3D object.
     788             :          */
     789             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     790             :         constexpr T product () const noexcept
     791             :         {
     792             :             T p = 1;
     793             :             for (int i = 0; i < (XHI-XLO+1)*(YHI-YLO+1)*(ZHI-ZLO+1); ++i) {
     794             :                 p *= arr[i];
     795             :             }
     796             :             return p;
     797             :         }
     798             : 
     799             : 
     800             :         /**
     801             :          * When called with three arguments, performs a product reduction over
     802             :          * the specified \c axis, for a particular set of location indices \c loc0
     803             :          * and \c loc1.
     804             :          *
     805             :          * \param axis The dimension to reduce (0 for \a x dimension,
     806             :          *             1 for \a y dimension, 2 for \a z dimension)
     807             :          * \param loc0 The appropriate location index (either \c i or \c j)
     808             :          * \param loc1 The appropriate location index (either \c j or \c k)
     809             :          *
     810             :          * This can be used, for instance, to calculate the sum over the \a z
     811             :          * dimension of an Array3D object that was instantiated as
     812             :          * \verbatim Array3D<amrex::Real, 1, M, 1, N, 1, K> array; \endverbatim
     813             :          *
     814             :          * One could instantiate an Array2D object to hold the results,
     815             :          * \verbatim Array2D<amrex::Real, 1, M, 1, N> mat; \endverbatim
     816             :          * and then perform the summation for each element of the resulting
     817             :          * matrix.
     818             :          * \verbatim
     819             :          for     (int j = 1; j <= N; ++j) {
     820             :              for (int i = 1; i <= M; ++i) {
     821             :                  mat(i,j) = array.sum(2,i,j)
     822             :              }
     823             :          }
     824             :          \endverbatim
     825             :          * In this example, the axis is 2 and the location indices are \c loc0 = \c i
     826             :          * and \c loc1 = \c j. For axis = 0, the location indices are treated as
     827             :          * \c loc0 = \c j and \c loc1 = \c k; for axis = 1, \c loc0 = \c i and \c loc1 = \c k.
     828             :          *
     829             :          */
     830             :         [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
     831             :         constexpr T product (const int axis, const int loc0, const int loc1) const noexcept
     832             :         {
     833             :             T p = 1;
     834             :             if        (axis == 0) {
     835             :                 int j = loc0;
     836             :                 int k = loc1;
     837             :                 for (int i = XLO; i <= XHI; ++i) {
     838             :                     p *= this->operator()(i,j,k);
     839             :                 }
     840             :             } else if (axis == 1) {
     841             :                 int i = loc0;
     842             :                 int k = loc1;
     843             :                 for (int j = YLO; j <= YHI; ++j) {
     844             :                     p *= this->operator()(i,j,k);
     845             :                 }
     846             :             } else if (axis == 2) {
     847             :                 int i = loc0;
     848             :                 int j = loc1;
     849             :                 for (int k = ZLO; k <= ZHI; ++k) {
     850             :                     p *= this->operator()(i,j,k);
     851             :                 }
     852             :             }
     853             :             return p;
     854             :         }
     855             : 
     856             :         T arr[(XHI-XLO+1)*(YHI-YLO+1)*(ZHI-ZLO+1)];
     857             :     };
     858             : }
     859             : 
     860             : namespace amrex
     861             : {
     862             :     template <class T, typename = typename T::FABType>
     863             :     std::array<T*,AMREX_SPACEDIM> GetArrOfPtrs (std::array<T,AMREX_SPACEDIM>& a) noexcept
     864             :     {
     865             :         return {{AMREX_D_DECL(a.data(), a.data()+1, a.data()+2)}};
     866             :     }
     867             : 
     868             :     template <class T>
     869             :     std::array<T*,AMREX_SPACEDIM> GetArrOfPtrs (const std::array<std::unique_ptr<T>,AMREX_SPACEDIM>& a) noexcept
     870             :     {
     871             :         return {{AMREX_D_DECL(a[0].get(), a[1].get(), a[2].get())}};
     872             :     }
     873             : 
     874             :     template <class T>
     875             :     std::array<T const*,AMREX_SPACEDIM> GetArrOfConstPtrs (const std::array<T,AMREX_SPACEDIM>& a) noexcept
     876             :     {
     877             :         return {{AMREX_D_DECL(a.data(), a.data()+1, a.data()+2)}};
     878             :     }
     879             : 
     880             :     template <class T>
     881             :     std::array<T const*,AMREX_SPACEDIM> GetArrOfConstPtrs (const std::array<T*,AMREX_SPACEDIM>& a) noexcept
     882             :     {
     883             :         return {{AMREX_D_DECL(a[0], a[1], a[2])}};
     884             :     }
     885             : 
     886             :     template <class T>
     887             :     std::array<T const*,AMREX_SPACEDIM> GetArrOfConstPtrs (const std::array<std::unique_ptr<T>,AMREX_SPACEDIM>& a) noexcept
     888             :     {
     889             :         return {{AMREX_D_DECL(a[0].get(), a[1].get(), a[2].get())}};
     890             :     }
     891             : 
     892             : }
     893             : 
     894             : namespace amrex
     895             : {
     896             :     inline XDim3 makeXDim3 (const Array<Real,AMREX_SPACEDIM>& a) noexcept
     897             :     {
     898             : #if (AMREX_SPACEDIM == 1)
     899             :         return XDim3{a[0], 0., 0.};
     900             : #elif (AMREX_SPACEDIM == 2)
     901             :         return XDim3{a[0], a[1], 0.};
     902             : #else
     903             :         return XDim3{a[0], a[1], a[2]};
     904             : #endif
     905             :     }
     906             : }
     907             : 
     908             : #endif

Generated by: LCOV version 1.14