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