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,
25 const CopyStrategy& a_toRegion,
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++) {
41 CH_assert(!(a_dst[lvl].isNull()));
42 CH_assert(!(a_src[lvl].isNull()));
43
44 this->copyData(*a_dst[lvl], *a_src[lvl], lvl, toRealm, fromRealm, dstComps, srcComps, a_toRegion, a_fromRegion);
45 }
46}
47
48template <typename T>
49void
51 const EBAMRData<T>& a_src,
52 const Interval& a_dstComps,
53 const Interval& a_srcComps,
54 const CopyStrategy& a_toRegion,
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++) {
66 CH_assert(!(a_dst[lvl].isNull()));
67 CH_assert(!(a_src[lvl].isNull()));
68
69 this->copyData(*a_dst[lvl], *a_src[lvl], lvl, toRealm, fromRealm, a_dstComps, a_srcComps, a_toRegion, a_fromRegion);
70 }
71}
72
73template <typename T>
74void
75AmrMesh::copyData(LevelData<T>& a_dst,
76 const LevelData<T>& a_src,
77 const int a_level,
78 const std::string a_toRealm,
79 const std::string a_fromRealm,
80 const CopyStrategy& a_toRegion,
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
91 this->copyData(a_dst, a_src, a_level, a_toRealm, a_fromRealm, dstComps, srcComps, a_toRegion, a_fromRegion);
92}
93
94template <typename T>
95void
96AmrMesh::copyData(LevelData<T>& a_dst,
97 const LevelData<T>& a_src,
98 const int a_level,
99 const std::string a_toRealm,
100 const std::string a_fromRealm,
101 const Interval& a_dstComps,
102 const Interval& a_srcComps,
103 const CopyStrategy& a_toRegion,
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
125 Copier copier;
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
153 a_src.copyTo(a_srcComps, a_dst, a_dstComps, copier);
154 }
155 else {
156 a_src.localCopyTo(a_srcComps, a_dst, a_dstComps);
157 }
158}
159
160template <typename T>
161void
162AmrMesh::deallocate(Vector<T*>& a_data) const
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
176AmrMesh::deallocate(Vector<RefCountedPtr<T>>& a_data) const
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];
185 a_data[lvl] = RefCountedPtr<T>(0);
186#if 0
187 if(!a_data[lvl].isNull()){
188 delete &(*a_data[lvl]);
189 a_data[lvl] = RefCountedPtr<T> (NULL);
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
210AmrMesh::alias(Vector<T*>& a_alias, const Vector<RefCountedPtr<T>>& a_data) const
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
226AmrMesh::alias(Vector<T*>& a_alias, const EBAMRData<S>& a_data) const
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 P, typename Traits>
237void
238AmrMesh::allocate(ParticleContainer<P, Traits>& a_container, const std::string& a_realm) const
239{
240 CH_TIME("AmrMesh::allocate(ParticleContainer<P, Traits>, string)");
241 if (m_verbosity > 5) {
242 pout() << "AmrMesh::allocate(ParticleContainer<P, Traits>, string)" << endl;
243 }
244
245 if (!this->queryRealm(a_realm)) {
246 const std::string str = "AmrMesh::allocate(ParticleContainer<P, Traits>, string) - could not find Realm '" +
247 a_realm + "'";
248 MayDay::Abort(str.c_str());
249 }
250
251 a_container.define(m_realms[a_realm]->getGrids(),
252 m_realms[a_realm]->getDomains(),
253 m_realms[a_realm]->getDx(),
254 m_realms[a_realm]->getRefinementRatios(),
255 m_probLo,
257 m_realms[a_realm]->getLevelTiles(), // alias the Realm's tile->box maps (single source)
259 a_realm,
260 &m_realms[a_realm]->getValidCells()); // alias for remap()'s stayer fast path
261}
262
263template <typename T>
264void
265AmrMesh::allocatePointer(Vector<RefCountedPtr<T>>& a_data) const
266{
267 CH_TIME("AmrMesh::allocatePointer(Vector<RefCountedPtr<T> >)");
268 if (m_verbosity > 5) {
269 pout() << "AmrMesh::allocatePointer(Vector<RefCountedPtr<T> >)" << endl;
270 }
271
272 a_data.resize(1 + m_finestLevel);
273 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
274 a_data[lvl] = RefCountedPtr<T>(new T());
275 }
276}
277
278template <typename T>
279void
280AmrMesh::allocatePointer(Vector<RefCountedPtr<T>>& a_data, const int a_finestLevel) const
281{
282 CH_TIME("AmrMesh::allocatePointer(Vector<RefCountedPtr<T> >, int)");
283 if (m_verbosity > 5) {
284 pout() << "AmrMesh::allocatePointer(Vector<RefCountedPtr<T> >, int)" << endl;
285 }
286
287 a_data.resize(1 + a_finestLevel);
288
289 for (int lvl = 0; lvl <= a_finestLevel; lvl++) {
290 a_data[lvl] = RefCountedPtr<T>(new T());
291 }
292}
293
294template <typename T>
295void
296AmrMesh::allocatePointer(EBAMRData<T>& a_data, const std::string& a_realm) const
297{
298 CH_TIME("AmrMesh::allocatePointer(EBAMRData<T>, std::string)");
299 if (m_verbosity > 5) {
300 pout() << "AmrMesh::allocatePointer(EBAMRData<T>, std::string)" << endl;
301 }
302
303 this->allocatePointer(a_data.getData());
304
305 a_data.setRealm(a_realm);
306}
307
308template <typename T>
309void
310AmrMesh::allocatePointer(EBAMRData<T>& a_data, const std::string& a_realm, const int a_finestLevel) const
311{
312 CH_TIME("AmrMesh::allocatePointer(EBAMRData<T>, std::string, int)");
313 if (m_verbosity > 5) {
314 pout() << "AmrMesh::allocatePointer(EBAMRData<T>, std::string, int)" << endl;
315 }
316
317 this->allocatePointer(a_data.getData(), a_finestLevel);
318
319 a_data.setRealm(a_realm);
320}
321
322template <typename P, typename Traits>
323void
325 const int a_lmin,
326 const int a_newFinestLevel) const noexcept
327{
328 CH_TIME("AmrMesh::remapToNewGrids(ParticleContainer)");
329 if (m_verbosity > 5) {
330 pout() << "AmrMesh::remapToNewGrids(ParticleContainer)" << endl;
331 }
332
333 (void)a_lmin; // ParticleContainer::regrid redistributes from the preRegrid cache; no lmin needed.
334
335 const std::string realm = a_particles.getRealm();
336
337 a_particles.regrid(this->getGrids(realm),
338 this->getDomains(),
339 this->getDx(),
340 this->getRefinementRatios(),
341 m_minBlockSize,
342 m_realms[realm]->getLevelTiles(), // alias the Realm's tile->box maps (single source)
343 a_newFinestLevel);
344}
345
346template <typename P, typename Traits>
347void
348AmrMesh::depositParticles(EBAMRIVData& a_meshData,
349 const std::string& a_realm,
350 const phase::which_phase& a_phase,
351 const ParticleContainer<P, Traits>& a_particles) const noexcept
352{
353 CH_TIME("AmrMesh::depositParticles(surface, SoA)");
354 if (m_verbosity > 5) {
355 pout() << "AmrMesh::depositParticles(surface, SoA)" << endl;
356 }
357
358 CH_assert(a_meshData[0]->nComp() == 1);
359 CH_assert(a_meshData.getRealm() == a_particles.getRealm());
360
361 EBAMRSurfaceDeposition& surfaceDeposition = this->getSurfaceDeposition(a_realm, a_phase);
362
363 surfaceDeposition.deposit<P, Traits>(a_meshData, a_particles);
364}
365
366template <typename P, typename Traits>
367void
368AmrMesh::depositWeight(EBAMRCellData& a_meshData,
369 const std::string& a_realm,
370 const phase::which_phase& a_phase,
371 const ParticleContainer<P, Traits>& a_particles,
372 const DepositionType a_depositionType,
373 const CoarseFineDeposition a_coarseFineDeposition,
374 const bool a_forceIrregNGP)
375{
376 CH_TIME("AmrMesh::depositWeight(ParticleContainer)");
377 if (m_verbosity > 5) {
378 pout() << "AmrMesh::depositWeight(ParticleContainer)" << endl;
379 }
380
381 EBAMRParticleMesh& particleMesh = this->getParticleMesh(a_realm, a_phase);
382
383 particleMesh.depositWeight(a_meshData, a_particles, a_depositionType, a_coarseFineDeposition, a_forceIrregNGP);
384}
385
386template <typename P, typename Traits, typename CellGather>
387void
388AmrMesh::depositGathered(EBAMRCellData& a_meshData,
389 const std::string& a_realm,
390 const phase::which_phase& a_phase,
391 const ParticleContainer<P, Traits>& a_particles,
392 const DepositionType a_depositionType,
393 const CoarseFineDeposition a_coarseFineDeposition,
394 const bool a_forceIrregNGP,
395 CellGather a_cellGather)
396{
397 CH_TIME("AmrMesh::depositGathered(ParticleContainer)");
398 if (m_verbosity > 5) {
399 pout() << "AmrMesh::depositGathered(ParticleContainer)" << endl;
400 }
401
402 EBAMRParticleMesh& particleMesh = this->getParticleMesh(a_realm, a_phase);
403
404 particleMesh
405 .depositGathered(a_meshData, a_particles, a_depositionType, a_coarseFineDeposition, a_forceIrregNGP, a_cellGather);
406}
407
408template <auto... Members, typename P, typename Traits>
409void
410AmrMesh::depositParticles(EBAMRCellData& a_meshData,
411 const std::string& a_realm,
412 const phase::which_phase& a_phase,
413 const ParticleContainer<P, Traits>& a_particles,
414 const DepositionType a_depositionType,
415 const CoarseFineDeposition a_coarseFineDeposition,
416 const bool a_forceIrregNGP)
417{
418 CH_TIME("AmrMesh::depositParticles(ParticleContainer)");
419 if (m_verbosity > 5) {
420 pout() << "AmrMesh::depositParticles(ParticleContainer)" << endl;
421 }
422
423 EBAMRParticleMesh& particleMesh = this->getParticleMesh(a_realm, a_phase);
424
425 particleMesh.template deposit<Members...>(a_meshData,
426 a_particles,
427 a_depositionType,
428 a_coarseFineDeposition,
429 a_forceIrregNGP);
430}
431
432template <typename P, typename Traits>
433void
435 const std::string& a_realm,
436 const phase::which_phase& a_phase,
437 const EBAMRCellData& a_meshScalarField,
438 const DepositionType a_interpType,
439 const bool a_forceIrregNGP) const
440{
441 CH_TIME("AmrMesh::interpolateWeight(ParticleContainer)");
442 if (m_verbosity > 5) {
443 pout() << "AmrMesh::interpolateWeight(ParticleContainer)" << endl;
444 }
445
446 EBAMRParticleMesh& particleMesh = this->getParticleMesh(a_realm, a_phase);
447
448 particleMesh.interpolateWeight(a_particles, a_meshScalarField, a_interpType, a_forceIrregNGP);
449}
450
451template <auto... Members, typename P, typename Traits>
452void
454 const std::string& a_realm,
455 const phase::which_phase& a_phase,
456 const EBAMRCellData& a_meshField,
457 const DepositionType a_interpType,
458 const bool a_forceIrregNGP) const
459{
460 CH_TIME("AmrMesh::interpolateParticles(ParticleContainer)");
461 if (m_verbosity > 5) {
462 pout() << "AmrMesh::interpolateParticles(ParticleContainer)" << endl;
463 }
464
465 EBAMRParticleMesh& particleMesh = this->getParticleMesh(a_realm, a_phase);
466
467 particleMesh.template interpolate<Members...>(a_particles, a_meshField, a_interpType, a_forceIrregNGP);
468}
469
470template <typename P, typename Traits>
471void
473 const phase::which_phase& a_phase,
474 const Real a_tolerance) const
475{
476 CH_TIME("AmrMesh::removeCoveredParticlesIF(ParticleContainer)");
477 if (m_verbosity > 5) {
478 pout() << "AmrMesh::removeCoveredParticlesIF(ParticleContainer)" << endl;
479 }
480
481 // Figure out the implicit function
482 RefCountedPtr<BaseIF> implicitFunction;
483
484 switch (a_phase) {
485 case phase::gas: {
486 implicitFunction = m_baseif.at(phase::gas);
487
488 break;
489 }
490 case phase::solid: {
491 implicitFunction = m_baseif.at(phase::solid);
492
493 break;
494 }
495 default: {
496 MayDay::Error("AmrMesh::removeCoveredParticlesIF(ParticleContainer) - logic bust");
497 }
498 }
499
500 const std::string whichRealm = a_particles.getRealm();
501
502 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
503 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
504 const DataIterator& dit = dbl.dataIterator();
505 const Real dx = this->getDx()[lvl];
506 const Real tol = a_tolerance * dx;
507
508 const int nbox = dit.size();
509#pragma omp parallel for schedule(runtime)
510 for (int mybox = 0; mybox < nbox; mybox++) {
511 const DataIndex& din = dit[mybox];
512
513 ParticleSoA<P, Traits>& leaf = a_particles[lvl][din];
514
515 // swap-and-pop removal: do NOT advance i after a removal (a new particle now sits in slot i).
516 std::size_t i = 0;
517 while (i < leaf.size()) {
518 if (implicitFunction->value(leaf.position(i)) > tol) {
519 leaf.remove(i);
520 }
521 else {
522 i++;
523 }
524 }
525 }
526 }
527}
528
529template <typename P, typename Traits>
530void
532 const phase::which_phase& a_phase,
533 const Real a_tolerance) const
534{
535 CH_TIME("AmrMesh::removeCoveredParticlesDiscrete(ParticleContainer)");
536 if (m_verbosity > 5) {
537 pout() << "AmrMesh::removeCoveredParticlesDiscrete(ParticleContainer)" << endl;
538 }
539
540 const std::string whichRealm = a_particles.getRealm();
541
542 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
543 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
544 const DataIterator& dit = dbl.dataIterator();
545 const EBISLayout& ebisl = this->getEBISLayout(whichRealm, a_phase)[lvl];
546 const Real dx = this->getDx()[lvl];
547 const Real tol = a_tolerance * dx;
548
549 const int nbox = dit.size();
550#pragma omp parallel for schedule(runtime)
551 for (int mybox = 0; mybox < nbox; mybox++) {
552 const DataIndex& din = dit[mybox];
553 const EBISBox& ebisBox = ebisl[din];
554 const Box region = ebisBox.getRegion();
555
556 const bool isRegular = ebisBox.isAllRegular();
557 const bool isCovered = ebisBox.isAllCovered();
558 const bool isIrregular = !isRegular && !isCovered;
559
560 ParticleSoA<P, Traits>& leaf = a_particles[lvl][din];
561
562 if (isCovered) {
563 leaf.clear();
564 }
565 else if (isIrregular) {
566 // swap-and-pop removal: do NOT advance i after a removal.
567 std::size_t i = 0;
568 while (i < leaf.size()) {
569 const RealVect pos = leaf.position(i);
570 const IntVect iv = ParticleOps::getParticleCellIndex(pos, m_probLo, dx);
571
572 CH_assert(region.contains(iv));
573
574 if (ebisBox.isCovered(iv)) {
575 leaf.remove(i);
576 }
577 else if (ebisBox.isIrregular(iv)) {
578 // Inside the valid region if it is on the valid side of at least one of the cell's VoF faces.
579 bool insideAtLeastOneVoF = false;
580
581 const std::vector<VolIndex> vofs = ebisBox.getVoFs(iv).stdVector();
582 for (const auto& vof : vofs) {
583 const RealVect ebNormal = ebisBox.normal(vof);
584 const RealVect ebCentroid = m_probLo + Location::position(Location::Cell::Boundary, vof, ebisBox, dx);
585 const Real faceProjection = ebNormal.dotProduct(pos - ebCentroid);
586
587 if (faceProjection >= -tol) {
588 insideAtLeastOneVoF = true;
589 break;
590 }
591 }
592
593 if (!insideAtLeastOneVoF) {
594 leaf.remove(i);
595 }
596 else {
597 i++;
598 }
599 }
600 else {
601 i++;
602 }
603 }
604 }
605 }
606 }
607}
608
609template <typename P, typename Traits>
610void
612 const phase::which_phase& a_phase) const
613{
614 CH_TIME("AmrMesh::removeCoveredParticlesVoxels(ParticleContainer)");
615 if (m_verbosity > 5) {
616 pout() << "AmrMesh::removeCoveredParticlesVoxels(ParticleContainer)" << endl;
617 }
618
619 const std::string whichRealm = a_particles.getRealm();
620
621 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
622 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
623 const DataIterator& dit = dbl.dataIterator();
624 const EBISLayout& ebisl = this->getEBISLayout(whichRealm, a_phase)[lvl];
625 const Real dx = this->getDx()[lvl];
626
627 const int nbox = dit.size();
628#pragma omp parallel for schedule(runtime)
629 for (int mybox = 0; mybox < nbox; mybox++) {
630 const DataIndex& din = dit[mybox];
631 const EBISBox& ebisBox = ebisl[din];
632 const Box region = ebisBox.getRegion();
633
634 const bool isRegular = ebisBox.isAllRegular();
635 const bool isCovered = ebisBox.isAllCovered();
636 const bool isIrregular = !isRegular && !isCovered;
637
638 ParticleSoA<P, Traits>& leaf = a_particles[lvl][din];
639
640 if (isCovered) {
641 leaf.clear();
642 }
643 else if (isIrregular) {
644 std::size_t i = 0;
645 while (i < leaf.size()) {
646 const RealVect pos = leaf.position(i);
647 const RealVect rv = (pos - m_probLo) / dx;
648 const IntVect iv = IntVect(D_DECL(floor(rv[0]), floor(rv[1]), floor(rv[2])));
649
650 CH_assert(region.contains(iv));
651
652 if (ebisBox.isCovered(iv)) {
653 leaf.remove(i);
654 }
655 else {
656 i++;
657 }
658 }
659 }
660 }
661 }
662}
663
664template <typename P, typename Traits>
665void
667 ParticleContainer<P, Traits>& a_particlesTo,
668 const phase::which_phase& a_phase,
669 const Real a_tolerance) const
670{
671 CH_TIME("AmrMesh::transferCoveredParticlesIF(ParticleContainer)");
672 if (m_verbosity > 5) {
673 pout() << "AmrMesh::transferCoveredParticlesIF(ParticleContainer)" << endl;
674 }
675
676 // Figure out the implicit function
677 RefCountedPtr<BaseIF> implicitFunction;
678
679 switch (a_phase) {
680 case phase::gas: {
681 implicitFunction = m_baseif.at(phase::gas);
682
683 break;
684 }
685 case phase::solid: {
686 implicitFunction = m_baseif.at(phase::solid);
687
688 break;
689 }
690 default: {
691 MayDay::Error("AmrMesh::transferCoveredParticlesIF(ParticleContainer) - logic bust");
692 }
693 }
694
695 const std::string realmFrom = a_particlesFrom.getRealm();
696 const std::string realmTo = a_particlesTo.getRealm();
697
698 CH_assert(realmFrom == realmTo);
699
700 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
701 const DisjointBoxLayout& dbl = this->getGrids(realmFrom)[lvl];
702 const DataIterator& dit = dbl.dataIterator();
703 const Real dx = this->getDx()[lvl];
704 const Real tol = a_tolerance * dx;
705
706 const int nbox = dit.size();
707#pragma omp parallel for schedule(runtime)
708 for (int mybox = 0; mybox < nbox; mybox++) {
709 const DataIndex& din = dit[mybox];
710
711 ParticleSoA<P, Traits>& from = a_particlesFrom[lvl][din];
712 ParticleSoA<P, Traits>& to = a_particlesTo[lvl][din];
713
714 // swap-and-pop transfer: do NOT advance i after a transfer (a new particle now sits in slot i).
715 std::size_t i = 0;
716 while (i < from.size()) {
717 if (implicitFunction->value(from.position(i)) > tol) {
718 to.appendParticle(from, i);
719 from.remove(i);
720 }
721 else {
722 i++;
723 }
724 }
725 }
726 }
727}
728
729template <typename P, typename Traits>
730void
732 ParticleContainer<P, Traits>& a_particlesTo,
733 const phase::which_phase& a_phase,
734 const Real a_tolerance) const
735{
736 CH_TIME("AmrMesh::transferCoveredParticlesDiscrete(ParticleContainer)");
737 if (m_verbosity > 5) {
738 pout() << "AmrMesh::transferCoveredParticlesDiscrete(ParticleContainer)" << endl;
739 }
740
741 const std::string realmFrom = a_particlesFrom.getRealm();
742 const std::string realmTo = a_particlesTo.getRealm();
743
744 CH_assert(realmFrom == realmTo);
745
746 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
747 const DisjointBoxLayout& dbl = this->getGrids(realmFrom)[lvl];
748 const DataIterator& dit = dbl.dataIterator();
749 const EBISLayout& ebisl = this->getEBISLayout(realmFrom, a_phase)[lvl];
750 const Real dx = this->getDx()[lvl];
751 const Real tol = a_tolerance * dx;
752
753 const int nbox = dit.size();
754#pragma omp parallel for schedule(runtime)
755 for (int mybox = 0; mybox < nbox; mybox++) {
756 const DataIndex& din = dit[mybox];
757 const EBISBox& ebisBox = ebisl[din];
758 const Box region = ebisBox.getRegion();
759
760 const bool isRegular = ebisBox.isAllRegular();
761 const bool isCovered = ebisBox.isAllCovered();
762 const bool isIrregular = !isRegular && !isCovered;
763
764 ParticleSoA<P, Traits>& from = a_particlesFrom[lvl][din];
765 ParticleSoA<P, Traits>& to = a_particlesTo[lvl][din];
766
767 if (isCovered) {
768 to.catenate(from);
769 }
770 else if (isIrregular) {
771 // swap-and-pop transfer: do NOT advance i after a transfer.
772 std::size_t i = 0;
773 while (i < from.size()) {
774 const RealVect pos = from.position(i);
775 const IntVect iv = ParticleOps::getParticleCellIndex(pos, m_probLo, dx);
776
777 CH_assert(region.contains(iv));
778
779 if (ebisBox.isCovered(iv)) {
780 to.appendParticle(from, i);
781 from.remove(i);
782 }
783 else if (ebisBox.isIrregular(iv)) {
784 // Inside the valid region if it is on the valid side of at least one of the cell's VoF faces.
785 bool insideAtLeastOneVoF = false;
786
787 const std::vector<VolIndex> vofs = ebisBox.getVoFs(iv).stdVector();
788 for (const auto& vof : vofs) {
789 const RealVect ebCentroid = m_probLo + Location::position(Location::Cell::Boundary, vof, ebisBox, dx);
790 const RealVect ebNormal = ebisBox.normal(vof);
791 const Real faceProjection = ebNormal.dotProduct(pos - ebCentroid);
792
793 if (faceProjection >= -tol) {
794 insideAtLeastOneVoF = true;
795 break;
796 }
797 }
798
799 if (!insideAtLeastOneVoF) {
800 to.appendParticle(from, i);
801 from.remove(i);
802 }
803 else {
804 i++;
805 }
806 }
807 else {
808 i++;
809 }
810 }
811 }
812 }
813 }
814}
815
816template <typename P, typename Traits>
817void
819 ParticleContainer<P, Traits>& a_particlesTo,
820 const phase::which_phase& a_phase) const
821{
822 CH_TIME("AmrMesh::transferCoveredParticlesVoxels(ParticleContainer)");
823 if (m_verbosity > 5) {
824 pout() << "AmrMesh::transferCoveredParticlesVoxels(ParticleContainer)" << endl;
825 }
826
827 const std::string realmFrom = a_particlesFrom.getRealm();
828 const std::string realmTo = a_particlesTo.getRealm();
829
830 CH_assert(realmFrom == realmTo);
831
832 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
833 const DisjointBoxLayout& dbl = this->getGrids(realmFrom)[lvl];
834 const DataIterator& dit = dbl.dataIterator();
835 const EBISLayout& ebisl = this->getEBISLayout(realmFrom, a_phase)[lvl];
836 const Real dx = this->getDx()[lvl];
837
838 const int nbox = dit.size();
839#pragma omp parallel for schedule(runtime)
840 for (int mybox = 0; mybox < nbox; mybox++) {
841 const DataIndex& din = dit[mybox];
842 const EBISBox& ebisBox = ebisl[din];
843 const Box region = ebisBox.getRegion();
844
845 const bool isRegular = ebisBox.isAllRegular();
846 const bool isCovered = ebisBox.isAllCovered();
847 const bool isIrregular = !isRegular && !isCovered;
848
849 ParticleSoA<P, Traits>& from = a_particlesFrom[lvl][din];
850 ParticleSoA<P, Traits>& to = a_particlesTo[lvl][din];
851
852 if (isCovered) {
853 to.catenate(from);
854 }
855 else if (isIrregular) {
856 std::size_t i = 0;
857 while (i < from.size()) {
858 const RealVect pos = from.position(i);
859 const IntVect iv = ParticleOps::getParticleCellIndex(pos, m_probLo, dx);
860
861 CH_assert(region.contains(iv));
862
863 if (ebisBox.isCovered(iv)) {
864 to.appendParticle(from, i);
865 from.remove(i);
866 }
867 else {
868 i++;
869 }
870 }
871 }
872 }
873 }
874}
875
876template <auto... OldPosition, typename P, typename Traits>
877void
879 ParticleContainer<P, Traits>& a_activeParticles,
880 ParticleContainer<P, Traits>& a_ebParticles,
881 ParticleContainer<P, Traits>& a_domainParticles,
882 const phase::which_phase a_phase,
883 const Real a_tolerance,
884 const bool a_deleteParticles,
885 const std::function<void(ParticleSoA<P, Traits>&, std::size_t)>& a_nonDeletionModifier) const noexcept
886{
887 CH_TIME("AmrMesh::intersectParticlesRaycastIF(ParticleContainer)");
888 if (m_verbosity > 5) {
889 pout() << "AmrMesh::intersectParticlesRaycastIF(ParticleContainer)" << endl;
890 }
891
892 static_assert(sizeof...(OldPosition) == SpaceDim,
893 "AmrMesh::intersectParticlesRaycastIF(ParticleContainer) - need exactly SpaceDim oldPosition members");
894
895 CH_assert(a_activeParticles.getRealm() == a_ebParticles.getRealm());
896 CH_assert(a_activeParticles.getRealm() == a_domainParticles.getRealm());
897
898 a_ebParticles.clearParticles();
899 a_domainParticles.clearParticles();
900
901 const std::string whichRealm = a_activeParticles.getRealm();
902
903 // Figure out the implicit function
904 RefCountedPtr<BaseIF> implicitFunction;
905
906 switch (a_phase) {
907 case phase::gas: {
908 implicitFunction = m_baseif.at(phase::gas);
909
910 break;
911 }
912 case phase::solid: {
913 implicitFunction = m_baseif.at(phase::solid);
914
915 break;
916 }
917 default: {
918 MayDay::Error("AmrMesh::intersectParticlesRaycastIF(ParticleContainer) - logic bust");
919
920 break;
921 }
922 }
923
924 // Safety factor to prevent particles falling off the domain if they intersect the high-side of the domain
925 constexpr Real safety = 1.E-12;
926
927 // Level loop -- go through each AMR level
928 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
929
930 // Handle to various grid stuff.
931 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
932 const DataIterator& dit = dbl.dataIterator();
933
934 const int nbox = dit.size();
935#pragma omp parallel for schedule(runtime)
936 for (int mybox = 0; mybox < nbox; mybox++) {
937 const DataIndex& din = dit[mybox];
938
939 ParticleSoA<P, Traits>& active = a_activeParticles[lvl][din];
940 ParticleSoA<P, Traits>& eb = a_ebParticles[lvl][din];
941 ParticleSoA<P, Traits>& domain = a_domainParticles[lvl][din];
942
943 // swap-and-pop transfer: do NOT advance i after a deletion (a new particle now sits in slot i).
944 std::size_t i = 0;
945 while (i < active.size()) {
946 const RealVect newPos = active.position(i);
947
948 // Assemble the previous position from the payload columns (left-to-right pack expansion).
949 RealVect oldPos;
950 int odir = 0;
951 ((oldPos[odir++] = active.template get<OldPosition>(i)), ...);
952
953 const RealVect path = newPos - oldPos;
954
955 // Cheap initial tests that allow us to skip some intersections tests.
956 bool checkEB = false;
957 bool checkDomain = false;
958
959 if (!implicitFunction.isNull()) {
960 checkEB = true;
961 }
962 for (int dir = 0; dir < SpaceDim; dir++) {
963 const bool outsideLo = newPos[dir] < m_probLo[dir];
964 const bool outsideHi = newPos[dir] > m_probHi[dir];
965
966 if (outsideLo || outsideHi) {
967 checkDomain = true;
968 }
969 }
970
971 // Do the intersection tests.
972 if (checkEB || checkDomain) {
973
974 // These are the solution
975 Real sDomain = std::numeric_limits<Real>::max();
976 Real sEB = std::numeric_limits<Real>::max();
977
978 bool contactDomain = false;
979 bool contactEB = false;
980
981 if (checkDomain) {
982 contactDomain = ParticleOps::domainIntersection(oldPos, newPos, m_probLo, m_probHi, sDomain);
983 }
984 if (checkEB) {
985 contactEB = ParticleOps::ebIntersectionRaycast(implicitFunction, oldPos, newPos, a_tolerance, sEB);
986 }
987
988 // Particle bumped into something. Move it onto the intersection point and transfer it to the EB/domain
989 // container. When the original is kept we restore its end position after copying the intersection point.
990 if (contactDomain || contactEB) {
991 if (sEB <= sDomain) { // Crashed with EB "first".
992 const RealVect intersectionPos = oldPos + sEB * path;
993
994 active.setPosition(i, intersectionPos);
995 eb.appendParticle(active, i);
996
997 if (a_deleteParticles) {
998 active.remove(i);
999 }
1000 else {
1001 active.setPosition(i, newPos);
1002 a_nonDeletionModifier(active, i);
1003 i++;
1004 }
1005 }
1006 else { // Crashed with domain "first".
1007 const Real sSafety = std::max((Real)0.0, sDomain - safety);
1008 const RealVect intersectionPos = oldPos + sSafety * path;
1009
1010 active.setPosition(i, intersectionPos);
1011 domain.appendParticle(active, i);
1012
1013 if (a_deleteParticles) {
1014 active.remove(i);
1015 }
1016 else {
1017 active.setPosition(i, newPos);
1018 a_nonDeletionModifier(active, i);
1019 i++;
1020 }
1021 }
1022 }
1023 else {
1024 i++;
1025 }
1026 }
1027 else {
1028 i++;
1029 }
1030 }
1031 }
1032 }
1033
1034 // These need to be remapped.
1035 a_ebParticles.remap();
1036 a_domainParticles.remap();
1037}
1038
1039template <auto... OldPosition, typename P, typename Traits>
1040void
1042 ParticleContainer<P, Traits>& a_activeParticles,
1043 ParticleContainer<P, Traits>& a_ebParticles,
1044 ParticleContainer<P, Traits>& a_domainParticles,
1045 const phase::which_phase a_phase,
1046 const Real a_bisectionStep,
1047 const bool a_deleteParticles,
1048 const std::function<void(ParticleSoA<P, Traits>&, std::size_t)>& a_nonDeletionModifier) const noexcept
1049{
1050 CH_TIME("AmrMesh::intersectParticlesBisectIF(ParticleContainer)");
1051 if (m_verbosity > 5) {
1052 pout() << "AmrMesh::intersectParticlesBisectIF(ParticleContainer)" << endl;
1053 }
1054
1055 static_assert(sizeof...(OldPosition) == SpaceDim,
1056 "AmrMesh::intersectParticlesBisectIF(ParticleContainer) - need exactly SpaceDim oldPosition members");
1057
1058 CH_assert(a_activeParticles.getRealm() == a_ebParticles.getRealm());
1059 CH_assert(a_activeParticles.getRealm() == a_domainParticles.getRealm());
1060
1061 // TLDR: This is pretty much a hard-copy of intersectParticlesRaycastIF(ParticleContainer), with the exception
1062 // that the EB intersection test is replaced by a bisection test.
1063
1064 a_ebParticles.clearParticles();
1065 a_domainParticles.clearParticles();
1066
1067 const std::string whichRealm = a_activeParticles.getRealm();
1068
1069 // Figure out the implicit function
1070 RefCountedPtr<BaseIF> implicitFunction;
1071
1072 switch (a_phase) {
1073 case phase::gas: {
1074 implicitFunction = m_baseif.at(phase::gas);
1075
1076 break;
1077 }
1078 case phase::solid: {
1079 implicitFunction = m_baseif.at(phase::solid);
1080
1081 break;
1082 }
1083 default: {
1084 MayDay::Error("AmrMesh::intersectParticlesBisectIF(ParticleContainer) - logic bust");
1085
1086 break;
1087 }
1088 }
1089
1090 // Safety factor to prevent particles falling off the domain if they intersect the high-side of the domain
1091 constexpr Real safety = 1.E-12;
1092
1093 // Level loop -- go through each AMR level
1094 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
1095
1096 // Handle to various grid stuff.
1097 const DisjointBoxLayout& dbl = this->getGrids(whichRealm)[lvl];
1098 const DataIterator& dit = dbl.dataIterator();
1099
1100 const int nbox = dit.size();
1101#pragma omp parallel for schedule(runtime)
1102 for (int mybox = 0; mybox < nbox; mybox++) {
1103 const DataIndex& din = dit[mybox];
1104
1105 ParticleSoA<P, Traits>& active = a_activeParticles[lvl][din];
1106 ParticleSoA<P, Traits>& eb = a_ebParticles[lvl][din];
1107 ParticleSoA<P, Traits>& domain = a_domainParticles[lvl][din];
1108
1109 // swap-and-pop transfer: do NOT advance i after a deletion (a new particle now sits in slot i).
1110 std::size_t i = 0;
1111 while (i < active.size()) {
1112 const RealVect newPos = active.position(i);
1113
1114 // Assemble the previous position from the payload columns (left-to-right pack expansion).
1115 RealVect oldPos;
1116 int odir = 0;
1117 ((oldPos[odir++] = active.template get<OldPosition>(i)), ...);
1118
1119 const RealVect path = newPos - oldPos;
1120
1121 // Cheap initial tests that allow us to skip some intersections tests.
1122 bool checkEB = false;
1123 bool checkDomain = false;
1124
1125 if (!implicitFunction.isNull()) {
1126 checkEB = true;
1127 }
1128 for (int dir = 0; dir < SpaceDim; dir++) {
1129 const bool outsideLo = newPos[dir] < m_probLo[dir];
1130 const bool outsideHi = newPos[dir] > m_probHi[dir];
1131
1132 if (outsideLo || outsideHi) {
1133 checkDomain = true;
1134 }
1135 }
1136
1137 // Do the intersection tests.
1138 if (checkEB || checkDomain) {
1139
1140 // These are the solution
1141 Real sDomain = std::numeric_limits<Real>::max();
1142 Real sEB = std::numeric_limits<Real>::max();
1143
1144 bool contactDomain = false;
1145 bool contactEB = false;
1146
1147 if (checkDomain) {
1148 contactDomain = ParticleOps::domainIntersection(oldPos, newPos, m_probLo, m_probHi, sDomain);
1149 }
1150 if (checkEB) {
1151 contactEB = ParticleOps::ebIntersectionBisect(implicitFunction, oldPos, newPos, a_bisectionStep, sEB);
1152 }
1153
1154 // Particle bumped into something. Move it onto the intersection point and transfer it to the EB/domain
1155 // container. When the original is kept we restore its end position after copying the intersection point.
1156 if (contactDomain || contactEB) {
1157 if (sEB <= sDomain) { // Crashed with EB "first".
1158 const RealVect intersectionPos = oldPos + sEB * path;
1159
1160 active.setPosition(i, intersectionPos);
1161 eb.appendParticle(active, i);
1162
1163 if (a_deleteParticles) {
1164 active.remove(i);
1165 }
1166 else {
1167 active.setPosition(i, newPos);
1168 a_nonDeletionModifier(active, i);
1169 i++;
1170 }
1171 }
1172 else { // Crashed with domain "first".
1173 const Real sSafety = std::max((Real)0.0, sDomain - safety);
1174 const RealVect intersectionPos = oldPos + sSafety * path;
1175
1176 active.setPosition(i, intersectionPos);
1177 domain.appendParticle(active, i);
1178
1179 if (a_deleteParticles) {
1180 active.remove(i);
1181 }
1182 else {
1183 active.setPosition(i, newPos);
1184 a_nonDeletionModifier(active, i);
1185 i++;
1186 }
1187 }
1188 }
1189 else {
1190 i++;
1191 }
1192 }
1193 else {
1194 i++;
1195 }
1196 }
1197 }
1198 }
1199
1200 // These need to be remapped.
1201 a_ebParticles.remap();
1202 a_domainParticles.remap();
1203}
1204
1205template <typename P, typename Traits>
1206void
1208 ParticleContainer<P, Traits>& a_srcParticles,
1209 const phase::which_phase a_phase) const noexcept
1210{
1211 CH_TIME("AmrMesh::transferIrregularParticles(ParticleContainer)");
1212 if (m_verbosity > 5) {
1213 pout() << "AmrMesh::transferIrregularParticles(ParticleContainer)" << endl;
1214 }
1215
1216 CH_assert(a_dstParticles.getRealm() == a_srcParticles.getRealm());
1217
1218 const std::string realm = a_dstParticles.getRealm();
1219
1220 for (int lvl = 0; lvl <= m_finestLevel; lvl++) {
1221 const DisjointBoxLayout& dbl = this->getGrids(realm)[lvl];
1222 const DataIterator& dit = dbl.dataIterator();
1223 const EBISLayout& ebisl = this->getEBISLayout(realm, a_phase)[lvl];
1224 const Real dx = m_dx[lvl];
1225
1226 const int nbox = dit.size();
1227#pragma omp parallel for schedule(runtime)
1228 for (int mybox = 0; mybox < nbox; mybox++) {
1229 const DataIndex& din = dit[mybox];
1230 const Box cellBox = dbl[din];
1231 const EBISBox& ebisbox = ebisl[din];
1232
1233 ParticleSoA<P, Traits>& dst = a_dstParticles[lvl][din];
1234 ParticleSoA<P, Traits>& src = a_srcParticles[lvl][din];
1235
1236 // swap-and-pop transfer: do NOT advance i after a transfer (a new particle now sits in slot i).
1237 std::size_t i = 0;
1238 while (i < src.size()) {
1239 const RealVect pos = src.position(i);
1240 const IntVect iv = ParticleOps::getParticleCellIndex(pos, m_probLo, dx);
1241
1242 bool moved = false;
1243
1244 if (cellBox.contains(iv) && ebisbox.isIrregular(iv)) {
1245 bool insideAnyVoF = false;
1246
1247 const Vector<VolIndex> allVoFs = ebisbox.getVoFs(iv);
1248 for (int k = 0; k < allVoFs.size(); k++) {
1249 const RealVect normal = ebisbox.normal(allVoFs[k]);
1250 const RealVect ebPos = m_probLo + Location::position(Location::Cell::Boundary, allVoFs[k], ebisbox, dx);
1251
1252 if ((pos - ebPos).dotProduct(normal) >= 0.0) {
1253 insideAnyVoF = true;
1254 }
1255 }
1256
1257 if (!insideAnyVoF) {
1258 const VolIndex& vof = allVoFs[0];
1259 const RealVect ebPos = m_probLo + Location::position(Location::Cell::Boundary, vof, ebisbox, dx);
1260
1261 src.setPosition(i, ebPos);
1262 dst.appendParticle(src, i);
1263 src.remove(i);
1264
1265 moved = true;
1266 }
1267 }
1268
1269 if (!moved) {
1270 i++;
1271 }
1272 }
1273 }
1274 }
1275}
1276
1277#include <CD_NamespaceFooter.H>
1278
1279#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:28
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 allocatePointer(Vector< RefCountedPtr< T > > &a_data) const
Allocate pointer but not any memory blocks.
Definition CD_AmrMeshImplem.H:265
void transferCoveredParticlesIF(ParticleContainer< P, Traits > &a_particlesFrom, ParticleContainer< P, Traits > &a_particlesTo, const phase::which_phase &a_phase, const Real a_tolerance) const
Transfer SoA particles inside the EB (implicit-function test) from one container to another: f(x) > a...
Definition CD_AmrMeshImplem.H:666
void allocate(ParticleContainer< P, Traits > &a_container, const std::string &a_realm) const
Allocate a struct-of-arrays particle container on the given realm.
Definition CD_AmrMeshImplem.H:238
const Vector< RefCountedPtr< LevelTiles > > & getLevelTiles(const std::string &a_realm) const
Get the tiled space representation.
Definition CD_AmrMesh.cpp:3439
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
const AMRMask & getValidCells(const std::string &a_realm) const
Get a map of all valid cells on a specified realm.
Definition CD_AmrMesh.cpp:3423
void interpolateWeight(ParticleContainer< P, Traits > &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) const
Interpolate a mesh scalar field onto the SoA container's weight column.
Definition CD_AmrMeshImplem.H:434
RealVect m_probLo
Domain simulation corner.
Definition CD_AmrMesh.H:2241
void intersectParticlesBisectIF(ParticleContainer< P, Traits > &a_activeParticles, ParticleContainer< P, Traits > &a_ebParticles, ParticleContainer< P, Traits > &a_domainParticles, const phase::which_phase a_phase, const Real a_bisectionStep, const bool a_deleteParticles, const std::function< void(ParticleSoA< P, Traits > &, std::size_t)> &a_nonDeletionModifier) const noexcept
SoA bisection-based particle intersection algorithm.
Definition CD_AmrMeshImplem.H:1041
const Vector< DisjointBoxLayout > & getGrids(const std::string &a_realm) const
Get the grids.
Definition CD_AmrMesh.cpp:3271
int m_verbosity
Verbosity.
Definition CD_AmrMesh.H:2256
void depositGathered(EBAMRCellData &a_meshData, const std::string &a_realm, const phase::which_phase &a_phase, const ParticleContainer< P, Traits > &a_particles, const DepositionType a_depositionType, const CoarseFineDeposition a_coarseFineDeposition, const bool a_forceIrregNGP, CellGather a_cellGather)
Deposit a custom per-particle scalar (a_cellGather) of an SoA container on the mesh.
Definition CD_AmrMeshImplem.H:388
int m_minBlockSize
Blocking factor.
Definition CD_AmrMesh.H:2296
void depositWeight(EBAMRCellData &a_meshData, const std::string &a_realm, const phase::which_phase &a_phase, const ParticleContainer< P, Traits > &a_particles, const DepositionType a_depositionType, const CoarseFineDeposition a_coarseFineDeposition, const bool a_forceIrregNGP)
Deposit the SoA container's weight column on the mesh (all coarse-fine strategies).
Definition CD_AmrMeshImplem.H:368
void transferCoveredParticlesDiscrete(ParticleContainer< P, Traits > &a_particlesFrom, ParticleContainer< P, Traits > &a_particlesTo, const phase::which_phase &a_phase, const Real a_tolerance) const
Transfer SoA particles inside the EB using discrete (EBISBox) information from one container to anoth...
Definition CD_AmrMeshImplem.H:731
void removeCoveredParticlesVoxels(ParticleContainer< P, Traits > &a_particles, const phase::which_phase &a_phase) const
Remove SoA particles that live in covered cells (voxel test).
Definition CD_AmrMeshImplem.H:611
void transferIrregularParticles(ParticleContainer< P, Traits > &a_dstParticles, ParticleContainer< P, Traits > &a_srcParticles, const phase::which_phase a_phase) const noexcept
Transfer SoA particles that are on the covered side of the EB to a different container.
Definition CD_AmrMeshImplem.H:1207
int m_finestLevel
Finest level.
Definition CD_AmrMesh.H:2261
void removeCoveredParticlesIF(ParticleContainer< P, Traits > &a_particles, const phase::which_phase &a_phase, const Real a_tolerance) const
Remove SoA particles that fall inside the EB (implicit-function test): f(x) > a_tolerance*dx.
Definition CD_AmrMeshImplem.H:472
std::map< phase::which_phase, RefCountedPtr< BaseIF > > m_baseif
Implicit functions.
Definition CD_AmrMesh.H:2160
bool queryRealm(const std::string &a_realm) const
Query if a realm exists.
Definition CD_AmrMesh.cpp:3861
void intersectParticlesRaycastIF(ParticleContainer< P, Traits > &a_activeParticles, ParticleContainer< P, Traits > &a_ebParticles, ParticleContainer< P, Traits > &a_domainParticles, const phase::which_phase a_phase, const Real a_tolerance, const bool a_deleteParticles, const std::function< void(ParticleSoA< P, Traits > &, std::size_t)> &a_nonDeletionModifier) const noexcept
SoA ray-casting particle intersection algorithm.
Definition CD_AmrMeshImplem.H:878
const Vector< Real > & getDx() const
Get spatial resolutions.
Definition CD_AmrMesh.cpp:3215
EBAMRParticleMesh & getParticleMesh(const std::string &a_realm, const phase::which_phase a_phase) const
Get EBAMRParticleMesh operator.
Definition CD_AmrMesh.cpp:3685
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:3287
std::map< std::string, RefCountedPtr< Realm > > m_realms
These are all the Realms.
Definition CD_AmrMesh.H:2155
void interpolateParticles(ParticleContainer< P, Traits > &a_particles, const std::string &a_realm, const phase::which_phase &a_phase, const EBAMRCellData &a_meshField, const DepositionType a_interpType, const bool a_forceIrregNGP) const
Interpolate a mesh field onto one or more SoA payload columns.
Definition CD_AmrMeshImplem.H:453
void depositParticles(EBAMRIVData &a_meshData, const std::string &a_realm, const phase::which_phase &a_phase, const ParticleContainer< P, Traits > &a_particles) const noexcept
Deposit the weight column of an SoA particle container onto the surface (EB).
Definition CD_AmrMeshImplem.H:348
void remapToNewGrids(ParticleContainer< P, Traits > &a_particles, const int a_lmin, const int a_newFinestLevel) const noexcept
Regrid a struct-of-arrays particle container to new grids.
Definition CD_AmrMeshImplem.H:324
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
void transferCoveredParticlesVoxels(ParticleContainer< P, Traits > &a_particlesFrom, ParticleContainer< P, Traits > &a_particlesTo, const phase::which_phase &a_phase) const
Transfer SoA particles that live in covered cells (voxel test) from one container to another.
Definition CD_AmrMeshImplem.H:818
const Vector< int > & getRefinementRatios() const
Get refinement ratios.
Definition CD_AmrMesh.cpp:3226
void removeCoveredParticlesDiscrete(ParticleContainer< P, Traits > &a_particles, const phase::which_phase &a_phase, const Real a_tolerance) const
Remove SoA particles inside the EB using discrete (EBISBox) information: covered cells,...
Definition CD_AmrMeshImplem.H:531
const Vector< ProblemDomain > & getDomains() const
Get domains.
Definition CD_AmrMesh.cpp:3249
Default class for holding LevelData<T> data across an EBAMR realm.
Definition CD_EBAMRData.H:41
Vector< RefCountedPtr< LevelData< T > > > & getData() noexcept
Get underlying data. Returns m_data.
Definition CD_EBAMRDataImplem.H:115
void setRealm(const std::string &a_realm) noexcept
Sets the realm for this object.
Definition CD_EBAMRDataImplem.H:143
AMR driver that deposits/interpolates ParticleContainer particles across the hierarchy.
Definition CD_EBAMRParticleMesh.H:74
void depositWeight(EBAMRCellData &a_meshData, const ParticleContainer< P, Traits > &a_particles, const DepositionType a_depositionType, const CoarseFineDeposition a_coarseFineDeposition, const bool a_forceIrregNGP)
Deposit the container-owned weight onto the AMR mesh.
Definition CD_EBAMRParticleMesh.H:251
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:204
void depositGathered(EBAMRCellData &a_meshData, const ParticleContainer< P, Traits > &a_particles, const DepositionType a_depositionType, const CoarseFineDeposition a_coarseFineDeposition, const bool a_forceIrregNGP, CellGather a_cellGather)
Deposit a custom per-particle scalar (computed by a_cellGather) onto the AMR mesh.
Definition CD_EBAMRParticleMesh.H:316
class for handling surface deposition of particles with EB and AMR.
Definition CD_EBAMRSurfaceDeposition.H:30
void deposit(EBAMRIVData &a_meshData, const ParticleContainer< P, Traits > &a_particles) const noexcept
Deposit the container-owned weight column of an SoA particle container onto the surface.
Definition CD_EBAMRSurfaceDepositionImplem.H:32
AMR-hierarchy container of computational particles, stored per patch in Struct-of-Arrays form.
Definition CD_ParticleContainer.H:123
void clearParticles()
Drop all valid particles on every level (keeps each leaf's arena capacity).
Definition CD_ParticleContainer.H:442
void define(const Vector< DisjointBoxLayout > &a_grids, const Vector< ProblemDomain > &a_domains, const Vector< Real > &a_dx, const Vector< int > &a_refRat, const RealVect &a_probLo, const int a_minBlockSize, const Vector< RefCountedPtr< LevelTiles > > &a_levelTiles, const int a_finestLevel, const std::string &a_realm, const Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > *a_validCells)
Allocate the per-level holders and the per-level tile-ownership maps over the AMR grids.
Definition CD_ParticleContainer.H:193
std::string getRealm() const
Realm label.
Definition CD_ParticleContainer.H:300
void remap()
Redistribute every valid particle to the patch/level/rank that owns its cell.
Definition CD_ParticleContainerImplem.H:494
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:224
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:175
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:32
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:126
Arena-backed Struct-of-Arrays particle container for a single grid patch.
Definition CD_ParticleSoA.H:655
RealVect position(const std::size_t a_index) const noexcept
Position of particle i as a RealVect (by value, assembled from the scalar columns).
Definition CD_ParticleSoA.H:1188
std::size_t size() const noexcept
Number of particles currently stored.
Definition CD_ParticleSoA.H:882
void setPosition(const std::size_t a_index, const RealVect &a_position) noexcept
Set the position of particle i.
Definition CD_ParticleSoA.H:1206
void catenate(ParticleSoA &a_other)
Move every particle of another container into this one, leaving a_other empty (catenate).
Definition CD_ParticleSoA.H:1002
void remove(const std::size_t a_index) noexcept
Remove particle i using swap-and-pop (O(1), does NOT preserve order).
Definition CD_ParticleSoA.H:1033
void clear() noexcept
Drop all particles (keeps the arena; invalidates the cell sort).
Definition CD_ParticleSoA.H:911
void appendParticle(const ParticleSoA &a_src, const std::size_t a_index)
Append a single particle (all columns, incl. id/rank) copied from another container.
Definition CD_ParticleSoAImplem.H:172
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