Skip to content

Commit 7c63d06

Browse files
authored
Initialize non-zero base state for wrfinput made from ideal.exe (#3730)
1 parent c75823f commit 7c63d06

2 files changed

Lines changed: 64 additions & 45 deletions

File tree

Source/Initialization/ERF_InitFromWRFInput.cpp

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -163,58 +163,58 @@ read_base_state_params_from_wrfinput (const std::string& fname,
163163
if (ParallelDescriptor::IOProcessor()) {
164164
auto ncf = ncutils::NCFile::open(fname, NC_CLOBBER | NC_NETCDF4);
165165

166+
// Remember what was passed in so we can fall back to it below
167+
const Real T00_def = T00;
168+
const Real P00_def = P00;
169+
const Real TLP_def = TLP;
170+
const Real TISO_def = TISO;
171+
const Real TLP_STRAT_def = TLP_STRAT;
172+
const Real P_STRAT_def = P_STRAT;
173+
166174
std::vector<size_t> shape;
167175
std::vector<size_t> start;
168-
int success = ncf.has_var("T00");
169-
if (success) {
170-
Print() << "Reading T00 from wrfinput\n";
171-
shape = ncf.var("T00").shape();
172-
start.resize(shape.size(), 0);
173-
ncf.var("T00").get(&T00 ,start, shape);
174-
}
175-
176-
success = ncf.has_var("P00");
177-
if (success) {
178-
Print() << "Reading P00 from wrfinput\n";
179-
shape = ncf.var("P00").shape();
180-
start.resize(shape.size(), 0);
181-
ncf.var("P00").get(&P00 ,start, shape);
182-
}
183-
184-
success = ncf.has_var("TLP");
185-
if (success) {
186-
Print() << "Reading TLP from wrfinput\n";
187-
shape = ncf.var("TLP").shape();
176+
auto read_scalar = [&] (const std::string& name, Real& val)
177+
{
178+
if (!ncf.has_var(name)) return;
179+
Print() << "Reading " << name << " from wrfinput\n";
180+
shape = ncf.var(name).shape();
181+
start.clear();
188182
start.resize(shape.size(), 0);
189-
ncf.var("TLP").get(&TLP ,start, shape);
190-
}
183+
ncf.var(name).get(&val, start, shape);
184+
};
191185

192-
success = ncf.has_var("TISO");
193-
if (success) {
194-
Print() << "Reading TISO from wrfinput\n";
195-
shape = ncf.var("TISO").shape();
196-
start.resize(shape.size(), 0);
197-
ncf.var("TISO").get(&TISO ,start, shape);
198-
}
186+
read_scalar("T00" , T00);
187+
read_scalar("P00" , P00);
188+
read_scalar("TLP" , TLP);
189+
read_scalar("TISO" , TISO);
190+
read_scalar("TLP_STRAT", TLP_STRAT);
191+
read_scalar("P_STRAT" , P_STRAT);
199192

200-
success = ncf.has_var("TLP_STRAT");
201-
if (success) {
202-
Print() << "Reading TLP_STRAT from wrfinput\n";
203-
shape = ncf.var("TLP_STRAT").shape();
204-
start.resize(shape.size(), 0);
205-
ncf.var("TLP_STRAT").get(&TLP_STRAT ,start, shape);
206-
}
193+
ncf.close();
207194

208-
success = ncf.has_var("P_STRAT");
209-
if (success) {
210-
Print() << "Reading P_STRAT from wrfinput\n";
211-
shape = ncf.var("P_STRAT").shape();
212-
start.resize(shape.size(), 0);
213-
ncf.var("P_STRAT").get(&P_STRAT ,start, shape);
195+
// Idealized WRF cases (and some hand-built wrfinput files) declare these
196+
// variables but leave them zero-filled. T00, P00 and TISO are absolute
197+
// temperatures/pressures, so a non-positive value is never meaningful; if
198+
// any of them is bad we discard the whole group and keep the defaults.
199+
// (TLP, TLP_STRAT and P_STRAT may legitimately be zero, so they are only
200+
// reset alongside a bad T00/P00/TISO.)
201+
const bool params_ok = std::isfinite(T00) && (T00 > Real(0)) &&
202+
std::isfinite(P00) && (P00 > Real(0)) &&
203+
std::isfinite(TISO) && (TISO > Real(0)) &&
204+
std::isfinite(TLP) && std::isfinite(TLP_STRAT) &&
205+
std::isfinite(P_STRAT);
206+
207+
if (!params_ok) {
208+
Print() << "WARNING: WRF base state parameters read from " << fname
209+
<< " are invalid: (T00, P00, TLP, TISO, TLP_STRAT, P_STRAT) = ("
210+
<< T00 << ", " << P00 << ", " << TLP << ", " << TISO << ", "
211+
<< TLP_STRAT << ", " << P_STRAT << ")\n";
212+
Print() << " T00, P00 and TISO must all be positive and finite; "
213+
"reverting to ERF defaults.\n";
214+
T00 = T00_def; P00 = P00_def; TLP = TLP_def;
215+
TISO = TISO_def; TLP_STRAT = TLP_STRAT_def; P_STRAT = P_STRAT_def;
214216
}
215217

216-
ncf.close();
217-
218218
Print() << "WRF base state parameters (T00, P00, TLP, TISO, TLP_STRAT, P_STRAT) are: ("
219219
<< T00 << ", " << P00 << ", " << TLP << ", " << TISO << ", " << TLP_STRAT << ", "
220220
<< P_STRAT << ") \n";
@@ -1629,6 +1629,12 @@ init_base_state_from_wrfinput (const Box& subdomain,
16291629
int k_dom_lo = dom_lo.z;
16301630
int k_dom_hi = dom_hi.z;
16311631

1632+
// The vertical integration below is seeded with the surface values (P00,T00),
1633+
// so these must be valid regardless of whether ALB was present in the file
1634+
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(std::isfinite(P00) && (P00 > Real(0)) &&
1635+
std::isfinite(T00) && (T00 > Real(0)),
1636+
"Cannot rebalance the WRF base state: P00 and T00 must be positive");
1637+
16321638
#ifdef AMREX_USE_FLOAT
16331639
Real tol = Real(1.0e-6);
16341640
#else

Source/Utils/ERF_HSEUtils.H

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,22 @@ namespace HSEutils
5555
Real& F,
5656
const bool& maintain_Th)
5757
{
58+
// A non-finite residual (or a non-positive initial guess) would make the
59+
// convergence test below evaluate to false on the very first pass, so we
60+
// would silently return the initial guess and leave, e.g., an all-zero
61+
// base state. Trap that here rather than propagating it downstream.
62+
if (!(P > amrex::Real(0)) || !(rd > amrex::Real(0)) || !std::isfinite(F)) {
63+
AMREX_DEVICE_PRINTF("ERROR: HSE Newton started from an invalid state: P = %e, rd = %e, F = %e\n",
64+
double(P), double(rd), double(F));
65+
AMREX_DEVICE_PRINTF(" Check the surface pressure/temperature used to seed the integration%s\n", "");
66+
}
67+
AMREX_ALWAYS_ASSERT(P > amrex::Real(0) && rd > amrex::Real(0) && std::isfinite(F));
68+
5869
int iter=0;
5970
int max_iter=20;
60-
while (std::abs(F)>m_tol && iter<max_iter) {
71+
// Written as !(|F| <= tol) so that a NaN residual enters the loop instead
72+
// of being mistaken for convergence
73+
while (!(std::abs(F)<=m_tol) && iter<max_iter) {
6174
// Compute change in pressure
6275
Real dRdP = (maintain_Th) ? iGamma * rd / P : rd / P;
6376
Real dFdp = one + myhalf*dRdP*g*dz;

0 commit comments

Comments
 (0)