import numpy as np
import xarray as xr
import netCDF4 as nc
import datetime as dtm
[docs]
def read(
self,
name,
varnames,
dates,
files,
interpol_flx=False,
comp_type=None,
ddi=None,
**kwargs
):
"""Get initial and boundary conditions from pre-computed values
Args:
self: the wrfchem_icbc plugin
name: the name of the component
dates: list of dates to extract
interpol_flx (bool): if True, interpolates fluxes at time t from
values of surrounding available files
comp_type: 'inicond' or 'latcond'
"""
# Check the type of limit condition to check
if comp_type is None:
raise Exception(
"Trying to read limit conditions for wrfchem, "
"but did not specify the type"
)
# Read initial conditions
if comp_type == "inicond":
raise NotImplementedError("To do: implement 'read' for inicond")
# ic_file = files[0]
# ds = xr.open_dataset(ic_file)
# data = ds[var2extract][:]
#
# # -- Add fake lat dimensions at the end (TODO: remove 1e9)
# # data = data.values[:, :, np.newaxis, :] / 1e9
# data = data.values[:, :, np.newaxis, :]
#
# xmod = xr.DataArray(
# data,
# coords={"time": [np.min(dates)]},
# dims=("time", "lev", "lat", "lon"),
# )
# Read Lateral boundary conditions
elif comp_type == "latcond":
if len(files)>1:
raise ValueError("There should only be one latcond file")
ncf = nc.Dataset(files[0])
# "datef" requested? If not in file (which is how I set
# up the wrfchem model mapper), have to compute from bt.
# Unpack requested times
times_req = sorted(set([x for y in dates for x in y]))
# Get times in file
times_char = ncf["Times"][:].astype(str)
times_str = np.apply_along_axis(lambda x: "".join(x), 1, times_char)
times_file = [dtm.datetime.strptime(t, "%Y-%m-%d_%H:%M:%S") for t in times_str]
# Compare requested times to those in file
# Can do the following cases:
# Case 1: All requested times are in the file
if set(times_req)==set(times_file):
ind_copy = range(len(times_file))
tend = False
# Case 2: Requesting one more date than in file
# -> Compute from tendency variables
# (This should be the usual case)
elif (set(times_req[:-1])==set(times_file)) & \
((times_file[-1] + (times_file[-1]-times_file[-2]))==times_req[-1]):
ind_copy = range(len(times_file))
tend = True
dt = (times_file[-1]-times_file[-2]).total_seconds()
else:
raise ValueError("Times available in latcond file " + \
"are not as expected")
varname = getattr(self.chemistry.acspecies, name).varname
# Read all values
b = dict(
XS = ncf[varname + "_BXS"][:],
XE = ncf[varname + "_BXE"][:],
YS = ncf[varname + "_BYS"][:],
YE = ncf[varname + "_BYE"][:])
if tend:
btf = dict(
XS = ncf[varname + "_BTXS"][-1, ...],
XE = ncf[varname + "_BTXE"][-1, ...],
YS = ncf[varname + "_BTYS"][-1, ...],
YE = ncf[varname + "_BTYE"][-1, ...])
bdy_width = len(ncf.dimensions["bdy_width"])
ncf.close()
# Arrange the data into a single variable as defined
# in domains/wrfchem/get_sides.py (this is much the
# same as in write.py).
icbc = np.zeros((len(dates), ) + \
(len(self.domain.sigma_a)-1, ) + \
(self.domain.zlon_side.shape))
icbc = icbc*np.nan
nlon2d = self.domain.zlon2d.shape[1]
nlat2d = self.domain.zlon2d.shape[0]
# Fill variable
indi = 0
for nw in range(bdy_width):
inde = indi + nlon2d
icbc[ind_copy,:,0,indi:inde] = b["YS"][:,nw,:,:]
if tend:
icbc[-1, :,0,indi:inde] = b["YS"][-1,nw,:,:] + \
dt*btf["YS"][nw,:,:]
indi = inde
inde = indi + nlon2d
icbc[ind_copy,:,0,indi:inde] = b["YE"][:,nw,:,:]
if tend:
icbc[-1,:,0,indi:inde] = b["YE"][-1,nw,:,:] + \
dt*btf["YE"][nw,:,:]
indi = inde
inde = indi + nlat2d
icbc[ind_copy,:,0,indi:inde] = b["XS"][:,nw,:,:]
if tend:
icbc[-1,:,0,indi:inde] = b["XS"][-1,nw,:,:] + \
dt*btf["XS"][nw,:,:]
indi = inde
inde = indi + nlat2d
icbc[ind_copy,:,0,indi:inde] = b["XE"][:,nw,:,:]
if tend:
icbc[-1,:,0,indi:inde] = b["XE"][-1,nw,:,:] + \
dt*btf["XE"][nw,:,:]
indi = inde
# Put the data into an xarray
xmod = xr.DataArray(
icbc, coords={"time": times_req}, dims=("time", "lev", "lat", "lon")
)
else:
raise Exception(
"Could not recognize the type of file "
"to read in wrfchem: {}".format(comp_type)
)
return xmod