Block-Structured AMR Software Framework
AMReX_InSituUtils.H
Go to the documentation of this file.
1 #ifndef AMReX_InSituUtils_H
2 #define AMReX_InSituUtils_H
3 #include <AMReX_Config.H>
4 
5 #include <svtkDataSetAttributes.h>
6 #include <svtkUnsignedCharArray.h>
7 #include <svtkFloatArray.h>
8 #include <svtkDoubleArray.h>
9 
10 #include <AMReX_BoxArray.H>
11 #include <AMReX_Geometry.H>
12 #include <AMReX_RealBox.H>
13 #include <AMReX_Box.H>
14 #include <AMReX_ArrayLim.H>
15 #include <AMReX_MFIter.H>
17 #include <AMReX_IndexType.H>
18 
19 #include <map>
20 #include <utility>
21 #include <string>
22 #include <vector>
23 
24 namespace amrex {
25 namespace InSituUtils {
26 
27 // The following bit fields are consistent with VisIt ghost zones specification
28 // For details, see http://www.visitusers.org/index.php?title=Representing_ghost_data
29 
31 {
32  DUPLICATECELL = 1, // the cell is present on multiple processors
33  HIGHCONNECTIVITYCELL = 2, // the cell has more neighbors than in a regular mesh
34  LOWCONNECTIVITYCELL = 4, // the cell has less neighbors than in a regular mesh
35  REFINEDCELL = 8, // other cells are present that refines it.
36  EXTERIORCELL = 16, // the cell is on the exterior of the data set
37  HIDDENCELL = 32 // the cell is needed to maintain connectivity,
38  // but the data values should be ignored.
39 };
40 
42 {
43  DUPLICATEPOINT = 1, // the cell is present on multiple processors
44  HIDDENPOINT = 2 // the point is needed to maintain connectivity,
45  // but the data values should be ignored.
46 };
47 
48 
49 
50 // traits helper for mapping between amrex_real and svtkDataArray
51 template <typename cpp_t> struct amrex_tt {};
52 
53 #define amrex_tt_specialize(cpp_t, svtk_t, svtk_t_e) \
54 template <> \
55 struct amrex_tt<cpp_t> \
56 { \
57  using svtk_type = svtk_t; \
58  \
59  static \
60  constexpr int svtk_type_enum() { return svtk_t_e; } \
61 };
62 
63 amrex_tt_specialize(float, svtkFloatArray, SVTK_FLOAT)
64 amrex_tt_specialize(double, svtkDoubleArray, SVTK_DOUBLE)
65 
66 
67 // helpers to modify values
68 template<typename n_t>
69 struct assignOp { void operator()(n_t &elem, n_t val) { elem = val; } };
70 
71 template<typename n_t>
72 struct orOp { void operator()(n_t &elem, n_t val) { elem |= val; } };
73 
74 // --------------------------------------------------------------------------
75 template <typename n_t, typename op_t>
76 int UpdatePatch(long *len, int *lo, int *hi, n_t *darray, n_t val)
77 {
78  op_t updateOp;
79 
80  long nx = len[0];
81  long nxy = len[0]*len[1];
82 
83  for (int k = lo[2]; k <= hi[2]; ++k)
84  {
85  for (int j = lo[1]; j <= hi[1]; ++j)
86  {
87  for (int i = lo[0]; i <= hi[0]; ++i)
88  {
89  updateOp(darray[k*nxy + j*nx + i], val);
90  }
91  }
92  }
93  return 0;
94 }
95 
96 // --------------------------------------------------------------------------
97 template <typename n_t>
98 int AllocateBoxArray(const amrex::Box &pdom, const amrex::BoxArray &boxes,
99  const amrex::DistributionMapping &dmap, int ng, std::vector<n_t*> &darrays)
100 {
101  amrex::ignore_unused(pdom);
102 
103  int rank = 0;
104  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
105 
106  unsigned int nBoxes = boxes.size();
107 
108  darrays.resize(nBoxes, nullptr);
109 
110  // loop over boxes
111  for (unsigned int p = 0; p < nBoxes; ++p)
112  {
113  // skip non local box
114  if (dmap[p] != rank)
115  continue;
116 
117  // for computing indices
118  amrex::Box box = boxes[p];
119 
120  // add ghosts
121  for (unsigned int q = 0; q < AMREX_SPACEDIM; ++q)
122  box.grow(q, ng);
123 
124  // TODO -- handle node cenetred data via flag
125  // and surroundingNodes
126 
127  // array size
128  int lo[3] = {AMREX_ARLIM(box.loVect())};
129  int hi[3] = {AMREX_ARLIM(box.hiVect())};
130  long len[3] = {0};
131 
132  for (int q = 0; q < 3; ++q)
133  len[q] = hi[q] - lo[q] + 1;
134 
135  long nxyz = 1;
136  for (int q = 0; q < 3; ++q)
137  nxyz *= len[q];
138 
139  // allocate array
140  n_t *tmp = (n_t*)malloc(sizeof(n_t)*nxyz);
141 
142  // default initialize
143  for (long q = 0; q < nxyz; ++q)
144  tmp[q] = n_t();
145 
146  // store at box index
147  darrays[p] = tmp;
148  }
149 
150  return 0;
151 }
152 
153 // --------------------------------------------------------------------------
154 template <typename n_t>
155 int MaskGhostCells(const amrex::Box &pdom, const amrex::BoxArray &boxes,
156  const amrex::DistributionMapping &dmap, unsigned int ng,
157  std::vector<n_t*> &darrays)
158 {
159  amrex::ignore_unused(pdom);
160 
161  // no ghosts to mask
162  if (ng < 1)
163  return 0;
164 
165  int rank = 0;
166  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
167 
168  // loop over boxes
169  unsigned int nBoxes = boxes.size();
170  for (unsigned int p = 0; p < nBoxes; ++p)
171  {
172  // skip non local box
173  if (dmap[p] != rank)
174  continue;
175 
176  // for computing indices
177  amrex::Box box = boxes[p];
178 
179  // add ghosts
180  for (int q = 0; q < AMREX_SPACEDIM; ++q)
181  box.grow(q, ng);
182 
183  // restrict to problem domain
184  //box &= pdom;
185 
186  // shift to array indexing space
187  box.shift(-1*box.smallEnd());
188 
189  // array size
190  int lo[3] = {AMREX_ARLIM(box.loVect())};
191  int hi[3] = {AMREX_ARLIM(box.hiVect())};
192 
193  long len[3] = {0};
194  for (int q = 0; q < 3; ++q)
195  len[q] = hi[q] - lo[q] + 1;
196 
197  // get array
198  n_t *tmp = darrays[p];
199 
200  // for each valid direction
201  for (int q = 0; q < AMREX_SPACEDIM; ++q)
202  {
203  int glo[3] = {0};
204  int ghi[3] = {0};
205 
206  // fill low side ghosts
207  for (int r = 0; r < 3; ++r)
208  glo[r] = lo[r];
209 
210  for (int r = 0; r < 3; ++r)
211  ghi[r] = hi[r];
212 
213  ghi[q] = glo[q] + ng - 1;
214 
215  UpdatePatch<unsigned char,orOp<unsigned char>>(len,
216  glo, ghi, tmp, CellGhostTypes::DUPLICATECELL);
217 
218  // fill high side ghosts
219  for (int r = 0; r < 3; ++r)
220  glo[r] = lo[r];
221 
222  for (int r = 0; r < 3; ++r)
223  ghi[r] = hi[r];
224 
225  glo[q] = ghi[q] + ng - 1;
226 
227  UpdatePatch<unsigned char,orOp<unsigned char>>(len,
228  glo, ghi, tmp, CellGhostTypes::DUPLICATECELL);
229  }
230  }
231 
232  return 0;
233 }
234 
235 // --------------------------------------------------------------------------
236 template <typename n_t>
237 int MaskCoveredCells(const amrex::Box &pdom, const amrex::BoxArray &cBoxes,
238  const amrex::DistributionMapping &cMap, amrex::BoxArray fBoxes,
239  const IntVect &fRefRatio, int ng, std::vector<n_t*> &cMasks)
240 {
241  amrex::ignore_unused(pdom);
242 
243  int rank = 0;
244  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
245 
246  // work in the coarse level index space
247  fBoxes.coarsen(fRefRatio);
248 
249  // loop over the local coarse boxes
250  unsigned int nCBoxes = cBoxes.size();
251  for (unsigned int p = 0; p < nCBoxes; ++p)
252  {
253  // skip non local coarse box. we do not need to mask it.
254  if (cMap[p] != rank)
255  continue;
256 
257  // this one tells us info for computing indices
258  amrex::Box cBox = cBoxes[p];
259 
260  // add ghosts
261  for (int q = 0; q < AMREX_SPACEDIM; ++q)
262  cBox.grow(q, ng);
263 
264  // restrict to problem domain
265  //cBox &= pdom;
266 
267  // array size
268  int cLo[3] = {AMREX_ARLIM(cBox.loVect())};
269  int cHi[3] = {AMREX_ARLIM(cBox.hiVect())};
270 
271  long cLen[3] = {0};
272  for (int q = 0; q < 3; ++q)
273  cLen[q] = cHi[q] - cLo[q] + 1;
274 
275  // mask array
276  n_t *cMask = cMasks[p];
277 
278  // loop over fine boxes
279  unsigned int nFBoxes = fBoxes.size();
280  for (unsigned int pp = 0; pp < nFBoxes; ++pp)
281  {
282  // intersect, the intersection is the covered region
283  amrex::Box fBox = fBoxes[pp];;
284  amrex::Box iBox = fBox & cBox;
285 
286 
287  if (!iBox.isEmpty())
288  {
289  // shift to array indexing space
290  iBox -= cBox.smallEnd();
291 
292  // indices of covered region
293  int iLo[3] = {AMREX_ARLIM(iBox.loVect())};
294  int iHi[3] = {AMREX_ARLIM(iBox.hiVect())};
295 
296  UpdatePatch<n_t, orOp<n_t>>(cLen, iLo, iHi, cMask,
298  }
299  }
300  }
301 
302  return 0;
303 }
304 
305 
306 // helper to track names and centerings of the available arrays
307 class StateMap
308 {
309 public:
310  void Clear(){ this->Map.clear(); }
311 
312  int GetIndex(const std::string &arrayName,
313  int centering, int &desc, int &comp);
314 
315  int Size(int centering){ return this->Map[centering].size(); }
316 
317  int GetName(int centering, int id, std::string &name);
318 
319 protected:
320  std::map<int,std::map<std::string,std::pair<int,int>>> Map;
321 };
322 
323 }
324 }
325 
326 #endif
amrex::ParmParse pp
Input file parser instance for the given namespace.
Definition: AMReX_HypreIJIface.cpp:15
static constexpr int MPI_COMM_WORLD
Definition: AMReX_ccse-mpi.H:54
void * malloc(YYSIZE_T)
A collection of Boxes stored in an Array.
Definition: AMReX_BoxArray.H:550
BoxArray & coarsen(int refinement_ratio)
Coarsen each Box in the BoxArray to the specified ratio.
Long size() const noexcept
Return the number of boxes in the BoxArray.
Definition: AMReX_BoxArray.H:597
AMREX_GPU_HOST_DEVICE const IntVectND< dim > & smallEnd() const &noexcept
Get the smallend of the BoxND.
Definition: AMReX_Box.H:105
AMREX_GPU_HOST_DEVICE BoxND & shift(int dir, int nzones) noexcept
Shift this BoxND nzones indexing positions in coordinate direction dir.
Definition: AMReX_Box.H:496
AMREX_GPU_HOST_DEVICE BoxND & grow(int i) noexcept
Definition: AMReX_Box.H:627
AMREX_GPU_HOST_DEVICE const int * hiVect() const &noexcept
Returns a constant pointer the array of high end coordinates. Useful for calls to FORTRAN.
Definition: AMReX_Box.H:183
AMREX_GPU_HOST_DEVICE bool isEmpty() const noexcept
Checks if it is an empty BoxND.
Definition: AMReX_Box.H:196
AMREX_GPU_HOST_DEVICE const int * loVect() const &noexcept
Returns a constant pointer the array of low end coordinates. Useful for calls to FORTRAN.
Definition: AMReX_Box.H:178
Calculates the distribution of FABs to MPI processes.
Definition: AMReX_DistributionMapping.H:41
Definition: AMReX_InSituUtils.H:308
int GetName(int centering, int id, std::string &name)
Definition: AMReX_InSituUtils.cpp:38
void Clear()
Definition: AMReX_InSituUtils.H:310
int Size(int centering)
Definition: AMReX_InSituUtils.H:315
int GetIndex(const std::string &arrayName, int centering, int &desc, int &comp)
Definition: AMReX_InSituUtils.cpp:10
std::map< int, std::map< std::string, std::pair< int, int > > > Map
Definition: AMReX_InSituUtils.H:320
svtkDoubleArray
Definition: AMReX_InSituUtils.H:64
int MaskCoveredCells(const amrex::Box &pdom, const amrex::BoxArray &cBoxes, const amrex::DistributionMapping &cMap, amrex::BoxArray fBoxes, const IntVect &fRefRatio, int ng, std::vector< n_t * > &cMasks)
Definition: AMReX_InSituUtils.H:237
CellGhostTypes
Definition: AMReX_InSituUtils.H:31
@ HIDDENCELL
Definition: AMReX_InSituUtils.H:37
@ LOWCONNECTIVITYCELL
Definition: AMReX_InSituUtils.H:34
@ HIGHCONNECTIVITYCELL
Definition: AMReX_InSituUtils.H:33
@ REFINEDCELL
Definition: AMReX_InSituUtils.H:35
@ EXTERIORCELL
Definition: AMReX_InSituUtils.H:36
@ DUPLICATECELL
Definition: AMReX_InSituUtils.H:32
int MaskGhostCells(const amrex::Box &pdom, const amrex::BoxArray &boxes, const amrex::DistributionMapping &dmap, unsigned int ng, std::vector< n_t * > &darrays)
Definition: AMReX_InSituUtils.H:155
int UpdatePatch(long *len, int *lo, int *hi, n_t *darray, n_t val)
Definition: AMReX_InSituUtils.H:76
PointGhostTypes
Definition: AMReX_InSituUtils.H:42
@ HIDDENPOINT
Definition: AMReX_InSituUtils.H:44
@ DUPLICATEPOINT
Definition: AMReX_InSituUtils.H:43
int AllocateBoxArray(const amrex::Box &pdom, const amrex::BoxArray &boxes, const amrex::DistributionMapping &dmap, int ng, std::vector< n_t * > &darrays)
Definition: AMReX_InSituUtils.H:98
amrex_tt_specialize(float, svtkFloatArray, SVTK_FLOAT) amrex_tt_specialize(double
Definition: AMReX_Amr.cpp:49
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition: AMReX.H:111
Definition: AMReX_InSituUtils.H:51
Definition: AMReX_InSituUtils.H:69
void operator()(n_t &elem, n_t val)
Definition: AMReX_InSituUtils.H:69
Definition: AMReX_InSituUtils.H:72
void operator()(n_t &elem, n_t val)
Definition: AMReX_InSituUtils.H:72