IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
SubFieldLayout.hpp
Go to the documentation of this file.
1//
2// Class SubFieldLayout
3// SubFieldLayout provides a layout for a sub-region of a larger field.
4// It ensures that the sub-region is partitioned in the same way as the original FieldLayout,
5// maintaining consistent parallel decomposition and neighbor relationships within the sub-region.
6//
7#include "Ippl.h"
8
9#include <cstdlib>
10#include <limits>
11
13#include "Utility/IpplTimings.h"
14#include "Utility/PAssert.h"
15
17
18namespace ippl {
19
27 template <unsigned Dim>
29 : FieldLayout<Dim>(communicator) {}
30
43 template <unsigned Dim>
45 const NDIndex<Dim>& subDomain, std::array<bool, Dim> isParallel, bool isAllPeriodic)
46 : FieldLayout<Dim>(communicator) {
47 initialize(domain, subDomain, isParallel, isAllPeriodic);
48 }
49
57 template <unsigned Dim>
59 std::array<bool, Dim> isParallel, bool isAllPeriodic)
60 : FieldLayout<Dim>(communicator) {
61 initialize(domain, isParallel, isAllPeriodic);
62 }
63
75 template <unsigned Dim>
76 void SubFieldLayout<Dim>::initialize(const NDIndex<Dim>& domain, const NDIndex<Dim>& subDomain, std::array<bool, Dim> isParallel,
77 bool isAllPeriodic) {
78
79 // Ensure the sub-domain is contained within the main domain
80 PAssert(domain.contains(subDomain));
81
82 // Call the base class initialize method to set up the main domain and parallel decomposition
83 FieldLayout<Dim>::initialize(domain, isParallel, isAllPeriodic);
84
85 unsigned int nRanks = this->comm.size();
86
87 originDomain_m = domain;
88
89 this->gDomain_m = subDomain;
90
91 // Check if all ranks have a valid local domain that intersects with the sub-domain
92 if (this->hLocalDomains_m(this->comm.rank()).intersect(subDomain).empty()) {
93 throw std::runtime_error("SubFieldLayout:initialize: given subdomain is not valid, rank"
94 + std::to_string(this->comm.rank()) + " has an empty local domain, choose a sub-domain that has content on all ranks");
95 }
96
97 // If the local domain is not contained in the sub-domain, change it to the intersection of the local domain and the sub-domain
98 // This ensures that the sub-field layout is consistent with the original layout
99 for (unsigned int rank = 0; rank < nRanks; ++rank) {
100 if (!this->gDomain_m.contains(this->hLocalDomains_m(rank))) {
101 this->hLocalDomains_m(rank) = this->hLocalDomains_m(rank).intersect(this->gDomain_m);
102 }
103 }
104
105 this->findNeighbors();
106
107 Kokkos::deep_copy(this->dLocalDomains_m, this->hLocalDomains_m);
108
109 this->calcWidths();
110 }
111
119 template <unsigned Dim>
120 void SubFieldLayout<Dim>::initialize(const NDIndex<Dim>& domain, std::array<bool, Dim> isParallel,
121 bool isAllPeriodic) {
122 // Call the base class initialize method to set up the main domain and parallel decomposition
123 FieldLayout<Dim>::initialize(domain, isParallel, isAllPeriodic);
124
125 originDomain_m = domain;
126 }
127
128} // namespace ippl
constexpr unsigned Dim
#define PAssert(c)
Definition PAssert.h:116
Definition Archive.h:20
void findNeighbors(int nghost=1)
std::array< bool, Dim > isParallel() const
void initialize(const NDIndex< Dim > &domain, std::array< bool, Dim > decomp, bool isAllPeriodic=false)
mpi::Communicator comm
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).
NDIndex_t gDomain_m
Global domain.
SubFieldLayout(const mpi::Communicator &=MPI_COMM_WORLD)
Default constructor, which should only be used if you are going to call 'initialize' soon after (befo...
NDIndex_t originDomain_m
Original global domain in which the sub-field is defined.
void initialize(const NDIndex< Dim > &domain, const NDIndex< Dim > &subDomain, std::array< bool, Dim > decomp, bool isAllPeriodic=false)
Initializes a SubFieldLayout with the sub-domain partitioned in the same way as the original FieldLay...
KOKKOS_INLINE_FUNCTION bool contains(const NDIndex< Dim > &a) const
Definition NDIndex.hpp:104