diff --git a/README.md b/README.md
index 9425d50..aafac32 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,25 @@
-# ERFtools
-A collection of scripts for facilitating the usage of ERF.
+# ERF Tools
+A collection of Python-based modules and scripts for facilitating the usage of
+the Energy Research and Forecasting (ERF) model.
+
+## Installation
+
+Clone and create a conda (or mamba) environment:
+```shell
+git clone https://github.com/erf-model/erftools.git
+cd erftools
+conda create -n erftools python=3.9
+conda activate erftools
+```
+
+Then, install with:
+```shell
+pip install -e . # editable install
+```
+or install with all optional dependencies:
+```shell
+pip install -e .[all]
+```
## Examples
@@ -7,15 +27,24 @@ A collection of scripts for facilitating the usage of ERF.
```python
from erftools.preprocessing import WRFInputDeck
wrf = WRFInputDeck('namelist.input')
+wrf.write_inputfile('inputs')
+
+# optional: extract data from wrfinput
wrf.process_initial_conditions('wrfinput_d01',
landuse_table_path='/Users/equon/WRF/run/LANDUSE.TBL',
write_hgt='terrain_height.txt',
write_z0='roughness_height.txt')
-wrf.write_inputfile('inputs')
+```
+
+The namelist conversion may also be accomplished from the command line:
+```bash
+wrf_namelist_to_erf namelist.input inputs
```
### Postprocessing data logs
-Data logs are output with the `erf.data_log` param and can include time histories of surface conditions and planar averaged profiles (e.g., for idealized LES simulations)
+Data logs are output with the `erf.data_log` param and can include time
+histories of surface conditions and planar averaged profiles (e.g., for
+idealized LES simulations)
```python
from erftools.postprocessing import DataLog
log = DataLog(f'{simdir}/surf_hist.dat',
@@ -31,6 +60,8 @@ print(log.ds) # data are stored in an xarray dataset
Some notes and recommendations:
-* An aspirational goal is to contribute code that can be used as in the examples above, with clear, intuitive naming and following PEP-8 style as a set of guidelines rather than gospel.
-* To avoid duplication, model constants are defined in `erf.constants`, which should replicate `ERF/Source/ERF_Constants.H`.
-* In the same vein, equation of state evaluations are defined in `erf.EOS`, which should replicate `ERF/Source/Utils/ERF_EOS.H`.
+* An aspirational goal is to contribute code that can be used as in the examples above, with clear, intuitive naming.
+* To avoid duplication, model constants are defined in `erftools.constants`, which should replicate `ERF/Source/ERF_Constants.H`.
+* In the same vein, equation of state evaluations are defined in `erftools.utils.EOS`, which should replicate `ERF/Source/Utils/ERF_EOS.H`.
+* Other utilities for calculating/deriving/diagnosing quantities of interest are also in `erftools.utils.*`
+* Please follow PEP-8 style--as a set of guidelines rather than gospel--to facilitate code usage and maintenance by the community.
diff --git a/erftools/data/ozone_CAM.nc b/erftools/data/ozone_CAM.nc
new file mode 100644
index 0000000..7810df1
Binary files /dev/null and b/erftools/data/ozone_CAM.nc differ
diff --git a/erftools/parms.py b/erftools/erfparms.py
similarity index 89%
rename from erftools/parms.py
rename to erftools/erfparms.py
index fc9fc1e..eeb8a82 100644
--- a/erftools/parms.py
+++ b/erftools/erfparms.py
@@ -16,12 +16,23 @@ def check_unknown_params(data_dict, dataclass_type):
provided_params = set(data_dict.keys())
unknown_params = list(provided_params - known_params)
+ # ignore MOST settings
+ unknown_params = [param for param in unknown_params
+ if not param.startswith('most.')]
+
+ # ignore refinement indicators
if 'refinement_indicators' in data_dict:
- boxes = data_dict['refinement_indicators'].split()
- for box in boxes:
+ refine_names = data_dict['refinement_indicators']
+ if isinstance(refine_names, str):
+ refine_names = [refine_names]
+ for box in refine_names:
unknown_params = [param for param in unknown_params
if not param.startswith(f'{box}.')]
+ # ignore nc_init_file_*
+ unknown_params = [param for param in unknown_params
+ if not param.startswith('nc_init_file_')]
+
if unknown_params:
warnings.warn(f'Non-standard {dataclass_type.__name__} ignored: {unknown_params}')
@@ -33,7 +44,6 @@ class AMRParms:
max_level: int = 0
ref_ratio: Union[int,List[int]] = 2
ref_ratio_vect: List[int] = field(default_factory=list)
- regrid_int: int = -1
v: int = 0 # verbosity
@@ -125,6 +135,7 @@ class ERFParms:
# Refinement
refinement_indicators: Union[str,List[str]] = field(default_factory=list)
+ regrid_int: int = -1
# Grid Stretching
grid_stretching_ratio: float = 1.
@@ -240,9 +251,6 @@ class ERFParms:
rayleigh_dampcoef: float = 0.2
rayleigh_zdamp: float = 500.
- # BCs
- use_explicit_most: bool = False
-
# Initialization
init_type: str = 'None'
init_sounding_ideal: bool = False
@@ -263,6 +271,27 @@ class ERFParms:
# Radiation
radiation_model: str = 'None'
+ rad_freq_in_steps: int = 1
+ rad_write_fluxes: bool = False
+ #nswbands: int = 14
+ #nlwbands: int = 16
+ #nswgpts: int = 224
+ #nlwgpts: int = 256
+ co2vmr: float = 0.00036 # from DevTests/Radiation
+ o3vmr: Union[float,List[float]] = 1.887e-7 # default
+ n2ovmr: float = 3.2e-7 # from DevTests/Radiation
+ covmr: float = 1.5e-7 # from DevTests/Radiation
+ ch4vmr: float = 1.7e-6 # from DevTests/Radiation
+ o2vmr: float = 0.209 # default
+ n2vmr: float = 0.7906 # default
+ rrtmgp_file_path: str = './'
+ #rrtmgp_coeffs_sw: str = 'rrtmgp-data-sw-g224-2018-12-04.nc'
+ #rrtmgp_coeffs_lw: str = 'rrtmgp-data-lw-g256-2018-12-04.nc'
+ #rrtmgp_cloud_optics_sw: str = 'rrtmgp-cloud-optics-coeffs-sw.nc'
+ #rrtmgp_cloud_optics_lw: str = 'rrtmgp-cloud-optics-coeffs-lw.nc'
+
+ # Land Surface
+ land_surface_model: str = 'None'
def __post_init__(self):
if self.anelastic:
@@ -321,7 +350,7 @@ def __post_init__(self):
les_types = self.les_type if isinstance(self.les_type,list) else [self.les_type]
for turbmodel in les_types:
- assert turbmodel in ['None','Smagorinsky','Deardorff'], \
+ assert turbmodel in ['None','Smagorinsky','Smagorinsky2D','Deardorff'], \
f'Unexpected erf.les_type={turbmodel}'
if any([turbmodel == 'Smagorinsky' for turbmodel in les_types]):
smag_Cs = self.Cs if isinstance(self.Cs,list) else len(les_types)*[self.Cs]
@@ -329,7 +358,7 @@ def __post_init__(self):
pbl_types = self.pbl_type if isinstance(self.pbl_type,list) else [self.pbl_type]
for pblscheme in pbl_types:
- assert pblscheme in ['None','MYNN25','YSU'], \
+ assert pblscheme in ['None','MYJ','MYNN25','MRF','YSU'], \
f'Unexpected erf.pbl_type={pblscheme}'
assert self.abl_driver_type in \
diff --git a/erftools/inputs.py b/erftools/inputs.py
index 8162af2..0fcc895 100644
--- a/erftools/inputs.py
+++ b/erftools/inputs.py
@@ -1,10 +1,14 @@
import sys
import warnings
+from datetime import datetime
+from dateutil import parser
+
+import click
import contextlib
import numpy as np
# parameters parsed by AMReX's ParmParse
-from .parms import AMRParms, GeometryParms, ERFParms, check_unknown_params
+from .erfparms import AMRParms, GeometryParms, ERFParms, check_unknown_params
def parmparse(prefix, ppdata):
@@ -37,6 +41,14 @@ def list_to_str(mylist,dtype=None):
def strs_to_str(mylist):
return ' '.join([s.strip('"').strip("'") for s in mylist])
+def to_datetime(dt):
+ # ensure that we have a datetime object, parse if needed
+ if isinstance(dt, datetime):
+ return dt
+ elif isinstance(dt, list):
+ assert len(dt) == 2, 'expected date string + time string'
+ dt = ' '.join(dt)
+ return parser.parse(dt)
class ERFInputs(object):
"""Input data container with validation and output"""
@@ -50,8 +62,13 @@ def __init__(self,inpfile=None,**ppdata):
self.max_step = int(ppdata.get('max_step',-1))
self.start_time = float(ppdata.get('start_time',0.))
self.stop_time = float(ppdata.get('stop_time',1e34))
- self.start_date = ppdata.get('start_date',None)
- self.stop_date = ppdata.get('stop_date',None)
+
+ self.start_datetime = ppdata.get('start_datetime',None)
+ if self.start_datetime is not None:
+ self.start_datetime = to_datetime(self.start_datetime)
+ self.stop_datetime = ppdata.get('stop_datetime',None)
+ if self.stop_datetime is not None:
+ self.stop_datetime = to_datetime(self.stop_datetime)
# read amr, geometry, and erf inputs
amrparms = parmparse('amr',ppdata)
@@ -128,7 +145,7 @@ def read_bcs(self,ppdata):
assert 'zhi.type' in ppdata.keys()
self.zlo = parmparse('zlo',ppdata)
self.zhi = parmparse('zhi',ppdata)
- if self.zlo['type'] == 'MOST':
+ if self.zlo['type'] == 'surface_layer':
self.most = parmparse('erf.most',ppdata)
def read_refinement(self,ppdata):
@@ -164,7 +181,9 @@ def read_refinement(self,ppdata):
self.refine[box][test] = thresh
def validate(self):
- # additional validation that depends on different parmparse types
+ """Additional validation (outside of what is performed in
+ erfparms.*) that depends on different parmparse tables
+ """
if self.erf.terrain_type.lower() != 'none':
if self.erf.terrain_z_levels:
nz = self.amr.n_cell[2]
@@ -178,19 +197,22 @@ def validate(self):
f' will be inactive with'
f' amr.max_level={self.amr.max_level}')
if 'field_name' in refineparams and \
- self.amr.regrid_int <= 0:
+ self.erf.regrid_int <= 0:
warnings.warn(f'{box} dynamic refinement will be inactive'
- f' with amr.regrid_int={self.amr.regrid_int}')
+ f' with erf.regrid_int={self.erf.regrid_int}')
+
+ if isinstance(self.erf.o3vmr, list):
+ assert len(self.erf.o3vmr) == self.amr.n_cell[2]
def write(self,fpath=None):
with open_file_or_stdout(fpath) as f:
f.write('# ------------------------------- INPUTS TO ERF -------------------------------\n')
f.write('# written by erftools.inputs (https://github.com/erf-model/erftools)\n')
- if self.start_date and self.stop_date:
+ if self.start_datetime and self.stop_datetime:
f.write(f"""
max_step = {self.max_step}
-start_datetime = {self.start_date} # epoch time: {self.start_time} s
-stop_datetime = {self.stop_date} # epoch time: {self.stop_time} s
+start_datetime = {self.start_datetime} # epoch time: {self.start_time} s
+stop_datetime = {self.stop_datetime} # epoch time: {self.stop_time} s
""")
else:
f.write(f"""
@@ -238,14 +260,15 @@ def write(self,fpath=None):
if hasattr(self,'zlo'):
f.write('\n')
write_bc(f,'zlo',self.zlo)
- if self.zlo['type'] == 'MOST':
+ if self.zlo['type'] == 'surface_layer':
for key,val in self.most.items():
f.write(f'erf.most.{key} = {val}\n')
write_bc(f,'zhi',self.zhi)
########################################
f.write('\n# TIME STEP CONTROL\n')
- f.write(f'erf.substepping_type = {self.erf.substepping_type}\n')
+ if self.erf.substepping_type != 'implicit':
+ f.write(f'erf.substepping_type = {self.erf.substepping_type}\n')
if self.erf.fixed_dt > 0:
f.write(f'erf.fixed_dt = {self.erf.fixed_dt}\n')
else:
@@ -270,7 +293,7 @@ def write(self,fpath=None):
########################################
f.write('\n# REFINEMENT / REGRIDDING\n')
f.write(f'amr.max_level = {self.amr.max_level}\n')
- f.write(f'amr.regrid_int = {self.amr.regrid_int}\n')
+ f.write(f'erf.regrid_int = {self.erf.regrid_int}\n')
if len(self.erf.refinement_indicators) > 0:
if len(self.amr.ref_ratio_vect) > 0:
f.write('amr.ref_ratio_vect = '
@@ -337,14 +360,15 @@ def write(self,fpath=None):
f.write('\n# PLOTFILES\n')
if self.erf.plotfile_type != 'amrex':
f.write(f'erf.plotfile_type = {self.erf.plotfile_type}\n')
- if (self.erf.plot_int_1 > 0) or (self.erf.plot_per_1 > 0):
- f.write(f'erf.plot_file_1 = {self.erf.plot_file_1}\n')
- if self.erf.plot_per_1 > 0:
- f.write(f'erf.plot_per_1 = {self.erf.plot_per_1}\n')
- else:
- f.write(f'erf.plot_int_1 = {self.erf.plot_int_1}\n')
- f.write('erf.plot_vars_1 = '
- f"{strs_to_str(self.erf.plot_vars_1)}\n")
+
+ f.write(f'erf.plot_file_1 = {self.erf.plot_file_1}\n')
+ if self.erf.plot_per_1 > 0:
+ f.write(f'erf.plot_per_1 = {self.erf.plot_per_1}\n')
+ else:
+ f.write(f'erf.plot_int_1 = {self.erf.plot_int_1}\n')
+ f.write('erf.plot_vars_1 = '
+ f"{strs_to_str(self.erf.plot_vars_1)}\n")
+
if (self.erf.plot_int_2 > 0) or (self.erf.plot_per_2 > 0):
f.write(f'erf.plot_file_2 = {self.erf.plot_file_2}\n')
if self.erf.plot_per_2 > 0:
@@ -404,13 +428,14 @@ def write(self,fpath=None):
lestypes = self.erf.les_type \
if isinstance(self.erf.les_type,list) \
else [self.erf.les_type]
- have_smag = ('Smagorinsky' in lestypes)
+ have_smag = ('Smagorinsky' in lestypes) or ('Smagorinsky2D' in lestypes)
have_dear = ('Deardorff' in lestypes)
if have_smag or have_dear:
f.write(f'\nerf.les_type = {strs_to_str(lestypes)}\n')
if have_smag:
Cs_list = self.erf.Cs if isinstance(self.erf.Cs,list) else [self.erf.Cs]
- f.write(f'erf.Cs = {list_to_str(Cs_list)}\n')
+ comment = ' # Cs=0.25 is WRF default' if (0.25 in Cs_list) else ''
+ f.write(f'erf.Cs = {list_to_str(Cs_list)}{comment}\n')
if have_dear:
Ck_list = self.erf.Ck if isinstance(self.erf.Ck,list) else [self.erf.Ck]
f.write(f'erf.Ck = {list_to_str(Ck_list)}\n')
@@ -445,7 +470,28 @@ def write(self,fpath=None):
########################################
if self.erf.radiation_model != 'None':
f.write(f"""\n# RADIATION
-erf.radiation_model = {self.erf.radiation_model}
+erf.radiation_model = {self.erf.radiation_model}
+erf.rad_freq_in_steps = {self.erf.rad_freq_in_steps}
+erf.rad_write_fluxes = {bool_to_str(self.erf.rad_write_fluxes)}
+erf.co2vmr = {self.erf.co2vmr}
+""")
+ if isinstance(self.erf.o3vmr, (list,np.ndarray)):
+ f.write(f'erf.o3vmr = {list_to_str(self.erf.o3vmr)}')
+ else:
+ f.write(f'erf.o3vmr = {self.erf.o3vmr}')
+ f.write(f"""
+erf.n2ovmr = {self.erf.n2ovmr}
+erf.covmr = {self.erf.covmr}
+erf.ch4vmr = {self.erf.ch4vmr}
+erf.o2vmr = {self.erf.o2vmr}
+erf.n2vmr = {self.erf.n2vmr}
+erf.rrtmgp_file_path = {self.erf.rrtmgp_file_path}
+""")
+
+ ########################################
+ if self.erf.land_surface_model != 'None':
+ f.write(f"""\n# LAND SURFACE
+erf.land_surface_model = {self.erf.land_surface_model}
""")
########################################
@@ -516,12 +562,15 @@ def write(self,fpath=None):
erf.init_sounding_ideal = {bool_to_str(self.erf.init_sounding_ideal)}
""")
elif self.erf.init_type.lower() == 'wrfinput':
- f.write(f"""
-erf.init_type = wrfinput
-erf.use_real_bcs = {bool_to_str(self.erf.use_real_bcs)}
-erf.nc_init_file_0 = {self.erf.nc_init_file_0}""")
+ f.write('\nerf.init_type = wrfinput\n')
+ nc_init_files = [
+ param for param in dir(self.erf)
+ if param.startswith('nc_init_file_')]
+ for initfile in nc_init_files:
+ f.write(f'erf.{initfile} = {getattr(self.erf,initfile)}\n')
if self.erf.use_real_bcs:
f.write(f"""
+erf.use_real_bcs = {bool_to_str(self.erf.use_real_bcs)}
erf.nc_bdy_file = {self.erf.nc_bdy_file}
erf.real_width = {self.erf.real_width}
erf.real_set_width = {self.erf.real_set_width}
@@ -557,3 +606,10 @@ def write_bc(f, bcname, bcdict):
else:
assert isinstance(val, list)
f.write(f"{bcname}.{key} = {list_to_str(val,float)}\n")
+
+
+@click.command()
+@click.argument('input_file', type=click.Path(exists=True, readable=True))
+def check_erf_input(input_file):
+ """Validate ERF input file"""
+ ERFInputs(input_file)
diff --git a/erftools/preprocessing/__init__.py b/erftools/preprocessing/__init__.py
index 2e7de1c..14f882b 100644
--- a/erftools/preprocessing/__init__.py
+++ b/erftools/preprocessing/__init__.py
@@ -1,21 +1,26 @@
-from .wrf_inputs import WRFInputDeck
+from ..wrf.inputdeck import WRFInputDeck
from .grids import LambertConformalGrid
-# ERA5 related funrcions
-from .era5.IO import calculate_utm_zone
-from .era5.IO import write_binary_simple_ERF
-from .era5.IO import write_binary_vtk_structured_grid
-from .era5.IO import write_binary_vtk_cartesian_file
-from .era5.IO import find_latlon_indices
-from .era5.IO import find_erf_domain_extents
-from .era5.IO import write_binary_vtk_cartesian
-from .era5.Plot_1D import plot_1d
-from .era5.ReadERA5DataAndWriteERF_IC import ReadERA5_3DData
-from .era5.ReadERA5DataAndWriteERF_SurfBC import Download_ERA5_SurfaceData
-from .era5.ReadERA5DataAndWriteERF_SurfBC import Download_ERA5_ForecastSurfaceData
-from .era5.ReadERA5DataAndWriteERF_SurfBC import ReadERA5_SurfaceData
-from .era5.Download_ERA5Data import Download_ERA5_Data
-from .era5.Download_ERA5Data import Download_ERA5_ForecastData
+try:
+ import cdsapi
+except ModuleNotFoundError:
+ print("Note: Need to install package 'cdsapi' to work with reanalysis data")
+else:
+ # ERA5 related funrcions
+ from .era5.IO import calculate_utm_zone
+ from .era5.IO import write_binary_simple_ERF
+ from .era5.IO import write_binary_vtk_structured_grid
+ from .era5.IO import write_binary_vtk_cartesian_file
+ from .era5.IO import find_latlon_indices
+ from .era5.IO import find_erf_domain_extents
+ from .era5.IO import write_binary_vtk_cartesian
+ from .era5.Plot_1D import plot_1d
+ from .era5.ReadERA5DataAndWriteERF_IC import ReadERA5_3DData
+ from .era5.ReadERA5DataAndWriteERF_SurfBC import Download_ERA5_SurfaceData
+ from .era5.ReadERA5DataAndWriteERF_SurfBC import Download_ERA5_ForecastSurfaceData
+ from .era5.ReadERA5DataAndWriteERF_SurfBC import ReadERA5_SurfaceData
+ from .era5.Download_ERA5Data import Download_ERA5_Data
+ from .era5.Download_ERA5Data import Download_ERA5_ForecastData
# GFS related funrcions
from .gfs.Download_GFSData import Download_GFS_Data
diff --git a/erftools/preprocessing/hrrr.py b/erftools/preprocessing/hrrr.py
index 6aee911..10e2116 100644
--- a/erftools/preprocessing/hrrr.py
+++ b/erftools/preprocessing/hrrr.py
@@ -549,8 +549,8 @@ def to_wrfbdy(self,bdy_width,dtype=float):
ds = xr.Dataset()
# interpolate staggered velocity fields
- Ugrid = self.interpxy('U', self.xg_u[*idxs], self.yg_u[*idxs], dtype=dtype)
- Vgrid = self.interpxy('V', self.xg_v[*idxs], self.yg_v[*idxs], dtype=dtype)
+ Ugrid = self.interpxy('U', self.xg_u[idxs], self.yg_u[idxs], dtype=dtype)
+ Vgrid = self.interpxy('V', self.xg_v[idxs], self.yg_v[idxs], dtype=dtype)
ds['U'] = Ugrid.rename(west_east='west_east_stag')
ds['V'] = Vgrid.rename(south_north='south_north_stag')
@@ -567,12 +567,12 @@ def to_wrfbdy(self,bdy_width,dtype=float):
'QRAIN',
]
for varn in unstag_interp_vars:
- ds[varn] = self.interpxy(varn, self.xg[*idxs], self.yg[*idxs], dtype=dtype)
+ ds[varn] = self.interpxy(varn, self.xg[idxs], self.yg[idxs], dtype=dtype)
# setup map scale factors
sn_ew_idxs = idxs[::-1]
- msf_u = self.grid.calc_msf(lat_u[*sn_ew_idxs])
- msf_v = self.grid.calc_msf(lat_v[*sn_ew_idxs])
+ msf_u = self.grid.calc_msf(lat_u[sn_ew_idxs])
+ msf_v = self.grid.calc_msf(lat_v[sn_ew_idxs])
ds['MAPFAC_U'] = (('south_north', 'west_east_stag'), msf_u.astype(dtype))
ds['MAPFAC_V'] = (('south_north_stag', 'west_east'), msf_v.astype(dtype))
diff --git a/erftools/utils.py b/erftools/utils.py
index 655edcd..c69ed54 100644
--- a/erftools/utils.py
+++ b/erftools/utils.py
@@ -1,7 +1,10 @@
import numpy as np
import xarray as xr
+import ussa1976
from .constants import CONST_GRAV
+from .inputs import ERFInputs
+from .input_sounding import InputSounding
def get_stag_dims(ds_cc):
stag_dims = {dim if dim != 'bottom_top' else 'bottom_top_stag': size
@@ -40,3 +43,43 @@ def get_w_from_omega(omega_cc, rho_cc, stag_dims=None):
da.loc[dict(bottom_top_stag=-1)] = w_top
return da
+
+
+def get_zcc(inp) -> np.array:
+ """Automatically get modeled heights at cell centers, which is exact
+ for const dz or stretched grids and approximate for general,
+ variable dz grids over terrain.
+
+ `inp` may be an ERF input file path or an instance of ERFInputs.
+ """
+ if not isinstance(inp, ERFInputs):
+ inp = ERFInputs(inp)
+ if len(inp.erf.terrain_z_levels) > 0:
+ zstag = np.array(inp.erf.terrain_z_levels)
+ zcc = 0.5 * (zstag[1:] + zstag[:-1])
+ elif inp.erf.grid_stretching_ratio > 1:
+ s = inp.erf.grid_stretching_ratio
+ dz0 = inp.erf.initial_dz
+ nz = inp.amr.n_cell[2]
+ zstag = dz0 * (s**np.arange(nz+1) - 1) / (s - 1) # partial sum
+ zcc = 0.5 * (zstag[1:] + zstag[:-1])
+ else:
+ nz = inp.amr.n_cell[2]
+ const_dz = (inp.geometry.prob_hi[2] - inp.geometry.prob_lo[2]) / nz
+ zcc = inp.geometry.prob_lo[2] + np.arange(0.5, nz) * const_dz
+ return zcc
+
+def est_p(z, soundingfile=None) -> np.array:
+ """Estimate air pressure [Pa] at a set of heights, using either the
+ US Standard Atmosphere (1976) or a WRF-style input_sounding.
+ """
+ z = np.array(z)
+ if soundingfile is not None:
+ sound = InputSounding(soundingfile)
+ sound.interp_levels(z)
+ sound.integrate_column()
+ p = sound.pm
+ else:
+ ds = ussa1976.compute(z,'p')
+ p = ds['p'].values
+ return p
diff --git a/erftools/wrf/__init__.py b/erftools/wrf/__init__.py
index c545d20..27e23c0 100644
--- a/erftools/wrf/__init__.py
+++ b/erftools/wrf/__init__.py
@@ -1,3 +1,4 @@
from .real import (get_zlevels_auto,
get_eta_levels)
+from .namelist.tslist import TSList
diff --git a/erftools/preprocessing/wrf_inputs.py b/erftools/wrf/inputdeck.py
similarity index 69%
rename from erftools/preprocessing/wrf_inputs.py
rename to erftools/wrf/inputdeck.py
index 783a497..ac60739 100644
--- a/erftools/preprocessing/wrf_inputs.py
+++ b/erftools/wrf/inputdeck.py
@@ -1,20 +1,28 @@
import logging
import os
+
import numpy as np
import pandas as pd
import xarray as xr
import f90nml
import calendar
from scipy.interpolate import RegularGridInterpolator
+import click
+
+from .namelist.input import (TimeControl,
+ Domains,
+ Physics,
+ Dynamics,
+ BoundaryControl)
+from .namelist.tslist import TSList
+from .landuse import LandUseTable
+from .real import RealInit, get_zlevels_auto
+from .rad import interp_ozone
-from ..wrf.namelist import (TimeControl, Domains, Physics, Dynamics,
- BoundaryControl)
-from ..wrf.tslist import TSList
-from ..wrf.landuse import LandUseTable
-from ..wrf.real import RealInit, get_zlevels_auto
from ..constants import CONST_GRAV, p_0
from ..inputs import ERFInputs
+
class WRFInputDeck(object):
"""Class to parse inputs from WRF and convert to inputs for ERF
WRF inputs include:
@@ -23,12 +31,16 @@ class WRFInputDeck(object):
This will instantiate WRFNamelist objects from a given namelist, with WRF
defaults included. From the WRFNamelists, a WRFInputDeck.input_dict will be
- populated with ERF input parameters. When WRFInputDec.write() is called, an
+ populated with ERF input parameters. When WRFInputDeck.write() is called, an
ERFInputs object is instantiated--inside ERFInputs is where error checking
occurs. ERFInputs.write() is used to finally output an ERF input file.
"""
- def __init__(self,nmlpath,tslist=None,verbosity=logging.DEBUG):
+ default_plot_vars = ['density','x_velocity','y_velocity','z_velocity',
+ 'pressure','theta','KE',
+ 'Kmh','Kmv','Khh','Khv','qv','qc']
+
+ def __init__(self,nmlpath,wrfinput=None,tslist=None,verbosity=logging.DEBUG):
# setup logger
self.log = logging.getLogger(__name__)
if not self.log.hasHandlers():
@@ -51,6 +63,9 @@ def __init__(self,nmlpath,tslist=None,verbosity=logging.DEBUG):
self.set_defaults()
self.generate_inputs()
+ self.wrfinput = wrfinput
+ self.get_map_info()
+
if tslist is not None:
self.tslist = TSList(tslist)
else:
@@ -74,10 +89,9 @@ def set_defaults(self):
'yhi.type': 'Outflow',
'zhi.type': 'SlipWall',
'erf.terrain_type': 'StaticFittedMesh',
- 'erf.terrain_smoothing': 1,
+ 'erf.terrain_smoothing': 0, # only valid option with multilievel
'erf.init_type': 'wrfinput',
'erf.use_real_bcs': True,
- 'erf.nc_init_file_0': 'wrfinput_d01',
'erf.nc_bdy_file': 'wrfbdy_d01',
'erf.dycore_horiz_adv_type': 'Upwind_5th',
'erf.dycore_vert_adv_type': 'Upwind_3rd',
@@ -89,9 +103,8 @@ def set_defaults(self):
'erf.v': 1, # verbosity in ERF.cpp
'erf.sum_interval': 1, # timesteps between computing mass
'erf.plot_file_1': 'plt',
- 'erf.plot_vars_1': ['density','x_velocity','y_velocity','z_velocity',
- 'pressure','theta','KE',
- 'Kmh','Kmv','Khh','Khv','qv','qc'],
+ 'erf.plot_vars_1': self.default_plot_vars,
+ 'erf.rad_freq_in_steps': -1,
}
def generate_inputs(self):
@@ -111,9 +124,9 @@ def generate_inputs(self):
startdate = self.time_control.start_datetimes[0]
enddate = self.time_control.end_datetimes[0]
tsim = (enddate - startdate).total_seconds()
- inp['start_date'] = startdate
- inp['stop_date'] = enddate
- inp['start_time'] = calendar.timegm(startdate.timetuple())
+ inp['start_datetime'] = startdate
+ inp['stop_datetime'] = enddate
+ inp['start_time'] = calendar.timegm(startdate.timetuple()) # epoch time
inp['stop_time'] = calendar.timegm(enddate.timetuple())
self.log.info(f'Total simulation time: {tsim}')
self.log.info(f"Start from {startdate.strftime('%Y-%m-%d %H:%M:%S')}"
@@ -146,23 +159,17 @@ def generate_inputs(self):
assert eta_levels[0] == 1
assert eta_levels[-1] == 0
- # get geopotential height from base state
- real = RealInit(eta_stag=eta_levels, ptop=ptop)
- #phb = real.phb.squeeze().values
- # better match real.exe output...
- alb = real.alb.squeeze().values
- phb = np.zeros_like(eta_levels)
- psurf = p_0
- mub = psurf - ptop
- for k in range(len(eta_levels)-1):
- phb[k+1] = phb[k] - (eta_levels[k+1]-eta_levels[k]) * mub * alb[k]
-
- z_levels = phb / CONST_GRAV
+ # get geopotential heights from base state
+ real = RealInit(eta_levels=eta_levels, ptop=ptop)
+ z_levels = real.zlevels.squeeze().values
self.base_heights = z_levels
inp['erf.terrain_z_levels'] = z_levels
most_zref = 0.5*(z_levels[0] + z_levels[1])
inp['erf.most.zref'] = most_zref # need to specify for terrain
+ self.log.info('Reference height for MOST set to the average of the '
+ 'first two base-state geopotential heights: '
+ f'{z_levels[0]:g} {z_levels[1]:g}')
ztop = z_levels[-1]
self.log.info('Estimated domain ztop from domains.p_top_requested'
@@ -186,12 +193,18 @@ def generate_inputs(self):
dt = np.array(self.domains.parent_time_step_ratio) * self.domains.time_step
inp['erf.fixed_dt'] = dt[0]
- # refinements
+ # initial conditions
max_dom = self.domains.max_dom
+ for i in range(max_dom):
+ inp[f'erf.nc_init_file_{i}'] = f'wrfinput_d{i+1:02d}'
+
+ # refinements / nests
inp['amr.max_level'] = max_dom - 1 # zero-based indexing
if max_dom > 1:
self.log.info('Assuming parent_time_step_ratio == parent_grid_ratio')
+ self.refinement_boxes = []
+
refine_names = [f'nest{idom:d}' for idom in range(1,max_dom)]
inp['erf.refinement_indicators'] = refine_names
@@ -204,33 +217,58 @@ def generate_inputs(self):
grid_ratio = self.domains.parent_grid_ratio[idom]
ref_ratio_vect += [grid_ratio, grid_ratio, 1]
- parent_ds = np.array([ dx[idom-1], dy[idom-1]], dtype=float)
- child_ds = np.array([ dx[idom ], dy[idom ]], dtype=float)
- parent_ext = np.array([imax[idom-1], jmax[idom-1]]) * parent_ds
- child_ext = np.array([imax[idom ], jmax[idom ]]) * child_ds
+ parent_dx = np.array([ dx[idom-1] , dy[idom-1] ], dtype=float)
+ child_dx = np.array([ dx[idom ] , dy[idom ] ], dtype=float)
+ parent_ext = np.array([imax[idom-1]-1, jmax[idom-1]-1]) * parent_dx
+ child_ext = np.array([imax[idom ]-1, jmax[idom ]-1]) * child_dx
lo_idx = np.array([
self.domains.i_parent_start[idom] - 1,
self.domains.j_parent_start[idom] - 1])
- in_box_lo = lo_idx * parent_ds
+ in_box_lo = lo_idx * parent_dx
in_box_hi = in_box_lo + child_ext
assert (in_box_hi[0] <= parent_ext[0])
assert (in_box_hi[1] <= parent_ext[1])
+ inp[f'erf.nest{idom:d}.max_level'] = idom
inp[f'erf.nest{idom:d}.in_box_lo'] = in_box_lo
inp[f'erf.nest{idom:d}.in_box_hi'] = in_box_hi
+ self.refinement_boxes.append((in_box_lo, in_box_hi))
inp['amr.ref_ratio_vect'] = ref_ratio_vect
restart_interval = self.time_control.restart_interval * 60.0 # [s]
- inp['erf.check_int'] = int(restart_interval / dt[0])
+ if restart_interval <= 0:
+ inp['erf.check_int'] = -1
+ else:
+ inp['erf.check_int'] = int(restart_interval / dt[0])
wrfout_interval = self.time_control.history_interval[0] * 60.0 # [s]
- inp['erf.plot_int_1'] = int(wrfout_interval / dt[0])
+ if wrfout_interval <= 0:
+ inp['erf.plot_int_1'] = -1
+ else:
+ inp['erf_plot_file_1'] = 'plt'
+ #inp['erf.plot_int_1'] = int(wrfout_interval / dt[0])
+ inp['erf.plot_per_1'] = wrfout_interval
+ inp['erf.plot_vars_1'] = self.default_plot_vars
+ self.log.info('Setting default plotting vars for history output: '
+ f'{self.default_plot_vars}')
+
+ auxhist2_interval = self.time_control.auxhist2_interval[0] * 60.0 # [s]
+ if auxhist2_interval <= 0:
+ inp['erf.plot_int_2'] = -1
+ else:
+ inp['erf.plot_file_2'] = 'plt_aux'
+ #inp['erf.plot_int_2'] = int(auxhist2_interval / dt[0])
+ inp['erf.plot_per_2'] = auxhist2_interval
+ inp['erf.plot_vars_2'] = self.default_plot_vars
+ self.log.info('Setting default plotting vars for auxhist output: '
+ f'{self.default_plot_vars} -- need to manually specify '
+ 'erf.plot_vars_2 to replicate auxhist2 output')
sfclayscheme = self.physics.sf_sfclay_physics[0]
if sfclayscheme == 'None':
inp['zlo.type'] = 'SlipWall'
- elif sfclayscheme == 'MOST':
- inp['zlo.type'] = 'MOST'
+ elif sfclayscheme == 'SurfaceLayer':
+ inp['zlo.type'] = 'surface_layer'
else:
self.log.warning(f'Surface layer scheme {sfclayscheme} not implemented in ERF')
inp['zlo.type'] = sfclayscheme
@@ -254,9 +292,9 @@ def generate_inputs(self):
inp['erf.dryscal_horiz_adv_type'] = h_sca_adv_order
inp['erf.dryscal_vert_adv_type'] = v_sca_adv_order
if not all([adv_opt == 'WENO5' for adv_opt in self.dynamics.moist_adv_opt]):
- self.log.warning('Need to manually specify moist erf.moistscal_*_adv_type'
- f' for WRF moist_adv_opt = {self.dynamics.moist_adv_opt}'
- ' -- defaulting to 5th-order WENO')
+ self.log.warning(f'WRF moist_adv_opt = {self.dynamics.moist_adv_opt}'
+ ' not available -- defaulting to 5th-order WENO for'
+ ' erf.moistscal_*_adv_type')
inp['erf.pbl_type'] = self.physics.bl_pbl_physics
for idom in range(max_dom):
@@ -296,10 +334,7 @@ def generate_inputs(self):
inp['erf.num_diff_coeff'] = num_diff_coeff
if any([opt != 'constant' for opt in self.dynamics.km_opt]):
- # in ERF, Smagorinsky == 2D Smagorinsky
- les_types = [turb if 'Smagorinsky' not in turb else 'Smagorinsky'
- for turb in self.dynamics.km_opt]
- les_types = les_types[:max_dom]
+ les_types = self.dynamics.km_opt[:max_dom]
inp['erf.les_type'] = les_types
smag_Cs = self.dynamics.c_s
dear_Ck = self.dynamics.c_k
@@ -324,6 +359,30 @@ def generate_inputs(self):
self.log.warning(f'Applying the {rad_model} radiation scheme on all levels')
inp['erf.radiation_model'] = rad_model
+ inp['erf.rad_freq_in_steps'] = self.physics.radt[0]
+ if inp['erf.rad_freq_in_steps'] < 0:
+ # rule of thumb: rad freq is "1 min per km of dx"
+ dx_km = self.domains.dx[0] / 1000.
+ radt = dx_km * 60. # [s]
+ rad_freq = int(radt / dt[0])
+ inp['erf.rad_freq_in_steps'] = rad_freq
+ self.log.info('Calculated radiation update frequency to be '
+ f'every {rad_freq} steps, corresponding to an '
+ f'interval of {rad_freq * dt[0] / 60:g} min on '
+ 'domain d01')
+
+ if any([opt != 'None' for opt in self.physics.surface_physics]):
+ lsm_model = self.physics.surface_physics[0]
+ if len(set(self.physics.surface_physics)) > 1:
+ self.log.warning(f'Applying the {lsm_model} surface scheme on all levels')
+ if lsm_model == 'NoahMP':
+ #self.log.warning(f'&noah_mp was not parsed, additional options'
+ # ' need to be manually specified')
+ self.log.warning('NoahMP verification is ongoing; '
+ 'reverting to simple land model (SLM) for now')
+ lsm_model = 'SLM'
+ inp['erf.land_surface_model'] = lsm_model
+
if any([opt != 'None' for opt in self.physics.cu_physics]):
self.log.warning('ERF currently does not have any cumulus parameterizations')
@@ -338,15 +397,42 @@ def generate_inputs(self):
self.log.warning(f'Damping option {self.dynamics.damp_opt} not supported')
self.input_dict = inp
-
- def process_initial_conditions(self,init_input='wrfinput_d01',
+
+ def get_map_info(self,init_input=None):
+ if init_input is None:
+ init_input = self.wrfinput
+ if init_input is None:
+ self.cen_lat = None
+ self.cen_lon = None
+ self.truelat1 = None
+ self.truelat2 = None
+ self.moad_cen_lat = None
+ self.stand_lon = None
+ self.map_proj = None
+ return
+
+ inp = xr.open_dataset(init_input)
+ self.cen_lat = inp.attrs['CEN_LAT']
+ self.cen_lon = inp.attrs['CEN_LON']
+ self.truelat1 = inp.attrs['TRUELAT1'] # standard parallels
+ self.truelat2 = inp.attrs['TRUELAT2']
+ self.moad_cen_lat = inp.attrs['MOAD_CEN_LAT'] # "mother of all domains"
+ self.stand_lon = inp.attrs['STAND_LON']
+ self.map_proj = inp.attrs['MAP_PROJ_CHAR']
+
+ def process_initial_conditions(self,init_input=None,
calc_geopotential_heights=False,
landuse_table_path=None,
write_hgt=None,
write_z0=None,
write_albedo=None):
+ if init_input is None:
+ init_input = self.wrfinput
wrfinp = xr.open_dataset(init_input)
+ idx = init_input.index('_d')
+ idom = int(init_input[idx+2:idx+4]) - 1
+
# Get Coriolis parameters
period = 4*np.pi / wrfinp['F'] * np.sin(np.radians(wrfinp.coords['XLAT'])) # F: "Coriolis sine latitude term"
mean_lat = np.mean(wrfinp.coords['XLAT'].values)
@@ -371,14 +457,22 @@ def process_initial_conditions(self,init_input='wrfinput_d01',
inp['erf.most.zref'] = most_zref # need to specify for terrain
# Grid data needed if hgt or z0 are written
- dx = self.domains.dx[0]
- dy = self.domains.dy[0]
+ dx = self.domains.dx[idom]
+ assert dx == wrfinp.attrs['DX']
+ dy = self.domains.dy[idom]
+ assert dy == wrfinp.attrs['DY']
nx = wrfinp.sizes['west_east']
ny = wrfinp.sizes['south_north']
- west_east = np.arange(0.5,nx) * dx
- south_north = np.arange(0.5,ny) * dy
- west_east_stag = np.arange(nx+1) * dx
- south_north_stag = np.arange(ny+1) * dy
+
+ x0, y0 = 0.0, 0.0
+ if idom > 0:
+ refine_box_lo, _ = self.refinement_boxes[idom-1]
+ x0, y0 = refine_box_lo[:2]
+
+ west_east = x0 + np.arange(0.5,nx) * dx
+ south_north = y0 + np.arange(0.5,ny) * dy
+ west_east_stag = x0 + np.arange(nx+1) * dx
+ south_north_stag = y0 + np.arange(ny+1) * dy
xg,yg = np.meshgrid(west_east_stag, south_north_stag, indexing='ij')
hgt = wrfinp['HGT'].isel(Time=0) # terrain height
@@ -398,15 +492,15 @@ def process_initial_conditions(self,init_input='wrfinput_d01',
xyz = np.stack((xg.ravel(order='F'),
yg.ravel(order='F'),
hgt_nodes.ravel(order='F')),axis=-1)
- print('Writing out',write_hgt)
- np.savetxt(write_hgt, xyz, fmt='%.8g')
+
+ write_ascii_table(write_hgt, xyz, names=['x','y','hgt'])
self.input_dict['erf.terrain_file_name'] = \
os.path.split(write_hgt)[1]
# Process land use information
if landuse_table_path is None:
- print('Need to specify `landuse_table_path` from your WRF installation'
- 'land-use indices to estimate z0')
+ print('Need to specify `landuse_table_path` from your WRF '
+ ' installation to determine z0, alb from land-use indices')
if write_z0:
print('Surface roughness map was not written')
if write_albedo:
@@ -460,8 +554,8 @@ def alfun(idx):
xyz0 = np.stack((xg.ravel(order='F'),
yg.ravel(order='F'),
z0_nodes.ravel(order='F')),axis=-1)
- print('Writing out',write_z0)
- np.savetxt(write_z0, xyz0, fmt='%.8g')
+
+ write_ascii_table(write_z0, xyz0, names=['x','y','z0'])
self.input_dict['erf.most.roughness_file_name'] = \
os.path.split(write_z0)[1]
else:
@@ -483,24 +577,71 @@ def alfun(idx):
xyz0 = np.stack((xg.ravel(order='F'),
yg.ravel(order='F'),
al_nodes.ravel(order='F')),axis=-1)
- print('Writing out',write_albedo)
- np.savetxt(write_albedo, xyz0, fmt='%.8g')
+
+ write_ascii_table(write_albedo, xyz0, names=['x','y','alb'])
self.input_dict['erf.rad_albedo_file_name'] = \
os.path.split(write_albedo)[1]
def to_erf(self):
+ inp = ERFInputs(**self.input_dict)
+
+ if inp.erf.radiation_model != 'None':
+ if self.cen_lat:
+ inp.erf.o3vmr = interp_ozone(inp, self.cen_lat)
+ else:
+ self.log.warning('Using a radiation model with a constant for '
+ 'the entire column; need to set `cen_lat`, '
+ 'e.g. by providing a wrfinput file')
+
if self.tslist:
if self.tslist.have_ij:
nz = self.input_dict['amr.n_cell'][2]
lo_ijk, hi_ijk = self.tslist.get_ijk_lists(nz)
- self.input_dict['erf.sample_line_lo'] = lo_ijk
- self.input_dict['erf.sample_line_hi'] = hi_ijk
+ inp.erf.sample_line_lo = lo_ijk
+ inp.erf.sample_line_hi = hi_ijk
else:
self.log.info('A tslist was provided but lat,lon were not '
'converted to i,j')
- return ERFInputs(**self.input_dict)
+
+ return inp
def write_inputfile(self,fpath):
inp = self.to_erf()
inp.write(fpath)
print('Wrote',fpath)
+
+
+def write_ascii_table(fpath, xyz, names=None):
+ print('Writing out',fpath)
+ ext = os.path.splitext(fpath)[1]
+ if ext == '.csv':
+ columns = None
+ if names is not None:
+ columns = names
+ df = pd.DataFrame(xyz, columns=columns)
+ df.to_csv(fpath, index=False)
+ else:
+ header = ''
+ if names is not None:
+ header = ' '.join(names)
+ np.savetxt(fpath, xyz, header=header, fmt='%.8g')
+
+
+@click.command()
+@click.argument('namelist_input', type=click.Path(exists=True, readable=True))
+@click.argument('erf_input', type=click.Path(writable=True), required=False,
+ default='inputs')
+@click.option('--init',
+ type=click.Path(exists=True, readable=True),
+ help='Path to a wrfinput_d01 file to provide additional '
+ 'information about the simulation setup (optional)',
+ required=False)
+@click.option('--tslist',
+ type=click.Path(exists=True, readable=True),
+ help='Path to a tslist file to convert into line sampling '
+ 'inputs for ERF (optional)',
+ required=False)
+def wrf_namelist_to_erf(namelist_input, erf_input, init=None, tslist=None):
+ """Convert a WRF namelist.input into an ERF input file"""
+ wrf = WRFInputDeck(namelist_input, wrfinput=init, tslist=tslist)
+ wrf.write_inputfile(erf_input)
diff --git a/erftools/wrf/namelist.py b/erftools/wrf/namelist/input.py
similarity index 83%
rename from erftools/wrf/namelist.py
rename to erftools/wrf/namelist/input.py
index 58aab2d..d38fa72 100644
--- a/erftools/wrf/namelist.py
+++ b/erftools/wrf/namelist/input.py
@@ -4,7 +4,7 @@
import warnings
from datetime import datetime, timedelta
-from .namelist_mappings import *
+from .mappings import *
class WRFNamelist(object):
def __init__(self,nmldict):
@@ -60,6 +60,8 @@ def __init__(self,nmldict):
if history_interval_s is not None:
self.history_interval = [interval / 60. for interval in history_interval_s]
+ self.auxhist2_interval = self.getarrayvar('auxhist2_interval',default=[0]) # [min]
+
self.parse_datetime_range()
def __str__(self):
@@ -71,14 +73,23 @@ def parse_datetime_range(self):
start_month = self.getarrayvar('start_month')
start_day = self.getarrayvar('start_day')
start_hour = self.getarrayvar('start_hour')
- start_minute = self.getarrayvar('start_minute')
- start_second = self.getarrayvar('start_second')
+ start_minute = self.getarrayvar('start_minute', optional=True)
+ start_second = self.getarrayvar('start_second', optional=True)
end_year = self.getarrayvar('end_year')
end_month = self.getarrayvar('end_month')
end_day = self.getarrayvar('end_day')
end_hour = self.getarrayvar('end_hour')
- end_minute = self.getarrayvar('end_minute')
- end_second = self.getarrayvar('end_second')
+ end_minute = self.getarrayvar('end_minute', optional=True)
+ end_second = self.getarrayvar('end_second', optional=True)
+ if start_minute is None:
+ start_minute = len(start_year) * [0]
+ if start_second is None:
+ start_second = len(start_year) * [0]
+ if end_minute is None:
+ end_minute = len(start_year) * [0]
+ if end_second is None:
+ end_second = len(start_year) * [0]
+
self.start_datetimes = []
self.end_datetimes = []
for idom in range(len(start_year)):
@@ -105,10 +116,10 @@ def parse_datetime_range(self):
self.start_datetimes.append(start_date)
self.end_datetimes.append(end_date)
- run_days = self.getvar('run_days')
- run_hours = self.getvar('run_hours')
- run_minutes = self.getvar('run_minutes')
- run_seconds = self.getvar('run_seconds')
+ run_days = self.getvar('run_days', default=0)
+ run_hours = self.getvar('run_hours', default=0)
+ run_minutes = self.getvar('run_minutes', default=0)
+ run_seconds = self.getvar('run_seconds', default=0)
spec_run_time = run_days * 86400 \
+ run_hours * 3600 \
+ run_minutes * 60 \
@@ -118,6 +129,8 @@ def parse_datetime_range(self):
if spec_run_time != simtime.total_seconds():
new_end_datetime = self.start_datetimes[0] \
+ timedelta(seconds=spec_run_time)
+ # From WRF user guide: run_days/run_hours takes precedence
+ # over the end times
print(f'Specified run time {spec_run_time} s'
f' differs from {simtime.total_seconds()} s' \
f' (from {self.start_datetimes[0]}'
@@ -145,7 +158,7 @@ def __str__(self):
def parse_time_integration(self):
self.time_step = self.getvar('time_step') # seconds
dt_num = self.getvar('time_step_fract_num',optional=True)
- if dt_num is not None:
+ if dt_num is not None and dt_num > 0:
dt_den = self.getvar('time_step_fract_den')
self.time_step = dt_num / dt_den
self.parent_time_step_ratio = self.getarrayvar(
@@ -177,8 +190,18 @@ def parse_grid(self):
assert self.i_parent_start[0] == 1
assert self.j_parent_start[0] == 1
for dom in range(1,self.max_dom):
- assert (self.dx[dom-1]/self.dx[dom] == self.parent_grid_ratio[dom])
- assert (self.dy[dom-1]/self.dy[dom] == self.parent_grid_ratio[dom])
+ if len(self.dx) >= self.max_dom:
+ assert (self.dx[dom-1]/self.dx[dom] == self.parent_grid_ratio[dom])
+ else:
+ print(f'Note: dx on d{dom+1:02d} not found,'
+ ' setting from parent_grid_ratio')
+ self.dx.append(self.dx[dom-1] / self.parent_grid_ratio[dom])
+ if len(self.dy) >= self.max_dom:
+ assert (self.dy[dom-1]/self.dy[dom] == self.parent_grid_ratio[dom])
+ else:
+ print(f'Note: dy on d{dom+1:02d} not found'
+ ' setting from parent_grid_ratio')
+ self.dy.append(self.dy[dom-1] / self.parent_grid_ratio[dom])
self.eta_levels = self.getarrayvar('eta_levels',optional=True)
self.etac = self.getvar('etac',default=0.2)
self.auto_levels_opt = self.getvar('auto_levels_opt',default=2)
@@ -213,6 +236,13 @@ def parse_all(self):
self.bl_pbl_physics = [pbl_mapping.get(idx,'UNKNOWN') for idx in pbl_idx_list]
for i in range(len(self.bl_pbl_physics)):
if self.bl_pbl_physics[i] == 'MYNN':
+ if pbl_mynn_closure > 2.5:
+ pbl_mynn_closure = 2.5
+ warnings.warn(f'MYNN level {pbl_mynn_closure} selected, but'
+ ' it is currently not available in ERF'
+ ' -- reverting to MYNN level 2.5.'
+ ' Note: A port of MYNN-EDMF is also available'
+ ' but it has not been fully verified.')
lvlstr = str(pbl_mynn_closure).replace('.','')
self.bl_pbl_physics[i] += lvlstr
self.sf_sfclay_physics = [sfclay_mapping.get(idx,'UNKNOWN') for idx in sfclay_idx_list]
@@ -227,6 +257,13 @@ def parse_all(self):
'Different longwave/shortwave radiation schemes not handled'
self.ra_physics = [ra_physics_mapping.get(idx,'UNKNOWN') for idx in ra_lw_idx_list]
+ self.radt = self.getarrayvar('radt', default=-1)
+ assert all([t==self.radt[0] for t in self.radt]), \
+ 'Different radiation call intervals not handled'
+
+ lsm_idx_list = self.getarrayvar('sf_surface_physics')
+ self.surface_physics = [surface_physics_mapping.get(idx,'UNKNOWN') for idx in lsm_idx_list]
+
cu_idx_list = self.getarrayvar('cu_physics')
self.cu_physics = [cu_physics_mapping.get(idx,'UNKNOWN') for idx in cu_idx_list]
diff --git a/erftools/wrf/namelist_mappings.py b/erftools/wrf/namelist/mappings.py
similarity index 58%
rename from erftools/wrf/namelist_mappings.py
rename to erftools/wrf/namelist/mappings.py
index f2f6d10..8e1c25a 100644
--- a/erftools/wrf/namelist_mappings.py
+++ b/erftools/wrf/namelist/mappings.py
@@ -1,3 +1,5 @@
+# for reference, see WRF/run/README.namelist
+
pbl_mapping = {
0: 'None',
1: 'YSU', # YSU scheme
@@ -16,9 +18,9 @@
sfclay_mapping = {
0: 'None',
- 1: 'MOST', # Revised MM5 Monin-Obukhov scheme (Jimenez, renamed in v3.6)
- 2: 'MOST', # Monin-Obukhov (Janjic) scheme
- 5: 'MOST', # MYNN surface layer
+ 1: 'SurfaceLayer', # Revised MM5 Monin-Obukhov scheme (Jimenez, renamed in v3.6)
+ 2: 'SurfaceLayer', # Monin-Obukhov (Janjic) scheme
+ 5: 'SurfaceLayer', # MYNN surface layer
}
valid_sfclay = {
# for each PBL scheme, based on acceptable WRF inputs
@@ -39,9 +41,15 @@
0: 'None',
1: 'Kessler',
2: 'SAM', # SAM is comparable to Lin et al. scheme
- 3: 'Kessler', # WRF Single-Moment, 3-class scheme
+ 3: 'SAM', # WRF Single-Moment, 3-class scheme with ice
+ 4: 'SAM', # WRF Single-Moment, 5-class scheme
+ 5: 'SAM', # Ferrier (new Eta), operational High-Resolution Window version
6: 'SAM', # WRF Single-Moment, 6-class scheme
- 28: 'SAM', # aerosol-aware Thompson scheme
+ 8: 'Morrison', # Thompson scheme
+ 10: 'Morrison', # Morrison (double moment) scheme
+ 14: 'Morrison', # WRF Double-Moment 5-class scheme
+ 16: 'Morrison', # WRF Double-Moment 6-class scheme
+ 28: 'Morrison', # aerosol-aware Thompson scheme
}
ra_physics_mapping = {
@@ -49,6 +57,13 @@
4: 'RRTMGP',
}
+surface_physics_mapping = {
+ 0: 'None',
+ 1: 'SLM', # thermal diffusion scheme (soil temperature only, 5 layers)
+ 2: 'NoahMP', # Unified Noah land-surface model
+ 4: 'NoahMP', # Noah-MP land-surface model
+}
+
cu_physics_mapping = {
0: 'None',
}
@@ -77,9 +92,9 @@
1: 'constant',
2: 'Deardorff', # 1.5 order TKE closure (3D)
3: 'Smagorinsky', # Smagorinsky first-order closure (3D)
- 4: '2D Smagorinsky', # horizontal Smagorinsky closure (diagnosed from just
- # horizontal deformation); vertical diffusion from
- # PBL scheme
+ 4: 'Smagorinsky2D', # horizontal Smagorinsky closure (diagnosed from just
+ # horizontal deformation); vertical diffusion from
+ # PBL scheme
}
damp_opt_mapping = {
diff --git a/erftools/wrf/tslist.py b/erftools/wrf/namelist/tslist.py
similarity index 100%
rename from erftools/wrf/tslist.py
rename to erftools/wrf/namelist/tslist.py
diff --git a/erftools/wrf/rad.py b/erftools/wrf/rad.py
new file mode 100644
index 0000000..be94ffa
--- /dev/null
+++ b/erftools/wrf/rad.py
@@ -0,0 +1,205 @@
+from datetime import datetime
+from importlib import resources
+
+import numpy as np
+import xarray as xr
+import click
+
+from erftools.utils import get_zcc, est_p
+from erftools.inputs import ERFInputs
+
+
+# wrap Jan/Dec for a 365 day year
+my_date_oz = np.array(
+ [-15,
+ 16, 45, 75, 105, 136, 166, 197, 228, 258, 289, 319, 350,
+ 381]
+)
+
+def monthly_interp_weights_from_date(dt):
+ """Get interpolation weights to be applied to monthly data centered
+ on specific days of the year (hardcoded).
+ """
+ # get decimal day of year (1-based)
+ jan1 = datetime(dt.year, 1, 1)
+ decimal_day = (dt - jan1).total_seconds() / 86400. + 1.0
+
+ # find months to interpolate between
+ idx_r = np.where(my_date_oz > decimal_day)[0][0]
+ idx_l = idx_r - 1
+
+ # calculate interpolation weights
+ tdelta = my_date_oz[idx_r] - my_date_oz[idx_l]
+ fac_l = (my_date_oz[idx_r] - decimal_day) / tdelta
+ fac_r = (decimal_day - my_date_oz[idx_l]) / tdelta
+
+ # fill full array of monthly weights
+ weights = np.zeros(12)
+ if idx_l == 0 or idx_r == 13:
+ weights[-1] = fac_l
+ weights[0] = fac_r
+ else:
+ weights[idx_l-1] = fac_l
+ weights[idx_r-1] = fac_r
+
+ return xr.DataArray(weights, dims='month')
+
+def interp_from_monthly_to_date(xdata,dt):
+ """Interpolate from monthly data `xdata` (an xarray Dataset or
+ DataArray) to a specific datetime `dt`
+
+ The data should have the dimension 'month'
+ """
+ weightedvals = monthly_interp_weights_from_date(dt) * xdata
+ return weightedvals.sum('month')
+
+def interp_from_monthly_to_date_heights(xdata,dt,heights,**kwargs):
+ """Interpolate from monthly data `xdata` (an xarray Dataset or
+ DataArray) to a specific datetime `dt` and an array of model heights
+
+ The data should have the dimensions 'month' and 'plev' and the
+ pressure levels are in hPa.
+ """
+ # get pressure levels from a standard atmosphere
+ plev = est_p(heights,**kwargs) / 100 # hPa
+
+ # interpolate to pressure levels
+ plev_data = interp_from_monthly_to_date(xdata, dt)
+ interp_data = plev_data.interp(plev=plev)
+
+ # create new dimension coordinate
+ interp_data = interp_data.rename(plev='height')
+ interp_data = interp_data.assign_coords(height=heights,
+ plev=('height',plev))
+
+ # fill in near-surface values
+ interp_data = interp_data.bfill('height')
+
+ return interp_data
+
+
+def interp_ozone(inp, latitude, dataset='CAM', verbose=False):
+ """Interpolate from climatological O3 data to the starting datetime
+ and height levels from the ERF inputfile.
+
+ `inp` may be an input file or an ERFInputs object
+
+ Ozone datasets are stored in erftools/data/ozone_*.nc
+ """
+ dataname = f'ozone_{dataset}.nc'
+ with resources.files('erftools.data').joinpath(dataname) as fpath:
+ ds = xr.load_dataset(fpath)
+
+ date = inp.start_datetime
+ if date is None:
+ raise ValueError(f'start_date not found in {inputfile}')
+ if verbose:
+ print('Interpolating to',date)
+
+ heights = get_zcc(inp)
+ if verbose:
+ print('Model heights:',heights)
+
+ plevels = est_p(heights)
+ if verbose:
+ print('Standard pressure levels:',plevels)
+
+ ds = ds.interp(lat=latitude)
+ interpdata = interp_from_monthly_to_date_heights(ds, date, heights)
+ if verbose:
+ print('O3 [ppbv]: ', interpdata['o3vmr'].values / 1e-9)
+
+ return interpdata['o3vmr'].values
+
+
+@click.command()
+@click.argument('inputfile', type=click.Path(writable=True))
+@click.option('--latitude', type=click.FloatRange(-90,90),
+ required=True)
+@click.option('--dataset', default='CAM',
+ help='Name of O3 dataset [default=CAM]')
+def generate_ozone_profile(inputfile, latitude, dataset):
+ """Interpolate from climatological O3 data to the starting datetime
+ and height levels from the ERF inputfile.
+
+ Ozone datasets are stored in erftools/data/ozone_*.nc
+ """
+ inp = ERFInputs(inputfile)
+ o3vmr = interp_ozone(inp, latitude, dataset, verbose=True)
+ erfstr = str(o3vmr).lstrip('[').rstrip(']')
+ print('erf.o3vmr = ', erfstr)
+
+'''
+For verifying interpolator behavior
+
+date_oz = [16, 45, 75, 105, 136, 166, 197, 228, 258, 289, 319, 350]
+daysperyear = 365
+
+def ozn_time_int(julday, julian, ozmixm=None):
+ """Interpolate ozone concentration profile
+
+ Port of ozn_time_int subroutine from WRF
+ phys/module_radiation_driver.F
+
+ Parameters
+ ----------
+ julday: int
+ Day of year
+ julian: float
+ Day of year, 0.0 at 0Z on 1 Jan
+ ozmixm: np.array
+ Ozone concentration (nlon, nlev, nlat, nmonth)
+ """
+ ozncyc = True
+ intjulian = julian + 1.0
+ # Jan 1st 00Z is julian=1.0 here
+ ijul = int(intjulian)
+ intjulian = intjulian - ijul
+ ijul = ijul % 365
+ if ijul==0:
+ ijul = 365
+ intjulian = intjulian + ijul
+
+ np1 = 0
+ datefound = False
+ for m in range(12):
+ if (date_oz[m] > intjulian) and not datefound:
+ np1 = m
+ datefound = True
+ cdayozp = date_oz[np1]
+
+ if np1 > 0:
+ cdayozm = date_oz[np1-1]
+ np = np1
+ nm = np - 1
+ else:
+ cdayozm = date_oz[11]
+ np = np1 # ==0, jan
+ nm = 11 # dec
+
+ if ozncyc and np1 == 0:
+ # Dec-Jan interpolation
+ deltat = cdayozp + daysperyear - cdayozm
+ if intjulian > cdayozp:
+ print('interp in dec',cdayozm,cdayozp)
+ # We are in December
+ fact1 = (cdayozp + daysperyear - intjulian) / deltat
+ fact2 = (intjulian - cdayozm) / deltat
+ else:
+ print('interp in jan',cdayozm,cdayozp)
+ # We are in January
+ fact1 = (cdayozp - intjulian) / deltat
+ fact2 = (intjulian + daysperyear - cdayozm) / deltat
+ else:
+ print('interp in general',cdayozm,cdayozp)
+ deltat = cdayozp - cdayozm
+ fact1 = (cdayozp - intjulian) / deltat
+ fact2 = (intjulian - cdayozm) / deltat
+
+ if ozmixm is not None:
+ # WRF source has indices nm+1, np+1, which should be to account for
+ # module_ra_cam_suopport:oznini filling ozmixm starting from m=2...
+ return ozmixm[:,:,:,nm]*fact1 + ozmixm[:,:,:,np]*fact2
+ else:
+ return fact1, fact2
+'''
diff --git a/notebooks/read_CAM_ozone_data.ipynb b/notebooks/read_CAM_ozone_data.ipynb
new file mode 100644
index 0000000..738815c
--- /dev/null
+++ b/notebooks/read_CAM_ozone_data.ipynb
@@ -0,0 +1,686 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "4545ba45-299a-4092-a611-f96d8836287b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import xarray as xr\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "2037da30-bc62-4df3-9212-0fbffd828cac",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "wrfsrc = '/Users/equon/WRF/run'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "497259e0-89a3-430b-9454-06d37334b18c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "lat = np.loadtxt(f'{wrfsrc}/ozone_lat.formatted')\n",
+ "plev = np.loadtxt(f'{wrfsrc}/ozone_plev.formatted')\n",
+ "o3vmr = np.loadtxt(f'{wrfsrc}/ozone.formatted')\n",
+ "\n",
+ "nlat = len(lat)\n",
+ "nz = len(plev)\n",
+ "o3vmr = o3vmr.reshape((nz, nlat, 12), order='F')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "d84be422-bb42-4bec-ab6c-b5de2f6bbae6",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "
<xarray.Dataset>\n",
+ "Dimensions: (plev: 59, lat: 64, month: 12)\n",
+ "Coordinates:\n",
+ " * plev (plev) float64 1.004e+03 959.0 849.5 750.4 ... 0.3719 0.3254 0.2842\n",
+ " * lat (lat) float64 -87.86 -85.1 -82.31 -79.53 ... 79.53 82.31 85.1 87.86\n",
+ " * month (month) int64 1 2 3 4 5 6 7 8 9 10 11 12\n",
+ "Data variables:\n",
+ " o3vmr (plev, lat, month) float64 1.43e-08 8.647e-09 ... 1.78e-06
plev
(plev)
float64
1.004e+03 959.0 ... 0.3254 0.2842
- long_name :
- Pressure Levels
- units :
- mbar
array([1.00369e+03, 9.58981e+02, 8.49521e+02, 7.50393e+02, 6.60837e+02,\n",
+ " 5.80132e+02, 5.07601e+02, 4.42610e+02, 3.84573e+02, 3.32956e+02,\n",
+ " 2.87273e+02, 2.47079e+02, 2.11947e+02, 1.81445e+02, 1.55122e+02,\n",
+ " 1.32514e+02, 1.13155e+02, 9.66096e+01, 8.24830e+01, 7.04289e+01,\n",
+ " 6.01483e+01, 5.13840e+01, 4.39150e+01, 3.75509e+01, 3.21283e+01,\n",
+ " 2.75066e+01, 2.35659e+01, 2.02039e+01, 1.73342e+01, 1.48832e+01,\n",
+ " 1.27894e+01, 1.10000e+01, 9.47080e+00, 8.16370e+00, 7.04640e+00,\n",
+ " 6.09070e+00, 5.27280e+00, 4.57190e+00, 3.97050e+00, 3.45370e+00,\n",
+ " 3.00880e+00, 2.62530e+00, 2.29400e+00, 2.00740e+00, 1.75890e+00,\n",
+ " 1.54310e+00, 1.35510e+00, 1.19110e+00, 1.04760e+00, 9.21700e-01,\n",
+ " 8.11000e-01, 7.13500e-01, 6.27500e-01, 5.51400e-01, 4.84200e-01,\n",
+ " 4.24600e-01, 3.71900e-01, 3.25400e-01, 2.84200e-01])
lat
(lat)
float64
-87.86 -85.1 -82.31 ... 85.1 87.86
- long_name :
- Latitude
- units :
- deg
array([-87.8638 , -85.0965 , -82.3129 , -79.5256 , -76.7369 , -73.9475 ,\n",
+ " -71.1577 , -68.3678 , -65.5776 , -62.7873 , -59.997 , -57.2066 ,\n",
+ " -54.4162 , -51.6257 , -48.8352 , -46.0447 , -43.2542 , -40.4636 ,\n",
+ " -37.6731 , -34.8825 , -32.0919 , -29.3014 , -26.5108 , -23.7202 ,\n",
+ " -20.9296 , -18.139 , -15.3484 , -12.5578 , -9.76709, -6.9765 ,\n",
+ " -4.1859 , -1.3953 , 1.3953 , 4.1859 , 6.9765 , 9.7671 ,\n",
+ " 12.5578 , 15.3484 , 18.139 , 20.9296 , 23.7202 , 26.5108 ,\n",
+ " 29.3014 , 32.0919 , 34.8825 , 37.6731 , 40.4636 , 43.2542 ,\n",
+ " 46.0447 , 48.8352 , 51.6257 , 54.4162 , 57.2066 , 59.997 ,\n",
+ " 62.7873 , 65.5776 , 68.3678 , 71.1577 , 73.9475 , 76.7369 ,\n",
+ " 79.5256 , 82.3129 , 85.0965 , 87.8638 ])
month
(month)
int64
1 2 3 4 5 6 7 8 9 10 11 12
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
PandasIndex
PandasIndex(Index([1003.69, 958.981, 849.521, 750.393, 660.837, 580.132, 507.601, 442.61,\n",
+ " 384.573, 332.956, 287.273, 247.079, 211.947, 181.445, 155.122, 132.514,\n",
+ " 113.155, 96.6096, 82.483, 70.4289, 60.1483, 51.384, 43.915, 37.5509,\n",
+ " 32.1283, 27.5066, 23.5659, 20.2039, 17.3342, 14.8832, 12.7894, 11.0,\n",
+ " 9.4708, 8.1637, 7.0464, 6.0907, 5.2728, 4.5719, 3.9705, 3.4537,\n",
+ " 3.0088, 2.6253, 2.294, 2.0074, 1.7589, 1.5431, 1.3551, 1.1911,\n",
+ " 1.0476, 0.9217, 0.811, 0.7135, 0.6275, 0.5514, 0.4842, 0.4246,\n",
+ " 0.3719, 0.3254, 0.2842],\n",
+ " dtype='float64', name='plev'))
PandasIndex
PandasIndex(Index([-87.8638, -85.0965, -82.3129, -79.5256, -76.7369, -73.9475, -71.1577,\n",
+ " -68.3678, -65.5776, -62.7873, -59.997, -57.2066, -54.4162, -51.6257,\n",
+ " -48.8352, -46.0447, -43.2542, -40.4636, -37.6731, -34.8825, -32.0919,\n",
+ " -29.3014, -26.5108, -23.7202, -20.9296, -18.139, -15.3484, -12.5578,\n",
+ " -9.76709, -6.9765, -4.1859, -1.3953, 1.3953, 4.1859, 6.9765,\n",
+ " 9.7671, 12.5578, 15.3484, 18.139, 20.9296, 23.7202, 26.5108,\n",
+ " 29.3014, 32.0919, 34.8825, 37.6731, 40.4636, 43.2542, 46.0447,\n",
+ " 48.8352, 51.6257, 54.4162, 57.2066, 59.997, 62.7873, 65.5776,\n",
+ " 68.3678, 71.1577, 73.9475, 76.7369, 79.5256, 82.3129, 85.0965,\n",
+ " 87.8638],\n",
+ " dtype='float64', name='lat'))
PandasIndex
PandasIndex(Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype='int64', name='month'))
"
+ ],
+ "text/plain": [
+ "\n",
+ "Dimensions: (plev: 59, lat: 64, month: 12)\n",
+ "Coordinates:\n",
+ " * plev (plev) float64 1.004e+03 959.0 849.5 750.4 ... 0.3719 0.3254 0.2842\n",
+ " * lat (lat) float64 -87.86 -85.1 -82.31 -79.53 ... 79.53 82.31 85.1 87.86\n",
+ " * month (month) int64 1 2 3 4 5 6 7 8 9 10 11 12\n",
+ "Data variables:\n",
+ " o3vmr (plev, lat, month) float64 1.43e-08 8.647e-09 ... 1.78e-06"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ozone = xr.Dataset(\n",
+ " {\n",
+ " 'o3vmr': (('plev','lat','month'), o3vmr),\n",
+ " },\n",
+ " coords={'plev': plev, 'lat': lat, 'month': np.arange(1,13)},\n",
+ ")\n",
+ "\n",
+ "ozone.coords['plev'].attrs = {\n",
+ " 'long_name': 'Pressure Levels',\n",
+ " 'units': 'mbar',\n",
+ "}\n",
+ "ozone.coords['lat'].attrs = {\n",
+ " 'long_name': 'Latitude',\n",
+ " 'units': 'deg',\n",
+ "}\n",
+ "ozone['o3vmr'].attrs = {\n",
+ " 'long_name': 'Ozone Volume Mixing Ratio',\n",
+ " 'units': 'mol O3 / mol air',\n",
+ "}\n",
+ "\n",
+ "ozone = ozone.sortby('plev', ascending=False)\n",
+ "ozone"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "642d020e-e6a8-4807-a59d-c7d9c0f5873a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ozone.to_netcdf('data/ozone_CAM.nc')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8b065fcd-4d71-4975-beb4-0324efcf767c",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c0fb5e2c-e270-4a6e-8d22-d1464d6e8274",
+ "metadata": {},
+ "source": [
+ "## do some checks against literature"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "d782277e-c6fb-4191-9f96-b45718e68345",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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De/UrGKAw+Fwdw6Pl5iYqMTERElSXFycoqOjVVhYSDGgBcqq65x/7hDU7DoUAOAUGmdbsfQKAFxrS0MxYFBy82ZGA+2R6WWuF198UYMGDVJERIQiIiI0atQoffLJJy59jq+//lqXXHKJkpKSZLFY9P7775/0vBdeeEHdunVTcHCwhg0bpm+++eak561bt04Oh0MpKSkuzentGosBHYKsrLsCABcoatiulaVXAOBaW7LriwEDO1MMgPcyvRjQuXNnPf7441q3bp3WrVun8847T5deeqm2bdt20vO//fZb1dbWnnB8586dys3NPenXVFRUaPDgwXruuedOmeOdd97R7Nmz9eCDD2rjxo06++yzdeGFF+rQoUNNzisoKNDVV1+tl19+uQWvEpJUWlX//y0imFkBAOAKjTMDaB4IAK5ztLRaeWU2+VmkfokUA+C9TC8GXHLJJbrooovUq1cv9erVS4899pg6dOig77///oRzHQ6HbrnlFs2YMaNJg8Ldu3fr3HPP1euvv37S57jwwgv16KOP6rLLLjtljqefflrXX3+9fvOb36hv376aP3++UlJS9OKLLzrPsdls+uUvf6kHHnhAo0ePbsWr9k2NMwPCg7mDBQCu0LhDSxQzAwDAZRqXCKTFhSsk0N/kNID7mF4M+DG73a5FixapoqJCo0aNOuFxPz8/ffzxx9q4caOuvvpqORwO7du3T+edd56mTp2q++6774yet6amRuvXr9ekSZOaHJ80aZJWr14tSTIMQ9dcc43OO+88zZw582e/3/PPP69+/fppxIgRZ5THW5VV188MCGdmAOCzGB9dp87uUGlDkTWKngFAu8f46Dk2s0QAPsIjigFbtmxRhw4dFBQUpBtvvFGLFy9Wv379TnpuUlKSvvjiC3377beaMWOGzjvvPE2YMEEvvfTSGT9/fn6+7Ha74uPjmxyPj493Lj349ttv9c477+j9999Xenq60tPTtWXLlpN+v1tuuUXbt2/X2rVrzziTNzo+M4BiAOCrGB9dp6Tq+JK5SHZoAdo9xkfPsbWxGEDzQHi5M7oq27dvn1599VXt27dPf/vb3xQXF6dly5YpJSVF/fv3b/H36927tzIyMlRcXKx3331Xs2bN0sqVK09ZEOjSpYtef/11jRs3Tt27d9eCBQtksbS+Id1Pv4dhGM5jY8eOZVeFVip1zgzgTSsAtFZj88CIYKus/h5R2weAds8wDOe2gswMgLdr8buHlStXauDAgfrhhx/03nvvqby8XJK0efNmPfTQQ2cUIjAwUD179tTw4cM1b948DR48WH/7299Oef7Ro0f1u9/9TpdccokqKyt15513ntHzNoqNjZW/v/8JDQjz8vJOmC2AM8fMAABwHZoHAoDrHS21Kb/cJn8/i/olRpgdB3CrFhcDfv/73+vRRx/V8uXLFRh4/A3Iueeeq++++84loQzDkM1mO+lj+fn5mjBhgvr27av33ntPX3zxhf7v//5P99xzzxk/X2BgoIYNG6bly5c3Ob58+XIaBbpQYzEggumsANBqjc0DO9IvAABcZvPhYklSWlwHBQfQPBDercW3aLds2aK33377hOOdOnVSQUFBiwP84Q9/0IUXXqiUlBSVlZVp0aJF+uqrr7Rs2bITznU4HLrggguUmpqqd955R1arVX379tWKFSt07rnnKjk5+aSzBMrLy7V3717n55mZmcrIyFB0dLS6dOkiSbrrrrs0c+ZMDR8+XKNGjdLLL7+sQ4cO6cYbb2zxa8LJldJAEABcprhhmUA0OwkAgMvQLwC+pMVXZR07dlROTo66devW5PjGjRuVnJzc4gBHjx7VzJkzlZOTo8jISA0aNEjLli3T+eeff8K5fn5+mjdvns4+++wmsxIGDhyoFStWKCYm5qTPsW7dOp177rnOz++66y5J0qxZs7Rw4UJJ0q9//WsVFBTokUceUU5OjgYMGKCPP/5YqampLX5NOLkyegYAgMs4lwkwMwAAXKZxJ4FB9AuAD2hxMWDGjBm6//779Z///EcWi0UOh0Pffvut7rnnHl199dUtDrBgwYIWnX+yIoEkpaenn/Jrxo8fL8MwTvu9b775Zt18880tyoPmcy4TYGYAALRaYwNBlgkAgGsYhqEtDc0DBzAzAD6gxT0DHnvsMXXp0kXJyckqLy9Xv379dM4552j06NH64x//6I6M8BI0EAQA12nsGRDFMgEAcImckmoVVNTI6mdRX5oHwge0+KosICBAb731lh555BFt3LhRDodDQ4YMUVpamjvywYuwTAAAXIfdBADAtRq3FEyLD6d5IHzCGd+i7dGjh3r06OHKLPByx5cJUAwAgNZqbCBIzwAAcI3G5oGDWCIAH9GsYkBjw73mePrpp884DLwbywQAwHWONxCkwAoA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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# c.f. Saiz-Lopez et al. 2012, ACP -- Fig. 3\n",
+ "\n",
+ "gala = ozone['o3vmr'].interp(lat=1. ).mean('month')\n",
+ "fiji = ozone['o3vmr'].interp(lat=18.).mean('month')\n",
+ "naha = ozone['o3vmr'].interp(lat=26.).mean('month')\n",
+ "\n",
+ "fig,axs = plt.subplots(ncols=3,sharex=True,sharey=True,figsize=(12,4))\n",
+ "axs[0].semilogy(gala/1e-9, ozone.plev)\n",
+ "axs[1].semilogy(fiji/1e-9, ozone.plev)\n",
+ "axs[2].semilogy(naha/1e-9, ozone.plev)\n",
+ "\n",
+ "axs[0].set_ylabel('Altitude [hPa]')\n",
+ "for ax in axs:\n",
+ " ax.set_xlabel\n",
+ "axs[0].set_ylim((100,1000))\n",
+ "axs[0].set_xlim((0,150))\n",
+ "axs[0].set_xticks(np.arange(0,150,20))\n",
+ "ylabels = [100,200,400,600,1000]\n",
+ "axs[0].set_yticks(ylabels)\n",
+ "axs[0].set_yticklabels(ylabels)\n",
+ "axs[0].invert_yaxis()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "600aac0c-1006-4655-9248-e46ee8277318",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Text(0, 0.5, 'Pressure [hPa]')"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# c.f. Montornes et al. 2015, ACP -- Fig. 1\n",
+ "midlat_summer = ozone['o3vmr'].sel(lat=slice(30,60),month=[6,7,8]).mean(['lat','month'])\n",
+ "midlat_winter = ozone['o3vmr'].sel(lat=slice(30,60),month=[12,1,2]).mean(['lat','month'])\n",
+ "arctic_summer = ozone['o3vmr'].sel(lat=slice(60,90),month=[6,7,8]).mean(['lat','month'])\n",
+ "arctic_winter = ozone['o3vmr'].sel(lat=slice(60,90),month=[12,1,2]).mean(['lat','month'])\n",
+ "\n",
+ "fig,ax = plt.subplots()\n",
+ "ax.semilogy(midlat_summer, ozone.plev, 'tab:purple', label='mid lat summer')\n",
+ "ax.semilogy(midlat_winter, ozone.plev, 'tab:red', label='mid lat winter')\n",
+ "ax.semilogy(arctic_summer, ozone.plev, 'tab:green', label='arctic summer')\n",
+ "ax.semilogy(arctic_winter, ozone.plev, 'tab:orange', label='arctic winter')\n",
+ "ax.invert_yaxis()\n",
+ "ax.set_yticks(10.**np.arange(-4,4))\n",
+ "ax.grid(alpha=0.25)\n",
+ "ax.legend(loc='upper left',bbox_to_anchor=(1,1))\n",
+ "ax.set_xlabel('Ozone volume mixing ratio')\n",
+ "ax.set_ylabel('Pressure [hPa]')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "37453d55-d86b-40e6-ad5d-481ebc8fe747",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "forge",
+ "language": "python",
+ "name": "forge"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..991739a
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,74 @@
+[build-system]
+requires = ["setuptools>=64", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "erftools"
+version = "0.1.1"
+description = "Python code to make life easier for users of the Energy Research & Forecasting model"
+authors = [
+ {name = "U.S. Department of Energy", email = "eliot.quon@nrel.gov"}
+]
+readme = "README.md"
+license = "Apache-2.0"
+
+classifiers = [
+ "Development Status :: 4 - Beta",
+ "Intended Audience :: Science/Research",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+]
+
+requires-python = ">=3.9"
+
+dependencies = [
+ "numpy>=2.0.2",
+ "scipy>=1.13.1",
+ "pandas>=2.3.2",
+ "xarray>=2024.7.0",
+ "netcdf4>=1.7.2",
+ "h5netcdf>=1.6.4",
+ "bottleneck>=1.5.0",
+ "pydantic",
+ "f90nml",
+ "click",
+ "ussa1976",
+]
+
+[project.optional-dependencies]
+dev = [
+ "jupyter",
+ "matplotlib",
+]
+performance = [
+ "dask>=2024.8.0",
+ "mpi4py>=4.1.0",
+]
+grib = [
+ "pygrib>=2.1.6",
+ "cdsapi>=0.7.6",
+ "herbie-data>=2024.8.0",
+ "cartopy>=0.23.0",
+ "pyproj>=3.6.1",
+]
+all = [
+ "erftools[dev,performance,grib]"
+]
+
+[tool.setuptools]
+packages = ["erftools"]
+
+# Console scripts -- creates command line tools
+[project.scripts]
+check_erf_input = "erftools.inputs:check_erf_input"
+wrf_namelist_to_erf = "erftools.wrf.inputdeck:wrf_namelist_to_erf"
+generate_ozone_profile = "erftools.wrf.rad:generate_ozone_profile"
+
+[project.urls]
+Homepage = "https://erf.readthedocs.io/en/latest/"
+Repository = "https://github.com/erf-model/erftools"
+Issues = "https://github.com/erf-model/erftools/issues"
+
diff --git a/setup.py b/setup.py
deleted file mode 100644
index fd343f0..0000000
--- a/setup.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# This setup file is based on https://github.com/a2e-mmc/mmctools/blob/master/setup.py
-# accessed on April 3, 2020.
-
-# Note: To use the 'upload' functionality of this file, you must:
-# $ pip install twine
-
-import io
-import os
-
-from setuptools import find_packages, setup
-
-# Package meta-data.
-NAME = 'erftools'
-DESCRIPTION = 'Scripts to make life easier for users of the Energy Research & Forecasting model'
-URL = 'https://github.com/erf-model/erftools'
-EMAIL = 'eliot.quon@nrel.gov'
-AUTHOR = 'U.S. Department of Energy'
-REQUIRES_PYTHON = '>=3.6.0'
-VERSION = '0.1.1'
-
-# What packages are required for this module to be executed?
-REQUIRED = [
- # core
- 'numpy>=1.18.1',
- 'pandas>=1.0.1',
- 'xarray>=0.15.0',
- 'netcdf4>=1.5.1',
- 'pydantic',
- 'f90nml',
- 'cartopy',
- #'matplotlib>=3',
- #'scipy>=1.4.1',
- #'dask>=2.10.1',
- #'utm>=0.5.0',
-]
-
-EXTRAS = {
-}
-
-# The rest you shouldn't have to touch too much :)
-# ------------------------------------------------
-# Except, perhaps the License and Trove Classifiers!
-# If you do change the License, remember to change the Trove Classifier for that!
-
-here = os.path.abspath(os.path.dirname(__file__))
-
-# Import the README and use it as the long-description.
-# Note: this will only work if 'README.md' is present in your MANIFEST.in file!
-try:
- with io.open(os.path.join(here, 'README.md'), encoding='utf-8') as f:
- long_description = '\n' + f.read()
-except FileNotFoundError:
- long_description = DESCRIPTION
-
-# Load the package's __version__.py module as a dictionary.
-about = {}
-if not VERSION:
- project_slug = NAME.lower().replace("-", "_").replace(" ", "_")
- with open(os.path.join(here, project_slug, '__version__.py')) as f:
- exec(f.read(), about)
-else:
- about['__version__'] = VERSION
-
-# Where the magic happens:
-setup(
- name=NAME,
- version=about['__version__'],
- description=DESCRIPTION,
- long_description=long_description,
- long_description_content_type='text/markdown',
- author=AUTHOR,
- author_email=EMAIL,
- python_requires=REQUIRES_PYTHON,
- url=URL,
- #packages=find_packages(exclude=["tests", "*.tests", "*.tests.*", "tests.*"]),
- # If your package is a single module, use this instead of 'packages':
- py_modules=[NAME],
- # entry_points={
- # 'console_scripts': ['mycli=mymodule:cli'],
- # },
- install_requires=REQUIRED,
- extras_require=EXTRAS,
- include_package_data=True,
- license='Apache-2.0',
- classifiers=[
- # Trove classifiers
- # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
- 'License :: OSI Approved :: Apache Software License',
- 'Topic :: Scientific/Engineering',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3',
- 'Development Status :: 4 - Beta',
- ],
- # $ setup.py publish support.
- #cmdclass={
- # 'upload': UploadCommand,
- #},
-)