1 /* ----------------------------------------------------------------------
2 SPARTA - Stochastic PArallel Rarefied-gas Time-accurate Analyzer
3 http://sparta.sandia.gov
4 Steve Plimpton, sjplimp@sandia.gov, Michael Gallis, magalli@sandia.gov
5 Sandia National Laboratories
6
7 Copyright (2014) Sandia Corporation. Under the terms of Contract
8 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
9 certain rights in this software. This software is distributed under
10 the GNU General Public License.
11
12 See the README file in the top-level SPARTA directory.
13 ------------------------------------------------------------------------- */
14
15 #include "string.h"
16 #include "grid_kokkos.h"
17 #include "geometry.h"
18 #include "domain.h"
19 #include "comm.h"
20 #include "irregular.h"
21 #include "math_const.h"
22 #include "memory_kokkos.h"
23 #include "error.h"
24 #include "kokkos.h"
25 #include "sparta_masks.h"
26
27 using namespace SPARTA_NS;
28 using namespace MathConst;
29
30 #define DELTA 8192
31 #define DELTAPARENT 1024
32 #define BIG 1.0e20
33 #define MAXGROUP 32
34 #define MAXLEVEL 32
35
36 // default value, can be overridden by global command
37
38 #define MAXSURFPERCELL 100
39
40 enum{XLO,XHI,YLO,YHI,ZLO,ZHI,INTERIOR}; // same as Domain
41 enum{PERIODIC,OUTFLOW,REFLECT,SURFACE,AXISYM}; // same as Domain
42 enum{REGION_ALL,REGION_ONE,REGION_CENTER}; // same as Surf
43
44 // cell is entirely outside/inside surfs or has any overlap with surfs
45 // corner pt is outside/inside surfs or is on a surf
46
47 enum{UNKNOWN,OUTSIDE,INSIDE,OVERLAP}; // several files
48 enum{NCHILD,NPARENT,NUNKNOWN,NPBCHILD,NPBPARENT,NPBUNKNOWN,NBOUND}; // Update
49 enum{NOWEIGHT,VOLWEIGHT,RADWEIGHT,RADUNWEIGHT};
50
51 // allocate space for static class variable
52
53 //Grid *Grid::gptr;
54
55 // corners[i][j] = J corner points of face I of a grid cell
56 // works for 2d quads and 3d hexes
57
58 //int corners[6][4] = {{0,2,4,6}, {1,3,5,7}, {0,1,4,5}, {2,3,6,7},
59 // {0,1,2,3}, {4,5,6,7}};
60
61 /* ---------------------------------------------------------------------- */
62
GridKokkos(SPARTA * sparta)63 GridKokkos::GridKokkos(SPARTA *sparta) : Grid(sparta)
64 {
65 delete [] plevels;
66 memoryKK->create_kokkos(k_plevels,plevels,MAXLEVEL,"grid:plevels");
67 }
68
~GridKokkos()69 GridKokkos::~GridKokkos()
70 {
71 if (copy || copymode) return;
72
73 cells = NULL;
74 cinfo = NULL;
75 sinfo = NULL;
76 pcells = NULL;
77 plevels = NULL;
78 }
79
80 ///////////////////////////////////////////////////////////////////////////
81 // grow cell list data structures
82 ///////////////////////////////////////////////////////////////////////////
83
84 /* ----------------------------------------------------------------------
85 insure cells and cinfo can hold N and M new cells respectively
86 ------------------------------------------------------------------------- */
87
grow_cells(int n,int m)88 void GridKokkos::grow_cells(int n, int m)
89 {
90 if (sparta->kokkos->prewrap) {
91 Grid::grow_cells(n,m);
92 } else {
93
94 if (nlocal+nghost+n >= maxcell) {
95 while (maxcell < nlocal+nghost+n) maxcell += DELTA;
96 if (cells == NULL)
97 k_cells = tdual_cell_1d("grid:cells",maxcell);
98 else {
99 this->sync(Device,CELL_MASK); // force resize on device
100 k_cells.resize(maxcell);
101 this->modify(Device,CELL_MASK); // needed for auto sync
102 }
103 cells = k_cells.h_view.data();
104 }
105
106 if (nlocal+m >= maxlocal) {
107 while (maxlocal < nlocal+m) maxlocal += DELTA;
108 if (cinfo == NULL)
109 k_cinfo = tdual_cinfo_1d("grid:cinfo",maxlocal);
110 else {
111 this->sync(Device,CINFO_MASK); // force resize on device
112 k_cinfo.resize(maxlocal);
113 this->modify(Device,CINFO_MASK); // needed for auto sync
114 }
115 cinfo = k_cinfo.h_view.data();
116 }
117 }
118 }
119
120 /* ----------------------------------------------------------------------
121 grow pcells
122 ------------------------------------------------------------------------- */
123
grow_pcells()124 void GridKokkos::grow_pcells()
125 {
126 if (sparta->kokkos->prewrap) {
127 Grid::grow_pcells();
128 } else {
129
130 maxparent += DELTA;
131 if (pcells == NULL)
132 k_pcells = tdual_pcell_1d("grid:pcells",maxparent);
133 else {
134 this->sync(Device,PCELL_MASK); // force resize on device
135 k_pcells.resize(maxparent);
136 this->modify(Device,PCELL_MASK); // needed for auto sync
137 }
138 pcells = k_pcells.h_view.data();
139 }
140 }
141
142 /* ----------------------------------------------------------------------
143 insure sinfo can hold N new split cells
144 ------------------------------------------------------------------------- */
145
grow_sinfo(int n)146 void GridKokkos::grow_sinfo(int n)
147 {
148 if (sparta->kokkos->prewrap) {
149 Grid::grow_sinfo(n);
150 } else {
151
152 if (nsplitlocal+nsplitghost+n >= maxsplit) {
153 while (maxsplit < nsplitlocal+nsplitghost+n) maxsplit += DELTA;
154 if (sinfo == NULL)
155 k_sinfo = tdual_sinfo_1d("grid:sinfo",maxsplit);
156 else {
157 this->sync(Device,SINFO_MASK); // force resize on device
158 k_sinfo.resize(maxsplit);
159 this->modify(Device,SINFO_MASK); // needed for auto sync
160 }
161 sinfo = k_sinfo.h_view.data();
162 }
163 }
164 }
165
166 /* ---------------------------------------------------------------------- */
167
wrap_kokkos_graphs()168 void GridKokkos::wrap_kokkos_graphs()
169 {
170 // csurfs
171
172 Kokkos::Crs<int, SPAHostType, void, int> h_csurfs;
173 auto csurfs_lambda = [=](int icell, int* fill) {
174 int nsurf = cells[icell].nsurf;
175 if (nsurf < 0) nsurf = 0;
176 else if (fill) {
177 surfint* csurfs = cells[icell].csurfs;
178 // d_csurfs doesn't need to be surfint because at this point there are only
179 // local (not global) ids stored in csurfs
180 for (int j = 0; j < nsurf; ++j) fill[j] = (int) csurfs[j];
181 }
182 return nsurf;
183 };
184 Kokkos::count_and_fill_crs(h_csurfs, nlocal+nghost, csurfs_lambda);
185 d_csurfs.row_map = decltype(d_csurfs.row_map)(
186 "csurfs.row_map", h_csurfs.row_map.size());
187 d_csurfs.entries = decltype(d_csurfs.entries)(
188 "csurfs.entries", h_csurfs.entries.size());
189 Kokkos::deep_copy(d_csurfs.row_map, h_csurfs.row_map);
190 Kokkos::deep_copy(d_csurfs.entries, h_csurfs.entries);
191
192 if (sinfo != NULL) {
193
194 Kokkos::Crs<int, SPAHostType, void, int> h_csplits;
195 auto csplits_lambda = [=](int isplit, int* fill) {
196 int icell = sinfo[isplit].icell;
197 int nsurf = cells[icell].nsurf;
198 int nsplit = cells[icell].nsplit;
199 if (nsurf < 0 || nsplit <= 1) nsurf = 0;
200 else if (fill) {
201 int* csplits = sinfo[isplit].csplits;
202 for (int j = 0; j < nsurf; ++j) fill[j] = csplits[j];
203 }
204 return nsurf;
205 };
206 Kokkos::count_and_fill_crs(h_csplits, nsplitlocal+nsplitghost, csplits_lambda);
207 d_csplits.row_map = decltype(d_csplits.row_map)(
208 "csplits.row_map", h_csplits.row_map.size());
209 d_csplits.entries = decltype(d_csplits.entries)(
210 "csplits.entries", h_csplits.entries.size());
211 Kokkos::deep_copy(d_csplits.row_map, h_csplits.row_map);
212 Kokkos::deep_copy(d_csplits.entries, h_csplits.entries);
213
214 Kokkos::Crs<int, SPAHostType, void, int> h_csubs;
215 auto csubs_lambda = [=](int isplit, int* fill) {
216 int icell = sinfo[isplit].icell;
217 int nsurf = cells[icell].nsurf;
218 int nsplit = cells[icell].nsplit;
219 if (nsurf < 0 || nsplit <= 1) nsplit = 0;
220 else if (fill) {
221 int* csubs = sinfo[isplit].csubs;
222 for (int j = 0; j < nsplit; ++j) fill[j] = csubs[j];
223 }
224 return nsplit;
225 };
226 Kokkos::count_and_fill_crs(h_csubs, nsplitlocal+nsplitghost, csubs_lambda);
227 d_csubs.row_map = decltype(d_csubs.row_map)(
228 "csubs.row_map", h_csubs.row_map.size());
229 d_csubs.entries = decltype(d_csubs.entries)(
230 "csubs.entries", h_csubs.entries.size());
231 Kokkos::deep_copy(d_csubs.row_map, h_csubs.row_map);
232 Kokkos::deep_copy(d_csubs.entries, h_csubs.entries);
233
234 }
235 }
236
237 /* ---------------------------------------------------------------------- */
238
wrap_kokkos()239 void GridKokkos::wrap_kokkos()
240 {
241 // cells
242
243 if (cells != k_cells.h_view.data()) {
244 memoryKK->wrap_kokkos(k_cells,cells,maxcell,"grid:cells");
245 k_cells.modify_host();
246 k_cells.sync_device();
247 memory->sfree(cells);
248 cells = k_cells.h_view.data();
249 }
250
251 // cinfo
252
253 if (cinfo != k_cinfo.h_view.data()) {
254 memoryKK->wrap_kokkos(k_cinfo,cinfo,maxlocal,"grid:cinfo");
255 k_cinfo.modify_host();
256 k_cinfo.sync_device();
257 memory->sfree(cinfo);
258 cinfo = k_cinfo.h_view.data();
259 }
260
261 // sinfo
262
263 if (sinfo != k_sinfo.h_view.data()) {
264 memoryKK->wrap_kokkos(k_sinfo,sinfo,maxsplit,"grid:sinfo");
265 k_sinfo.modify_host();
266 k_sinfo.sync_device();
267 memory->sfree(sinfo);
268 sinfo = k_sinfo.h_view.data();
269 }
270
271 wrap_kokkos_graphs();
272
273 // pcells
274
275 if (pcells != k_pcells.h_view.data()) {
276 memoryKK->wrap_kokkos(k_pcells,pcells,maxparent,"grid:pcells");
277 k_pcells.modify_host();
278 k_pcells.sync_device();
279 memory->sfree(pcells);
280 pcells = k_pcells.h_view.data();
281 }
282
283 // plevels
284
285 if (plevels != k_plevels.h_view.data()) {
286 memoryKK->wrap_kokkos(k_plevels,plevels,maxparent,"grid:plevels");
287 k_plevels.modify_host();
288 k_plevels.sync_device();
289 memory->sfree(plevels);
290 plevels = k_plevels.h_view.data();
291 }
292 }
293
294 /* ---------------------------------------------------------------------- */
295
sync(ExecutionSpace space,unsigned int mask)296 void GridKokkos::sync(ExecutionSpace space, unsigned int mask)
297 {
298 if (sparta->kokkos->prewrap) {
299 if (space == Device)
300 error->one(FLERR,"Sync Device before wrap");
301 else
302 return;
303 }
304
305 if (space == Device) {
306 if (sparta->kokkos->auto_sync)
307 modify(Host,mask);
308 if (mask & CELL_MASK) k_cells.sync_device();
309 if (mask & CINFO_MASK) k_cinfo.sync_device();
310 if (mask & PCELL_MASK) k_pcells.sync_device();
311 if (mask & SINFO_MASK) k_sinfo.sync_device();
312 if (mask & PLEVEL_MASK) k_plevels.sync_device();
313 } else {
314 if (mask & CELL_MASK) k_cells.sync_host();
315 if (mask & CINFO_MASK) k_cinfo.sync_host();
316 if (mask & PCELL_MASK) k_pcells.sync_host();
317 if (mask & SINFO_MASK) k_sinfo.sync_host();
318 if (mask & PLEVEL_MASK) k_plevels.sync_host();
319 }
320 }
321
322 /* ---------------------------------------------------------------------- */
323
modify(ExecutionSpace space,unsigned int mask)324 void GridKokkos::modify(ExecutionSpace space, unsigned int mask)
325 {
326 if (sparta->kokkos->prewrap) {
327 if (space == Device)
328 error->one(FLERR,"Modify Device before wrap");
329 else
330 return;
331 }
332
333 if (space == Device) {
334 if (mask & CELL_MASK) k_cells.modify_device();
335 if (mask & CINFO_MASK) k_cinfo.modify_device();
336 if (mask & PCELL_MASK) k_pcells.modify_device();
337 if (mask & SINFO_MASK) k_sinfo.modify_device();
338 if (mask & PLEVEL_MASK) k_plevels.modify_device();
339 if (sparta->kokkos->auto_sync)
340 sync(Host,mask);
341 } else {
342 if (mask & CELL_MASK) k_cells.modify_host();
343 if (mask & CINFO_MASK) k_cinfo.modify_host();
344 if (mask & PCELL_MASK) k_pcells.modify_host();
345 if (mask & SINFO_MASK) k_sinfo.modify_host();
346 if (mask & PLEVEL_MASK) k_plevels.modify_host();
347 }
348 }
349