chombo-discharge
Loading...
Searching...
No Matches
CD_AmrMeshImplem.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_AMRMESHIMPLEM_H
14#define CD_AMRMESHIMPLEM_H
15
16// Our includes
17#include <CD_AmrMesh.H>
18#include <CD_ParticleOps.H>
19#include <CD_NamespaceHeader.H>
20
21template <typename T>
22void
24 const EBAMRData<T>& a_src,
26 const CopyStrategy& a_fromRegion) const noexcept
27{
28 CH_TIME("AmrMesh::copyData(EBAMRData, simple)");
29 if (m_verbosity > 5) {
30 pout() << "AmrMesh::copyData(EBAMRData, simple)" << endl;
31 }
32
33 const int nComp = a_dst[0]->nComp();
34 const Interval dstComps = Interval(0, nComp - 1);
35 const Interval srcComps = Interval(0, nComp - 1);
36
37 const std::string toRealm = a_dst.getRealm();
38 const std::string fromRealm = a_src.getRealm();
39
40 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
43
45 }
46}
47
48template <typename T>
49void
51 const EBAMRData<T>& a_src,
52 const Interval& a_dstComps,
53 const Interval& a_srcComps,
55 const CopyStrategy& a_fromRegion) const noexcept
56{
57 CH_TIME("AmrMesh::copyData(EBAMRData, full)");
58 if (m_verbosity > 5) {
59 pout() << "AmrMesh::copyData(EBAMRData, full)" << endl;
60 }
61
62 const std::string toRealm = a_dst.getRealm();
63 const std::string fromRealm = a_src.getRealm();
64
65 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
68
70 }
71}
72
73template <typename T>
74void
76 const LevelData<T>& a_src,
77 const int a_level,
81 const CopyStrategy& a_fromRegion) const noexcept
82{
83 CH_TIME("AmrMesh::copyData(LD<T>_full)");
84 if (m_verbosity > 5) {
85 pout() << "AmrMesh::copyData(LD<T>_full)" << endl;
86 }
87
88 const Interval dstComps = Interval(0, a_dst.nComp() - 1);
89 const Interval srcComps = Interval(0, a_src.nComp() - 1);
90
92}
93
94template <typename T>
95void
97 const LevelData<T>& a_src,
98 const int a_level,
101 const Interval& a_dstComps,
102 const Interval& a_srcComps,
104 const CopyStrategy& a_fromRegion) const noexcept
105{
106 CH_TIME("AmrMesh::copyData(LD<T>_full)");
107 if (m_verbosity > 5) {
108 pout() << "AmrMesh::copyData(LD<T>_full)" << endl;
109 }
110
111 CH_assert(a_dstComps.size() == a_srcComps.size());
112 CH_assert(a_dst.nComp() > a_dstComps.end());
113 CH_assert(a_src.nComp() > a_srcComps.end());
114
115 if (a_toRealm != a_fromRealm) {
116 const auto id = std::make_pair(a_fromRealm, a_toRealm);
117
118 if (a_toRegion == CopyStrategy::ValidGhost) {
119 CH_assert(a_dst.ghostVect() == m_numGhostCells * IntVect::Unit);
120 }
121 if (a_fromRegion == CopyStrategy::ValidGhost) {
122 CH_assert(a_src.ghostVect() == m_numGhostCells * IntVect::Unit);
123 }
124
126
127 if (a_fromRegion == CopyStrategy::Valid) {
128 if (a_toRegion == CopyStrategy::Valid) {
129 copier = m_validToValidRealmCopiers.at(id)[a_level];
130 }
131 else if (a_toRegion == CopyStrategy::ValidGhost) {
132 copier = m_validToValidGhostRealmCopiers.at(id)[a_level];
133 }
134 else {
135 MayDay::Abort("AmrMesh::copyData - logic bust 1");
136 }
137 }
138 else if (a_fromRegion == CopyStrategy::ValidGhost) {
139 if (a_toRegion == CopyStrategy::Valid) {
140 copier = m_validGhostToValidRealmCopiers.at(id)[a_level];
141 }
142 else if (a_toRegion == CopyStrategy::ValidGhost) {
143 copier = m_validGhostToValidGhostRealmCopiers.at(id)[a_level];
144 }
145 else {
146 MayDay::Abort("AmrMesh::copyData - logic bust 2");
147 }
148 }
149 else {
150 MayDay::Abort("AmrMesh::copyData - logic bust 3");
151 }
152
154 }
155 else {
156 a_src.localCopyTo(a_srcComps, a_dst, a_dstComps);
157 }
158}
159
160template <typename T>
161void
163{
164 CH_TIME("AmrMesh::deallocate(Vector<T*>)");
165 if (m_verbosity > 5) {
166 pout() << "AmrMesh::deallocate(Vector<T*>)" << endl;
167 }
168
169 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
170 delete a_data[lvl];
171 }
172}
173
174template <typename T>
175void
177{
178 CH_TIME("AmrMesh::deallocate(Vector<RefCountedPtr<T>)");
179 if (m_verbosity > 5) {
180 pout() << "AmrMesh::deallocate(Vector<RefCountedPtr<T>)" << endl;
181 }
182
183 for (int lvl = 0; lvl < a_data.size(); lvl++) {
184 // delete &a_data[lvl];
186#if 0
187 if(!a_data[lvl].isNull()){
188 delete &(*a_data[lvl]);
190 }
191
192#endif
193 }
194}
195
196template <typename T>
197void
199{
200 CH_TIME("AmrMesh::deallocate(EBAMRData<T>)");
201 if (m_verbosity > 5) {
202 pout() << "AmrMesh::deallocate(EBAMRData<T>)" << endl;
203 }
204
205 return this->deallocate(a_data.getData());
206}
207
208template <typename T>
209void
211{
212 CH_TIME("AmrMesh::alias(Vector<T*>, Vector<RefCountedPtr<T>)");
213 if (m_verbosity > 5) {
214 pout() << "AmrMesh::alias(Vector<T*>, Vector<RefCountedPtr<T>)" << endl;
215 }
216
217 a_alias.resize(a_data.size());
218
219 for (int lvl = 0; lvl < a_data.size(); lvl++) {
220 a_alias[lvl] = &(*a_data[lvl]);
221 }
222}
223
224template <typename T, typename S>
225void
227{
228 CH_TIME("AmrMesh::alias(Vector<T*>, EBAMRData<S>)");
229 if (m_verbosity > 5) {
230 pout() << "AmrMesh::alias(Vector<T*>, EBAMRData<S>" << endl;
231 }
232
233 return this->alias(a_alias, a_data.getData());
234}
235
236template <typename T>
237void
239{
240 CH_TIME("AmrMesh::allocate(Vector<RefCountedPtr<ParticleData<T> > >, string)");
241 if (m_verbosity > 5) {
242 pout() << "AmrMesh::allocate(Vector<RefCountedPtr<ParticleData<T> > >, string)" << endl;
243 }
244
245 if (!this->queryRealm(a_realm)) {
246 const std::string
247 str = "AmrMesh::allocate(Vector<RefCountedPtr<ParticleData<T> > >, string) - could not find Realm '" + a_realm +
248 "'";
249 MayDay::Abort(str.c_str());
250 }
251
254 "AmrMesh::allocate(Vector<RefCountedPtr<ParticleData<T> > >, string) - only constant box sizes supported for particle methods");
255 }
256
257 a_particles.resize(1 + m_finestLevel);
258
259 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
260 const DisjointBoxLayout& dbl = m_realms[a_realm]->getGrids()[lvl];
261 const ProblemDomain& domain = m_realms[a_realm]->getDomains()[lvl];
262
263 const Real dx = m_dx[lvl];
264
267 }
268}
269
270template <typename T>
271void
273{
274 CH_TIME("AmrMesh::allocate(ParticleContainer<T>, int, string)");
275 if (m_verbosity > 5) {
276 pout() << "AmrMesh::allocate(ParticleContainer<T>, int, string)" << endl;
277 }
278
279 if (!this->queryRealm(a_realm)) {
280 const std::string str = "AmrMesh::allocate(ParticleContainer<T>, int, string) - could not find Realm '" + a_realm +
281 "'";
282 MayDay::Abort(str.c_str());
283 }
284
287 "AmrMesh::allocate(ParticleContainer<T>, int, string) - only constant box sizes are supported for particle methods");
288 }
289
296 m_probLo,
299 a_realm);
300}
301
302template <typename T>
303void
305{
306 CH_TIME("AmrMesh::allocatePointer(Vector<RefCountedPtr<T> >)");
307 if (m_verbosity > 5) {
308 pout() << "AmrMesh::allocatePointer(Vector<RefCountedPtr<T> >)" << endl;
309 }
310
311 a_data.resize(1 + m_finestLevel);
312 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
313 a_data[lvl] = RefCountedPtr<T>(new T());
314 }
315}
316
317template <typename T>
318void
320{
321 CH_TIME("AmrMesh::allocatePointer(Vector<RefCountedPtr<T> >, int)");
322 if (m_verbosity > 5) {
323 pout() << "AmrMesh::allocatePointer(Vector<RefCountedPtr<T> >, int)" << endl;
324 }
325
326 a_data.resize(1 + a_finestLevel);
327
328 for (int lvl = 0; lvl <= a_finestLevel; lvl++) {
329 a_data[lvl] = RefCountedPtr<T>(new T());
330 }
331}
332
333template <typename T>
334void
336{
337 CH_TIME("AmrMesh::allocatePointer(EBAMRData<T>, std::string)");
338 if (m_verbosity > 5) {
339 pout() << "AmrMesh::allocatePointer(EBAMRData<T>, std::string)" << endl;
340 }
341
342 this->allocatePointer(a_data.getData());
343
345}
346
347template <typename T>
348void
350{
351 CH_TIME("AmrMesh::allocatePointer(EBAMRData<T>, std::string, int)");
352 if (m_verbosity > 5) {
353 pout() << "AmrMesh::allocatePointer(EBAMRData<T>, std::string, int)" << endl;
354 }
355
356 this->allocatePointer(a_data.getData(), a_finestLevel);
357
359}
360
361template <class P>
362void
364{
365 CH_TIME("AmrMesh::remapToNewGrids");
366 if (m_verbosity > 5) {
367 pout() << "AmrMesh::remapToNewGrids" << endl;
368 }
369
370 const std::string realm = a_particles.getRealm();
371
372 a_particles.regrid(this->getGrids(realm),
373 this->getDomains(),
374 this->getDx(),
375 this->getRefinementRatios(),
376 this->getValidCells(realm),
377 this->getLevelTiles(realm),
378 a_lmin,
380}
381
382template <class P, class Ret, Ret (P::*MemberFunc)() const>
383void
385 const std::string& a_realm,
390 const bool a_forceIrregNGP)
391{
392 CH_TIME("AmrMesh::depositParticles");
393 if (m_verbosity > 5) {
394 pout() << "AmrMesh::depositParticles" << endl;
395 }
396
398
404}
405
406template <class P, typename Ret, Ret (P::*MemberFunc)() const>
407void
409 const std::string& a_realm,
411 const ParticleContainer<P>& a_particles) const noexcept
412{
413 CH_TIME("AmrMesh::depositParticles(surface)");
414 if (m_verbosity > 5) {
415 pout() << "AmrMesh::depositParticles(surface)" << endl;
416 }
417
418 CH_assert(a_meshData[0]->nComp() == 1);
419 CH_assert(a_meshData.getRealm() == a_particles.getRealm());
420
421 EBAMRSurfaceDeposition& surfaceDeposition = this->getSurfaceDeposition(a_realm, a_phase);
422
424}
425
426template <class P, class Ret, Ret (P::*MemberFunc)()>
427void
429 const std::string& a_realm,
433 const bool a_forceIrregNGP) const
434{
435 CH_TIME("AmrMesh::interpolateParticles(scalar)");
436 if (m_verbosity > 5) {
437 pout() << "AmrMesh::interpolateParticles(scalar)" << endl;
438 }
439
440 CH_assert(a_realm == a_particles.getRealm());
441 CH_assert(a_realm == a_meshScalarField.getRealm());
442
444
446}
447
448template <class P>
449void
452 const Real a_tolerance) const
453{
454 CH_TIME("AmrMesh::removeCoveredParticlesIF");
455 if (m_verbosity > 5) {
456 pout() << "AmrMesh::removeCoveredParticlesIF" << endl;
457 }
458
459 CH_assert(!a_particles.isOrganizedByCell());
460
461 // Figure out the implicit function
463
464 switch (a_phase) {
465 case phase::gas: {
467
468 break;
469 }
470 case phase::solid: {
472
473 break;
474 }
475 default: {
476 MayDay::Error("AmrMesh::removeCoveredParticlesIF - logic bust");
477 }
478 }
479
480 // Get the realm where the particles live.
481 const std::string whichRealm = a_particles.getRealm();
482
483 // Go through all particles and remove them if they are less than dx*a_tolerance away from the EB.
484 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
485 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
486 const DataIterator& dit = dbl.dataIterator();
487 const Real dx = this->getDx()[lvl];
488 const Real tol = a_tolerance * dx;
489
490 const int nbox = dit.size();
491#pragma omp parallel for schedule(runtime)
492 for (int mybox = 0; mybox < nbox; mybox++) {
493 const DataIndex& din = dit[mybox];
494
495 List<P>& particles = a_particles[lvl][din].listItems();
496
497 // Check if particles are outside the implicit function.
498 for (ListIterator<P> lit(particles); lit.ok();) {
499 const RealVect& pos = lit().position();
500
501 const Real f = implicitFunction->value(pos);
502
503 if (f > tol) {
504 particles.remove(lit);
505 }
506 else {
507 lit++;
508 }
509 }
510 }
511 }
512}
513
514template <class P>
515void
518 const Real a_tolerance) const
519{
520 CH_TIME("AmrMesh::removeCoveredParticlesDiscrete");
521 if (m_verbosity > 5) {
522 pout() << "AmrMesh::removeCoveredParticlesDiscrete" << endl;
523 }
524
525 CH_assert(!a_particles.isOrganizedByCell());
526
527 // Get the realm where the particles live.
528 const std::string whichRealm = a_particles.getRealm();
529
530 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
531 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
532 const DataIterator& dit = dbl.dataIterator();
533 const EBISLayout& ebisl = this->getEBISLayout(whichRealm, a_phase)[lvl];
534 const Real dx = this->getDx()[lvl];
535 const Real tol = a_tolerance * dx;
536
537 const int nbox = dit.size();
538#pragma omp parallel for schedule(runtime)
539 for (int mybox = 0; mybox < nbox; mybox++) {
540 const DataIndex& din = dit[mybox];
541 const EBISBox& ebisBox = ebisl[din];
542 const Box region = ebisBox.getRegion();
543
544 const bool isRegular = ebisBox.isAllRegular();
545 const bool isCovered = ebisBox.isAllCovered();
546 const bool isIrregular = !isRegular && !isCovered;
547
548 List<P>& particles = a_particles[lvl][din].listItems();
549
550 if (isCovered) {
551 particles.clear();
552 }
553 else if (isIrregular) {
554 for (ListIterator<P> lit(particles); lit.ok();) {
555 const P& particle = lit();
556 const RealVect& pos = particle.position();
557
558 // Get the cell where the particle lives.
560
561 CH_assert(region.contains(iv));
562
563 if (ebisBox.isCovered(iv)) {
564 particles.remove(lit);
565 }
566 else if (ebisBox.isIrregular(iv)) {
567
568 // There could potentially be multiple degrees of freedom -- we check if the particle is inside at least one
569 // of the VoFs in the cell.
570
571 bool insideAtLeastOneVoF = false;
572
573 // For each VoF, compute the projection of the particle position onth the EB face. Because the EB normal points outwards, we have a positive
574 // value if the particle lies in the valid region.
575 const std::vector<VolIndex> vofs = ebisBox.getVoFs(iv).stdVector();
576 for (const auto& vof : vofs) {
577 const RealVect ebNormal = ebisBox.normal(vof);
578 const RealVect ebCentroid = m_probLo + Location::position(Location::Cell::Boundary, vof, ebisBox, dx);
579 const Real faceProjection = ebNormal.dotProduct(pos - ebCentroid);
580
581 if (faceProjection >= -tol) {
582 insideAtLeastOneVoF = true;
583
584 break;
585 }
586 }
587
588 if (!insideAtLeastOneVoF) {
589 particles.remove(lit);
590 }
591 else {
592 ++lit;
593 }
594 }
595 else {
596 ++lit;
597 }
598 }
599 }
600 }
601 }
602}
603
604template <class P>
605void
607{
608 CH_TIME("AmrMesh::removeCoveredParticlesVoxels");
609 if (m_verbosity > 5) {
610 pout() << "AmrMesh::removeCoveredParticlesVoxels" << endl;
611 }
612
613 CH_assert(!a_particles.isOrganizedByCell());
614
615 // Get the realm where the particles live.
616 const std::string whichRealm = a_particles.getRealm();
617
618 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
619 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
620 const DataIterator& dit = dbl.dataIterator();
621 const EBISLayout& ebisl = this->getEBISLayout(whichRealm, a_phase)[lvl];
622 const Real dx = this->getDx()[lvl];
623
624 const int nbox = dit.size();
625#pragma omp parallel for schedule(runtime)
626 for (int mybox = 0; mybox < nbox; mybox++) {
627 const DataIndex& din = dit[mybox];
628 const EBISBox& ebisBox = ebisl[din];
629 const Box region = ebisBox.getRegion();
630
631 const bool isRegular = ebisBox.isAllRegular();
632 const bool isCovered = ebisBox.isAllCovered();
633 const bool isIrregular = !isRegular && !isCovered;
634
635 List<P>& particles = a_particles[lvl][din].listItems();
636
637 if (isCovered) {
638 particles.clear();
639 }
640 else if (isIrregular) {
641 for (ListIterator<P> lit(particles); lit.ok();) {
642 const P& particle = lit();
643 const RealVect& pos = particle.position();
644
645 // Get the cell where the particle lives.
646 const RealVect rv = (pos - m_probLo) / dx;
647 const IntVect iv = IntVect(D_DECL(floor(rv[0]), floor(rv[1]), floor(rv[2])));
648
649 CH_assert(region.contains(iv));
650
651 if (ebisBox.isCovered(iv)) {
652 particles.remove(lit);
653 }
654 else {
655 ++lit;
656 }
657 }
658 }
659 }
660 }
661}
662
663template <class P>
664void
668 const Real a_tolerance) const
669{
670 CH_TIME("AmrMesh::transferCoveredParticlesIF");
671 if (m_verbosity > 5) {
672 pout() << "AmrMesh::transferCoveredParticlesIF" << endl;
673 }
674
675 CH_assert(!a_particlesFrom.isOrganizedByCell());
676 CH_assert(!a_particlesTo.isOrganizedByCell());
677
678 // Figure out the implicit function
680
681 switch (a_phase) {
682 case phase::gas: {
684
685 break;
686 }
687 case phase::solid: {
689
690 break;
691 }
692 default: {
693 MayDay::Error("AmrMesh::removeCoveredParticlesIF - logic bust");
694
695 break;
696 }
697 }
698
699 // Get the realm where the particles live.
700 const std::string realmFrom = a_particlesFrom.getRealm();
701 const std::string realmTo = a_particlesTo.getRealm();
702
704
705 // Go through all particles and remove them if they are less than dx*a_tolerance away from the EB.
706 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
707 const DisjointBoxLayout& dbl = this->getGrids(realmFrom)[lvl];
708 const DataIterator& dit = dbl.dataIterator();
709 const Real dx = this->getDx()[lvl];
710 const Real tol = a_tolerance * dx;
711
712 const int nbox = dit.size();
713#pragma omp parallel for schedule(runtime)
714 for (int mybox = 0; mybox < nbox; mybox++) {
715 const DataIndex& din = dit[mybox];
716
718 List<P>& particlesTo = a_particlesTo[lvl][din].listItems();
719
720 // Check if particles are outside the implicit function.
721 for (ListIterator<P> lit(particlesFrom); lit.ok();) {
722 const RealVect& pos = lit().position();
723
724 const Real f = implicitFunction->value(pos);
725
726 if (f > tol) {
727 particlesTo.transfer(lit);
728 }
729 else {
730 ++lit;
731 }
732 }
733 }
734 }
735}
736
737template <class P>
738void
742 const Real a_tolerance) const
743{
744 CH_TIME("AmrMesh::transferCoveredParticlesDiscrete");
745 if (m_verbosity > 5) {
746 pout() << "AmrMesh::transferCoveredParticlesDiscrete" << endl;
747 }
748
749 CH_assert(!a_particlesFrom.isOrganizedByCell());
750 CH_assert(!a_particlesTo.isOrganizedByCell());
751
752 // Get the realm where the particles live.
753 const std::string realmFrom = a_particlesFrom.getRealm();
754 const std::string realmTo = a_particlesTo.getRealm();
755
757
758 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
759 const DisjointBoxLayout& dbl = this->getGrids(realmFrom)[lvl];
760 const DataIterator& dit = dbl.dataIterator();
761 const EBISLayout& ebisl = this->getEBISLayout(realmFrom, a_phase)[lvl];
762 const Real dx = this->getDx()[lvl];
763 const Real tol = a_tolerance * dx;
764
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 const EBISBox& ebisBox = ebisl[din];
770 const Box region = ebisBox.getRegion();
771
772 const bool isRegular = ebisBox.isAllRegular();
773 const bool isCovered = ebisBox.isAllCovered();
774 const bool isIrregular = !isRegular && !isCovered;
775
777 List<P>& particlesTo = a_particlesTo[lvl][din].listItems();
778
779 if (isCovered) {
780 particlesTo.catenate(particlesFrom);
781 }
782 else if (isIrregular) {
783 for (ListIterator<P> lit(particlesFrom); lit.ok();) {
784 const P& particle = lit();
785 const RealVect& pos = particle.position();
786
787 // Get the cell where the particle lives.
789
790 CH_assert(region.contains(iv));
791
792 if (ebisBox.isCovered(iv)) {
793 particlesTo.transfer(lit);
794 }
795 else if (ebisBox.isIrregular(iv)) {
796 // There could potentially be multiple degrees of freedom -- we check if the particle is inside at least one of the VoFs in the cell.
797
798 bool insideAtLeastOneVoF = false;
799
800 // For each VoF, compute the projection of the particle position onth the EB face. Because the EB normal points outwards, we have a positive
801 // value if the particle lies in the valid region.
802 const std::vector<VolIndex> vofs = ebisBox.getVoFs(iv).stdVector();
803 for (const auto& vof : vofs) {
804 const RealVect ebCentroid = m_probLo + Location::position(Location::Cell::Boundary, vof, ebisBox, dx);
805 const RealVect ebNormal = ebisBox.normal(vof);
806 const Real faceProjection = ebNormal.dotProduct(pos - ebCentroid);
807
808 if (faceProjection >= -tol) {
809 insideAtLeastOneVoF = true;
810
811 break;
812 }
813 }
814
815 if (!insideAtLeastOneVoF) {
816 particlesTo.transfer(lit);
817 }
818 else {
819 ++lit;
820 }
821 }
822 else {
823 ++lit;
824 }
825 }
826 }
827 }
828 }
829}
830
831template <class P>
832void
835 const phase::which_phase& a_phase) const
836{
837 CH_TIME("AmrMesh::transferCoveredParticlesVoxels");
838 if (m_verbosity > 5) {
839 pout() << "AmrMesh::transferCoveredParticlesVoxels" << endl;
840 }
841
842 CH_assert(!a_particlesFrom.isOrganizedByCell());
843 CH_assert(!a_particlesTo.isOrganizedByCell());
844
845 // Get the realm where the particles live.
846 const std::string realmFrom = a_particlesFrom.getRealm();
847 const std::string realmTo = a_particlesTo.getRealm();
848
850
851 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
852 const DisjointBoxLayout& dbl = this->getGrids(realmFrom)[lvl];
853 const DataIterator dit = dbl.dataIterator();
854 const EBISLayout& ebisl = this->getEBISLayout(realmFrom, a_phase)[lvl];
855 const Real dx = this->getDx()[lvl];
856
857 const int nbox = dit.size();
858#pragma omp parallel for schedule(runtime)
859 for (int mybox = 0; mybox < nbox; mybox++) {
860 const DataIndex& din = dit[mybox];
861 const EBISBox& ebisBox = ebisl[din];
862 const Box region = ebisBox.getRegion();
863
864 const bool isRegular = ebisBox.isAllRegular();
865 const bool isCovered = ebisBox.isAllCovered();
866 const bool isIrregular = !isRegular && !isCovered;
867
869 List<P>& particlesTo = a_particlesTo[lvl][din].listItems();
870
871 if (isCovered) {
872 particlesTo.catenate(particlesFrom);
873 }
874 else if (isIrregular) {
875 for (ListIterator<P> lit(particlesFrom); lit.ok();) {
876 const P& particle = lit();
877 const RealVect& pos = particle.position();
878
879 // Get the cell where the particle lives.
881
882 CH_assert(region.contains(iv));
883
884 if (ebisBox.isCovered(iv)) {
885 particlesTo.transfer(lit);
886 }
887 else {
888 ++lit;
889 }
890 }
891 }
892 }
893 }
894}
895
896template <class P>
897void
901 const std::function<void(P&)>& a_transferModifier) const noexcept
902{
903 CH_TIME("AmrMesh::transferIrregularParticles");
904 if (m_verbosity > 5) {
905 pout() << "AmrMesh::transferIrregularParticles" << endl;
906 }
907
908 CH_assert(a_dstParticles.getRealm() == a_srcParticles.getRealm());
909
910 const std::string realm = a_dstParticles.getRealm();
911
912 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
913 const DisjointBoxLayout& dbl = this->getGrids(realm)[lvl];
914 const DataIterator& dit = dbl.dataIterator();
915 const EBISLayout& ebisl = this->getEBISLayout(realm, a_phase)[lvl];
916 const ProblemDomain& domain = this->getDomains()[lvl];
917 const RealVect probLo = this->getProbLo();
918 const Real dx = this->getDx()[lvl];
919
920 const int nbox = dit.size();
921#pragma omp parallel for schedule(runtime)
922 for (int mybox = 0; mybox < nbox; mybox++) {
923 const DataIndex& din = dit[mybox];
924
925 const Box cellBox = dbl[din];
926 const EBISBox& ebisbox = ebisl[din];
927
928 List<P>& dstParticles = a_dstParticles[lvl][din].listItems();
929 List<P>& srcParticles = a_srcParticles[lvl][din].listItems();
930
931 for (ListIterator<P> lit(srcParticles); lit.ok();) {
932 P& p = lit();
933
934 const IntVect iv = ParticleOps::getParticleCellIndex(p.position(), probLo, dx);
935
936 if (!(cellBox.contains(iv))) {
937 MayDay::Warning("CD_AmrMeshImplem.H in routine 'transferIrregularParticles' - particle not in box!");
938
939 ++lit;
940 }
941
942 if (ebisbox.isIrregular(iv)) {
943 bool insideAnyVoF = false;
944
945 const Vector<VolIndex> allVoFs = ebisbox.getVoFs(iv);
946
947 for (int i = 0; i < allVoFs.size(); i++) {
948 const VolIndex& vof = allVoFs[i];
949 const RealVect normal = ebisbox.normal(vof);
950 const RealVect ebPos = probLo + Location::position(Location::Cell::Boundary, vof, ebisbox, dx);
951
952 // Note: Can have normal = 0!
953 if ((p.position() - ebPos).dotProduct(normal) >= 0.0) {
954 insideAnyVoF = true;
955 }
956 }
957
958 if (!insideAnyVoF) {
959 const VolIndex& vof = allVoFs[0];
960 const RealVect ebPos = probLo + Location::position(Location::Cell::Boundary, vof, ebisbox, dx);
961
962 p.position() = ebPos;
963
965
966 dstParticles.transfer(lit);
967 }
968 else {
969 ++lit;
970 }
971 }
972 else {
973 ++lit;
974 }
975 }
976 }
977 }
978}
979
980template <class P>
981void
986 const Real a_tolerance,
987 const bool a_deleteParticles,
988 const std::function<void(P&)>& a_nonDeletionModifier) const noexcept
989{
990 CH_TIME("AmrMesh::intersectParticlesRaycastIF");
991 if (m_verbosity > 5) {
992 pout() << "AmrMesh::intersectParticlesRaycastIF" << endl;
993 }
994
995 CH_assert(a_activeParticles.getRealm() == a_ebParticles.getRealm());
996 CH_assert(a_activeParticles.getRealm() == a_domainParticles.getRealm());
997
998 a_ebParticles.clearParticles();
999 a_domainParticles.clearParticles();
1000
1001 const std::string whichRealm = a_activeParticles.getRealm();
1002
1003 // Figure out the implicit function
1005
1006 switch (a_phase) {
1007 case phase::gas: {
1008 implicitFunction = m_baseif.at(phase::gas);
1009
1010 break;
1011 }
1012 case phase::solid: {
1013 implicitFunction = m_baseif.at(phase::solid);
1014
1015 break;
1016 }
1017 default: {
1018 MayDay::Error("AmrMesh::intersectParticlesRaycastIF - logic bust");
1019
1020 break;
1021 }
1022 }
1023
1024 // Safety factor to prevent particles falling off the domain if they intersect the high-side of the domain
1025 constexpr Real safety = 1.E-12;
1026
1027 // Level loop -- go through each AMR level
1028 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
1029
1030 // Handle to various grid stuff.
1031 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
1032 const DataIterator& dit = dbl.dataIterator();
1033
1034 const int nbox = dit.size();
1035#pragma omp parallel for schedule(runtime)
1036 for (int mybox = 0; mybox < nbox; mybox++) {
1037 const DataIndex& din = dit[mybox];
1038
1040 List<P>& ebParticles = a_ebParticles[lvl][din].listItems();
1042
1043 for (ListIterator<P> lit(activeParticles); lit.ok();) {
1044 P& particle = lit();
1045
1046 const RealVect newPos = particle.position();
1047 const RealVect oldPos = particle.oldPosition();
1048 const RealVect path = newPos - oldPos;
1049
1050 // Cheap initial tests that allow us to skip some intersections tests.
1051 bool checkEB = false;
1052 bool checkDomain = false;
1053
1054 if (!implicitFunction.isNull()) {
1055 checkEB = true;
1056 }
1057 for (int dir = 0; dir < SpaceDim; dir++) {
1058 const bool outsideLo = newPos[dir] < m_probLo[dir];
1059 const bool outsideHi = newPos[dir] > m_probHi[dir];
1060
1061 if (outsideLo || outsideHi) {
1062 checkDomain = true;
1063 }
1064 }
1065
1066 // Do the intersection tests.
1067 if (checkEB || checkDomain) {
1068
1069 // These are the solution
1070 Real sDomain = std::numeric_limits<Real>::max();
1071 Real sEB = std::numeric_limits<Real>::max();
1072
1073 bool contactDomain = false;
1074 bool contactEB = false;
1075
1076 // Check if the particle intersected the domain. If it did, we compute sDomain such that the intersection
1077 // point with the domain is X = X0 + sDomain * (X1-X0) where X1=newPos and X0=oldPos
1078 if (checkDomain) {
1080 }
1081
1082 // Check if the particle intersected the EB. If it did, we compute sEB such that the intersection
1083 // point with the domain is X = X0 + sEB * (X1-X0) where X1=newPos and X0=oldPos
1084 if (checkEB) {
1086 }
1087
1088 // Particle bumped into something.
1089 if (contactDomain || contactEB) {
1090 if (sEB <= sDomain) { // Crashed with EB "first".
1092
1093 // If we delete the original particles we can just transfer the one we have. Otherwise we create
1094 // a new particle.
1095 if (a_deleteParticles) {
1096 particle.position() = intersectionPos;
1097
1098 ebParticles.transfer(lit);
1099 }
1100 else {
1101 P p = lit();
1102
1103 p.position() = intersectionPos;
1104
1105 ebParticles.add(p);
1106
1108
1109 lit++;
1110 }
1111 }
1112 else {
1113 // Crashed with domain "first". Safety factor is to prevent particles falling off the high side of the domain
1114 const Real sSafety = std::max((Real)0.0, sDomain - safety);
1115
1117
1118 if (a_deleteParticles) {
1119 particle.position() = intersectionPos;
1120
1121 domainParticles.transfer(lit);
1122 }
1123 else {
1124 P p = lit();
1125
1126 p.position() = intersectionPos;
1127
1128 domainParticles.add(p);
1129
1131
1132 ++lit;
1133 }
1134 }
1135 }
1136 else {
1137 ++lit;
1138 }
1139 }
1140 else {
1141 ++lit;
1142 }
1143 }
1144 }
1145 }
1146
1147 // These need to be remapped.
1150}
1151
1152template <class P>
1153void
1158 const Real a_bisectionStep,
1159 const bool a_deleteParticles,
1160 const std::function<void(P&)>& a_nonDeletionModifier) const noexcept
1161{
1162 CH_TIME("AmrMesh::intersectParticlesBisectIF");
1163 if (m_verbosity > 5) {
1164 pout() << "AmrMesh::intersectParticlesBisectIF" << endl;
1165 }
1166
1167 CH_assert(a_activeParticles.getRealm() == a_ebParticles.getRealm());
1168 CH_assert(a_activeParticles.getRealm() == a_domainParticles.getRealm());
1169
1170 // TLDR: This is pretty much a hard-copy of intersectParticlesRaycastIF, with the exception that the EB intersection
1171 // test is replaced by a bisection test.
1172
1173 a_ebParticles.clearParticles();
1174 a_domainParticles.clearParticles();
1175
1176 const std::string whichRealm = a_activeParticles.getRealm();
1177
1178 // Figure out the implicit function
1180
1181 switch (a_phase) {
1182 case phase::gas: {
1183 implicitFunction = m_baseif.at(phase::gas);
1184
1185 break;
1186 }
1187 case phase::solid: {
1188 implicitFunction = m_baseif.at(phase::solid);
1189
1190 break;
1191 }
1192 default: {
1193 MayDay::Error("AmrMesh::intersectParticlesBisectIF - logic bust");
1194
1195 break;
1196 }
1197 }
1198
1199 // Safety factor to prevent particles falling off the domain if they intersect the high-side of the domain
1200 constexpr Real safety = 1.E-12;
1201
1202 // Level loop -- go through each AMR level
1203 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
1204
1205 // Handle to various grid stuff.
1206 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
1207 const DataIterator& dit = dbl.dataIterator();
1208
1209 const int nbox = dit.size();
1210#pragma omp parallel for schedule(runtime)
1211 for (int mybox = 0; mybox < nbox; mybox++) {
1212 const DataIndex& din = dit[mybox];
1213
1215 List<P>& ebParticles = a_ebParticles[lvl][din].listItems();
1217
1218 for (ListIterator<P> lit(activeParticles); lit.ok();) {
1219 P& particle = lit();
1220
1221 const RealVect newPos = particle.position();
1222 const RealVect oldPos = particle.oldPosition();
1223 const RealVect path = newPos - oldPos;
1224
1225 // Cheap initial tests that allow us to skip some intersections tests.
1226 bool checkEB = false;
1227 bool checkDomain = false;
1228
1229 if (!implicitFunction.isNull()) {
1230 checkEB = true;
1231 }
1232 for (int dir = 0; dir < SpaceDim; dir++) {
1233 const bool outsideLo = newPos[dir] < m_probLo[dir];
1234 const bool outsideHi = newPos[dir] > m_probHi[dir];
1235
1236 if (outsideLo || outsideHi) {
1237 checkDomain = true;
1238 }
1239 }
1240
1241 // Do the intersection tests.
1242 if (checkEB || checkDomain) {
1243
1244 // These are the solution
1245 Real sDomain = std::numeric_limits<Real>::max();
1246 Real sEB = std::numeric_limits<Real>::max();
1247
1248 bool contactDomain = false;
1249 bool contactEB = false;
1250
1251 // Check if the particle intersected the domain. If it did, we compute sDomain such that the intersection
1252 // point with the domain is X = X0 + sDomain * (X1-X0) where X1=newPos and X0=oldPos
1253 if (checkDomain) {
1255 }
1256
1257 // Check if the particle intersected the EB. If it did, we compute sEB such that the intersection
1258 // point with the domain is X = X0 + sEB * (X1-X0) where X1=newPos and X0=oldPos
1259 if (checkEB) {
1261 }
1262
1263 // Particle bumped into something.
1264 if (contactDomain || contactEB) {
1265 if (sEB <= sDomain) {
1266 // Crashed with EB "first".
1268
1269 if (a_deleteParticles) {
1270 particle.position() = intersectionPos;
1271
1272 ebParticles.transfer(lit);
1273 }
1274 else {
1275 P p = particle;
1276
1277 p.position() = intersectionPos;
1278
1279 ebParticles.add(p);
1280
1281 ++lit;
1282
1284 }
1285 }
1286 else {
1287 // Crashed with domain "first".
1288 const Real sSafety = std::max((Real)0.0, sDomain - safety);
1289
1291
1292 if (a_deleteParticles) {
1293 particle.position() = intersectionPos;
1294
1295 domainParticles.transfer(lit);
1296 }
1297 else {
1298 P p = particle;
1299
1300 p.position() = intersectionPos;
1301
1302 domainParticles.add(p);
1303
1304 ++lit;
1305
1307 }
1308 }
1309 }
1310 else {
1311 ++lit;
1312 }
1313 }
1314 else {
1315 ++lit;
1316 }
1317 }
1318 }
1319 }
1320
1321 // These need to be remapped.
1324}
1325
1326#include <CD_NamespaceFooter.H>
1327
1328#endif
Declaration of core class for handling AMR-related operations (with embedded boundaries)
CoarseFineDeposition
Coarse-fine deposition types (see CD_EBAMRParticleMesh for how these are handled).
Definition CD_CoarseFineDeposition.H:27
CopyStrategy
Enum for distinguishing how we copy data Valid => valid region ValidGhost => valid+ghost region.
Definition CD_CopyStrategy.H:24
DepositionType
Deposition types.
Definition CD_DepositionType.H:24
Declaration of a static class containing some common useful particle routines that would otherwise be...
void removeCoveredParticlesVoxels(ParticleContainer< P > &a_particles, const phase::which_phase &a_phase) const
Function which removes particles from the domain if they fall inside the EB.
Definition CD_AmrMeshImplem.H:606
void transferCoveredParticlesDiscrete(ParticleContainer< P > &a_particlesFrom, ParticleContainer< P > &a_particlesTo, const phase::which_phase &a_phase, const Real a_tolerance=0.0) const
Function which transferse particles from one particle container to another if they fall inside the EB...
Definition CD_AmrMeshImplem.H:739
void allocatePointer(Vector< RefCountedPtr< T > > &a_data) const
Allocate pointer but not any memory blocks.
Definition CD_AmrMeshImplem.H:304
const Vector< RefCountedPtr< LevelTiles > > & getLevelTiles(const std::string &a_realm) const
Get the tiled space representation.
Definition CD_AmrMesh.cpp:3353
void copyData(EBAMRData< T > &a_dst, const EBAMRData< T > &a_src, const CopyStrategy &a_toRegion=CopyStrategy::Valid, const CopyStrategy &a_fromRegion=CopyStrategy::Valid) const noexcept
Method for copying from a source container to a destination container. User supplies information abou...
Definition CD_AmrMeshImplem.H:23
void transferCoveredParticlesIF(ParticleContainer< P > &a_particlesFrom, ParticleContainer< P > &a_particlesTo, const phase::which_phase &a_phase, const Real a_tolerance=0.0) const
Function which transferse particles from one particle container to another if they fall inside the EB...
Definition CD_AmrMeshImplem.H:665
int m_maxBoxSize
Max box size.
Definition CD_AmrMesh.H:2109
const AMRMask & getValidCells(const std::string &a_realm) const
Get a map of all valid cells on a specified realm.
Definition CD_AmrMesh.cpp:3337
RealVect m_probLo
Domain simulation corner.
Definition CD_AmrMesh.H:2069
void remapToNewGrids(ParticleContainer< P > &a_particles, const int a_lmin, const int a_newFinestLevel) const noexcept
Regrid particle to new grids.
Definition CD_AmrMeshImplem.H:363
const Vector< DisjointBoxLayout > & getGrids(const std::string &a_realm) const
Get the grids.
Definition CD_AmrMesh.cpp:3185
void removeCoveredParticlesIF(ParticleContainer< P > &a_particles, const phase::which_phase &a_phase, const Real a_tolerance=0.0) const
Function which removes particles from the domain if they fall inside the EB.
Definition CD_AmrMeshImplem.H:450
int m_verbosity
Verbosity.
Definition CD_AmrMesh.H:2084
void removeCoveredParticlesDiscrete(ParticleContainer< P > &a_particles, const phase::which_phase &a_phase, const Real a_tolerance=0.0) const
Function which removes particles from the domain if they fall inside the EB.
Definition CD_AmrMeshImplem.H:516
void intersectParticlesBisectIF(ParticleContainer< P > &a_activeParticles, ParticleContainer< P > &a_ebParticles, ParticleContainer< P > &a_domainParticles, const phase::which_phase a_phase, const Real a_bisectionStep, const bool a_deleteParticles, const std::function< void(P &)> &a_nonDeletionModifier=[](P &) -> void { return;}) const noexcept
Particle intersection algorithm based on bisection.
Definition CD_AmrMeshImplem.H:1154
Vector< Real > m_dx
Level resolutions.
Definition CD_AmrMesh.H:2189
int m_finestLevel
Finest level.
Definition CD_AmrMesh.H:2089
void intersectParticlesRaycastIF(ParticleContainer< P > &a_activeParticles, ParticleContainer< P > &a_ebParticles, ParticleContainer< P > &a_domainParticles, const phase::which_phase a_phase, const Real a_tolerance, const bool a_deleteParticles, const std::function< void(P &)> &a_nonDeletionModifier=[](P &) -> void { return;}) const noexcept
Particle intersection algorithm based on ray-casting.
Definition CD_AmrMeshImplem.H:982
void depositParticles(EBAMRCellData &a_meshData, const std::string &a_realm, const phase::which_phase &a_phase, const ParticleContainer< P > &a_particles, const DepositionType a_depositionType, const CoarseFineDeposition a_coarseFineDeposition, const bool a_forceIrregNGP=false)
Deposit scalar particle quantities on the mesh.
Definition CD_AmrMeshImplem.H:384
void transferIrregularParticles(ParticleContainer< P > &a_dstParticles, ParticleContainer< P > &a_srcParticles, const phase::which_phase a_phase, const std::function< void(P &)> &a_transferModifier=[](P &) -> void { return;}) const noexcept
Transfer particles that are on the wrong side of the EB to a different container.
Definition CD_AmrMeshImplem.H:898
std::map< phase::which_phase, RefCountedPtr< BaseIF > > m_baseif
Implicit functions.
Definition CD_AmrMesh.H:1988
bool queryRealm(const std::string &a_realm) const
Query if a realm exists.
Definition CD_AmrMesh.cpp:3680
const Vector< Real > & getDx() const
Get spatial resolutions.
Definition CD_AmrMesh.cpp:3129
EBAMRParticleMesh & getParticleMesh(const std::string &a_realm, const phase::which_phase a_phase) const
Get EBAMRParticleMesh operator.
Definition CD_AmrMesh.cpp:3504
const Vector< EBISLayout > & getEBISLayout(const std::string &a_realm, const phase::which_phase a_phase) const
Get EBISLayouts for a Realm and phase.
Definition CD_AmrMesh.cpp:3201
std::map< std::string, RefCountedPtr< Realm > > m_realms
These are all the Realms.
Definition CD_AmrMesh.H:1983
int m_blockingFactor
Blocking factor.
Definition CD_AmrMesh.H:2124
void interpolateParticles(ParticleContainer< P > &a_particles, const std::string &a_realm, const phase::which_phase &a_phase, const EBAMRCellData &a_meshScalarField, const DepositionType a_interpType, const bool a_forceIrregNGP=false) const
Interpolate mesh data onto a particle position.
Definition CD_AmrMeshImplem.H:428
void allocate(Vector< RefCountedPtr< ParticleData< T > > > &a_particles, const std::string &a_realm) const
Template class for generic allocation of particle data.
Definition CD_AmrMeshImplem.H:238
void transferCoveredParticlesVoxels(ParticleContainer< P > &a_particlesFrom, ParticleContainer< P > &a_particlesTo, const phase::which_phase &a_phase) const
Function which transferse particles from one particle container to another if they fall inside the EB...
Definition CD_AmrMeshImplem.H:833
void alias(Vector< T * > &a_alias, const Vector< RefCountedPtr< T > > &a_data) const
Turn smart-pointer data structure into regular-pointer data structure.
Definition CD_AmrMeshImplem.H:210
void deallocate(Vector< T * > &a_data) const
Deallocate data.
Definition CD_AmrMeshImplem.H:162
const Vector< int > & getRefinementRatios() const
Get refinement ratios.
Definition CD_AmrMesh.cpp:3140
const Vector< ProblemDomain > & getDomains() const
Get domains.
Definition CD_AmrMesh.cpp:3163
Class for handling particle-mesh operations with AMR.
Definition CD_EBAMRParticleMesh.H:53
class for handling surface deposition of particles with EB and AMR.
Definition CD_EBAMRSurfaceDeposition.H:30
static bool ebIntersectionRaycast(const RefCountedPtr< BaseIF > &a_impFunc, const RealVect &a_oldPos, const RealVect &a_newPos, const Real &a_tolerance, Real &a_s)
Compute the intersection point between a particle path and an implicit function using a ray-casting a...
Definition CD_ParticleOpsImplem.H:222
static bool ebIntersectionBisect(const RefCountedPtr< BaseIF > &a_impFunc, const RealVect &a_oldPos, const RealVect &a_newPos, const Real &a_bisectStep, Real &a_s)
Compute the intersection point between a particle path and an implicit function using a bisection alg...
Definition CD_ParticleOpsImplem.H:178
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
static bool domainIntersection(const RealVect &a_oldPos, const RealVect &a_newPos, const RealVect &a_probLo, const RealVect &a_probHi, Real &a_s)
Compute the intersection point between a particle path and a domain side.
Definition CD_ParticleOpsImplem.H:132
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition CD_TracerParticleSolver.H:38
virtual void remap()
Remap particles.
Definition CD_TracerParticleSolverImplem.H:339
virtual void setRealm(const std::string &a_realm)
Set the solver realm.
Definition CD_TracerParticleSolverImplem.H:233
TracerParticleSolver()
Default constructor.
Definition CD_TracerParticleSolverImplem.H:26
virtual void deposit(EBAMRCellData &a_phi) const noexcept
Deposit particle weight on mesh.
Definition CD_TracerParticleSolverImplem.H:363
virtual void regrid(const int a_lmin, const int a_oldFinestLevel, const int a_newFinestLevel)
Regrid this solver.
Definition CD_TracerParticleSolverImplem.H:322
RealVect position(Location::Cell a_location, const VolIndex &a_vof, const EBISBox &a_ebisbox, const Real &a_dx)
Compute the position (ignoring the "origin) of a Vof.
Definition CD_LocationImplem.H:21
which_phase
Enumeration of supported phases.
Definition CD_MultiFluidIndexSpace.H:38
@ solid
Solid (dielectric) phase.
Definition CD_MultiFluidIndexSpace.H:40
@ gas
Gas phase.
Definition CD_MultiFluidIndexSpace.H:39