Skip to content

Commit 54d0623

Browse files
committed
SoA: InitRandom/RandomPerBox/OnePerCell
Support more init methods on SoA particle containers.
1 parent 07f87b0 commit 54d0623

File tree

5 files changed

+151
-89
lines changed

5 files changed

+151
-89
lines changed

Src/Particle/AMReX_ParticleContainer.H

+21-3
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,23 @@ struct ParticleLocData
106106
* a given component, then the extra values will be set to zero. If more components
107107
* are specified, it is a compile-time error.
108108
*
109+
* Note that the position attributes, first AMREX_SPACEDIM in ParticleReal, and the IDs, first
110+
* two ints, are skipped here.
111+
* Note that the counts in the type of the SoAParticle definition are explicit about these default-required
112+
* attributes.
113+
*
109114
* Example usage:
110115
*
111-
* ParticleInitType<0, 2, 4, 1> pdata = {{}, {7, 9}, {1.5, 2.5, 3.5, 4.5}, {11}};
116+
* ParticleInitType<Particle<0, 2>, 4, 1> pdata = {{}, {7, 9}, {1.5, 2.5, 3.5, 4.5}, {11}};
117+
* ParticleInitTypeSoA<4, 3> pdata = {{1.5, 2.5, 3.5, 4.5}, {7, 9, 11}}; // 3D: SoAParticle<7, 5>
112118
*/
113-
template<int NStructReal, int NStructInt, int NArrayReal, int NArrayInt>
119+
template <int NArrayReal, int NArrayInt>
120+
struct ParticleInitTypeSoA
121+
{
122+
std::array<double, NArrayReal > real_array_data;
123+
std::array<int, NArrayInt > int_array_data;
124+
};
125+
template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt>
114126
struct ParticleInitType
115127
{
116128
std::array<double, NStructReal> real_struct_data;
@@ -177,7 +189,13 @@ public:
177189

178190
using ParticleContainerType = ParticleContainer_impl<ParticleType, NArrayReal, NArrayInt, Allocator>;
179191
using ParticleTileType = ParticleTile<ParticleType, NArrayReal, NArrayInt, Allocator>;
180-
using ParticleInitData = ParticleInitType<NStructReal, NStructInt, NArrayReal, NArrayInt>;
192+
using ParticleInitData = typename std::conditional<
193+
T_ParticleType::is_soa_particle,
194+
// SoA Particle: init w/o positions and id/cpu, but explicitly listed in define
195+
ParticleInitTypeSoA<NArrayReal - AMREX_SPACEDIM, NArrayInt - 2>,
196+
// legacy particle: init w/o positions and id/cpu, only implicitly listed in define
197+
ParticleInitType<T_ParticleType::NReal, T_ParticleType::NInt, NArrayReal, NArrayInt>
198+
>::type;
181199

182200
//! A single level worth of particles is indexed (grid id, tile id)
183201
//! for both SoA and AoS data.

Src/Particle/AMReX_ParticleInit.H

+116-73
Original file line numberDiff line numberDiff line change
@@ -1063,8 +1063,27 @@ InitRandom (Long icount,
10631063

10641064
if (who == MyProc) {
10651065

1066-
if constexpr(!ParticleType::is_soa_particle)
1067-
{
1066+
if constexpr(ParticleType::is_soa_particle) {
1067+
for (int i = 0; i < AMREX_SPACEDIM; i++) {
1068+
host_real_attribs[pld.m_lev][ind][i].push_back(pos[j*AMREX_SPACEDIM+i]);
1069+
}
1070+
1071+
host_int_attribs[pld.m_lev][ind][0].push_back(ParticleType::NextID());
1072+
host_int_attribs[pld.m_lev][ind][1].push_back(MyProc);
1073+
1074+
host_particles[pld.m_lev][ind];
1075+
1076+
// add the real...
1077+
for (int i = AMREX_SPACEDIM; i < NArrayReal; i++) {
1078+
host_real_attribs[pld.m_lev][ind][i].push_back(static_cast<ParticleReal>(pdata.real_array_data[i]));
1079+
}
1080+
1081+
// ... and int array data
1082+
for (int i = 2; i < NArrayInt; i++) {
1083+
host_int_attribs[pld.m_lev][ind][i].push_back(pdata.int_array_data[i]);
1084+
}
1085+
}
1086+
else {
10681087
ParticleType p;
10691088
for (int i = 0; i < AMREX_SPACEDIM; i++) {
10701089
p.pos(i) = pos[j*AMREX_SPACEDIM + i];
@@ -1094,25 +1113,6 @@ InitRandom (Long icount,
10941113
for (int i = 0; i < NArrayInt; i++) {
10951114
host_int_attribs[pld.m_lev][ind][i].push_back(pdata.int_array_data[i]);
10961115
}
1097-
} else {
1098-
for (int i = 0; i < AMREX_SPACEDIM; i++) {
1099-
host_real_attribs[pld.m_lev][ind][i].push_back(pos[j*AMREX_SPACEDIM+i]);
1100-
}
1101-
1102-
host_int_attribs[pld.m_lev][ind][0].push_back(ParticleType::NextID());
1103-
host_int_attribs[pld.m_lev][ind][1].push_back(MyProc);
1104-
1105-
host_particles[pld.m_lev][ind];
1106-
1107-
// add the real...
1108-
for (int i = AMREX_SPACEDIM; i < NArrayReal; i++) {
1109-
host_real_attribs[pld.m_lev][ind][i].push_back(static_cast<ParticleReal>(pdata.real_array_data[i]));
1110-
}
1111-
1112-
// ... and int array data
1113-
for (int i = 2; i < NArrayInt; i++) {
1114-
host_int_attribs[pld.m_lev][ind][i].push_back(pdata.int_array_data[i]);
1115-
}
11161116
}
11171117
}
11181118
}
@@ -1127,11 +1127,11 @@ InitRandom (Long icount,
11271127
auto& dst_tile = GetParticles(host_lev)[std::make_pair(grid,tile)];
11281128
auto old_size = dst_tile.GetArrayOfStructs().size();
11291129
auto new_size = old_size;
1130-
if constexpr(!ParticleType::is_soa_particle)
1130+
if constexpr(ParticleType::is_soa_particle)
11311131
{
1132-
new_size += src_tile.size();
1133-
} else {
11341132
new_size += host_real_attribs[host_lev][std::make_pair(grid,tile)][0].size();
1133+
} else {
1134+
new_size += src_tile.size();
11351135
}
11361136
dst_tile.resize(new_size);
11371137

@@ -1362,44 +1362,71 @@ ParticleContainer_impl<ParticleType, NArrayReal, NArrayInt, Allocator>
13621362
for (Long jcnt = 0; jcnt < icount_per_box; jcnt++) {
13631363
for (Long kcnt = 0; kcnt < icount_per_box; kcnt++)
13641364
{
1365-
p.pos(0) = static_cast<ParticleReal>(grid_box.lo(0) + (dist(mt) + icnt) / icount_per_box * grid_box.length(0));
1366-
p.pos(1) = static_cast<ParticleReal>(grid_box.lo(1) + (dist(mt) + jcnt) / icount_per_box * grid_box.length(1));
1367-
p.pos(2) = static_cast<ParticleReal>(grid_box.lo(2) + (dist(mt) + kcnt) / icount_per_box * grid_box.length(2));
1365+
// the position data
1366+
for (int d = 0; d < AMREX_SPACEDIM; d++) {
1367+
p.pos(d) = static_cast<ParticleReal>(grid_box.lo(d) + (dist(mt) + icnt) / icount_per_box * grid_box.length(d));
1368+
}
13681369

1369-
for (int i = 0; i < AMREX_SPACEDIM; i++)
1370-
AMREX_ASSERT(p.pos(i) < grid_box.hi(i));
1370+
for (int d = 0; d < AMREX_SPACEDIM; d++)
1371+
AMREX_ASSERT(p.pos(d) < grid_box.hi(d));
13711372

1372-
// the real struct data
1373-
for (int i = 0; i < NStructReal; i++) {
1374-
p.rdata(i) = static_cast<ParticleReal>(pdata.real_struct_data[i]);
1375-
}
1373+
if constexpr(ParticleType::is_soa_particle) {
1374+
if (!Where(p, pld)) {
1375+
amrex::Abort("ParticleContainer::InitRandom(): invalid particle");
1376+
}
1377+
AMREX_ASSERT(pld.m_lev >= 0 && pld.m_lev <= finestLevel());
1378+
std::pair<int, int> ind(pld.m_grid, pld.m_tile);
13761379

1377-
// the int struct data
1378-
p.id() = ParticleType::NextID();
1379-
p.cpu() = ParallelDescriptor::MyProc();
1380+
// IDs
1381+
p.id() = ParticleType::NextID();
1382+
p.cpu() = ParallelDescriptor::MyProc();
13801383

1381-
for (int i = 0; i < NStructInt; i++) {
1382-
p.idata(i) = pdata.int_struct_data[i];
1383-
}
1384+
// add the real (after position)
1385+
for (int i = AMREX_SPACEDIM; i < NArrayReal; i++) {
1386+
m_particles[pld.m_lev][ind].push_back_real(i, static_cast<ParticleReal>(pdata.real_array_data[i]));
1387+
}
13841388

1385-
// locate the particle
1386-
if (!Where(p, pld)) {
1387-
amrex::Abort("ParticleContainer::InitRandomPerBox(): invalid particle");
1389+
// add the int array data (after id, cpu)
1390+
for (int i = 2; i < NArrayInt; i++) {
1391+
m_particles[pld.m_lev][ind].push_back_int(i, pdata.int_array_data[i]);
1392+
}
1393+
1394+
// add
1395+
m_particles[pld.m_lev][ind].push_back(p);
13881396
}
1389-
AMREX_ASSERT(pld.m_lev >= 0 && pld.m_lev <= finestLevel());
1390-
std::pair<int, int> ind(pld.m_grid, pld.m_tile);
1397+
else {
1398+
// the real struct data
1399+
for (int i = 0; i < NStructReal; i++) {
1400+
p.rdata(i) = static_cast<ParticleReal>(pdata.real_struct_data[i]);
1401+
}
13911402

1392-
// add the struct
1393-
m_particles[pld.m_lev][ind].push_back(p);
1403+
// the int struct data
1404+
p.id() = ParticleType::NextID();
1405+
p.cpu() = ParallelDescriptor::MyProc();
13941406

1395-
// add the real...
1396-
for (int i = 0; i < NArrayReal; i++) {
1397-
m_particles[pld.m_lev][ind].push_back_real(i, static_cast<ParticleReal>(pdata.real_array_data[i]));
1398-
}
1407+
for (int i = 0; i < NStructInt; i++) {
1408+
p.idata(i) = pdata.int_struct_data[i];
1409+
}
13991410

1400-
// ... and int array data
1401-
for (int i = 0; i < NArrayInt; i++) {
1402-
m_particles[pld.m_lev][ind].push_back_int(i, pdata.int_array_data[i]);
1411+
// locate the particle
1412+
if (!Where(p, pld)) {
1413+
amrex::Abort("ParticleContainer::InitRandomPerBox(): invalid particle");
1414+
}
1415+
AMREX_ASSERT(pld.m_lev >= 0 && pld.m_lev <= finestLevel());
1416+
std::pair<int, int> ind(pld.m_grid, pld.m_tile);
1417+
1418+
// add the struct
1419+
m_particles[pld.m_lev][ind].push_back(p);
1420+
1421+
// add the real...
1422+
for (int i = 0; i < NArrayReal; i++) {
1423+
m_particles[pld.m_lev][ind].push_back_real(i, static_cast<ParticleReal>(pdata.real_array_data[i]));
1424+
}
1425+
1426+
// ... and int array data
1427+
for (int i = 0; i < NArrayInt; i++) {
1428+
m_particles[pld.m_lev][ind].push_back_int(i, pdata.int_array_data[i]);
1429+
}
14031430
}
14041431

14051432
} } }
@@ -1438,48 +1465,64 @@ InitOnePerCell (Real x_off, Real y_off, Real z_off, const ParticleInitData& pdat
14381465

14391466
const Real* dx = geom.CellSize();
14401467

1441-
ParticleType p;
1442-
14431468
// We'll generate the particles in parallel -- but no tiling of the grid here.
14441469
for (MFIter mfi(*m_dummy_mf[0], false); mfi.isValid(); ++mfi) {
14451470
Box grid = ParticleBoxArray(0)[mfi.index()];
14461471
auto ind = std::make_pair(mfi.index(), mfi.LocalTileIndex());
14471472
RealBox grid_box (grid,dx,geom.ProbLo());
1473+
1474+
// tile for one particle
14481475
ParticleTile<ParticleType, NArrayReal, NArrayInt, amrex::PinnedArenaAllocator> ptile_tmp;
1476+
ptile_tmp.resize(1);
1477+
auto ptd = ptile_tmp.getParticleTileData();
1478+
14491479
for (IntVect beg = grid.smallEnd(), end=grid.bigEnd(), cell = grid.smallEnd(); cell <= end; grid.next(cell))
14501480
{
1451-
// the real struct data
1452-
AMREX_D_TERM(p.pos(0) = static_cast<ParticleReal>(grid_box.lo(0) + (x_off + cell[0]-beg[0])*dx[0]);,
1453-
p.pos(1) = static_cast<ParticleReal>(grid_box.lo(1) + (y_off + cell[1]-beg[1])*dx[1]);,
1454-
p.pos(2) = static_cast<ParticleReal>(grid_box.lo(2) + (z_off + cell[2]-beg[2])*dx[2]););
1481+
// particle index
1482+
constexpr int i = 0;
1483+
1484+
// the position data
1485+
for (int d = 0; d < AMREX_SPACEDIM; d++) {
1486+
ptile_tmp.pos(i, d) = static_cast<ParticleReal>(grid_box.lo(d) + (x_off + cell[d]-beg[d])*dx[d]);
1487+
}
14551488

14561489
for (int d = 0; d < AMREX_SPACEDIM; ++d) {
1457-
AMREX_ASSERT(p.pos(d) < grid_box.hi(d));
1490+
AMREX_ASSERT(ptile_tmp.pos(i, d) < grid_box.hi(d));
14581491
}
14591492

1460-
for (int i = 0; i < NStructReal; i++) {
1461-
p.rdata(i) = static_cast<ParticleReal>(pdata.real_struct_data[i]);
1493+
if constexpr(!ParticleType::is_soa_particle) {
1494+
for (int n = 0; n < NStructReal; n++) {
1495+
ptd.rdata(n)[i] = static_cast<ParticleReal>(pdata.real_struct_data[n]);
1496+
}
14621497
}
14631498

14641499
// the int struct data
1465-
p.id() = ParticleType::NextID();
1466-
p.cpu() = ParallelDescriptor::MyProc();
1467-
1468-
for (int i = 0; i < NStructInt; i++) {
1469-
p.idata(i) = pdata.int_struct_data[i];
1500+
if constexpr(ParticleType::is_soa_particle) {
1501+
ptd.idata(0)[i] = ParticleType::NextID();
1502+
ptd.idata(1)[i] = ParallelDescriptor::MyProc();
1503+
}
1504+
else {
1505+
auto& p = make_particle<ParticleType>{}(ptd, i);
1506+
p.id() = ParticleType::NextID();
1507+
p.cpu() = ParallelDescriptor::MyProc();
14701508
}
14711509

1472-
// add the struct
1473-
ptile_tmp.push_back(p);
1510+
if constexpr(!ParticleType::is_soa_particle) {
1511+
for (int n = 0; n < NStructInt; n++) {
1512+
ptd.idata(n)[i] = pdata.int_struct_data[n];
1513+
}
1514+
}
14741515

14751516
// add the real...
1476-
for (int i = 0; i < NArrayReal; i++) {
1477-
ptile_tmp.push_back_real(i, static_cast<ParticleReal>(pdata.real_array_data[i]));
1517+
int n_min_real = ParticleType::is_soa_particle ? AMREX_SPACEDIM : 0; // jump over position
1518+
for (int n = n_min_real; n < NArrayReal; n++) {
1519+
ptile_tmp.push_back_real(n, static_cast<ParticleReal>(pdata.real_array_data[n]));
14781520
}
14791521

14801522
// ... and int array data
1481-
for (int i = 0; i < NArrayInt; i++) {
1482-
ptile_tmp.push_back_int(i, pdata.int_array_data[i]);
1523+
int n_min_int = ParticleType::is_soa_particle ? 2 : 0; // jump over cpuid
1524+
for (int n = n_min_int; n < NArrayInt; n++) {
1525+
ptile_tmp.push_back_int(n, pdata.int_array_data[n]);
14831526
}
14841527
}
14851528

Tests/Particles/AssignDensity/main.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ void test_assign_density(TestParams& parms)
2121
{
2222

2323
RealBox real_box;
24-
for (int n = 0; n < BL_SPACEDIM; n++) {
24+
for (int n = 0; n < AMREX_SPACEDIM; n++) {
2525
real_box.setLo(n, 0.0);
2626
real_box.setHi(n, 1.0);
2727
}
@@ -48,10 +48,10 @@ void test_assign_density(TestParams& parms)
4848
MultiFab density(ba, dmap, 1, 0);
4949
density.setVal(0.0);
5050

51-
MultiFab partMF(ba, dmap, 1 + BL_SPACEDIM, 1);
51+
MultiFab partMF(ba, dmap, 1 + AMREX_SPACEDIM, 1);
5252
partMF.setVal(0.0);
5353

54-
typedef ParticleContainer<1 + BL_SPACEDIM> MyParticleContainer;
54+
typedef ParticleContainer<1 + AMREX_SPACEDIM> MyParticleContainer;
5555
MyParticleContainer myPC(geom, dmap, ba);
5656
myPC.SetVerbose(false);
5757

Tests/Particles/InitRandom/main.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ void testSOA ()
6060
}
6161

6262
// Add some particles
63-
constexpr int NReal = 12;
64-
constexpr int NInt = 4;
63+
constexpr int NReal = AMREX_SPACEDIM + 12;
64+
constexpr int NInt = 2 + 4;
6565

6666
typedef ParticleContainerPureSoA<NReal, NInt> MyPC;
6767
MyPC myPC(geom, dmap, ba, ref_ratio);
@@ -70,7 +70,7 @@ void testSOA ()
7070
int num_particles = nppc * AMREX_D_TERM(ncells, * ncells, * ncells);
7171
bool serialize = false;
7272
int iseed = 451;
73-
MyPC::ParticleInitData pdata = {{}, {},
73+
MyPC::ParticleInitData pdata = {
7474
{1.0, 2.0, 3.0, 4.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0},
7575
{5, 14, 15, 16}};
7676

Tests/Particles/ParticleIterator/main.cpp

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
#include "AMReX_Vector.H"
2+
#include "AMReX_FabArray.H"
3+
#include "AMReX_Particles.H"
4+
15
#include <iostream>
26
#include <map>
37
#include <vector>
48

5-
#include <AMReX_Vector.H>
6-
#include "AMReX_FabArray.H"
7-
#include "AMReX_Particles.H"
89

910
using namespace amrex;
1011

@@ -19,7 +20,7 @@ int main(int argc, char* argv[])
1920
int coord = 0;
2021

2122
RealBox real_box;
22-
for (int n = 0; n < BL_SPACEDIM; n++)
23+
for (int n = 0; n < AMREX_SPACEDIM; n++)
2324
{
2425
real_box.setLo(n,0.0);
2526
real_box.setHi(n,1.0);
@@ -49,10 +50,10 @@ int main(int argc, char* argv[])
4950
for (int lev = 0; lev < nlevs; lev++)
5051
dmap[lev].define(ba[lev]);
5152

52-
typedef ParticleContainer<1+BL_SPACEDIM> MyParticleContainer;
53+
using MyParticleContainer = ParticleContainer<1+AMREX_SPACEDIM>;
5354
MyParticleContainer MyPC(geom, dmap, ba, rr);
5455

55-
MyParticleContainer::ParticleInitData pdata = {{1.0},{},{},{}};
56+
MyParticleContainer::ParticleInitData pdata = {{1.0, AMREX_D_DECL(1.0, 2.0, 3.0)},{},{},{}};
5657
MyPC.InitOnePerCell(0.5, 0.5, 0.5, pdata);
5758
MyParticleContainer::do_tiling = true;
5859

@@ -61,7 +62,7 @@ int main(int argc, char* argv[])
6162
#ifdef AMREX_USE_OMP
6263
#pragma omp parallel
6364
#endif
64-
for (ParIter<1+BL_SPACEDIM> mfi(MyPC, 0); mfi.isValid(); ++mfi) {
65+
for (ParIter<1+AMREX_SPACEDIM> mfi(MyPC, 0); mfi.isValid(); ++mfi) {
6566
amrex::AllPrintToFile("particle_iterator_out") << mfi.index() << " " << mfi.tileIndex() << "\n";
6667
}
6768
}

0 commit comments

Comments
 (0)