IPPL API Reference
Independent Parallel Particle Layer C++ API
Loading...
Searching...
No Matches
RegionLayout.hpp
1//
2// Class RegionLayout
3// RegionLayout stores a partitioned set of NDRegion objects, to represent
4// the parallel layout of an encompassing NDRegion. It also contains
5// functions to find the subsets of the NDRegion partitions which intersect
6// or touch a given NDRegion. It is similar to FieldLayout, with the
7// following changes:
8// 1. It uses NDRegion instead of NDIndex, so it is templated on the position
9// data type (although it can be constructed with an NDIndex and a Mesh
10// as well);
11// 2. It does not contain any consideration for guard cells;
12// 3. It can store not only the partitioned domain, but periodic copies of
13// the partitioned domain for use by particle periodic boundary conditions
14// 4. It also keeps a list of FieldLayoutUser's, so that it can notify them
15// when the internal FieldLayout here is reparitioned or otherwise changed.
16//
17// If this is constructed with a FieldLayout, it stores a pointer to it
18// so that if we must repartition the copy of the FieldLayout that
19// is stored here, we will end up repartitioning all the registered Fields.
20//
21namespace ippl {
22 namespace detail {
23 template <typename T, unsigned Dim, class Mesh, class... Properties>
24 RegionLayout<T, Dim, Mesh, Properties...>::RegionLayout()
25 : dLocalRegions_m("local regions (device)", 0)
26 , hLocalRegions_m(Kokkos::create_mirror_view(dLocalRegions_m)) {
27 indexOffset_m.fill(0);
28 centerOffset_m.fill(0);
29 node_m = false;
30 }
31
32 template <typename T, unsigned Dim, class Mesh, class... Properties>
33 RegionLayout<T, Dim, Mesh, Properties...>::RegionLayout(const FieldLayout<Dim>& fl,
34 const Mesh& mesh, bool node)
35 : RegionLayout() {
36 node_m = node;
37 changeDomain(fl, mesh);
38 }
39
40 template <typename T, unsigned Dim, class Mesh, class... Properties>
41 void RegionLayout<T, Dim, Mesh, Properties...>::changeDomain(const FieldLayout<Dim>& fl,
42 const Mesh& mesh) {
43 // set our index space offset
44 for (unsigned int d = 0; d < Dim; ++d) {
45 indexOffset_m[d] = fl.getDomain()[d].first();
46 centerOffset_m[d] = 1;
47 }
48
49 region_m = convertNDIndex(fl.getDomain(), mesh);
50
51 fillRegions(fl, mesh);
52
53 if (node_m) {
54 for (unsigned int d = 0; d < Dim; d++) {
55 T firstCoord = region_m[d].min();
56 T lastCoord = region_m[d].max() - mesh.getMeshSpacing()[d];
57 region_m[d] = PRegion<T>(firstCoord, lastCoord);
58 }
59 }
60
61 }
62
63 // convert a given NDIndex into an NDRegion ... if this object was
64 // constructed from a FieldLayout, this does nothing, but if we are maintaining
65 // our own internal FieldLayout, we must convert from the [0,N-1] index
66 // space to our own continuous NDRegion space.
67 // NOTE: THIS ASSUMES THAT REGION'S HAVE first() < last() !!
68 template <typename T, unsigned Dim, class Mesh, class... Properties>
69 typename RegionLayout<T, Dim, Mesh, Properties...>::NDRegion_t
70 RegionLayout<T, Dim, Mesh, Properties...>::convertNDIndex(const NDIndex<Dim>& ni,
71 const Mesh& mesh) const {
72 // find first and last points in NDIndex and get coordinates from mesh
73 NDIndex<Dim> firstPoint, lastPoint;
74 for (unsigned int d = 0; d < Dim; d++) {
75 int first = ni[d].first() - indexOffset_m[d];
76 int last = ni[d].last() - indexOffset_m[d] + centerOffset_m[d];
77 firstPoint[d] = Index(first, first);
78 lastPoint[d] = Index(last, last);
79 }
80
81 // convert to mesh space
82 Vector<T, Dim> firstCoord = mesh.getVertexPosition(firstPoint);
83 Vector<T, Dim> lastCoord = mesh.getVertexPosition(lastPoint);
84
85 if (node_m) {
86 for (unsigned int d = 0; d < Dim; d++) {
87 if (lastCoord[d] == region_m[d].max()) {
88 lastCoord[d] -= mesh.getMeshSpacing()[d];
89 }
90 }
91 }
92
93 NDRegion_t ndregion;
94 for (unsigned int d = 0; d < Dim; d++) {
95 ndregion[d] = PRegion<T>(firstCoord(d), lastCoord(d));
96 }
97 return ndregion;
98 }
99
100 template <typename T, unsigned Dim, class Mesh, class... Properties>
101 void RegionLayout<T, Dim, Mesh, Properties...>::fillRegions(const FieldLayout<Dim>& fl,
102 const Mesh& mesh) {
103 using domain_type = typename FieldLayout<Dim>::host_mirror_type;
104 const domain_type& ldomains = fl.getHostLocalDomains();
105
106 Kokkos::resize(hLocalRegions_m, ldomains.size());
107 Kokkos::resize(dLocalRegions_m, ldomains.size());
108
109 using size_type = typename domain_type::size_type;
110 for (size_type i = 0; i < ldomains.size(); ++i) {
111 hLocalRegions_m(i) = convertNDIndex(ldomains(i), mesh);
112 }
113
114 Kokkos::deep_copy(dLocalRegions_m, hLocalRegions_m);
115 }
116
117 template <typename T, unsigned Dim, class Mesh, class... Properties>
118 void RegionLayout<T, Dim, Mesh, Properties...>::write(std::ostream& out) const {
119 if (Comm->rank() > 0) {
120 return;
121 }
122
123 out << "Total region = " << region_m << "\n"
124 << "Total number of subregions = " << hLocalRegions_m.size() << "\n";
125
126 using size_type = typename host_mirror_type::size_type;
127 for (size_type i = 0; i < hLocalRegions_m.size(); ++i) {
128 out << " subregion " << i << " " << hLocalRegions_m(i) << "\n";
129 }
130 }
131
132 template <typename T, unsigned Dim, class Mesh, class... Properties>
133 const typename RegionLayout<T, Dim, Mesh, Properties...>::view_type
134 RegionLayout<T, Dim, Mesh, Properties...>::getdLocalRegions() const {
135 return dLocalRegions_m;
136 }
137
138 template <typename T, unsigned Dim, class Mesh, class... Properties>
139 const typename RegionLayout<T, Dim, Mesh, Properties...>::host_mirror_type
140 RegionLayout<T, Dim, Mesh, Properties...>::gethLocalRegions() const {
141 return hLocalRegions_m;
142 }
143
144 template <typename T, unsigned Dim, class Mesh, class... Properties>
145 std::ostream& operator<<(std::ostream& out, const RegionLayout<T, Dim, Mesh>& rl) {
146 rl.write(out);
147 return out;
148 }
149 } // namespace detail
150} // namespace ippl
Definition Vector.h:23
Definition Archive.h:20