1 #ifndef SUPERDROPLET_PC_H_
2 #define SUPERDROPLET_PC_H_
4 #ifdef ERF_USE_PARTICLES
11 #include <AMReX_StructOfArrays.H>
13 class SuperDropletPC :
public ERFPC
15 using MFPtr = std::unique_ptr<amrex::MultiFab>;
16 using BCTypeArr = amrex::GpuArray<ERF_BC, AMREX_SPACEDIM*2>;
21 SuperDropletPC ( amrex::ParGDBBase* a_gdb,
22 const std::vector<Species::Name>& a_species_mat,
23 const std::vector<Species::Name>& a_aerosol_mat,
25 const std::string& a_name =
"super_droplets" )
26 : ERFPC (a_gdb, a_name)
28 define( a_species_mat,
30 a_gdb->ParticleBoxArray(0),
31 a_gdb->ParticleDistributionMap(0),
36 SuperDropletPC (
const amrex::Geometry& a_geom,
37 const amrex::DistributionMapping& a_dmap,
38 const amrex::BoxArray& a_ba,
39 const std::vector<Species::Name>& a_species_mat,
40 const std::vector<Species::Name>& a_aerosol_mat,
42 const std::string& a_name =
"super_droplets" )
43 : ERFPC (a_geom, a_dmap, a_ba, a_name)
45 define(a_species_mat, a_aerosol_mat, a_ba, a_dmap, a_dt);
51 if (m_mass_change_logging) {
52 fclose(m_mass_change_log);
58 virtual void setSpeciesMaterial (
const Species::Name& a_name )
60 if (a_name == Species::Name::H2O) { m_idx_w = m_species_mat.size(); }
61 m_species_mat.push_back(std::make_unique<MaterialProperties>(a_name));
62 m_device_props_initialized =
false;
67 virtual void setSpeciesMaterial (
const std::vector<Species::Name>& a_names )
69 for (
auto& name : a_names) { setSpeciesMaterial(name); }
74 virtual const MaterialProperties& getSpeciesMaterial(
const Species::Name& a_name)
const
76 for (
auto& species : m_species_mat) {
77 if (species->m_name == a_name) {
return *species; }
79 amrex::Abort(
"SuperDropletPC::getSpeciesMaterial() - species not found");
80 return *m_species_mat[0];
85 virtual void setAerosolMaterial (
const Species::Name& a_name )
87 m_aerosol_mat.push_back(std::make_unique<MaterialProperties>(a_name));
88 m_device_props_initialized =
false;
93 virtual void setAerosolMaterial (
const std::vector<Species::Name>& a_names )
95 for (
auto& name : a_names) { setAerosolMaterial(name); }
99 void updateDeviceProperties();
102 template<
typename SOAType>
103 void setupMassPointers(SOAType& soa, SDPCDefn::SDSpeciesMassArr& sp_mass_ptrs,
104 SDPCDefn::SDAerosolMassArr& ae_mass_ptrs)
const
107 sp_mass_ptrs[i] = soa.GetRealData(idx_s(i, m_num_aerosols,
m_num_species)).data();
109 for (
int i = 0; i < m_num_aerosols; i++) {
110 ae_mass_ptrs[i] = soa.GetRealData(idx_a(i, m_num_aerosols,
m_num_species)).data();
115 AMREX_GPU_DEVICE AMREX_FORCE_INLINE
116 static void updateParticleAttributes(
118 amrex::ParticleReal* radius_ptr,
119 amrex::ParticleReal* mass_ptr,
121 amrex::ParticleReal rho_w,
122 int num_sp,
int num_ae,
123 const int* sp_sol_arr,
124 const int* ae_sol_arr,
125 const SDPCDefn::SDSpeciesMassArr sp_mass_ptrs,
126 const SDPCDefn::SDAerosolMassArr ae_mass_ptrs,
127 const amrex::ParticleReal* sp_rho_arr,
128 const amrex::ParticleReal* ae_rho_arr)
131 radius_ptr[particle_idx] = SD_effective_radius(
132 particle_idx, idx_w, rho_w,
134 sp_sol_arr, ae_sol_arr,
135 sp_mass_ptrs, ae_mass_ptrs,
136 sp_rho_arr, ae_rho_arr);
139 mass_ptr[particle_idx] = SD_total_mass(
140 particle_idx, num_sp, num_ae,
141 sp_mass_ptrs, ae_mass_ptrs);
145 [[nodiscard]]
virtual amrex::Vector<std::string> varNames ()
const override;
148 [[nodiscard]]
virtual amrex::Vector<std::string> meshPlotVarNames ()
const override;
151 virtual void computeMeshVar(
const std::string&,
153 const amrex::MultiFab&,
154 const int )
const override;
157 void InitializeParticles (
const int a_lev,
const amrex::Real a_t,
const MFPtr& a_ptr);
159 using ERFPC::InitializeParticles;
168 void setNumSDBoxDistribution(
int a_lev,
172 const amrex::RealBox&,
176 void setNumSDBubbleDistribution(
int a_lev,
180 const amrex::RealBox&,
186 virtual void SetAttributes ( amrex::MultiFab& a_mf );
191 virtual void DensityScaling (
const amrex::MultiFab& a_mf );
194 virtual void EvolveParticles (
int,
196 amrex::Vector<amrex::Vector<amrex::MultiFab>>&,
197 const amrex::Vector<MFPtr>& )
override
199 amrex::Abort(
"SuperDropletPC::EvolveParticles() is intentionally disabled.");
203 virtual void AdvectParticles (
int a_lev,
206 const amrex::MultiFab*
const a_flow_vel,
207 const amrex::MultiFab& a_density,
208 const amrex::MultiFab& a_pressure,
209 const amrex::MultiFab& a_temperature,
210 const amrex::Vector<MFPtr>& a_z_phys_nd,
211 const BCTypeArr& a_bctypes,
212 const bool a_recycle);
215 virtual void MassChange (
int a_lev,
217 const Species::Name& a_vap_name,
218 const amrex::MultiFab& a_temperature,
219 const amrex::MultiFab& a_pressure,
220 const amrex::MultiFab& a_sat_pressure,
221 const amrex::MultiFab& a_sat_ratio,
222 const amrex::Vector<MFPtr>& a_z_phys_nd,
223 const bool a_is_water);
226 virtual void Coalescence (
int a_lev,
228 const amrex::MultiFab& a_pressure,
229 const amrex::MultiFab& a_temperature);
232 virtual void Recycle (
const int a_lev,
233 const amrex::Vector<MFPtr>& a_z_phys_nd,
236 const bool a_recycle);
240 [[nodiscard]]
inline virtual amrex::Long NumSuperDroplets ()
242 return ERFPC::TotalNumberOfParticles();
246 [[nodiscard]]
virtual amrex::Real TotalNumberOfParticles ();
249 [[nodiscard]]
virtual amrex::Long NumSDDeactivated ();
252 virtual void Diagnostics (
int,
int,
amrex::Real,
bool);
254 virtual void ComputeDistributions (
int,
int,
256 amrex::ParticleReal );
257 #ifdef ERF_USE_ML_UPHYS_DIAGNOSTICS
259 virtual void ComputeBinnedDistributions (
int,
int );
261 virtual void ComputeBinnedDistributionsCell (
int,
int,
amrex::Real );
265 virtual void SDNumberDensity ( amrex::MultiFab&,
const amrex::MultiFab& a_z_phys_nd,
int a_lev,
const int a_comp=0 )
const;
267 virtual void numberDensity ( amrex::MultiFab&,
const amrex::MultiFab& a_z_phys_nd,
int a_lev,
const int a_comp=0 )
const;
269 virtual void massDensity ( amrex::MultiFab&,
const amrex::MultiFab& a_z_phys_nd,
const int& a_lev,
const int& a_comp=0 )
const override;
271 virtual void massFlux ( amrex::MultiFab&,
const amrex::MultiFab& a_z_phys_nd,
int a_lev,
const int,
const int a_comp=0 )
const;
274 virtual void speciesMassDensity ( amrex::MultiFab&,
275 const amrex::MultiFab& a_z_phys_nd,
278 const int a_comp = 0)
const;
281 virtual void cloudRainDensity ( amrex::MultiFab&,
282 const amrex::MultiFab& a_z_phys_nd,
286 const int a_comp = 0)
const;
289 virtual void speciesMassFlux ( amrex::MultiFab&,
const amrex::MultiFab& a_z_phys_nd,
int a_lev,
const int,
const int,
const int a_comp=0 )
const;
292 virtual void aerosolMassDensity ( amrex::MultiFab&,
const amrex::MultiFab& a_z_phys_nd,
int a_lev,
const int,
const int a_comp=0 )
const;
294 virtual void aerosolMassFlux ( amrex::MultiFab&,
const amrex::MultiFab& a_z_phys_nd,
int a_lev,
const int,
const int,
const int a_comp=0 )
const;
297 virtual void effectiveRadius ( amrex::MultiFab&,
const amrex::MultiFab& a_z_phys_nd,
int a_lev,
const int a_comp=0 )
const;
300 virtual void applyBoundaryTreatment (
int,
const amrex::Vector<MFPtr>&,
const BCTypeArr&,
const bool );
304 SDCoalescenceKernelType m_coalescence_kernel;
305 bool m_include_brownian_coalescence;
307 SDTerminalVelocityType m_term_vel_type_w;
309 int m_num_sd_per_cell;
310 bool m_density_scaling;
311 bool m_nucleate_particles;
312 bool m_prescribed_advection;
315 std::vector<std::unique_ptr<MaterialProperties>> m_species_mat;
317 std::vector<std::unique_ptr<MaterialProperties>> m_aerosol_mat;
326 bool m_mass_change_logging;
327 FILE* m_mass_change_log;
328 std::string m_mass_change_log_fname;
331 SDMassChangeTIMethod m_mass_change_ti;
332 long m_num_unconverged_particles;
334 amrex::IntVect m_coalescence_bin_size;
336 int m_distribution_grid_size;
338 amrex::MultiFab m_mf_buf;
340 #ifdef ERF_USE_ML_UPHYS_DIAGNOSTICS
345 amrex::MultiFab m_mass_ln_R_mf;
347 amrex::MultiFab m_num_ln_R_mf;
354 int m_num_initializations = 1;
356 std::vector< std::unique_ptr<SDInitialization> > m_initializations;
359 int m_num_injections = 0;
361 std::vector< std::unique_ptr<SDInjection> > m_injections;
367 bool m_place_randomly_in_cells;
370 std::mt19937 m_rndeng;
379 bool m_save_inactive;
382 amrex::Gpu::DeviceVector<amrex::ParticleReal> m_sp_density;
383 amrex::Gpu::DeviceVector<int> m_sp_solubility;
384 amrex::Gpu::DeviceVector<amrex::ParticleReal> m_sp_ionization;
385 amrex::Gpu::DeviceVector<amrex::ParticleReal> m_sp_mol_weight;
387 amrex::Gpu::DeviceVector<amrex::ParticleReal> m_ae_density;
388 amrex::Gpu::DeviceVector<int> m_ae_solubility;
389 amrex::Gpu::DeviceVector<amrex::ParticleReal> m_ae_ionization;
390 amrex::Gpu::DeviceVector<amrex::ParticleReal> m_ae_mol_weight;
393 bool m_device_props_initialized =
false;
404 void initializeDeviceProperties();
407 SDProcess::ProcessContext buildProcessContext(
int a_lev)
const
409 SDProcess::ProcessContext ctx;
410 const amrex::Geometry& geom = m_gdb->Geom(a_lev);
411 ctx.plo = geom.ProbLoArray();
412 ctx.phi = geom.ProbHiArray();
413 ctx.dxi = geom.InvCellSizeArray();
414 ctx.dx = geom.CellSizeArray();
415 ctx.domain = geom.Domain();
416 for (
int d = 0; d < AMREX_SPACEDIM; d++) {
417 ctx.is_periodic[d] = geom.isPeriodic(d) ? 1 : 0;
419 const auto cell_size = geom.CellSize();
420 ctx.cell_volume = AMREX_D_TERM(cell_size[0], *cell_size[1], *cell_size[2]);
422 ctx.num_aerosols = m_num_aerosols;
423 ctx.idx_water = m_idx_w;
424 ctx.rho_water = m_species_mat[m_idx_w]->m_density;
429 template<
typename SOAType,
typename AOSType>
430 void setupParticlePointers(
433 SDProcess::ParticlePointers& ptrs)
const
435 using namespace SDPCDefn;
437 constexpr
int rtoff_i = SuperDropletsIntIdx::ncomps;
438 constexpr
int rtoff_r = SuperDropletsRealIdx::ncomps;
440 ptrs.num_particles = aos.numParticles();
441 ptrs.mass_ptr = soa.GetRealData(SuperDropletsRealIdx::mass).data();
442 ptrs.radius_ptr = soa.GetRealData(rtoff_r + SuperDropletsRealIdxSoA_RT::radius).data();
443 ptrs.active_ptr = soa.GetIntData(rtoff_i + SuperDropletsIntIdxSoA_RT::active).data();
444 ptrs.v_ptr[0] = soa.GetRealData(SuperDropletsRealIdx::vx).data();
445 ptrs.v_ptr[1] = soa.GetRealData(SuperDropletsRealIdx::vy).data();
446 ptrs.v_ptr[2] = soa.GetRealData(SuperDropletsRealIdx::vz).data();
447 ptrs.vterm_ptr = soa.GetRealData(rtoff_r + SuperDropletsRealIdxSoA_RT::term_vel).data();
448 ptrs.mult_ptr = soa.GetRealData(rtoff_r + SuperDropletsRealIdxSoA_RT::multiplicity).data();
449 setupMassPointers(soa, ptrs.sp_mass_ptrs, ptrs.ae_mass_ptrs);
450 if (!m_device_props_initialized) {
451 const_cast<SuperDropletPC*
>(
this)->initializeDeviceProperties();
453 ptrs.sp_rho_arr = m_sp_density.data();
454 ptrs.sp_sol_arr = m_sp_solubility.data();
455 ptrs.sp_ion_arr = m_sp_ionization.data();
456 ptrs.sp_mw_arr = m_sp_mol_weight.data();
457 ptrs.ae_rho_arr = m_ae_density.data();
458 ptrs.ae_sol_arr = m_ae_solubility.data();
459 ptrs.ae_ion_arr = m_ae_ionization.data();
460 ptrs.ae_mw_arr = m_ae_mol_weight.data();
464 template<
typename TileFunc>
465 void forEachParticleTileBody(
466 ParIterType& pti,
int a_lev,
467 const SDProcess::ProcessContext& ctx,
470 int grid = pti.index();
471 auto& ptile = ParticlesAt(a_lev, pti);
472 auto& aos = ptile.GetArrayOfStructs();
473 auto& soa = ptile.GetStructOfArrays();
474 if (aos.numParticles() == 0) {
return; }
475 auto* p_pbox = aos().data();
476 SDProcess::ParticlePointers ptrs;
477 setupParticlePointers(soa, aos, ptrs);
478 func(pti, grid, p_pbox, ptrs, ctx);
482 template<
typename TileFunc>
484 void forEachParticleTile(
486 const SDProcess::ProcessContext& ctx,
490 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
492 for (ParIterType pti(*
this, a_lev); pti.isValid(); ++pti) {
493 forEachParticleTileBody(pti, a_lev, ctx, std::forward<TileFunc>(func));
500 template<
typename TileFunc>
502 void forEachParticleTileSerial(
int a_lev,
const SDProcess::ProcessContext& ctx, TileFunc&& func)
504 for (ParIterType pti(*
this, a_lev); pti.isValid(); ++pti) {
505 forEachParticleTileBody(pti, a_lev, ctx, std::forward<TileFunc>(func));
510 template<
typename TileFunc>
511 void forEachParticleTile(
int a_lev, TileFunc&& func)
514 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
516 for (ParIterType pti(*
this, a_lev); pti.isValid(); ++pti) {
517 int grid = pti.index();
518 auto& ptile = ParticlesAt(a_lev, pti);
519 auto& aos = ptile.GetArrayOfStructs();
520 auto& soa = ptile.GetStructOfArrays();
521 const int num_particles = aos.numParticles();
522 if (num_particles == 0) {
continue; }
523 auto* p_pbox = aos().data();
524 SDProcess::ParticlePointers ptrs;
525 setupParticlePointers(soa, aos, ptrs);
526 func(pti, grid, p_pbox, ptrs, num_particles);
531 virtual void readInputs ()
override
533 amrex::Abort(
"SuperDropletPC::readInputs(): Do not use this interface.");
540 void initializeParticlesNull (
const MFPtr&) { }
545 void define (
const std::vector<Species::Name>&,
546 const std::vector<Species::Name>&,
547 const amrex::BoxArray&,
548 const amrex::DistributionMapping&,
552 void add_superdroplet_attributes();
int m_num_species
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:28
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Common data structures for SuperDroplet physical processes.
Super-droplets initial properties.
Definition: ERF_SDInitialization.H:150
Definition: ERF_MaterialProperties.H:171