chombo-discharge
Loading...
Searching...
No Matches
CD_EBParticleMesh.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
42#ifndef CD_EBPARTICLEMESH_H
43#define CD_EBPARTICLEMESH_H
44
45// Std includes
46#include <cstddef>
47#include <type_traits>
48#include <utility>
49
50// Chombo includes
51#include <CH_Timer.H>
52#include <ProblemDomain.H>
53#include <EBISBox.H>
54#include <EBCellFAB.H>
55#include <RealVect.H>
56#include <Box.H>
57#include <IntVect.H>
58
59// Our includes
60#include <CD_DepositionType.H>
61#include <CD_ParticleOps.H>
62#include <CD_BoxLoops.H>
63#include <CD_ParticleSoA.H>
64#include <CD_NamespaceHeader.H>
65
71{
72public:
77 {}
78
87 EBParticleMesh(const ProblemDomain& a_domain,
88 const Box& a_region,
89 const EBISBox& a_ebisbox,
90 const RealVect& a_dx,
91 const RealVect& a_probLo)
92 {
93 this->define(a_domain, a_region, a_ebisbox, a_dx, a_probLo);
94 }
95
104 void
105 define(const ProblemDomain& a_domain,
106 const Box& a_region,
107 const EBISBox& a_ebisbox,
108 const RealVect& a_dx,
109 const RealVect& a_probLo)
110 {
111 CH_TIME("EBParticleMesh::define");
112
113 m_verbose = false;
114 m_domain = a_domain;
115 m_region = a_region;
116 m_ebisbox = &a_ebisbox; // alias, NOT a copy -- see m_ebisbox declaration
117 m_probLo = a_probLo;
118 m_dx = a_dx;
119 }
120
134 template <typename P, typename Traits>
135 void
136 depositWeight(EBCellFAB& a_meshData,
137 const int a_comp,
138 const ParticleSoA<P, Traits>& a_particles,
139 const DepositionType a_depositionType,
140 const Real a_widthScale,
141 const bool a_forceIrregNGP) const
142 {
143 CH_TIME("EBParticleMesh::depositWeight");
144
145 this->depositCore(a_meshData,
146 a_comp,
147 a_particles,
148 1,
149 a_depositionType,
150 a_widthScale,
151 a_forceIrregNGP,
152 [&](const std::size_t a_i, Real* a_out) {
153 a_out[0] = a_particles.weight(a_i);
154 });
155 }
156
167 template <typename P, typename Traits>
168 void
169 depositWeight(EBCellFAB& a_meshData,
170 const ParticleSoA<P, Traits>& a_particles,
171 const DepositionType a_depositionType,
172 const Real a_widthScale,
173 const bool a_forceIrregNGP) const
174 {
175 CH_TIME("EBParticleMesh::depositWeight");
176
177 this->depositWeight(a_meshData, 0, a_particles, a_depositionType, a_widthScale, a_forceIrregNGP);
178 }
179
194 template <auto... Members, typename P, typename Traits>
195 void
196 deposit(EBCellFAB& a_meshData,
197 const int a_comp,
198 const ParticleSoA<P, Traits>& a_particles,
199 const DepositionType a_depositionType,
200 const Real a_widthScale,
201 const bool a_forceIrregNGP) const
202 {
203 CH_TIME("EBParticleMesh::deposit");
204
205 static_assert(sizeof...(Members) == 1 || sizeof...(Members) == SpaceDim,
206 "deposit selects either one scalar column or SpaceDim vector-component columns");
207
208 this->depositCore(a_meshData,
209 a_comp,
210 a_particles,
211 static_cast<int>(sizeof...(Members)),
212 a_depositionType,
213 a_widthScale,
214 a_forceIrregNGP,
215 [&](const std::size_t a_i, Real* a_out) {
216 std::size_t k = 0;
217 ((a_out[k++] = static_cast<Real>(a_particles.template get<Members>(a_i))), ...);
218 });
219 }
220
232 template <auto... Members, typename P, typename Traits>
233 void
234 deposit(EBCellFAB& a_meshData,
235 const ParticleSoA<P, Traits>& a_particles,
236 const DepositionType a_depositionType,
237 const Real a_widthScale,
238 const bool a_forceIrregNGP) const
239 {
240 CH_TIME("EBParticleMesh::deposit");
241
242 this->deposit<Members...>(a_meshData, 0, a_particles, a_depositionType, a_widthScale, a_forceIrregNGP);
243 }
244
261 template <typename P, typename Traits, typename GatherFunc>
262 void
263 depositGathered(EBCellFAB& a_meshData,
264 const int a_comp,
265 const ParticleSoA<P, Traits>& a_particles,
266 const DepositionType a_depositionType,
267 const Real a_widthScale,
268 const bool a_forceIrregNGP,
269 GatherFunc&& a_gather) const
270 {
271 CH_TIME("EBParticleMesh::depositGathered");
272
273 this->depositCore(a_meshData,
274 a_comp,
275 a_particles,
276 1,
277 a_depositionType,
278 a_widthScale,
279 a_forceIrregNGP,
280 std::forward<GatherFunc>(a_gather));
281 }
282
296 template <auto... Members, typename P, typename Traits>
297 void
299 const EBCellFAB& a_meshData,
300 const int a_comp,
301 const DepositionType a_interpType,
302 const bool a_forceIrregNGP) const
303 {
304 CH_TIME("EBParticleMesh::interpolate");
305
306 static_assert(sizeof...(Members) == 1 || sizeof...(Members) == SpaceDim,
307 "interpolate targets either one scalar column or SpaceDim vector-component columns");
308
309 this->interpolateCore(
310 a_particles,
311 a_meshData,
312 a_comp,
313 static_cast<int>(sizeof...(Members)),
314 a_interpType,
315 a_forceIrregNGP,
316 [&](const std::size_t a_i, const Real* a_in) {
317 std::size_t k = 0;
318 ((a_particles.template get<Members>(
319 a_i) = static_cast<std::decay_t<decltype(a_particles.template get<Members>(a_i))>>(a_in[k++])),
320 ...);
321 });
322 }
323
334 template <auto... Members, typename P, typename Traits>
335 void
337 const EBCellFAB& a_meshData,
338 const DepositionType a_interpType,
339 const bool a_forceIrregNGP) const
340 {
341 CH_TIME("EBParticleMesh::interpolate");
342
343 this->interpolate<Members...>(a_particles, a_meshData, 0, a_interpType, a_forceIrregNGP);
344 }
345
358 template <typename P, typename Traits>
359 void
361 const EBCellFAB& a_meshData,
362 const int a_comp,
363 const DepositionType a_interpType,
364 const bool a_forceIrregNGP) const
365 {
366 CH_TIME("EBParticleMesh::interpolateWeight");
367
368 this->interpolateCore(a_particles,
369 a_meshData,
370 a_comp,
371 1,
372 a_interpType,
373 a_forceIrregNGP,
374 [&](const std::size_t a_i, const Real* a_in) {
375 a_particles.weight(a_i) = a_in[0];
376 });
377 }
378
388 template <typename P, typename Traits>
389 void
391 const EBCellFAB& a_meshData,
392 const DepositionType a_interpType,
393 const bool a_forceIrregNGP) const
394 {
395 CH_TIME("EBParticleMesh::interpolateWeight");
396
397 this->interpolateWeight(a_particles, a_meshData, 0, a_interpType, a_forceIrregNGP);
398 }
399
400protected:
404 ProblemDomain m_domain;
405
410
415
427 const EBISBox* m_ebisbox = nullptr;
428
432 RealVect m_dx;
433
437 RealVect m_probLo;
438
454 template <typename P, typename Traits, typename StrengthFn>
455 void
456 depositCore(EBCellFAB& a_meshData,
457 const int a_comp,
458 const ParticleSoA<P, Traits>& a_particles,
459 const int a_numComp,
460 const DepositionType a_depositionType,
461 const Real a_widthScale,
462 const bool a_forceIrregNGP,
463 StrengthFn a_gather) const
464 {
465 CH_TIME("EBParticleMesh::depositCore");
466
467 CH_assert(a_meshData.nComp() >= a_comp + a_numComp);
468
469 Real invVol = 1.0;
470 for (int dir = 0; dir < SpaceDim; dir++) {
471 invVol /= m_dx[dir];
472 }
473
474 const RealVect cicWidth = 1 * a_widthScale * RealVect::Unit;
475 const RealVect tscWidth = 2 * a_widthScale * RealVect::Unit;
476
477 Real ngpFactor = invVol;
478 Real cicFactor = invVol;
479 Real tscFactor = invVol;
480 for (int dir = 0; dir < SpaceDim; dir++) {
481 cicFactor *= 1.0 / cicWidth[dir];
482 tscFactor *= 2.0 / tscWidth[dir];
483 }
484
485 const std::size_t numParticles = a_particles.size();
486
487 Real strength[SpaceDim];
488
489 switch (a_depositionType) {
490 case DepositionType::NGP: {
491 for (std::size_t i = 0; i < numParticles; i++) {
492 a_gather(i, strength);
493 this->depositParticleNGP(a_meshData, a_comp, a_particles.position(i), ngpFactor, strength, a_numComp);
494 }
495 break;
496 }
497 case DepositionType::CIC: {
498 for (std::size_t i = 0; i < numParticles; i++) {
499 a_gather(i, strength);
500 this->depositParticleCIC(a_meshData,
501 a_comp,
502 a_particles.position(i),
503 cicWidth,
504 cicFactor,
505 strength,
506 a_numComp,
507 a_forceIrregNGP);
508 }
509 break;
510 }
511 case DepositionType::TSC: {
512 for (std::size_t i = 0; i < numParticles; i++) {
513 a_gather(i, strength);
514 this->depositParticleTSC(a_meshData,
515 a_comp,
516 a_particles.position(i),
517 tscWidth,
518 tscFactor,
519 strength,
520 a_numComp,
521 a_forceIrregNGP);
522 }
523 break;
524 }
525 default: {
526 MayDay::Abort("EBParticleMesh::depositCore -- logic bust");
527 break;
528 }
529 }
530 }
531
546 template <typename P, typename Traits, typename ScatterFn>
547 void
549 const EBCellFAB& a_meshData,
550 const int a_comp,
551 const int a_numComp,
552 const DepositionType a_interpType,
553 const bool a_forceIrregNGP,
554 ScatterFn a_scatter) const
555 {
556 CH_TIME("EBParticleMesh::interpolateCore");
557
558 CH_assert(a_meshData.nComp() >= a_comp + a_numComp);
559
560 // validBox is where the chosen scheme has enough cells; gatherBox is the read stencil.
561 Box validBox;
562 Box gatherBox;
563 switch (a_interpType) {
564 case DepositionType::NGP: {
565 validBox = m_domain.domainBox();
566 gatherBox = Box(IntVect::Zero, IntVect::Zero);
567 break;
568 }
569 case DepositionType::CIC: {
570 validBox = grow(m_domain.domainBox(), -1);
571 gatherBox = Box(IntVect::Zero, IntVect::Unit);
572 break;
573 }
574 case DepositionType::TSC: {
575 validBox = grow(m_domain.domainBox(), -2);
576 gatherBox = Box(IntVect::Zero, 2 * IntVect::Unit);
577 break;
578 }
579 default: {
580 MayDay::Error("EBParticleMesh::interpolateCore - logic bust");
581 }
582 }
583
584 const std::size_t numParticles = a_particles.size();
585
586 Real field[SpaceDim];
587
588 switch (a_interpType) {
589 case DepositionType::NGP: {
590 for (std::size_t i = 0; i < numParticles; i++) {
591 this->interpolateParticleNGP(field, a_meshData, a_comp, a_particles.position(i), a_numComp);
592 a_scatter(i, field);
593 }
594 break;
595 }
596 case DepositionType::CIC: {
597 for (std::size_t i = 0; i < numParticles; i++) {
598 this->interpolateParticleCIC(field,
599 a_meshData,
600 a_comp,
601 validBox,
602 gatherBox,
603 a_particles.position(i),
604 a_numComp,
605 a_forceIrregNGP);
606 a_scatter(i, field);
607 }
608 break;
609 }
610 case DepositionType::TSC: {
611 for (std::size_t i = 0; i < numParticles; i++) {
612 this->interpolateParticleTSC(field,
613 a_meshData,
614 a_comp,
615 validBox,
616 gatherBox,
617 a_particles.position(i),
618 a_numComp,
619 a_forceIrregNGP);
620 a_scatter(i, field);
621 }
622 break;
623 }
624 default: {
625 MayDay::Abort("EBParticleMesh::interpolateCore -- logic bust");
626 break;
627 }
628 }
629 }
630
631 // ===========================================================================
632 // The per-particle EB/cut-cell kernels below are adapted from
633 // Source/Particle/CD_EBParticleMeshImplem.H -- storage-agnostic, with an added
634 // destination-component offset (a_comp) and the TSC partition-of-unity fix.
635 // ===========================================================================
636
646 inline void
647 depositParticleNGP(EBCellFAB& a_rho,
648 const int a_comp,
649 const RealVect& a_position,
650 const Real& a_volumeFactor,
651 const Real* a_strength,
652 const int& a_numComp) const noexcept
653 {
654 const IntVect particleIV = ParticleOps::getParticleCellIndex(a_position, m_probLo, m_dx);
655
656 CH_assert(m_region.contains(particleIV));
657
658 FArrayBox& rho = a_rho.getFArrayBox();
659
660 for (int comp = 0; comp < a_numComp; comp++) {
661 rho(particleIV, a_comp + comp) += a_strength[comp] * a_volumeFactor;
662 }
663 }
664
676 inline Box
677 cloudBox(const RealVect& a_position, const RealVect& a_particleWidth) const noexcept
678 {
679 RealVect lo;
680 RealVect hi;
681 for (int dir = 0; dir < SpaceDim; dir++) {
682 const Real halfWidth = 0.5 * a_particleWidth[dir] * m_dx[dir];
683 lo[dir] = a_position[dir] - halfWidth;
684 hi[dir] = a_position[dir] + halfWidth;
685 }
688 }
689
701 inline void
702 depositParticleCIC(EBCellFAB& a_rho,
703 const int a_comp,
704 const RealVect& a_position,
705 const RealVect& a_particleWidth,
706 const Real& a_volumeFactor,
707 const Real* a_strength,
708 const int& a_numComp,
709 const bool a_forceIrregNGP) const noexcept
710 {
711 const IntVect particleIV = ParticleOps::getParticleCellIndex(a_position, m_probLo, m_dx);
712
713 CH_assert(m_region.contains(particleIV));
714
715 FArrayBox& rho = a_rho.getFArrayBox();
716
717 // forceIrregNGP first so the common (false) case short-circuits before the EBISBox query.
718 if (a_forceIrregNGP && m_ebisbox->isIrregular(particleIV)) {
719 for (int comp = 0; comp < a_numComp; comp++) {
720 rho(particleIV, a_comp + comp) += a_strength[comp] * a_volumeFactor;
721 }
722 }
723 else {
724 auto cicKernel = [&](const IntVect& iv) -> void {
725 Real weight = a_volumeFactor;
726
727 for (int dir = 0; dir < SpaceDim; dir++) {
728 const Real a = (m_probLo[dir] - a_position[dir]) / m_dx[dir] + iv[dir];
729 const Real b = a + 1.0;
730 const Real L = 0.5 * a_particleWidth[dir];
731
732 weight *= std::max(0.0, std::min(b, L) - std::max(a, -L));
733 }
734
735 for (int comp = 0; comp < a_numComp; comp++) {
736 rho(iv, a_comp + comp) += weight * a_strength[comp];
737 }
738 };
739
740 BoxLoops::loop<D_DECL(1, 1, 1)>(this->cloudBox(a_position, a_particleWidth), cicKernel);
741 }
742 }
743
755 inline void
756 depositParticleTSC(EBCellFAB& a_rho,
757 const int a_comp,
758 const RealVect& a_position,
759 const RealVect& a_particleWidth,
760 const Real& a_volumeFactor,
761 const Real* a_strength,
762 const int& a_numComp,
763 const bool a_forceIrregNGP) const noexcept
764 {
765 const IntVect particleIV = ParticleOps::getParticleCellIndex(a_position, m_probLo, m_dx);
766
767 CH_assert(m_region.contains(particleIV));
768
769 FArrayBox& rho = a_rho.getFArrayBox();
770
771 // forceIrregNGP first so the common (false) case short-circuits before the EBISBox query.
772 if (a_forceIrregNGP && m_ebisbox->isIrregular(particleIV)) {
773 for (int comp = 0; comp < a_numComp; comp++) {
774 rho(particleIV, a_comp + comp) += a_strength[comp] * a_volumeFactor;
775 }
776 }
777 else {
778 auto tscKernel = [&](const IntVect& iv) -> void {
779 Real weight = a_volumeFactor;
780
781 for (int dir = 0; dir < SpaceDim; dir++) {
782 const Real a = (m_probLo[dir] - a_position[dir]) / m_dx[dir] + iv[dir];
783 const Real b = a + 1.0;
784 const Real L = a_particleWidth[dir];
785
786 const Real alpha = std::max(a, -0.5 * L);
787 const Real beta = std::min(b, +0.5 * L);
788 const Real factor = (alpha < beta) ? 1.0 : 0.0;
789
790 // factor gates the ENTIRE overlap integral so out-of-support cells contribute zero.
791 // This fixes a partition-of-unity bug in the original AoS depositParticleTSC, where
792 // factor multiplied only the first term and the cloud over-deposited ~2.33x per
793 // dimension.
794 weight *= factor * ((beta - alpha) - (beta * std::abs(beta) - alpha * std::abs(alpha)) / L);
795 }
796
797 for (int comp = 0; comp < a_numComp; comp++) {
798 rho(iv, a_comp + comp) += weight * a_strength[comp];
799 }
800 };
801
802 BoxLoops::loop<D_DECL(1, 1, 1)>(this->cloudBox(a_position, a_particleWidth), tscKernel);
803 }
804 }
805
814 inline void
815 interpolateParticleNGP(Real* a_particleField,
816 const EBCellFAB& a_meshData,
817 const int a_comp,
818 const RealVect& a_position,
819 const int& a_numComp) const noexcept
820 {
821 const IntVect particleIV = ParticleOps::getParticleCellIndex(a_position, m_probLo, m_dx);
822 const FArrayBox& meshData = a_meshData.getFArrayBox();
823 const Real factor = m_ebisbox->isCovered(particleIV) ? 0.0 : 1.0;
824
825 for (int comp = 0; comp < a_numComp; comp++) {
826 a_particleField[comp] = factor * meshData(particleIV, a_comp + comp);
827 }
828 }
829
841 inline void
842 interpolateParticleCIC(Real* a_particleField,
843 const EBCellFAB& a_meshData,
844 const int a_comp,
845 const Box& a_validBox,
846 const Box& a_gatherBox,
847 const RealVect& a_position,
848 const int& a_numComp,
849 const bool a_forceIrregNGP) const noexcept
850 {
851 const IntVect particleIV = ParticleOps::getParticleCellIndex(a_position, m_probLo, m_dx);
852 const IntVect loIndex = ParticleOps::getParticleCellIndex(a_position - 0.5 * m_dx, m_probLo, m_dx);
853
854 CH_assert(m_region.contains(particleIV));
855
856 const FArrayBox& meshData = a_meshData.getFArrayBox();
857
858 for (int comp = 0; comp < a_numComp; comp++) {
859 a_particleField[comp] = 0.0;
860 }
861
862 if ((m_ebisbox->isIrregular(particleIV) && a_forceIrregNGP) || !(a_validBox.contains(particleIV))) {
863 for (int comp = 0; comp < a_numComp; comp++) {
864 a_particleField[comp] = meshData(particleIV, a_comp + comp);
865 }
866 }
867 else if (!(m_ebisbox->isCovered(particleIV))) {
868 auto cicKernel = [&](const IntVect& iv) -> void {
869 Real weight = 1.0;
870
871 const RealVect L = (m_probLo - a_position) / m_dx + (RealVect(iv) + 0.5 * RealVect::Unit);
872
873 for (int dir = 0; dir < SpaceDim; dir++) {
874 weight *= (1. - std::abs(L[dir]));
875 }
876
877 for (int comp = 0; comp < a_numComp; comp++) {
878 a_particleField[comp] += weight * meshData(iv, a_comp + comp);
879 }
880 };
881
882 const Box gatherBox = a_gatherBox + loIndex;
883
884 BoxLoops::loop<D_DECL(1, 1, 1)>(gatherBox, cicKernel);
885 }
886 }
887
899 inline void
900 interpolateParticleTSC(Real* a_particleField,
901 const EBCellFAB& a_meshData,
902 const int a_comp,
903 const Box& a_validBox,
904 const Box& a_gatherBox,
905 const RealVect& a_position,
906 const int& a_numComp,
907 const bool a_forceIrregNGP) const noexcept
908 {
909 const IntVect particleIV = ParticleOps::getParticleCellIndex(a_position, m_probLo, m_dx);
910 const IntVect loIndex = ParticleOps::getParticleCellIndex(a_position - m_dx, m_probLo, m_dx);
911
912 CH_assert(m_region.contains(particleIV));
913
914 const FArrayBox& meshData = a_meshData.getFArrayBox();
915
916 for (int comp = 0; comp < a_numComp; comp++) {
917 a_particleField[comp] = 0.0;
918 }
919
920 if ((m_ebisbox->isIrregular(particleIV) && a_forceIrregNGP) || !(a_validBox.contains(particleIV))) {
921 for (int comp = 0; comp < a_numComp; comp++) {
922 a_particleField[comp] = meshData(particleIV, a_comp + comp);
923 }
924 }
925 else if (!(m_ebisbox->isCovered(particleIV))) {
926 auto tscKernel = [&](const IntVect& iv) -> void {
927 Real weight = 1.0;
928
929 const RealVect L = (m_probLo - a_position) / m_dx + (RealVect(iv) + 0.5 * RealVect::Unit);
930
931 for (int dir = 0; dir < SpaceDim; dir++) {
932 const Real& l = std::abs(L[dir]);
933
934 if (l < 0.5) {
935 weight *= 0.75 - l * l;
936 }
937 else {
938 weight *= 0.5 * (1.5 - l) * (1.5 - l);
939 }
940 }
941
942 for (int comp = 0; comp < a_numComp; comp++) {
943 a_particleField[comp] += weight * meshData(iv, a_comp + comp);
944 }
945 };
946
947 const Box gatherBox = a_gatherBox + loIndex;
948
949 BoxLoops::loop<D_DECL(1, 1, 1)>(gatherBox, tscKernel);
950 }
951 }
952};
953
954#include <CD_NamespaceFooter.H>
955
956#endif
Declaration of a namespace for proto-typing grid and EB loops.
Declaration of deposition types.
DepositionType
Deposition types.
Definition CD_DepositionType.H:24
Declaration of a static class containing some common useful particle routines that would otherwise be...
Declaration of ParticleSoA, an arena-backed Struct-of-Arrays particle container.
Deposits/interpolates ParticleSoA leaves on a single patch, with embedded-boundary (cut-cell) awarene...
Definition CD_EBParticleMesh.H:71
Box m_region
Cell-centered valid box.
Definition CD_EBParticleMesh.H:414
bool m_verbose
Verbose flag.
Definition CD_EBParticleMesh.H:409
void depositCore(EBCellFAB &a_meshData, const int a_comp, const ParticleSoA< P, Traits > &a_particles, const int a_numComp, const DepositionType a_depositionType, const Real a_widthScale, const bool a_forceIrregNGP, StrengthFn a_gather) const
Shared deposition loop: gathers each particle's strength via a_gather, then calls the storage-agnosti...
Definition CD_EBParticleMesh.H:456
void depositParticleCIC(EBCellFAB &a_rho, const int a_comp, const RealVect &a_position, const RealVect &a_particleWidth, const Real &a_volumeFactor, const Real *a_strength, const int &a_numComp, const bool a_forceIrregNGP) const noexcept
CIC deposition of one particle.
Definition CD_EBParticleMesh.H:702
EBParticleMesh()
Default constructor. Must subsequently call define.
Definition CD_EBParticleMesh.H:76
void define(const ProblemDomain &a_domain, const Box &a_region, const EBISBox &a_ebisbox, const RealVect &a_dx, const RealVect &a_probLo)
Define function.
Definition CD_EBParticleMesh.H:105
void interpolate(ParticleSoA< P, Traits > &a_particles, const EBCellFAB &a_meshData, const int a_comp, const DepositionType a_interpType, const bool a_forceIrregNGP) const
Interpolate mesh components [a_comp, a_comp + nColumns) onto one or more payload columns.
Definition CD_EBParticleMesh.H:298
void depositParticleNGP(EBCellFAB &a_rho, const int a_comp, const RealVect &a_position, const Real &a_volumeFactor, const Real *a_strength, const int &a_numComp) const noexcept
NGP deposition of one particle.
Definition CD_EBParticleMesh.H:647
void depositWeight(EBCellFAB &a_meshData, const ParticleSoA< P, Traits > &a_particles, const DepositionType a_depositionType, const Real a_widthScale, const bool a_forceIrregNGP) const
Deposit the weight column onto the first mesh component (a_comp == 0).
Definition CD_EBParticleMesh.H:169
void depositWeight(EBCellFAB &a_meshData, const int a_comp, const ParticleSoA< P, Traits > &a_particles, const DepositionType a_depositionType, const Real a_widthScale, const bool a_forceIrregNGP) const
Deposit the container-owned weight column onto mesh component a_comp.
Definition CD_EBParticleMesh.H:136
void interpolateWeight(ParticleSoA< P, Traits > &a_particles, const EBCellFAB &a_meshData, const int a_comp, const DepositionType a_interpType, const bool a_forceIrregNGP) const
Interpolate mesh component a_comp onto the container-owned weight column.
Definition CD_EBParticleMesh.H:360
void interpolateWeight(ParticleSoA< P, Traits > &a_particles, const EBCellFAB &a_meshData, const DepositionType a_interpType, const bool a_forceIrregNGP) const
Interpolate the first mesh component (a_comp == 0) onto the weight column.
Definition CD_EBParticleMesh.H:390
void deposit(EBCellFAB &a_meshData, const int a_comp, const ParticleSoA< P, Traits > &a_particles, const DepositionType a_depositionType, const Real a_widthScale, const bool a_forceIrregNGP) const
Deposit one or more payload columns onto mesh components [a_comp, a_comp + nColumns).
Definition CD_EBParticleMesh.H:196
void depositParticleTSC(EBCellFAB &a_rho, const int a_comp, const RealVect &a_position, const RealVect &a_particleWidth, const Real &a_volumeFactor, const Real *a_strength, const int &a_numComp, const bool a_forceIrregNGP) const noexcept
TSC deposition of one particle.
Definition CD_EBParticleMesh.H:756
void depositGathered(EBCellFAB &a_meshData, const int a_comp, const ParticleSoA< P, Traits > &a_particles, const DepositionType a_depositionType, const Real a_widthScale, const bool a_forceIrregNGP, GatherFunc &&a_gather) const
Deposit a custom per-particle scalar (computed by a_gather) onto mesh component a_comp.
Definition CD_EBParticleMesh.H:263
void interpolateParticleCIC(Real *a_particleField, const EBCellFAB &a_meshData, const int a_comp, const Box &a_validBox, const Box &a_gatherBox, const RealVect &a_position, const int &a_numComp, const bool a_forceIrregNGP) const noexcept
CIC interpolation onto one particle.
Definition CD_EBParticleMesh.H:842
void interpolateCore(ParticleSoA< P, Traits > &a_particles, const EBCellFAB &a_meshData, const int a_comp, const int a_numComp, const DepositionType a_interpType, const bool a_forceIrregNGP, ScatterFn a_scatter) const
Shared interpolation loop: calls the storage-agnostic per-particle kernel into a stack scratch,...
Definition CD_EBParticleMesh.H:548
RealVect m_dx
Grid resolution.
Definition CD_EBParticleMesh.H:432
void interpolateParticleTSC(Real *a_particleField, const EBCellFAB &a_meshData, const int a_comp, const Box &a_validBox, const Box &a_gatherBox, const RealVect &a_position, const int &a_numComp, const bool a_forceIrregNGP) const noexcept
TSC interpolation onto one particle.
Definition CD_EBParticleMesh.H:900
ProblemDomain m_domain
Computational domain.
Definition CD_EBParticleMesh.H:404
const EBISBox * m_ebisbox
Non-owning alias to the caller's EBIS box.
Definition CD_EBParticleMesh.H:427
void interpolate(ParticleSoA< P, Traits > &a_particles, const EBCellFAB &a_meshData, const DepositionType a_interpType, const bool a_forceIrregNGP) const
Interpolate the first mesh components (a_comp == 0) onto payload columns.
Definition CD_EBParticleMesh.H:336
void deposit(EBCellFAB &a_meshData, const ParticleSoA< P, Traits > &a_particles, const DepositionType a_depositionType, const Real a_widthScale, const bool a_forceIrregNGP) const
Deposit payload columns onto the first mesh components (a_comp == 0).
Definition CD_EBParticleMesh.H:234
RealVect m_probLo
Lower-left corner of the computational domain.
Definition CD_EBParticleMesh.H:437
EBParticleMesh(const ProblemDomain &a_domain, const Box &a_region, const EBISBox &a_ebisbox, const RealVect &a_dx, const RealVect &a_probLo)
Full constructor; calls define.
Definition CD_EBParticleMesh.H:87
Box cloudBox(const RealVect &a_position, const RealVect &a_particleWidth) const noexcept
Cell box that exactly covers the support of a cloud of the given per-direction width.
Definition CD_EBParticleMesh.H:677
void interpolateParticleNGP(Real *a_particleField, const EBCellFAB &a_meshData, const int a_comp, const RealVect &a_position, const int &a_numComp) const noexcept
NGP interpolation onto one particle.
Definition CD_EBParticleMesh.H:815
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
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
double & weight(const std::size_t a_index) noexcept
Weight of particle i.
Definition CD_ParticleSoA.H:1222
std::size_t size() const noexcept
Number of particles currently stored.
Definition CD_ParticleSoA.H:882