Line data Source code
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 : //
21 : namespace ippl {
22 : namespace detail {
23 : template <typename T, unsigned Dim, class Mesh, class... Properties>
24 60 : RegionLayout<T, Dim, Mesh, Properties...>::RegionLayout()
25 60 : : dLocalRegions_m("local regions (device)", 0)
26 120 : , hLocalRegions_m(Kokkos::create_mirror_view(dLocalRegions_m)) {
27 60 : indexOffset_m.fill(0);
28 60 : centerOffset_m.fill(0);
29 60 : }
30 :
31 : template <typename T, unsigned Dim, class Mesh, class... Properties>
32 60 : RegionLayout<T, Dim, Mesh, Properties...>::RegionLayout(const FieldLayout<Dim>& fl,
33 : const Mesh& mesh)
34 60 : : RegionLayout() {
35 60 : changeDomain(fl, mesh);
36 60 : }
37 :
38 : template <typename T, unsigned Dim, class Mesh, class... Properties>
39 84 : void RegionLayout<T, Dim, Mesh, Properties...>::changeDomain(const FieldLayout<Dim>& fl,
40 : const Mesh& mesh) {
41 : // set our index space offset
42 378 : for (unsigned int d = 0; d < Dim; ++d) {
43 294 : indexOffset_m[d] = fl.getDomain()[d].first();
44 294 : centerOffset_m[d] = 1;
45 : }
46 :
47 84 : region_m = convertNDIndex(fl.getDomain(), mesh);
48 :
49 84 : fillRegions(fl, mesh);
50 84 : }
51 :
52 : // convert a given NDIndex into an NDRegion ... if this object was
53 : // constructed from a FieldLayout, this does nothing, but if we are maintaining
54 : // our own internal FieldLayout, we must convert from the [0,N-1] index
55 : // space to our own continuous NDRegion space.
56 : // NOTE: THIS ASSUMES THAT REGION'S HAVE first() < last() !!
57 : template <typename T, unsigned Dim, class Mesh, class... Properties>
58 : typename RegionLayout<T, Dim, Mesh, Properties...>::NDRegion_t
59 168 : RegionLayout<T, Dim, Mesh, Properties...>::convertNDIndex(const NDIndex<Dim>& ni,
60 : const Mesh& mesh) const {
61 : // find first and last points in NDIndex and get coordinates from mesh
62 168 : NDIndex<Dim> firstPoint, lastPoint;
63 756 : for (unsigned int d = 0; d < Dim; d++) {
64 588 : int first = ni[d].first() - indexOffset_m[d];
65 588 : int last = ni[d].last() - indexOffset_m[d] + centerOffset_m[d];
66 588 : firstPoint[d] = Index(first, first);
67 588 : lastPoint[d] = Index(last, last);
68 : }
69 :
70 : // convert to mesh space
71 168 : Vector<T, Dim> firstCoord = mesh.getVertexPosition(firstPoint);
72 168 : Vector<T, Dim> lastCoord = mesh.getVertexPosition(lastPoint);
73 168 : NDRegion_t ndregion;
74 756 : for (unsigned int d = 0; d < Dim; d++) {
75 588 : ndregion[d] = PRegion<T>(firstCoord(d), lastCoord(d));
76 : }
77 168 : return ndregion;
78 168 : }
79 :
80 : template <typename T, unsigned Dim, class Mesh, class... Properties>
81 84 : void RegionLayout<T, Dim, Mesh, Properties...>::fillRegions(const FieldLayout<Dim>& fl,
82 : const Mesh& mesh) {
83 : using domain_type = typename FieldLayout<Dim>::host_mirror_type;
84 84 : const domain_type& ldomains = fl.getHostLocalDomains();
85 :
86 84 : Kokkos::resize(hLocalRegions_m, ldomains.size());
87 84 : Kokkos::resize(dLocalRegions_m, ldomains.size());
88 :
89 : using size_type = typename domain_type::size_type;
90 168 : for (size_type i = 0; i < ldomains.size(); ++i) {
91 168 : hLocalRegions_m(i) = convertNDIndex(ldomains(i), mesh);
92 : }
93 :
94 84 : Kokkos::deep_copy(dLocalRegions_m, hLocalRegions_m);
95 84 : }
96 :
97 : template <typename T, unsigned Dim, class Mesh, class... Properties>
98 : void RegionLayout<T, Dim, Mesh, Properties...>::write(std::ostream& out) const {
99 : if (Comm->rank() > 0) {
100 : return;
101 : }
102 :
103 : out << "Total region = " << region_m << "\n"
104 : << "Total number of subregions = " << hLocalRegions_m.size() << "\n";
105 :
106 : using size_type = typename host_mirror_type::size_type;
107 : for (size_type i = 0; i < hLocalRegions_m.size(); ++i) {
108 : out << " subregion " << i << " " << hLocalRegions_m(i) << "\n";
109 : }
110 : }
111 :
112 : template <typename T, unsigned Dim, class Mesh, class... Properties>
113 : const typename RegionLayout<T, Dim, Mesh, Properties...>::view_type
114 12 : RegionLayout<T, Dim, Mesh, Properties...>::getdLocalRegions() const {
115 12 : return dLocalRegions_m;
116 : }
117 :
118 : template <typename T, unsigned Dim, class Mesh, class... Properties>
119 : const typename RegionLayout<T, Dim, Mesh, Properties...>::host_mirror_type
120 0 : RegionLayout<T, Dim, Mesh, Properties...>::gethLocalRegions() const {
121 0 : return hLocalRegions_m;
122 : }
123 :
124 : template <typename T, unsigned Dim, class Mesh, class... Properties>
125 : std::ostream& operator<<(std::ostream& out, const RegionLayout<T, Dim, Mesh>& rl) {
126 : rl.write(out);
127 : return out;
128 : }
129 : } // namespace detail
130 : } // namespace ippl
|