diff --git a/grid/src/Cabana_Grid_LocalGrid.hpp b/grid/src/Cabana_Grid_LocalGrid.hpp index 17d250e28..7fe991c9e 100644 --- a/grid/src/Cabana_Grid_LocalGrid.hpp +++ b/grid/src/Cabana_Grid_LocalGrid.hpp @@ -252,11 +252,81 @@ class LocalGrid boundaryIndexSpace( DecompositionTag t1, EntityType t2, const int off_i, const int off_j, const int halo_width = -1 ) const; + /*! + \brief Given the relative offsets of a periodic boundary relative to this + local grid's indices get the set of local entity indices associated with + that boundary in the given decomposition. + + \param t1 Decomposition type: Own or Ghost + \param t2 Entity: Cell, Node, Edge, or Face + \param off_ijk %Array of neighbor offset indices. + \param halo_width Optional depth of shared indices within the halo. Must + be less than or equal to the halo width of the local grid. Default is to + use the halo width of the local grid. + + For example, if the Own decomposition is used, the interior entities that + would be affected by a periodic boundary operation are provided whereas if + the Ghost decomposition is used the halo entities of that periodic + neighbor are provided. + */ + template + IndexSpace + periodicIndexSpace( DecompositionTag t1, EntityType t2, + const std::array& off_ijk, + const int halo_width = -1 ) const; + + /*! + \brief Given the relative offsets of a periodic boundary relative to this + local grid's indices get the set of local entity indices associated with + that boundary in the given decomposition. + + \param t1 Decomposition type: Own or Ghost + \param t2 Entity: Cell, Node, Edge, or Face + \param off_i, off_j, off_k Neighbor offset index in a given dimension. + \param halo_width Optional depth of shared indices within the halo. Must + be less than or equal to the halo width of the local grid. Default is to + use the halo width of the local grid. + + For example, if the Own decomposition is used, the interior entities that + would be affected by a boundary operation are provided whereas if the + Ghost decomposition is used the halo entities of that periodic neighbor + are provided. + */ + template + std::enable_if_t<3 == NSD, IndexSpace<3>> + periodicIndexSpace( DecompositionTag t1, EntityType t2, const int off_i, + const int off_j, const int off_k, + const int halo_width = -1 ) const; + + /*! + \brief Given the relative offsets of a periodic boundary relative to this + local grid's indices get the set of local entity indices associated with + that boundary in the given decomposition. + + \param t1 Decomposition type: Own or Ghost + \param t2 Entity: Cell, Node, Edge, or Face + \param off_i, off_j Neighbor offset index in a given dimension. + \param halo_width Optional depth of shared indices within the halo. Must + be less than or equal to the halo width of the local grid. Default is to + use the halo width of the local grid. + + For example, if the Own decomposition is used, the interior entities that + would be affected by a boundary operation are provided whereas if the + Ghost decomposition is used the halo entities of that periodic neighbor + are provided. + */ + template + std::enable_if_t<2 == NSD, IndexSpace<2>> + periodicIndexSpace( DecompositionTag t1, EntityType t2, const int off_i, + const int off_j, const int halo_width = -1 ) const; + private: // Helper functions - zeroIndexSpace(); - setupHaloWidthImpl( const int halo_width ); - checkOffsets( const std::array& off_ijk ); + auto zeroIndexSpace() const; + auto setupHaloWidth( const int halo_width ) const; + void checkOffsets( const std::array& off_ijk ) const; template auto getBound( OwnedIndexSpace owned_space, const int upper_lower, diff --git a/grid/src/Cabana_Grid_LocalGrid_impl.hpp b/grid/src/Cabana_Grid_LocalGrid_impl.hpp index 584fd1097..a38470e00 100644 --- a/grid/src/Cabana_Grid_LocalGrid_impl.hpp +++ b/grid/src/Cabana_Grid_LocalGrid_impl.hpp @@ -95,7 +95,8 @@ LocalGrid::neighborRank( const int off_i, const int off_j ) const //---------------------------------------------------------------------------// // Get the index space for a given combination of decomposition, entity, and // index types. -auto LocalGrid::zeroIndexSpace() +template +auto LocalGrid::zeroIndexSpace() const { std::array zero_size; for ( std::size_t d = 0; d < num_space_dim; ++d ) @@ -103,7 +104,8 @@ auto LocalGrid::zeroIndexSpace() return IndexSpace( zero_size, zero_size ); } -auto LocalGrid::setupHaloWidth( const int halo_width ) +template +auto LocalGrid::setupHaloWidth( const int halo_width ) const { // If we got the default halo width of -1 this means we want to use the // default of the entire halo. @@ -116,8 +118,9 @@ auto LocalGrid::setupHaloWidth( const int halo_width ) return hw; } -auto LocalGrid::checkOffsets( - const std::array& off_ijk ) +template +void LocalGrid::checkOffsets( + const std::array& off_ijk ) const { // Check that the offsets are valid. for ( std::size_t d = 0; d < num_space_dim; ++d ) @@ -238,6 +241,65 @@ LocalGrid::boundaryIndexSpace( DecompositionTag t1, EntityType t2, return boundaryIndexSpace( t1, t2, off_ijk, halo_width ); } +//---------------------------------------------------------------------------// +// Given the relative offsets of a boundary relative to this local grid's +// indices get the set of local entity indices associated with that periodic +// boundary in the given decomposition. Optionally provide a halo width for the +// shared space. This halo width must be less than or equal to the halo width of +// the local grid. The default behavior is to use the halo width of the local +// grid. For example, if the Own decomposition is used, the interior entities +// that would be affected by a periodic boundary operation are provided whereas +// if the Ghost decomposition is used the halo entities on the boundary are +// provided. +template +template +auto LocalGrid::periodicIndexSpace( + DecompositionTag t1, EntityType t2, + const std::array& off_ijk, const int halo_width ) const + -> IndexSpace +{ + auto hw = setupHaloWidth( halo_width ); + checkOffsets( off_ijk ); + + // Check to see if this is a periodic neighbor. If not, return a boundary + // space of size 0 because there is no periodic boundary. + bool periodic_ijk = true; + for ( std::size_t d = 0; d < num_space_dim; ++d ) + if ( off_ijk[d] == 0 || !_global_grid->isPeriodic( d ) ) + periodic_ijk = false; + if ( !periodic_ijk ) + { + return zeroIndexSpace(); + } + + // Call the underlying implementation. Periodic index spaces are simply the + // subset of shared index spaces that are on periodic boundaries. + return sharedIndexSpaceImpl( t1, t2, off_ijk, hw ); +} + +template +template +std::enable_if_t<3 == NSD, IndexSpace<3>> +LocalGrid::periodicIndexSpace( DecompositionTag t1, EntityType t2, + const int off_i, const int off_j, + const int off_k, + const int halo_width ) const +{ + std::array off_ijk = { off_i, off_j, off_k }; + return periodicIndexSpace( t1, t2, off_ijk, halo_width ); +} + +template +template +std::enable_if_t<2 == NSD, IndexSpace<2>> +LocalGrid::periodicIndexSpace( DecompositionTag t1, EntityType t2, + const int off_i, const int off_j, + const int halo_width ) const +{ + std::array off_ijk = { off_i, off_j }; + return periodicIndexSpace( t1, t2, off_ijk, halo_width ); +} + //---------------------------------------------------------------------------// // Get the local index space of the owned cells. template