ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ProbCommon.H
Go to the documentation of this file.
1 #ifndef ERF_PROBCOMMON_H_
2 #define ERF_PROBCOMMON_H_
3 
4 #include <AMReX_ParmParse.H>
5 #include <AMReX_Geometry.H>
6 #include <AMReX_FArrayBox.H>
7 #include <AMReX_MultiFab.H>
8 
9 #include "ERF_DataStruct.H"
10 #include "ERF_EOS.H"
11 #include "ERF_HSEUtils.H"
12 #include "ERF_TileNoZ.H"
13 
16  amrex::Real T_0 = 300.0;
17 };
18 
19 template <typename T>
20 T erf_get_single_value (std::istream& is, int n)
21 {
22  T r = 0;
23  std::string line;
24  if (std::getline(is, line)) {
25  std::stringstream ss(line);
26  ss >> r;
27  if (ss.fail()) {
28  amrex::Abort("Failed to read");
29  }
30  if (ss >> r) {
31  amrex::Print() << "Trying to read line " << n << " in this file " << std::endl;
32  amrex::Abort("Wrong format: more than one number in this line");
33  }
34  } else {
35  amrex::Abort("Unable to read this line");
36  }
37  return r;
38 }
39 
40 /**
41  * Class to hold problem-specific routines
42 */
44 {
45 public:
46 
47  /**
48  * Virtual destructor to avoid data leakage with derived class
49  */
50  virtual ~ProblemBase () = default;
51 
52  /**
53  * Function to initialize the hydrostatic reference density
54  *
55  * @param[out] rho_hse hydrostatic reference density
56  * @param[in] z_phys_nd height coordinate at nodes
57  * @param[in] z_phys_cc height coordinate at cell centers
58  * @param[in] geom container for geometric information
59  */
60  virtual void
61  erf_init_dens_hse (amrex::MultiFab& /*rho_hse*/,
62  std::unique_ptr<amrex::MultiFab>& /*z_phys_nd*/,
63  std::unique_ptr<amrex::MultiFab>& /*z_phys_cc*/,
64  amrex::Geometry const& /*geom*/)
65  {
66  amrex::Print() << "Hydrostatically balanced density was NOT set"
67  << " -- an appropriate init_type should probably have been specified"
68  << " (e.g., input_sounding, WRFInput, or Metgrid)"
69  << std::endl;
70  amrex::Error("Should never call erf_init_dens_hse for "+name()+" problem");
71  }
72 
73  virtual void
74  erf_init_dens_hse_moist (amrex::MultiFab& /*rho_hse*/,
75  std::unique_ptr<amrex::MultiFab>& /*z_phys_nd*/,
76  amrex::Geometry const& /*geom*/)
77  {
78 
79  }
80 
81  /**
82  * Function to perform custom initialization of a test problem
83  *
84  * @param[in] bx cell-centered box on which to initialize scalars
85  * @param[in] xbx box on which to initialize x-component of velocity
86  * @param[in] ybx box on which to initialize y-component of velocity
87  * @param[in] zbx box on which to initialize z-component of velocity
88  * @param[out] state cell-centered variables to be filled in this routine
89  * @param[out] x_velocity x-component of velocity to be filled in this routine
90  * @param[out] y_velocity y-component of velocity to be filled in this routine
91  * @param[out] z_velocity z-component of velocity to be filled in this routine
92  * @param[out] r_hse hydrostatic reference density
93  * @param[out] p_hse hydrostatic reference pressure
94  * @param[in] z_nd height coordinate at nodes
95  * @param[in] z_cc height coordinate at cell centers
96  * @param[in] qv water vapor
97  * @param[in] qc cloud water
98  * @param[in] qi cloud ice
99  * @param[in] mf_m map factor on cell centers
100  * @param[in] mf_u map factor on x-faces
101  * @param[in] mf_v map factor on y-faces
102  * @param[in] sc SolverChoice structure that carries parameters
103  */
104  virtual void
105  init_custom_pert (const amrex::Box& /*bx*/,
106  const amrex::Box& /*xbx*/,
107  const amrex::Box& /*ybx*/,
108  const amrex::Box& /*zbx*/,
109  amrex::Array4<amrex::Real const> const& /*state*/,
110  amrex::Array4<amrex::Real > const& /*state_pert*/,
111  amrex::Array4<amrex::Real > const& /*x_vel_pert*/,
112  amrex::Array4<amrex::Real > const& /*y_vel_pert*/,
113  amrex::Array4<amrex::Real > const& /*z_vel_pert*/,
114  amrex::Array4<amrex::Real > const& /*r_hse*/,
115  amrex::Array4<amrex::Real > const& /*p_hse*/,
116  amrex::Array4<amrex::Real const> const& /*z_nd*/,
117  amrex::Array4<amrex::Real const> const& /*z_cc*/,
118  amrex::GeometryData const& /*geomdata*/,
119  amrex::Array4<amrex::Real const> const& /*mf_m*/,
120  amrex::Array4<amrex::Real const> const& /*mf_u*/,
121  amrex::Array4<amrex::Real const> const& /*mf_v*/,
122  const SolverChoice& /*sc*/,
123  const int /*lev*/)
124  {
125  amrex::Print() << "No perturbation to background fields supplied for "
126  << name() << " problem" << std::endl;
127  }
128 
129  /**
130  * Function to update user-specified temperature source terms that can
131  * vary with time and height.
132  *
133  * @param[in] time current time
134  * @param[out] rhotheta_source forcing profile
135  * @param[in] geom container for geometric information
136  * @param[in] z_phys_cc height coordinate at cell centers
137  */
138  virtual void
140  amrex::Vector<amrex::Real>& src,
141  amrex::Gpu::DeviceVector<amrex::Real>& d_src,
142  const amrex::Geometry& geom,
143  std::unique_ptr<amrex::MultiFab>& /*z_phys_cc*/)
144  {
145  if (src.empty()) return;
146 
147  amrex::Warning("Temperature forcing not defined for "+name()+" problem");
148 
149  const int khi = geom.Domain().bigEnd()[2];
150  // const amrex::Real* prob_lo = geom.ProbLo();
151  // const auto dx = geom.CellSize();
152  for (int k = 0; k <= khi; k++)
153  {
154  // const amrex::Real z_cc = prob_lo[2] + (k+0.5)* dx[2];
155  // set RHS term of RhoTheta equation based on time, z_cc here
156  src[k] = 0.0;
157  }
158 
159  // Copy from host version to device version
160  amrex::Gpu::copy(amrex::Gpu::hostToDevice, src.begin(), src.end(), d_src.begin());
161  }
162 
163  /**
164  * Function to update user-specified moisture source terms that can
165  * vary with time and height.
166  *
167  * @param[in] time current time
168  * @param[out] rhoqt_source moisture forcing profile
169  * @param[in] geom container for geometric information
170  * @param[in] z_phys_cc height coordinate at cell centers
171  */
172  virtual void
174  amrex::Vector<amrex::Real>& qsrc,
175  amrex::Gpu::DeviceVector<amrex::Real>& d_qsrc,
176  const amrex::Geometry& geom,
177  std::unique_ptr<amrex::MultiFab>& /*z_phys_cc*/)
178  {
179  if (qsrc.empty()) return;
180 
181  amrex::Warning("Moisture forcing not defined for "+name()+" problem");
182 
183  const int khi = geom.Domain().bigEnd()[2];
184  // const amrex::Real* prob_lo = geom.ProbLo();
185  // const auto dx = geom.CellSize();
186  for (int k = 0; k <= khi; k++)
187  {
188  // const amrex::Real z_cc = prob_lo[2] + (k+0.5)* dx[2];
189  // set RHS term of RhoQ1 equation based on time, z_cc here
190  qsrc[k] = 0.0;
191  }
192 
193  // Copy from host version to device version
194  amrex::Gpu::copy(amrex::Gpu::hostToDevice, qsrc.begin(), qsrc.end(), d_qsrc.begin());
195  }
196 
197  /**
198  * Function to update the vertical velocity profile, used to add subsidence
199  * source terms for x-mom, y-mom, rho*theta, rho*Q1, and rho*Q2.
200  *
201  * TODO: Currently, this is only called by InitData, so there is no time
202  * dependence.
203  *
204  * @param[in] time current time
205  * @param[out] wbar w vel forcing profile
206  * @param[in] geom container for geometric information
207  * @param[in] z_phys_cc height coordinate at cell centers
208  */
209  virtual void
211  amrex::Vector<amrex::Real>& wbar,
212  amrex::Gpu::DeviceVector<amrex::Real>& d_wbar,
213  const amrex::Geometry& geom,
214  std::unique_ptr<amrex::MultiFab>& /*z_phys_cc*/)
215  {
216  if (wbar.empty()) return;
217 
218  amrex::Warning("Moisture forcing not defined for "+name()+" problem");
219 
220  const int khi = geom.Domain().bigEnd()[2];
221  // const amrex::Real* prob_lo = geom.ProbLo();
222  // const auto dx = geom.CellSize();
223  for (int k = 0; k <= khi; k++)
224  {
225  // const amrex::Real z_cc = prob_lo[2] + (k+0.5)* dx[2];
226  // set vertical velocity profile based on time, z_cc here
227  wbar[k] = 0.0;
228  }
229 
230  // Copy from host version to device version
231  amrex::Gpu::copy(amrex::Gpu::hostToDevice, wbar.begin(), wbar.end(), d_wbar.begin());
232  }
233 
234  /**
235  * Function to update user-specified geostrophic wind profile.
236  *
237  * @param[in] time current time
238  * @param[out] u_geos geostrophic wind profile
239  * @param[out] v_geos geostrophic wind profile
240  * @param[in] geom container for geometric information
241  * @param[in] z_phys_cc height coordinate at cell centers
242  */
243  virtual void
245  amrex::Vector<amrex::Real>& u_geos,
246  amrex::Gpu::DeviceVector<amrex::Real>& d_u_geos,
247  amrex::Vector<amrex::Real>& v_geos,
248  amrex::Gpu::DeviceVector<amrex::Real>& d_v_geos,
249  const amrex::Geometry& geom,
250  std::unique_ptr<amrex::MultiFab>& /*z_phys_cc*/)
251  {
252  if (u_geos.empty()) return;
253 
254  amrex::Warning("Geostrophic wind profile not defined for "+name()+" problem");
255 
256  const int khi = geom.Domain().bigEnd()[2];
257  // const amrex::Real* prob_lo = geom.ProbLo();
258  // const auto dx = geom.CellSize();
259  for (int k = 0; k <= khi; k++)
260  {
261  // const amrex::Real z_cc = prob_lo[2] + (k+0.5)* dx[2];
262  // set RHS term of RhoTheta equation based on time, z_cc here
263  u_geos[k] = 0.0;
264  v_geos[k] = 0.0;
265  }
266 
267  // Copy from host version to device version
268  amrex::Gpu::copy(amrex::Gpu::hostToDevice, u_geos.begin(), u_geos.end(), d_u_geos.begin());
269  amrex::Gpu::copy(amrex::Gpu::hostToDevice, v_geos.begin(), v_geos.end(), d_v_geos.begin());
270  }
271 
272  /**
273  * Function to perform custom initialization of buildings
274  *
275  * @param[in] geom container for geometric information
276  * @param[out] z_phys_nd height coordinate at nodes
277  * @param[in] time current time
278  */
279  void
280  init_buildings_surface (const amrex::Geometry& geom,
281  amrex::FArrayBox& buildings_fab,
282  const amrex::Real& time)
283  {
284  // Check if a valid text file exists for the buildings
285  std::string fname;
286  amrex::ParmParse pp("erf");
287  auto valid_fname = pp.query("buildings_file_name",fname);
288 
289  if (valid_fname) {
290  read_custom_terrain(fname,false,geom,buildings_fab,time);
291  } else {
292  init_custom_terrain(geom, buildings_fab, time);
293  }
294  }
295 
296 
297  /**
298  * Function to perform custom initialization of terrain
299  *
300  * @param[in] geom container for geometric information
301  * @param[out] z_phys_nd height coordinate at nodes
302  * @param[in] time current time
303  */
304  void
305  init_terrain_surface (const amrex::Geometry& geom,
306  amrex::FArrayBox& terrain_fab,
307  const amrex::Real& time)
308  {
309  // Check if a valid text file exists for the terrain
310  std::string fname, fname_usgs;
311  amrex::ParmParse pp("erf");
312  auto valid_fname = pp.query("terrain_file_name",fname);
313  auto valid_fname_USGS = pp.query("terrain_file_name_USGS",fname_usgs);
314 
315  bool is_usgs;
316 
317  if (valid_fname) {
318  is_usgs = false;
319  read_custom_terrain(fname,is_usgs,geom,terrain_fab,time);
320 
321  } else if (valid_fname_USGS) {
322  is_usgs = true;
323  read_custom_terrain(fname_usgs,is_usgs,geom,terrain_fab,time);
324 
325  } else {
326  init_custom_terrain (geom, terrain_fab, time);
327  }
328  }
329 
330  void
331  read_custom_terrain(const std::string& fname,
332  const bool is_usgs,
333  const amrex::Geometry& geom,
334  amrex::FArrayBox& terrain_fab,
335  const amrex::Real& /*time*/)
336  {
337  amrex::Vector<amrex::Real> m_xterrain,m_yterrain,m_zterrain;
338 
339  int nx = 0; int ny = 0;
340 
341  if (amrex::ParallelDescriptor::IOProcessor()) {
342  // Read terrain file
343  amrex::Print()<<"Reading terrain file: "<< fname<< std::endl;
344  std::ifstream file(fname);
345 
346  if (!file.is_open()) {
347  amrex::Abort("Error: Could not open the file " + fname+ "\n");
348  }
349 
350  // Check if file is empty
351  if (file.peek() == std::ifstream::traits_type::eof()) {
352  amrex::Abort("Error: The file " + fname+ " is empty.\n");
353  }
354 
355  amrex::Real value1,value2,value3;
356 
357  if (is_usgs) {
358  amrex::Real lat_min, lon_min;
359 
360  file >> lon_min >> lat_min;
361  if(std::fabs(lon_min) > 180.0) {
362  amrex::Error("The value of longitude for entry in the first line in " + fname
363  + " should not exceed 180. It is " + std::to_string(lon_min));
364  }
365  if(std::fabs(lat_min) > 90.0) {
366  amrex::Error("The value of latitude for entry in the first line in " + fname
367  + " should not exceed 90. It is " + std::to_string(lat_min));
368  }
369 
370  file >> nx >> ny;
371 
372  int counter = 0;
373  while (file >> value1 >> value2 >> value3) {
374  m_xterrain.push_back(value1);
375  if(counter%nx==0) {
376  m_yterrain.push_back(value2);
377  }
378  m_zterrain.push_back(value3);
379  counter += 1;
380  }
381  AMREX_ASSERT(m_xterrain.size() == static_cast<long int>(nx*ny));
382  AMREX_ASSERT(m_yterrain.size() == static_cast<long int>(ny));
383  AMREX_ASSERT(m_zterrain.size() == static_cast<long int>(nx*ny));
384 
385  } else {
386  int cnt = 1;
387  nx = erf_get_single_value<int>(file,cnt); cnt++;
388  ny = erf_get_single_value<int>(file,cnt); cnt++;
389  amrex::Print()<<"Expecting " << nx << " values of x, " <<
390  ny << " values of y, and " <<
391  nx*ny << " values of z" << std::endl;
392  AMREX_ALWAYS_ASSERT(nx > 0);
393  AMREX_ALWAYS_ASSERT(ny > 0);
394  m_xterrain.resize(nx);
395  m_yterrain.resize(ny);
396  m_zterrain.resize(nx * ny);
397  for (int n = 0; n < nx; n++) {
398  m_xterrain[n] = erf_get_single_value<amrex::Real>(file,cnt);
399  cnt++;
400  }
401  for (int n = 0; n < ny; n++) {
402  m_yterrain[n] = erf_get_single_value<amrex::Real>(file,cnt);
403  cnt++;
404  }
405  for (int n = 0; n < nx * ny; n++) {
406  m_zterrain[n] = erf_get_single_value<amrex::Real>(file,cnt);
407  cnt++;
408  }
409  }
410 
411  // Close the file after reading
412  file.close();
413  }
414 
415  amrex::ParallelDescriptor::Bcast(&nx,1,amrex::ParallelDescriptor::IOProcessorNumber());
416  amrex::ParallelDescriptor::Bcast(&ny,1,amrex::ParallelDescriptor::IOProcessorNumber());
417 
418  int nz = nx * ny;
419 
420  m_xterrain.resize(nx);
421  m_yterrain.resize(ny);
422  m_zterrain.resize(nz);
423 
424  amrex::ParallelDescriptor::Bcast(m_xterrain.data(),nx,amrex::ParallelDescriptor::IOProcessorNumber());
425  amrex::ParallelDescriptor::Bcast(m_yterrain.data(),ny,amrex::ParallelDescriptor::IOProcessorNumber());
426  amrex::ParallelDescriptor::Bcast(m_zterrain.data(),nz,amrex::ParallelDescriptor::IOProcessorNumber());
427 
428  // Copy data to the GPU
429  amrex::Gpu::DeviceVector<amrex::Real> d_xterrain(nx),d_yterrain(ny),d_zterrain(nz);
430  amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_xterrain.begin(), m_xterrain.end(), d_xterrain.begin());
431  amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_yterrain.begin(), m_yterrain.end(), d_yterrain.begin());
432  amrex::Gpu::copy(amrex::Gpu::hostToDevice, m_zterrain.begin(), m_zterrain.end(), d_zterrain.begin());
433 
434  amrex::Real* d_xt = d_xterrain.data();
435  amrex::Real* d_yt = d_yterrain.data();
436  amrex::Real* d_zt = d_zterrain.data();
437 
438  auto dx = geom.CellSizeArray();
439  auto ProbLoArr = geom.ProbLoArray();
440 
441  int ilo = geom.Domain().smallEnd(0);
442  int jlo = geom.Domain().smallEnd(1);
443  int klo = geom.Domain().smallEnd(2);
444  int ihi = geom.Domain().bigEnd(0) + 1;
445  int jhi = geom.Domain().bigEnd(1) + 1;
446 
447  amrex::Box zbx = terrain_fab.box();
448  amrex::Array4<amrex::Real> const& z_arr = terrain_fab.array();
449 
450  amrex::ParallelFor(zbx, [=] AMREX_GPU_DEVICE (int i, int j, int /*k*/)
451  {
452  // Clip indices for ghost cells
453  int ii = amrex::min(amrex::max(i,ilo),ihi);
454  int jj = amrex::min(amrex::max(j,jlo),jhi);
455 
456  // Location of nodes
457  amrex::Real x = ProbLoArr[0] + ii * dx[0] + 1e-3;
458  amrex::Real y = ProbLoArr[1] + jj * dx[1] + 1e-3;
459 
460  int ind11, ind12, ind21, ind22;
461  amrex::Real x1, x2, y1, y2;
462 
463  int iindex_terrain=-1;
464  int jindex_terrain=-1;
465  // *******************************************************************
466  // NOTE: usgs-format is contiguous in x
467  // *******************************************************************
468  if (is_usgs) {
469 
470  for (int it = 0; it < ny && jindex_terrain == -1; it++) {
471  if (d_yt[it] > y) {
472  jindex_terrain = it-1;
473  }
474  }
475  if (jindex_terrain == -1) {
476  jindex_terrain = ny-1;
477  }
478 
479  int gstart = (jindex_terrain )*nx;
480  int gend = (jindex_terrain+1)*nx-1;
481  for (int it = gstart; it <= gend && iindex_terrain == -1; it++) {
482  if (d_xt[it] > x) {
483  iindex_terrain = it-gstart;
484  }
485  }
486 
487  // Define the four values to interpolate between
488  ind11 = jindex_terrain*nx + iindex_terrain; // (x1,y1)
489  ind12 = ind11+nx; // (x1,y2)
490  ind21 = ind11+1; // (x2,y1)
491  ind22 = ind12+1; // (x2,y2)
492 
493  x1 = d_xt[ind11];
494  x2 = d_xt[ind21];
495  y1 = d_yt[jindex_terrain];
496  y2 = d_yt[jindex_terrain+1];
497 
498  amrex::Real denom = (x2-x1)*(y2-y1);
499  amrex::Real w_11 = (x2-x)*(y2-y)/denom; // (x1,y1)
500  amrex::Real w_12 = (x2-x)*(y-y1)/denom; // (x1,y2)
501  amrex::Real w_21 = (x-x1)*(y2-y)/denom; // (x2,y1)
502  amrex::Real w_22 = (x-x1)*(y-y1)/denom; // (x2,y2)
503 
504  // Do bilinear interpolation
505  z_arr(i,j,klo) = w_11*d_zt[ind11] + w_12*d_zt[ind12] + w_21*d_zt[ind21] + w_22*d_zt[ind22];
506 
507  } else {
508 
509  for (int it = 0; it < ny && jindex_terrain == -1; it++) {
510  if (d_yt[it] > y) {
511  jindex_terrain = it-1;
512  }
513  }
514  if (jindex_terrain == -1) {
515  jindex_terrain = ny-1;
516  }
517 
518  for (int it = 0; it < nx && iindex_terrain == -1; it++) {
519  if (d_xt[it] > x) {
520  iindex_terrain = it-1;
521  }
522  }
523  if (iindex_terrain == -1) {
524  iindex_terrain = nx-1;
525  }
526 
527  // Define the four values to interpolate between
528  x1 = d_xt[iindex_terrain];
529  x2 = d_xt[iindex_terrain+1];
530  y1 = d_yt[jindex_terrain];
531  y2 = d_yt[jindex_terrain+1];
532 
533 #if 1
534  // *******************************************************************
535  // NOTE: this format is contiguous in y to match the AMR-Wind read
536  // *******************************************************************
537  ind11 = iindex_terrain * ny + jindex_terrain; // (x1,y1)
538  ind21 = std::min(iindex_terrain+1,nx-1) * ny + jindex_terrain; // (x2,y1)
539 
540  ind12 = iindex_terrain * ny + std::min(jindex_terrain+1,ny-1); // (x1,y2)
541  ind22 = std::min(iindex_terrain+1,nx-1) * ny + std::min(jindex_terrain+1,ny-1); // (x1,y2)
542 #else
543  // *******************************************************************
544  // NOTE: this format is contiguous in x as an alternative
545  // *******************************************************************
546 
547  ind11 = jindex_terrain * nx + iindex_terrain; // (x1,y1)
548  ind12 = std::min(jindex_terrain+1,ny-1) * nx + iindex_terrain; // (x1,y2)
549 
550  ind21 = jindex_terrain * nx + std::min(iindex_terrain+1,nx-1); // (x2,y1)
551  ind22 = std::min(jindex_terrain+1,ny-1) * nx + std::min(iindex_terrain+1,nx-1); // (x2,y2)
552 #endif
553 
554  if (iindex_terrain == nx-1 && jindex_terrain == ny-1)
555  {
556  z_arr(i,j,klo) = d_zt[ind11];
557  }
558  else if (iindex_terrain != nx-1 && jindex_terrain == ny-1)
559  {
560  amrex::Real w_11 = (x2-x); // (x1,y1)
561  amrex::Real w_21 = (x-x1); // (x2,y1)
562  amrex::Real denom = (x2-x1);
563  z_arr(i,j,klo) = (w_11*d_zt[ind11] + w_21*d_zt[ind21])/denom;
564  }
565  else if (iindex_terrain == nx-1 && jindex_terrain != ny-1)
566  {
567  amrex::Real w_11 = (y2-y); // (x1,y1)
568  amrex::Real w_12 = (y-y1); // (x1,y2)
569  amrex::Real denom = (y2-y1);
570  z_arr(i,j,klo) = (w_11*d_zt[ind11] + w_12*d_zt[ind12])/denom;
571  }
572  else
573  {
574  amrex::Real w_11 = (x2-x)*(y2-y); // (x1,y1)
575  amrex::Real w_21 = (x-x1)*(y2-y); // (x2,y1)
576  amrex::Real w_12 = (x2-x)*(y-y1); // (x1,y2)
577  amrex::Real w_22 = (x-x1)*(y-y1); // (x2,y2)
578  amrex::Real denom = (x2-x1)*(y2-y1);
579  z_arr(i,j,klo) = (w_11*d_zt[ind11] + w_12*d_zt[ind12] + w_21*d_zt[ind21] + w_22*d_zt[ind22]) / denom;
580  }
581  } // usgs?
582  });
583  }
584 
585  /**
586  * Function to perform custom initialization of terrain
587  *
588  * Note: Terrain functionality can also be used to provide grid stretching.
589  *
590  * @param[in] geom container for geometric information
591  * @param[out] terrain_mf height coordinate at nodes
592  * @param[in] time current time
593  */
594  virtual void
595  init_custom_terrain (const amrex::Geometry& /*geom*/,
596  amrex::FArrayBox& terrain_fab,
597  const amrex::Real& /*time*/)
598  {
599  amrex::Print() << "Initializing flat terrain" << std::endl;
600 
601  if (SolverChoice::mesh_type == MeshType::VariableDz) {
602  SolverChoice::set_mesh_type(MeshType::StretchedDz);
603  amrex::Print() << "Resetting mesh type to StretchedDz" << std::endl;
604  }
605 
606  terrain_fab.template setVal<amrex::RunOn::Device>(0.0);
607  }
608 
609 #ifdef ERF_USE_TERRAIN_VELOCITY
610  virtual amrex::Real compute_terrain_velocity(const amrex::Real /*time*/)
611  {
612  amrex::Error("Should never call compute_terrain_velocity for "+name()+" problem");
613  }
614 #endif
615 
616  /**
617  * Function to define the quantities needed to impose Rayleigh damping
618  *
619  * @param[out] rayleigh_ptrs = {strength of Rayleigh damping, reference values for xvel/yvel/zvel/theta used to define Rayleigh damping}
620  * @param[in] geom container for geometric information
621  * @param[in] z_phys_cc height coordinate at cell centers
622  */
623  virtual void
624  erf_init_rayleigh (amrex::Vector<amrex::Vector<amrex::Real> >& /*rayleigh_ptrs*/,
625  amrex::Geometry const& /*geom*/,
626  std::unique_ptr<amrex::MultiFab>& /*z_phys_nd*/,
627  amrex::Real /*zdamp*/)
628  {
629  amrex::Error("Should never call erf_init_rayleigh for "+name()+" problem");
630  }
631 
632  /**
633  * Function to set uniform background density and potential temperature fields
634  */
635  void
636  init_uniform (const amrex::Box& bx, amrex::Array4<amrex::Real> const& state)
637  {
638  amrex::Real rho_0 = base_parms.rho_0;
639  amrex::Real T_0 = base_parms.T_0;
640  amrex::Print() << "Initializing uniform fields"
641  << " rho=" << rho_0 << " theta=" << T_0
642  << std::endl;
643 
644  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
645  {
646  state(i, j, k, Rho_comp) = rho_0;
647  state(i, j, k, RhoTheta_comp) = rho_0 * T_0;
648  });
649  }
650 
651 protected:
652  // Struct to store problem parameters
654 
655  /**
656  * Function to update default base parameters, currently only used for
657  * init_type == InitType::Uniform
658  */
660  base_parms.rho_0 = rho_0;
661  base_parms.T_0 = T_0;
662  }
663 
664  // descriptor for problem definition
665  virtual std::string name () = 0;
666 };
667 
668 
669 /**
670  * Function to init the physical bounds of the domain
671  * and instantiate a Problem derived from ProblemBase
672 */
673 extern std::unique_ptr<ProblemBase> amrex_probinit (const amrex_real* problo,
674  const amrex_real* probhi) AMREX_ATTRIBUTE_WEAK;
675 #endif
@ wbar
Definition: ERF_DataStruct.H:96
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:233
T erf_get_single_value(std::istream &is, int n)
Definition: ERF_ProbCommon.H:20
std::unique_ptr< ProblemBase > amrex_probinit(const amrex_real *problo, const amrex_real *probhi) AMREX_ATTRIBUTE_WEAK
const Box zbx
Definition: ERF_SetupDiff.H:9
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_ProbCommon.H:44
virtual std::string name()=0
void init_uniform(const amrex::Box &bx, amrex::Array4< amrex::Real > const &state)
Definition: ERF_ProbCommon.H:636
void init_terrain_surface(const amrex::Geometry &geom, amrex::FArrayBox &terrain_fab, const amrex::Real &time)
Definition: ERF_ProbCommon.H:305
void read_custom_terrain(const std::string &fname, const bool is_usgs, const amrex::Geometry &geom, amrex::FArrayBox &terrain_fab, const amrex::Real &)
Definition: ERF_ProbCommon.H:331
void init_buildings_surface(const amrex::Geometry &geom, amrex::FArrayBox &buildings_fab, const amrex::Real &time)
Definition: ERF_ProbCommon.H:280
virtual void update_w_subsidence(const amrex::Real &, amrex::Vector< amrex::Real > &wbar, amrex::Gpu::DeviceVector< amrex::Real > &d_wbar, const amrex::Geometry &geom, std::unique_ptr< amrex::MultiFab > &)
Definition: ERF_ProbCommon.H:210
virtual void erf_init_rayleigh(amrex::Vector< amrex::Vector< amrex::Real > > &, amrex::Geometry const &, std::unique_ptr< amrex::MultiFab > &, amrex::Real)
Definition: ERF_ProbCommon.H:624
void init_base_parms(amrex::Real rho_0, amrex::Real T_0)
Definition: ERF_ProbCommon.H:659
virtual void update_rhotheta_sources(const amrex::Real &, amrex::Vector< amrex::Real > &src, amrex::Gpu::DeviceVector< amrex::Real > &d_src, const amrex::Geometry &geom, std::unique_ptr< amrex::MultiFab > &)
Definition: ERF_ProbCommon.H:139
virtual void init_custom_terrain(const amrex::Geometry &, amrex::FArrayBox &terrain_fab, const amrex::Real &)
Definition: ERF_ProbCommon.H:595
virtual ~ProblemBase()=default
virtual void erf_init_dens_hse_moist(amrex::MultiFab &, std::unique_ptr< amrex::MultiFab > &, amrex::Geometry const &)
Definition: ERF_ProbCommon.H:74
ProbParmDefaults base_parms
Definition: ERF_ProbCommon.H:653
virtual void init_custom_pert(const amrex::Box &, const amrex::Box &, const amrex::Box &, const amrex::Box &, amrex::Array4< amrex::Real const > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real > const &, amrex::Array4< amrex::Real const > const &, amrex::Array4< amrex::Real const > const &, amrex::GeometryData const &, amrex::Array4< amrex::Real const > const &, amrex::Array4< amrex::Real const > const &, amrex::Array4< amrex::Real const > const &, const SolverChoice &, const int)
Definition: ERF_ProbCommon.H:105
virtual void erf_init_dens_hse(amrex::MultiFab &, std::unique_ptr< amrex::MultiFab > &, std::unique_ptr< amrex::MultiFab > &, amrex::Geometry const &)
Definition: ERF_ProbCommon.H:61
virtual void update_geostrophic_profile(const amrex::Real &, amrex::Vector< amrex::Real > &u_geos, amrex::Gpu::DeviceVector< amrex::Real > &d_u_geos, amrex::Vector< amrex::Real > &v_geos, amrex::Gpu::DeviceVector< amrex::Real > &d_v_geos, const amrex::Geometry &geom, std::unique_ptr< amrex::MultiFab > &)
Definition: ERF_ProbCommon.H:244
virtual void update_rhoqt_sources(const amrex::Real &, amrex::Vector< amrex::Real > &qsrc, amrex::Gpu::DeviceVector< amrex::Real > &d_qsrc, const amrex::Geometry &geom, std::unique_ptr< amrex::MultiFab > &)
Definition: ERF_ProbCommon.H:173
@ T
Definition: ERF_IndexDefines.H:110
Definition: ERF_ProbCommon.H:14
amrex::Real T_0
Definition: ERF_ProbCommon.H:16
amrex::Real rho_0
Definition: ERF_ProbCommon.H:15
Definition: ERF_DataStruct.H:128
static MeshType mesh_type
Definition: ERF_DataStruct.H:983
static void set_mesh_type(MeshType new_mesh_type)
Definition: ERF_DataStruct.H:986