Tutorial 1: Assimilate
Now, we can set up a workflow in the script tutorial_assim.py.
In the following, its contents are explained step-by-step.
The first block of imports never changes.
from dartwrf.workflows import WorkFlows
from dartwrf.utils import Config
Default configuration
The second block of imports loads dictionaries that contain a default configuration.
You can customize those by modifying config/jet.py and config/defaults.py.
from config.jet import cluster_defaults
from config.defaults import dart_nml
Set ensemble size
The ensemble size needs to be set in the DART namelist and for DART-WRF.
To do that, we overwrite the default values in dart_nml:
ensemble_size = 10
dart_nml['&filter_nml'].update(num_output_state_members=ensemble_size,
ens_size=ensemble_size)
cluster_defaults.update(ensemble_size=ensemble_size,)
Select observations
To create observations one by one, follow the instructions in the DART documentation for the
perfect_model_obsprogram.To use existing obs_seq files, set
assimilate_existing_obsseq = '/jetfs/scratch/username/obs/%Y-%m-%d_%H:%M_obs_seq.out'where time-placeholders (%Y-%m-%d_%H:%M) are filled in later, depending on the assimilation time.To create observations on the fly, set
assimilate_existing_obsseq = False.
By default, the DART namelist of the build directory will be used.
If you want to set different parameters, specify your changes in /config/defaults.py or provide
them as arguments to the dartwrf.utils.Config instance.
For a description of DART’s parameters, see the official DART documentation.
Single observation
To define an observation type, we use a dictionary. If you want to assimilate radiosonde temperature observations, use
t = dict(
kind='RADIOSONDE_TEMPERATURE',
obs_locations=[(45., 0.)], # location of observations
error_generate=0.25, # observation error used to generate observations
error_assimilate=0.5, # observation error used for assimilation
heights=[1000,], # for radiosondes, use range(1000, 17001, 2000)
loc_horiz_km=50, # horizontal localization half-width
loc_vert_km=2.5 # vertical localization half-width
)
assimilate_these_observations = [t,] # select observations for assimilation
kindis the observation type as defined by DART (DART/observations/forward_operators/obs_def_mod.f90)obs_locationstakes a list of coordinates for each observation
Multiple observations
To generate a grid of observations with homogeneous observation density,
set km_between_obs``and ``skip_border_km.
t2m = dict(..., km_between_obs=12, skip_border_km=8.0,)
assimilate_these_observations = [t2m,]
Alternatively, provide coordinates to the obs_locations argument of the obs-type:
t2m = dict(..., obs_locations=[(45., 0.), (45.1, 0.),],)
assimilate_these_observations = [t2m,]
For vertical observations, set the heights parameter to specify the vertical levels at which to generate observations:
t = dict(..., heights=[1000, 2000, 3000])
assimilate_these_observations = [t,]
Modify localization radius
To modify the localization radius for an observation, set the loc_horiz_km and loc_vert_km parameters in the observation dictionary:
t = dict(..., loc_horiz_km=100, loc_vert_km=5)
assimilate_these_observations = [t,]
Modify observation error
To assimilate observations assuming a larger error, set the error_assimilate parameter in the observation dictionary, e.g.:
t = dict(..., error_assimilate=1.2)
assimilate_these_observations = [t,]
Passing config parameters
We create a dartwrf.utils.Config object and fill it with all parameters we want.
nameshould be a unique experiment name and will be used as folder nameupdate_varsare the WRF variables which shall be updated by the assimilationtimeis the time of the assimilationdart_nmlis a dictionary with DART namelist parameters
Which parameters are required? This depends on the code you’re running.
The advantage of this behavior is that you can easily introduce new parameters.
You just need to pass them as argument into dartwrf.utils.Config.
Existing configs can be updated by calling cfg.update(new_parameter = 'abc').
Assimilate
In this example, we set up the run_WRF directories with w.prepare_WRFrundir(cfg) and
then assimilate using w.assimilate(cfg).
Workflow methods are defined in DART-WRF/dartwrf/workflows.py.
cfg = Config(
name='exp1',
dart_nml = dart_nml,
assimilate_these_observations = [t2m,],
assimilate_existing_obsseq = False,
nature_wrfout_pattern = '/jetfs/scratch/username/raw_data/nature/*/1/wrfout_d01_%Y-%m-%d_%H_%M_%S',
geo_em_nature = '/jetfs/scratch/username/geo_em.d01.nc',
geo_em_forecast = '/jetfs/scratch/username/geo_em.d01.nc',
time = dt.datetime(2008, 7, 30, 13),
update_vars = ['THM', 'PH', 'MU', 'QVAPOR',],
**cluster_defaults)
w = WorkFlows(cfg)
w.prepare_WRFrundir(cfg)
w.assimilate(cfg)
Execute the script with python tutorial_assim.py.