diff --git a/Src/Base/AMReX_BaseFwd.H b/Src/Base/AMReX_BaseFwd.H index 622689a2e8e..d187673869a 100644 --- a/Src/Base/AMReX_BaseFwd.H +++ b/Src/Base/AMReX_BaseFwd.H @@ -22,7 +22,9 @@ class BoxList; class DistributionMapping; class Geometry; -class Box; +template +class BoxND; +using Box = BoxND; template class IntVectND; using IntVect = IntVectND; diff --git a/Src/Base/AMReX_Box.H b/Src/Base/AMReX_Box.H index f29428b1022..7d4cb30c43e 100644 --- a/Src/Base/AMReX_Box.H +++ b/Src/Base/AMReX_Box.H @@ -21,59 +21,61 @@ namespace amrex { +template +class BoxND; +using Box = BoxND; class BoxCommHelper; /** * \brief A Rectangular Domain on an Integer Lattice * -* A Box is an abstraction for defining discrete regions of -* SPACEDIM indexing space. Boxes have an IndexType, which defines +* A BoxND is an abstraction for defining discrete regions of +* dim indexing space. Boxes have an IndexType, which defines * IndexType::CELL or IndexType::NODE based points for each direction * and a low and high INTVECT which defines the lower and upper corners -* of the Box. Boxes can exist in positive and negative indexing space. +* of the BoxND. Boxes can exist in positive and negative indexing space. * -* Box is a dimension dependent class, so SPACEDIM must be +* Box is a dimension dependent alias to BoxND, so AMREX_SPACEDIM must be * defined as either 1, 2, or 3 when compiling. */ -class Box +template +class BoxND { friend MPI_Datatype ParallelDescriptor::Mpi_typemap::type(); friend class BoxCommHelper; public: /* - * \brief The default constructor. For safety, the constructed Box is + * \brief The default constructor. For safety, the constructed BoxND is * invalid and may be tested for validity with ok(). * DO NOT CHANGE THIS BEHAVIOR! */ AMREX_GPU_HOST_DEVICE - constexpr Box () noexcept + constexpr BoxND () noexcept : smallend(1), bigend(0) {} - //! Construct cell-centered type Box. + //! Construct cell-centered type BoxND. AMREX_GPU_HOST_DEVICE - constexpr Box (const IntVect& small, const IntVect& big) noexcept + constexpr BoxND (const IntVectND& small, const IntVectND& big) noexcept : smallend(small), bigend(big) {} - //! Construct box with specified lengths. + //! Construct BoxND with specified lengths. AMREX_GPU_HOST_DEVICE - Box (const IntVect& small, const int* vec_len) noexcept + BoxND (const IntVectND& small, const int* vec_len) noexcept : smallend(small), - bigend(AMREX_D_DECL(small[0]+vec_len[0]-1, - small[1]+vec_len[1]-1, - small[2]+vec_len[2]-1)) + bigend(small + IntVectND(vec_len) - 1) {} /** - * \brief Construct Box with given type. small and big are expected + * \brief Construct BoxND with given type. small and big are expected * to be consistent with given type. */ AMREX_GPU_HOST_DEVICE - Box (const IntVect& small, const IntVect& big, const IntVect& typ) noexcept + BoxND (const IntVectND& small, const IntVectND& big, const IntVectND& typ) noexcept : smallend(small), bigend(big), btype(typ) @@ -83,27 +85,27 @@ public: //! Construct dimension specific Boxes. AMREX_GPU_HOST_DEVICE - Box (const IntVect& small, const IntVect& big, IndexType t) noexcept + BoxND (const IntVectND& small, const IntVectND& big, IndexTypeND t) noexcept : smallend(small), bigend(big), btype(t) {} - template + template = 0> AMREX_GPU_HOST_DEVICE - explicit Box (Array4 const& a) noexcept - : smallend(AMREX_D_DECL(a.begin.x,a.begin.y,a.begin.z)), - bigend (AMREX_D_DECL(a.end.x-1,a.end.y-1,a.end.z-1)) + explicit BoxND (Array4 const& a) noexcept + : smallend(a.begin), + bigend(IntVectND(a.end) - 1) {} // dtor, copy-ctor, copy-op=, move-ctor, and move-op= are compiler generated. - //! Get the smallend of the box. + //! Get the smallend of the BoxND. [[nodiscard]] AMREX_GPU_HOST_DEVICE - const IntVect& smallEnd () const& noexcept { return smallend; } + const IntVectND& smallEnd () const& noexcept { return smallend; } - //! Get the smallend of the box. - [[nodiscard]] const IntVect& smallEnd () && = delete; + //! Get the smallend of the BoxND. + [[nodiscard]] const IntVectND& smallEnd () && = delete; //! Returns the coordinate of the low end in the given direction. [[nodiscard]] AMREX_GPU_HOST_DEVICE @@ -111,10 +113,10 @@ public: //! Get the bigend. [[nodiscard]] AMREX_GPU_HOST_DEVICE - const IntVect& bigEnd () const& noexcept { return bigend; } + const IntVectND& bigEnd () const& noexcept { return bigend; } //! Get the bigend. - [[nodiscard]] const IntVect& bigEnd () && = delete; + [[nodiscard]] const IntVectND& bigEnd () && = delete; //! Returns the coordinate of the high end in the given direction. [[nodiscard]] AMREX_GPU_HOST_DEVICE @@ -122,69 +124,53 @@ public: //! Returns the indexing type. [[nodiscard]] AMREX_GPU_HOST_DEVICE - IndexType ixType () const noexcept { return btype; } + IndexTypeND ixType () const noexcept { return btype; } //! Returns the indexing type. [[nodiscard]] AMREX_GPU_HOST_DEVICE - IntVect type () const noexcept { return btype.ixType(); } + IntVectND type () const noexcept { return btype.ixType(); } //! Returns the indexing type in the specified direction. [[nodiscard]] AMREX_GPU_HOST_DEVICE IndexType::CellIndex type (int dir) const noexcept { return btype.ixType(dir); } - //! Return the length of the Box. + //! Return the length of the BoxND. [[nodiscard]] AMREX_GPU_HOST_DEVICE - IntVect size () const noexcept + IntVectND size () const noexcept { - return IntVect(AMREX_D_DECL(bigend[0]-smallend[0] + 1, - bigend[1]-smallend[1] + 1, - bigend[2]-smallend[2] + 1)); + return bigend - smallend + 1; } - //! Return the length of the Box. + //! Return the length of the BoxND. [[nodiscard]] AMREX_GPU_HOST_DEVICE - IntVect length () const noexcept + IntVectND length () const noexcept { - return IntVect(AMREX_D_DECL(bigend[0]-smallend[0] + 1, - bigend[1]-smallend[1] + 1, - bigend[2]-smallend[2] + 1)); + return bigend - smallend + 1; } - //! Return the length of the Box in given direction. + //! Return the length of the BoxND in given direction. [[nodiscard]] AMREX_GPU_HOST_DEVICE int length (int dir) const noexcept { return bigend[dir] - smallend[dir] + 1; } + template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE GpuArray length3d () const noexcept { -#if (AMREX_SPACEDIM == 1) - return {{bigend[0]-smallend[0]+1, 1, 1}}; -#elif (AMREX_SPACEDIM == 2) - return {{bigend[0]-smallend[0]+1, bigend[1]-smallend[1]+1, 1}}; -#elif (AMREX_SPACEDIM == 3) - return {{bigend[0]-smallend[0]+1, bigend[1]-smallend[1]+1, bigend[2]-smallend[2]+1}}; -#endif + Dim3 len3d = length().dim3(1); + return {{len3d.x, len3d.y, len3d.z}}; } + template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE GpuArray loVect3d () const noexcept { -#if (AMREX_SPACEDIM == 1) - return {{smallend[0], 0, 0}}; -#elif (AMREX_SPACEDIM == 2) - return {{smallend[0], smallend[1], 0}}; -#elif (AMREX_SPACEDIM == 3) - return {{smallend[0], smallend[1], smallend[2]}}; -#endif + Dim3 lo3d = smallend.dim3(0); + return {{lo3d.x, lo3d.y, lo3d.z}}; } + template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE GpuArray hiVect3d () const noexcept { -#if (AMREX_SPACEDIM == 1) - return {{bigend[0], 0, 0}}; -#elif (AMREX_SPACEDIM == 2) - return {{bigend[0], bigend[1], 0}}; -#elif (AMREX_SPACEDIM == 3) - return {{bigend[0], bigend[1], bigend[2]}}; -#endif + Dim3 hi3d = bigend.dim3(0); + return {{hi3d.x, hi3d.y, hi3d.z}}; } //! Returns a constant pointer the array of low end coordinates. Useful for calls to FORTRAN. @@ -205,77 +191,77 @@ public: return face.isLow() ? smallend[dir] : bigend[dir]; } - //! Checks if it is an empty box. + //! Checks if it is an empty BoxND. [[nodiscard]] AMREX_GPU_HOST_DEVICE bool isEmpty () const noexcept { return !ok(); } - //! Checks if it is a proper Box (including a valid type). + //! Checks if it is a proper BoxND (including a valid type). [[nodiscard]] AMREX_GPU_HOST_DEVICE bool ok () const noexcept { return bigend.allGE(smallend) && btype.ok(); } - //! Returns true if argument is contained within Box. + //! Returns true if argument is contained within BoxND. [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool contains (const IntVect& p) const noexcept { return p.allGE(smallend) && p.allLE(bigend); } + bool contains (const IntVectND& p) const noexcept { + return p.allGE(smallend) && p.allLE(bigend); + } - //! Returns true if argument is contained within Box. + //! Returns true if argument is contained within BoxND. + template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE bool contains (const Dim3& p) const noexcept { - return AMREX_D_TERM(p.x >= smallend[0] && p.x <= bigend[0], - && p.y >= smallend[1] && p.y <= bigend[1], - && p.z >= smallend[2] && p.z <= bigend[2]); + IntVectND piv{p}; + return contains(piv); } - //! Returns true if argument is contained within Box. + //! Returns true if argument is contained within BoxND. + template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE -#if (AMREX_SPACEDIM == 1) - bool contains (int i, int, int) const noexcept { -#elif (AMREX_SPACEDIM == 2) - bool contains (int i, int j, int) const noexcept { -#else bool contains (int i, int j, int k) const noexcept { -#endif - return AMREX_D_TERM(i >= smallend[0] && i <= bigend[0], - && j >= smallend[1] && j <= bigend[1], - && k >= smallend[2] && k <= bigend[2]); + Dim3 p3d{i, j, k}; + return contains(p3d); } - /** \brief Returns true if argument is contained within Box. + /** \brief Returns true if argument is contained within BoxND. * It is an error if the Boxes have different types. */ [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool contains (const Box& b) const noexcept + bool contains (const BoxND& b) const noexcept { BL_ASSERT(sameType(b)); return b.smallend.allGE(smallend) && b.bigend.allLE(bigend); } - //! Returns true if argument is strictly contained within Box. + //! Returns true if argument is strictly contained within BoxND. [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool strictly_contains (const IntVect& p) const noexcept { return p.allGT(smallend) && p.allLT(bigend); } + bool strictly_contains (const IntVectND& p) const noexcept { + return p.allGT(smallend) && p.allLT(bigend); + } /** - * \brief Returns true if argument is strictly contained within Box. + * \brief Returns true if argument is strictly contained within BoxND. * It is an error if the Boxes have different types. */ [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool strictly_contains (const Box& b) const noexcept + bool strictly_contains (const BoxND& b) const noexcept { BL_ASSERT(sameType(b)); return b.smallend.allGT(smallend) && b.bigend.allLT(bigend); } - //! Returns true if argument is strictly contained within Box. + //! Returns true if argument is strictly contained within BoxND. + template = 0> + [[nodiscard]] AMREX_GPU_HOST_DEVICE + bool strictly_contains (const Dim3& p) const noexcept { + IntVectND piv{p}; + return strictly_contains(piv); + } + + //! Returns true if argument is strictly contained within BoxND. + template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE -#if (AMREX_SPACEDIM == 1) - bool strictly_contains (int i, int, int) const noexcept { -#elif (AMREX_SPACEDIM == 2) - bool strictly_contains (int i, int j, int) const noexcept { -#else bool strictly_contains (int i, int j, int k) const noexcept { -#endif - return AMREX_D_TERM(i > smallend[0] && i < bigend[0], - && j > smallend[1] && j < bigend[1], - && k > smallend[2] && k < bigend[2]); + Dim3 p3d{i, j, k}; + return strictly_contains(p3d); } /** @@ -283,34 +269,32 @@ public: * It is an error if the Boxes have different types. */ [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool intersects (const Box& b) const noexcept { Box isect(*this); isect &= b; return isect.ok(); } + bool intersects (const BoxND& b) const noexcept { BoxND isect(*this); isect &= b; return isect.ok(); } /** * \brief Returns true is Boxes same size, ie translates of each other,. * It is an error if they have different types. */ [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool sameSize (const Box& b) const noexcept { + bool sameSize (const BoxND& b) const noexcept { BL_ASSERT(sameType(b)); - return AMREX_D_TERM(length(0) == b.length(0), - && length(1) == b.length(1), - && length(2) == b.length(2)); + return length() == b.length(); } //! Returns true if Boxes have same type. [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool sameType (const Box &b) const noexcept { return btype == b.btype; } + bool sameType (const BoxND &b) const noexcept { return btype == b.btype; } //! Returns true if Boxes are identical (including type). [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool operator== (const Box& b) const noexcept { return smallend == b.smallend && bigend == b.bigend && b.btype == btype; } + bool operator== (const BoxND& b) const noexcept { return smallend == b.smallend && bigend == b.bigend && b.btype == btype; } //! Returns true if Boxes differ (including type). [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool operator!= (const Box& b) const noexcept { return !operator==(b); } + bool operator!= (const BoxND& b) const noexcept { return !operator==(b); } [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool operator< (const Box& rhs) const noexcept + bool operator< (const BoxND& rhs) const noexcept { return btype < rhs.btype || ((btype == rhs.btype) && @@ -318,67 +302,106 @@ public: ((smallend == rhs.smallend) && (bigend < rhs.bigend)) )); } [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool operator <= (const Box& rhs) const noexcept { + bool operator <= (const BoxND& rhs) const noexcept { return !(rhs < *this); } [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool operator> (const Box& rhs) const noexcept { + bool operator> (const BoxND& rhs) const noexcept { return rhs < *this; } [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool operator>= (const Box& rhs) const noexcept { + bool operator>= (const BoxND& rhs) const noexcept { return !(*this < rhs); } - //! Returns true if Box is cell-centered in all indexing directions. + //! Returns true if BoxND is cell-centered in all indexing directions. [[nodiscard]] AMREX_GPU_HOST_DEVICE bool cellCentered () const noexcept { return !btype.any(); } + //! Assert that there are no int/Long overflows when calling length or numPts. + void checkOverflow () const noexcept { + if (ok()) { + for (int i = 0; i < dim; ++i) { + auto lo = static_cast(smallend[i]); + auto hi = static_cast(bigend[i]); + Long len = hi - lo + 1; + AMREX_ALWAYS_ASSERT_WITH_MESSAGE(len>=0 && len::max(), + "Overflow when computing length of box"); + } + auto num_pts = static_cast(length(0)); + for (int i = 1; i < dim; ++i) { + auto len = static_cast(length(i)); + AMREX_ALWAYS_ASSERT_WITH_MESSAGE(num_pts == 0 || len == 0 || + num_pts <= std::numeric_limits::max() / len, + "Overflow when computing numPts of box"); + num_pts *= len; + } + } + } + /** - * \brief Returns the number of points contained in the Box. + * \brief Returns the number of points contained in the BoxND. */ [[nodiscard]] AMREX_GPU_HOST_DEVICE Long numPts () const noexcept { - return ok() ? AMREX_D_TERM( static_cast(length(0)), - *static_cast(length(1)), - *static_cast(length(2))) - : Long(0); +#if defined(AMREX_DEBUG) || defined(AMREX_USE_ASSERTION) + AMREX_IF_ON_HOST((checkOverflow();)) +#endif + if (ok()) { + auto num_pts = static_cast(length(0)); + for (int i = 1; i < dim; ++i) { + num_pts *= static_cast(length(i)); + } + return num_pts; + } else { + return Long(0); + } } /** - * \brief Returns the number of points contained in the Box. + * \brief Returns the number of points contained in the BoxND. * This is intended for use only in diagnostic messages. */ [[nodiscard]] AMREX_GPU_HOST_DEVICE double d_numPts () const noexcept { - return ok() ? AMREX_D_TERM( double(length(0)), - *double(length(1)), - *double(length(2))) - : 0.0; + if (ok()) { + auto num_pts = static_cast(length(0)); + for (int i = 1; i < dim; ++i) { + num_pts *= static_cast(length(i)); + } + return num_pts; + } else { + return 0.0; + } } /** * \brief Return the volume, in indexing space, of region enclosed by - * this Box. This is identical to numPts() for CELL centered - * Box; otherwise, numPts() > volume(). + * this BoxND. This is identical to numPts() for CELL centered + * BoxND; otherwise, numPts() > volume(). */ [[nodiscard]] AMREX_GPU_HOST_DEVICE Long volume () const noexcept { - return ok() ? AMREX_D_TERM( static_cast(length(0)-btype[0]), - *static_cast(length(1)-btype[1]), - *static_cast(length(2)-btype[2])) - : Long(0); + if (ok()) { + auto num_pts = static_cast(length(0)-btype[0]); + for (int i = 1; i < dim; ++i) { + num_pts *= static_cast(length(i)-btype[i]); + } + return num_pts; + } else { + return Long(0); + } } /** * \brief Returns length of longest side. dir is modified to give - * direction with longest side: 0...SPACEDIM-1. Ignores type. + * direction with longest side: 0...dim-1. Ignores type. */ [[nodiscard]] AMREX_GPU_HOST_DEVICE int longside (int& dir) const noexcept { int maxlen = length(0); dir = 0; - for (int i = 1; i < AMREX_SPACEDIM; i++) + for (int i = 1; i < dim; i++) { if (length(i) > maxlen) { @@ -398,13 +421,13 @@ public: /** * \brief Returns length of shortest side. dir is modified to give - * direction with shortest side: 0...SPACEDIM-1. Ignores type. + * direction with shortest side: 0...dim-1. Ignores type. */ [[nodiscard]] AMREX_GPU_HOST_DEVICE int shortside (int& dir) const noexcept { int minlen = length(0); dir = 0; - for (int i = 1; i < AMREX_SPACEDIM; i++) + for (int i = 1; i < dim; i++) { if (length(i) < minlen) { @@ -428,56 +451,57 @@ public: * Is used in accessing FArrayBox. */ [[nodiscard]] AMREX_GPU_HOST_DEVICE - Long index (const IntVect& v) const noexcept; + Long index (const IntVectND& v) const noexcept; - //! Given the offset, compute IntVect + //! Given the offset, compute IntVectND [[nodiscard]] AMREX_GPU_HOST_DEVICE - IntVect atOffset (Long offset) const noexcept; + IntVectND atOffset (Long offset) const noexcept; + template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE GpuArray atOffset3d (Long offset) const noexcept; - //! Redefine the small end of the Box. + //! Redefine the small end of the BoxND. AMREX_GPU_HOST_DEVICE - Box& setSmall (const IntVect& sm) noexcept { smallend = sm; return *this; } + BoxND& setSmall (const IntVectND& sm) noexcept { smallend = sm; return *this; } - //! Redefine the small end of the Box. + //! Redefine the small end of the BoxND. AMREX_GPU_HOST_DEVICE - Box& setSmall (int dir, int sm_index) noexcept { smallend.setVal(dir,sm_index); return *this; } + BoxND& setSmall (int dir, int sm_index) noexcept { smallend.setVal(dir,sm_index); return *this; } - //! Redefine the big end of the Box. + //! Redefine the big end of the BoxND. AMREX_GPU_HOST_DEVICE - Box& setBig (const IntVect& bg) noexcept { bigend = bg; return *this; } + BoxND& setBig (const IntVectND& bg) noexcept { bigend = bg; return *this; } - //! Redefine the big end of the Box. + //! Redefine the big end of the BoxND. AMREX_GPU_HOST_DEVICE - Box& setBig (int dir, int bg_index) noexcept { bigend.setVal(dir,bg_index); return *this; } + BoxND& setBig (int dir, int bg_index) noexcept { bigend.setVal(dir,bg_index); return *this; } /** * \brief Set the entire range in a given direction, starting at * sm_index with length n_cells. NOTE: This will yield an - * illegal Box if n_cells <= 0. + * illegal BoxND if n_cells <= 0. */ AMREX_GPU_HOST_DEVICE - Box& setRange (int dir, + BoxND& setRange (int dir, int sm_index, int n_cells = 1) noexcept; //! Set indexing type AMREX_GPU_HOST_DEVICE - Box& setType (const IndexType& t) noexcept { btype = t; return *this; } + BoxND& setType (const IndexTypeND& t) noexcept { btype = t; return *this; } - //! Shift this Box nzones indexing positions in coordinate direction dir. + //! Shift this BoxND nzones indexing positions in coordinate direction dir. AMREX_GPU_HOST_DEVICE - Box& shift (int dir, int nzones) noexcept { smallend.shift(dir,nzones); bigend.shift(dir,nzones); return *this; } + BoxND& shift (int dir, int nzones) noexcept { smallend.shift(dir,nzones); bigend.shift(dir,nzones); return *this; } //! Equivalent to b.shift(0,iv[0]).shift(1,iv[1]) .... AMREX_GPU_HOST_DEVICE - Box& shift (const IntVect& iv) noexcept { smallend.shift(iv); bigend.shift(iv); return *this; } + BoxND& shift (const IntVectND& iv) noexcept { smallend.shift(iv); bigend.shift(iv); return *this; } /** - * \brief This member shifts the Box by "half" indices, thereby - * converting the Box from type CELL to NODE and visa-versa. + * \brief This member shifts the BoxND by "half" indices, thereby + * converting the BoxND from type CELL to NODE and visa-versa. * b.shiftHalf(0,1) shifts b to the right by 1/2 cells. * b.shiftHalf(1,-3) shifts b in the -j direction by 3/2 cells. * NOTE: If num_halfs is EVEN the shift is num_halfs/2 full @@ -485,64 +509,64 @@ public: * This is: b.shifthalf(4) == b.shift(2). */ AMREX_GPU_HOST_DEVICE - Box& shiftHalf (int dir, int num_halfs) noexcept; + BoxND& shiftHalf (int dir, int num_halfs) noexcept; //! Equivalent to b.shiftHalf(0,iv[0]).shiftHalf(1,iv[1]) ... AMREX_GPU_HOST_DEVICE - Box& shiftHalf (const IntVect& iv) noexcept; + BoxND& shiftHalf (const IntVectND& iv) noexcept; /** - * \brief Convert the Box from the current type into the - * argument type. This may change the Box coordinates: + * \brief Convert the BoxND from the current type into the + * argument type. This may change the BoxND coordinates: * type CELL -> NODE : increase coordinate by one on high end * type NODE -> CELL : reduce coordinate by one on high end * other type mappings make no change. */ AMREX_GPU_HOST_DEVICE - Box& convert (IndexType typ) noexcept; + BoxND& convert (IndexTypeND typ) noexcept; /** - * \brief Convert the Box from the current type into the - * argument type. This may change the Box coordinates: + * \brief Convert the BoxND from the current type into the + * argument type. This may change the BoxND coordinates: * type CELL -> NODE : increase coordinate by one on high end * type NODE -> CELL : reduce coordinate by one on high end * other type mappings make no change. */ AMREX_GPU_HOST_DEVICE - Box& convert (const IntVect& typ) noexcept; + BoxND& convert (const IntVectND& typ) noexcept; //! Convert to NODE type in all directions. AMREX_GPU_HOST_DEVICE - Box& surroundingNodes () noexcept; + BoxND& surroundingNodes () noexcept; //! Convert to NODE type in given direction. AMREX_GPU_HOST_DEVICE - Box& surroundingNodes (int dir) noexcept; + BoxND& surroundingNodes (int dir) noexcept; AMREX_GPU_HOST_DEVICE - Box& surroundingNodes (Direction d) noexcept { return surroundingNodes(static_cast(d)); } + BoxND& surroundingNodes (Direction d) noexcept { return surroundingNodes(static_cast(d)); } //! Convert to CELL type in all directions. AMREX_GPU_HOST_DEVICE - Box& enclosedCells () noexcept; + BoxND& enclosedCells () noexcept; //! Convert to CELL type in given direction. AMREX_GPU_HOST_DEVICE - Box& enclosedCells (int dir) noexcept; + BoxND& enclosedCells (int dir) noexcept; AMREX_GPU_HOST_DEVICE - Box& enclosedCells (Direction d) noexcept { return enclosedCells(static_cast(d)); } + BoxND& enclosedCells (Direction d) noexcept { return enclosedCells(static_cast(d)); } /** - * \brief Return Box that is intersection of this Box + * \brief Return BoxND that is intersection of this BoxND * and argument. The Boxes MUST be of same type. */ AMREX_GPU_HOST_DEVICE - Box operator& (const Box& rhs) const noexcept { Box lhs(*this); lhs &= rhs; return lhs; } + BoxND operator& (const BoxND& rhs) const noexcept { BoxND lhs(*this); lhs &= rhs; return lhs; } - //! Intersect this Box with its argument. The Boxes MUST be of the same type. + //! Intersect this BoxND with its argument. The Boxes MUST be of the same type. AMREX_GPU_HOST_DEVICE - Box& operator&= (const Box& rhs) noexcept + BoxND& operator&= (const BoxND& rhs) noexcept { BL_ASSERT(sameType(rhs)); smallend.max(rhs.smallend); @@ -551,12 +575,12 @@ public: } /** - * \brief Modify Box to that of the minimum Box containing both - * the original Box and the argument. + * \brief Modify BoxND to that of the minimum BoxND containing both + * the original BoxND and the argument. * Both Boxes must have identical type. */ AMREX_GPU_HOST_DEVICE - Box& minBox (const Box& b) noexcept { + BoxND& minBox (const BoxND& b) noexcept { // BoxArray may call this with not ok boxes. BL_ASSERT(b.ok() && ok()); BL_ASSERT(sameType(b)); smallend.min(b.smallend); @@ -564,82 +588,82 @@ public: return *this; } - //! Shift Box (relative) by given IntVect. + //! Shift BoxND (relative) by given IntVectND. AMREX_GPU_HOST_DEVICE - Box& operator+= (const IntVect& v) noexcept { smallend += v; bigend += v; return *this; } + BoxND& operator+= (const IntVectND& v) noexcept { smallend += v; bigend += v; return *this; } - //! Shift Box (relative) by given IntVect. + //! Shift BoxND (relative) by given IntVectND. AMREX_GPU_HOST_DEVICE - Box operator+ (const IntVect& v) const noexcept { Box r(*this); r += v; return r; } + BoxND operator+ (const IntVectND& v) const noexcept { BoxND r(*this); r += v; return r; } - //! Shift Box (relative) by given IntVect. + //! Shift BoxND (relative) by given IntVectND. AMREX_GPU_HOST_DEVICE - Box& operator-= (const IntVect& v) noexcept { smallend -= v; bigend -= v; return *this; } + BoxND& operator-= (const IntVectND& v) noexcept { smallend -= v; bigend -= v; return *this; } - //! Shift Box (relative) by given IntVect. + //! Shift BoxND (relative) by given IntVectND. AMREX_GPU_HOST_DEVICE - Box operator- (const IntVect& v) const noexcept { Box r(*this); r -= v; return r; } + BoxND operator- (const IntVectND& v) const noexcept { BoxND r(*this); r -= v; return r; } /** - * \brief Chop the Box at the chop_pnt in the dir direction - * returns one Box, modifies the object Box. - * The union of the two is the original Box. - * The modified Box is the low end, the returned Box + * \brief Chop the BoxND at the chop_pnt in the dir direction + * returns one BoxND, modifies the object BoxND. + * The union of the two is the original BoxND. + * The modified BoxND is the low end, the returned BoxND * is the high end. If type(dir) = CELL, the Boxes are disjoint - * with the chop_pnt included in the high end (new Box). - * It is an ERROR if chop_pnt is the low end of the orig Box. + * with the chop_pnt included in the high end (new BoxND). + * It is an ERROR if chop_pnt is the low end of the orig BoxND. * If type(dir) = NODE, the chop_pnt is included in both Boxes * but is the only point in common. It is also an error if the - * chop_pnt is an end node of the Box. + * chop_pnt is an end node of the BoxND. */ AMREX_GPU_HOST_DEVICE - Box chop (int dir, int chop_pnt) noexcept; + BoxND chop (int dir, int chop_pnt) noexcept; /* - * \brief Grow Box in all directions by given amount. - * NOTE: n_cell negative shrinks the Box by that number of cells. + * \brief Grow BoxND in all directions by given amount. + * NOTE: n_cell negative shrinks the BoxND by that number of cells. */ AMREX_GPU_HOST_DEVICE - Box& grow (int i) noexcept { smallend.diagShift(-i); bigend.diagShift(i); return *this; } + BoxND& grow (int i) noexcept { smallend.diagShift(-i); bigend.diagShift(i); return *this; } - //! Grow Box in each direction by specified amount. + //! Grow BoxND in each direction by specified amount. AMREX_GPU_HOST_DEVICE - Box& grow (const IntVect& v) noexcept { smallend -= v; bigend += v; return *this;} + BoxND& grow (const IntVectND& v) noexcept { smallend -= v; bigend += v; return *this;} /** - * \brief Grow the Box on the low and high end by n_cell cells + * \brief Grow the BoxND on the low and high end by n_cell cells * in direction idir. */ AMREX_GPU_HOST_DEVICE - Box& grow (int idir, int n_cell) noexcept { smallend.shift(idir, -n_cell); bigend.shift(idir, n_cell); return *this; } + BoxND& grow (int idir, int n_cell) noexcept { smallend.shift(idir, -n_cell); bigend.shift(idir, n_cell); return *this; } AMREX_GPU_HOST_DEVICE - Box& grow (Direction d, int n_cell) noexcept { return grow(static_cast(d), n_cell); } + BoxND& grow (Direction d, int n_cell) noexcept { return grow(static_cast(d), n_cell); } /** - * \brief Grow the Box on the low end by n_cell cells in direction idir. - * NOTE: n_cell negative shrinks the Box by that number of cells. + * \brief Grow the BoxND on the low end by n_cell cells in direction idir. + * NOTE: n_cell negative shrinks the BoxND by that number of cells. */ AMREX_GPU_HOST_DEVICE - Box& growLo (int idir, int n_cell = 1) noexcept { smallend.shift(idir, -n_cell); return *this; } + BoxND& growLo (int idir, int n_cell = 1) noexcept { smallend.shift(idir, -n_cell); return *this; } AMREX_GPU_HOST_DEVICE - Box& growLo (Direction d, int n_cell = 1) noexcept { return growLo(static_cast(d), n_cell); } + BoxND& growLo (Direction d, int n_cell = 1) noexcept { return growLo(static_cast(d), n_cell); } /** - * \brief Grow the Box on the high end by n_cell cells in - * direction idir. NOTE: n_cell negative shrinks the Box by that + * \brief Grow the BoxND on the high end by n_cell cells in + * direction idir. NOTE: n_cell negative shrinks the BoxND by that * number of cells. */ AMREX_GPU_HOST_DEVICE - Box& growHi (int idir, int n_cell = 1) noexcept { bigend.shift(idir,n_cell); return *this; } + BoxND& growHi (int idir, int n_cell = 1) noexcept { bigend.shift(idir,n_cell); return *this; } AMREX_GPU_HOST_DEVICE - Box& growHi (Direction d, int n_cell = 1) noexcept { return growHi(static_cast(d), n_cell); } + BoxND& growHi (Direction d, int n_cell = 1) noexcept { return growHi(static_cast(d), n_cell); } //! Grow in the direction of the given face. AMREX_GPU_HOST_DEVICE - Box& grow (Orientation face, int n_cell = 1) noexcept { + BoxND& grow (Orientation face, int n_cell = 1) noexcept { int idir = face.coordDir(); if (face.isLow()) { smallend.shift(idir, -n_cell); @@ -650,80 +674,80 @@ public: } /** - * \brief Refine Box by given (positive) refinement ratio. + * \brief Refine BoxND by given (positive) refinement ratio. * NOTE: if type(dir) = CELL centered: lo <- lo*ratio and * hi <- (hi+1)*ratio - 1. * NOTE: if type(dir) = NODE centered: lo <- lo*ratio and * hi <- hi*ratio. */ AMREX_GPU_HOST_DEVICE - Box& refine (int ref_ratio) noexcept { - return this->refine(IntVect(ref_ratio)); + BoxND& refine (int ref_ratio) noexcept { + return this->refine(IntVectND(ref_ratio)); } /* - * \brief Refine Box by given (positive) refinement ratio. + * \brief Refine BoxND by given (positive) refinement ratio. * NOTE: if type(dir) = CELL centered: lo <- lo*ratio and * hi <- (hi+1)*ratio - 1. * NOTE: if type(dir) = NODE centered: lo <- lo*ratio and * hi <- hi*ratio. */ AMREX_GPU_HOST_DEVICE - Box& refine (const IntVect& ref_ratio) noexcept; + BoxND& refine (const IntVectND& ref_ratio) noexcept; /** - * \brief Coarsen Box by given (positive) refinement ratio. + * \brief Coarsen BoxND by given (positive) refinement ratio. * NOTE: if type(dir) = CELL centered: lo <- lo/ratio and * hi <- hi/ratio. * NOTE: if type(dir) = NODE centered: lo <- lo/ratio and * hi <- hi/ratio + ((hi%ratio)==0 ? 0 : 1). - * That is, refinement of coarsened Box must contain - * the original Box. + * That is, refinement of coarsened BoxND must contain + * the original BoxND. */ AMREX_GPU_HOST_DEVICE - Box& coarsen (int ref_ratio) noexcept { - return this->coarsen(IntVect(ref_ratio)); + BoxND& coarsen (int ref_ratio) noexcept { + return this->coarsen(IntVectND(ref_ratio)); } /** - * \brief Coarsen Box by given (positive) refinement ratio. + * \brief Coarsen BoxND by given (positive) refinement ratio. * NOTE: if type(dir) = CELL centered: lo <- lo/ratio and * hi <- hi/ratio. * NOTE: if type(dir) = NODE centered: lo <- lo/ratio and * hi <- hi/ratio + ((hi%ratio)==0 ? 0 : 1). - * That is, refinement of coarsened Box must contain - * the original Box. + * That is, refinement of coarsened BoxND must contain + * the original BoxND. */ AMREX_GPU_HOST_DEVICE - Box& coarsen (const IntVect& ref_ratio) noexcept; + BoxND& coarsen (const IntVectND& ref_ratio) noexcept; /** * \brief Step through the rectangle. It is a runtime error to give * a point not inside rectangle. Iteration may not be efficient. */ AMREX_GPU_HOST_DEVICE - void next (IntVect &) const noexcept; + void next (IntVectND &) const noexcept; /** * \brief This static member function returns a constant reference to - * an object of type Box representing the unit box in - * AMREX_SPACEDIM-dimensional space. + * an object of type BoxND representing the unit BoxND in + * dim-dimensional space. */ AMREX_GPU_HOST_DEVICE - static Box TheUnitBox () noexcept { - return Box(IntVect::TheZeroVector(),IntVect::TheZeroVector()); + static BoxND TheUnitBox () noexcept { + return BoxND(IntVectND::TheZeroVector(),IntVectND::TheZeroVector()); } [[nodiscard]] AMREX_GPU_HOST_DEVICE bool isSquare() const noexcept; [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool coarsenable(const IntVect& refrat, const IntVect& min_width) const noexcept + bool coarsenable(const IntVectND& refrat, const IntVectND& min_width) const noexcept { if (!size().allGE(refrat*min_width)) { return false; } else { - Box testBox = *this; + BoxND testBox = *this; testBox.coarsen(refrat); testBox.refine (refrat); return (*this == testBox); @@ -732,19 +756,19 @@ public: [[nodiscard]] AMREX_GPU_HOST_DEVICE bool coarsenable(int refrat, int min_width=1) const noexcept { - return coarsenable(IntVect(refrat), IntVect(min_width)); + return coarsenable(IntVectND(refrat), IntVectND(min_width)); } [[nodiscard]] AMREX_GPU_HOST_DEVICE - bool coarsenable(const IntVect& refrat, int min_width=1) const noexcept + bool coarsenable(const IntVectND& refrat, int min_width=1) const noexcept { - return coarsenable(refrat, IntVect(min_width)); + return coarsenable(refrat, IntVectND(min_width)); } AMREX_GPU_HOST_DEVICE void normalize () noexcept { - for (int idim=0; idim < AMREX_SPACEDIM; ++idim) { + for (int idim=0; idim < dim; ++idim) { if (this->length(idim) == 0) { this->growHi(idim,1); } @@ -752,37 +776,80 @@ public: } AMREX_GPU_HOST_DEVICE - Box& makeSlab (int direction, int slab_index) noexcept + BoxND& makeSlab (int direction, int slab_index) noexcept { smallend[direction] = slab_index; bigend[direction] = slab_index; return *this; } - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Dim3 lbound (Box const& box) noexcept; - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Dim3 ubound (Box const& box) noexcept; - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Dim3 begin (Box const& box) noexcept; - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Dim3 end (Box const& box) noexcept; - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Dim3 length (Box const& box) noexcept; - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Dim3 max_lbound (Box const&, Box const&) noexcept; - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Dim3 max_lbound (Box const&, Dim3 const&) noexcept; - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Dim3 min_ubound (Box const&, Box const&) noexcept; - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Dim3 min_ubound (Box const&, Dim3 const&) noexcept; - AMREX_GPU_HOST_DEVICE friend AMREX_FORCE_INLINE Box minBox (Box const&, Box const&, IndexType) noexcept; + [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + static constexpr std::size_t ndims () noexcept { + return static_cast(dim); + } + + [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + static constexpr int indims () noexcept { + return dim; + } + + /** + * \brief Returns a new BoxND of dimension new_dim and + * assigns the first new_dim dimension of this BoxND to it. + */ + template + [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + BoxND shrink () const noexcept { + static_assert(new_dim <= dim); + auto lo = smallend.template shrink(); + auto hi = bigend.template shrink(); + auto typ = btype.template shrink(); + return BoxND(lo, hi, typ); + } + + /** + * \brief Returns a new BoxND of size new_dim and + * assigns all values of this BoxND to it and + * (small=0, big=0, typ=CELL) to the remaining elements. + */ + template + [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + BoxND expand () const noexcept { + static_assert(new_dim >= dim); + auto lo = smallend.template expand(0); + auto hi = bigend.template expand(0); + auto typ = btype.template expand(IndexType::CellIndex::CELL); + return BoxND(lo, hi, typ); + } + + /** + * \brief Returns a new BoxND of size new_dim + * by either shrinking or expanding this BoxND + */ + template + [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + BoxND resize () const noexcept { + if constexpr (new_dim > dim) { + return expand(); + } else { + return shrink(); + } + } private: - IntVect smallend; - IntVect bigend; - IndexType btype; + IntVectND smallend; + IntVectND bigend; + IndexTypeND btype; }; +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box& -Box::refine (const IntVect& ref_ratio) noexcept +BoxND& +BoxND::refine (const IntVectND& ref_ratio) noexcept { if (ref_ratio != 1) { - IntVect shft(1); + IntVectND shft(1); shft -= btype.ixType(); smallend *= ref_ratio; bigend += shft; @@ -792,10 +859,11 @@ Box::refine (const IntVect& ref_ratio) noexcept return *this; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box& -Box::coarsen (const IntVect& ref_ratio) noexcept +BoxND& +BoxND::coarsen (const IntVectND& ref_ratio) noexcept { if (ref_ratio != 1) { @@ -803,8 +871,8 @@ Box::coarsen (const IntVect& ref_ratio) noexcept if (btype.any()) { - IntVect off(0); - for (int dir = 0; dir < AMREX_SPACEDIM; dir++) + IntVectND off(0); + for (int dir = 0; dir < dim; dir++) { if (btype[dir]) { if (bigend[dir]%ref_ratio[dir]) { @@ -824,38 +892,41 @@ Box::coarsen (const IntVect& ref_ratio) noexcept return *this; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box& -Box::convert (const IntVect& typ) noexcept +BoxND& +BoxND::convert (const IntVectND& typ) noexcept { BL_ASSERT(typ.allGE(0) && typ.allLE(1)); - IntVect shft(typ - btype.ixType()); + IntVectND shft(typ - btype.ixType()); bigend += shft; - btype = IndexType(typ); + btype = IndexTypeND(typ); return *this; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box& -Box::convert (IndexType t) noexcept +BoxND& +BoxND::convert (IndexTypeND t) noexcept { - for (int dir = 0; dir < AMREX_SPACEDIM; dir++) + for (int dir = 0; dir < dim; dir++) { const auto typ = t[dir]; const auto bitval = btype[dir]; const int off = typ - bitval; bigend.shift(dir,off); - btype.setType(dir, (IndexType::CellIndex) typ); + btype.setType(dir, static_cast(typ)); } return *this; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box& -Box::surroundingNodes (int dir) noexcept +BoxND& +BoxND::surroundingNodes (int dir) noexcept { if (!(btype[dir])) { @@ -868,12 +939,13 @@ Box::surroundingNodes (int dir) noexcept return *this; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box& -Box::surroundingNodes () noexcept +BoxND& +BoxND::surroundingNodes () noexcept { - for (int i = 0; i < AMREX_SPACEDIM; ++i) { + for (int i = 0; i < dim; ++i) { if ((btype[i] == 0)) { bigend.shift(i,1); } @@ -882,10 +954,11 @@ Box::surroundingNodes () noexcept return *this; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box& -Box::enclosedCells (int dir) noexcept +BoxND& +BoxND::enclosedCells (int dir) noexcept { if (btype[dir]) { @@ -898,12 +971,13 @@ Box::enclosedCells (int dir) noexcept return *this; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box& -Box::enclosedCells () noexcept +BoxND& +BoxND::enclosedCells () noexcept { - for (int i = 0 ; i < AMREX_SPACEDIM; ++i) { + for (int i = 0 ; i < dim; ++i) { if (btype[i]) { bigend.shift(i,-1); } @@ -912,78 +986,64 @@ Box::enclosedCells () noexcept return *this; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Long -Box::index (const IntVect& v) const noexcept -{ - Long result = v[0]-smallend[0]; -#if AMREX_SPACEDIM==2 - result += length(0)*Long(v[1]-smallend[1]); -#elif AMREX_SPACEDIM==3 - result += length(0)*((v[1]-smallend[1]) - +Long(v[2]-smallend[2])*length(1)); -#endif +BoxND::index (const IntVectND& v) const noexcept +{ + IntVectND vz = v - smallend; + Long result = vz[0]; + Long mult = length(0); + for (int i = 1 ; i < dim; ++i) { + result += mult * vz[i]; + mult *= length(i); + } return result; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -IntVect -Box::atOffset (Long offset) const noexcept -{ -#if (AMREX_SPACEDIM == 1) - return IntVect{static_cast(offset+smallend[0])}; -#elif (AMREX_SPACEDIM == 2) - int xlen = bigend[0]-smallend[0]+1; - Long j = offset / xlen; - Long i = offset - j*xlen; - return IntVect{static_cast(i+smallend[0]), - static_cast(j+smallend[1])}; -#elif (AMREX_SPACEDIM == 3) - int xlen = bigend[0]-smallend[0]+1; - int ylen = bigend[1]-smallend[1]+1; - Long k = offset / (xlen*ylen); - Long j = (offset - k*(xlen*ylen)) / xlen; - Long i = (offset - k*(xlen*ylen)) - j*xlen; - return IntVect{static_cast(i+smallend[0]), - static_cast(j+smallend[1]), - static_cast(k+smallend[2])}; -#endif +IntVectND +BoxND::atOffset (Long offset) const noexcept +{ + IntVectND result = smallend; + + if constexpr (dim > 1) { + GpuArray mult{}; + mult[0] = length(0); + for (int i = 1 ; i < dim-1; ++i) { + mult[i] = mult[i-1] * length(i); + } + for (int i = dim-1 ; i > 0; --i) { + Long idx = offset / mult[i-1]; + offset -= idx * mult[i-1]; + result[i] += static_cast(idx); + } + } + + result[0] += static_cast(offset); + + return result; } +template +template > AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE GpuArray -Box::atOffset3d (Long offset) const noexcept -{ -#if (AMREX_SPACEDIM == 1) - return {{static_cast(offset+smallend[0]), - static_cast(0), - static_cast(0)}}; -#elif (AMREX_SPACEDIM == 2) - int xlen = bigend[0]-smallend[0]+1; - Long j = offset / xlen; - Long i = offset - j*xlen; - return {{static_cast(i+smallend[0]), - static_cast(j+smallend[1]), - static_cast(0)}}; -#elif (AMREX_SPACEDIM == 3) - int xlen = bigend[0]-smallend[0]+1; - int ylen = bigend[1]-smallend[1]+1; - Long k = offset / (xlen*ylen); - Long j = (offset - k*(xlen*ylen)) / xlen; - Long i = (offset - k*(xlen*ylen)) - j*xlen; - return {{static_cast(i+smallend[0]), - static_cast(j+smallend[1]), - static_cast(k+smallend[2])}}; -#endif +BoxND::atOffset3d (Long offset) const noexcept +{ + Dim3 iv3d = atOffset(offset).dim3(0); + return {{iv3d.x, iv3d.y, iv3d.z}}; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box& -Box::setRange (int dir, +BoxND& +BoxND::setRange (int dir, int sm_index, int n_cells) noexcept { @@ -992,93 +1052,92 @@ Box::setRange (int dir, return *this; } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void -Box::next (IntVect& p) const noexcept // NOLINT(readability-convert-member-functions-to-static) +BoxND::next (IntVectND& p) const noexcept // NOLINT(readability-convert-member-functions-to-static) { BL_ASSERT(contains(p)); ++p[0]; -#if (AMREX_SPACEDIM >= 2) - if (p[0] > bigend[0]) - { - p[0] = smallend[0]; - ++p[1]; -#if (AMREX_SPACEDIM == 3) - if (p[1] > bigend[1]) - { - p[1] = smallend[1]; - ++p[2]; + for (int i = 0 ; i < dim-1; ++i) { + if (p[i] > bigend[i]) { + p[i] = smallend[i]; + ++p[i+1]; + } else { + break; } -#endif } -#endif } +template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool -Box::isSquare () const noexcept // NOLINT(readability-convert-member-functions-to-static) -{ -#if AMREX_SPACEDIM==1 - return false; // can't build a square in 1-D -#elif AMREX_SPACEDIM==2 - const IntVect& sz = this->size(); - return (sz[0] == sz[1]); -#elif AMREX_SPACEDIM==3 - const IntVect& sz = this->size(); - return (sz[0] == sz[1] && (sz[1] == sz[2])); -#endif +BoxND::isSquare () const noexcept // NOLINT(readability-convert-member-functions-to-static) +{ + if constexpr (dim == 1) { + return false; // can't build a square in 1-D + } else { + bool is_square = true; + const IntVectND& sz = this->size(); + for (int i = 0 ; i < dim-1; ++i) { + is_square = is_square && (sz[i] == sz[i+1]); + } + return is_square; + } } // -// Modified Box is low end, returned Box is high end. +// Modified BoxND is low end, returned BoxND is high end. // If CELL: chop_pnt included in high end. // If NODE: chop_pnt included in both Boxes. // +template AMREX_GPU_HOST_DEVICE inline -Box -Box::chop (int dir, int chop_pnt) noexcept +BoxND +BoxND::chop (int dir, int chop_pnt) noexcept { // - // Define new high end Box including chop_pnt. + // Define new high end BoxND including chop_pnt. // - IntVect sm(smallend); - IntVect bg(bigend); + IntVectND sm(smallend); + IntVectND bg(bigend); sm.setVal(dir,chop_pnt); if (btype[dir]) { // - // NODE centered Box. + // NODE centered BoxND. // BL_ASSERT(chop_pnt > smallend[dir] && chop_pnt < bigend[dir]); // - // Shrink original Box to just contain chop_pnt. + // Shrink original BoxND to just contain chop_pnt. // bigend.setVal(dir,chop_pnt); } else { // - // CELL centered Box. + // CELL centered BoxND. // BL_ASSERT(chop_pnt > smallend[dir] && chop_pnt <= bigend[dir]); // - // Shrink original Box to one below chop_pnt. + // Shrink original BoxND to one below chop_pnt. // bigend.setVal(dir,chop_pnt-1); } - return Box(sm,bg,btype); + return BoxND(sm,bg,btype); } +template AMREX_GPU_HOST_DEVICE inline -Box& -Box::shiftHalf (int dir, int num_halfs) noexcept +BoxND& +BoxND::shiftHalf (int dir, int num_halfs) noexcept { const int nbit = (num_halfs<0 ? -num_halfs : num_halfs)%2; int nshift = num_halfs/2; @@ -1099,12 +1158,13 @@ Box::shiftHalf (int dir, int num_halfs) noexcept return *this; } +template AMREX_GPU_HOST_DEVICE inline -Box& -Box::shiftHalf (const IntVect& iv) noexcept +BoxND& +BoxND::shiftHalf (const IntVectND& iv) noexcept { - for (int i = 0; i < AMREX_SPACEDIM; i++) { + for (int i = 0; i < dim; i++) { shiftHalf(i,iv[i]); } return *this; @@ -1140,308 +1200,332 @@ public: void AllGatherBoxes (Vector& bxs, int n_extra_reserve=0); /** - * \brief Grow Box in all directions by given amount. + * \brief Grow BoxND in all directions by given amount. - * NOTE: n_cell negative shrinks the Box by that number of cells. + * NOTE: n_cell negative shrinks the BoxND by that number of cells. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box grow (const Box& b, int i) noexcept +BoxND grow (const BoxND& b, int i) noexcept { - Box result = b; + BoxND result = b; result.grow(i); return result; } - //! Grow Box in each direction by specified amount. + //! Grow BoxND in each direction by specified amount. +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box grow (const Box& b, const IntVect& v) noexcept +BoxND grow (const BoxND& b, const IntVectND& v) noexcept { - Box result = b; + BoxND result = b; result.grow(v); return result; } - //! Grow Box in direction idir be n_cell cells + //! Grow BoxND in direction idir be n_cell cells +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box grow (const Box& b, int idir, int n_cell) noexcept +BoxND grow (const BoxND& b, int idir, int n_cell) noexcept { - Box result = b; + BoxND result = b; result.grow(idir, n_cell); return result; } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box grow (const Box& b, Direction d, int n_cell) noexcept +BoxND grow (const BoxND& b, Direction d, int n_cell) noexcept { return grow(b, static_cast(d), n_cell); } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box growLo (const Box& b, int idir, int n_cell) noexcept +BoxND growLo (const BoxND& b, int idir, int n_cell) noexcept { - Box result = b; + BoxND result = b; result.growLo(idir, n_cell); return result; } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box growLo (const Box& b, Direction d, int n_cell) noexcept +BoxND growLo (const BoxND& b, Direction d, int n_cell) noexcept { return growLo(b, static_cast(d), n_cell); } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box growHi (const Box& b, int idir, int n_cell) noexcept +BoxND growHi (const BoxND& b, int idir, int n_cell) noexcept { - Box result = b; + BoxND result = b; result.growHi(idir, n_cell); return result; } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box growHi (const Box& b, Direction d, int n_cell) noexcept +BoxND growHi (const BoxND& b, Direction d, int n_cell) noexcept { return growHi(b, static_cast(d), n_cell); } /** - * \brief Coarsen Box by given (positive) refinement ratio. + * \brief Coarsen BoxND by given (positive) refinement ratio. * NOTE: if type(dir) = CELL centered: lo <- lo/ratio and * hi <- hi/ratio. * NOTE: if type(dir) = NODE centered: lo <- lo/ratio and * hi <- hi/ratio + ((hi%ratio)==0 ? 0 : 1). - * That is, refinement of coarsened Box must contain - * the original Box. + * That is, refinement of coarsened BoxND must contain + * the original BoxND. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box coarsen (const Box& b, int ref_ratio) noexcept +BoxND coarsen (const BoxND& b, int ref_ratio) noexcept { - Box result = b; - result.coarsen(IntVect(ref_ratio)); + BoxND result = b; + result.coarsen(IntVectND(ref_ratio)); return result; } /** - * \brief Coarsen Box by given (positive) refinement ratio. + * \brief Coarsen BoxND by given (positive) refinement ratio. * NOTE: if type(dir) = CELL centered: lo <- lo/ratio and * hi <- hi/ratio. * NOTE: if type(dir) = NODE centered: lo <- lo/ratio and * hi <- hi/ratio + ((hi%ratio)==0 ? 0 : 1). - * That is, refinement of coarsened Box must contain - * the original Box. + * That is, refinement of coarsened BoxND must contain + * the original BoxND. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box coarsen (const Box& b, const IntVect& ref_ratio) noexcept +BoxND coarsen (const BoxND& b, const IntVectND& ref_ratio) noexcept { - Box result = b; + BoxND result = b; result.coarsen(ref_ratio); return result; } /** - * Refine Box by given (positive) refinement ratio. + * Refine BoxND by given (positive) refinement ratio. * NOTE: if type(dir) = CELL centered: lo <- lo*ratio and * hi <- (hi+1)*ratio - 1. * NOTE: if type(dir) = NODE centered: lo <- lo*ratio and * hi <- hi*ratio. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box refine (const Box& b, int ref_ratio) noexcept +BoxND refine (const BoxND& b, int ref_ratio) noexcept { - Box result = b; - result.refine(IntVect(ref_ratio)); + BoxND result = b; + result.refine(IntVectND(ref_ratio)); return result; } /** - * \brief Refine Box by given (positive) refinement ratio. + * \brief Refine BoxND by given (positive) refinement ratio. * NOTE: if type(dir) = CELL centered: lo <- lo*ratio and * hi <- (hi+1)*ratio - 1. * NOTE: if type(dir) = NODE centered: lo <- lo*ratio and * hi <- hi*ratio. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box refine (const Box& b, const IntVect& ref_ratio) noexcept +BoxND refine (const BoxND& b, const IntVectND& ref_ratio) noexcept { - Box result = b; + BoxND result = b; result.refine(ref_ratio); return result; } - //! Return a Box with indices shifted by nzones in dir direction. + //! Return a BoxND with indices shifted by nzones in dir direction. +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box shift (const Box& b, int dir, int nzones) noexcept +BoxND shift (const BoxND& b, int dir, int nzones) noexcept { - Box result = b; + BoxND result = b; result.shift(dir, nzones); return result; } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box shift (const Box& b, const IntVect& nzones) noexcept +BoxND shift (const BoxND& b, const IntVectND& nzones) noexcept { - Box result = b; + BoxND result = b; result.shift(nzones); return result; } /** - * \brief Returns a Box with NODE based coordinates in direction dir - * that encloses Box b. NOTE: equivalent to b.convert(dir,NODE) + * \brief Returns a BoxND with NODE based coordinates in direction dir + * that encloses BoxND b. NOTE: equivalent to b.convert(dir,NODE) * NOTE: error if b.type(dir) == NODE. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box surroundingNodes (const Box& b, int dir) noexcept +BoxND surroundingNodes (const BoxND& b, int dir) noexcept { - Box bx(b); + BoxND bx(b); bx.surroundingNodes(dir); return bx; } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box surroundingNodes (const Box& b, Direction d) noexcept +BoxND surroundingNodes (const BoxND& b, Direction d) noexcept { return surroundingNodes(b, static_cast(d)); } /** - * \brief Returns a Box with NODE based coordinates in all - * directions that encloses Box b. + * \brief Returns a BoxND with NODE based coordinates in all + * directions that encloses BoxND b. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box surroundingNodes (const Box& b) noexcept +BoxND surroundingNodes (const BoxND& b) noexcept { - Box bx(b); + BoxND bx(b); bx.surroundingNodes(); return bx; } - //! Returns a Box with different type + //! Returns a BoxND with different type +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box convert (const Box& b, const IntVect& typ) noexcept +BoxND convert (const BoxND& b, const IntVectND& typ) noexcept { - Box bx(b); + BoxND bx(b); bx.convert(typ); return bx; } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box convert (const Box& b, const IndexType& typ) noexcept +BoxND convert (const BoxND& b, const IndexTypeND& typ) noexcept { - Box bx(b); + BoxND bx(b); bx.convert(typ); return bx; } /** - * \brief Returns a Box with CELL based coordinates in + * \brief Returns a BoxND with CELL based coordinates in * direction dir that is enclosed by b. * NOTE: equivalent to b.convert(dir,CELL) * NOTE: error if b.type(dir) == CELL. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box enclosedCells (const Box& b, int dir) noexcept +BoxND enclosedCells (const BoxND& b, int dir) noexcept { - Box bx(b); + BoxND bx(b); bx.enclosedCells(dir); return bx; } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box enclosedCells (const Box& b, Direction d) noexcept +BoxND enclosedCells (const BoxND& b, Direction d) noexcept { return enclosedCells(b, static_cast(d)); } /** - * \brief Returns a Box with CELL based coordinates in all + * \brief Returns a BoxND with CELL based coordinates in all * directions that is enclosed by b. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box enclosedCells (const Box& b) noexcept +BoxND enclosedCells (const BoxND& b) noexcept { - Box bx(b); + BoxND bx(b); bx.enclosedCells(); return bx; } /** - * \brief Returns the edge-centered Box (in direction dir) defining - * the low side of Box b. + * \brief Returns the edge-centered BoxND (in direction dir) defining + * the low side of BoxND b. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box bdryLo (const Box& b, int dir, int len=1) noexcept +BoxND bdryLo (const BoxND& b, int dir, int len=1) noexcept { - IntVect low(b.smallEnd()); - IntVect hi(b.bigEnd()); + IntVectND low(b.smallEnd()); + IntVectND hi(b.bigEnd()); int sm = low[dir]; low.setVal(dir,sm-len+1); hi.setVal(dir,sm); // // set dir'th bit to 1 = IndexType::NODE. // - IndexType typ(b.ixType()); + IndexTypeND typ(b.ixType()); typ.set(dir); - return Box(low,hi,typ); + return BoxND(low,hi,typ); } /** - * \brief Returns the edge-centered Box (in direction dir) defining - * the high side of Box b. + * \brief Returns the edge-centered BoxND (in direction dir) defining + * the high side of BoxND b. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box bdryHi (const Box& b, int dir, int len=1) noexcept +BoxND bdryHi (const BoxND& b, int dir, int len=1) noexcept { - IntVect low(b.smallEnd()); - IntVect hi(b.bigEnd()); + IntVectND low(b.smallEnd()); + IntVectND hi(b.bigEnd()); auto const bitval = b.type()[dir]; int bg = hi[dir] + 1 - bitval%2; low.setVal(dir,bg); @@ -1449,23 +1533,24 @@ Box bdryHi (const Box& b, int dir, int len=1) noexcept // // Set dir'th bit to 1 = IndexType::NODE. // - IndexType typ(b.ixType()); + IndexTypeND typ(b.ixType()); typ.set(dir); - return Box(low,hi,typ); + return BoxND(low,hi,typ); } /** * \brief Similar to bdryLo and bdryHi except that it operates on the * given face of box b. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box bdryNode (const Box& b, Orientation face, int len=1) noexcept +BoxND bdryNode (const BoxND& b, Orientation face, int len=1) noexcept { int dir = face.coordDir(); - IntVect low(b.smallEnd()); - IntVect hi(b.bigEnd()); + IntVectND low(b.smallEnd()); + IntVectND hi(b.bigEnd()); if (face.isLow()) { int sm = low[dir]; @@ -1482,51 +1567,53 @@ Box bdryNode (const Box& b, Orientation face, int len=1) noexcept // // Set dir'th bit to 1 = IndexType::NODE. // - IndexType typ(b.ixType()); + IndexTypeND typ(b.ixType()); typ.set(dir); - return Box(low,hi,typ); + return BoxND(low,hi,typ); } /** - * \brief Returns the cell centered Box of length len adjacent + * \brief Returns the cell centered BoxND of length len adjacent * to b on the low end along the coordinate direction dir. - * The return Box is identical to b in the other directions. - * The return Box and b have an empty intersection. + * The return BoxND is identical to b in the other directions. + * The return BoxND and b have an empty intersection. * NOTE: len >= 1 - * NOTE: Box retval = b.adjCellLo(b,dir,len) + * NOTE: BoxND retval = b.adjCellLo(b,dir,len) * is equivalent to the following set of operations: - * Box retval(b); - * retval.convert(dir,Box::CELL); + * BoxND retval(b); + * retval.convert(dir,BoxND::CELL); * retval.setrange(dir,retval.smallEnd(dir)-len,len); */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box adjCellLo (const Box& b, int dir, int len=1) noexcept +BoxND adjCellLo (const BoxND& b, int dir, int len=1) noexcept { BL_ASSERT(len > 0); - IntVect low(b.smallEnd()); - IntVect hi(b.bigEnd()); + IntVectND low(b.smallEnd()); + IntVectND hi(b.bigEnd()); int sm = low[dir]; low.setVal(dir,sm - len); hi.setVal(dir,sm - 1); // // Set dir'th bit to 0 = IndexType::CELL. // - IndexType typ(b.ixType()); + IndexTypeND typ(b.ixType()); typ.unset(dir); - return Box(low,hi,typ); + return BoxND(low,hi,typ); } - //! Similar to adjCellLo but builds an adjacent Box on the high end. + //! Similar to adjCellLo but builds an adjacent BoxND on the high end. +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box adjCellHi (const Box& b, int dir, int len=1) noexcept +BoxND adjCellHi (const BoxND& b, int dir, int len=1) noexcept { BL_ASSERT(len > 0); - IntVect low(b.smallEnd()); - IntVect hi(b.bigEnd()); + IntVectND low(b.smallEnd()); + IntVectND hi(b.bigEnd()); int bitval = b.type()[dir]; int bg = hi[dir] + 1 - bitval%2; low.setVal(dir,bg); @@ -1534,20 +1621,21 @@ Box adjCellHi (const Box& b, int dir, int len=1) noexcept // // Set dir'th bit to 0 = IndexType::CELL. // - IndexType typ(b.ixType()); + IndexTypeND typ(b.ixType()); typ.unset(dir); - return Box(low,hi,typ); + return BoxND(low,hi,typ); } //! Similar to adjCellLo and adjCellHi; operates on given face. +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box adjCell (const Box& b, Orientation face, int len=1) noexcept +BoxND adjCell (const BoxND& b, Orientation face, int len=1) noexcept { BL_ASSERT(len > 0); - IntVect low(b.smallEnd()); - IntVect hi(b.bigEnd()); + IntVectND low(b.smallEnd()); + IntVectND hi(b.bigEnd()); int dir = face.coordDir(); if (face.isLow()) { @@ -1565,225 +1653,310 @@ Box adjCell (const Box& b, Orientation face, int len=1) noexcept // // Set dir'th bit to 0 = IndexType::CELL. // - IndexType typ(b.ixType()); + IndexTypeND typ(b.ixType()); typ.unset(dir); - return Box(low,hi,typ); + return BoxND(low,hi,typ); } /** - * \brief Modify Box to that of the minimum Box containing both - * the original Box and the argument. - * Both Boxes must have identical type. + * \brief Modify BoxND to that of the minimum BoxND containing both + * the original BoxND and the argument. + * Both BoxNDes must have identical type. */ +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box minBox (const Box& b1, const Box& b2) noexcept +BoxND minBox (const BoxND& b1, const BoxND& b2) noexcept { - Box result = b1; + BoxND result = b1; result.minBox(b2); return result; } - //! Write an ASCII representation to the ostream. -std::ostream& operator<< (std::ostream& os, const Box& bx); +namespace detail { + std::ostream& box_write (std::ostream& os, const int * smallend, const int * bigend, + const int * type, int dim); + std::istream& box_read (std::istream& is, int * smallend, int * bigend, int * type, int dim); + + template + AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr + auto BoxSplit_imp (std::index_sequence, + const T& lo, const T& hi, const U& typ) noexcept { + return makeTuple(BoxND(get(lo), get(hi), get(typ))...); + } +} + +//! Write an ASCII representation to the ostream. +template +std::ostream& operator<< (std::ostream& os, const BoxND& bx) +{ + IntVectND type = bx.type(); + return detail::box_write(os, bx.smallEnd().begin(), bx.bigEnd().begin(), type.begin(), dim); +} + +//! Read from istream. +template +std::istream& operator>> (std::istream& is, BoxND& bx) { + IntVectND small; + IntVectND big; + IntVectND type; + detail::box_read(is, small.begin(), big.begin(), type.begin(), dim); + bx = BoxND{small, big, type}; + return is; +} + +/** +* \brief Returns a BoxND obtained by concatenating the input BoxNDs. +* The dimension of the return value equals the sum of the dimensions of the inputted BoxNDs. +*/ +template +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +constexpr BoxND()> +BoxCat (const BoxND& bx, const BoxND&...boxes) noexcept { + auto lo = IntVectCat(bx.smallEnd(), boxes.smallEnd()...); + auto hi = IntVectCat(bx.bigEnd(), boxes.bigEnd()...); + auto typ = IndexTypeCat(bx.ixType(), boxes.ixType()...); + return BoxND()>{lo, hi, typ}; +} + +/** +* \brief Returns a tuple of BoxNDs obtained by splitting the input BoxND +* according to the dimensions specified by the template arguments. +*/ +template +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +constexpr GpuTuple, BoxND...> +BoxSplit (const BoxND()>& bx) noexcept { + auto lo = IntVectSplit(bx.smallEnd()); + auto hi = IntVectSplit(bx.bigEnd()); + auto typ = IndexTypeSplit(bx.ixType()); + return detail::BoxSplit_imp(std::make_index_sequence<1 + sizeof...(dims)>(), lo, hi, typ); +} + +/** +* \brief Returns a new BoxND of dimension new_dim and +* assigns the first new_dim dimension of this BoxND to it. +*/ +template +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +constexpr BoxND +BoxShrink (const BoxND& bx) noexcept { + return bx.template shrink(); +} + +/** +* \brief Returns a new BoxND of size new_dim and +* assigns all values of this BoxND to it and +* (small=0, big=0, typ=CELL) to the remaining elements. +*/ +template +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +constexpr BoxND +BoxExpand (const BoxND& bx) noexcept { + return bx.template expand(); +} - //! Read from istream. -std::istream& operator>> (std::istream& is, Box& bx); +/** +* \brief Returns a new BoxND of size new_dim +* by either shrinking or expanding this BoxND +*/ +template +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +constexpr BoxND +BoxResize (const BoxND& bx) noexcept { + return bx.template resize(); +} +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Dim3 lbound (Box const& box) noexcept +IntVectND lbound_iv (BoxND const& box) noexcept { -#if (AMREX_SPACEDIM == 1) - return {box.smallend[0], 0, 0}; -#elif (AMREX_SPACEDIM == 2) - return {box.smallend[0], box.smallend[1], 0}; -#elif (AMREX_SPACEDIM == 3) - return {box.smallend[0], box.smallend[1], box.smallend[2]}; -#endif + return box.smallEnd(); } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Dim3 ubound (Box const& box) noexcept +IntVectND ubound_iv (BoxND const& box) noexcept { -#if (AMREX_SPACEDIM == 1) - return {box.bigend[0], 0, 0}; -#elif (AMREX_SPACEDIM == 2) - return {box.bigend[0], box.bigend[1], 0}; -#elif (AMREX_SPACEDIM == 3) - return {box.bigend[0], box.bigend[1], box.bigend[2]}; -#endif + return box.bigEnd(); } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Dim3 begin (Box const& box) noexcept +IntVectND begin_iv (BoxND const& box) noexcept { -#if (AMREX_SPACEDIM == 1) - return {box.smallend[0], 0, 0}; -#elif (AMREX_SPACEDIM == 2) - return {box.smallend[0], box.smallend[1], 0}; -#elif (AMREX_SPACEDIM == 3) - return {box.smallend[0], box.smallend[1], box.smallend[2]}; -#endif + return box.smallEnd(); } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Dim3 end (Box const& box) noexcept +IntVectND end_iv (BoxND const& box) noexcept { -#if (AMREX_SPACEDIM == 1) - return {box.bigend[0]+1, 1, 1}; -#elif (AMREX_SPACEDIM == 2) - return {box.bigend[0]+1, box.bigend[1]+1, 1}; -#elif (AMREX_SPACEDIM == 3) - return {box.bigend[0]+1, box.bigend[1]+1, box.bigend[2]+1}; -#endif + return box.bigEnd() + 1; } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Dim3 length (Box const& box) noexcept +IntVectND length_iv (BoxND const& box) noexcept { -#if (AMREX_SPACEDIM == 1) - return {box.bigend[0]-box.smallend[0]+1, 1, 1}; -#elif (AMREX_SPACEDIM == 2) - return {box.bigend[0]-box.smallend[0]+1, - box.bigend[1]-box.smallend[1]+1, 1}; -#elif (AMREX_SPACEDIM == 3) - return {box.bigend[0]-box.smallend[0]+1, - box.bigend[1]-box.smallend[1]+1, - box.bigend[2]-box.smallend[2]+1}; -#endif + return box.bigEnd() - box.smallEnd() + 1; } // Max of lower bound +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Dim3 max_lbound (Box const& b1, Box const& b2) noexcept +IntVectND max_lbound_iv (BoxND const& b1, BoxND const& b2) noexcept { -#if (AMREX_SPACEDIM == 1) - return {amrex::max(b1.smallend[0], b2.smallend[0]), - 0, 0}; -#elif (AMREX_SPACEDIM == 2) - return {amrex::max(b1.smallend[0], b2.smallend[0]), - amrex::max(b1.smallend[1], b2.smallend[1]), - 0}; -#elif (AMREX_SPACEDIM == 3) - return {amrex::max(b1.smallend[0], b2.smallend[0]), - amrex::max(b1.smallend[1], b2.smallend[1]), - amrex::max(b1.smallend[2], b2.smallend[2])}; -#endif + return max(b1.smallEnd(), b2.smallEnd()); } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Dim3 max_lbound (Box const& b1, Dim3 const& lo) noexcept +IntVectND max_lbound_iv (BoxND const& b1, IntVectND const& lo) noexcept { -#if (AMREX_SPACEDIM == 1) - return {amrex::max(b1.smallend[0], lo.x), - 0, 0}; -#elif (AMREX_SPACEDIM == 2) - return {amrex::max(b1.smallend[0], lo.x), - amrex::max(b1.smallend[1], lo.y), - 0}; -#elif (AMREX_SPACEDIM == 3) - return {amrex::max(b1.smallend[0], lo.x), - amrex::max(b1.smallend[1], lo.y), - amrex::max(b1.smallend[2], lo.z)}; -#endif + return max(b1.smallEnd(), lo); } // Min of upper bound +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Dim3 min_ubound (Box const& b1, Box const& b2) noexcept +IntVectND min_ubound_iv (BoxND const& b1, BoxND const& b2) noexcept { -#if (AMREX_SPACEDIM == 1) - return {amrex::min(b1.bigend[0], b2.bigend[0]), - 0, 0}; -#elif (AMREX_SPACEDIM == 2) - return {amrex::min(b1.bigend[0], b2.bigend[0]), - amrex::min(b1.bigend[1], b2.bigend[1]), - 0}; -#elif (AMREX_SPACEDIM == 3) - return {amrex::min(b1.bigend[0], b2.bigend[0]), - amrex::min(b1.bigend[1], b2.bigend[1]), - amrex::min(b1.bigend[2], b2.bigend[2])}; -#endif + return min(b1.bigEnd(), b2.bigEnd()); } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Dim3 min_ubound (Box const& b1, Dim3 const& hi) noexcept +IntVectND min_ubound_iv (BoxND const& b1, IntVectND const& hi) noexcept { -#if (AMREX_SPACEDIM == 1) - return {amrex::min(b1.bigend[0], hi.x), - 0, 0}; -#elif (AMREX_SPACEDIM == 2) - return {amrex::min(b1.bigend[0], hi.x), - amrex::min(b1.bigend[1], hi.y), - 0}; -#elif (AMREX_SPACEDIM == 3) - return {amrex::min(b1.bigend[0], hi.x), - amrex::min(b1.bigend[1], hi.y), - amrex::min(b1.bigend[2], hi.z)}; -#endif + return min(b1.bigEnd(), hi); } +template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box minBox (Box const& b1, Box const& b2, IndexType typ) noexcept -{ -#if (AMREX_SPACEDIM == 1) - return Box(IntVect(amrex::max(b1.smallend[0], b2.smallend[0])), - IntVect(amrex::min(b1.bigend [0], b2.bigend [0])), - typ); -#elif (AMREX_SPACEDIM == 2) - return Box(IntVect(amrex::max(b1.smallend[0], b2.smallend[0]), - amrex::max(b1.smallend[1], b2.smallend[1])), - IntVect(amrex::min(b1.bigend [0], b2.bigend [0]), - amrex::min(b1.bigend [1], b2.bigend [1])), - typ); -#elif (AMREX_SPACEDIM == 3) - return Box(IntVect(amrex::max(b1.smallend[0], b2.smallend[0]), - amrex::max(b1.smallend[1], b2.smallend[1]), - amrex::max(b1.smallend[2], b2.smallend[2])), - IntVect(amrex::min(b1.bigend [0], b2.bigend [0]), - amrex::min(b1.bigend [1], b2.bigend [1]), - amrex::min(b1.bigend [2], b2.bigend [2])), - typ); -#endif +Dim3 lbound (BoxND const& box) noexcept +{ + return box.smallEnd().dim3(); +} + +template = 0> +[[nodiscard]] +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +Dim3 ubound (BoxND const& box) noexcept +{ + return box.bigEnd().dim3(); +} + +template = 0> +[[nodiscard]] +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +Dim3 begin (BoxND const& box) noexcept +{ + return box.smallEnd().dim3(); +} + +template = 0> +[[nodiscard]] +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +Dim3 end (BoxND const& box) noexcept +{ + return (box.bigEnd() + 1).dim3(1); +} + +template = 0> +[[nodiscard]] +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +Dim3 length (BoxND const& box) noexcept +{ + return (box.bigEnd() - box.smallEnd() + 1).dim3(1); } -// Returns a Box that covers all the argument Boxes in index +// Max of lower bound +template = 0> +[[nodiscard]] +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +Dim3 max_lbound (BoxND const& b1, BoxND const& b2) noexcept +{ + return max(b1.smallEnd(), b2.smallEnd()).dim3(); +} + +template = 0> +[[nodiscard]] +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +Dim3 max_lbound (BoxND const& b1, Dim3 const& lo) noexcept +{ + return max(b1.smallEnd(), IntVectND(lo)).dim3(); +} + +// Min of upper bound +template = 0> +[[nodiscard]] +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +Dim3 min_ubound (BoxND const& b1, BoxND const& b2) noexcept +{ + return min(b1.bigEnd(), b2.bigEnd()).dim3(); +} + +template = 0> +[[nodiscard]] +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +Dim3 min_ubound (BoxND const& b1, Dim3 const& hi) noexcept +{ + return min(b1.bigEnd(), IntVectND(hi)).dim3(); +} + +// Returns a BoxND that covers all the argument Boxes in index // space. The types are ignored. Thus, the arguments can have -// different index types, and the returned Box's index type has no +// different index types, and the returned BoxND's index type has no // meaning. +template [[nodiscard]] AMREX_FORCE_INLINE -Box getIndexBounds (Box const& b1) noexcept +BoxND getIndexBounds (BoxND const& b1) noexcept { return b1; } +template [[nodiscard]] AMREX_FORCE_INLINE -Box getIndexBounds (Box const& b1, Box const& b2) noexcept +BoxND getIndexBounds (BoxND const& b1, BoxND const& b2) noexcept { - Box b = b1; + BoxND b = b1; b.setType(b2.ixType()); b.minBox(b2); return b; @@ -1792,16 +1965,17 @@ Box getIndexBounds (Box const& b1, Box const& b2) noexcept template [[nodiscard]] AMREX_FORCE_INLINE -Box getIndexBounds (T const& b1, T const& b2, Ts const& ... b3) noexcept +auto getIndexBounds (T const& b1, T const& b2, Ts const& ... b3) noexcept { return getIndexBounds(getIndexBounds(b1,b2),b3...); } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -IntVect getCell (Box const* boxes, int nboxes, Long icell) noexcept +IntVectND getCell (BoxND const* boxes, int nboxes, Long icell) noexcept { int ibox; Long ncells_subtotal = 0; @@ -1817,117 +1991,113 @@ IntVect getCell (Box const* boxes, int nboxes, Long icell) noexcept return boxes[ibox].atOffset(offset); } +template [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box makeSlab (Box const& b, int direction, int slab_index) noexcept +BoxND makeSlab (BoxND const& b, int direction, int slab_index) noexcept { - Box r = b; + BoxND r = b; r.makeSlab(direction,slab_index); return r; } +template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE -Box makeSingleCellBox (int i, int j, int k, IndexType typ = IndexType::TheCellType()) +BoxND makeSingleCellBox (int i, int j, int k, IndexTypeND typ = IndexTypeND::TheCellType()) { -#if (AMREX_SPACEDIM == 1) - amrex::ignore_unused(j,k); -#elif (AMREX_SPACEDIM == 2) - amrex::ignore_unused(k); -#endif - return Box(IntVect(AMREX_D_DECL(i,j,k)),IntVect(AMREX_D_DECL(i,j,k)),typ); + Dim3 p3d{i, j, k}; + IntVectND vect{p3d}; + return BoxND{vect, vect, typ}; } -struct BoxIndexer +template +[[nodiscard]] +AMREX_GPU_HOST_DEVICE +AMREX_FORCE_INLINE +BoxND makeSingleCellBox (IntVectND const& vect, IndexTypeND typ = IndexTypeND::TheCellType()) { - std::uint64_t npts; + return BoxND{vect, vect, typ}; +} -#if (AMREX_SPACEDIM == 3) - Math::FastDivmodU64 fdxy; - Math::FastDivmodU64 fdx; - IntVect lo; +template +struct BoxIndexerND +{ + std::uint64_t npts; + Math::FastDivmodU64 fdm[dim-1]; + IntVectND lo; - BoxIndexer (Box const& box) + BoxIndexerND (BoxND const& box) : npts(box.numPts()), - fdxy(std::uint64_t(box.length(0))*std::uint64_t(box.length(1))), - fdx (std::uint64_t(box.length(0))), lo (box.smallEnd()) - {} - - [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE - Dim3 operator() (std::uint64_t icell) const - { - std::uint64_t x, y, z, rem; - fdxy(z, rem, icell); - fdx(y, x, rem); - return {int(x)+lo[0], int(y)+lo[1], int(z)+lo[2]}; - } + { + std::uint64_t mult = 1; + for (int i=0; i intVect (std::uint64_t icell) const { - std::uint64_t x, y, z, rem; - fdxy(z, rem, icell); - fdx(y, x, rem); - return {int(x)+lo[0], int(y)+lo[1], int(z)+lo[2]}; - } + IntVectND retval = lo; -#elif (AMREX_SPACEDIM == 2) + for (int i=dim-1; i>0; --i) { + std::uint64_t quotient, remainder; + fdm[i-1](quotient, remainder, icell); + retval[i] += quotient; + icell = remainder; + } - Math::FastDivmodU64 fdx; - IntVect lo; + retval[0] += icell; - BoxIndexer (Box const& box) - : npts(box.numPts()), - fdx (std::uint64_t(box.length(0))), - lo (box.smallEnd()) - {} + return retval; + } + template = 0> [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 operator() (std::uint64_t icell) const { - std::uint64_t x, y; - fdx(y, x, icell); - return {int(x)+lo[0], int(y)+lo[1], 0}; + return intVect(icell).dim3(); } [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE - IntVect intVect (std::uint64_t icell) const - { - std::uint64_t x, y; - fdx(y, x, icell); - return {int(x)+lo[0], int(y)+lo[1]}; - } + std::uint64_t numPts () const { return npts; } +}; -#elif (AMREX_SPACEDIM == 1) +template<> +struct BoxIndexerND<1> +{ + std::uint64_t npts; int lo; - BoxIndexer (Box const& box) + BoxIndexerND (BoxND<1> const& box) : npts(box.numPts()), lo(box.smallEnd(0)) {} [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE - Dim3 operator() (std::uint64_t icell) const + IntVectND<1> intVect (std::uint64_t icell) const { - return {int(icell)+lo, 0, 0}; + return IntVectND<1>{int(icell)+lo}; } [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE - IntVect intVect (std::uint64_t icell) const + Dim3 operator() (std::uint64_t icell) const { - return IntVect{int(icell)+lo}; + return {int(icell)+lo, 0, 0}; } -#endif - [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE std::uint64_t numPts () const { return npts; } }; +using BoxIndexer = BoxIndexerND; + } #endif /*AMREX_BOX_H*/ diff --git a/Src/Base/AMReX_Box.cpp b/Src/Base/AMReX_Box.cpp index b0db9caa994..0f53bda5e99 100644 --- a/Src/Base/AMReX_Box.cpp +++ b/Src/Base/AMReX_Box.cpp @@ -10,19 +10,23 @@ namespace amrex { +namespace detail { + // // I/O functions. // std::ostream& -operator<< (std::ostream& os, - const Box& b) +box_write (std::ostream& os, + const int * smallend, + const int * bigend, + const int * type, + int dim) { - os << '(' - << b.smallEnd() << ' ' - << b.bigEnd() << ' ' - << b.type() - << ')'; + os << '('; + int_vector_write(os, smallend, dim) << ' '; + int_vector_write(os, bigend, dim) << ' '; + int_vector_write(os, type, dim) << ')'; if (os.fail()) { amrex::Error("operator<<(ostream&,Box&) failed"); @@ -37,37 +41,44 @@ operator<< (std::ostream& os, #define BL_IGNORE_MAX 100000 std::istream& -operator>> (std::istream& is, - Box& b) +box_read (std::istream& is, + int * smallend, + int * bigend, + int * type, + int dim) { - IntVect lo, hi, typ; - is >> std::ws; char c; is >> c; + for (int i=0; i> lo >> hi; + int_vector_read(is, smallend, dim); + int_vector_read(is, bigend, dim); is >> c; // Read an optional IndexType is.putback(c); if ( c == '(' ) { - is >> typ; + int_vector_read(is, type, dim); } is.ignore(BL_IGNORE_MAX,')'); } else if (c == '<') { is.putback(c); - is >> lo >> hi; + int_vector_read(is, smallend, dim); + int_vector_read(is, bigend, dim); is >> c; // Read an optional IndexType is.putback(c); if ( c == '<' ) { - is >> typ; + int_vector_read(is, type, dim); } //is.ignore(BL_IGNORE_MAX,'>'); } @@ -76,8 +87,6 @@ operator>> (std::istream& is, amrex::Error("operator>>(istream&,Box&): expected \'(\'"); } - b = Box(lo,hi,typ); - if (is.fail()) { amrex::Error("operator>>(istream&,Box&) failed"); } @@ -85,6 +94,8 @@ operator>> (std::istream& is, return is; } +} // namespace detail + BoxCommHelper::BoxCommHelper (const Box& bx, int* p_) : p(p_) { diff --git a/Src/Base/AMReX_IntVect.H b/Src/Base/AMReX_IntVect.H index c133a1f57c4..6452f29b036 100644 --- a/Src/Base/AMReX_IntVect.H +++ b/Src/Base/AMReX_IntVect.H @@ -167,6 +167,18 @@ public: } } + template = 0> + [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + Dim3 dim3 ([[maybe_unused]] int fill_extra) const noexcept { + if constexpr (dim == 1) { + return Dim3{vect[0],fill_extra,fill_extra}; + } else if constexpr (dim == 2) { + return Dim3{vect[0],vect[1],fill_extra}; + } else { + return Dim3{vect[0],vect[1],vect[2]}; + } + } + #if __cplusplus >= 201402L template< typename T = int > AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE diff --git a/Src/Base/AMReX_Math.H b/Src/Base/AMReX_Math.H index 42762001268..c4d8d524af0 100644 --- a/Src/Base/AMReX_Math.H +++ b/Src/Base/AMReX_Math.H @@ -274,7 +274,7 @@ std::uint64_t umulhi (std::uint64_t a, std::uint64_t b) /// struct FastDivmodU64 { - std::uint64_t divisor; + std::uint64_t divisor = 0; #ifdef AMREX_INT128_SUPPORTED std::uint64_t multiplier = 1U; @@ -324,6 +324,9 @@ struct FastDivmodU64 #endif + /// Default construct an invalid FastDivmodU64 + FastDivmodU64 () = default; + /// Returns the quotient of floor(dividend / divisor) [[nodiscard]] AMREX_GPU_HOST_DEVICE std::uint64_t divide (std::uint64_t dividend) const diff --git a/Src/Base/AMReX_ParmParse.H b/Src/Base/AMReX_ParmParse.H index 286bed71660..c9e273643ec 100644 --- a/Src/Base/AMReX_ParmParse.H +++ b/Src/Base/AMReX_ParmParse.H @@ -18,7 +18,9 @@ namespace amrex { -class Box; +template +class BoxND; +using Box = BoxND; template class IntVectND; using IntVect = IntVectND; diff --git a/Tools/Plotfile/fboxinfo.cpp b/Tools/Plotfile/fboxinfo.cpp index 6d84ab519c7..85886d6c0c5 100644 --- a/Tools/Plotfile/fboxinfo.cpp +++ b/Tools/Plotfile/fboxinfo.cpp @@ -6,18 +6,18 @@ using namespace amrex; namespace { -class BoxND +class BoxNDDynamic { public: - friend std::ostream& operator<< (std::ostream& os, const BoxND& b); - BoxND (Box const& b, int dim) : m_box(b), m_dim(dim) {} + friend std::ostream& operator<< (std::ostream& os, const BoxNDDynamic& b); + BoxNDDynamic (Box const& b, int dim) : m_box(b), m_dim(dim) {} private: Box m_box; int m_dim; }; std::ostream& -operator<< (std::ostream& os, const BoxND& b) +operator<< (std::ostream& os, const BoxNDDynamic& b) { if (b.m_dim == 1) { os << "(" @@ -175,10 +175,10 @@ void main_main() const BoxArray& ba = plotfile.boxArray(ilev); const Long nboxes = ba.size(); const Box prob_domain = plotfile.probDomain(ilev); - amrex::Print() << " " << BoxND(prob_domain,dim) + amrex::Print() << " " << BoxNDDynamic(prob_domain,dim) << " " << nboxes << "\n"; for (int ibox = 0; ibox < nboxes; ++ibox) { - amrex::Print() << " " << BoxND(ba[ibox],dim) << "\n"; + amrex::Print() << " " << BoxNDDynamic(ba[ibox],dim) << "\n"; } } }