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