ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
InputSoundingData Struct Reference

#include <ERF_InputSoundingData.H>

Collaboration diagram for InputSoundingData:

Public Member Functions

 InputSoundingData ()
 Construct input sounding metadata from the ERF input namespace. More...
 
void resize_arrays ()
 Resize host and device sounding arrays for the configured sounding times. More...
 
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. More...
 
void calc_rho_p (int itime)
 Hydrostatically integrate density and pressure for one sounding. More...
 
void calc_rho_p_isentropic (int itime)
 Compute density and pressure for an isentropic sounding profile. More...
 
void host_to_device (int itime)
 Copy host sounding arrays for one time index to device storage. More...
 
int size (int itime) const
 Return the number of interpolated samples for one sounding time. More...
 
void set_start_time (amrex::Real start_time)
 

Public Attributes

int ntimes
 Number of sounding times represented in the arrays. More...
 
amrex::Real tau_nudging = amrex::Real(5.0)
 Nudging time scale for relaxing toward input sounding data. More...
 
amrex::Vector< std::string > input_sounding_file = {}
 Sounding file path for each configured sounding time. More...
 
amrex::Vector< amrex::Realinput_sounding_time = {}
 Physical time associated with each input sounding file. More...
 
int n_sounding_files = 0
 Number of input sounding files. More...
 
int n_sounding_times = 0
 Number of input sounding times. More...
 
bool assume_dry {false}
 Whether to ignore moisture in isentropic pressure integration. More...
 
amrex::Real press_ref_inp_sound
 Surface reference pressure read from the input sounding [Pa]. More...
 
amrex::Real theta_ref_inp_sound
 Surface reference potential temperature read from the input sounding [K]. More...
 
amrex::Real qv_ref_inp_sound
 Surface reference water vapor mixing ratio read from the input sounding [kg/kg]. More...
 
amrex::Vector< amrex::Vector< amrex::Real > > z_inp_sound
 Interpolated host sounding heights for each sounding time [m]. More...
 
amrex::Vector< amrex::Vector< amrex::Real > > theta_inp_sound
 Interpolated host potential temperature profiles [K]. More...
 
amrex::Vector< amrex::Vector< amrex::Real > > qv_inp_sound
 Interpolated host water vapor mixing ratio profiles [kg/kg]. More...
 
amrex::Vector< amrex::Vector< amrex::Real > > U_inp_sound
 Interpolated host x velocity profiles. More...
 
amrex::Vector< amrex::Vector< amrex::Real > > V_inp_sound
 Interpolated host y velocity profiles. More...
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > z_inp_sound_d
 Device sounding heights for each sounding time [m]. More...
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > theta_inp_sound_d
 Device potential temperature profiles [K]. More...
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > qv_inp_sound_d
 Device water vapor mixing ratio profiles [kg/kg]. More...
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > U_inp_sound_d
 Device x velocity profiles. More...
 
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > V_inp_sound_d
 Device y velocity profiles. More...
 
amrex::Vector< amrex::Realpm_integ
 Hydrostatically integrated moist pressure profile. More...
 
amrex::Vector< amrex::Realrhod_integ
 Hydrostatically integrated dry density profile. More...
 
amrex::Gpu::DeviceVector< amrex::Realp_inp_sound_d
 Device pressure profile used to initialize solution fields. More...
 
amrex::Gpu::DeviceVector< amrex::Realrho_inp_sound_d
 Device density profile used to initialize solution fields. More...
 

Detailed Description

Data structure storing input sounding data. Also handles reading the input file for sounding data and hydrostatic column integration.

Constructor & Destructor Documentation

◆ InputSoundingData()

InputSoundingData::InputSoundingData ( )
inline

Construct input sounding metadata from the ERF input namespace.

29  {
30  amrex::ParmParse pp("erf");
31  pp.queryAdd("tau_nudging", tau_nudging);
32 
33  // Read in input_sounding filename
34  n_sounding_files = pp.countval("input_sounding_file");
35  if (n_sounding_files > 0) {
37  pp.queryarr("input_sounding_file", input_sounding_file, 0, n_sounding_files);
38  } else {
39  n_sounding_files = 1;
41  input_sounding_file[0] = "input_sounding";
42  }
43 
44  // Read in input_sounding times
45  n_sounding_times = pp.countval("input_sounding_time");
46 
47  if (n_sounding_times > 0) {
49  pp.queryarr("input_sounding_time", input_sounding_time, 0, n_sounding_times);
50  } else {
51  n_sounding_times = 1;
54  }
55 
56  // If we have more files than times or times than files we just use the minimum
57  int n = std::min(n_sounding_times, n_sounding_files);
58  n_sounding_files = n;
59  n_sounding_times = n;
60  input_sounding_file.resize(n);
61  input_sounding_time.resize(n);
62  }
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
ParmParse pp("prob")
amrex::Vector< amrex::Real > input_sounding_time
Physical time associated with each input sounding file.
Definition: ERF_InputSoundingData.H:496
int n_sounding_times
Number of input sounding times.
Definition: ERF_InputSoundingData.H:498
amrex::Vector< std::string > input_sounding_file
Sounding file path for each configured sounding time.
Definition: ERF_InputSoundingData.H:495
amrex::Real tau_nudging
Nudging time scale for relaxing toward input sounding data.
Definition: ERF_InputSoundingData.H:493
int n_sounding_files
Number of input sounding files.
Definition: ERF_InputSoundingData.H:497
Here is the call graph for this function:

Member Function Documentation

◆ calc_rho_p()

void InputSoundingData::calc_rho_p ( int  itime)
inline

Hydrostatically integrate density and pressure for one sounding.

Parameters
itimeSounding time/file index to integrate.
233  {
234  /* Calculate density and pressure, roughly following the procedure in
235  * WRF dyn_em/module_initialize_ideal.F. We integrate hydrostatically
236  * from the surface up through the air column to get the dry density
237  * and moist pressure.
238  */
239  const int Ninp = size(itime);
240  pm_integ.resize(Ninp);
241  rhod_integ.resize(Ninp);
242 
243  // evaluate surface quantities (k=0): total pressure and dry air
247  RdoCp,
249 
250  amrex::Print() << "ideal sounding init: surface dry air density = "
251  << std::setprecision(15)
252  << rhod_integ[0] << " kg/m^3" << std::endl;
253 
254  // Note:
255  // p_dry = rho_d R_d T
256  // p_tot = rho_m R_d T_v
257  // = rho_d(1 + q_v) R_d T_v
258 
259 #if 0 // Printing
260  // In this absence of moisture, this moist profile will match the
261  // following dry profile
262  amrex::Print() << "z p_m rho_d theta qv U V" << std::endl;
263  amrex::Print() << z_inp_sound[itime][0]
264  << " " << pm_integ[0]
265  << " " << rhod_integ[0]
266  << " " << theta_inp_sound[itime][0]
267  << " " << qv_inp_sound[itime][0]
268  << " " << U_inp_sound[itime][0]
269  << " " << V_inp_sound[itime][0]
270  << std::endl;
271 #endif
272 
273  // integrate from surface to domain top
274  amrex::Real dz, F, C;
275  amrex::Real T_hi;
276  amrex::Real rho_tot_hi, rho_tot_lo;
277  for (int k=1; k < size(itime); ++k)
278  {
279  // Vertical grid spacing
280  dz = z_inp_sound[itime][k] - z_inp_sound[itime][k-1];
281 
282  // The Newton residual F below is a pressure, so the tolerance it is
283  // tested against has to be scaled to the pressure being solved for.
284  // The iterate cannot do better than settle into a one-ulp limit
285  // cycle about the true root, which puts a hard floor of roughly
286  // ulp(p) on |F| -- 3.6e-12 for a 1.6e4 Pa pressure in double, and
287  // ~1e-2 Pa at 1e5 Pa in single. The fixed 1e-12 Pa tolerance used
288  // here previously sat below that floor, so the iteration burned all
289  // of its allowed passes and reported a spurious non-convergence
290  // warning for a column that had in fact converged to roundoff.
291 #ifdef AMREX_USE_FLOAT
292  const amrex::Real tol = amrex::Real(4)
294  * pm_integ[k-1];
295 #else
296  const amrex::Real tol = amrex::Real(1.0e-12);
297 #endif
298 
299  // Establish known constant
300  rho_tot_lo = rhod_integ[k-1] * (one + qv_inp_sound[itime][k-1]);
301  C = -pm_integ[k-1] + myhalf*rho_tot_lo*CONST_GRAV*dz;
302 
303  // Initial guess and residual
304  pm_integ[k] = pm_integ[k-1];
305  T_hi = getTgivenPandTh(pm_integ[k], theta_inp_sound[itime][k], RdoCp);
307  pm_integ[k],
308  RdoCp,
309  qv_inp_sound[itime][k]);
310  rho_tot_hi = rhod_integ[k] * (one + qv_inp_sound[itime][k]);
311  F = pm_integ[k] + myhalf*rho_tot_hi*CONST_GRAV*dz + C;
312 
313  // Do iterations
314  if (std::abs(F)>tol) {
315  bool maintain_Th = true;
317  CONST_GRAV, C, theta_inp_sound[itime][k], T_hi,
318  qv_inp_sound[itime][k], qv_inp_sound[itime][k],
319  pm_integ[k], rhod_integ[k], F, maintain_Th);
320  }
321 
322 #if 0 // Printing
323  amrex::Print() << z_inp_sound[itime][k]
324  << " " << pm_integ[k]
325  << " " << rhod_integ[k]
326  << " " << theta_inp_sound[itime][k]
327  << " " << qv_inp_sound[itime][k]
328  << " " << U_inp_sound[itime][k]
329  << " " << V_inp_sound[itime][k]
330  << std::endl;
331 #endif
332  }
333  // Note: at this point, the surface pressure, density of the dry air
334  // column is stored in pm_integ[0], rhod_integ[0]
335 
336  // update
337  host_to_device(itime);
338  }
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:64
constexpr amrex::Real RdoCp
Definition: ERF_Constants.H:54
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
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
@ dz
Definition: ERF_AdvanceWDM6.cpp:270
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
void host_to_device(int itime)
Copy host sounding arrays for one time index to device storage.
Definition: ERF_InputSoundingData.H:429
amrex::Vector< amrex::Vector< amrex::Real > > V_inp_sound
Interpolated host y velocity profiles.
Definition: ERF_InputSoundingData.H:506
amrex::Vector< amrex::Real > pm_integ
Hydrostatically integrated moist pressure profile.
Definition: ERF_InputSoundingData.H:512
amrex::Real qv_ref_inp_sound
Surface reference water vapor mixing ratio read from the input sounding [kg/kg].
Definition: ERF_InputSoundingData.H:503
amrex::Vector< amrex::Vector< amrex::Real > > theta_inp_sound
Interpolated host potential temperature profiles [K].
Definition: ERF_InputSoundingData.H:506
amrex::Vector< amrex::Real > rhod_integ
Hydrostatically integrated dry density profile.
Definition: ERF_InputSoundingData.H:514
amrex::Vector< amrex::Vector< amrex::Real > > U_inp_sound
Interpolated host x velocity profiles.
Definition: ERF_InputSoundingData.H:506
amrex::Real theta_ref_inp_sound
Surface reference potential temperature read from the input sounding [K].
Definition: ERF_InputSoundingData.H:503
amrex::Vector< amrex::Vector< amrex::Real > > z_inp_sound
Interpolated host sounding heights for each sounding time [m].
Definition: ERF_InputSoundingData.H:506
amrex::Vector< amrex::Vector< amrex::Real > > qv_inp_sound
Interpolated host water vapor mixing ratio profiles [kg/kg].
Definition: ERF_InputSoundingData.H:506
amrex::Real press_ref_inp_sound
Surface reference pressure read from the input sounding [Pa].
Definition: ERF_InputSoundingData.H:503
int size(int itime) const
Return the number of interpolated samples for one sounding time.
Definition: ERF_InputSoundingData.H:473
Here is the call graph for this function:

◆ calc_rho_p_isentropic()

void InputSoundingData::calc_rho_p_isentropic ( int  itime)
inline

Compute density and pressure for an isentropic sounding profile.

Parameters
itimeSounding time/file index to integrate.
345  {
346  /* Calculate density and pressure assuming isentropic (constant theta)
347  background conditions. This does not use Newton-Raphson iterations
348  to calculate rho and p.
349  */
350  const int Ninp = size(itime);
351  pm_integ.resize(Ninp);
352  rhod_integ.resize(Ninp);
353 
354  // evaluate surface quantities (k=0): total pressure and dry air
358  RdoCp,
360 
361  const amrex::Real th0 = theta_ref_inp_sound;
362  const amrex::Real p0_pow = std::pow(p_0, (Gamma-1)/Gamma);
363 
364  amrex::Print() << "isentropic sounding init: surface dry air density = "
365  << std::setprecision(15)
366  << rhod_integ[0] << " kg/m^3" << std::endl;
367 
368 #if 0 // Printing
369  // In this absence of moisture, this moist profile will match the
370  // following dry profile
371  amrex::Print() << "z p_m rho_d theta qv U V" << std::endl;
372  amrex::Print() << z_inp_sound[itime][0]
373  << " " << pm_integ[0]
374  << " " << rhod_integ[0]
375  << " " << theta_inp_sound[itime][0]
376  << " " << qv_inp_sound[itime][0]
377  << " " << U_inp_sound[itime][0]
378  << " " << V_inp_sound[itime][0]
379  << std::endl;
380 #endif
381 
382  // integrate from surface to domain top
383  amrex::Real dz;
384  for (int k=1; k < size(itime); ++k)
385  {
386  // Vertical grid spacing
387  dz = z_inp_sound[itime][k] - z_inp_sound[itime][k-1];
388 
389  // Isentropic pressure at next level
390  amrex::Real qvmean = (assume_dry) ? zero : myhalf*(qv_inp_sound[itime][k-1] + qv_inp_sound[itime][k]);
391  amrex::Real thm0 = th0 * (one + RvoRd * qvmean);
392  amrex::Real plo_pow = std::pow(pm_integ[k-1], (Gamma-1)/Gamma);
393  pm_integ[k] = (Gamma-1)/Gamma *
394  (-CONST_GRAV * p0_pow / (R_d * thm0) * (1 + qvmean) * dz
395  + Gamma/(Gamma-1) * plo_pow);
396  pm_integ[k] = std::pow(pm_integ[k], Gamma / (Gamma-1));
397 
398  // Note: The pressure calculated here is copied to `p_inp_sound_d`
399  // and currently not used.
400 
401  // Get corresponding dry air density
403  pm_integ[k],
404  RdoCp,
405  qv_inp_sound[itime][k]);
406 
407 #if 0 // Printing
408  amrex::Print() << z_inp_sound[itime][k]
409  << " " << pm_integ[k]
410  << " " << rhod_integ[k]
411  << " " << theta_inp_sound[itime][k]
412  << " " << qv_inp_sound[itime][k]
413  << " " << U_inp_sound[itime][k]
414  << " " << V_inp_sound[itime][k]
415  << std::endl;
416 #endif
417  }
418  // Note: at this point, the surface pressure, density of the dry air
419  // column is stored in pm_integ[0], rhod_integ[0]
420 
421  // update
422  host_to_device(itime);
423  }
constexpr amrex::Real p_0
Definition: ERF_Constants.H:61
constexpr amrex::Real RvoRd
Definition: ERF_Constants.H:56
constexpr amrex::Real R_d
Definition: ERF_Constants.H:47
constexpr amrex::Real Gamma
Definition: ERF_Constants.H:62
bool assume_dry
Whether to ignore moisture in isentropic pressure integration.
Definition: ERF_InputSoundingData.H:500
Here is the call graph for this function:

◆ host_to_device()

void InputSoundingData::host_to_device ( int  itime)
inline

Copy host sounding arrays for one time index to device storage.

Parameters
itimeSounding time/file index to copy.
430  {
431  const int Ninp = size(itime);
432  z_inp_sound_d[itime].resize(Ninp);
433  theta_inp_sound_d[itime].resize(Ninp);
434  qv_inp_sound_d[itime].resize(Ninp);
435  U_inp_sound_d[itime].resize(Ninp);
436  V_inp_sound_d[itime].resize(Ninp);
437 
438  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
439  z_inp_sound[itime].begin(), z_inp_sound[itime].end(),
440  z_inp_sound_d[itime].begin());
441  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
442  theta_inp_sound[itime].begin(), theta_inp_sound[itime].end(),
443  theta_inp_sound_d[itime].begin());
444  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
445  qv_inp_sound[itime].begin(), qv_inp_sound[itime].end(),
446  qv_inp_sound_d[itime].begin());
447  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
448  U_inp_sound[itime].begin(), U_inp_sound[itime].end(),
449  U_inp_sound_d[itime].begin());
450  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
451  V_inp_sound[itime].begin(), V_inp_sound[itime].end(),
452  V_inp_sound_d[itime].begin());
453 
454  if (rhod_integ.size() > 0)
455  {
456  //amrex::Print() << "Copying rho_d, p_d to device" << std::endl;
457  rho_inp_sound_d.resize(size(itime)+2);
458  p_inp_sound_d.resize(size(itime)+2);
459  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
460  rhod_integ.begin(), rhod_integ.end(),
461  rho_inp_sound_d.begin());
462  amrex::Gpu::copy(amrex::Gpu::hostToDevice,
463  pm_integ.begin(), pm_integ.end(),
464  p_inp_sound_d.begin());
465  }
466  }
amrex::Gpu::DeviceVector< amrex::Real > rho_inp_sound_d
Device density profile used to initialize solution fields.
Definition: ERF_InputSoundingData.H:516
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > qv_inp_sound_d
Device water vapor mixing ratio profiles [kg/kg].
Definition: ERF_InputSoundingData.H:509
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > V_inp_sound_d
Device y velocity profiles.
Definition: ERF_InputSoundingData.H:509
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > z_inp_sound_d
Device sounding heights for each sounding time [m].
Definition: ERF_InputSoundingData.H:509
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > theta_inp_sound_d
Device potential temperature profiles [K].
Definition: ERF_InputSoundingData.H:509
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > U_inp_sound_d
Device x velocity profiles.
Definition: ERF_InputSoundingData.H:509
amrex::Gpu::DeviceVector< amrex::Real > p_inp_sound_d
Device pressure profile used to initialize solution fields.
Definition: ERF_InputSoundingData.H:516

Referenced by calc_rho_p(), calc_rho_p_isentropic(), and read_from_file().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_from_file()

void InputSoundingData::read_from_file ( const amrex::Geometry &  geom,
const amrex::Vector< amrex::Real > &  zlevels_stag,
int  itime,
bool  is_moist 
)
inline

Read and interpolate one input sounding profile onto level-0 heights.

Parameters
geomGeometry defining the level-0 vertical domain.
zlevels_stagStaggered vertical coordinates used for interpolation.
itimeSounding time/file index to read.
is_moistWhether the selected physics permits nonzero water vapor.
94  {
95  const int klo = 0;
96  const int khi = geom.Domain().bigEnd()[AMREX_SPACEDIM-1];
97  const int Nz = geom.Domain().size()[AMREX_SPACEDIM-1];
98 
99  const amrex::Real zbot = zlevels_stag[klo];
100  const amrex::Real ztop = zlevels_stag[khi+1];
101 
102  z_inp_sound[itime].resize(Nz+2);
103  theta_inp_sound[itime].resize(Nz+2);
104  qv_inp_sound[itime].resize(Nz+2);
105  U_inp_sound[itime].resize(Nz+2);
106  V_inp_sound[itime].resize(Nz+2);
107 
108  // Read the input_sounding file
109  amrex::Print() << "input_sounding file location : " << input_sounding_file[itime] << std::endl;
110  std::ifstream input_sounding_reader(input_sounding_file[itime]);
111  if(!input_sounding_reader.is_open()) {
112  amrex::Error("Error opening the input_sounding file\n");
113  }
114  else {
115  // Read the contents of the input_sounding file
116  amrex::Print() << "Successfully opened the input_sounding file. Now reading... " << std::endl;
117  std::string line;
118 
119  // First, read the input data into temp vectors; then, interpolate vectors to the
120  // domain lo/hi and cell centers (from level 0)
121  amrex::Vector<amrex::Real> z_inp_sound_tmp, theta_inp_sound_tmp, qv_inp_sound_tmp,
122  U_inp_sound_tmp, V_inp_sound_tmp;
123 
124  // Read surface quantities from the first line
125  std::getline(input_sounding_reader, line);
126  std::istringstream iss(line);
128  press_ref_inp_sound *= 100; // convert from hPa to Pa
129  qv_ref_inp_sound *= amrex::Real(0.001); // convert from g/kg to kg/kg
130 
131  // Add surface
132  z_inp_sound_tmp.push_back(zbot); // height above sea level [m]
133  theta_inp_sound_tmp.push_back(theta_ref_inp_sound);
134  qv_inp_sound_tmp.push_back(qv_ref_inp_sound);
135  U_inp_sound_tmp.push_back(0);
136  V_inp_sound_tmp.push_back(0);
137 
138  // *************************************************************************************************
139  // Make sure that if we specify surface values for temp in the inputs file and in the input sounding file,
140  // those values must match
141  // *************************************************************************************************
142  amrex::ParmParse pp_erf("erf");
143 
144  // Negative sentinel rather than the queryAdd return value: an absolute
145  // temperature is never negative, and the return value only reports whether
146  // the key existed before this call. ERF_SurfaceLayer.H parses the same key,
147  // so testing the return would report "specified" here whenever that site ran
148  // first. This was also an uninitialized read before.
149  amrex::Real surf_temp = amrex::Real(-1.0);
150  pp_erf.queryAdd("most.surf_temp", surf_temp);
151  bool surf_temp_specified = (surf_temp > amrex::Real(0.0));
152  if ( surf_temp_specified && (surf_temp != theta_inp_sound_tmp[0]) ) {
153  amrex::Print() << "Input sounding temp does not match most.surf_temp" << std::endl;
154  amrex::Print() << "Modify one or both to match." << std::endl;
155  amrex::Abort();
156  }
157 
158  // *************************************************************************************************
159  // Make sure that if we specify surface values for qv in the inputs file and in the input sounding file,
160  // those values must match
161  // *************************************************************************************************
162  // Negative sentinel, as for most.surf_temp above: a mixing ratio is never
163  // negative, and ERF_SurfaceLayer.H parses this same key.
164  amrex::Real surf_moist = amrex::Real(-1.0);
165  pp_erf.queryAdd("most.surf_moist", surf_moist);
166  bool surf_moist_specified = (surf_moist >= amrex::Real(0.0));
167  if ( surf_moist_specified && (surf_moist != qv_inp_sound_tmp[0]) ) {
168  amrex::Print() << "Input sounding qv does not match most.surf_moist" << std::endl;
169  amrex::Print() << "Modify one or both to match." << std::endl;
170  amrex::Abort();
171  }
172 
173  // Read the vertical profile at each given height
174  amrex::Real z, theta, qv, U, V;
175 
176  while(std::getline(input_sounding_reader, line)) {
177  std::istringstream iss_z(line);
178  iss_z >> z >> theta >> qv >> U >> V;
179 
180  // Dont read in non-zero qv if not using a moisture model
181  AMREX_ALWAYS_ASSERT(qv == zero || is_moist);
182 
183  if (z == zbot) {
184  AMREX_ALWAYS_ASSERT(theta == theta_inp_sound_tmp[0]);
185  AMREX_ALWAYS_ASSERT(qv*amrex::Real(0.001) == qv_inp_sound_tmp[0]); // convert from g/kg to kg/kg
186  U_inp_sound_tmp[0] = U;
187  V_inp_sound_tmp[0] = V;
188  } else {
189  AMREX_ALWAYS_ASSERT(z > z_inp_sound_tmp[z_inp_sound_tmp.size()-1]); // sounding is increasing in height
190  z_inp_sound_tmp.push_back(z);
191 
192  theta_inp_sound_tmp.push_back(theta);
193  qv_inp_sound_tmp.push_back(qv*amrex::Real(0.001)); // convert from g/kg to kg/kg
194  U_inp_sound_tmp.push_back(U);
195  V_inp_sound_tmp.push_back(V);
196  if (z >= ztop) break;
197  }
198  }
199 
200  // At this point, we have an input_sounding from zbot up to
201  // z_inp_sound_tmp[N-1] >= ztop. Now, interpolate to grid level 0 heights
202  const int Ninp = z_inp_sound_tmp.size();
203  z_inp_sound[itime][0] = zbot;
204  theta_inp_sound[itime][0] = theta_inp_sound_tmp[0];
205  qv_inp_sound[itime][0] = qv_inp_sound_tmp[0];
206  U_inp_sound[itime][0] = U_inp_sound_tmp[0];
207  V_inp_sound[itime][0] = V_inp_sound_tmp[0];
208  for (int k=0; k < Nz; ++k) {
209  z_inp_sound[itime][k+1] = myhalf * (zlevels_stag[k] + zlevels_stag[k+1]);
210  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);
211  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);
212  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);
213  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);
214  }
215  z_inp_sound[itime][Nz+1] = ztop;
216  theta_inp_sound[itime][Nz+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), theta_inp_sound_tmp.dataPtr(), ztop, Ninp);
217  qv_inp_sound[itime][Nz+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), qv_inp_sound_tmp.dataPtr(), ztop, Ninp);
218  U_inp_sound[itime][Nz+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), U_inp_sound_tmp.dataPtr(), ztop, Ninp);
219  V_inp_sound[itime][Nz+1] = interpolate_1d(z_inp_sound_tmp.dataPtr(), V_inp_sound_tmp.dataPtr(), ztop, Ninp);
220  }
221 
222  amrex::Print() << "Successfully read the " << itime << "th input_sounding file..." << std::endl;
223  input_sounding_reader.close();
224 
225  host_to_device(itime);
226  }
const Real ztop
Definition: ERF_InitCustomPertVels_ParticleTests.H:4
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
@ theta
Definition: ERF_SLM.H:20
@ qv
Definition: ERF_Kessler.H:30
@ U
Definition: ERF_IndexDefines.H:126
@ V
Definition: ERF_IndexDefines.H:127
Here is the call graph for this function:

◆ resize_arrays()

void InputSoundingData::resize_arrays ( )
inline

Resize host and device sounding arrays for the configured sounding times.

68  {
70 
71  z_inp_sound.resize(ntimes);
72  theta_inp_sound.resize(ntimes);
73  qv_inp_sound.resize(ntimes);
74  U_inp_sound.resize(ntimes);
75  V_inp_sound.resize(ntimes);
76 
77  z_inp_sound_d.resize(ntimes);
78  theta_inp_sound_d.resize(ntimes);
79  qv_inp_sound_d.resize(ntimes);
80  U_inp_sound_d.resize(ntimes);
81  V_inp_sound_d.resize(ntimes);
82  }
int ntimes
Number of sounding times represented in the arrays.
Definition: ERF_InputSoundingData.H:491

◆ set_start_time()

void InputSoundingData::set_start_time ( amrex::Real  start_time)
inline
483  {
484  for (int i = 0; i < n_sounding_times; i++)
485  {
486  input_sounding_time[i] += start_time;
487  }
488  }

◆ size()

int InputSoundingData::size ( int  itime) const
inline

Return the number of interpolated samples for one sounding time.

Parameters
itimeSounding time/file index to query.
Returns
Number of stored sounding profile levels.
474  {
476  AMREX_ALWAYS_ASSERT(z_inp_sound[itime].size() == qv_inp_sound[itime].size());
477  AMREX_ALWAYS_ASSERT(z_inp_sound[itime].size() == U_inp_sound[itime].size());
478  AMREX_ALWAYS_ASSERT(z_inp_sound[itime].size() == V_inp_sound[itime].size());
479  return z_inp_sound[itime].size();
480  }

Referenced by calc_rho_p(), calc_rho_p_isentropic(), host_to_device(), init_state_from_input_sounding(), init_state_from_input_sounding_hse(), and init_velocities_from_input_sounding().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ assume_dry

InputSoundingData::assume_dry {false}

Whether to ignore moisture in isentropic pressure integration.

Referenced by calc_rho_p_isentropic(), and init_state_from_input_sounding_hse().

◆ input_sounding_file

InputSoundingData::input_sounding_file = {}

Sounding file path for each configured sounding time.

Referenced by InputSoundingData(), and read_from_file().

◆ input_sounding_time

InputSoundingData::input_sounding_time = {}

Physical time associated with each input sounding file.

Referenced by InputSoundingData(), make_mom_sources(), and set_start_time().

◆ n_sounding_files

InputSoundingData::n_sounding_files = 0

Number of input sounding files.

Referenced by InputSoundingData(), and resize_arrays().

◆ n_sounding_times

InputSoundingData::n_sounding_times = 0

Number of input sounding times.

Referenced by InputSoundingData(), and set_start_time().

◆ ntimes

InputSoundingData::ntimes

Number of sounding times represented in the arrays.

Referenced by resize_arrays().

◆ p_inp_sound_d

InputSoundingData::p_inp_sound_d

Device pressure profile used to initialize solution fields.

Referenced by host_to_device().

◆ pm_integ

InputSoundingData::pm_integ

Hydrostatically integrated moist pressure profile.

Referenced by calc_rho_p(), calc_rho_p_isentropic(), host_to_device(), and LargeScaleForcingData::interp_forcing().

◆ press_ref_inp_sound

InputSoundingData::press_ref_inp_sound

Surface reference pressure read from the input sounding [Pa].

Referenced by calc_rho_p(), calc_rho_p_isentropic(), and read_from_file().

◆ qv_inp_sound

InputSoundingData::qv_inp_sound

Interpolated host water vapor mixing ratio profiles [kg/kg].

Referenced by calc_rho_p(), calc_rho_p_isentropic(), host_to_device(), read_from_file(), resize_arrays(), and size().

◆ qv_inp_sound_d

InputSoundingData::qv_inp_sound_d

Device water vapor mixing ratio profiles [kg/kg].

Referenced by host_to_device(), init_state_from_input_sounding(), init_state_from_input_sounding_hse(), and resize_arrays().

◆ qv_ref_inp_sound

InputSoundingData::qv_ref_inp_sound

Surface reference water vapor mixing ratio read from the input sounding [kg/kg].

Referenced by calc_rho_p(), calc_rho_p_isentropic(), and read_from_file().

◆ rho_inp_sound_d

InputSoundingData::rho_inp_sound_d

Device density profile used to initialize solution fields.

Referenced by host_to_device(), and init_state_from_input_sounding_hse().

◆ rhod_integ

InputSoundingData::rhod_integ

Hydrostatically integrated dry density profile.

Referenced by calc_rho_p(), calc_rho_p_isentropic(), and host_to_device().

◆ tau_nudging

InputSoundingData::tau_nudging = amrex::Real(5.0)

Nudging time scale for relaxing toward input sounding data.

Referenced by InputSoundingData(), and make_mom_sources().

◆ theta_inp_sound

InputSoundingData::theta_inp_sound

Interpolated host potential temperature profiles [K].

Referenced by calc_rho_p(), calc_rho_p_isentropic(), host_to_device(), read_from_file(), resize_arrays(), and size().

◆ theta_inp_sound_d

InputSoundingData::theta_inp_sound_d

Device potential temperature profiles [K].

Referenced by host_to_device(), init_state_from_input_sounding(), init_state_from_input_sounding_hse(), and resize_arrays().

◆ theta_ref_inp_sound

InputSoundingData::theta_ref_inp_sound

Surface reference potential temperature read from the input sounding [K].

Referenced by calc_rho_p(), calc_rho_p_isentropic(), and read_from_file().

◆ U_inp_sound

InputSoundingData::U_inp_sound

Interpolated host x velocity profiles.

Referenced by calc_rho_p(), calc_rho_p_isentropic(), host_to_device(), read_from_file(), resize_arrays(), and size().

◆ U_inp_sound_d

InputSoundingData::U_inp_sound_d

◆ V_inp_sound

InputSoundingData::V_inp_sound

Interpolated host y velocity profiles.

Referenced by calc_rho_p(), calc_rho_p_isentropic(), host_to_device(), read_from_file(), resize_arrays(), and size().

◆ V_inp_sound_d

InputSoundingData::V_inp_sound_d

◆ z_inp_sound

InputSoundingData::z_inp_sound

Interpolated host sounding heights for each sounding time [m].

Referenced by calc_rho_p(), calc_rho_p_isentropic(), host_to_device(), read_from_file(), resize_arrays(), and size().

◆ z_inp_sound_d

InputSoundingData::z_inp_sound_d

The documentation for this struct was generated from the following file: