chombo-discharge
Loading...
Searching...
No Matches
CD_EBAMRParticleMesh.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_EBAMRPARTICLEMESH_H
14#define CD_EBAMRPARTICLEMESH_H
15
16// Std includes
17#include <cstddef>
18#include <map>
19
20// Chombo includes
21#include <CH_Timer.H>
22#include <RefCountedPtr.H>
23#include <Vector.H>
24#include <Copier.H>
25#include <DataIterator.H>
26#include <NeighborIterator.H>
27#include <LevelData.H>
28#include <BaseFab.H>
29#include <FArrayBox.H>
30#include <EBCellFAB.H>
31#include <EBLevelGrid.H>
32#include <EBAlias.H>
33#include <IntVectSet.H>
34#include <BoxIterator.H>
35
36// Our includes
37#include <CD_EBAMRData.H>
38#include <CD_EBAddOp.H>
39#include <CD_DataOps.H>
40#include <CD_OpenMP.H>
41#include <CD_DepositionType.H>
45#include <CD_EBParticleMesh.H>
47#include <CD_NamespaceHeader.H>
48
95{
96public:
101
107
112
117
123 operator=(const EBAMRParticleMesh&) = delete;
124
134 void
135 define(const Vector<RefCountedPtr<EBLevelGrid>>& a_eblgs,
136 const Vector<int>& a_refRat,
137 const Vector<Real>& a_dx,
138 const RealVect& a_probLo,
139 const int a_ghost,
140 const int a_finestLevel)
141 {
142 CH_TIME("EBAMRParticleMesh::define");
143
144 CH_assert(a_eblgs.size() > a_finestLevel);
145 CH_assert(a_refRat.size() > a_finestLevel);
146 CH_assert(a_dx.size() > a_finestLevel);
147
148 m_eblgs = a_eblgs;
149 m_refRat = a_refRat;
150 m_dx = a_dx;
151 m_probLo = a_probLo;
152 m_ghost = a_ghost;
153 m_finestLevel = a_finestLevel;
154
156 this->defineEBParticleMesh();
157 this->defineLevelMotion();
158 this->defineOuterHaloMasks();
159 this->defineTransitionMasks();
160
161 m_isDefined = true;
162 }
163
165
170
183 template <auto... Members, typename P, typename Traits>
184 void
186 const EBAMRCellData& a_meshData,
187 const DepositionType a_interpType,
188 const bool a_forceIrregNGP) const
189 {
190 CH_TIME("EBAMRParticleMesh::interpolate");
191
192 CH_assert(m_isDefined);
193
194 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
195 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
196 const DataIterator& dit = dbl.dataIterator();
197
198 const int nbox = dit.size();
199
200#pragma omp parallel for schedule(runtime)
201 for (int mybox = 0; mybox < nbox; mybox++) {
202 const DataIndex& din = dit[mybox];
203 const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
204 const EBCellFAB& data = (*a_meshData[lvl])[din];
205
206 interp.template interpolate<Members...>(a_particles[lvl][din], data, a_interpType, a_forceIrregNGP);
207 }
208 }
209 }
210
223 template <typename P, typename Traits>
224 void
226 const EBAMRCellData& a_meshData,
227 const DepositionType a_interpType,
228 const bool a_forceIrregNGP) const
229 {
230 CH_TIME("EBAMRParticleMesh::interpolateWeight");
231
232 CH_assert(m_isDefined);
233
234 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
235 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
236 const DataIterator& dit = dbl.dataIterator();
237
238 const int nbox = dit.size();
239
240#pragma omp parallel for schedule(runtime)
241 for (int mybox = 0; mybox < nbox; mybox++) {
242 const DataIndex& din = dit[mybox];
243 const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
244 const EBCellFAB& data = (*a_meshData[lvl])[din];
245
246 interp.interpolateWeight(a_particles[lvl][din], data, a_interpType, a_forceIrregNGP);
247 }
248 }
249 }
250
252
257
270 template <typename P, typename Traits>
271 void
272 depositWeight(EBAMRCellData& a_meshData,
273 const ParticleContainer<P, Traits>& a_particles,
274 const DepositionType a_depositionType,
275 const CoarseFineDeposition a_coarseFineDeposition,
276 const IrregularDeposition a_irregularDeposition)
277 {
278 CH_TIME("EBAMRParticleMesh::depositWeight");
279
280 CH_assert(m_isDefined);
281
282 // The leaf kernels answer one question -- NGP in a cut cell, yes or no -- so the selector collapses to a bool
283 // here. Mirror and Redistribute leave the kernel alone and are the CALLER's responsibility; see the class
284 // documentation for why that is silent when the caller forgets.
285 const bool forceIrregNGP = (a_irregularDeposition == IrregularDeposition::NGP);
286
287 const auto patch =
288 [&](const EBParticleMesh& a_interp, EBCellFAB& a_rho, const auto& a_soa, const Real a_widthScale) {
289 a_interp.depositWeight(a_rho, a_soa, a_depositionType, a_widthScale, forceIrregNGP);
290 };
291 const auto patchNGP =
292 [&](const EBParticleMesh& a_interp, EBCellFAB& a_rho, const auto& a_soa, const Real a_widthScale) {
293 a_interp.depositWeight(a_rho, a_soa, DepositionType::NGP, a_widthScale, forceIrregNGP);
294 };
295
296 switch (a_coarseFineDeposition) {
297 case CoarseFineDeposition::Interp: {
298 this->depositInterpCore(a_meshData, a_particles, 1, patch);
299
300 break;
301 }
302 case CoarseFineDeposition::Halo: {
303 this->template depositHaloCore<1>(a_meshData, a_particles, patch);
304
305 break;
306 }
307 case CoarseFineDeposition::HaloNGP: {
308 this->template depositHaloNGPCore<1>(a_meshData, a_particles, patch, patchNGP);
309
310 break;
311 }
312 case CoarseFineDeposition::Transition: {
313 this->template depositTransitionCore<1>(a_meshData, a_particles, a_depositionType, patch);
314
315 break;
316 }
317 default: {
318 this->errorUnsupported();
319
320 break;
321 }
322 }
323 }
324
340 template <typename P, typename Traits, typename CellGather>
341 void
342 depositGathered(EBAMRCellData& a_meshData,
343 const ParticleContainer<P, Traits>& a_particles,
344 const DepositionType a_depositionType,
345 const CoarseFineDeposition a_coarseFineDeposition,
346 const IrregularDeposition a_irregularDeposition,
347 CellGather a_cellGather)
348 {
349 CH_TIME("EBAMRParticleMesh::depositGathered");
350
351 CH_assert(m_isDefined);
352
353 // See depositWeight for why the selector collapses to a bool here.
354 const bool forceIrregNGP = (a_irregularDeposition == IrregularDeposition::NGP);
355
356 const auto patch =
357 [&](const EBParticleMesh& a_interp, EBCellFAB& a_rho, const auto& a_soa, const Real a_widthScale) {
358 a_interp.depositGathered(a_rho,
359 0,
360 a_soa,
361 a_depositionType,
362 a_widthScale,
363 forceIrregNGP,
364 [&](const std::size_t a_i, Real* a_out) {
365 a_out[0] = a_cellGather(a_soa, a_i);
366 });
367 };
368 const auto patchNGP =
369 [&](const EBParticleMesh& a_interp, EBCellFAB& a_rho, const auto& a_soa, const Real a_widthScale) {
370 a_interp.depositGathered(a_rho,
371 0,
372 a_soa,
373 DepositionType::NGP,
374 a_widthScale,
375 forceIrregNGP,
376 [&](const std::size_t a_i, Real* a_out) {
377 a_out[0] = a_cellGather(a_soa, a_i);
378 });
379 };
380
381 switch (a_coarseFineDeposition) {
382 case CoarseFineDeposition::Interp: {
383 this->depositInterpCore(a_meshData, a_particles, 1, patch);
384
385 break;
386 }
387 case CoarseFineDeposition::Halo: {
388 this->template depositHaloCore<1>(a_meshData, a_particles, patch);
389
390 break;
391 }
392 case CoarseFineDeposition::HaloNGP: {
393 this->template depositHaloNGPCore<1>(a_meshData, a_particles, patch, patchNGP);
394
395 break;
396 }
397 case CoarseFineDeposition::Transition: {
398 this->template depositTransitionCore<1>(a_meshData, a_particles, a_depositionType, patch);
399
400 break;
401 }
402 default: {
403 this->errorUnsupported();
404
405 break;
406 }
407 }
408 }
409
422 template <auto... Members, typename P, typename Traits>
423 void
424 deposit(EBAMRCellData& a_meshData,
425 const ParticleContainer<P, Traits>& a_particles,
426 const DepositionType a_depositionType,
427 const CoarseFineDeposition a_coarseFineDeposition,
428 const IrregularDeposition a_irregularDeposition)
429 {
430 CH_TIME("EBAMRParticleMesh::deposit");
431
432 CH_assert(m_isDefined);
433
434 // See depositWeight for why the selector collapses to a bool here.
435 const bool forceIrregNGP = (a_irregularDeposition == IrregularDeposition::NGP);
436
437 const auto patch =
438 [&](const EBParticleMesh& a_interp, EBCellFAB& a_rho, const auto& a_soa, const Real a_widthScale) {
439 a_interp.template deposit<Members...>(a_rho, a_soa, a_depositionType, a_widthScale, forceIrregNGP);
440 };
441 const auto patchNGP =
442 [&](const EBParticleMesh& a_interp, EBCellFAB& a_rho, const auto& a_soa, const Real a_widthScale) {
443 a_interp.template deposit<Members...>(a_rho, a_soa, DepositionType::NGP, a_widthScale, forceIrregNGP);
444 };
445
446 switch (a_coarseFineDeposition) {
447 case CoarseFineDeposition::Interp: {
448 this->depositInterpCore(a_meshData, a_particles, static_cast<int>(sizeof...(Members)), patch);
449
450 break;
451 }
452 case CoarseFineDeposition::Halo: {
453 this->template depositHaloCore<static_cast<int>(sizeof...(Members))>(a_meshData, a_particles, patch);
454
455 break;
456 }
457 case CoarseFineDeposition::HaloNGP: {
458 this->template depositHaloNGPCore<static_cast<int>(sizeof...(Members))>(a_meshData, a_particles, patch, patchNGP);
459
460 break;
461 }
462 case CoarseFineDeposition::Transition: {
463 this->template depositTransitionCore<static_cast<int>(sizeof...(Members))>(a_meshData,
464 a_particles,
465 a_depositionType,
466 patch);
467 break;
468 }
469 default: {
470 this->errorUnsupported();
471
472 break;
473 }
474 }
475 }
476
478
479protected:
483 Vector<RefCountedPtr<EBLevelGrid>> m_eblgs;
484
488 Vector<int> m_refRat;
489
493 Vector<Real> m_dx;
494
498 RealVect m_probLo;
499
504
509
514
518 Vector<RefCountedPtr<LayoutData<EBParticleMesh>>> m_ebParticleMesh;
519
523 Vector<Copier> m_levelCopiers;
524
528 Vector<RefCountedPtr<EBCoarseFineParticleMesh>> m_coarseFinePM;
529
533 Vector<RefCountedPtr<LayoutData<EBParticleMesh>>> m_ebParticleMeshFiCo;
534
538 std::map<int, Vector<RefCountedPtr<LevelData<BaseFab<bool>>>>> m_outerHaloMasks;
539
543 std::map<int, Vector<RefCountedPtr<LevelData<BaseFab<bool>>>>> m_transitionMasks;
544
548 void
550 {
551 MayDay::Error("EBAMRParticleMesh: unsupported CoarseFineDeposition strategy");
552 }
553
557 void
559 {
560 CH_TIME("EBAMRParticleMesh::defineEBParticleMesh");
561
564
565 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
566 const ProblemDomain& domain = m_eblgs[lvl]->getDomain();
567 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
568 const EBISLayout& ebisl = m_eblgs[lvl]->getEBISL();
569 const DataIterator& dit = dbl.dataIterator();
570
571 m_ebParticleMesh[lvl] = RefCountedPtr<LayoutData<EBParticleMesh>>(new LayoutData<EBParticleMesh>(dbl));
572
573 const int nbox = dit.size();
574
575#pragma omp parallel for schedule(runtime)
576 for (int mybox = 0; mybox < nbox; mybox++) {
577 const DataIndex& din = dit[mybox];
578
579 (*m_ebParticleMesh[lvl])[din].define(domain, dbl[din], ebisl[din], m_dx[lvl] * RealVect::Unit, m_probLo);
580 }
581
582 // Refined-coarse leaves: deposit coarse-level halo particles at fine resolution (dx of this level).
583 if (lvl > 0) {
584 const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl]->getEblgFiCo();
585 const ProblemDomain& domainFiCo = eblgFiCo.getDomain();
586 const DisjointBoxLayout& dblFiCo = eblgFiCo.getDBL();
587 const EBISLayout& ebislFiCo = eblgFiCo.getEBISL();
588 const DataIterator& ditFiCo = dblFiCo.dataIterator();
589 const int nboxFiCo = ditFiCo.size();
590
591 m_ebParticleMeshFiCo[lvl] = RefCountedPtr<LayoutData<EBParticleMesh>>(new LayoutData<EBParticleMesh>(dblFiCo));
592
593#pragma omp parallel for schedule(runtime)
594 for (int mybox = 0; mybox < nboxFiCo; mybox++) {
595 const DataIndex& din = ditFiCo[mybox];
596
597 (*m_ebParticleMeshFiCo[lvl])[din].define(domainFiCo,
598 dblFiCo[din],
599 ebislFiCo[din],
600 m_dx[lvl] * RealVect::Unit,
601 m_probLo);
602 }
603 }
604 else {
605 m_ebParticleMeshFiCo[lvl] = RefCountedPtr<LayoutData<EBParticleMesh>>(nullptr);
606 }
607 }
608 }
609
613 void
615 {
616 CH_TIME("EBAMRParticleMesh::defineLevelMotion");
617
618 m_levelCopiers.resize(1 + m_finestLevel);
619 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
620 const EBLevelGrid& eblg = *m_eblgs[lvl];
621 const DisjointBoxLayout& dbl = eblg.getDBL();
622
623 m_levelCopiers[lvl].define(dbl, dbl, eblg.getDomain(), m_ghost * IntVect::Unit, true);
624 m_levelCopiers[lvl].reverse();
625 }
626 }
627
631 void
633 {
634 CH_TIME("EBAMRParticleMesh::defineCoarseFineMotion");
635
636 m_coarseFinePM.resize(1 + m_finestLevel);
637
638 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
639 if (lvl > 0) {
640 m_coarseFinePM[lvl] = RefCountedPtr<EBCoarseFineParticleMesh>(
641 new EBCoarseFineParticleMesh(*m_eblgs[lvl - 1], *m_eblgs[lvl], m_refRat[lvl - 1], m_ghost * IntVect::Unit));
642 }
643 else {
644 m_coarseFinePM[lvl] = RefCountedPtr<EBCoarseFineParticleMesh>(nullptr);
645 }
646 }
647 }
648
661 template <typename Container, typename PatchDeposit>
662 void
663 depositInterpCore(EBAMRCellData& a_meshData,
664 const Container& a_particles,
665 const int a_numComp,
666 PatchDeposit a_patchDeposit) const
667 {
668 CH_TIME("EBAMRParticleMesh::depositInterpCore");
669
670 CH_assert(m_isDefined);
671 CH_assert(a_meshData[0]->nComp() == a_numComp);
672
673 DataOps::setValue(a_meshData, 0.0);
674
675 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
676 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
677 const bool hasCoar = (lvl > 0);
678 const DataIterator& dit = dbl.dataIterator();
679
680 // 1. Deposit this level's valid particles.
681 const int nbox = dit.size();
682
683#pragma omp parallel for schedule(runtime)
684 for (int mybox = 0; mybox < nbox; mybox++) {
685 const DataIndex& din = dit[mybox];
686 const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
687
688 EBCellFAB& rho = (*a_meshData[lvl])[din];
689
690 a_patchDeposit(interp, rho, a_particles[lvl][din], 1.0);
691 }
692
693 // 2. Fold the mass deposited into ghost cells into the owning patch's valid region.
694 a_meshData[lvl]->exchange(Interval(0, a_numComp - 1), m_levelCopiers[lvl], EBAddOp());
695
696 // 3. Move over-refinement-boundary mass between this level and the coarser one (mesh-side).
697 if (hasCoar) {
698 for (int comp = 0; comp < a_numComp; comp++) {
699 LevelData<EBCellFAB> coarAlias;
700 LevelData<EBCellFAB> fineAlias;
701
702 aliasLevelData<EBCellFAB>(coarAlias, &(*a_meshData[lvl - 1]), Interval(comp, comp));
703 aliasLevelData<EBCellFAB>(fineAlias, &(*a_meshData[lvl]), Interval(comp, comp));
704
705 m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
706 m_coarseFinePM[lvl]->addInvalidCoarseToFine(fineAlias, coarAlias);
707 }
708 }
709 }
710 }
711
719 void
721 {
722 CH_TIME("EBAMRParticleMesh::defineOuterHaloMasks");
723
724 constexpr int comp = 0;
725 constexpr int numComp = 1;
726
727 m_outerHaloMasks.clear();
728
729 for (int ighost = 1; ighost <= m_ghost; ighost++) {
730 Vector<RefCountedPtr<LevelData<BaseFab<bool>>>> mask(1 + m_finestLevel);
731
732 for (int lvl = 0; lvl < m_finestLevel; lvl++) {
733 const DisjointBoxLayout& grids = m_eblgs[lvl]->getDBL();
734 const DisjointBoxLayout& gridsFine = m_eblgs[lvl + 1]->getDBL();
735 const ProblemDomain& domain = m_eblgs[lvl]->getDomain();
736
737 DisjointBoxLayout gridsCoFi;
738 coarsen(gridsCoFi, gridsFine, m_refRat[lvl]);
739
740 mask[lvl] = RefCountedPtr<LevelData<BaseFab<bool>>>(
741 new LevelData<BaseFab<bool>>(grids, numComp, IntVect::Zero));
742
743 LevelData<BaseFab<bool>>& levelMask = *mask[lvl];
744 {
745 const DataIterator& dit = grids.dataIterator();
746
747 const int nbox = dit.size();
748
749#pragma omp parallel for schedule(runtime)
750 for (int mybox = 0; mybox < nbox; mybox++) {
751 const DataIndex& din = dit[mybox];
752
753 levelMask[din].setVal(false);
754 }
755 }
756
757 // The coarse-grid cells surrounding the fine level, viewed from the coarsened-fine grids.
758 IntVectSet halo;
759 {
760 const DataIterator& dit = gridsCoFi.dataIterator();
761 const int nbox = dit.size();
762
763#pragma omp parallel for schedule(runtime) reduction(+ : halo)
764 for (int mybox = 0; mybox < nbox; mybox++) {
765 const DataIndex& din = dit[mybox];
766 const Box coFiBox = gridsCoFi[din];
767 const Box grownBox = grow(coFiBox, ighost) & domain;
768 IntVectSet myHalo(grownBox);
769 myHalo -= coFiBox;
770
771 NeighborIterator nit(gridsCoFi);
772 for (nit.begin(din); nit.ok(); ++nit) {
773 myHalo -= gridsCoFi[nit()];
774 }
775 halo |= myHalo;
776 }
777 }
778
779 // Re-express the halo on the coarse grid via a CoFi data holder whose ghosts add onto the coarse grid.
780 LevelData<FArrayBox> coFiMask(gridsCoFi, numComp, ighost * IntVect::Unit);
781 LevelData<FArrayBox> coarMask(grids, numComp, IntVect::Zero);
782 {
783 const DataIterator& dit = gridsFine.dataIterator();
784 const int nbox = dit.size();
785
786#pragma omp parallel for schedule(runtime)
787 for (int mybox = 0; mybox < nbox; mybox++) {
788 const DataIndex& din = dit[mybox];
789
790 coFiMask[din].setVal(0.0);
791 }
792 }
793 {
794 const DataIterator& dit = grids.dataIterator();
795 const int nbox = dit.size();
796
797#pragma omp parallel for schedule(runtime)
798 for (int mybox = 0; mybox < nbox; mybox++) {
799 const DataIndex& din = dit[mybox];
800
801 coarMask[din].setVal(0.0);
802 }
803 }
804 {
805 const DataIterator& dit = gridsFine.dataIterator();
806 const int nbox = dit.size();
807
808#pragma omp parallel for schedule(runtime)
809 for (int mybox = 0; mybox < nbox; mybox++) {
810 const DataIndex& din = dit[mybox];
811 const Box region = coFiMask[din].box();
812 const IntVectSet curHalo = halo & region;
813
814 for (IVSIterator ivsit(curHalo); ivsit.ok(); ++ivsit) {
815 coFiMask[din](ivsit(), comp) = 1.0;
816 }
817 }
818 }
819
820 Copier copier;
821 copier.ghostDefine(gridsCoFi, grids, domain, ighost * IntVect::Unit);
822 coFiMask.copyTo(Interval(comp, comp), coarMask, Interval(comp, comp), copier, LDaddOp<FArrayBox>());
823
824 // Make the boolean mask; undefine empty BaseFabs (so copyMaskParticles skips them).
825 const DataIterator& dit = grids.dataIterator();
826 const int nbox = dit.size();
827
828#pragma omp parallel for schedule(runtime)
829 for (int mybox = 0; mybox < nbox; mybox++) {
830 const DataIndex& din = dit[mybox];
831 const Box box = grids[din];
832 const FArrayBox& realMask = coarMask[din];
833
834 BaseFab<bool>& boolMask = levelMask[din];
835
836 bool emptyMask = true;
837 for (BoxIterator bit(box); bit.ok(); ++bit) {
838 if (realMask(bit(), comp) > 0.0) {
839 boolMask(bit(), comp) = true;
840 emptyMask = false;
841 }
842 }
843 if (emptyMask) {
844 boolMask.clear();
845 }
846 }
847 }
848
849 mask[m_finestLevel] = RefCountedPtr<LevelData<BaseFab<bool>>>(nullptr);
850 m_outerHaloMasks.emplace(ighost, mask);
851 }
852 }
853
867 template <int NCOMP, typename Container, typename PatchDeposit>
868 void
869 depositHaloCore(EBAMRCellData& a_meshData, const Container& a_particles, PatchDeposit a_patchDeposit) const
870 {
871 CH_TIME("EBAMRParticleMesh::depositHaloCore");
872
873 CH_assert(m_isDefined);
874 CH_assert(a_meshData[0]->nComp() == NCOMP);
875
876 DataOps::setValue(a_meshData, 0.0);
877
878 // Copy the coarse-side halo particles (width 1) into the container's mask holder.
879 constexpr int coarseMaskWidth = 1;
880 Container& particles = const_cast<Container&>(a_particles);
881 particles.copyMaskParticles(m_outerHaloMasks.at(coarseMaskWidth));
882
883 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
884 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
885 const bool hasCoar = (lvl > 0);
886
887 // 1. Deposit this level's valid particles.
888 const DataIterator& dit = dbl.dataIterator();
889 const int nbox = dit.size();
890
891#pragma omp parallel for schedule(runtime)
892 for (int mybox = 0; mybox < nbox; mybox++) {
893 const DataIndex& din = dit[mybox];
894 const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
895
896 EBCellFAB& rho = (*a_meshData[lvl])[din];
897
898 a_patchDeposit(interp, rho, a_particles[lvl][din], 1.0);
899 }
900
901 // 2. Fold ghost-deposited mass into the owner patch.
902 a_meshData[lvl]->exchange(Interval(0, NCOMP - 1), m_levelCopiers[lvl], EBAddOp());
903
904 // 3. Mass deposited into fine ghosts across the refinement boundary belongs to the coarse level.
905 if (hasCoar) {
906 m_coarseFinePM[lvl]->addFineGhostsToCoarse(*a_meshData[lvl - 1], *a_meshData[lvl]);
907 }
908
909 // 4. Re-deposit the coarse halo particles on the refined-coarse grid and add to the fine level.
910 if (hasCoar) {
911 const auto& coarHalo = a_particles.getMaskParticles()[lvl - 1];
912 const Real widthScale = static_cast<Real>(m_refRat[lvl - 1]);
913 const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl]->getEblgFiCo();
914 const DisjointBoxLayout& dblFiCo = eblgFiCo.getDBL();
915
916 LevelData<EBCellFAB>& bufferFiCo = m_coarseFinePM[lvl]->template getBufferFiCo<NCOMP>();
917
918 const DataIterator& ditFiCo = dblFiCo.dataIterator();
919
920 const int nboxFiCo = ditFiCo.size();
921#pragma omp parallel for schedule(runtime)
922 for (int mybox = 0; mybox < nboxFiCo; mybox++) {
923 const DataIndex& din = ditFiCo[mybox];
924 const EBParticleMesh& interp = (*m_ebParticleMeshFiCo[lvl])[din];
925
926 EBCellFAB& dataFiCo = bufferFiCo[din];
927
928 dataFiCo.setVal(0.0);
929 a_patchDeposit(interp, dataFiCo, (*coarHalo)[din], widthScale);
930 }
931
932 for (int comp = 0; comp < NCOMP; comp++) {
933 LevelData<EBCellFAB> meshAlias;
934 LevelData<EBCellFAB> bufAlias;
935
936 aliasLevelData<EBCellFAB>(meshAlias, &(*a_meshData[lvl]), Interval(comp, comp));
937 aliasLevelData<EBCellFAB>(bufAlias, &bufferFiCo, Interval(comp, comp));
938
939 m_coarseFinePM[lvl]->addFiCoDataToFine(meshAlias, bufAlias);
940 }
941 }
942 }
943
944 particles.clearMaskParticles();
945 }
946
963 template <int NCOMP, typename Container, typename PatchDeposit, typename PatchDepositNGP>
964 void
965 depositHaloNGPCore(EBAMRCellData& a_meshData,
966 const Container& a_particles,
967 PatchDeposit a_patch,
968 PatchDepositNGP a_patchNGP) const
969 {
970 CH_TIME("EBAMRParticleMesh::depositHaloNGPCore");
971
972 CH_assert(m_isDefined);
973 CH_assert(a_meshData[0]->nComp() == NCOMP);
974
975 DataOps::setValue(a_meshData, 0.0);
976
977 // Move the coarse-side halo particles (width 1) out of the valid holder into the mask holder.
978 constexpr int coarseMaskWidth = 1;
979 Container& particles = const_cast<Container&>(a_particles);
980
981 particles.transferMaskParticles(m_outerHaloMasks.at(coarseMaskWidth));
982
983 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
984 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
985 const bool hasCoar = (lvl > 0);
986
987 // 1. Deposit the non-halo particles with the requested kernel, the halo particles with NGP.
988 const DataIterator& dit = dbl.dataIterator();
989 const int nbox = dit.size();
990
991#pragma omp parallel for schedule(runtime)
992 for (int mybox = 0; mybox < nbox; mybox++) {
993 const DataIndex& din = dit[mybox];
994 const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
995
996 EBCellFAB& rho = (*a_meshData[lvl])[din];
997
998 a_patch(interp, rho, a_particles[lvl][din], 1.0);
999 a_patchNGP(interp, rho, (*a_particles.getMaskParticles()[lvl])[din], 1.0);
1000 }
1001
1002 // 2. Fold ghost-deposited mass into the owner patch.
1003 a_meshData[lvl]->exchange(Interval(0, NCOMP - 1), m_levelCopiers[lvl], EBAddOp());
1004
1005 // 3. Mass deposited into fine ghosts across the refinement boundary belongs to the coarse level.
1006 if (hasCoar) {
1007 for (int comp = 0; comp < NCOMP; comp++) {
1008 LevelData<EBCellFAB> coarAlias;
1009 LevelData<EBCellFAB> fineAlias;
1010
1011 aliasLevelData<EBCellFAB>(coarAlias, &(*a_meshData[lvl - 1]), Interval(comp, comp));
1012 aliasLevelData<EBCellFAB>(fineAlias, &(*a_meshData[lvl]), Interval(comp, comp));
1013
1014 m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
1015 }
1016 }
1017 }
1018
1019 // Return the halo particles to the valid holder.
1020 particles.transferParticles(particles.getMaskParticles());
1021 }
1022
1029 int
1030 getTransitionMaskWidth(const DepositionType a_depositionType, const int a_refRat) const
1031 {
1032 int maskWidth = 0;
1033 if (a_depositionType == DepositionType::CIC) {
1034 maskWidth = a_refRat / 2;
1035 }
1036 else if (a_depositionType == DepositionType::TSC) {
1037 maskWidth = a_refRat;
1038 }
1039 else {
1040 MayDay::Abort("EBAMRParticleMesh::getTransitionMaskWidth - logic bust");
1041 }
1042 if (maskWidth > m_ghost) {
1043 MayDay::Abort("EBAMRParticleMesh::getTransitionMaskWidth - not enough ghost cells");
1044 }
1045 return maskWidth;
1046 }
1047
1055 void
1057 {
1058 CH_TIME("EBAMRParticleMesh::defineTransitionMasks");
1059
1060 constexpr int comp = 0;
1061 constexpr int numComp = 1;
1062 const Interval interv = Interval(comp, comp);
1063
1064 m_transitionMasks.clear();
1065
1066 for (int ighost = 1; ighost <= m_ghost; ighost++) {
1067 Vector<RefCountedPtr<LevelData<BaseFab<bool>>>> mask(1 + m_finestLevel);
1068
1069 for (int lvl = 0; lvl < m_finestLevel; lvl++) {
1070 const DisjointBoxLayout& gridsFine = m_eblgs[lvl + 1]->getDBL();
1071 const EBLevelGrid& eblgFiCo = m_coarseFinePM[lvl + 1]->getEblgFiCo();
1072 const DisjointBoxLayout& gridsFiCo = eblgFiCo.getDBL();
1073 const ProblemDomain& domainFine = m_eblgs[lvl + 1]->getDomain();
1074
1075 mask[lvl] = RefCountedPtr<LevelData<BaseFab<bool>>>(
1076 new LevelData<BaseFab<bool>>(gridsFiCo, numComp, IntVect::Zero));
1077
1078 LevelData<BaseFab<bool>>& levelMask = *mask[lvl];
1079 LevelData<FArrayBox> cfivsFine(gridsFine, numComp, ighost * IntVect::Unit);
1080 LevelData<FArrayBox> cfivsFiCo(gridsFiCo, numComp, IntVect::Zero);
1081
1082 {
1083 const DataIterator& dit = gridsFiCo.dataIterator();
1084 const int nbox = dit.size();
1085
1086#pragma omp parallel for schedule(runtime)
1087 for (int mybox = 0; mybox < nbox; mybox++) {
1088 const DataIndex& din = dit[mybox];
1089
1090 levelMask[din].setVal(false);
1091 cfivsFiCo[din].setVal(0.0);
1092 }
1093 }
1094
1095 // Fine-grid coarse-fine interface band: ghost cells outside the fine boxes (minus neighbours).
1096 {
1097 const DataIterator& dit = gridsFine.dataIterator();
1098 const int nbox = dit.size();
1099
1100#pragma omp parallel for schedule(runtime)
1101 for (int mybox = 0; mybox < nbox; mybox++) {
1102 const DataIndex& din = dit[mybox];
1103 const Box cellBox = gridsFine[din];
1104 const Box ghostBox = grow(cellBox, ighost) & domainFine;
1105
1106 cfivsFine[din].setVal(1.0, ghostBox, comp);
1107 cfivsFine[din].setVal(0.0, cellBox, comp);
1108
1109 NeighborIterator nit(gridsFine);
1110 for (nit.begin(din); nit.ok(); ++nit) {
1111 cfivsFine[din].setVal(0.0, ghostBox & gridsFine[nit()], comp);
1112 }
1113 }
1114 }
1115
1116 Copier copier;
1117 copier.ghostDefine(gridsFine, gridsFiCo, domainFine, ighost * IntVect::Unit);
1118 cfivsFine.copyTo(interv, cfivsFiCo, interv, copier, LDaddOp<FArrayBox>());
1119
1120 const DataIterator& dit = gridsFiCo.dataIterator();
1121 const int nbox = dit.size();
1122
1123#pragma omp parallel for schedule(runtime)
1124 for (int mybox = 0; mybox < nbox; mybox++) {
1125 const DataIndex& din = dit[mybox];
1126 const Box cellBox = gridsFiCo[din];
1127 const FArrayBox& realMask = cfivsFiCo[din];
1128
1129 BaseFab<bool>& boolMask = levelMask[din];
1130
1131 bool emptyMask = true;
1132 for (BoxIterator bit(cellBox); bit.ok(); ++bit) {
1133 if (realMask(bit(), comp) > 0.5) {
1134 boolMask(bit(), comp) = true;
1135 emptyMask = false;
1136 }
1137 }
1138 if (emptyMask) {
1139 boolMask.clear();
1140 }
1141 }
1142 }
1143
1144 mask[m_finestLevel] = RefCountedPtr<LevelData<BaseFab<bool>>>(nullptr);
1145 m_transitionMasks.emplace(ighost, mask);
1146 }
1147 }
1148
1158 template <typename Container>
1159 void
1160 transferMaskParticlesTransition(Container& a_particles, const DepositionType a_depositionType) const
1161 {
1162 CH_TIME("EBAMRParticleMesh::transferMaskParticlesTransition");
1163
1164 if (a_depositionType == DepositionType::NGP) {
1165 return;
1166 }
1167
1168 for (int lvl = 0; lvl < m_finestLevel; lvl++) {
1169 const int maskWidth = this->getTransitionMaskWidth(a_depositionType, m_refRat[lvl]);
1170 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
1171 const Real dxFine = m_dx[lvl + 1];
1172
1173 const DataIterator& dit = dbl.dataIterator();
1174 const int nbox = dit.size();
1175
1176#pragma omp parallel for schedule(runtime)
1177 for (int mybox = 0; mybox < nbox; mybox++) {
1178 const DataIndex& din = dit[mybox];
1179 const BaseFab<bool>& mask = (*m_transitionMasks.at(maskWidth)[lvl])[din];
1180
1181 if (!mask.isUsable()) {
1182 continue;
1183 }
1184
1185 const Box maskBox = mask.box();
1186
1187 auto& valid = a_particles[lvl][din];
1188 auto& maskLeaf = (*a_particles.getMaskParticles()[lvl])[din];
1189
1190 std::size_t i = 0;
1191 while (i < valid.size()) {
1192 const RealVect pos = valid.position(i);
1193 IntVect iv;
1194 for (int dir = 0; dir < SpaceDim; dir++) {
1195 iv[dir] = static_cast<int>(std::floor((pos[dir] - m_probLo[dir]) / dxFine));
1196 }
1197 if (maskBox.contains(iv) && mask(iv, 0)) {
1198 maskLeaf.append(pos, valid.weight(i), valid.gather(i));
1199
1200 const std::size_t k = maskLeaf.size() - 1;
1201
1202 maskLeaf.particleID(k) = valid.particleID(i);
1203 maskLeaf.rankID(k) = valid.rankID(i);
1204
1205 valid.remove(i);
1206 }
1207 else {
1208 i++;
1209 }
1210 }
1211 }
1212 }
1213 }
1214
1231 template <int NCOMP, typename Container, typename PatchDeposit>
1232 void
1233 depositTransitionCore(EBAMRCellData& a_meshData,
1234 const Container& a_particles,
1235 const DepositionType a_depositionType,
1236 PatchDeposit a_patch) const
1237 {
1238 CH_TIME("EBAMRParticleMesh::depositTransitionCore");
1239
1240 CH_assert(m_isDefined);
1241 CH_assert(a_meshData[0]->nComp() == NCOMP);
1242
1243 if (a_depositionType == DepositionType::NGP) {
1244 this->depositInterpCore(a_meshData, a_particles, NCOMP, a_patch);
1245
1246 return;
1247 }
1248
1249 DataOps::setValue(a_meshData, 0.0);
1250
1251 Container& particles = const_cast<Container&>(a_particles);
1252 this->transferMaskParticlesTransition(particles, a_depositionType);
1253
1254 // 1. Deposit the non-transition particles on their levels.
1255 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
1256 const DisjointBoxLayout& dbl = m_eblgs[lvl]->getDBL();
1257 const DataIterator& dit = dbl.dataIterator();
1258 const int nbox = dit.size();
1259
1260#pragma omp parallel for schedule(runtime)
1261 for (int mybox = 0; mybox < nbox; mybox++) {
1262 const DataIndex& din = dit[mybox];
1263 const EBParticleMesh& interp = (*m_ebParticleMesh[lvl])[din];
1264
1265 EBCellFAB& rho = (*a_meshData[lvl])[din];
1266
1267 a_patch(interp, rho, a_particles[lvl][din], 1.0);
1268 }
1269 }
1270
1271 // 2. Fold ghost mass into the owner patch; fine-ghost mass over the boundary goes to coarse.
1272 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
1273 a_meshData[lvl]->exchange(Interval(0, NCOMP - 1), m_levelCopiers[lvl], EBAddOp());
1274 if (lvl > 0) {
1275 for (int comp = 0; comp < NCOMP; comp++) {
1276 LevelData<EBCellFAB> coarAlias;
1277 LevelData<EBCellFAB> fineAlias;
1278
1279 aliasLevelData<EBCellFAB>(coarAlias, &(*a_meshData[lvl - 1]), Interval(comp, comp));
1280 aliasLevelData<EBCellFAB>(fineAlias, &(*a_meshData[lvl]), Interval(comp, comp));
1281
1282 m_coarseFinePM[lvl]->addFineGhostsToCoarse(coarAlias, fineAlias);
1283 }
1284 }
1285 }
1286
1287 // 3a. Deposit the transition particles on the refined-coarse grid (fine-grid width).
1288 for (int lvl = 0; lvl < m_finestLevel; lvl++) {
1289 const int maskWidth = this->getTransitionMaskWidth(a_depositionType, m_refRat[lvl]);
1290 const DisjointBoxLayout& dblFiCo = m_coarseFinePM[lvl + 1]->getEblgFiCo().getDBL();
1291 LevelData<EBCellFAB>& bufferFiCo = m_coarseFinePM[lvl + 1]->template getBufferFiCo<NCOMP>();
1292
1293 const DataIterator& ditFiCo = dblFiCo.dataIterator();
1294 const int nboxFiCo = ditFiCo.size();
1295
1296#pragma omp parallel for schedule(runtime)
1297 for (int mybox = 0; mybox < nboxFiCo; mybox++) {
1298 const DataIndex& din = ditFiCo[mybox];
1299
1300 EBCellFAB& dataFiCo = bufferFiCo[din];
1301
1302 dataFiCo.setVal(0.0);
1303
1304 const BaseFab<bool>& mask = (*m_transitionMasks.at(maskWidth)[lvl])[din];
1305 if (mask.isUsable()) {
1306 const EBParticleMesh& interp = (*m_ebParticleMeshFiCo[lvl + 1])[din];
1307
1308 a_patch(interp, dataFiCo, (*a_particles.getMaskParticles()[lvl])[din], 1.0);
1309 }
1310 }
1311 }
1312
1313 // 3b/c/d. Distribute the refined-coarse buffer to the fine level and (restricted) to the coarse level.
1314 for (int lvl = 0; lvl < m_finestLevel; lvl++) {
1315 LevelData<EBCellFAB>& bufferFiCo = m_coarseFinePM[lvl + 1]->template getBufferFiCo<NCOMP>();
1316
1317 m_coarseFinePM[lvl + 1]->addFiCoDataToFine(*a_meshData[lvl + 1], bufferFiCo);
1318 m_coarseFinePM[lvl + 1]->exchangeAndAddFiCoData(bufferFiCo);
1319 m_coarseFinePM[lvl + 1]->restrictAndAddFiCoDataToCoar(*a_meshData[lvl],
1320 bufferFiCo,
1321 EBCoarseFineParticleMesh::Average::Conservative);
1322 }
1323
1324 // Return the transition particles to the valid holder.
1325 particles.transferParticles(particles.getMaskParticles());
1326 }
1327};
1328
1329#include <CD_NamespaceFooter.H>
1330
1331#endif
Declaration of deposition algorithms in an AMR context.
CoarseFineDeposition
Coarse-fine deposition types (see CD_EBAMRParticleMesh for how these are handled).
Definition CD_CoarseFineDeposition.H:28
Agglomeration of useful data operations.
Declaration of deposition types.
DepositionType
Deposition types.
Definition CD_DepositionType.H:24
Class for holding data across EBAMR hierarchies.
Declaration of a Copier class for making incrementation between LevelData<EBCellFAB> easier.
Declaration of a class for handling particle deposition arithmetic near refinement boundaries.
Single-patch ParticleSoA deposit/interpolate onto an embedded-boundary mesh.
Declaration of cut-cell deposition strategies.
IrregularDeposition
How a deposition scheme treats the cut cells.
Definition CD_IrregularDeposition.H:36
@ NGP
Put the particle's entire cloud in its own cell when that cell is a cut cell.
Declaration of various useful OpenMP-related utilities.
Declaration of an AMR-hierarchy container that owns per-patch ParticleSoA leaves.
static void setValue(LevelData< MFInterfaceFAB< T > > &a_lhs, const T &a_value)
Set value in an MFInterfaceFAB data holder.
Definition CD_DataOpsImplem.H:24
AMR driver that deposits/interpolates ParticleContainer particles across the hierarchy.
Definition CD_EBAMRParticleMesh.H:95
int m_ghost
Number of ghost cells in the mesh data holders.
Definition CD_EBAMRParticleMesh.H:503
void defineTransitionMasks()
Build the per-width transition masks: the fine-side transition band, on the refined-coarse grid.
Definition CD_EBAMRParticleMesh.H:1056
void interpolate(ParticleContainer< P, Traits > &a_particles, const EBAMRCellData &a_meshData, const DepositionType a_interpType, const bool a_forceIrregNGP) const
Interpolate a mesh field onto one or more payload columns, across all levels.
Definition CD_EBAMRParticleMesh.H:185
~EBAMRParticleMesh()=default
Destructor.
void define(const Vector< RefCountedPtr< EBLevelGrid > > &a_eblgs, const Vector< int > &a_refRat, const Vector< Real > &a_dx, const RealVect &a_probLo, const int a_ghost, const int a_finestLevel)
Define the per-level leaves, coarse-fine mesh operators, and halo/transition masks.
Definition CD_EBAMRParticleMesh.H:135
void interpolateWeight(ParticleContainer< P, Traits > &a_particles, const EBAMRCellData &a_meshData, const DepositionType a_interpType, const bool a_forceIrregNGP) const
Interpolate a mesh field onto the container-owned weight column, across all levels.
Definition CD_EBAMRParticleMesh.H:225
int getTransitionMaskWidth(const DepositionType a_depositionType, const int a_refRat) const
Transition-mask width for a kernel: CIC -> refRat/2, TSC -> refRat (NGP is handled upstream).
Definition CD_EBAMRParticleMesh.H:1030
void transferMaskParticlesTransition(Container &a_particles, const DepositionType a_depositionType) const
Move the coarse-side transition particles into the container mask holder (using the FiCo mask).
Definition CD_EBAMRParticleMesh.H:1160
EBAMRParticleMesh & operator=(const EBAMRParticleMesh &)=delete
Copy assignment is deleted.
std::map< int, Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > > m_outerHaloMasks
Outer-halo masks keyed by halo width: per-level coarse cells just outside the fine patch.
Definition CD_EBAMRParticleMesh.H:538
Vector< RefCountedPtr< EBCoarseFineParticleMesh > > m_coarseFinePM
Per-level coarse-fine mesh operators (null on level 0).
Definition CD_EBAMRParticleMesh.H:528
Vector< Real > m_dx
Per-level grid spacing (isotropic).
Definition CD_EBAMRParticleMesh.H:493
void errorUnsupported() const
Abort on an unrecognized coarse-fine deposition strategy.
Definition CD_EBAMRParticleMesh.H:549
void defineEBParticleMesh()
Build the per-level per-patch EBParticleMesh leaves (valid grids + refined-coarse grids).
Definition CD_EBAMRParticleMesh.H:558
int m_finestLevel
Finest AMR level index.
Definition CD_EBAMRParticleMesh.H:508
EBAMRParticleMesh(const EBAMRParticleMesh &)=delete
Copy construction is deleted (shared RefCountedPtr state).
void defineOuterHaloMasks()
Build the per-width outer-halo masks: per level, the coarse cells just outside the fine patch.
Definition CD_EBAMRParticleMesh.H:720
void depositHaloNGPCore(EBAMRCellData &a_meshData, const Container &a_particles, PatchDeposit a_patch, PatchDepositNGP a_patchNGP) const
The CoarseFineDeposition::HaloNGP deposition algorithm.
Definition CD_EBAMRParticleMesh.H:965
RealVect m_probLo
Lower-left corner of the physical domain.
Definition CD_EBAMRParticleMesh.H:498
void deposit(EBAMRCellData &a_meshData, const ParticleContainer< P, Traits > &a_particles, const DepositionType a_depositionType, const CoarseFineDeposition a_coarseFineDeposition, const IrregularDeposition a_irregularDeposition)
Deposit one or more payload columns onto the AMR mesh.
Definition CD_EBAMRParticleMesh.H:424
bool m_isDefined
Whether define() has been called.
Definition CD_EBAMRParticleMesh.H:513
Vector< RefCountedPtr< LayoutData< EBParticleMesh > > > m_ebParticleMesh
Per-level per-patch deposition/interpolation leaves.
Definition CD_EBAMRParticleMesh.H:518
Vector< RefCountedPtr< EBLevelGrid > > m_eblgs
Per-level EB level grids.
Definition CD_EBAMRParticleMesh.H:483
std::map< int, Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > > m_transitionMasks
Transition masks keyed by width: per-level fine-side transition band, on the refined-coarse grid.
Definition CD_EBAMRParticleMesh.H:543
Vector< Copier > m_levelCopiers
Per-level valid+ghost -> valid Copiers (fold ghost-deposited mass into the owner patch).
Definition CD_EBAMRParticleMesh.H:523
void depositWeight(EBAMRCellData &a_meshData, const ParticleContainer< P, Traits > &a_particles, const DepositionType a_depositionType, const CoarseFineDeposition a_coarseFineDeposition, const IrregularDeposition a_irregularDeposition)
Deposit the container-owned weight onto the AMR mesh.
Definition CD_EBAMRParticleMesh.H:272
EBAMRParticleMesh()
Default constructor. Leaves the object undefined; call define().
Definition CD_EBAMRParticleMesh.H:105
void depositGathered(EBAMRCellData &a_meshData, const ParticleContainer< P, Traits > &a_particles, const DepositionType a_depositionType, const CoarseFineDeposition a_coarseFineDeposition, const IrregularDeposition a_irregularDeposition, CellGather a_cellGather)
Deposit a custom per-particle scalar (computed by a_cellGather) onto the AMR mesh.
Definition CD_EBAMRParticleMesh.H:342
void depositTransitionCore(EBAMRCellData &a_meshData, const Container &a_particles, const DepositionType a_depositionType, PatchDeposit a_patch) const
The CoarseFineDeposition::Transition deposition algorithm.
Definition CD_EBAMRParticleMesh.H:1233
void depositInterpCore(EBAMRCellData &a_meshData, const Container &a_particles, const int a_numComp, PatchDeposit a_patchDeposit) const
The CoarseFineDeposition::Interp deposition algorithm, parameterized by the per-patch deposit.
Definition CD_EBAMRParticleMesh.H:663
Vector< RefCountedPtr< LayoutData< EBParticleMesh > > > m_ebParticleMeshFiCo
Per-level per-patch leaves on the refined-coarse (FiCo) grid (null on level 0).
Definition CD_EBAMRParticleMesh.H:533
void depositHaloCore(EBAMRCellData &a_meshData, const Container &a_particles, PatchDeposit a_patchDeposit) const
The CoarseFineDeposition::Halo deposition algorithm.
Definition CD_EBAMRParticleMesh.H:869
void defineCoarseFineMotion()
Build the per-level coarse-fine mesh operators (null on level 0).
Definition CD_EBAMRParticleMesh.H:632
void defineLevelMotion()
Build the per-level valid+ghost -> valid Copiers.
Definition CD_EBAMRParticleMesh.H:614
Vector< int > m_refRat
Per-level refinement ratios.
Definition CD_EBAMRParticleMesh.H:488
A Copier class for making copying between BoxLayoutData<EBCellFAB> easier. This increments EBCellFABs...
Definition CD_EBAddOp.H:28
A class for handling particle deposition clouds that hang over refinement boundaries....
Definition CD_EBCoarseFineParticleMesh.H:42
Deposits/interpolates ParticleSoA leaves on a single patch, with embedded-boundary (cut-cell) awarene...
Definition CD_EBParticleMesh.H:71
void depositWeight(EBCellFAB &a_meshData, const int a_comp, const ParticleSoA< P, Traits > &a_particles, const DepositionType a_depositionType, const Real a_widthScale, const bool a_forceIrregNGP) const
Deposit the container-owned weight column onto mesh component a_comp.
Definition CD_EBParticleMesh.H:136
void interpolateWeight(ParticleSoA< P, Traits > &a_particles, const EBCellFAB &a_meshData, const int a_comp, const DepositionType a_interpType, const bool a_forceIrregNGP) const
Interpolate mesh component a_comp onto the container-owned weight column.
Definition CD_EBParticleMesh.H:360
void depositGathered(EBCellFAB &a_meshData, const int a_comp, const ParticleSoA< P, Traits > &a_particles, const DepositionType a_depositionType, const Real a_widthScale, const bool a_forceIrregNGP, GatherFunc &&a_gather) const
Deposit a custom per-particle scalar (computed by a_gather) onto mesh component a_comp.
Definition CD_EBParticleMesh.H:263
AMR-hierarchy container of computational particles, stored per patch in Struct-of-Arrays form.
Definition CD_ParticleContainer.H:123