ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_TerrainFileChecks.H
Go to the documentation of this file.
1 #ifndef ERF_TERRAIN_FILE_CHECKS_H_
2 #define ERF_TERRAIN_FILE_CHECKS_H_
3 
4 /**
5  * \file ERF_TerrainFileChecks.H
6  *
7  * Checks of the height tables read from erf.terrain_file_name, erf.terrain_file_name_USGS
8  * and erf.buildings_file_name (ProblemBase::read_custom_terrain), a start-up summary of each
9  * table, and the warning for steep terrain next to an inflow or outflow face.
10  *
11  * Table layouts:
12  * - ERF text format (nx, ny >= 1): x has nx values, y has ny values, and height n sits at
13  * (x[n / ny], y[n % ny]), i.e. y varies fastest. A single value in a direction makes
14  * the surface constant in that direction (a two-dimensional profile).
15  * - USGS format (nx, ny >= 2): x has one value per point, y one value per row of nx
16  * points, and height n sits at (x[n], y[n / nx]), i.e. x varies fastest.
17  */
18 
19 #include <AMReX_Array.H>
20 #include <AMReX_Array4.H>
21 #include <AMReX_Geometry.H>
22 #include <AMReX_MultiFab.H>
23 #include <AMReX_GpuQualifiers.H>
24 #include <AMReX_Extension.H>
25 #include <AMReX_Math.H>
26 #include <AMReX_REAL.H>
27 #include <AMReX_Vector.H>
28 
30 
31 #include <cmath>
32 #include <string>
33 
34 #include <AMReX_Print.H>
35 
36 #include <sstream>
37 #include <type_traits>
38 
39 /**
40  * Read one number from line n of a text file that holds one number per line.
41  * Aborts, naming the file and the line, on a line that is missing, is not a
42  * number (a whole number for T = int), or has text after the number.
43  */
44 template <typename T>
45 T erf_get_single_value (std::istream& is, int n, const std::string& fname)
46 {
47  T r = 0;
48  std::string line;
49  if (std::getline(is, line)) {
50  std::stringstream ss(line);
51  ss >> r;
52  if (ss.fail()) {
53  amrex::Abort("Terrain file " + fname + ": line " + std::to_string(n)
54  + " is not a number: '" + line + "'");
55  }
56  std::string extra;
57  if (ss >> extra) {
58  if (std::is_integral_v<T> && (extra[0] == '.' || extra[0] == 'e' || extra[0] == 'E')) {
59  amrex::Abort("Terrain file " + fname + ": line " + std::to_string(n) + " must be a whole"
60  + " number (nx or ny): '" + line + "'");
61  }
62  amrex::Abort("Terrain file " + fname + ": line " + std::to_string(n) + " has text after"
63  + " the value: '" + line + "'; the file has one value per line, with no"
64  + " other text");
65  }
66  } else if (n <= 2) {
67  amrex::Abort("Terrain file " + fname + ": the file ends at line " + std::to_string(n-1)
68  + "; lines 1 and 2 must give nx and ny");
69  } else {
70  amrex::Abort("Terrain file " + fname + ": the file ends at line " + std::to_string(n-1)
71  + ", but nx and ny ask for nx + ny + nx*ny values after them");
72  }
73  return r;
74 }
75 
76 namespace erf_terrain_file {
77 
78 /** A height table as read from a terrain or buildings text file (layouts above). */
80 {
81  int nx = 0;
82  int ny = 0;
83  amrex::Vector<amrex::Real> x, y, z;
84 };
85 
86 /**
87  * The height table in file fname, read, checked (TableProblem) and summarised (TableSummary)
88  * on the I/O rank the first time the file is asked for, then broadcast; later calls return the
89  * same table without reading the file again. Aborts, naming the file and the line, on a file
90  * that cannot be read as the layout says.
91  *
92  * @param[in] fname file name
93  * @param[in] is_usgs USGS layout
94  * @param[in] prob_lo, prob_hi domain extent, for the coverage check
95  * @param[in] require_domain_coverage false for local building patches; all other checks remain
96  */
97 const HeightTable&
98 ReadHeightTable (const std::string& fname, bool is_usgs,
99  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& prob_lo,
100  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& prob_hi,
101  bool require_domain_coverage = true);
102 
103 /**
104  * The first problem found in a height table, or an empty string if there is none.
105  * Problems: fewer points than the layout needs (ERF format: one in each direction, USGS:
106  * two; one value in a direction is not checked further), list sizes that do not match nx and ny,
107  * a value that is not finite, x or y values that do not increase strictly (in the
108  * USGS format: the x values of each row, and the y values from row to row), and a
109  * table that does not cover the domain: each end of the x and y lists may stop at
110  * most one table spacing inside prob_lo or prob_hi (the layout of a file with one
111  * height per cell starting at prob_lo), with an allowance of 1e-3 of that spacing for
112  * rounded coordinates. Beyond the table the reader only extends the heights from its
113  * edge: linearly before the first point, and (ERF format) by holding the last value
114  * after the last point; USGS extends linearly at both ends.
115  * Setting require_domain_coverage to false skips only the coverage check, for building
116  * files that describe a local patch. Coordinate ordering and all format checks still apply.
117  *
118  * @param[in] is_usgs USGS layout (x varies fastest, one x per point)
119  * @param[in] nx, ny table size
120  * @param[in] x, y, z table coordinates and heights
121  * @param[in] prob_lo, prob_hi domain extent
122  * @param[in] require_domain_coverage whether the table must cover the domain
123  */
124 std::string
125 TableProblem (bool is_usgs, int nx, int ny,
126  const amrex::Vector<amrex::Real>& x,
127  const amrex::Vector<amrex::Real>& y,
128  const amrex::Vector<amrex::Real>& z,
129  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& prob_lo,
130  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& prob_hi,
131  bool require_domain_coverage = true);
132 
133 /**
134  * Text describing a valid height table: its size and extent, the order its heights are
135  * read in, where the lowest and highest heights sit, and the largest slopes |dh/dx| and
136  * |dh/dy| between neighbouring table points with where they sit. Meant to be printed once
137  * per file, so that a transposed or mis-ordered file can be spotted at start-up.
138  *
139  * @param[in] fname file name, for the first line
140  * @param[in] is_usgs USGS layout
141  * @param[in] nx, ny table size
142  * @param[in] x, y, z table coordinates and heights (must pass TableProblem)
143  */
144 std::string
145 TableSummary (const std::string& fname, bool is_usgs, int nx, int ny,
146  const amrex::Vector<amrex::Real>& x,
147  const amrex::Vector<amrex::Real>& y,
148  const amrex::Vector<amrex::Real>& z);
149 
150 /** Terrain slope |grad h| above which a band next to an inflow or outflow face is reported. */
152 
153 /**
154  * Physical slope |grad h| of the terrain over cell (i,j,k): the terrain drops of
155  * ComputeTerrainCellDrops (the same drops as the diffusive limits and the slope factor)
156  * times the map factor over the cell size in each direction.
157  *
158  * @param[in] i, j, k cell indices
159  * @param[in] z_nd nodal heights
160  * @param[in] mfx, mfy map factors of the cell
161  * @param[in] dxinv, dyinv inverse horizontal cell sizes
162  */
163 AMREX_GPU_HOST_DEVICE
164 AMREX_FORCE_INLINE
166 CellTerrainSlope (int i, int j, int k, const amrex::Array4<const amrex::Real>& z_nd,
167  amrex::Real mfx, amrex::Real mfy, amrex::Real dxinv, amrex::Real dyinv) noexcept
168 {
169  const TerrainCellDrops d = ComputeTerrainCellDrops(i, j, k, z_nd);
170  const amrex::Real hx = mfx * dxinv * d.dx_drop;
171  const amrex::Real hy = mfy * dyinv * d.dy_drop;
172  return std::sqrt(hx*hx + hy*hy);
173 }
174 
175 /**
176  * Largest CellTerrainSlope, on one level, over the surface cells within band cells of
177  * each lateral domain face, in the order xlo, xhi, ylo, yhi; -1 for a face whose band
178  * holds no cell of this level. Reduced over all ranks.
179  *
180  * @param[in] z_phys_nd nodal heights of the level (surface at the domain's lowest k)
181  * @param[in] mf_mx map factor in x at cell centres (ERF's mapfac m_x, on ba2d)
182  * @param[in] mf_my map factor in y at cell centres (m_y)
183  * @param[in] geom geometry of the level
184  * @param[in] band width of the band in cells (>= 1)
185  */
186 amrex::Array<amrex::Real,4>
187 FaceBandSlopes (const amrex::MultiFab& z_phys_nd, const amrex::MultiFab& mf_mx,
188  const amrex::MultiFab& mf_my, const amrex::Geometry& geom, int band);
189 
190 /**
191  * Warning text for the inflow and outflow faces of one level whose band slope (from
192  * FaceBandSlopes) exceeds open_face_slope_warn, or an empty string if there is none.
193  * The caller prints it only when no steep-terrain option is on at that level.
194  *
195  * @param[in] lev level, for the text
196  * @param[in] band band width in cells, for the text
197  * @param[in] slopes band slopes in the order xlo, xhi, ylo, yhi (-1 = no cells)
198  * @param[in] open whether each face is an inflow or outflow face
199  * @param[in] bc_names boundary type of each face, for the text
200  */
201 std::string
202 OpenFaceSlopeWarning (int lev, int band,
203  const amrex::Array<amrex::Real,4>& slopes,
204  const amrex::Array<bool,4>& open,
205  const amrex::Array<std::string,4>& bc_names);
206 
207 } // namespace erf_terrain_file
208 
209 #endif
const int nx
Definition: ERF_InitCustomPertVels_CloudChamber.H:14
const int ny
Definition: ERF_InitCustomPertVels_CloudChamber.H:15
const GpuArray< Real, AMREX_SPACEDIM > prob_lo
Definition: ERF_InitCustomPert_CloudChamber.H:33
const amrex::Real * prob_hi
Definition: ERF_InitCustomPert_DataAssimilation_ISV.H:17
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE TerrainCellDrops ComputeTerrainCellDrops(int i, int j, int k, const amrex::Array4< const amrex::Real > &z_nd) noexcept
Definition: ERF_TerrainDiffusionLimits.H:44
T erf_get_single_value(std::istream &is, int n, const std::string &fname)
Definition: ERF_TerrainFileChecks.H:45
@ T
Definition: ERF_IndexDefines.H:168
Definition: ERF_TerrainFileChecks.cpp:18
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real CellTerrainSlope(int i, int j, int k, const amrex::Array4< const amrex::Real > &z_nd, amrex::Real mfx, amrex::Real mfy, amrex::Real dxinv, amrex::Real dyinv) noexcept
Definition: ERF_TerrainFileChecks.H:166
std::string TableSummary(const std::string &fname, bool is_usgs, int nx, int ny, const Vector< Real > &x, const Vector< Real > &y, const Vector< Real > &z)
Definition: ERF_TerrainFileChecks.cpp:131
std::string TableProblem(bool is_usgs, int nx, int ny, const Vector< Real > &x, const Vector< Real > &y, const Vector< Real > &z, const GpuArray< Real, AMREX_SPACEDIM > &prob_lo, const GpuArray< Real, AMREX_SPACEDIM > &prob_hi, bool require_domain_coverage)
Definition: ERF_TerrainFileChecks.cpp:75
Array< Real, 4 > FaceBandSlopes(const MultiFab &z_phys_nd, const MultiFab &mf_mx, const MultiFab &mf_my, const Geometry &geom, int band)
Definition: ERF_TerrainFileChecks.cpp:350
const HeightTable & ReadHeightTable(const std::string &fname, bool is_usgs, const GpuArray< Real, AMREX_SPACEDIM > &prob_lo, const GpuArray< Real, AMREX_SPACEDIM > &prob_hi, bool require_domain_coverage)
Definition: ERF_TerrainFileChecks.cpp:331
constexpr amrex::Real open_face_slope_warn
Definition: ERF_TerrainFileChecks.H:151
std::string OpenFaceSlopeWarning(int lev, int band, const Array< Real, 4 > &slopes, const Array< bool, 4 > &open, const Array< std::string, 4 > &bc_names)
Definition: ERF_TerrainFileChecks.cpp:400
Definition: ERF_TerrainDiffusionLimits.H:29
amrex::Real dy_drop
Definition: ERF_TerrainDiffusionLimits.H:31
amrex::Real dx_drop
Definition: ERF_TerrainDiffusionLimits.H:30
Definition: ERF_TerrainFileChecks.H:80
int nx
Definition: ERF_TerrainFileChecks.H:81
amrex::Vector< amrex::Real > z
Definition: ERF_TerrainFileChecks.H:83
int ny
Definition: ERF_TerrainFileChecks.H:82
amrex::Vector< amrex::Real > y
Definition: ERF_TerrainFileChecks.H:83
amrex::Vector< amrex::Real > x
Definition: ERF_TerrainFileChecks.H:83