Skip to content

Commit 93f8d60

Browse files
do proper mapping from linearized index to cell coordinates in pulsed decay collision module (#6827)
The pulsed decay collision module (PR #6558) evaluates a space- and time-dependent decay rate using the parser. It reconstructs cell coordinates from a linearized index `i_cell` returned by `ParticleUtils::findParticlesInEachCell()`. However, `ParticleUtils::findParticlesInEachCell()` (via `amrex::DenseBins`) and `amrex::Box::atOffset` use different index orderings (z-fastest vs. x-fastest). The original implementation mixed these conventions, resulting in incorrect cell indices and thus incorrect physical coordinates passed to the parser. This PR fixes the bug by using a consistent indexing convention when mapping `i_cell` back to cell coordinates.
1 parent fcd1be2 commit 93f8d60

1 file changed

Lines changed: 27 additions & 15 deletions

File tree

Source/Particles/Collision/PulsedDecay/PulsedDecay.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,14 @@ PulsedDecay::doCollisions (amrex::Real cur_time, amrex::Real dt, MultiParticleCo
191191
index_type const* AMREX_RESTRICT bins_1_ptr = bins_1.binsPtr();
192192
amrex::ParticleReal* AMREX_RESTRICT wtot1_in_each_cell = wtot1_vec.dataPtr();
193193
amrex::ParticleReal* AMREX_RESTRICT w1 = soa_1.m_rdata[PIdx::w];
194+
uint64_t* AMREX_RESTRICT idcpu1 = soa_1.m_idcpu;
194195

195196
amrex::ParallelFor( np1,
196197
[=] AMREX_GPU_DEVICE (int ip) noexcept
197198
{
198-
amrex::Gpu::Atomic::AddNoRet(&wtot1_in_each_cell[bins_1_ptr[ip]],
199-
w1[ip]);
199+
if (idcpu1[ip] == amrex::ParticleIdCpus::Invalid) { return; }
200+
201+
amrex::Gpu::Atomic::AddNoRet(&wtot1_in_each_cell[bins_1_ptr[ip]], w1[ip]);
200202
}
201203
);
202204

@@ -205,9 +207,11 @@ PulsedDecay::doCollisions (amrex::Real cur_time, amrex::Real dt, MultiParticleCo
205207
index_type* AMREX_RESTRICT p_counts = num_products_vec.dataPtr();
206208

207209
// Get grid information needed to compute physical cell center coordinates
208-
const amrex::Box& box = mfi.tilebox();
210+
const amrex::Box box = mfi.tilebox(amrex::IntVect::TheZeroVector());
209211
const amrex::XDim3 xyzmin = WarpX::LowerCorner(box, lev, 0.0_rt);
210-
const amrex::Dim3 lo = lbound(box);
212+
#if AMREX_SPACEDIM > 1
213+
const amrex::IntVect len = box.length();
214+
#endif
211215
const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM> dx = geom_lev.CellSizeArray();
212216

213217
amrex::ParallelForRNG( n_cells,
@@ -216,21 +220,31 @@ PulsedDecay::doCollisions (amrex::Real cur_time, amrex::Real dt, MultiParticleCo
216220
const amrex::ParticleReal wtot1 = wtot1_in_each_cell[i_cell];
217221
if (wtot1 == 0.0_prt) { return; }
218222

219-
// Get physical coordinates at cell center
220-
const amrex::IntVect iv = box.atOffset(i_cell);
223+
// Note that ParticleUtils::findParticlesInEachCell() uses DenseBins,
224+
// which maps like i_cell = ix * nz + iz for 2D
225+
// and i_cell = ix * (ny * nz) + iy * nz + iz for 3D.
226+
// Don't use box.getOffset(i_cell), which assumes i_cell = ix + nx * iz
227+
// for 2D and i_cell = ix + nx * (iy + ny * iz) for 3D.
228+
229+
// Get physical coordinates at cell center.
221230
amrex::XDim3 xyz_cc = {0.0_rt, 0.0_rt, 0.0_rt};
222231
const amrex::Real half = 0.5_rt;
223232
#if defined(WARPX_DIM_1D_Z)
224-
xyz_cc.z = xyzmin.z + (iv[0] - lo.x + half)*dx[0];
233+
xyz_cc.z = xyzmin.z + (i_cell + half)*dx[0];
225234
#elif defined(WARPX_DIM_RCYLINDER) || defined(WARPX_DIM_RSPHERE)
226-
xyz_cc.x = xyzmin.x + (iv[0] - lo.x + half)*dx[0];
235+
xyz_cc.x = xyzmin.x + (i_cell + half)*dx[0];
227236
#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
228-
xyz_cc.x = xyzmin.x + (iv[0] - lo.x + half)*dx[0];
229-
xyz_cc.z = xyzmin.z + (iv[1] - lo.y + half)*dx[1];
237+
const int ix = i_cell / len[1];
238+
const int iz = i_cell % len[1];
239+
xyz_cc.x = xyzmin.x + (ix + half)*dx[0];
240+
xyz_cc.z = xyzmin.z + (iz + half)*dx[1];
230241
#elif defined(WARPX_DIM_3D)
231-
xyz_cc.x = xyzmin.x + (iv[0] - lo.x + half)*dx[0];
232-
xyz_cc.y = xyzmin.y + (iv[1] - lo.y + half)*dx[1];
233-
xyz_cc.z = xyzmin.z + (iv[2] - lo.z + half)*dx[2];
242+
const int ix = i_cell / (len[1] * len[2]);
243+
const int iy = (i_cell / len[2]) % len[1];
244+
const int iz = i_cell % len[2];
245+
xyz_cc.x = xyzmin.x + (ix + half)*dx[0];
246+
xyz_cc.y = xyzmin.y + (iy + half)*dx[1];
247+
xyz_cc.z = xyzmin.z + (iz + half)*dx[2];
234248
#endif
235249

236250
// Compute total weight of products to create in this cell
@@ -284,8 +298,6 @@ PulsedDecay::doCollisions (amrex::Real cur_time, amrex::Real dt, MultiParticleCo
284298
index_type const* AMREX_RESTRICT cell_offsets_1 = bins_1.offsetsPtr();
285299
index_type const* AMREX_RESTRICT indices_1 = bins_1.permutationPtr();
286300

287-
uint64_t* AMREX_RESTRICT idcpu1 = soa_1.m_idcpu;
288-
289301
amrex::ParticleReal* AMREX_RESTRICT wA = soa_productA.m_rdata[PIdx::w];
290302
amrex::ParticleReal* AMREX_RESTRICT uAx = soa_productA.m_rdata[PIdx::ux];
291303
amrex::ParticleReal* AMREX_RESTRICT uAy = soa_productA.m_rdata[PIdx::uy];

0 commit comments

Comments
 (0)