chombo-discharge
Loading...
Searching...
No Matches
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
23#include <CD_EBAddOp.H>
24#include <CD_DataOps.H>
25#include <CD_NamespaceHeader.H>
26
27template <class P, class Ret, Ret (P::*MemberFunc)() const>
28void
33 const bool a_forceIrregNGP)
34{
35 CH_TIME("EBAMRParticleMesh::deposit");
36 if (m_verbose) {
37 pout() << "EBAMRParticleMesh::deposit" << endl;
38 }
39
40 switch (a_coarseFineDeposition) {
41 case CoarseFineDeposition::Interp: {
43
44 break;
45 }
46 case CoarseFineDeposition::Halo: {
48
49 break;
50 }
51 case CoarseFineDeposition::HaloNGP: {
53
54 break;
55 }
56 case CoarseFineDeposition::Transition: {
58
59 break;
60 }
61 default: {
62 MayDay::Error("EBAMRParticleMesh::deposit - logic bust");
63
64 break;
65 }
66 }
67}
68
69template <class P, class Ret, Ret (P::*MemberFunc)() const>
70void
74 const bool a_forceIrregNGP)
75{
76 CH_TIME("EBAMRParticleMesh::depositInterp");
77 if (m_verbose) {
78 pout() << "EBAMRParticleMesh::depositInterp" << endl;
79 }
80
81 constexpr int numComp = EBParticleMesh::sanitize<Ret>();
82
83 CH_assert(a_meshData[0]->nComp() == numComp);
84
85 // Reset mesh data
87
88 // Start deposition loop
89 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
90 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
91 const DataIterator& dit = dbl.dataIterator();
92 const bool hasCoar = (lvl > 0);
93
94 // 1. Deposit particles on this level.
95 const int numBoxes = dit.size();
96#pragma omp parallel for schedule(runtime)
97 for (int mybox = 0; mybox < numBoxes; mybox++) {
98 const DataIndex& din = dit[mybox];
100 const List<P>& particles = a_particles[lvl][din].listItems();
101
103
105 }
106
107 // 2. Exchange ghost data on this level. After this, all the mass should be on the current level.
108 a_meshData[lvl]->exchange(Interval(0, numComp - 1), m_levelCopiers[lvl], EBAddOp());
109
110 // 3. If the particles deposited over the coarse-fine boundary, add the mass to the coarse level. Since
111 // the coarse-fine choreography buffer only uses a single component in the memory, we need to alias the data.
112 if (hasCoar) {
113 for (int comp = 0; comp < numComp; comp++) {
116
117 // This lets coarAlias be a 1-component data holder which references the dir-component
118 // in a_meshData.
121
122 // Add the mass that hangs from the fine level and over the refinement boundary onto the coarse level.
123 m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
124
125 // Likewise, take the particles that deposited mass to underneath the current level
126 // and put that mas on the fine level.
127 m_coarseFinePM[lvl]->addInvalidCoarseToFine(fineAlias, coarAlias);
128 }
129 }
130 }
131}
132
133template <class P, class Ret, Ret (P::*MemberFunc)() const>
134void
138 const bool a_forceIrregNGP)
139{
140 CH_TIME("EBAMRParticleMesh::depositHalo");
141 if (m_verbose) {
142 pout() << "EBAMRParticleMesh::depositHalo" << endl;
143 }
144
145 constexpr int numComp = EBParticleMesh::sanitize<Ret>();
146
147 CH_assert(a_meshData[0]->nComp() == numComp);
148
149 // Reset mesh data
151
152 // Copy the required particles to the masked particle data holder.
153 constexpr int coarseMaskWidth = 1;
154
155 a_particles.copyMaskParticles(m_outerHaloMasks.at(coarseMaskWidth));
156
157 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
158 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
159 const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
160 const DataIterator& dit = dbl.dataIterator();
161
162 const bool hasCoar = (lvl > 0);
163
164 // 1. Deposit particles on this level.
165 const int numBoxes = dit.size();
166#pragma omp parallel for schedule(runtime)
167 for (int mybox = 0; mybox < numBoxes; mybox++) {
168 const DataIndex& din = dit[mybox];
170 const List<P>& particles = a_particles[lvl][din].listItems();
171
173
175 }
176
177 // 2. Exchange ghost data on this level.
178 a_meshData[lvl]->exchange(Interval(0, numComp - 1), m_levelCopiers[lvl], EBAddOp());
179
180 // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
181 if (hasCoar) {
182 m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
183 }
184
185 // 4. The particles on the other side of the refinement boundary should deposit into this level and also the coarser level.
186 if (hasCoar) {
187 const ParticleData<P>& coarHaloParticles = *a_particles.getMaskParticles()[lvl - 1];
188
189 // Get the refined coarse grid stuff.
190 const int refRat = m_refRat[lvl - 1];
191 const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl]->getEblgFiCo();
192 const DisjointBoxLayout& dblFiCo = eblgFiCo.getDBL();
193 const EBISLayout& ebislFiCo = eblgFiCo.getEBISL();
194 const DataIterator& ditFiCo = dblFiCo.dataIterator();
195
196 // Get a buffer we can deposit into
198
199 const int numBoxesFiCo = ditFiCo.size();
200#pragma omp parallel for schedule(runtime)
201 for (int mybox = 0; mybox < numBoxesFiCo; mybox++) {
202 const DataIndex& din = ditFiCo[mybox];
205
206 dataFiCo.setVal(0.0);
207
209
211 haloParticles.listItems(),
213 refRat,
215 }
216
217 // Add the result of the buffer deposition to this level. The buffer above could have more than one
218 // component, while coarseFinePM works with only one component.
219 for (int comp = 0; comp < numComp; comp++) {
222
225
226 m_coarseFinePM[lvl]->addFiCoDataToFine(meshDataAlias, bufferFiCoAlias);
227 }
228 }
229 }
230
231 a_particles.clearMaskParticles();
232}
233
234template <class P, class Ret, Ret (P::*MemberFunc)() const>
235void
239 const bool a_forceIrregNGP)
240{
241 CH_TIME("EBAMRParticleMesh::depositHaloNGP");
242 if (m_verbose) {
243 pout() << "EBAMRParticleMesh::depositHaloNGP" << endl;
244 }
245
246 constexpr int numComp = EBParticleMesh::sanitize<Ret>();
247
248 CH_assert(a_meshData[0]->nComp() == numComp);
249
250 // Reset mesh data
252
253 // Copy the required particles to a masked particle data holder.
254 constexpr int coarseMaskWidth = 1;
255
256 // Doing the nasty here...
258
259 particles.transferMaskParticles(m_outerHaloMasks.at(coarseMaskWidth));
260
261 // nonHaloParticles will get deposited with the 'a_depositionType' scheme and haloParticles with an NGP scheme
263 const AMRParticles<P>& haloParticles = particles.getMaskParticles();
264
265 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
266 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
267 const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
268 const DataIterator& dit = dbl.dataIterator();
269
270 const bool hasCoar = (lvl > 0);
271
272 // 1. Deposit particles on this level.
273 const int numBoxes = dit.size();
274
275#pragma omp parallel for schedule(runtime)
276 for (int mybox = 0; mybox < numBoxes; mybox++) {
277 const DataIndex& din = dit[mybox];
281
283
285 interp.deposit<P, Ret, MemberFunc>(meshData, particlesNGP, DepositionType::NGP, 1.0, a_forceIrregNGP);
286 }
287
288 // 2. Exchange ghost data on this level.
289 a_meshData[lvl]->exchange(Interval(0, numComp - 1), m_levelCopiers[lvl], EBAddOp());
290
291 // 3. Deposition into ghost cells across the refinement boundary should end up to the coarse level. Add that mass right now.
292 if (hasCoar) {
293
294 // Because m_coarseFinePM works with one component but we have SpaceDim.
295 for (int comp = 0; comp < numComp; comp++) {
298
299 // This lets coarAlias be a 1-component data holder which references the comp-component
300 // in a_meshData.
303
304 // Average data in the fine-level ghost cells and add it to the coarse level.
305 m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
306 }
307 }
308 }
309
310 particles.transferParticles(particles.getMaskParticles());
311}
312
313template <class P, class Ret, Ret (P::*MemberFunc)() const>
314void
318 const bool a_forceIrregNGP)
319{
320 CH_TIME("EBAMRParticleMesh::depositTransition");
321 if (m_verbose) {
322 pout() << "EBAMRParticleMesh::depositTransition" << endl;
323 }
324
325 constexpr int numComp = EBParticleMesh::sanitize<Ret>();
326
327 CH_assert(a_meshData[0]->nComp() == numComp);
328
329 // If we're calling with NGP, use a cheaper version.
330 if (a_depositionType == DepositionType::NGP) {
331 EBAMRParticleMesh::depositInterp<P, Ret, MemberFunc>(a_meshData, a_particles, DepositionType::NGP, a_forceIrregNGP);
332
333 return;
334 }
335
336 // Reset mesh data
338
339 // This piece of code transfers the particles that lie on the coarse-side interface to a different particle container than
340 // a_particles. We can not use ParticleContainer::transferMaskParticles because the mask is defined on the refined coarse
341 // level. So we do this transfer directly.
343
345
346 // Main deposition loop -- this deposits all particles that do not lie along the refinement boundary.
347 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
348 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
349 const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
350 const DataIterator& dit = dbl.dataIterator();
351 const int numBoxes = dit.size();
352
353#pragma omp parallel for schedule(runtime)
354 for (int mybox = 0; mybox < numBoxes; mybox++) {
355 const DataIndex& din = dit[mybox];
358
360
362 }
363 }
364
365 // 2. Exchange ghost data on each level. Mass that hangs from the fine level across the refinement boundary is put on the coarse level.
366 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
367 const bool hasCoar = (lvl > 0);
368
369 // Exchange+add on this level.
370 a_meshData[lvl]->exchange(Interval(0, numComp - 1), m_levelCopiers[lvl], EBAddOp());
371
372 // Deposition into ghost cells across the refinement boundary must end up on the coarse level.
373 if (hasCoar) {
374 for (int comp = 0; comp < numComp; comp++) {
377
380
381 m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
382 }
383 }
384 }
385
386 // 3. If there is a finer level, not all of the particles on this level have yet been deposited because some of them were transferred into another
387 // particle container. We now run the following steps:
388 //
389 // a) Deposit the particles around the refinement boundary on the refined coarse level, using the fine-grid particle width.
390 // b) Add mass from the refined coarse level to the fine level -- this puts some mass into the fine side of the refinement boundary
391 // c) Exchange data on the refined coarse level to update ghost cells, so that all special mass is contained in the refined coarse grid
392 // d) Coarsen mass from the refined level onto this level.
393 //
394 // The above steps are split into step a), which is local on each rank, and steps b)+c)+d), which require MPI calls.
395 for (int lvl = 0; lvl < m_finestLevel; lvl++) {
396 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
397 const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
398 const DataIterator& dit = dbl.dataIterator();
399 const int numBoxes = dit.size();
400
401 // Note: eblgFiCo is for transferring data between lvl and lvl+1. It stores the refinement of grid level 'lvl' in eblgFiCo
402 const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl + 1]->getEblgFiCo();
403 const DisjointBoxLayout& dblFiCo = eblgFiCo.getDBL();
404 const EBISLayout& ebislFiCo = eblgFiCo.getEBISL();
405 const DataIterator& ditFiCo = dblFiCo.dataIterator();
406 const int numBoxesFiCo = ditFiCo.size();
407
408 // Make a buffer we can deposit into. This is a refined version of this level.
409 LevelData<EBCellFAB>& bufferFiCo = m_coarseFinePM[lvl + 1]->getBufferFiCo<numComp>();
410
411 const int maskWidth = this->getTransitionMaskWidth(a_depositionType, m_refRat[lvl]);
412
413 // a) Deposit the particles on the refined coarse level.
414#pragma omp parallel for schedule(runtime)
415 for (int mybox = 0; mybox < numBoxesFiCo; mybox++) {
416 const DataIndex& din = ditFiCo[mybox];
417
419
420 dataFiCo.setVal(0.0);
421
423 const List<P>& maskParticles = (*particles.getMaskParticles()[lvl])[din].listItems();
425
426 if (mask.isUsable()) {
428 }
429 }
430 }
431
432 // Perform steps b), c), and d) of step #3 above.
433 for (int lvl = 0; lvl < m_finestLevel; lvl++) {
434 LevelData<EBCellFAB>& bufferFiCo = m_coarseFinePM[lvl + 1]->getBufferFiCo<numComp>();
435
436 // b) Add the data to the fine level. This moves from valid+ghost -> valid
437 m_coarseFinePM[lvl + 1]->addFiCoDataToFine(*a_meshData[lvl + 1], bufferFiCo);
438
439 // c) Exchange data on this level
440 m_coarseFinePM[lvl + 1]->exchangeAndAddFiCoData(bufferFiCo);
441
442 // d) Coarsen data from the refined grid to this grid.
443 m_coarseFinePM[lvl + 1]->restrictAndAddFiCoDataToCoar(*a_meshData[lvl],
445 EBCoarseFineParticleMesh::Average::Conservative);
446 }
447
448 // Masked particles are but back in their correct mesh.
449 particles.transferParticles(particles.getMaskParticles());
450}
451
452template <class P, class Ret, Ret (P::*MemberFunc)()>
453void
457 const bool a_forceIrregNGP) const
458{
459 CH_TIME("EBAMRParticleMesh::interpolate");
460 if (m_verbose) {
461 pout() << "EBAMRParticleMesh::interpolate" << endl;
462 }
463
465
466 // TLDR: Run through each patch and interpolate to the particle positions.
467 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
468 const EBLevelGrid& eblg = *m_eblgs[lvl];
469 const DisjointBoxLayout& dbl = eblg.getDBL();
470 const EBISLayout& ebisl = eblg.getEBISL();
471 const DataIterator& dit = dbl.dataIterator();
472
473 const int numBoxes = dit.size();
474#pragma omp parallel for schedule(runtime)
475 for (int mybox = 0; mybox < numBoxes; mybox++) {
476 const DataIndex& din = dit[mybox];
477
478 List<P>& particles = a_particles[lvl][din].listItems();
479
480 const EBCellFAB& data = (*a_meshScalarField[lvl])[din];
482
484 }
485 }
486}
487
488template <class P>
489void
492{
493 CH_TIME("EBAMRParticleMesh::transferMaskParticlesTransition");
494 if (m_verbose) {
495 pout() << "EBAMRParticleMesh::transferMaskParticlesTransition" << endl;
496 }
497
498 for (int lvl = 0; lvl < m_finestLevel; lvl++) {
499 const EBLevelGrid& eblg = *m_eblgs[lvl];
500 const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl + 1]->getEblgFiCo();
501
502 const DisjointBoxLayout& dbl = eblg.getDBL();
503 const DisjointBoxLayout& dblFiCo = eblgFiCo.getDBL();
504
505 const EBISLayout& ebisl = eblg.getEBISL();
506 const EBISLayout& ebislFiCo = eblgFiCo.getEBISL();
507
508 const DataIterator& dit = dbl.dataIterator();
509 const DataIterator& ditFiCo = dblFiCo.dataIterator();
510
511 const int numBoxes = dit.size();
512 const int numBoxesFiCo = ditFiCo.size();
513
514 const Real dx = m_dx[lvl];
515 const Real dxFine = m_dx[lvl + 1];
516
517 if (a_depositionType != DepositionType::NGP) {
518 const int maskWidth = this->getTransitionMaskWidth(a_depositionType, m_refRat[lvl]);
519
520#pragma omp parallel for schedule(runtime)
521 for (int mybox = 0; mybox < numBoxes; mybox++) {
522 const DataIndex& din = dit[mybox];
523 const EBISBox& ebisbox = ebislFiCo[din];
524
526
527 if (mask.isUsable()) {
529 List<P>& maskParticles = (*a_particles.getMaskParticles()[lvl])[din].listItems();
530
531 const Box cellBox = dblFiCo[din];
532 const Box maskBox = mask.box();
533
535
536 for (ListIterator<P> lit(amrParticles); lit.ok();) {
538
539 if (mask(iv)) {
540 maskParticles.transfer(lit);
541 }
542 else {
543 ++lit;
544 }
545 }
546 }
547 }
548 }
549 }
550}
551
552#include <CD_NamespaceFooter.H>
553
554#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.
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 depositTransition(EBAMRCellData &a_meshData, const ParticleContainer< P > &a_particles, const DepositionType a_depositionType, const bool a_forceIrregNGP=false)
Deposit particles on the mesh.
Definition CD_EBAMRParticleMeshImplem.H:315
int getTransitionMaskWidth(const DepositionType a_depositionType, const int a_refRat) const
Get transition mask width.
Definition CD_EBAMRParticleMesh.cpp:470
std::map< int, Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > > m_outerHaloMasks
Outer halo masks with various widths.
Definition CD_EBAMRParticleMesh.H:213
Vector< RefCountedPtr< EBCoarseFineParticleMesh > > m_coarseFinePM
Buffers for handling arithmetic for mass moving from coarse to fine level and vice versa.
Definition CD_EBAMRParticleMesh.H:227
Vector< Real > m_dx
Grid resolutions.
Definition CD_EBAMRParticleMesh.H:188
void interpolate(ParticleContainer< P > &a_particles, const EBAMRCellData &a_meshData, const DepositionType a_interpType, const bool a_forceIrregNGP=false) const
Interpolate a scalar field onto the particle position.
Definition CD_EBAMRParticleMeshImplem.H:454
int m_finestLevel
Finest AMR level.
Definition CD_EBAMRParticleMesh.H:173
RealVect m_probLo
Lower-left corner of physical domain.
Definition CD_EBAMRParticleMesh.H:163
bool m_isDefined
Is defined or not.
Definition CD_EBAMRParticleMesh.H:153
Vector< RefCountedPtr< LayoutData< EBParticleMesh > > > m_ebParticleMesh
Regular particle-mesh object on each grid level.
Definition CD_EBAMRParticleMesh.H:193
Vector< RefCountedPtr< EBLevelGrid > > m_eblgs
Grids on each level.
Definition CD_EBAMRParticleMesh.H:178
std::map< int, Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > > m_transitionMasks
Transition masks with various widths.
Definition CD_EBAMRParticleMesh.H:221
bool m_verbose
Verbose or not.
Definition CD_EBAMRParticleMesh.H:158
Vector< Copier > m_levelCopiers
Copier for moving data from valid+ghost to valid on each AMR level.
Definition CD_EBAMRParticleMesh.H:233
void depositHalo(EBAMRCellData &a_meshData, const ParticleContainer< P > &a_particles, const DepositionType a_depositionType, const bool a_forceIrregNGP=false)
Deposit particles on the mesh, keeping the original particle width everywhere and depositing directly...
Definition CD_EBAMRParticleMeshImplem.H:135
void depositHaloNGP(EBAMRCellData &a_meshData, const ParticleContainer< P > &a_particles, const DepositionType a_depositionType, const bool a_forceIrregNGP=false)
Deposit particles on the mesh, using an NGP scheme for coarse-grid particles on the refinement bounda...
Definition CD_EBAMRParticleMeshImplem.H:236
void depositInterp(EBAMRCellData &a_meshData, const ParticleContainer< P > &a_particles, const DepositionType a_depositionType, const bool a_forceIrregNGP=false)
Deposit particles on the mesh, interpolating the coarse-grid invalid mass to the fine grid.
Definition CD_EBAMRParticleMeshImplem.H:71
Vector< RefCountedPtr< LayoutData< EBParticleMesh > > > m_ebParticleMeshFiCo
Special particle-mesh objects for depositing on the coarsened fine grid.
Definition CD_EBAMRParticleMesh.H:200
void transferMaskParticlesTransition(ParticleContainer< P > &a_particles, const DepositionType a_depositionType) const
Support function for transferring particles that lie in the transition zone around a refinement bound...
Definition CD_EBAMRParticleMeshImplem.H:490
Vector< int > m_refRat
Refinement ratios between levels.
Definition CD_EBAMRParticleMesh.H:183
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 is the main function that users shoul...
Definition CD_EBAMRParticleMeshImplem.H:29
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 on a single grid patch.
Definition CD_EBParticleMesh.H:34
static IntVect getParticleCellIndex(const RealVect &a_particlePosition, const RealVect &a_probLo, const Real &a_dx) noexcept
Get the cell index corresponding to the particle position.
Definition CD_ParticleOpsImplem.H:30
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition CD_TracerParticleSolver.H:37
virtual void deposit(EBAMRCellData &a_phi) const noexcept
Deposit particle weight on mesh.
Definition CD_TracerParticleSolverImplem.H:362
virtual ParticleContainer< P > & getParticles()
Get all particles.
Definition CD_TracerParticleSolverImplem.H:662