ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ParticleData.H
Go to the documentation of this file.
1 #ifndef ERF_PARTICLE_DATA_H_
2 #define ERF_PARTICLE_DATA_H_
3 
4 #ifdef ERF_USE_PARTICLES
5 
6 #include <map>
7 #include <vector>
8 #include <list>
9 #include <string>
10 #include <iostream>
11 
12 #include <AMReX_ParmParse.H>
13 #include <AMReX_Print.H>
14 #include <AMReX_Vector.H>
15 #include <AMReX_Gpu.H>
16 
17 #include <ERFPC.H>
18 
19 /**
20  * Container holding many of the particle-related data and options
21  */
22 
23 typedef std::map<std::string, ERFPC*> ParticleSpeciesMap;
24 typedef std::vector<std::string> ParticlesNamesVector;
25 typedef std::list<std::string> ParticlesNamesList;
26 
27 /**
28  * @brief Container holding particle-related data and options for multiple species.
29  */
30 class ParticleData
31 {
32  public:
33 
34  /*! Constructor */
35  ParticleData ()
36  {
37  BL_PROFILE("ParticleData::ParticleData()");
38 
39  amrex::ParmParse pp("particles");
40  m_disable_particle_op = false;
41  pp.queryAdd("disable_plt", m_disable_particle_op);
42 
43  m_particle_species.clear();
44  m_namelist.clear();
45  m_namelist_unalloc.clear();
46  }
47 
48  /*! Destructor */
49  ~ParticleData ()
50  {
51  BL_PROFILE("ParticleData::~ParticleData()");
52  for (ParticlesNamesVector::size_type i = 0; i < m_namelist.size(); i++) {
53  auto particles( m_particle_species[m_namelist[i]] );
54  delete particles;
55  }
56  m_particle_species.clear();
57  m_namelist.clear();
58  m_namelist_unalloc.clear();
59  }
60 
61  /*! Write particle info to plot files. Particles are stored with
62  * pos(2) = computational zeta; the on-disk plotfile holds the
63  * physical z, so convert in-place around the write. */
64  void writePlotFile ( const std::string& a_fname,
65  const amrex::Vector<std::unique_ptr<amrex::MultiFab>>& a_z_phys_nd ) const
66  {
67  BL_PROFILE("ParticleData::writePlotFile");
68  if (!m_disable_particle_op) {
69  for (ParticlesNamesVector::size_type i = 0; i < m_namelist.size(); i++) {
70  auto name( m_namelist[i] );
71  auto particles( m_particle_species.at(name) );
72  particles->ConvertZetaToZ(a_z_phys_nd);
73  particles->WritePlotFile(a_fname, name, particles->varNames());
74  particles->ConvertZToZeta(a_z_phys_nd);
75  }
76  }
77  }
78 
79  /*! Write checkpoint files */
80  void Checkpoint ( const std::string& a_fname ) const
81  {
82  BL_PROFILE("ParticleData::Checkpoint()");
83  for (ParticlesNamesVector::size_type i = 0; i < m_namelist.size(); i++) {
84  auto name( m_namelist[i] );
85  auto particles( m_particle_species.at(name) );
86  particles->Checkpoint( a_fname, name, true, particles->varNames() );
87  }
88  }
89 
90  /*! Get mesh plot quantities from each particle container */
91  void GetMeshPlotVarNames ( amrex::Vector<std::string>& a_names ) const
92  {
93  BL_PROFILE("ParticleData::GetMeshPlotVarNames()");
94  a_names.clear();
95  for (ParticlesNamesVector::size_type i = 0; i < m_namelist.size(); i++) {
96  auto name( m_namelist[i] );
97  auto particles( m_particle_species.at(name) );
98 
99  auto var_names = particles->meshPlotVarNames();
100  for (int n = 0; n < var_names.size(); n++) {
101  a_names.push_back( std::string(name+"_"+var_names[n]) );
102  }
103  }
104  }
105 
106  /**
107  * @brief Compute a mesh-based plot variable from particle data.
108  * @param[in] a_var_name Name of the variable to be computed.
109  * @param[out] a_mf MultiFab to store the resulting mesh variable.
110  * @param[in] a_z_phys_nd Nodal physical height field.
111  * @param[in] a_lev Current level.
112  */
113  void GetMeshPlotVar ( const std::string& a_var_name,
114  amrex::MultiFab& a_mf,
115  const amrex::MultiFab& a_z_phys_nd,
116  const int a_lev )
117  {
118  BL_PROFILE("ParticleData::GetMeshPlotVar()");
119  for (ParticlesNamesVector::size_type i = 0; i < m_namelist.size(); i++) {
120  auto particle_name( m_namelist[i] );
121  auto particles( m_particle_species.at(particle_name) );
122 
123  auto particle_var_names = particles->meshPlotVarNames();
124 
125  for (int n = 0; n < particle_var_names.size(); n++) {
126 
127  std::string var_name = particle_name+"_"+particle_var_names[n];
128  if ( var_name == a_var_name ) {
129  particles->computeMeshVar(particle_var_names[n], a_mf, a_z_phys_nd, a_lev);
130  return;
131  }
132  }
133  }
134  amrex::Abort("Requested var_name not found in ParticleData::GetMeshPlotVar");
135  }
136 
137  /*! Redistribute/rebalance particles data */
138  inline void Redistribute ()
139  {
140  BL_PROFILE("ParticleData::Redistribute()");
141  for (ParticlesNamesVector::size_type i = 0; i < m_namelist.size(); i++) {
142  m_particle_species[m_namelist[i]]->Redistribute();
143  }
144  }
145 
146  /*! Redistribute after AMR regrid. Also runs each species'
147  * SplitMergeAtLevelBoundary so new entrants on fine levels and
148  * departees on coarse levels are split/merged appropriately. */
149  inline void Redistribute (
150  const amrex::Vector<std::unique_ptr<amrex::MultiFab>>& /*a_z_phys_nd*/)
151  {
152  BL_PROFILE("ParticleData::Redistribute(z_phys_nd)");
153  for (ParticlesNamesVector::size_type i = 0; i < m_namelist.size(); i++) {
154  auto* pc = m_particle_species[m_namelist[i]];
155  pc->Redistribute();
156  pc->SplitMergeAtLevelBoundary();
157  }
158  }
159 
160  /*! Get species of a given name */
161  inline bool HasSpecies ( const std::string& a_name )
162  {
163  BL_PROFILE("ParticleData::HasSpecies()");
164  ParticleSpeciesMap::iterator it (m_particle_species.find(a_name));
165  if (it == m_particle_species.end()) {
166  return false;
167  } else {
168  return true;
169  }
170  }
171 
172  /*! Get species of a given name */
173  inline ERFPC* GetSpecies ( const std::string& a_name )
174  {
175  BL_PROFILE("ParticleData::GetSpecies()");
176  ParticleSpeciesMap::iterator it (m_particle_species.find(a_name));
177  if (it == m_particle_species.end()) {
178  amrex::Print() << "ERROR: unable to find particle species with name \""
179  << a_name << "\"!";
180  return nullptr;
181  } else {
182  return it->second;
183  }
184  }
185 
186  /*! accessor */
187  inline ERFPC* operator[] ( const std::string& a_name )
188  {
189  BL_PROFILE("ParticleData::operator[]");
190  ParticleSpeciesMap::iterator it (m_particle_species.find(a_name));
191  if (it == m_particle_species.end()) {
192  amrex::Print() << "ERROR: unable to find particle species with name \""
193  << a_name << "\"!";
194  return nullptr;
195  } else {
196  return it->second;
197  }
198  }
199 
200  /*! Get species of a given name (const version) */
201  inline const ERFPC* GetSpecies ( const std::string& a_name ) const
202  {
203  BL_PROFILE("ParticleData::GetSpecies()");
204  ParticleSpeciesMap::const_iterator it (m_particle_species.find(a_name));
205  if (it == m_particle_species.end()) {
206  amrex::Print() << "ERROR: unable to find particle species with name \""
207  << a_name << "\"!";
208  return nullptr;
209  } else {
210  return it->second;
211  }
212  }
213 
214  /*! accessor */
215  inline const ERFPC* operator[] ( const std::string& a_name ) const
216  {
217  BL_PROFILE("ParticleData::operator[]");
218  ParticleSpeciesMap::const_iterator it (m_particle_species.find(a_name));
219  if (it == m_particle_species.end()) {
220  amrex::Print() << "ERROR: unable to find particle species with name \""
221  << a_name << "\"!";
222  return nullptr;
223  } else {
224  return it->second;
225  }
226  }
227 
228  /*! Add a particle species to this container */
229  inline void pushBack (const std::string& a_name,
230  ERFPC* const a_pc )
231  {
232  BL_PROFILE("ParticleData::pushBack()");
233  AMREX_ASSERT(!contains(a_name));
234  m_particle_species[a_name] = a_pc;
235  m_namelist.push_back(a_name);
236  }
237 
238  /*! Add a name; particle container will be initialized later */
239  inline void addName (const std::string& a_name )
240  {
241  BL_PROFILE("ParticleData::addName()");
242  m_namelist_unalloc.push_back(a_name);
243  }
244 
245  /*! Returns list of names of particle species */
246  inline const ParticlesNamesVector& getNames () const
247  {
248  BL_PROFILE("ParticleData::getNames()");
249  return m_namelist;
250  }
251 
252  /*! Returns list of names of particle species that are unallocated */
253  inline ParticlesNamesList& getNamesUnalloc ()
254  {
255  BL_PROFILE("ParticleData::getNamesUnalloc()");
256  return m_namelist_unalloc;
257  }
258 
259  /*! queries if container has species of a certain name */
260  inline bool contains ( const std::string& a_name ) const
261  {
262  BL_PROFILE("ParticleData::contains()");
263  ParticleSpeciesMap::const_iterator it (m_particle_species.find(a_name));
264  return (it != m_particle_species.end());
265  }
266 
267  /*! query if container is empty */
268  inline bool isEmpty () const
269  {
270  BL_PROFILE("ParticleData::isEmpty()");
271  return (m_particle_species.size() == 0);
272  }
273 
274 
275  private:
276 
277  /*! Vector of all particle species */
278  ParticleSpeciesMap m_particle_species;
279  /*! Vector of particle species names */
280  ParticlesNamesVector m_namelist;
281  /*! List with names of unallocated species */
282  ParticlesNamesList m_namelist_unalloc;
283 
284  /*! Disable particle output in plotfile? (because expensive) */
285  bool m_disable_particle_op;
286 };
287 
288 #endif
289 #endif
ParmParse pp("prob")
std::string name
Definition: ERF_Plotfile2DCatalog.cpp:101