1#ifdef REMORA_USE_PARTICLES
4#include <AMReX_ParmParse.H>
8void REMORAPC::readInputs ()
10 BL_PROFILE(
"REMORAPC::readInputs");
12 ParmParse pp(
"remora."+m_name);
14 m_initialization_type = REMORAParticleInitializations::init_box_uniform;
15 pp.query(
"initial_distribution_type", m_initialization_type);
17 if (m_initialization_type == REMORAParticleInitializations::init_box_uniform)
19 Vector<Real> particle_box_lo(AMREX_SPACEDIM);
20 Vector<Real> particle_box_hi(AMREX_SPACEDIM);
23 for (
int i = 0; i < AMREX_SPACEDIM; i++) { particle_box_lo[i] = Geom(0).ProbLo(i); }
24 for (
int i = 0; i < AMREX_SPACEDIM; i++) { particle_box_hi[i] = Geom(0).ProbHi(i); }
26 pp.queryAdd(
"particle_box_lo", particle_box_lo, AMREX_SPACEDIM);
27 AMREX_ASSERT(particle_box_lo.size() == AMREX_SPACEDIM);
29 pp.queryAdd(
"particle_box_hi", particle_box_hi, AMREX_SPACEDIM);
30 AMREX_ASSERT(particle_box_hi.size() == AMREX_SPACEDIM);
32 m_particle_box.setLo(particle_box_lo);
33 m_particle_box.setHi(particle_box_hi);
37 place_randomly_in_cells =
true;
38 pp.query(
"place_randomly_in_cells", place_randomly_in_cells);
42 pp.query(
"initial_particles_per_cell", m_ppc_init);
44 m_advect_w_flow = (m_name == REMORAParticleNames::tracers ? true :
false);
45 pp.query(
"advect_with_flow", m_advect_w_flow);
51void REMORAPC::InitializeParticles (
const std::unique_ptr<MultiFab>& a_height_ptr)
53 BL_PROFILE(
"REMORAPC::initializeParticles");
55 if (m_initialization_type == REMORAParticleInitializations::init_box_uniform) {
56 initializeParticlesUniformDistributionInBox( a_height_ptr , m_particle_box );
58 Print() <<
"Error: " << m_initialization_type
59 <<
" is not a valid initialization for "
60 << m_name <<
" particle species.\n";
61 Error(
"See error message!");
68void REMORAPC::initializeParticlesUniformDistributionInBox (
const std::unique_ptr<MultiFab>& a_height_ptr,
69 const RealBox& particle_init_domain)
71 BL_PROFILE(
"REMORAPC::initializeParticlesUniformDistributionInBox");
74 const auto dx = Geom(lev).CellSizeArray();
75 const auto plo = Geom(lev).ProbLoArray();
77 int particles_per_cell = m_ppc_init;
79 iMultiFab num_particles( ParticleBoxArray(lev),
80 ParticleDistributionMap(lev),
82 num_particles.setVal(0);
84#pragma omp parallel if (Gpu::notInLaunchRegion())
86 for(MFIter mfi = MakeMFIter(lev); mfi.isValid(); ++mfi) {
87 const Box& tile_box = mfi.tilebox();
88 auto num_particles_arr = num_particles[mfi].array();
90 const auto height_arr = (*a_height_ptr)[mfi].array();
91 ParallelFor(tile_box, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
noexcept
93 Real
x = plo[0] + (i + 0.5)*dx[0];
94 Real
y = plo[1] + (j + 0.5)*dx[1];
95 Real
z = 0.125 * (height_arr(i,j ,k ) + height_arr(i+1,j ,k ) +
96 height_arr(i,j+1,k ) + height_arr(i+1,j+1,k ) +
97 height_arr(i,j ,k+1) + height_arr(i+1,j ,k+1) +
98 height_arr(i,j+1,k+1) + height_arr(i+1,j+1,k ) );
99 if (particle_init_domain.contains(RealVect(
x,
y,
z))) {
100 num_particles_arr(i,j,k) = particles_per_cell;
105 ParallelFor(tile_box, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
noexcept
107 Real
x = plo[0] + (i + 0.5)*dx[0];
108 Real
y = plo[1] + (j + 0.5)*dx[1];
109 Real
z = plo[2] + (k + 0.5)*dx[2];
110 if (particle_init_domain.contains(RealVect(
x,
y,
z))) {
111 num_particles_arr(i,j,k) = particles_per_cell;
117 iMultiFab offsets( ParticleBoxArray(lev),
118 ParticleDistributionMap(lev),
123#pragma omp parallel if (Gpu::notInLaunchRegion())
125 for(MFIter mfi = MakeMFIter(lev); mfi.isValid(); ++mfi) {
126 const Box& tile_box = mfi.tilebox();
130 int ncell = num_particles[mfi].numPts();
131 const int* in = num_particles[mfi].dataPtr();
132 int* out = offsets[mfi].dataPtr();
133 np = Scan::PrefixSum<int>( ncell,
134 [=] AMREX_GPU_DEVICE (
int i) ->
int {
return in[i]; },
135 [=] AMREX_GPU_DEVICE (
int i,
int const &
x) { out[i] =
x; },
136 Scan::Type::exclusive,
139 auto offset_arr = offsets[mfi].array();
141 auto& particle_tile = DefineAndReturnParticleTile(lev, mfi);
142 particle_tile.resize(np);
143 auto aos = &particle_tile.GetArrayOfStructs()[0];
144 auto& soa = particle_tile.GetStructOfArrays();
145 auto* vx_ptr = soa.GetRealData(REMORAParticlesRealIdxSoA::vx).data();
146 auto* vy_ptr = soa.GetRealData(REMORAParticlesRealIdxSoA::vy).data();
147 auto* vz_ptr = soa.GetRealData(REMORAParticlesRealIdxSoA::vz).data();
148 auto* mass_ptr = soa.GetRealData(REMORAParticlesRealIdxSoA::mass).data();
150 const auto num_particles_arr = num_particles[mfi].array();
152 auto my_proc = ParallelDescriptor::MyProc();
155 pid = ParticleType::NextID();
156 ParticleType::NextID(pid+np);
158 AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
static_cast<Long
>(pid + np) < LastParticleID,
159 "Error: overflow on particle id numbers!" );
161 if (a_height_ptr && place_randomly_in_cells) {
163 const auto height_arr = (*a_height_ptr)[mfi].array();
165 ParallelForRNG(tile_box, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k,
166 const RandomEngine& rnd_engine)
noexcept
168 int start = offset_arr(i,j,k);
169 for (
int n = start; n < start+num_particles_arr(i,j,k); n++) {
170 Real r[3] = {Random(rnd_engine), Random(rnd_engine), Random(rnd_engine)};
171 Real
v[3] = {0.0, 0.0, 0.0};
173 Real
x = plo[0] + (i + r[0])*dx[0];
174 Real
y = plo[1] + (j + r[1])*dx[1];
176 Real sx[] = { amrex::Real(1.) - r[0], r[0]};
177 Real sy[] = { amrex::Real(1.) - r[1], r[1]};
179 Real height_at_pxy_lo = 0.;
180 for (
int ii = 0; ii < 2; ++ii) {
181 for (
int jj = 0; jj < 2; ++jj) {
182 height_at_pxy_lo += sx[ii] * sy[jj] * height_arr(i+ii,j+jj,k);
185 Real height_at_pxy_hi = 0.;
186 for (
int ii = 0; ii < 2; ++ii) {
187 for (
int jj = 0; jj < 2; ++jj) {
188 height_at_pxy_hi += sx[ii] * sy[jj] * height_arr(i+ii,j+jj,k+1);
192 Real
z = height_at_pxy_lo + r[2] * (height_at_pxy_hi - height_at_pxy_lo);
198 p.pos(0) =
x; p.pos(1) =
y; p.pos(2) =
z;
200 p.idata(REMORAParticlesIntIdxAoS::k) = k;
202 vx_ptr[n] =
v[0]; vy_ptr[n] =
v[1]; vz_ptr[n] =
v[2];
204 mass_ptr[n] = 1.0e-6;
208 }
else if (a_height_ptr && !place_randomly_in_cells) {
210 const auto height_arr = (*a_height_ptr)[mfi].array();
212 ParallelFor(tile_box, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
noexcept
214 int start = offset_arr(i,j,k);
215 for (
int n = start; n < start+num_particles_arr(i,j,k); n++) {
216 Real r[3] = {0.3, 0.7, 0.25};
217 Real
v[3] = {0.0, 0.0, 0.0};
219 Real
x = plo[0] + (i + r[0])*dx[0];
220 Real
y = plo[1] + (j + r[1])*dx[1];
222 Real sx[] = { amrex::Real(1.) - r[0], r[0]};
223 Real sy[] = { amrex::Real(1.) - r[1], r[1]};
225 Real height_at_pxy_lo = 0.;
226 for (
int ii = 0; ii < 2; ++ii) {
227 for (
int jj = 0; jj < 2; ++jj) {
228 height_at_pxy_lo += sx[ii] * sy[jj] * height_arr(i+ii,j+jj,k);
231 Real height_at_pxy_hi = 0.;
232 for (
int ii = 0; ii < 2; ++ii) {
233 for (
int jj = 0; jj < 2; ++jj) {
234 height_at_pxy_hi += sx[ii] * sy[jj] * height_arr(i+ii,j+jj,k+1);
238 Real
z = height_at_pxy_lo + r[2] * (height_at_pxy_hi - height_at_pxy_lo);
244 p.pos(0) =
x; p.pos(1) =
y; p.pos(2) =
z;
246 p.idata(REMORAParticlesIntIdxAoS::k) = k;
248 vx_ptr[n] =
v[0]; vy_ptr[n] =
v[1]; vz_ptr[n] =
v[2];
250 mass_ptr[n] = 1.0e-6;
254 }
else if (!a_height_ptr && place_randomly_in_cells) {
256 ParallelForRNG(tile_box, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k,
257 const RandomEngine& rnd_engine)
noexcept
259 int start = offset_arr(i,j,k);
260 for (
int n = start; n < start+num_particles_arr(i,j,k); n++) {
261 Real r[3] = {Random(rnd_engine), Random(rnd_engine), Random(rnd_engine)};
262 Real
v[3] = {0.0, 0.0, 0.0};
264 Real
x = plo[0] + (i + r[0])*dx[0];
265 Real
y = plo[1] + (j + r[1])*dx[1];
266 Real
z = plo[2] + (k + r[2])*dx[2];
272 p.pos(0) =
x; p.pos(1) =
y; p.pos(2) =
z;
274 p.idata(REMORAParticlesIntIdxAoS::k) = k;
276 vx_ptr[n] =
v[0]; vy_ptr[n] =
v[1]; vz_ptr[n] =
v[2];
278 mass_ptr[n] = 1.0e-6;
284 ParallelFor(tile_box, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
noexcept
286 int start = offset_arr(i,j,k);
287 for (
int n = start; n < start+num_particles_arr(i,j,k); n++) {
288 Real r[3] = {0.3, 0.7, 0.25};
289 Real
v[3] = {0.0, 0.0, 0.0};
291 Real
x = plo[0] + (i + r[0])*dx[0];
292 Real
y = plo[1] + (j + r[1])*dx[1];
293 Real
z = plo[2] + (k + r[2])*dx[2];
299 p.pos(0) =
x; p.pos(1) =
y; p.pos(2) =
z;
301 p.idata(REMORAParticlesIntIdxAoS::k) = k;
303 vx_ptr[n] =
v[0]; vy_ptr[n] =
v[1]; vz_ptr[n] =
v[2];
305 mass_ptr[n] = 1.0e-6;