Browse Source

Fix issues found during testing of static and moving nests.

lon0
Bill Ladwig 7 years ago
parent
commit
06280e5cae
  1. 31
      src/wrf/interp.py
  2. 2
      src/wrf/latlonutils.py
  3. 32
      src/wrf/metadecorators.py
  4. 3
      src/wrf/util.py
  5. 106
      test/utests.py

31
src/wrf/interp.py

@ -272,15 +272,20 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64), @@ -272,15 +272,20 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
end_point_xy = None
pivot_point_xy = None
if timeidx is None:
if (latlon is True or is_latlon_pair(start_point) or
is_latlon_pair(pivot_point)):
if wrfin is not None:
is_moving = is_moving_domain(wrfin)
else:
is_moving = False
if timeidx is None:
if wrfin is not None:
# Moving nests aren't supported with ALL_TIMES because the
# domain could move outside of the cross section, which causes
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving_domain(wrfin):
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using lat/lon "
"cross sections because the domain could "
@ -288,6 +293,7 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64), @@ -288,6 +293,7 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
"You must request each time "
"individually.")
else:
# Domain not moving, just use 0
_timeidx = 0
# If using grid coordinates, then don't care about lat/lon
@ -295,7 +301,12 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64), @@ -295,7 +301,12 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
else:
_timeidx = 0
else:
if is_moving:
_timeidx = timeidx
else:
# When using non-moving nests, set the time to 0
# to avoid problems downstream
_timeidx = 0
if pivot_point is not None:
if pivot_point.lat is not None and pivot_point.lon is not None:
@ -472,15 +483,20 @@ def interpline(field2d, pivot_point=None, @@ -472,15 +483,20 @@ def interpline(field2d, pivot_point=None,
end_point_xy = None
pivot_point_xy = None
if timeidx is None:
if (latlon is True or is_latlon_pair(start_point) or
is_latlon_pair(pivot_point)):
if wrfin is not None:
is_moving = is_moving_domain(wrfin)
else:
is_moving = False
if timeidx is None:
if wrfin is not None:
# Moving nests aren't supported with ALL_TIMES because the
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving_domain(wrfin):
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using a lat/lon "
"line because the domain could "
@ -496,7 +512,12 @@ def interpline(field2d, pivot_point=None, @@ -496,7 +512,12 @@ def interpline(field2d, pivot_point=None,
else:
_timeidx = 0
else:
if is_moving:
_timeidx = timeidx
else:
# When using non-moving nests, set the time to 0
# to avoid problems downstream
_timeidx = 0
if pivot_point is not None:
if pivot_point.lat is not None and pivot_point.lon is not None:

2
src/wrf/latlonutils.py

@ -167,7 +167,7 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key): @@ -167,7 +167,7 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key):
# Only need one file and one time if the domain is not moving
if not is_moving:
if is_multi_time_req(timeidx):
# Always use the 0th time for non-moving domains to avoid problems
lat_timeidx = 0
if is_multi_file(wrfin):

32
src/wrf/metadecorators.py

@ -933,15 +933,20 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -933,15 +933,20 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
end_point_xy = None
pivot_point_xy = None
if timeidx is None:
if (inc_latlon is True or is_latlon_pair(start_point) or
is_latlon_pair(pivot_point)):
if wrfin is not None:
is_moving = is_moving_domain(wrfin)
else:
is_moving = False
if timeidx is None:
if wrfin is not None:
# Moving nests aren't supported with ALL_TIMES because the
# domain could move outside of the cross section, which causes
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving_domain(wrfin):
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using lat/lon "
"cross sections because the domain could "
@ -949,6 +954,7 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -949,6 +954,7 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
"You must request each time "
"individually.")
else:
# Domain not moving, just use 0
_timeidx = 0
# If using grid coordinates, then don't care about lat/lon
@ -956,7 +962,12 @@ def _set_cross_meta(wrapped, instance, args, kwargs): @@ -956,7 +962,12 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
else:
_timeidx = 0
else:
if is_moving:
_timeidx = timeidx
else:
# When using non-moving nests, set the time to 0
# to avoid problems downstream
_timeidx = 0
if pivot_point is not None:
if pivot_point.lat is not None and pivot_point.lon is not None:
@ -1176,15 +1187,20 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1176,15 +1187,20 @@ def _set_line_meta(wrapped, instance, args, kwargs):
end_point_xy = None
pivot_point_xy = None
if timeidx is None:
if (inc_latlon is True or is_latlon_pair(start_point) or
is_latlon_pair(pivot_point)):
if wrfin is not None:
is_moving = is_moving_domain(wrfin)
else:
is_moving = False
if timeidx is None:
if wrfin is not None:
# Moving nests aren't supported with ALL_TIMES because the
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving_domain(wrfin):
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using a lat/lon "
"line because the domain could "
@ -1200,7 +1216,13 @@ def _set_line_meta(wrapped, instance, args, kwargs): @@ -1200,7 +1216,13 @@ def _set_line_meta(wrapped, instance, args, kwargs):
else:
_timeidx = 0
else:
if is_moving:
_timeidx = timeidx
else:
# When using non-moving nests, set the time to 0
# to avoid problems downstream
_timeidx = 0
if pivot_point is not None:
if pivot_point.lat is not None and pivot_point.lon is not None:

3
src/wrf/util.py

@ -3893,7 +3893,10 @@ def is_latlon_pair(pair): @@ -3893,7 +3893,10 @@ def is_latlon_pair(pair):
:obj:`bool`: True if the pair is a lat/lon pair.
"""
if pair is not None:
return (pair.lat is not None and pair.lon is not None)
else:
return False

106
test/utests.py

@ -15,9 +15,11 @@ from wrf.util import is_multi_file @@ -15,9 +15,11 @@ from wrf.util import is_multi_file
NCL_EXE = "/Users/ladwig/miniconda2/envs/ncl_build/bin/ncl"
NCARG_ROOT = "/Users/ladwig/miniconda2/envs/ncl_build"
#TEST_FILE = "/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00"
DIR = "/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest"
DIRS = ["/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest",
"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/static_nest"]
PATTERN = "wrfout_d02_*"
REF_NC_FILE = "/tmp/wrftest.nc"
REF_NC_FILES = ["/tmp/wrftest_moving.nc", "/tmp/wrftest_static.nc"]
NEST = ["moving", "static"]
# Python 3
if sys.version_info > (3,):
@ -36,15 +38,17 @@ def setUpModule(): @@ -36,15 +38,17 @@ def setUpModule():
ncl_script = os.path.join(os.path.dirname(this_path),
"ncl_get_var.ncl")
cmd = "%s %s 'dir=\"%s\"' 'pattern=\"%s\"' 'out_file=\"%s\"'" % (NCL_EXE,
for dir,outfile in zip(DIRS, REF_NC_FILES):
cmd = "%s %s 'dir=\"%s\"' 'pattern=\"%s\"' 'out_file=\"%s\"'" % (
NCL_EXE,
ncl_script,
DIR,
dir,
PATTERN,
REF_NC_FILE)
outfile)
print cmd
if not os.path.exists(REF_NC_FILE):
if not os.path.exists(outfile):
status = subprocess.call(cmd, shell=True)
if (status != 0):
raise RuntimeError("NCL script failed. Could not set up test.")
@ -377,6 +381,9 @@ def make_interp_test(varname, dir, pattern, referent, multi=False, @@ -377,6 +381,9 @@ def make_interp_test(varname, dir, pattern, referent, multi=False,
# Only do this for the non-multi case, since the domain
# might be moving
if not multi:
if lats.ndim > 2: # moving nest
lats = lats[0,:]
lons = lons[0,:]
ll_point = ll_points(lats, lons)
@ -430,7 +437,7 @@ def make_interp_test(varname, dir, pattern, referent, multi=False, @@ -430,7 +437,7 @@ def make_interp_test(varname, dir, pattern, referent, multi=False,
nt.assert_allclose(to_np(ht_cross),
to_np(ref_ht_vertcross2), atol=.01)
idxs = (0, slice(None)) if multi else (slice(None),)
idxs = (0, slice(None)) if lats.ndim > 2 else (slice(None),)
start_lat = np.amin(lats[idxs]) + .25*(np.amax(lats[idxs]) - np.amin(lats[idxs]))
end_lat = np.amin(lats[idxs]) + .65*(np.amax(lats[idxs]) - np.amin(lats[idxs]))
@ -501,6 +508,7 @@ def make_interp_test(varname, dir, pattern, referent, multi=False, @@ -501,6 +508,7 @@ def make_interp_test(varname, dir, pattern, referent, multi=False,
lats = t2.coords["XLAT"]
lons = t2.coords["XLONG"]
if multi:
if lats.ndim > 2: # moving nest
lats = lats[0,:]
lons = lons[0,:]
@ -852,6 +860,14 @@ def make_latlon_test(testid, dir, pattern, referent, single, @@ -852,6 +860,14 @@ def make_latlon_test(testid, dir, pattern, referent, single,
nt.assert_allclose(to_np(xy), ref)
if xy.ndim > 2:
# Moving nest
is_moving = True
numtimes = xy.shape[-2]
else:
is_moving = False
numtimes = 1
for tidx in range(9):
# Next make sure the 'proj' version works
@ -859,7 +875,12 @@ def make_latlon_test(testid, dir, pattern, referent, single, @@ -859,7 +875,12 @@ def make_latlon_test(testid, dir, pattern, referent, single,
xy_proj = ll_to_xy_proj(lats, lons, as_int=False,
**projparams)
nt.assert_allclose(to_np(xy_proj), to_np(xy[:,tidx,:]))
if is_moving:
idxs = (slice(None), tidx, slice(None))
else:
idxs = (slice(None),)
nt.assert_allclose(to_np(xy_proj), to_np(xy[idxs]))
else:
# i_s, j_s taken from NCL script, just hard-coding for now
@ -887,13 +908,25 @@ def make_latlon_test(testid, dir, pattern, referent, single, @@ -887,13 +908,25 @@ def make_latlon_test(testid, dir, pattern, referent, single,
nt.assert_allclose(to_np(ll), ref)
if ll.ndim > 2:
# Moving nest
is_moving = True
numtimes = ll.shape[-2]
else:
is_moving = False
numtimes = 1
for tidx in range(9):
for tidx in range(numtimes):
# Next make sure the 'proj' version works
projparams = extract_proj_params(wrfin, timeidx=tidx)
ll_proj = xy_to_ll_proj(x_s, y_s, **projparams)
nt.assert_allclose(to_np(ll_proj), to_np(ll[:,tidx,:]))
if is_moving:
idxs = (slice(None), tidx, slice(None))
else:
idxs = (slice(None),)
nt.assert_allclose(to_np(ll_proj), to_np(ll[idxs]))
return test
@ -924,6 +957,7 @@ if __name__ == "__main__": @@ -924,6 +957,7 @@ if __name__ == "__main__":
interp_methods = ["interplevel", "vertcross", "interpline", "vinterp"]
latlon_tests = ["xy", "ll"]
for dir, ref_nc_file, nest in zip(DIRS, REF_NC_FILES, NEST):
try:
import netCDF4
except ImportError:
@ -933,32 +967,32 @@ if __name__ == "__main__": @@ -933,32 +967,32 @@ if __name__ == "__main__":
if var in ignore_vars:
continue
test_func1 = make_test(var, DIR, PATTERN, REF_NC_FILE)
test_func2 = make_test(var, DIR, PATTERN, REF_NC_FILE, multi=True)
setattr(WRFVarsTest, 'test_{0}'.format(var), test_func1)
setattr(WRFVarsTest, 'test_multi_{0}'.format(var), test_func2)
test_func1 = make_test(var, dir, PATTERN, ref_nc_file)
test_func2 = make_test(var, dir, PATTERN, ref_nc_file, multi=True)
setattr(WRFVarsTest, 'test_{0}_{1}'.format(nest,var), test_func1)
setattr(WRFVarsTest, 'test_{0}_multi_{1}'.format(nest,var), test_func2)
for method in interp_methods:
test_interp_func1 = make_interp_test(method, DIR, PATTERN,
REF_NC_FILE)
test_interp_func2 = make_interp_test(method, DIR, PATTERN,
REF_NC_FILE, multi=True)
setattr(WRFInterpTest, 'test_{0}'.format(method),
test_interp_func1 = make_interp_test(method, dir, PATTERN,
ref_nc_file)
test_interp_func2 = make_interp_test(method, dir, PATTERN,
ref_nc_file, multi=True)
setattr(WRFInterpTest, 'test_{0}_{1}'.format(nest,method),
test_interp_func1)
setattr(WRFInterpTest, 'test_multi_{0}'.format(method),
setattr(WRFInterpTest, 'test_{0}_multi_{1}'.format(nest,method),
test_interp_func2)
for testid in latlon_tests:
for single in (True, False):
for multi in (True, False):
test_ll_func = make_latlon_test(testid, DIR, PATTERN,
REF_NC_FILE,
test_ll_func = make_latlon_test(testid, dir, PATTERN,
ref_nc_file,
single=single,
multi=multi,
pynio=False)
multistr = "" if not multi else "_multi"
singlestr = "_nosingle" if not single else "_single"
test_name = "test_{}{}{}".format(testid, singlestr,
test_name = "test_{}_{}{}{}".format(nest, testid, singlestr,
multistr)
setattr(WRFLatLonTest, test_name, test_ll_func)
@ -971,34 +1005,34 @@ if __name__ == "__main__": @@ -971,34 +1005,34 @@ if __name__ == "__main__":
if var in ignore_vars:
continue
test_func1 = make_test(var, DIR, PATTERN, REF_NC_FILE, pynio=True)
test_func2 = make_test(var, DIR, PATTERN, REF_NC_FILE, multi=True,
test_func1 = make_test(var, dir, PATTERN, ref_nc_file, pynio=True)
test_func2 = make_test(var, dir, PATTERN, ref_nc_file, multi=True,
pynio=True)
setattr(WRFVarsTest, 'test_pynio_{0}'.format(var), test_func1)
setattr(WRFVarsTest, 'test_pynio_multi_{0}'.format(var),
setattr(WRFVarsTest, 'test_pynio_{0}_{1}'.format(nest,var), test_func1)
setattr(WRFVarsTest, 'test_pynio_{0}_multi_{1}'.format(nest,var),
test_func2)
for method in interp_methods:
test_interp_func1 = make_interp_test(method, DIR, PATTERN,
REF_NC_FILE)
test_interp_func2 = make_interp_test(method, DIR, PATTERN,
REF_NC_FILE, multi=True)
setattr(WRFInterpTest, 'test_pynio_{0}'.format(method),
test_interp_func1 = make_interp_test(method, dir, PATTERN,
ref_nc_file)
test_interp_func2 = make_interp_test(method, dir, PATTERN,
ref_nc_file, multi=True)
setattr(WRFInterpTest, 'test_pynio_{0}_{1}'.format(nest,method),
test_interp_func1)
setattr(WRFInterpTest, 'test_pynio_multi_{0}'.format(method),
setattr(WRFInterpTest, 'test_pynio_{0}_multi_{1}'.format(nest,method),
test_interp_func2)
for testid in latlon_tests:
for single in (True, False):
for multi in (True, False):
test_ll_func = make_latlon_test(testid, DIR, PATTERN,
REF_NC_FILE,
test_ll_func = make_latlon_test(testid, dir, PATTERN,
ref_nc_file,
single=single,
multi=multi,
pynio=False)
multistr = "" if not multi else "_multi"
singlestr = "_nosingle" if not single else "_single"
test_name = "test_pynio_{}{}{}".format(testid,
test_name = "test_pynio_{}_{}{}{}".format(nest, testid,
singlestr,
multistr)
setattr(WRFLatLonTest, test_name, test_ll_func)

Loading…
Cancel
Save