42#ifndef CD_EBPARTICLEMESH_H
43#define CD_EBPARTICLEMESH_H
52#include <ProblemDomain.H>
64#include <CD_NamespaceHeader.H>
89 const EBISBox& a_ebisbox,
91 const RealVect& a_probLo)
93 this->
define(a_domain, a_region, a_ebisbox, a_dx, a_probLo);
107 const EBISBox& a_ebisbox,
108 const RealVect& a_dx,
109 const RealVect& a_probLo)
111 CH_TIME(
"EBParticleMesh::define");
134 template <
typename P,
typename Traits>
140 const Real a_widthScale,
141 const bool a_forceIrregNGP)
const
143 CH_TIME(
"EBParticleMesh::depositWeight");
152 [&](
const std::size_t a_i, Real* a_out) {
153 a_out[0] = a_particles.
weight(a_i);
167 template <
typename P,
typename Traits>
172 const Real a_widthScale,
173 const bool a_forceIrregNGP)
const
175 CH_TIME(
"EBParticleMesh::depositWeight");
177 this->
depositWeight(a_meshData, 0, a_particles, a_depositionType, a_widthScale, a_forceIrregNGP);
194 template <
auto... Members,
typename P,
typename Traits>
200 const Real a_widthScale,
201 const bool a_forceIrregNGP)
const
203 CH_TIME(
"EBParticleMesh::deposit");
205 static_assert(
sizeof...(Members) == 1 ||
sizeof...(Members) == SpaceDim,
206 "deposit selects either one scalar column or SpaceDim vector-component columns");
211 static_cast<int>(
sizeof...(Members)),
215 [&](
const std::size_t a_i, Real* a_out) {
217 ((a_out[k++] =
static_cast<Real
>(a_particles.template get<Members>(a_i))), ...);
232 template <
auto... Members,
typename P,
typename Traits>
237 const Real a_widthScale,
238 const bool a_forceIrregNGP)
const
240 CH_TIME(
"EBParticleMesh::deposit");
242 this->
deposit<Members...>(a_meshData, 0, a_particles, a_depositionType, a_widthScale, a_forceIrregNGP);
261 template <
typename P,
typename Traits,
typename GatherFunc>
267 const Real a_widthScale,
268 const bool a_forceIrregNGP,
269 GatherFunc&& a_gather)
const
271 CH_TIME(
"EBParticleMesh::depositGathered");
280 std::forward<GatherFunc>(a_gather));
296 template <
auto... Members,
typename P,
typename Traits>
299 const EBCellFAB& a_meshData,
302 const bool a_forceIrregNGP)
const
304 CH_TIME(
"EBParticleMesh::interpolate");
306 static_assert(
sizeof...(Members) == 1 ||
sizeof...(Members) == SpaceDim,
307 "interpolate targets either one scalar column or SpaceDim vector-component columns");
313 static_cast<int>(
sizeof...(Members)),
316 [&](
const std::size_t a_i,
const Real* a_in) {
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++])),
334 template <
auto... Members,
typename P,
typename Traits>
337 const EBCellFAB& a_meshData,
339 const bool a_forceIrregNGP)
const
341 CH_TIME(
"EBParticleMesh::interpolate");
343 this->
interpolate<Members...>(a_particles, a_meshData, 0, a_interpType, a_forceIrregNGP);
358 template <
typename P,
typename Traits>
361 const EBCellFAB& a_meshData,
364 const bool a_forceIrregNGP)
const
366 CH_TIME(
"EBParticleMesh::interpolateWeight");
374 [&](
const std::size_t a_i,
const Real* a_in) {
375 a_particles.
weight(a_i) = a_in[0];
388 template <
typename P,
typename Traits>
391 const EBCellFAB& a_meshData,
393 const bool a_forceIrregNGP)
const
395 CH_TIME(
"EBParticleMesh::interpolateWeight");
397 this->
interpolateWeight(a_particles, a_meshData, 0, a_interpType, a_forceIrregNGP);
454 template <
typename P,
typename Traits,
typename StrengthFn>
461 const Real a_widthScale,
462 const bool a_forceIrregNGP,
463 StrengthFn a_gather)
const
465 CH_TIME(
"EBParticleMesh::depositCore");
467 CH_assert(a_meshData.nComp() >= a_comp + a_numComp);
470 for (
int dir = 0; dir < SpaceDim; dir++) {
474 const RealVect cicWidth = 1 * a_widthScale * RealVect::Unit;
475 const RealVect tscWidth = 2 * a_widthScale * RealVect::Unit;
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];
485 const std::size_t numParticles = a_particles.
size();
487 Real strength[SpaceDim];
489 switch (a_depositionType) {
490 case DepositionType::NGP: {
491 for (std::size_t i = 0; i < numParticles; i++) {
492 a_gather(i, strength);
497 case DepositionType::CIC: {
498 for (std::size_t i = 0; i < numParticles; i++) {
499 a_gather(i, strength);
511 case DepositionType::TSC: {
512 for (std::size_t i = 0; i < numParticles; i++) {
513 a_gather(i, strength);
526 MayDay::Abort(
"EBParticleMesh::depositCore -- logic bust");
546 template <
typename P,
typename Traits,
typename ScatterFn>
549 const EBCellFAB& a_meshData,
553 const bool a_forceIrregNGP,
554 ScatterFn a_scatter)
const
556 CH_TIME(
"EBParticleMesh::interpolateCore");
558 CH_assert(a_meshData.nComp() >= a_comp + a_numComp);
563 switch (a_interpType) {
564 case DepositionType::NGP: {
566 gatherBox = Box(IntVect::Zero, IntVect::Zero);
569 case DepositionType::CIC: {
570 validBox = grow(
m_domain.domainBox(), -1);
571 gatherBox = Box(IntVect::Zero, IntVect::Unit);
574 case DepositionType::TSC: {
575 validBox = grow(
m_domain.domainBox(), -2);
576 gatherBox = Box(IntVect::Zero, 2 * IntVect::Unit);
580 MayDay::Error(
"EBParticleMesh::interpolateCore - logic bust");
584 const std::size_t numParticles = a_particles.
size();
586 Real field[SpaceDim];
588 switch (a_interpType) {
589 case DepositionType::NGP: {
590 for (std::size_t i = 0; i < numParticles; i++) {
596 case DepositionType::CIC: {
597 for (std::size_t i = 0; i < numParticles; i++) {
610 case DepositionType::TSC: {
611 for (std::size_t i = 0; i < numParticles; i++) {
625 MayDay::Abort(
"EBParticleMesh::interpolateCore -- logic bust");
649 const RealVect& a_position,
650 const Real& a_volumeFactor,
651 const Real* a_strength,
652 const int& a_numComp)
const noexcept
656 CH_assert(
m_region.contains(particleIV));
658 FArrayBox& rho = a_rho.getFArrayBox();
660 for (
int comp = 0; comp < a_numComp; comp++) {
661 rho(particleIV, a_comp + comp) += a_strength[comp] * a_volumeFactor;
677 cloudBox(
const RealVect& a_position,
const RealVect& a_particleWidth)
const noexcept
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;
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
713 CH_assert(
m_region.contains(particleIV));
715 FArrayBox& rho = a_rho.getFArrayBox();
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;
724 auto cicKernel = [&](
const IntVect& iv) ->
void {
725 Real weight = a_volumeFactor;
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];
732 weight *= std::max(0.0, std::min(b, L) - std::max(a, -L));
735 for (
int comp = 0; comp < a_numComp; comp++) {
736 rho(iv, a_comp + comp) += weight * a_strength[comp];
740 BoxLoops::loop<D_DECL(1, 1, 1)>(this->
cloudBox(a_position, a_particleWidth), cicKernel);
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
767 CH_assert(
m_region.contains(particleIV));
769 FArrayBox& rho = a_rho.getFArrayBox();
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;
778 auto tscKernel = [&](
const IntVect& iv) ->
void {
779 Real weight = a_volumeFactor;
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];
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;
794 weight *= factor * ((beta - alpha) - (beta * std::abs(beta) - alpha * std::abs(alpha)) / L);
797 for (
int comp = 0; comp < a_numComp; comp++) {
798 rho(iv, a_comp + comp) += weight * a_strength[comp];
802 BoxLoops::loop<D_DECL(1, 1, 1)>(this->
cloudBox(a_position, a_particleWidth), tscKernel);
816 const EBCellFAB& a_meshData,
818 const RealVect& a_position,
819 const int& a_numComp)
const noexcept
822 const FArrayBox& meshData = a_meshData.getFArrayBox();
823 const Real factor =
m_ebisbox->isCovered(particleIV) ? 0.0 : 1.0;
825 for (
int comp = 0; comp < a_numComp; comp++) {
826 a_particleField[comp] = factor * meshData(particleIV, a_comp + comp);
843 const EBCellFAB& a_meshData,
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
854 CH_assert(
m_region.contains(particleIV));
856 const FArrayBox& meshData = a_meshData.getFArrayBox();
858 for (
int comp = 0; comp < a_numComp; comp++) {
859 a_particleField[comp] = 0.0;
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);
867 else if (!(
m_ebisbox->isCovered(particleIV))) {
868 auto cicKernel = [&](
const IntVect& iv) ->
void {
871 const RealVect L = (
m_probLo - a_position) /
m_dx + (RealVect(iv) + 0.5 * RealVect::Unit);
873 for (
int dir = 0; dir < SpaceDim; dir++) {
874 weight *= (1. - std::abs(L[dir]));
877 for (
int comp = 0; comp < a_numComp; comp++) {
878 a_particleField[comp] += weight * meshData(iv, a_comp + comp);
882 const Box gatherBox = a_gatherBox + loIndex;
884 BoxLoops::loop<D_DECL(1, 1, 1)>(gatherBox, cicKernel);
901 const EBCellFAB& a_meshData,
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
912 CH_assert(
m_region.contains(particleIV));
914 const FArrayBox& meshData = a_meshData.getFArrayBox();
916 for (
int comp = 0; comp < a_numComp; comp++) {
917 a_particleField[comp] = 0.0;
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);
925 else if (!(
m_ebisbox->isCovered(particleIV))) {
926 auto tscKernel = [&](
const IntVect& iv) ->
void {
929 const RealVect L = (
m_probLo - a_position) /
m_dx + (RealVect(iv) + 0.5 * RealVect::Unit);
931 for (
int dir = 0; dir < SpaceDim; dir++) {
932 const Real& l = std::abs(L[dir]);
935 weight *= 0.75 - l * l;
938 weight *= 0.5 * (1.5 - l) * (1.5 - l);
942 for (
int comp = 0; comp < a_numComp; comp++) {
943 a_particleField[comp] += weight * meshData(iv, a_comp + comp);
947 const Box gatherBox = a_gatherBox + loIndex;
949 BoxLoops::loop<D_DECL(1, 1, 1)>(gatherBox, tscKernel);
954#include <CD_NamespaceFooter.H>
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