From e1495b9611749006242962dae3d021d5f1056c1e Mon Sep 17 00:00:00 2001 From: Lukas Kugler <lukas.kugler@univie.ac.at> Date: Thu, 27 Feb 2025 12:36:07 +0100 Subject: [PATCH] unfinished --- config/jet.py | 4 +- dartwrf/evaluate_obs_space.py | 4 +- dartwrf/evaluate_prior.py | 4 +- docs/source/tutorial1.rst | 4 +- free_forecast2.py | 49 ++++++++++ multiple_exps.py | 173 ++++++++++++++++++++-------------- tests/test_assim.py | 2 +- 7 files changed, 162 insertions(+), 78 deletions(-) create mode 100644 free_forecast2.py diff --git a/config/jet.py b/config/jet.py index ed06145..5b30a22 100755 --- a/config/jet.py +++ b/config/jet.py @@ -2,7 +2,7 @@ cluster_defaults = dict( max_nproc = 20, - max_nproc_for_each_ensemble_member = 16, + max_nproc_for_each_ensemble_member = 9, use_slurm = True, # binaries @@ -20,7 +20,7 @@ cluster_defaults = dict( # paths used as input dir_wrf_src = '/jetfs/home/lkugler/data/compile/WRF-4.3/run', - dir_dart_src = '/jetfs/home/lkugler/data/compile/DART/DART-10.8.3_10pct/models/wrf/work/', + dir_dart_src = '/jetfs/home/lkugler/data/compile/DART/DART-10.8.3/models/wrf/work/', dir_rttov_src = '/jetfs/home/lkugler/data/compile/RTTOV13/rtcoef_rttov13/', dir_dartwrf_dev = '/jetfs/home/lkugler/DART-WRF/', diff --git a/dartwrf/evaluate_obs_space.py b/dartwrf/evaluate_obs_space.py index 05d8b67..b772111 100755 --- a/dartwrf/evaluate_obs_space.py +++ b/dartwrf/evaluate_obs_space.py @@ -21,9 +21,9 @@ def evaluate_one_time(assim_time, valid_time, use_other_obsseq=False): aso.prepare_prior_ensemble(valid_time, prior_init_time=assim_time, prior_valid_time=valid_time, prior_path_exp=cluster.archivedir) dart_nml.write_namelist() - if os.path.isfile(exp.use_existing_obsseq): + if os.path.isfile(exp.assimilate_existing_obsseq): # use the existing obs_seq.out file - shutil.copy(exp.use_existing_obsseq, cluster.dart_rundir+'/obs_seq.out') + shutil.copy(exp.assimilate_existing_obsseq, cluster.dart_rundir+'/obs_seq.out') else: # is there a pre-existing obs file from assimilation before? f_oso = valid_time.strftime(cluster.pattern_obs_seq_out) diff --git a/dartwrf/evaluate_prior.py b/dartwrf/evaluate_prior.py index d218751..8f7ed49 100755 --- a/dartwrf/evaluate_prior.py +++ b/dartwrf/evaluate_prior.py @@ -21,8 +21,8 @@ if __name__ == "__main__": aso.prepare_prior_ensemble(assim_time, prior_init, prior_valid_time, cluster.archive_base+'/'+prior_exp) # prepare an obsseq without rejected observations - if exp.use_existing_obsseq: # from another exp - oso_input = assim_time.strftime(exp.use_existing_obsseq) + if exp.assimilate_existing_obsseq: # from another exp + oso_input = assim_time.strftime(exp.assimilate_existing_obsseq) else: # from same exp oso_input = cluster.archivedir+'/obs_seq_out' + assim_time.strftime("/%Y-%m-%d_%H:%M_obs_seq.out-beforeQC") if not os.path.isfile(oso_input): diff --git a/docs/source/tutorial1.rst b/docs/source/tutorial1.rst index ed73fa4..25f5332 100644 --- a/docs/source/tutorial1.rst +++ b/docs/source/tutorial1.rst @@ -61,7 +61,7 @@ In case you want to generate new observations, like for an observing system simu .. code-block:: python - exp.use_existing_obsseq = False + exp.assimilate_existing_obsseq = False in this case, you need to set the path to WRF nature run files from where DART can generate observations: @@ -77,7 +77,7 @@ You can use pre-existing observation files with .. code-block:: python - exp.use_existing_obsseq = '/usr/data/sim_archive/exp_ABC/obs_seq_out/%Y-%m-%d_%H:%M_obs_seq.out' + exp.assimilate_existing_obsseq = '/usr/data/sim_archive/exp_ABC/obs_seq_out/%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. diff --git a/free_forecast2.py b/free_forecast2.py new file mode 100644 index 0000000..70182c1 --- /dev/null +++ b/free_forecast2.py @@ -0,0 +1,49 @@ +import sys +import datetime as dt +import pandas as pd +from dartwrf.workflows import WorkFlows +from dartwrf.utils import Config + + +# import default config for jet +from config.jet import cluster_defaults +from config.defaults import dart_nml, CF_config + + +ensemble_size = 1 +t0 = dt.datetime(2008, 7, 30, 8) + +for c_s in [0.15, 0.2]: + + id = None + cfg = Config(name='exp_nat250m_Cs'+str(c_s), + model_dx = 2000, + ensemble_size = ensemble_size, + geo_em_forecast = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.2km_200x200', + time = t0, + c_s = str(c_s), + + input_profile = '/jetfs/home/lkugler/data/sim_archive/nat_250m_1600x1600x100/2008-07-30_08:00/1/input_sounding', + verify_against = 'nat_250m_blockavg2km', + **cluster_defaults, # type: ignore + ) + + + w = WorkFlows(cfg) + w.prepare_WRFrundir(cfg) + id = w.run_ideal(cfg, depends_on=id) + + timedelta_integrate = dt.timedelta(hours=10) + restart_interval = 9999 + + cfg.update( WRF_start=t0, + WRF_end=t0+timedelta_integrate, + restart=False, + restart_interval=restart_interval, + hist_interval_s=300, + ) + # only verification depends on the output + id_long = w.run_WRF(cfg, depends_on=id) + id_long = w.run_RTTOV(cfg, depends_on=id_long) + + w.verify(cfg, depends_on=id_long) \ No newline at end of file diff --git a/multiple_exps.py b/multiple_exps.py index 44019cf..6aa2a94 100644 --- a/multiple_exps.py +++ b/multiple_exps.py @@ -1,3 +1,4 @@ +import sys import datetime as dt import pandas as pd from dartwrf.workflows import WorkFlows @@ -6,89 +7,103 @@ from dartwrf.utils import Config # import default config for jet from config.jet import cluster_defaults -from config.defaults import dart_nml +from config.defaults import dart_nml, CF_config, vis # test multiple assimilation windows (11-12, 12-13, 13-14, ) timedelta_btw_assim = dt.timedelta(minutes=15) -assim_times_start = pd.date_range('2008-07-30 11:00', '2008-07-30 13:00', freq='1h') ensemble_size = 40 dart_nml['&filter_nml'].update(num_output_state_members=ensemble_size, ens_size=ensemble_size) -vis = dict( - kind='MSG_4_SEVIRI_BDRF', sat_channel=1, - km_between_obs=12, skip_border_km=8.0, - error_generate=0.03, error_assimilate=0.06, - loc_horiz_km=20, - height=6000, loc_vert_km=6, - ) +# which DART version to use? +assimilate_cloudfractions = True +cf1 = dict(kind='CF192km', loc_horiz_km=9999) +cf2 = dict(kind='CF96km', loc_horiz_km=96) +cf3 = dict(kind='CF48km', loc_horiz_km=48) +cf4 = dict(kind='CF24km', loc_horiz_km=24) +cf5 = dict(kind='CF12km', loc_horiz_km=12) -for t0 in assim_times_start: +assimilate_these_observations = [cf5] - id = None - cfg = Config(name=t0.strftime('exp_nat250_VIS_obs12_loc20_oe2_inf4-0.5_%H%M'), - model_dx = 2000, - ensemble_size = ensemble_size, - dart_nml = dart_nml, - geo_em_forecast = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.2km_200x200', - time = t0, - - use_existing_obsseq = False, - nature_wrfout_pattern = '/jetfs/home/lkugler/data/sim_archive/nat_250m_1600x1600x100/*/1/wrfout_d01_%Y-%m-%d_%H_%M_%S', - #geo_em_nature = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.2km_200x200', - geo_em_nature = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.250m_1600x1600', - - update_vars = ['U', 'V', 'W', 'THM', 'PH', 'MU', 'QVAPOR', 'QCLOUD', 'QICE', 'QSNOW', 'PSFC'], - input_profile = '/jetfs/home/lkugler/data/sim_archive/nat_250m_1600x1600x100/2008-07-30_08:00/1/input_sounding', - nature_exp_verif = 'nat_250m_blockavg2km', - assimilate_these_observations = [vis,], - **cluster_defaults, # type: ignore +if assimilate_cloudfractions: + cluster_defaults.update( + dir_dart_src = '/jetfs/home/lkugler/data/compile/DART/DART-v10.9.2-andrea/models/wrf/work/', ) +else: + for obs in assimilate_these_observations: + if obs['kind'] == 'MSG_4_SEVIRI_BDRF': + cluster_defaults.update( + dir_dart_src = '/jetfs/home/lkugler/data/compile/DART/DART-10.8.3_10pct/models/wrf/work/', + ) + - w = WorkFlows(cfg) - w.prepare_WRFrundir(cfg) - #id = w.run_ideal(cfg, depends_on=id) + +time0 = dt.datetime(2008, 7, 30, 11) + +id = None +cfg = Config(name='exp_nat250_VIS_SO12_loc12_oe2_inf4-0.5', + model_dx = 2000, + ensemble_size = ensemble_size, + dart_nml = dart_nml, + geo_em_forecast = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.2km_200x200', + time = time0, + + assimilate_these_observations = assimilate_these_observations, + assimilate_cloudfractions = assimilate_cloudfractions, + CF_config=CF_config, + + assimilate_existing_obsseq = False, + #nature_wrfout_pattern = '/jetfs/home/lkugler/data/sim_archive/nat_250m_1600x1600x100/*/1/wrfout_d01_%Y-%m-%d_%H_%M_%S', + #geo_em_nature = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.2km_200x200', + # geo_em_nature = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.250m_1600x1600', - # assimilate at these times - time0 = cfg.time - assim_times = pd.date_range(time0, time0 + dt.timedelta(hours=1), freq=timedelta_btw_assim) - last_assim_time = assim_times[-1] + update_vars = ['U', 'V', 'W', 'THM', 'PH', 'MU', 'QVAPOR', 'QCLOUD', 'QICE', 'QSNOW', 'PSFC'], + #input_profile = '/jetfs/home/lkugler/data/sim_archive/nat_250m_1600x1600x100/2008-07-30_08:00/1/input_sounding', + verify_against = 'nat_250m_blockavg2km', + **cluster_defaults) - # loop over assimilations - for i, t in enumerate(assim_times): - - if i == 0: - if t == dt.datetime(2008, 7, 30, 11): - prior_init_time = dt.datetime(2008, 7, 30, 8) - else: - prior_init_time = t - dt.timedelta(minutes=15) - - cfg.update(time = t, - prior_init_time = prior_init_time, - prior_valid_time = t, - prior_path_exp = '/jetfs/home/lkugler/data/sim_archive/exp_nat250m_noDA/',) - else: - cfg.update(time = t, - prior_init_time = assim_times[i-1], - prior_valid_time = t, - prior_path_exp = cfg.dir_archive,) - - - id = w.assimilate(cfg, depends_on=id) - - # 1) Set posterior = prior - id = w.prepare_IC_from_prior(cfg, depends_on=id) - - # 2) Update posterior += updates from assimilation - id = w.update_IC_from_DA(cfg, depends_on=id) - - if t == last_assim_time: - restart_interval = 9999 - timedelta_integrate = dt.timedelta(hours=4) + +w = WorkFlows(cfg) +w.prepare_WRFrundir(cfg) +#id = w.run_ideal(cfg, depends_on=id) + +# assimilate at these times +assim_times = pd.date_range(time0, time0 + dt.timedelta(hours=4), freq=timedelta_btw_assim) +last_assim_time = assim_times[-1] + +# loop over assimilations +for i, t in enumerate(assim_times): + + if i == 0: + if t == dt.datetime(2008, 7, 30, 11): + prior_init_time = dt.datetime(2008, 7, 30, 8) else: - restart_interval = timedelta_btw_assim.total_seconds()/60 # in minutes - timedelta_integrate = dt.timedelta(minutes=15) + prior_init_time = t - dt.timedelta(minutes=15) + + cfg.update(time = t, + prior_init_time = prior_init_time, + prior_valid_time = t, + prior_path_exp = '/jetfs/home/lkugler/data/sim_archive/exp_nat250m_noDA/',) + else: + cfg.update(time = t, + prior_init_time = assim_times[i-1], + prior_valid_time = t, + prior_path_exp = cfg.dir_archive,) + + + id = w.assimilate(cfg, depends_on=id) + + # 1) Set posterior = prior + id = w.prepare_IC_from_prior(cfg, depends_on=id) + + # 2) Update posterior += updates from assimilation + id = w.update_IC_from_DA(cfg, depends_on=id) + + if t != last_assim_time: + # integrate until next assimilation + timedelta_integrate = dt.timedelta(minutes=15) + restart_interval = timedelta_btw_assim.total_seconds()/60 # in minutes cfg.update( WRF_start=t, WRF_end=t+timedelta_integrate, @@ -98,4 +113,24 @@ for t0 in assim_times_start: ) # 3) Run WRF ensemble - id = w.run_WRF(cfg, depends_on=id) \ No newline at end of file + id = w.run_WRF(cfg, depends_on=id) + id = w.run_RTTOV(cfg, depends_on=id) + + if t.minute == 0 and i != 0: + # full hour but not first one + # make long forecasts without restart files + timedelta_integrate = dt.timedelta(hours=4) + restart_interval = 9999 + + cfg.update( WRF_start=t, + WRF_end=t+timedelta_integrate, + restart=True, + restart_interval=restart_interval, + hist_interval_s=300, + ) + # only verification depends on the output + # but we only have one run directory, so we need to wait until the other forecast is done + id = w.run_WRF(cfg, depends_on=id) + id = w.run_RTTOV(cfg, depends_on=id) + +w.verify(cfg, depends_on=id) \ No newline at end of file diff --git a/tests/test_assim.py b/tests/test_assim.py index 875d670..c68ed35 100644 --- a/tests/test_assim.py +++ b/tests/test_assim.py @@ -32,7 +32,7 @@ def test_dartwrf_cycled_da(): geo_em_forecast = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.2km_200x200', time = dt.datetime(2008, 7, 30, 11), - use_existing_obsseq = False, + assimilate_existing_obsseq = False, nature_wrfout_pattern = '/jetfs/home/lkugler/data/sim_archive/nat_250m_1600x1600x100/*/1/wrfout_d01_%Y-%m-%d_%H_%M_%S', #geo_em_nature = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.2km_200x200', geo_em_nature = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.250m_1600x1600', -- GitLab