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