8 #ifndef ERFPC_PARTICLE_TO_MESH_H_
9 #define ERFPC_PARTICLE_TO_MESH_H_
13 #include <AMReX_MultiFabUtil.H>
15 template<
typename ValueFunc>
16 void ERFPC::ERFPCParticleToMesh (amrex::MultiFab& a_mf,
17 const amrex::MultiFab& a_z_phys_nd,
18 int a_lev,
int a_comp,
19 ValueFunc&& value_func,
22 using namespace amrex;
25 AMREX_ASSERT(numParticlesOutOfRange(*
this, 0) == 0);
30 const auto& geom = Geom(a_lev);
31 const auto plo = geom.ProbLoArray();
32 const auto dxi = geom.InvCellSizeArray();
33 const Real dx = geom.CellSize(0);
34 const Real dy = geom.CellSize(1);
35 const Box domain = geom.Domain();
36 const int k_max = domain.bigEnd(AMREX_SPACEDIM-1);
37 const int i_lo = domain.smallEnd(0), i_hi = domain.bigEnd(0);
38 const int j_lo = domain.smallEnd(1), j_hi = domain.bigEnd(1);
39 const int k_lo = domain.smallEnd(AMREX_SPACEDIM-1);
40 const bool per_x = geom.isPeriodic(0);
41 const bool per_y = geom.isPeriodic(1);
45 owned.define(a_mf.boxArray(), a_mf.DistributionMap(), 1, IntVect(1));
47 if (a_lev < finestLevel()) {
48 iMultiFab exposed = makeFineMask(a_mf, ParticleBoxArray(a_lev+1),
49 GetParGDB()->refRatio(a_lev), 1, 0);
50 iMultiFab::Copy(owned, exposed, 0, 0, 1, 0);
52 owned.setVal(1, 0, 1, 0);
54 owned.FillBoundary(geom.periodicity());
60 #pragma omp parallel if (Gpu::notInLaunchRegion())
62 for (ParConstIterType pti(*
this, a_lev); pti.isValid(); ++pti)
64 const int grid = pti.index();
65 const auto& ptile = ParticlesAt(a_lev, pti);
66 const auto& aos = ptile.GetArrayOfStructs();
67 const int np = aos.numParticles();
68 if (np == 0) {
continue; }
70 auto rho = a_mf[grid].array();
71 auto zheight = a_z_phys_nd[grid].array();
72 const Array4<const int> valid = composite ? owned.const_array(grid) : Array4<const int>{};
74 const auto ptd = ptile.getConstParticleTileData();
78 const auto&
p = ptd.m_aos[i];
79 if (
p.id() <= 0) { return; }
81 const Real pval =
static_cast<Real>(value_func(ptd, i));
83 const Real lx =
static_cast<Real>((
p.pos(0) - plo[0]) * dxi[0]) +
Real(0.5);
84 const int ix =
static_cast<int>(Math::floor(
lx)) - 1;
85 const Real wx1 =
lx -
static_cast<Real>(ix + 1);
88 const Real ly =
static_cast<Real>((
p.pos(1) - plo[1]) * dxi[1]) +
Real(0.5);
89 const int iy =
static_cast<int>(Math::floor(
ly)) - 1;
90 const Real wy1 =
ly -
static_cast<Real>(iy + 1);
93 const int kz =
static_cast<int>(amrex::Math::floor((
p.pos(AMREX_SPACEDIM-1) - plo[AMREX_SPACEDIM-1])
94 * dxi[AMREX_SPACEDIM-1]));
95 const int ix_p =
static_cast<int>(Math::floor((
p.pos(0) - plo[0]) * dxi[0]));
96 const int iy_p =
static_cast<int>(Math::floor((
p.pos(1) - plo[1]) * dxi[1]));
97 const Real fx =
static_cast<Real>((
p.pos(0) - plo[0]) * dxi[0]) -
static_cast<Real>(ix_p);
98 const Real fy =
static_cast<Real>((
p.pos(1) - plo[1]) * dxi[1]) -
static_cast<Real>(iy_p);
100 auto zface = [=] AMREX_GPU_DEVICE (
int k_face) ->
Real {
101 return zheight(ix_p , iy_p , k_face) * (
Real(1.0)-fx) * (
Real(1.0)-fy)
102 + zheight(ix_p+1, iy_p , k_face) * fx * (
Real(1.0)-fy)
103 + zheight(ix_p , iy_p+1, k_face) * (
Real(1.0)-fx) * fy
104 + zheight(ix_p+1, iy_p+1, k_face) * fx * fy;
113 const int kz_hi_safe = amrex::min(k_max, zheight.end[2] - 2);
114 const int kz_lo_safe = amrex::max(0, zheight.begin[2] + 1);
118 const Real z_ctr_k =
Real(0.5) * (z_lo_k + z_hi_k);
124 p.pos(0),
p.pos(1),
p.pos(AMREX_SPACEDIM-1),
129 if (p_z >= z_ctr_k) {
133 if (kz < kz_hi_safe) {
135 const Real z_ctr_hi =
Real(0.5) * (z_hi_k + z_hi2);
136 span = z_ctr_hi - z_ctr_k;
138 span = z_hi_k - z_lo_k;
140 wz_hi = (p_z - z_ctr_k) / span;
141 wz_lo =
Real(1.0) - wz_hi;
146 if (kz > kz_lo_safe) {
148 const Real z_ctr_lo =
Real(0.5) * (z_lo2 + z_lo_k);
149 span = z_ctr_k - z_ctr_lo;
151 span = z_hi_k - z_lo_k;
153 wz_lo = (z_ctr_k - p_z) / span;
154 wz_hi =
Real(1.0) - wz_lo;
158 auto dz_cell = [=] AMREX_GPU_DEVICE (
int ic,
int jc,
int kc) ->
Real {
160 zheight(ic , jc , kc+1) - zheight(ic , jc , kc)
161 + zheight(ic+1, jc , kc+1) - zheight(ic+1, jc , kc)
162 + zheight(ic , jc+1, kc+1) - zheight(ic , jc+1, kc)
163 + zheight(ic+1, jc+1, kc+1) - zheight(ic+1, jc+1, kc) );
175 for (
int iz = 0; iz < 2; ++iz) {
176 const int kc = iz ? kz_hi : kz_lo;
177 const Real wz = iz ? wz_hi : wz_lo;
178 for (
int jy = 0; jy < 2; ++jy) {
179 for (
int jx = 0; jx < 2; ++jx) {
180 if (valid(ix+jx, iy+jy, kc)) {
181 weight += (jx ? wx1 : wx0) * (jy ? wy1 : wy0) * wz;
189 auto deposit = [=] AMREX_GPU_DEVICE (
int ic,
int jc,
int kc,
Real w_horiz,
Real w_z)
197 if (w_horiz ==
Real(0.0) || w_z ==
Real(0.0)) {
return; }
198 if (composite && !valid(ic,jc,kc)) {
return; }
204 const int ic_dz = per_x ? ic : amrex::max(i_lo, amrex::min(i_hi, ic));
205 const int jc_dz = per_y ? jc : amrex::max(j_lo, amrex::min(j_hi, jc));
206 const int kc_dz = amrex::max(k_lo, amrex::min(k_max, kc));
207 const Real dz = dz_cell(ic_dz, jc_dz, kc_dz);
209 const Real contrib = pval * w_horiz * w_z * inv_dxdy / (
dz * weight);
210 Gpu::Atomic::AddNoRet(&
rho(ic, jc, kc, a_comp), contrib);
213 deposit(ix , iy , kz_lo, wx0*wy0, wz_lo);
214 deposit(ix+1, iy , kz_lo, wx1*wy0, wz_lo);
215 deposit(ix , iy+1, kz_lo, wx0*wy1, wz_lo);
216 deposit(ix+1, iy+1, kz_lo, wx1*wy1, wz_lo);
217 deposit(ix , iy , kz_hi, wx0*wy0, wz_hi);
218 deposit(ix+1, iy , kz_hi, wx1*wy0, wz_hi);
219 deposit(ix , iy+1, kz_hi, wx0*wy1, wz_hi);
220 deposit(ix+1, iy+1, kz_hi, wx1*wy1, wz_hi);
224 a_mf.SumBoundary(geom.periodicity());
@ zface
Definition: ERF_EBStruct.H:29
const Real lx
Definition: ERF_InitCustomPertVels_CloudChamber.H:10
const Real ly
Definition: ERF_InitCustomPertVels_CloudChamber.H:11
const Real dy
Definition: ERF_InitCustomPert_ABL.H:45
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real z_from_zeta(amrex::Real x, amrex::Real y, amrex::Real zeta, amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > const &plo, amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > const &dxi, amrex::Array4< amrex::Real const > const &height_arr) noexcept
Convert computational vertical coordinate zeta to physical z at column (x, y).
Definition: ERF_TerrainConversion.H:77
@ rho
Definition: ERF_Kessler.H:25
@ dz
Definition: ERF_AdvanceWDM6.cpp:273
@ p
Definition: ERF_WSM6.H:301
Definition: ERF_ConsoleIO.cpp:17