21 template <
unsigned Dim>
27 static const int digit_swap[3] = {1, 0, 2};
30 match += digit_swap[index % 3] * d;
36 template <
unsigned Dim>
41 for (
unsigned int d = 0; d <
Dim; ++d) {
46 template <
unsigned Dim>
48 std::array<bool, Dim>
isParallel,
bool isAllPeriodic)
53 template <
unsigned Dim>
55 if (domains.empty()) {
59 for (
unsigned int i = 0; i < domains.size(); i++) {
70 template <
unsigned Dim>
73 int nRanks =
comm.size();
93 for (
unsigned d = 0; d <
Dim; ++d) {
97 if (totparelems < nRanks) {
98 throw std::runtime_error(
"FieldLayout:initialize: domain can only be partitioned in to "
99 + std::to_string(totparelems) +
" local domains, but there are " + std::to_string(nRanks) +
" ranks, decrease the number of ranks or increase the domain.");
115 template <
unsigned Dim>
120 template <
unsigned Dim>
128 template <
unsigned Dim>
134 template <
unsigned Dim>
139 template <
unsigned Dim>
144 template <
unsigned Dim>
150 template <
unsigned Dim>
156 template <
unsigned Dim>
158 if (
comm.rank() > 0) {
165 using size_type =
typename host_mirror_type::size_type;
171 template <
unsigned Dim>
174 for (
unsigned int d = 0; d <
Dim; ++d) {
178 using size_type =
typename host_mirror_type::size_type;
181 for (
unsigned int d = 0; d <
Dim; ++d) {
182 if ((
unsigned int)dom[d].length() <
minWidth_m[d]) {
189 template <
unsigned Dim>
193 std::map<unsigned int, int>& offsets,
unsigned d0,
195 for (
unsigned int d = d0; d <
Dim; ++d) {
198 for (
int k = 0; k < 2; ++k) {
206 if (grown.
touches(neighborDomain)) {
207 auto intersect = grown.
intersect(neighborDomain);
208 for (
auto& [d, offset] : offsets) {
209 neighborDomain[d] -= offset;
211 addNeighbors(grown, localDomain, neighborDomain, intersect, nghost, rank);
212 for (
auto& [d, offset] : offsets) {
213 neighborDomain[d] += offset;
216 if (codim + 1 <
Dim) {
217 findPeriodicNeighbors(nghost, localDomain, grown, neighborDomain, rank, offsets,
227 template <
unsigned Dim>
238 int myRank =
comm.rank();
244 auto gnd = nd.grow(nghost);
250 for (
int rank = 0; rank <
comm.size(); ++rank) {
251 if (rank == myRank) {
259 if (gnd.touches(ndNeighbor)) {
260 auto intersect = gnd.intersect(ndNeighbor);
267 std::map<unsigned int, int> offsets;
274 template <
unsigned Dim>
277 int nghost,
int rank) {
279 rangeSend =
getBounds(nd, ndNeighbor, nd, nghost);
281 rangeRecv =
getBounds(ndNeighbor, nd, nd, nghost);
284 for (
unsigned d = 0, digit = 1; d <
Dim; d++, digit *= 3) {
291 if (intersect[d].length() == 1) {
299 neighbors_m[index].push_back(rank);
300 neighborsSendRange_m[index].push_back(rangeSend);
301 neighborsRecvRange_m[index].push_back(rangeRecv);
304 template <
unsigned Dim>
313 bound_type intersect;
318 for (
size_t i = 0; i <
Dim; ++i) {
319 intersect.lo[i] = overlap[i].
first() - offset[i].
first() + nghost;
320 intersect.hi[i] = overlap[i].
last() - offset[i].
first() + nghost + 1;
326 template <
unsigned Dim>
336 if (nd[d].
min() == gDomain_m[d].
min()) {
337 return gDomain_m[d].length();
341 throw IpplException(
"FieldLayout:getPeriodicOffset",
"k has to be either 0 or 1");
ippl::detail::size_type size_type
constexpr KOKKOS_INLINE_FUNCTION auto first()
KOKKOS_INLINE_FUNCTION Vector< T, Dim > min(const Vector< T, Dim > &a, const Vector< T, Dim > &b)
KOKKOS_INLINE_FUNCTION constexpr unsigned int countHypercubes(unsigned int dim)
std::array< bool, Dim > isParallelDim_m
typename view_type::host_mirror_type host_mirror_type
void findNeighbors(int nghost=1)
const neighbor_list & getNeighbors() const
const host_mirror_type getHostLocalDomains() const
unsigned int minWidth_m[Dim]
void addNeighbors(const NDIndex_t &gnd, const NDIndex_t &nd, const NDIndex_t &ndNeighbor, const NDIndex_t &intersect, int nghost, int rank)
const view_type getDeviceLocalDomains() const
neighbor_list neighbors_m
neighbor_range_list neighborsSendRange_m
std::array< bool, Dim > isParallel() const
std::array< rank_list, detail::countHypercubes(Dim) - 1 > neighbor_list
typename detail::ViewType< NDIndex_t, 1 >::view_type view_type
void initialize(const NDIndex< Dim > &domain, std::array< bool, Dim > decomp, bool isAllPeriodic=false)
const NDIndex_t & getLocalNDIndex() const
void findPeriodicNeighbors(const int nghost, const NDIndex< Dim > &localDomain, NDIndex< Dim > &grown, NDIndex< Dim > &neighborDomain, const int rank, std::map< unsigned int, int > &offsets, unsigned d0=0, unsigned codim=0)
int getPeriodicOffset(const NDIndex_t &nd, const unsigned int d, const int k)
neighbor_range_list neighborsRecvRange_m
view_type dLocalDomains_m
Local domains (device view).
FieldLayout(const mpi::Communicator &=MPI_COMM_WORLD)
host_mirror_type hLocalDomains_m
Local domains (host mirror view).
void write(std::ostream &=std::cout) const
std::array< bounds_list, detail::countHypercubes(Dim) - 1 > neighbor_range_list
const neighbor_range_list & getNeighborsSendRange() const
const neighbor_range_list & getNeighborsRecvRange() const
bound_type getBounds(const NDIndex_t &nd1, const NDIndex_t &nd2, const NDIndex_t &offset, int nghost)
NDIndex_t gDomain_m
Global domain.
void updateLayout(const std::vector< NDIndex_t > &domains)
static int getMatchingIndex(int index)
KOKKOS_INLINE_FUNCTION bool touches(const NDIndex< Dim > &) const
KOKKOS_INLINE_FUNCTION Vector< int, Dim > last() const
KOKKOS_INLINE_FUNCTION Vector< int, Dim > first() const
KOKKOS_INLINE_FUNCTION NDIndex< Dim > intersect(const NDIndex< Dim > &) const
KOKKOS_INLINE_FUNCTION Vector< size_t, Dim > length() const
KOKKOS_INLINE_FUNCTION NDIndex< Dim > grow(int ncells) const
void split(const NDIndex< Dim > &domain, view_type &view, const std::array< bool, Dim > &isParallel, int nSplits) const
Timing::TimerRef TimerRef
static TimerRef getTimer(const char *nm)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)