chombo-discharge
CD_EBAMRParticleMeshImplem.H
Go to the documentation of this file.
1 /* chombo-discharge
2  * Copyright © 2021 SINTEF Energy Research.
3  * Please refer to Copyright.txt and LICENSE in the chombo-discharge root directory.
4  */
5 
12 #ifndef CD_EBAMRParticleMeshImplem_H
13 #define CD_EBAMRParticleMeshImplem_H
14 
15 // Chombo includes
16 #include <CH_Timer.H>
17 #include <EBAlias.H>
18 #include <LevelData.H>
19 #include <EBCellFactory.H>
20 
21 // Our includes
22 #include <CD_EBAMRParticleMesh.H>
23 #include <CD_EBAddOp.H>
24 #include <CD_DataOps.H>
25 #include <CD_NamespaceHeader.H>
26 
27 template <class P, const Real& (P::*particleScalarField)() const>
28 void
30  const ParticleContainer<P>& a_particles,
31  const DepositionType a_depositionType,
32  const CoarseFineDeposition a_coarseFineDeposition,
33  const bool a_forceIrregNGP)
34 {
35  CH_TIME("EBAMRParticleMesh::deposit(scalar)");
36 
37  CH_assert(a_meshData[0]->nComp() == 1);
38 
39  switch (a_coarseFineDeposition) {
40  case CoarseFineDeposition::Interp: {
41  this->depositInterp<P, particleScalarField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
42 
43  break;
44  }
45  case CoarseFineDeposition::Halo: {
46  this->depositHalo<P, particleScalarField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
47 
48  break;
49  }
50  case CoarseFineDeposition::HaloNGP: {
51  this->depositHaloNGP<P, particleScalarField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
52 
53  break;
54  }
55  default: {
56  MayDay::Error("EBAMRParticleMesh::deposit(scalar) - logic bust");
57 
58  break;
59  }
60  }
61 }
62 
63 template <class P, Real (P::*particleScalarField)() const>
64 void
66  const ParticleContainer<P>& a_particles,
67  const DepositionType a_depositionType,
68  const CoarseFineDeposition a_coarseFineDeposition,
69  const bool a_forceIrregNGP)
70 {
71  CH_TIME("EBAMRParticleMesh::deposit(scalar)");
72 
73  // Note: This is just like the other version except that the function signature is Real P::particleScalarField() const
74 
75  CH_assert(a_meshData[0]->nComp() == 1);
76 
77  switch (a_coarseFineDeposition) {
78  case CoarseFineDeposition::Interp: {
79  this->depositInterp<P, particleScalarField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
80 
81  break;
82  }
83  case CoarseFineDeposition::Halo: {
84  this->depositHalo<P, particleScalarField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
85 
86  break;
87  }
88  case CoarseFineDeposition::HaloNGP: {
89  this->depositHaloNGP<P, particleScalarField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
90 
91  break;
92  }
93  default: {
94  MayDay::Error("EBAMRParticleMesh::deposit(scalar) - logic bust");
95 
96  break;
97  }
98  }
99 }
100 
101 template <class P, const RealVect& (P::*particleVectorField)() const>
102 void
104  const ParticleContainer<P>& a_particles,
105  const DepositionType a_depositionType,
106  const CoarseFineDeposition a_coarseFineDeposition,
107  const bool a_forceIrregNGP)
108 {
109 
110  CH_TIME("EBAMRParticleMesh::deposit(vector)");
111 
112  CH_assert(a_meshData[0]->nComp() == SpaceDim);
113 
114  switch (a_coarseFineDeposition) {
115  case CoarseFineDeposition::Interp: {
116  this->depositInterp<P, particleVectorField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
117 
118  break;
119  }
120  case CoarseFineDeposition::Halo: {
121  this->depositHalo<P, particleVectorField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
122 
123  break;
124  }
125  case CoarseFineDeposition::HaloNGP: {
126  this->depositHaloNGP<P, particleVectorField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
127 
128  break;
129  }
130  default: {
131  MayDay::Error("EBAMRParticleMesh::deposit(RealVect) - logic bust");
132 
133  break;
134  }
135  }
136 }
137 
138 template <class P, RealVect (P::*particleVectorField)() const>
139 void
141  const ParticleContainer<P>& a_particles,
142  const DepositionType a_depositionType,
143  const CoarseFineDeposition a_coarseFineDeposition,
144  const bool a_forceIrregNGP)
145 {
146  CH_TIME("EBAMRParticleMesh::deposit(vector)");
147 
148  CH_assert(a_meshData[0]->nComp() == SpaceDim);
149 
150  switch (a_coarseFineDeposition) {
151  case CoarseFineDeposition::Interp: {
152  this->depositInterp<P, particleVectorField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
153 
154  break;
155  }
156  case CoarseFineDeposition::Halo: {
157  this->depositHalo<P, particleVectorField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
158 
159  break;
160  }
161  case CoarseFineDeposition::HaloNGP: {
162  this->depositHaloNGP<P, particleVectorField>(a_meshData, a_particles, a_depositionType, a_forceIrregNGP);
163 
164  break;
165  }
166  default: {
167  MayDay::Error("EBAMRParticleMesh::deposit(RealVect) - logic bust");
168 
169  break;
170  }
171  }
172 }
173 
174 template <class P, const Real& (P::*particleScalarField)() const>
175 void
177  const ParticleContainer<P>& a_particles,
178  const DepositionType a_depositionType,
179  const bool a_forceIrregNGP)
180 {
181  CH_TIME("EBAMRParticleMesh::depositInterp");
182 
183  CH_assert(a_meshData[0]->nComp() == 1);
184 
185  // TLDR: On each level the particles are deposited as usual. This routine assumes that none of the fine-level particles
186  // have deposition clouds that hang over the refinement boundary, so there is no fine-to-coarse mass transfer from
187  // fine-level particles. On the coarse level the particles might have deposition clouds that extend beneath the
188  // fine grid. That mass needs to find it's way into the fine level. The way we handle this is that we do piecewise
189  // constant interpolation of the coarse-grid data to the fine grid.
190 
191  DataOps::setValue(a_meshData, 0.0);
192 
193  const Interval interv(0, 0);
194 
195  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
196  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
197  const bool hasCoar = lvl > 0;
198  const DataIterator& dit = dbl.dataIterator();
199  const int nbox = dit.size();
200 
201  // 1. Deposit particles on this level.
202 #pragma omp parallel for schedule(runtime)
203  for (int mybox = 0; mybox < nbox; mybox++) {
204  const DataIndex& din = dit[mybox];
205 
206  EBCellFAB& meshData = (*a_meshData[lvl])[din];
207  const ListBox<P>& boxParticles = a_particles[lvl][din];
208 
209  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
210 
211  interp.deposit<P, particleScalarField>(boxParticles.listItems(), meshData, a_depositionType, a_forceIrregNGP);
212  }
213 
214  // 2. Exchange ghost data on this level. After this, all the mass should be on the current level.
215  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
216 
217  // 3. If the particles deposited over the coarse-fine boundary, add the mass to the coarse level.
218  if (hasCoar) {
219  m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
220  }
221 
222  // 4. The mass on the part of the coarse level underneath this grid should be added to this level. Fortunately,
223  // EBCoarseFineParticleMesh has buffers and functions that handle that type of interpolation.
224  if (hasCoar) {
225  m_coarseFinePM[lvl]->addInvalidCoarseToFine(*a_meshData[lvl], *a_meshData[lvl - 1]);
226  }
227  }
228 }
229 
230 template <class P, Real (P::*particleScalarField)() const>
231 void
233  const ParticleContainer<P>& a_particles,
234  const DepositionType a_depositionType,
235  const bool a_forceIrregNGP)
236 {
237  CH_TIME("EBAMRParticleMesh::depositInterp");
238 
239  CH_assert(a_meshData[0]->nComp() == 1);
240 
241  // TLDR: On each level the particles are deposited as usual. This routine assumes that none of the fine-level particles
242  // have deposition clouds that hang over the refinement boundary, so there is no fine-to-coarse mass transfer from
243  // fine-level particles. On the coarse level the particles might have deposition clouds that extend beneath the
244  // fine grid. That mass needs to find it's way into the fine level. The way we handle this is that we do piecewise
245  // constant interpolation of the coarse-grid data to the fine grid.
246 
247  DataOps::setValue(a_meshData, 0.0);
248 
249  const Interval interv(0, 0);
250 
251  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
252  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
253  const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
254  const DataIterator& dit = dbl.dataIterator();
255  const bool hasCoar = lvl > 0;
256 
257  // 1. Deposit particles on this level.
258  const int nbox = dit.size();
259 #pragma omp parallel for schedule(runtime)
260  for (int mybox = 0; mybox < nbox; mybox++) {
261  const DataIndex& din = dit[mybox];
262 
263  EBCellFAB& meshData = (*a_meshData[lvl])[din];
264  const ListBox<P>& boxParticles = a_particles[lvl][din];
265 
266  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
267 
268  interp.deposit<P, particleScalarField>(boxParticles.listItems(), meshData, a_depositionType, a_forceIrregNGP);
269  }
270 
271  // 2. Exchange ghost data on this level. After this, all the mass should be on the current level.
272  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
273 
274  // 3. If the particles deposited over the coarse-fine boundary, add the mass to the coarse level.
275  if (hasCoar) {
276  m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
277  }
278 
279  // 4. The mass on the part of the coarse level underneath this grid should be added to this level. Fortunately,
280  // EBCoarseFineParticleMesh has buffers and functions that handle that type of interpolation.
281  if (hasCoar) {
282  m_coarseFinePM[lvl]->addInvalidCoarseToFine(*a_meshData[lvl], *a_meshData[lvl - 1]);
283  }
284  }
285 }
286 
287 template <class P, const Real& (P::*particleScalarField)() const>
288 void
290  const ParticleContainer<P>& a_particles,
291  const DepositionType a_depositionType,
292  const bool a_forceIrregNGP)
293 {
294  CH_TIME("EBAMRParticleMesh::depositHalo");
295 
296  CH_assert(a_meshData[0]->nComp() == 1);
297 
298  // TLDR: On each level the particles are deposited as usual. This routine permits particles to live right next to the refinement boundary
299  // so both the coarse-level and fine-level particles have clouds that hang into the fine/coarse level. The way we handle this is as follows:
300  // The fine-level particles will have deposited into ghost cells that lie around the refinement boundary. This mass is put on the coarse grid.
301  // On the coarse level the particles have clouds that extend beneath the fine grid. Instead of interpolating this mass to the fine grid we
302  // run a special deposition procedure which allows us to deposit directly on the fine grid using 2x or 4x the particle width (depending on the
303  // refinement ratio).
304 
305  DataOps::setValue(a_meshData, 0.0);
306 
307  const Interval interv(0, 0);
308 
309  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
310  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
311  const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
312  const DataIterator& dit = dbl.dataIterator();
313  const bool hasCoar = (lvl > 0);
314 
315  // 1. Deposit particles on this level.
316  const int nbox = dit.size();
317 #pragma omp parallel for schedule(runtime)
318  for (int mybox = 0; mybox < nbox; mybox++) {
319  const DataIndex& din = dit[mybox];
320 
321  EBCellFAB& meshData = (*a_meshData[lvl])[din];
322  const ListBox<P>& boxParticles = a_particles[lvl][din];
323 
324  // Note: EBParticleMesh construction is cheap.
325  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
326 
327  interp.deposit<P, particleScalarField>(boxParticles.listItems(), meshData, a_depositionType, a_forceIrregNGP);
328  }
329 
330  // 2. Exchange ghost data on this level.
331  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
332 
333  // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
334  if (hasCoar) {
335  m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
336  }
337 
338  // 4. The particles on the other side of the refinement bounadry should deposit into this level.
339  if (hasCoar) {
340  // Particles that live "around" the refinment boundary. Must have
341  // been filled by the user.
342  const ParticleData<P>& coarHaloParticles = *a_particles.getMaskParticles()[lvl - 1];
343 
344  // Get the refined coarse grid stuff.
345  const int refRat = m_refRat[lvl - 1];
346  const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl]->getEblgFiCo();
347  const DisjointBoxLayout& dblFiCo = eblgFiCo.getDBL();
348  const EBISLayout& ebislFiCo = eblgFiCo.getEBISL();
349  const DataIterator& ditFiCo = dblFiCo.dataIterator();
350 
351  // Make a buffer we can deposit into.
352  LevelData<EBCellFAB> bufferFiCo(dblFiCo, 1, m_ghost, EBCellFactory(ebislFiCo));
353 
354  const int nboxFiCo = ditFiCo.size();
355 #pragma omp parallel for schedule(runtime)
356  for (int mybox = 0; mybox < nboxFiCo; mybox++) {
357  const DataIndex& din = ditFiCo[mybox];
358 
359  EBCellFAB& dataFiCo = bufferFiCo[din];
360  const ListBox<P>& haloParticles = coarHaloParticles[din];
361 
362  dataFiCo.setVal(0.0);
363 
364  const EBParticleMesh& interp = (*m_ebParticleMeshFiCo[lvl])[din];
365 
366  switch (refRat) {
367  case 2: {
368  interp.deposit2<P, particleScalarField>(haloParticles.listItems(),
369  dataFiCo,
370  a_depositionType,
371  a_forceIrregNGP);
372 
373  break;
374  }
375  case 4: {
376  interp.deposit4<P, particleScalarField>(haloParticles.listItems(),
377  dataFiCo,
378  a_depositionType,
379  a_forceIrregNGP);
380 
381  break;
382  }
383  default: {
384  MayDay::Error("CD_EBAMRParticleMeshImplem.H - logic bust in EBAMRParticleMesh::depositHalo(Real)");
385 
386  break;
387  }
388  }
389  }
390 
391  // Add the result of the buffer deposition to this level.
392  m_coarseFinePM[lvl]->addFiCoDataToFine(*a_meshData[lvl], bufferFiCo);
393  }
394  }
395 }
396 
397 template <class P, Real (P::*particleScalarField)() const>
398 void
400  const ParticleContainer<P>& a_particles,
401  const DepositionType a_depositionType,
402  const bool a_forceIrregNGP)
403 {
404  CH_TIME("EBAMRParticleMesh::depositHalo");
405 
406  CH_assert(a_meshData[0]->nComp() == 1);
407 
408  // TLDR: On each level the particles are deposited as usual. This routine permits particles to live right next to the refinement boundary
409  // so both the coarse-level and fine-level particles have clouds that hang into the fine/coarse level. The way we handle this is as follows:
410  // The fine-level particles will have deposited into ghost cells that lie around the refinement boundary. This mass is put on the coarse grid.
411  // On the coarse level the particles have clouds that extend beneath the fine grid. Instead of interpolating this mass to the fine grid we
412  // run a special deposition procedure which allows us to deposit directly on the fine grid using 2x or 4x the particle width (depending on the
413  // refinement ratio).
414 
415  DataOps::setValue(a_meshData, 0.0);
416 
417  const Interval interv(0, 0);
418 
419  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
420  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
421  const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
422  const DataIterator& dit = dbl.dataIterator();
423  const bool hasCoar = (lvl > 0);
424 
425  // 1. Deposit particles on this level.
426  const int nbox = dit.size();
427 #pragma omp parallel for schedule(runtime)
428  for (int mybox = 0; mybox < nbox; mybox++) {
429  const DataIndex& din = dit[mybox];
430 
431  EBCellFAB& meshData = (*a_meshData[lvl])[din];
432  const ListBox<P>& boxParticles = a_particles[lvl][din];
433 
434  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
435 
436  interp.deposit<P, particleScalarField>(boxParticles.listItems(), meshData, a_depositionType, a_forceIrregNGP);
437  }
438 
439  // 2. Exchange ghost data on this level.
440  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
441 
442  // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
443  if (hasCoar) {
444  m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
445  }
446 
447  // 4. The particles on the other side of the refinement bounadry should deposit into this level.
448  if (hasCoar) {
449  // Particles that live "around" the refinment boundary. Must have
450  // been filled by the user.
451  const ParticleData<P>& coarHaloParticles = *a_particles.getMaskParticles()[lvl - 1];
452 
453  // Get the refined coarse grid stuff.
454  const int refRat = m_refRat[lvl - 1];
455  const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl]->getEblgFiCo();
456  const DisjointBoxLayout& dblFiCo = eblgFiCo.getDBL();
457  const EBISLayout& ebislFiCo = eblgFiCo.getEBISL();
458  const DataIterator& ditFiCo = dblFiCo.dataIterator();
459 
460  // Make a buffer we can deposit into.
461  LevelData<EBCellFAB> bufferFiCo(dblFiCo, 1, m_ghost, EBCellFactory(ebislFiCo));
462 
463  const int nboxFiCo = ditFiCo.size();
464 #pragma omp parallel for schedule(runtime)
465  for (int mybox = 0; mybox < nboxFiCo; mybox++) {
466  const DataIndex& din = ditFiCo[mybox];
467 
468  EBCellFAB& dataFiCo = bufferFiCo[din];
469  const ListBox<P>& haloParticles = coarHaloParticles[din];
470 
471  dataFiCo.setVal(0.0);
472 
473  const EBParticleMesh& interp = (*m_ebParticleMeshFiCo[lvl])[din];
474 
475  switch (refRat) {
476  case 2: {
477  interp.deposit2<P, particleScalarField>(haloParticles.listItems(),
478  dataFiCo,
479  a_depositionType,
480  a_forceIrregNGP);
481 
482  break;
483  }
484  case 4: {
485  interp.deposit4<P, particleScalarField>(haloParticles.listItems(),
486  dataFiCo,
487  a_depositionType,
488  a_forceIrregNGP);
489 
490  break;
491  }
492  default: {
493  MayDay::Error("CD_EBAMRParticleMeshImplem.H - logic bust in EBAMRParticleMesh::depositHalo(Real)");
494 
495  break;
496  }
497  }
498  }
499 
500  // Add the result of the buffer deposition to this level.
501  m_coarseFinePM[lvl]->addFiCoDataToFine(*a_meshData[lvl], bufferFiCo);
502  }
503  }
504 }
505 
506 template <class P, const Real& (P::*particleScalarField)() const>
507 void
509  const ParticleContainer<P>& a_particles,
510  const DepositionType a_depositionType,
511  const bool a_forceIrregNGP)
512 {
513  CH_TIME("EBAMRParticleMesh::depositHaloNGP");
514 
515  CH_assert(a_meshData[0]->nComp() == 1);
516 
517  DataOps::setValue(a_meshData, 0.0);
518 
519  const Interval interv(0, 0);
520 
521  // nonHaloParticles will get deposited with the 'a_depositionType' scheme and haloParticles with an NGP scheme
522  const AMRParticles<P>& nonHaloParticles = a_particles.getParticles();
523  const AMRParticles<P>& haloParticles = a_particles.getMaskParticles();
524 
525  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
526  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
527  const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
528  const DataIterator& dit = dbl.dataIterator();
529 
530  const bool hasCoar = (lvl > 0);
531 
532  // 1. Deposit particles on this level.
533  const int nbox = dit.size();
534 #pragma omp parallel for schedule(runtime)
535  for (int mybox = 0; mybox < nbox; mybox++) {
536  const DataIndex& din = dit[mybox];
537 
538  EBCellFAB& meshData = (*a_meshData[lvl])[din];
539  const ListBox<P>& particlesCloud = (*nonHaloParticles[lvl])[din];
540  const ListBox<P>& particlesNGP = (*haloParticles[lvl])[din];
541 
542  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
543 
544  interp.deposit<P, particleScalarField>(particlesCloud.listItems(), meshData, a_depositionType, a_forceIrregNGP);
545  interp.deposit<P, particleScalarField>(particlesNGP.listItems(), meshData, DepositionType::NGP, a_forceIrregNGP);
546  }
547 
548  // 2. Exchange ghost data on this level.
549  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
550 
551  // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
552  if (hasCoar) {
553  m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
554  }
555  }
556 }
557 
558 template <class P, Real (P::*particleScalarField)() const>
559 void
561  const ParticleContainer<P>& a_particles,
562  const DepositionType a_depositionType,
563  const bool a_forceIrregNGP)
564 {
565  CH_TIME("EBAMRParticleMesh::depositHaloNGP");
566 
567  CH_assert(a_meshData[0]->nComp() == 1);
568 
569  DataOps::setValue(a_meshData, 0.0);
570 
571  const Interval interv(0, 0);
572 
573  // nonHaloParticles will get deposited with the 'a_depositionType' scheme and haloParticles with an NGP scheme
574  const AMRParticles<P>& nonHaloParticles = a_particles.getParticles();
575  const AMRParticles<P>& haloParticles = a_particles.getMaskParticles();
576 
577  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
578  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
579  const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
580  const DataIterator& dit = dbl.dataIterator();
581 
582  const bool hasCoar = (lvl > 0);
583 
584  // 1. Deposit particles on this level.
585  const int nbox = dit.size();
586 #pragma omp parallel for schedule(runtime)
587  for (int mybox = 0; mybox < nbox; mybox++) {
588  const DataIndex& din = dit[mybox];
589 
590  EBCellFAB& meshData = (*a_meshData[lvl])[din];
591  const ListBox<P>& particlesCloud = (*nonHaloParticles[lvl])[din];
592  const ListBox<P>& particlesNGP = (*haloParticles[lvl])[din];
593 
594  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
595 
596  interp.deposit<P, particleScalarField>(particlesCloud.listItems(), meshData, a_depositionType, a_forceIrregNGP);
597  interp.deposit<P, particleScalarField>(particlesNGP.listItems(), meshData, DepositionType::NGP, a_forceIrregNGP);
598  }
599 
600  // 2. Exchange ghost data on this level.
601  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
602 
603  // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
604  if (hasCoar) {
605  m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
606  }
607  }
608 }
609 
610 template <class P, Real& (P::*particleScalarField)()>
611 void
613  const EBAMRCellData& a_meshScalarField,
614  const DepositionType a_interpType,
615  const bool a_forceIrregNGP) const
616 {
617  CH_TIME("EBAMRParticleMesh::interpolate(scalar)");
618 
619  CH_assert(m_isDefined);
620 
621  // TLDR: Run through each patch and interpolate to the particle positions.
622 
623  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
624  const EBLevelGrid& eblg = *m_eblgs[lvl];
625  const DisjointBoxLayout& dbl = eblg.getDBL();
626  const EBISLayout& ebisl = eblg.getEBISL();
627  const DataIterator& dit = dbl.dataIterator();
628 
629  CH_assert(a_meshScalarField[lvl]->nComp() == 1);
630 
631  const int nbox = dit.size();
632 #pragma omp parallel for schedule(runtime)
633  for (int mybox = 0; mybox < nbox; mybox++) {
634  const DataIndex& din = dit[mybox];
635 
636  List<P>& particles = a_particles[lvl][din].listItems();
637 
638  const EBCellFAB& data = (*a_meshScalarField[lvl])[din];
639  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
640 
641  interp.interpolate<P, particleScalarField>(particles, data, a_interpType, a_forceIrregNGP);
642  }
643  }
644 }
645 
646 template <class P, RealVect& (P::*particleVectorField)()>
647 void
649  const EBAMRCellData& a_meshVectorField,
650  const DepositionType a_interpType,
651  const bool a_forceIrregNGP) const
652 {
653  CH_TIME("EBAMRParticleMesh::interpolate(vector)");
654 
655  CH_assert(m_isDefined);
656 
657  // TLDR: Run through each patch and interpolate to the particle positions.
658 
659  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
660  const EBLevelGrid& eblg = *m_eblgs[lvl];
661  const DisjointBoxLayout& dbl = eblg.getDBL();
662  const ProblemDomain& domain = eblg.getDomain();
663  const EBISLayout& ebisl = eblg.getEBISL();
664  const Real& dx = m_dx[lvl];
665  const DataIterator& dit = dbl.dataIterator();
666 
667  CH_assert(a_meshVectorField[lvl]->nComp() == SpaceDim);
668 
669  const int nbox = dit.size();
670 #pragma omp parallel for schedule(runtime)
671  for (int mybox = 0; mybox < nbox; mybox++) {
672  const DataIndex& din = dit[mybox];
673 
674  List<P>& particles = a_particles[lvl][din].listItems();
675 
676  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
677  const EBCellFAB& data = (*a_meshVectorField[lvl])[din];
678 
679  interp.interpolate<P, particleVectorField>(particles, data, a_interpType, a_forceIrregNGP);
680  }
681  }
682 }
683 
684 template <class P, const RealVect& (P::*particleVectorField)() const>
685 void
687  const ParticleContainer<P>& a_particles,
688  const DepositionType a_depositionType,
689  const bool a_forceIrregNGP)
690 {
691  CH_TIME("EBAMRParticleMesh::depositInterp");
692 
693  CH_assert(a_meshData[0]->nComp() == SpaceDim);
694 
695  DataOps::setValue(a_meshData, 0.0);
696 
697  const Interval interv(0, 0);
698 
699  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
700  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
701  const DataIterator& dit = dbl.dataIterator();
702  const bool hasCoar = lvl > 0;
703 
704  // 1. Deposit particles on this level.
705  const int nbox = dit.size();
706 #pragma omp parallel for schedule(runtime)
707  for (int mybox = 0; mybox < nbox; mybox++) {
708  const DataIndex& din = dit[mybox];
709 
710  EBCellFAB& meshData = (*a_meshData[lvl])[din];
711  const ListBox<P>& boxParticles = a_particles[lvl][din];
712 
713  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
714 
715  interp.deposit<P, particleVectorField>(boxParticles.listItems(), meshData, a_depositionType, a_forceIrregNGP);
716  }
717 
718  // 2. Exchange ghost data on this level. After this, all the mass should be on the current level.
719  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
720 
721  // 3. If the particles deposited over the coarse-fine boundary, add the mass to the coarse level. Since
722  // the coarse-fine choreography buffer only uses a single component in the memory, we need to alias the data.
723  if (hasCoar) {
724  for (int dir = 0; dir < SpaceDim; dir++) {
725  LevelData<EBCellFAB> coarAlias;
726  LevelData<EBCellFAB> fineAlias;
727 
728  // This lets coarAlias be a 1-component data holder which references the dir-component
729  // in a_meshData.
730  aliasLevelData<EBCellFAB>(coarAlias, &(*a_meshData[lvl - 1]), Interval(dir, dir));
731  aliasLevelData<EBCellFAB>(fineAlias, &(*a_meshData[lvl]), Interval(dir, dir));
732 
733  // Add the mass that hangs from the fine level and over the refinement boundary onto the coarse level.
734  m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
735 
736  // Likewise, take the particles that deposited mass to underneath the current level
737  // and put that mas on the fine level.
738  m_coarseFinePM[lvl]->addInvalidCoarseToFine(fineAlias, coarAlias);
739  }
740  }
741  }
742 }
743 
744 template <class P, RealVect (P::*particleVectorField)() const>
745 void
747  const ParticleContainer<P>& a_particles,
748  const DepositionType a_depositionType,
749  const bool a_forceIrregNGP)
750 {
751  CH_TIME("EBAMRParticleMesh::depositInterp");
752 
753  CH_assert(a_meshData[0]->nComp() == SpaceDim);
754 
755  DataOps::setValue(a_meshData, 0.0);
756 
757  const Interval interv(0, 0);
758 
759  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
760  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
761  const DataIterator& dit = dbl.dataIterator();
762  const bool hasCoar = lvl > 0;
763 
764  // 1. Deposit particles on this level.
765  const int nbox = dit.size();
766 #pragma omp parallel for schedule(runtime)
767  for (int mybox = 0; mybox < nbox; mybox++) {
768  const DataIndex& din = dit[mybox];
769 
770  EBCellFAB& meshData = (*a_meshData[lvl])[din];
771  const ListBox<P>& boxParticles = a_particles[lvl][din];
772  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
773 
774  interp.deposit<P, particleVectorField>(boxParticles.listItems(), meshData, a_depositionType, a_forceIrregNGP);
775  }
776 
777  // 2. Exchange ghost data on this level. After this, all the mass should be on the current level.
778  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
779 
780  // 3. If the particles deposited over the coarse-fine boundary, add the mass to the coarse level. Since
781  // the coarse-fine choreography buffer only uses a single component in the memory, we need to alias the data.
782  if (hasCoar) {
783  for (int dir = 0; dir < SpaceDim; dir++) {
784  LevelData<EBCellFAB> coarAlias;
785  LevelData<EBCellFAB> fineAlias;
786 
787  // This lets coarAlias be a 1-component data holder which references the dir-component
788  // in a_meshData.
789  aliasLevelData<EBCellFAB>(coarAlias, &(*a_meshData[lvl - 1]), Interval(dir, dir));
790  aliasLevelData<EBCellFAB>(fineAlias, &(*a_meshData[lvl]), Interval(dir, dir));
791 
792  // Add the mass that hangs from the fine level and over the refinement boundary onto the coarse level.
793  m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
794 
795  // Likewise, take the particles that deposited mass to underneath the current level
796  // and put that mas on the fine level.
797  m_coarseFinePM[lvl]->addInvalidCoarseToFine(fineAlias, coarAlias);
798  }
799  }
800  }
801 }
802 
803 template <class P, const RealVect& (P::*particleVectorField)() const>
804 void
806  const ParticleContainer<P>& a_particles,
807  const DepositionType a_depositionType,
808  const bool a_forceIrregNGP)
809 {
810  CH_TIME("EBAMRParticleMesh::depositHalo(RealVect)");
811 
812  CH_assert(a_meshData[0]->nComp() == SpaceDim);
813 
814  DataOps::setValue(a_meshData, 0.0);
815 
816  const Interval interv(0, 0);
817 
818  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
819  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
820  const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
821  const DataIterator& dit = dbl.dataIterator();
822 
823  const bool hasCoar = (lvl > 0);
824 
825  // 1. Deposit particles on this level.
826  const int nbox = dit.size();
827 #pragma omp parallel for schedule(runtime)
828  for (int mybox = 0; mybox < nbox; mybox++) {
829  const DataIndex& din = dit[mybox];
830 
831  EBCellFAB& meshData = (*a_meshData[lvl])[din];
832  const ListBox<P>& boxParticles = a_particles[lvl][din];
833 
834  // Note: EBParticleMesh construction is cheap.
835  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
836 
837  interp.deposit<P, particleVectorField>(boxParticles.listItems(), meshData, a_depositionType, a_forceIrregNGP);
838  }
839 
840  // 2. Exchange ghost data on this level.
841  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
842 
843  // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
844  if (hasCoar) {
845  m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
846  }
847 
848  // 4. The particles on the other side of the refinement bounadry should deposit into this level.
849  if (hasCoar) {
850  // Particles that live "around" the refinment boundary. Must have
851  // been filled by the user.
852  const ParticleData<P>& coarHaloParticles = *a_particles.getMaskParticles()[lvl - 1];
853 
854  // Get the refined coarse grid stuff.
855  const int refRat = m_refRat[lvl - 1];
856  const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl]->getEblgFiCo();
857  const DisjointBoxLayout& dblFiCo = eblgFiCo.getDBL();
858  const EBISLayout& ebislFiCo = eblgFiCo.getEBISL();
859  const DataIterator& ditFiCo = dblFiCo.dataIterator();
860 
861  // Make a buffer we can deposit into.
862  LevelData<EBCellFAB> bufferFiCo(dblFiCo, SpaceDim, m_ghost, EBCellFactory(ebislFiCo));
863 
864  const int nboxFiCo = ditFiCo.size();
865 #pragma omp parallel for schedule(runtime)
866  for (int mybox = 0; mybox < nboxFiCo; mybox++) {
867  const DataIndex& din = ditFiCo[mybox];
868 
869  EBCellFAB& dataFiCo = bufferFiCo[din];
870  const ListBox<P>& haloParticles = coarHaloParticles[din];
871 
872  dataFiCo.setVal(0.0);
873 
874  const EBParticleMesh& interp = (*m_ebParticleMeshFiCo[lvl])[din];
875 
876  switch (refRat) {
877  case 2: {
878  interp.deposit2<P, particleVectorField>(haloParticles.listItems(),
879  dataFiCo,
880  a_depositionType,
881  a_forceIrregNGP);
882 
883  break;
884  }
885  case 4: {
886  interp.deposit4<P, particleVectorField>(haloParticles.listItems(),
887  dataFiCo,
888  a_depositionType,
889  a_forceIrregNGP);
890 
891  break;
892  }
893  default: {
894  MayDay::Error("CD_EBAMRParticleMeshImplem.H - logic bust in EBAMRParticleMesh::depositHalo(RealVect)");
895 
896  break;
897  }
898  }
899  }
900 
901  // Add the result of the buffer deposition to this level. The buffer above had SpaceDim
902  // components but coarseFinePM works with only one component, so we just alias the data.
903  for (int dir = 0; dir < SpaceDim; dir++) {
904  LevelData<EBCellFAB> meshDataAlias;
905  LevelData<EBCellFAB> bufferFiCoAlias;
906 
907  aliasLevelData<EBCellFAB>(meshDataAlias, &(*a_meshData[lvl]), Interval(dir, dir));
908  aliasLevelData<EBCellFAB>(bufferFiCoAlias, &bufferFiCo, Interval(dir, dir));
909 
910  m_coarseFinePM[lvl]->addFiCoDataToFine(meshDataAlias, bufferFiCoAlias);
911  }
912  }
913  }
914 }
915 
916 template <class P, RealVect (P::*particleVectorField)() const>
917 void
919  const ParticleContainer<P>& a_particles,
920  const DepositionType a_depositionType,
921  const bool a_forceIrregNGP)
922 {
923  CH_TIME("EBAMRParticleMesh::depositHalo(RealVect)");
924 
925  CH_assert(a_meshData[0]->nComp() == SpaceDim);
926 
927  DataOps::setValue(a_meshData, 0.0);
928 
929  const Interval interv(0, 0);
930 
931  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
932  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
933  const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
934  const DataIterator& dit = dbl.dataIterator();
935 
936  const bool hasCoar = (lvl > 0);
937 
938  // 1. Deposit particles on this level.
939  const int nbox = dit.size();
940 #pragma omp parallel for schedule(runtime)
941  for (int mybox = 0; mybox < nbox; mybox++) {
942  const DataIndex& din = dit[mybox];
943 
944  EBCellFAB& meshData = (*a_meshData[lvl])[din];
945  const ListBox<P>& boxParticles = a_particles[lvl][din];
946 
947  // Note: EBParticleMesh construction is cheap.
948  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
949 
950  interp.deposit<P, particleVectorField>(boxParticles.listItems(), meshData, a_depositionType, a_forceIrregNGP);
951  }
952 
953  // 2. Exchange ghost data on this level.
954  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
955 
956  // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
957  if (hasCoar) {
958  m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
959  }
960 
961  // 4. The particles on the other side of the refinement bounadry should deposit into this level.
962  if (hasCoar) {
963  // Particles that live "around" the refinment boundary. Must have
964  // been filled by the user.
965  const ParticleData<P>& coarHaloParticles = *a_particles.getMaskParticles()[lvl - 1];
966 
967  // Get the refined coarse grid stuff.
968  const int refRat = m_refRat[lvl - 1];
969  const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl]->getEblgFiCo();
970  const DisjointBoxLayout& dblFiCo = eblgFiCo.getDBL();
971  const EBISLayout& ebislFiCo = eblgFiCo.getEBISL();
972  const DataIterator& ditFiCo = dblFiCo.dataIterator();
973 
974  // Make a buffer we can deposit into.
975  LevelData<EBCellFAB> bufferFiCo(dblFiCo, SpaceDim, m_ghost, EBCellFactory(ebislFiCo));
976 
977  const int nboxFiCo = ditFiCo.size();
978 #pragma omp parallel for schedule(runtime)
979  for (int mybox = 0; mybox < nboxFiCo; mybox++) {
980  const DataIndex& din = ditFiCo[mybox];
981 
982  EBCellFAB& dataFiCo = bufferFiCo[din];
983  const ListBox<P>& haloParticles = coarHaloParticles[din];
984 
985  dataFiCo.setVal(0.0);
986 
987  const EBParticleMesh& interp = (*m_ebParticleMeshFiCo[lvl])[din];
988 
989  switch (refRat) {
990  case 2: {
991  interp.deposit2<P, particleVectorField>(haloParticles.listItems(),
992  dataFiCo,
993  a_depositionType,
994  a_forceIrregNGP);
995 
996  break;
997  }
998  case 4: {
999  interp.deposit4<P, particleVectorField>(haloParticles.listItems(),
1000  dataFiCo,
1001  a_depositionType,
1002  a_forceIrregNGP);
1003 
1004  break;
1005  }
1006  default: {
1007  MayDay::Error("CD_EBAMRParticleMeshImplem.H - logic bust in EBAMRParticleMesh::depositHalo(RealVect)");
1008 
1009  break;
1010  }
1011  }
1012  }
1013 
1014  // Add the result of the buffer deposition to this level. The buffer above had SpaceDim
1015  // components but coarseFinePM works with only one component, so we just alias the data.
1016  for (int dir = 0; dir < SpaceDim; dir++) {
1017  LevelData<EBCellFAB> meshDataAlias;
1018  LevelData<EBCellFAB> bufferFiCoAlias;
1019 
1020  aliasLevelData<EBCellFAB>(meshDataAlias, &(*a_meshData[lvl]), Interval(dir, dir));
1021  aliasLevelData<EBCellFAB>(bufferFiCoAlias, &bufferFiCo, Interval(dir, dir));
1022 
1023  m_coarseFinePM[lvl]->addFiCoDataToFine(meshDataAlias, bufferFiCoAlias);
1024  }
1025  }
1026  }
1027 }
1028 
1029 template <class P, const RealVect& (P::*particleVectorField)() const>
1030 void
1032  const ParticleContainer<P>& a_particles,
1033  const DepositionType a_depositionType,
1034  const bool a_forceIrregNGP)
1035 {
1036  CH_TIME("EBAMRParticleMesh::depositHaloNGP");
1037 
1038  CH_assert(a_meshData[0]->nComp() == SpaceDim);
1039 
1040  // TLDR: On each level the particles are deposited as usual. This routine permits particles to live right next to the refinement boundary
1041  // so both the coarse-level and fine-level particles have clouds that hang into the fine/coarse level. The way we handle this is as follows:
1042  // The fine-level particles will have deposited into ghost cells that lie around the refinement boundary. This mass is put on the coarse grid.
1043  // On the coarse level the particles have clouds that extend beneath the fine grid. Instead of interpolating this mass to the fine grid we
1044  // run a special deposition procedure which allows us to deposit directly on the fine grid using 2x or 4x the particle width (depending on the
1045  // refinement ratio).
1046 
1047  DataOps::setValue(a_meshData, 0.0);
1048 
1049  const Interval interv(0, 0);
1050 
1051  // nonHaloParticles will get deposited with the 'a_depositionType' scheme and haloParticles with an NGP scheme
1052  const AMRParticles<P>& nonHaloParticles = a_particles.getParticles();
1053  const AMRParticles<P>& haloParticles = a_particles.getMaskParticles();
1054 
1055  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
1056  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
1057  const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
1058  const DataIterator& dit = dbl.dataIterator();
1059 
1060  const bool hasCoar = (lvl > 0);
1061 
1062  // 1. Deposit particles on this level.
1063  const int nbox = dit.size();
1064 #pragma omp parallel for schedule(runtime)
1065  for (int mybox = 0; mybox < nbox; mybox++) {
1066  const DataIndex& din = dit[mybox];
1067 
1068  EBCellFAB& meshData = (*a_meshData[lvl])[din];
1069  const ListBox<P>& particlesCloud = (*nonHaloParticles[lvl])[din];
1070  const ListBox<P>& particlesNGP = (*haloParticles[lvl])[din];
1071 
1072  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
1073 
1074  interp.deposit<P, particleVectorField>(particlesCloud.listItems(), meshData, a_depositionType, a_forceIrregNGP);
1075  interp.deposit<P, particleVectorField>(particlesNGP.listItems(), meshData, DepositionType::NGP, a_forceIrregNGP);
1076  }
1077 
1078  // 2. Exchange ghost data on this level.
1079  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
1080 
1081  // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
1082  if (hasCoar) {
1083 
1084  // Because m_coarseFinePM works with one component but we have SpaceDim.
1085  for (int dir = 0; dir < SpaceDim; dir++) {
1086  LevelData<EBCellFAB> coarAlias;
1087  LevelData<EBCellFAB> fineAlias;
1088 
1089  // This lets coarAlias be a 1-component data holder which references the dir-component
1090  // in a_meshData.
1091  aliasLevelData<EBCellFAB>(coarAlias, &(*a_meshData[lvl - 1]), Interval(dir, dir));
1092  aliasLevelData<EBCellFAB>(fineAlias, &(*a_meshData[lvl]), Interval(dir, dir));
1093 
1094  // Average data in the fine-level ghost cells and add it to the coarse level.
1095  m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
1096  }
1097  }
1098  }
1099 }
1100 
1101 template <class P, RealVect (P::*particleVectorField)() const>
1102 void
1104  const ParticleContainer<P>& a_particles,
1105  const DepositionType a_depositionType,
1106  const bool a_forceIrregNGP)
1107 {
1108  CH_TIME("EBAMRParticleMesh::depositHaloNGP");
1109 
1110  CH_assert(a_meshData[0]->nComp() == SpaceDim);
1111 
1112  // TLDR: On each level the particles are deposited as usual. This routine permits particles to live right next to the refinement boundary
1113  // so both the coarse-level and fine-level particles have clouds that hang into the fine/coarse level. The way we handle this is as follows:
1114  // The fine-level particles will have deposited into ghost cells that lie around the refinement boundary. This mass is put on the coarse grid.
1115  // On the coarse level the particles have clouds that extend beneath the fine grid. Instead of interpolating this mass to the fine grid we
1116  // run a special deposition procedure which allows us to deposit directly on the fine grid using 2x or 4x the particle width (depending on the
1117  // refinement ratio).
1118 
1119  DataOps::setValue(a_meshData, 0.0);
1120 
1121  const Interval interv(0, 0);
1122 
1123  // nonHaloParticles will get deposited with the 'a_depositionType' scheme and haloParticles with an NGP scheme
1124  const AMRParticles<P>& nonHaloParticles = a_particles.getParticles();
1125  const AMRParticles<P>& haloParticles = a_particles.getMaskParticles();
1126 
1127  for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
1128  const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
1129  const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
1130  const DataIterator& dit = dbl.dataIterator();
1131 
1132  const bool hasCoar = (lvl > 0);
1133 
1134  // 1. Deposit particles on this level.
1135  const int nbox = dit.size();
1136 #pragma omp parallel for schedule(runtime)
1137  for (int mybox = 0; mybox < nbox; mybox++) {
1138  const DataIndex& din = dit[mybox];
1139 
1140  EBCellFAB& meshData = (*a_meshData[lvl])[din];
1141  const ListBox<P>& particlesCloud = (*nonHaloParticles[lvl])[din];
1142  const ListBox<P>& particlesNGP = (*haloParticles[lvl])[din];
1143 
1144  const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
1145 
1146  interp.deposit<P, particleVectorField>(particlesCloud.listItems(), meshData, a_depositionType, a_forceIrregNGP);
1147  interp.deposit<P, particleVectorField>(particlesNGP.listItems(), meshData, DepositionType::NGP, a_forceIrregNGP);
1148  }
1149 
1150  // 2. Exchange ghost data on this level.
1151  a_meshData[lvl]->exchange(interv, m_levelCopiers[lvl], EBAddOp());
1152 
1153  // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
1154  if (hasCoar) {
1155 
1156  // Because m_coarseFinePM works with one component but we have SpaceDim.
1157  for (int dir = 0; dir < SpaceDim; dir++) {
1158  LevelData<EBCellFAB> coarAlias;
1159  LevelData<EBCellFAB> fineAlias;
1160 
1161  // This lets coarAlias be a 1-component data holder which references the dir-component
1162  // in a_meshData.
1163  aliasLevelData<EBCellFAB>(coarAlias, &(*a_meshData[lvl - 1]), Interval(dir, dir));
1164  aliasLevelData<EBCellFAB>(fineAlias, &(*a_meshData[lvl]), Interval(dir, dir));
1165 
1166  // Average data in the fine-level ghost cells and add it to the coarse level.
1167  m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
1168  }
1169  }
1170  }
1171 }
1172 
1173 #include <CD_NamespaceFooter.H>
1174 
1175 #endif
CoarseFineDeposition
Coarse-fine deposition types (see CD_EBAMRParticleMesh for how these are handled).
Definition: CD_CoarseFineDeposition.H:26
Agglomeration of useful data operations.
DepositionType
Deposition types.
Definition: CD_DepositionType.H:23
Declaration of a class for handling particle-mesh operations with AMR.
Declaration of a Copier class for making incrementation between LevelData<EBCellFAB> easier.
Vector< RefCountedPtr< ParticleData< P > >> AMRParticles
Alias for ParticleData on each AMR level.
Definition: CD_ParticleContainer.H:34
static void setValue(LevelData< MFInterfaceFAB< T >> &a_lhs, const T &a_value)
Set value in an MFInterfaceFAB data holder.
Definition: CD_DataOpsImplem.H:23
void exchange() noexcept
Exchange on all AMR levels.
Definition: CD_EBAMRDataImplem.H:105
IntVect m_ghost
Number of ghost cells.
Definition: CD_EBAMRParticleMesh.H:262
Vector< RefCountedPtr< EBCoarseFineParticleMesh > > m_coarseFinePM
Buffers for handling arithmetic for mass moving from coarse to fine level and vice versa.
Definition: CD_EBAMRParticleMesh.H:305
Vector< Real > m_dx
Grid resolutions.
Definition: CD_EBAMRParticleMesh.H:287
void depositHaloNGP(EBAMRCellData &a_meshData, const ParticleContainer< P > &a_particles, const DepositionType a_depositionType, const bool a_forceIrregNGP=false)
Just like the deposit function, but forced to use the "HaloNGP" algorithm for handling refinement bou...
Definition: CD_EBAMRParticleMeshImplem.H:508
int m_finestLevel
Finest AMR level.
Definition: CD_EBAMRParticleMesh.H:272
void interpolate(ParticleContainer< P > &a_particles, const EBAMRCellData &a_meshVectorField, const DepositionType a_interpType, const bool a_forceIrregNGP=false) const
Interpolate a scalar field onto the particle position.
Definition: CD_EBAMRParticleMeshImplem.H:612
bool m_isDefined
Is defined or not.
Definition: CD_EBAMRParticleMesh.H:252
Vector< RefCountedPtr< LayoutData< EBParticleMesh > > > m_ebParticleMesh
Regular particle-mesh object on each grid level.
Definition: CD_EBAMRParticleMesh.H:292
Vector< RefCountedPtr< EBLevelGrid > > m_eblgs
Grids on each level.
Definition: CD_EBAMRParticleMesh.H:277
Vector< Copier > m_levelCopiers
Copier for moving data from valid+ghost to valid on each AMR level.
Definition: CD_EBAMRParticleMesh.H:311
void deposit(EBAMRCellData &a_meshData, const ParticleContainer< P > &a_particles, const DepositionType a_depositionType, const CoarseFineDeposition a_coarseFineDeposition, const bool a_forceIrregNGP=false)
Class for deposition of particles of a type P to the mesh. This does scalar quantities.
Definition: CD_EBAMRParticleMeshImplem.H:29
void depositInterp(EBAMRCellData &a_meshData, const ParticleContainer< P > &a_particles, const DepositionType a_depositionType, const bool a_forceIrregNGP=false)
Just like the deposit function, but forced to use the "PVR" algorithm for handling refinement boundar...
Definition: CD_EBAMRParticleMeshImplem.H:176
void depositHalo(EBAMRCellData &a_meshData, const ParticleContainer< P > &a_particles, const DepositionType a_depositionType, const bool a_forceIrregNGP=false)
Just like the deposit function, but forced to use the "Halo" algorithm for handling refinement bounda...
Definition: CD_EBAMRParticleMeshImplem.H:289
Vector< RefCountedPtr< LayoutData< EBParticleMesh > > > m_ebParticleMeshFiCo
Special particle-mesh objects for depositing on the coarsened fine grid.
Definition: CD_EBAMRParticleMesh.H:299
Vector< int > m_refRat
Refinement ratios between levels.
Definition: CD_EBAMRParticleMesh.H:282
A Copier class for making copying between BoxLayoutData<EBCellFAB> easier. This increments EBCellFABs...
Definition: CD_EBAddOp.H:26
A class for depositing and interpolating particles. Contains various useful routines for interpolatio...
Definition: CD_EBParticleMesh.H:34
void interpolate(List< P > &a_particleList, const EBCellFAB &a_meshScalarField, const DepositionType a_interpType, const bool a_forceIrregNGP=false) const
Interpolate a scalar field onto the particle position.
Definition: CD_EBParticleMeshImplem.H:340
void deposit2(const List< P > &a_particleList, EBCellFAB &a_rho, const DepositionType a_depositionType, const bool a_forceIrregNGP=false) const
Deposit particle onto the mesh using twice the standard cloud width.
Definition: CD_EBParticleMeshImplem.H:67
void deposit4(const List< P > &a_particleList, EBCellFAB &a_rho, const DepositionType a_depositionType, const bool a_forceIrregNGP=false) const
Deposit particle onto the mesh using 4x the standard cloud width.
Definition: CD_EBParticleMeshImplem.H:121
void deposit(const List< P > &a_particleList, EBCellFAB &a_rho, const DepositionType a_depositionType, const bool a_forceIrregNGP=false) const
Deposit particle onto the mesh using a standard cloud width.
Definition: CD_EBParticleMeshImplem.H:25
Templated class for holding particles on an AMR hierarchy with particle remapping.
Definition: CD_ParticleContainer.H:50
AMRParticles< P > & getMaskParticles()
Get the mask particles.
Definition: CD_ParticleContainerImplem.H:314
AMRParticles< P > & getParticles()
Get all particles on all levels.
Definition: CD_ParticleContainerImplem.H:270