ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_InputSoundingData.H
Go to the documentation of this file.
1 #ifndef ERF_INPUT_SOUNDING_DATA_H_
2 #define ERF_INPUT_SOUNDING_DATA_H_
3 
4 #include <string>
5 #include <iostream>
6 
7 #include <AMReX_ParmParse.H>
8 #include <AMReX_Print.H>
9 #include <AMReX_Gpu.H>
10 #include <AMReX_Geometry.H>
11 
12 #include <ERF_EOS.H>
13 #include <ERF_Constants.H>
14 #include <ERF_Interpolation_1D.H>
15 #include <ERF_HSEUtils.H>
16 
17 /**
18  * Data structure storing input sounding data. Also
19  * handles reading the input file for sounding data and
20  * hydrostatic column integration.
21  */
23 public:
24  /**
25  * @brief Construct input sounding metadata from the ERF input namespace.
26  */
28  {
29  amrex::ParmParse pp("erf");
30  pp.query("tau_nudging", tau_nudging);
31 
32  // Read in input_sounding filename
33  n_sounding_files = pp.countval("input_sounding_file");
34  if (n_sounding_files > 0) {
36  pp.queryarr("input_sounding_file", input_sounding_file, 0, n_sounding_files);
37  } else {
38  n_sounding_files = 1;
40  input_sounding_file[0] = "input_sounding";
41  }
42 
43  // Read in input_sounding times
44  n_sounding_times = pp.countval("input_sounding_time");
45 
46  if (n_sounding_times > 0) {
48  pp.queryarr("input_sounding_time", input_sounding_time, 0, n_sounding_times);
49  } else {
50  n_sounding_times = 1;
53  }
54 
55  // If we have more files than times or times than files we just use the minimum
56  int n = std::min(n_sounding_times, n_sounding_files);
57  n_sounding_files = n;
58  n_sounding_times = n;
59  input_sounding_file.resize(n);
60  input_sounding_time.resize(n);
61  }
62 
63  /**
64  * @brief Resize host and device sounding arrays for the configured sounding times.
65  */
66  void resize_arrays ()
67  {
69 
70  z_inp_sound.resize(ntimes);
71  theta_inp_sound.resize(ntimes);
72  qv_inp_sound.resize(ntimes);
73  U_inp_sound.resize(ntimes);
74  V_inp_sound.resize(ntimes);
75 
76  z_inp_sound_d.resize(ntimes);
77  theta_inp_sound_d.resize(ntimes);
78  qv_inp_sound_d.resize(ntimes);
79  U_inp_sound_d.resize(ntimes);
80  V_inp_sound_d.resize(ntimes);
81  }
82 
83  /**
84  * @brief Read and interpolate one input sounding profile onto level-0 heights.
85  * @param geom Geometry defining the level-0 vertical domain.
86  * @param zlevels_stag Staggered vertical coordinates used for interpolation.
87  * @param itime Sounding time/file index to read.
88  * @param is_moist Whether the selected physics permits nonzero water vapor.
89  */
90  void read_from_file (const amrex::Geometry &geom,
91  const amrex::Vector<amrex::Real>& zlevels_stag,
92  int itime, bool is_moist)
93  {
94  const int klo = 0;
95  const int khi = geom.Domain().bigEnd()[AMREX_SPACEDIM-1];
96  const int Nz = geom.Domain().size()[AMREX_SPACEDIM-1];
97 
98  const amrex::Real zbot = zlevels_stag[klo];
99  const amrex::Real ztop = zlevels_stag[khi+1];
100 
101  z_inp_sound[itime].resize(Nz+2);
102  theta_inp_sound[itime].resize(Nz+2);
103  qv_inp_sound[itime].resize(Nz+2);
104  U_inp_sound[itime].resize(Nz+2);
105  V_inp_sound[itime].resize(Nz+2);
106 
107  // Read the input_sounding file
108  amrex::Print() << "input_sounding file location : " << input_sounding_file[itime] << std::endl;
109  std::ifstream input_sounding_reader(input_sounding_file[itime]);
110  if(!input_sounding_reader.is_open()) {
111  amrex::Error("Error opening the input_sounding file\n");
112  }
113  else {
114  // Read the contents of the input_sounding file
115  amrex::Print() << "Successfully opened the input_sounding file. Now reading... " << std::endl;
116  std::string line;
117 
118  // First, read the input data into temp vectors; then, interpolate vectors to the
119  // domain lo/hi and cell centers (from level 0)
120  amrex::Vector<amrex::Real> z_inp_sound_tmp, theta_inp_sound_tmp, qv_inp_sound_tmp,
121  U_inp_sound_tmp, V_inp_sound_tmp;
122 
123  // Read surface quantities from the first line
124  std::getline(input_sounding_reader, line);
125  std::istringstream iss(line);
127  press_ref_inp_sound *= 100; // convert from hPa to Pa
128  qv_ref_inp_sound *= amrex::Real(0.001); // convert from g/kg to kg/kg
129 
130  // Add surface
131  z_inp_sound_tmp.push_back(zbot); // height above sea level [m]
132  theta_inp_sound_tmp.push_back(theta_ref_inp_sound);
133  qv_inp_sound_tmp.push_back(qv_ref_inp_sound);
134  U_inp_sound_tmp.push_back(0);
135  V_inp_sound_tmp.push_back(0);
136 
137  // *************************************************************************************************
138  // Make sure that if we specify surface values for temp in the inputs file and in the input sounding file,
139  // those values must match
140  // *************************************************************************************************
141  amrex::ParmParse pp_erf("erf");
142 
143  amrex::Real surf_temp;
144  bool surf_temp_specified = pp_erf.query("most.surf_temp", surf_temp);
145  if ( surf_temp_specified && (surf_temp != theta_inp_sound_tmp[0]) ) {
146  amrex::Print() << "Input sounding temp does not match most.surf_temp" << std::endl;
147  amrex::Print() << "Modify one or both to match." << std::endl;
148  amrex::Abort();
149  }
150 
151  // *************************************************************************************************
152  // Make sure that if we specify surface values for qv in the inputs file and in the input sounding file,
153  // those values must match
154  // *************************************************************************************************
155  amrex::Real surf_moist;
156  bool surf_moist_specified = pp_erf.query("most.surf_moist", surf_moist);
157  if ( surf_moist_specified && (surf_moist != qv_inp_sound_tmp[0]) ) {
158  amrex::Print() << "Input sounding qv does not match most.surf_moist" << std::endl;
159  amrex::Print() << "Modify one or both to match." << std::endl;
160  amrex::Abort();
161  }
162 
163  // Read the vertical profile at each given height
164  amrex::Real z, theta, qv, U, V;
165 
166  while(std::getline(input_sounding_reader, line)) {
167  std::istringstream iss_z(line);
168  iss_z >> z >> theta >> qv >> U >> V;
169 
170  // Dont read in non-zero qv if not using a moisture model
171  AMREX_ALWAYS_ASSERT(qv == zero || is_moist);
172 
173  if (z == zbot) {
174  AMREX_ALWAYS_ASSERT(theta == theta_inp_sound_tmp[0]);
175  AMREX_ALWAYS_ASSERT(qv*amrex::Real(0.001) == qv_inp_sound_tmp[0]); // convert from g/kg to kg/kg
176  U_inp_sound_tmp[0] = U;
177  V_inp_sound_tmp[0] = V;
178  } else {
179  AMREX_ALWAYS_ASSERT(z > z_inp_sound_tmp[z_inp_sound_tmp.size()-1]); // sounding is increasing in height
180  z_inp_sound_tmp.push_back(z);
181 
182  theta_inp_sound_tmp.push_back(theta);
183  qv_inp_sound_tmp.push_back(qv*amrex::Real(0.001)); // convert from g/kg to kg/kg
184  U_inp_sound_tmp.push_back(U);
185  V_inp_sound_tmp.push_back(V);
186  if (z >= ztop) break;
187  }
188  }
189 
190  // At this point, we have an input_sounding from zbot up to
191  // z_inp_sound_tmp[N-1] >= ztop. Now, interpolate to grid level 0 heights
192  const int Ninp = z_inp_sound_tmp.size();
193  z_inp_sound[itime][0] = zbot;
194  theta_inp_sound[itime][0] = theta_inp_sound_tmp[0];
195  qv_inp_sound[itime][0] = qv_inp_sound_tmp[0];
196  U_inp_sound[itime][0] = U_inp_sound_tmp[0];
197  V_inp_sound[itime][0] = V_inp_sound_tmp[0];
198  for (int k=0; k < Nz; ++k) {
199  z_inp_sound[itime][k+1] = myhalf * (zlevels_stag[k] + zlevels_stag[k+1]);
200  theta_inp_sound[itime][k+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), theta_inp_sound_tmp.dataPtr(), z_inp_sound[itime][k+1], Ninp);
201  qv_inp_sound[itime][k+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), qv_inp_sound_tmp.dataPtr(), z_inp_sound[itime][k+1], Ninp);
202  U_inp_sound[itime][k+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), U_inp_sound_tmp.dataPtr(), z_inp_sound[itime][k+1], Ninp);
203  V_inp_sound[itime][k+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), V_inp_sound_tmp.dataPtr(), z_inp_sound[itime][k+1], Ninp);
204  }
205  z_inp_sound[itime][Nz+1] = ztop;
206  theta_inp_sound[itime][Nz+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), theta_inp_sound_tmp.dataPtr(), ztop, Ninp);
207  qv_inp_sound[itime][Nz+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), qv_inp_sound_tmp.dataPtr(), ztop, Ninp);
208  U_inp_sound[itime][Nz+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), U_inp_sound_tmp.dataPtr(), ztop, Ninp);
209  V_inp_sound[itime][Nz+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), V_inp_sound_tmp.dataPtr(), ztop, Ninp);
210  }
211 
212  amrex::Print() << "Successfully read the " << itime << "th input_sounding file..." << std::endl;
213  input_sounding_reader.close();
214 
215  host_to_device(itime);
216  }
217 
218  /**
219  * @brief Hydrostatically integrate density and pressure for one sounding.
220  * @param itime Sounding time/file index to integrate.
221  */
222  void calc_rho_p (int itime)
223  {
224  /* Calculate density and pressure, roughly following the procedure in
225  * WRF dyn_em/module_initialize_ideal.F. We integrate hydrostatically
226  * from the surface up through the air column to get the dry density
227  * and moist pressure.
228  */
229  const amrex::Real tol = amrex::Real(1.0e-12);
230  const int Ninp = size(itime);
231  pm_integ.resize(Ninp);
232  rhod_integ.resize(Ninp);
233 
234  // evaluate surface quantities (k=0): total pressure and dry air
238  RdoCp,
240 
241  amrex::Print() << "ideal sounding init: surface dry air density = "
242  << std::setprecision(15)
243  << rhod_integ[0] << " kg/m^3" << std::endl;
244 
245  // Note:
246  // p_dry = rho_d R_d T
247  // p_tot = rho_m R_d T_v
248  // = rho_d(1 + q_v) R_d T_v
249 
250 #if 0 // Printing
251  // In this absence of moisture, this moist profile will match the
252  // following dry profile
253  amrex::Print() << "z p_m rho_d theta qv U V" << std::endl;
254  amrex::Print() << z_inp_sound[itime][0]
255  << " " << pm_integ[0]
256  << " " << rhod_integ[0]
257  << " " << theta_inp_sound[itime][0]
258  << " " << qv_inp_sound[itime][0]
259  << " " << U_inp_sound[itime][0]
260  << " " << V_inp_sound[itime][0]
261  << std::endl;
262 #endif
263 
264  // integrate from surface to domain top
265  amrex::Real dz, F, C;
266  amrex::Real T_hi;
267  amrex::Real rho_tot_hi, rho_tot_lo;
268  for (int k=1; k < size(itime); ++k)
269  {
270  // Vertical grid spacing
271  dz = z_inp_sound[itime][k] - z_inp_sound[itime][k-1];
272 
273  // Establish known constant
274  rho_tot_lo = rhod_integ[k-1] * (one + qv_inp_sound[itime][k-1]);
275  C = -pm_integ[k-1] + myhalf*rho_tot_lo*CONST_GRAV*dz;
276 
277  // Initial guess and residual
278  pm_integ[k] = pm_integ[k-1];
279  T_hi = getTgivenPandTh(pm_integ[k], theta_inp_sound[itime][k], RdoCp);
281  pm_integ[k],
282  RdoCp,
283  qv_inp_sound[itime][k]);
284  rho_tot_hi = rhod_integ[k] * (one + qv_inp_sound[itime][k]);
285  F = pm_integ[k] + myhalf*rho_tot_hi*CONST_GRAV*dz + C;
286 
287  // Do iterations
288  if (std::abs(F)>tol) {
289  bool maintain_Th = true;
291  CONST_GRAV, C, theta_inp_sound[itime][k], T_hi,
292  qv_inp_sound[itime][k], qv_inp_sound[itime][k],
293  pm_integ[k], rhod_integ[k], F, maintain_Th);
294  }
295 
296 #if 0 // Printing
297  amrex::Print() << z_inp_sound[itime][k]
298  << " " << pm_integ[k]
299  << " " << rhod_integ[k]
300  << " " << theta_inp_sound[itime][k]
301  << " " << qv_inp_sound[itime][k]
302  << " " << U_inp_sound[itime][k]
303  << " " << V_inp_sound[itime][k]
304  << std::endl;
305 #endif
306  }
307  // Note: at this point, the surface pressure, density of the dry air
308  // column is stored in pm_integ[0], rhod_integ[0]
309 
310  // update
311  host_to_device(itime);
312  }
313 
314  /**
315  * @brief Compute density and pressure for an isentropic sounding profile.
316  * @param itime Sounding time/file index to integrate.
317  */
318  void calc_rho_p_isentropic (int itime)
319  {
320  /* Calculate density and pressure assuming isentropic (constant theta)
321  background conditions. This does not use Newton-Raphson iterations
322  to calculate rho and p.
323  */
324  const int Ninp = size(itime);
325  pm_integ.resize(Ninp);
326  rhod_integ.resize(Ninp);
327 
328  // evaluate surface quantities (k=0): total pressure and dry air
332  RdoCp,
334 
335  const amrex::Real th0 = theta_ref_inp_sound;
336  const amrex::Real p0_pow = std::pow(p_0, (Gamma-1)/Gamma);
337 
338  amrex::Print() << "isentropic sounding init: surface dry air density = "
339  << std::setprecision(15)
340  << rhod_integ[0] << " kg/m^3" << std::endl;
341 
342 #if 0 // Printing
343  // In this absence of moisture, this moist profile will match the
344  // following dry profile
345  amrex::Print() << "z p_m rho_d theta qv U V" << std::endl;
346  amrex::Print() << z_inp_sound[itime][0]
347  << " " << pm_integ[0]
348  << " " << rhod_integ[0]
349  << " " << theta_inp_sound[itime][0]
350  << " " << qv_inp_sound[itime][0]
351  << " " << U_inp_sound[itime][0]
352  << " " << V_inp_sound[itime][0]
353  << std::endl;
354 #endif
355 
356  // integrate from surface to domain top
357  amrex::Real dz;
358  for (int k=1; k < size(itime); ++k)
359  {
360  // Vertical grid spacing
361  dz = z_inp_sound[itime][k] - z_inp_sound[itime][k-1];
362 
363  // Isentropic pressure at next level
364  amrex::Real qvmean = (assume_dry) ? zero : myhalf*(qv_inp_sound[itime][k-1] + qv_inp_sound[itime][k]);
365  amrex::Real thm0 = th0 * (one + RvoRd * qvmean);
366  amrex::Real plo_pow = std::pow(pm_integ[k-1], (Gamma-1)/Gamma);
367  pm_integ[k] = (Gamma-1)/Gamma *
368  (-CONST_GRAV * p0_pow / (R_d * thm0) * (1 + qvmean) * dz
369  + Gamma/(Gamma-1) * plo_pow);
370  pm_integ[k] = std::pow(pm_integ[k], Gamma / (Gamma-1));
371 
372  // Note: The pressure calculated here is copied to `p_inp_sound_d`
373  // and currently not used.
374 
375  // Get corresponding dry air density
377  pm_integ[k],
378  RdoCp,
379  qv_inp_sound[itime][k]);
380 
381 #if 0 // Printing
382  amrex::Print() << z_inp_sound[itime][k]
383  << " " << pm_integ[k]
384  << " " << rhod_integ[k]
385  << " " << theta_inp_sound[itime][k]
386  << " " << qv_inp_sound[itime][k]
387  << " " << U_inp_sound[itime][k]
388  << " " << V_inp_sound[itime][k]
389  << std::endl;
390 #endif
391  }
392  // Note: at this point, the surface pressure, density of the dry air
393  // column is stored in pm_integ[0], rhod_integ[0]
394 
395  // update
396  host_to_device(itime);
397  }
398 
399  /**
400  * @brief Copy host sounding arrays for one time index to device storage.
401  * @param itime Sounding time/file index to copy.
402  */
403  void host_to_device (int itime)
404  {
405  const int Ninp = size(itime);
406  z_inp_sound_d[itime].resize(Ninp);
407  theta_inp_sound_d[itime].resize(Ninp);
408  qv_inp_sound_d[itime].resize(Ninp);
409  U_inp_sound_d[itime].resize(Ninp);
410  V_inp_sound_d[itime].resize(Ninp);
411 
412  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
413  z_inp_sound[itime].begin(), z_inp_sound[itime].end(),
414  z_inp_sound_d[itime].begin());
415  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
416  theta_inp_sound[itime].begin(), theta_inp_sound[itime].end(),
417  theta_inp_sound_d[itime].begin());
418  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
419  qv_inp_sound[itime].begin(), qv_inp_sound[itime].end(),
420  qv_inp_sound_d[itime].begin());
421  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
422  U_inp_sound[itime].begin(), U_inp_sound[itime].end(),
423  U_inp_sound_d[itime].begin());
424  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
425  V_inp_sound[itime].begin(), V_inp_sound[itime].end(),
426  V_inp_sound_d[itime].begin());
427 
428  if (rhod_integ.size() > 0)
429  {
430  //amrex::Print() << "Copying rho_d, p_d to device" << std::endl;
431  rho_inp_sound_d.resize(size(itime)+2);
432  p_inp_sound_d.resize(size(itime)+2);
433  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
434  rhod_integ.begin(), rhod_integ.end(),
435  rho_inp_sound_d.begin());
436  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
437  pm_integ.begin(), pm_integ.end(),
438  p_inp_sound_d.begin());
439  }
440  }
441 
442  /**
443  * @brief Return the number of interpolated samples for one sounding time.
444  * @param itime Sounding time/file index to query.
445  * @return Number of stored sounding profile levels.
446  */
447  int size (int itime) const
448  {
450  AMREX_ALWAYS_ASSERT(z_inp_sound[itime].size() == qv_inp_sound[itime].size());
451  AMREX_ALWAYS_ASSERT(z_inp_sound[itime].size() == U_inp_sound[itime].size());
452  AMREX_ALWAYS_ASSERT(z_inp_sound[itime].size() == V_inp_sound[itime].size());
453  return z_inp_sound[itime].size();
454  }
455 
456  // Members
457  int ntimes;
458 
459  amrex::Real tau_nudging = amrex::Real(5.0); // time scale used for nudging
460 
461  amrex::Vector<std::string> input_sounding_file = {};
462  amrex::Vector<amrex::Real> input_sounding_time = {};
465 
466  bool assume_dry{false};
467 
468  // - read from file
470 
471  // This is a vector (over time) of Vectors
472  amrex::Vector<amrex::Vector<amrex::Real>> z_inp_sound, theta_inp_sound, qv_inp_sound, U_inp_sound, V_inp_sound;
473 
474  // This is a vector (over time) of DeviceVectors
475  amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real>> z_inp_sound_d, theta_inp_sound_d, qv_inp_sound_d, U_inp_sound_d, V_inp_sound_d;
476 
477  // - moist profiles
478  amrex::Vector<amrex::Real> pm_integ; // from integrating up air column
479  // - dry profiles
480  amrex::Vector<amrex::Real> rhod_integ; // from integrating down air column
481  // - to set solution fields
482  amrex::Gpu::DeviceVector<amrex::Real> p_inp_sound_d, rho_inp_sound_d;
483 };
484 
485 /**
486  * @var InputSoundingData::ntimes
487  * @brief Number of sounding times represented in the arrays.
488  * @var InputSoundingData::tau_nudging
489  * @brief Nudging time scale for relaxing toward input sounding data.
490  * @var InputSoundingData::input_sounding_file
491  * @brief Sounding file path for each configured sounding time.
492  * @var InputSoundingData::input_sounding_time
493  * @brief Physical time associated with each input sounding file.
494  * @var InputSoundingData::n_sounding_files
495  * @brief Number of input sounding files.
496  * @var InputSoundingData::n_sounding_times
497  * @brief Number of input sounding times.
498  * @var InputSoundingData::assume_dry
499  * @brief Whether to ignore moisture in isentropic pressure integration.
500  * @var InputSoundingData::press_ref_inp_sound
501  * @brief Surface reference pressure read from the input sounding [Pa].
502  * @var InputSoundingData::theta_ref_inp_sound
503  * @brief Surface reference potential temperature read from the input sounding [K].
504  * @var InputSoundingData::qv_ref_inp_sound
505  * @brief Surface reference water vapor mixing ratio read from the input sounding [kg/kg].
506  * @var InputSoundingData::z_inp_sound
507  * @brief Interpolated host sounding heights for each sounding time [m].
508  * @var InputSoundingData::theta_inp_sound
509  * @brief Interpolated host potential temperature profiles [K].
510  * @var InputSoundingData::qv_inp_sound
511  * @brief Interpolated host water vapor mixing ratio profiles [kg/kg].
512  * @var InputSoundingData::U_inp_sound
513  * @brief Interpolated host x velocity profiles.
514  * @var InputSoundingData::V_inp_sound
515  * @brief Interpolated host y velocity profiles.
516  * @var InputSoundingData::z_inp_sound_d
517  * @brief Device sounding heights for each sounding time [m].
518  * @var InputSoundingData::theta_inp_sound_d
519  * @brief Device potential temperature profiles [K].
520  * @var InputSoundingData::qv_inp_sound_d
521  * @brief Device water vapor mixing ratio profiles [kg/kg].
522  * @var InputSoundingData::U_inp_sound_d
523  * @brief Device x velocity profiles.
524  * @var InputSoundingData::V_inp_sound_d
525  * @brief Device y velocity profiles.
526  * @var InputSoundingData::pm_integ
527  * @brief Hydrostatically integrated moist pressure profile.
528  * @var InputSoundingData::rhod_integ
529  * @brief Hydrostatically integrated dry density profile.
530  * @var InputSoundingData::p_inp_sound_d
531  * @brief Device pressure profile used to initialize solution fields.
532  * @var InputSoundingData::rho_inp_sound_d
533  * @brief Device density profile used to initialize solution fields.
534  */
535 #endif
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
constexpr amrex::Real p_0
Definition: ERF_Constants.H:61
constexpr amrex::Real RvoRd
Definition: ERF_Constants.H:56
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:64
constexpr amrex::Real R_d
Definition: ERF_Constants.H:47
constexpr amrex::Real RdoCp
Definition: ERF_Constants.H:54
constexpr amrex::Real Gamma
Definition: ERF_Constants.H:62
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getRhogivenThetaPress(const amrex::Real th, const amrex::Real p, const amrex::Real rdOcp, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:96
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getTgivenPandTh(const amrex::Real P, const amrex::Real th, const amrex::Real rdOcp)
Definition: ERF_EOS.H:32
const Real ztop
Definition: ERF_InitCustomPertVels_ParticleTests.H:4
ParmParse pp("prob")
const int khi
Definition: ERF_InitCustomPert_Bubble.H:21
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real interpolate_1d(const amrex::Real *alpha, const amrex::Real *beta, const amrex::Real alpha_interp, const int alpha_size)
Definition: ERF_Interpolation_1D.H:14
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void Newton_Raphson_hse(const Real &m_tol, const Real &RdoCp, const Real &dz, const Real &g, const Real &C, const Real &Th, const Real &T, const Real &qt, const Real &qv, Real &P, Real &rd, Real &F, const bool &maintain_Th)
Definition: ERF_HSEUtils.H:44
@ theta
Definition: ERF_SLM.H:20
@ qv
Definition: ERF_Kessler.H:30
@ U
Definition: ERF_IndexDefines.H:123
@ V
Definition: ERF_IndexDefines.H:124
@ dz
Definition: ERF_AdvanceWSM6.cpp:104
Definition: ERF_InputSoundingData.H:22
void host_to_device(int itime)
Copy host sounding arrays for one time index to device storage.
Definition: ERF_InputSoundingData.H:403
amrex::Gpu::DeviceVector< amrex::Real > rho_inp_sound_d
Device density profile used to initialize solution fields.
Definition: ERF_InputSoundingData.H:482
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > qv_inp_sound_d
Device water vapor mixing ratio profiles [kg/kg].
Definition: ERF_InputSoundingData.H:475
amrex::Vector< amrex::Vector< amrex::Real > > V_inp_sound
Interpolated host y velocity profiles.
Definition: ERF_InputSoundingData.H:472
amrex::Vector< amrex::Real > pm_integ
Hydrostatically integrated moist pressure profile.
Definition: ERF_InputSoundingData.H:478
amrex::Real qv_ref_inp_sound
Surface reference water vapor mixing ratio read from the input sounding [kg/kg].
Definition: ERF_InputSoundingData.H:469
amrex::Vector< amrex::Real > input_sounding_time
Physical time associated with each input sounding file.
Definition: ERF_InputSoundingData.H:462
void resize_arrays()
Resize host and device sounding arrays for the configured sounding times.
Definition: ERF_InputSoundingData.H:66
bool assume_dry
Whether to ignore moisture in isentropic pressure integration.
Definition: ERF_InputSoundingData.H:466
int n_sounding_times
Number of input sounding times.
Definition: ERF_InputSoundingData.H:464
amrex::Vector< amrex::Vector< amrex::Real > > theta_inp_sound
Interpolated host potential temperature profiles [K].
Definition: ERF_InputSoundingData.H:472
amrex::Vector< amrex::Real > rhod_integ
Hydrostatically integrated dry density profile.
Definition: ERF_InputSoundingData.H:480
void calc_rho_p(int itime)
Hydrostatically integrate density and pressure for one sounding.
Definition: ERF_InputSoundingData.H:222
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > V_inp_sound_d
Device y velocity profiles.
Definition: ERF_InputSoundingData.H:475
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > z_inp_sound_d
Device sounding heights for each sounding time [m].
Definition: ERF_InputSoundingData.H:475
void calc_rho_p_isentropic(int itime)
Compute density and pressure for an isentropic sounding profile.
Definition: ERF_InputSoundingData.H:318
int ntimes
Number of sounding times represented in the arrays.
Definition: ERF_InputSoundingData.H:457
void read_from_file(const amrex::Geometry &geom, const amrex::Vector< amrex::Real > &zlevels_stag, int itime, bool is_moist)
Read and interpolate one input sounding profile onto level-0 heights.
Definition: ERF_InputSoundingData.H:90
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > theta_inp_sound_d
Device potential temperature profiles [K].
Definition: ERF_InputSoundingData.H:475
amrex::Vector< amrex::Vector< amrex::Real > > U_inp_sound
Interpolated host x velocity profiles.
Definition: ERF_InputSoundingData.H:472
amrex::Real theta_ref_inp_sound
Surface reference potential temperature read from the input sounding [K].
Definition: ERF_InputSoundingData.H:469
amrex::Vector< std::string > input_sounding_file
Sounding file path for each configured sounding time.
Definition: ERF_InputSoundingData.H:461
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > U_inp_sound_d
Device x velocity profiles.
Definition: ERF_InputSoundingData.H:475
amrex::Gpu::DeviceVector< amrex::Real > p_inp_sound_d
Device pressure profile used to initialize solution fields.
Definition: ERF_InputSoundingData.H:482
amrex::Vector< amrex::Vector< amrex::Real > > z_inp_sound
Interpolated host sounding heights for each sounding time [m].
Definition: ERF_InputSoundingData.H:472
amrex::Vector< amrex::Vector< amrex::Real > > qv_inp_sound
Interpolated host water vapor mixing ratio profiles [kg/kg].
Definition: ERF_InputSoundingData.H:472
amrex::Real tau_nudging
Nudging time scale for relaxing toward input sounding data.
Definition: ERF_InputSoundingData.H:459
InputSoundingData()
Construct input sounding metadata from the ERF input namespace.
Definition: ERF_InputSoundingData.H:27
amrex::Real press_ref_inp_sound
Surface reference pressure read from the input sounding [Pa].
Definition: ERF_InputSoundingData.H:469
int size(int itime) const
Return the number of interpolated samples for one sounding time.
Definition: ERF_InputSoundingData.H:447
int n_sounding_files
Number of input sounding files.
Definition: ERF_InputSoundingData.H:463