From 52c8740675cc28b1df5e612ea6f998358ada40f2 Mon Sep 17 00:00:00 2001
From: Lukas Kugler <lukas.kugler@univie.ac.at>
Date: Tue, 6 May 2025 16:28:51 +0200
Subject: [PATCH] example without SLURM

---
 dartwrf/dart_nml.py                     |   2 +-
 templates/namelist.input                |   4 +-
 templates/namelist.input-testsinglenode | 130 ++++++++++++++++++++++++
 test-singlenode.py                      | 120 +++++++++++++++-------
 4 files changed, 216 insertions(+), 40 deletions(-)
 create mode 100644 templates/namelist.input-testsinglenode

diff --git a/dartwrf/dart_nml.py b/dartwrf/dart_nml.py
index 1c63560..78abffc 100644
--- a/dartwrf/dart_nml.py
+++ b/dartwrf/dart_nml.py
@@ -420,6 +420,7 @@ def write_namelist(cfg: Config, just_prior_values=False) -> dict:
     # write to file
     dir_dart_run = cfg.dir_dart_run.replace('<exp>', cfg.name)
     write_namelist_from_dict(nml, dir_dart_run + "/input.nml")
+    print('Wrote namelist to', dir_dart_run + "/input.nml")
 
     # append section for RTTOV
     if hasattr(cfg, 'rttov_nml'):
@@ -433,4 +434,3 @@ if __name__ == "__main__":
     cfg = Config.from_file(sys.argv[1])
 
     nml = write_namelist(cfg)
-    print(nml)
diff --git a/templates/namelist.input b/templates/namelist.input
index 430be87..1f6f9a1 100644
--- a/templates/namelist.input
+++ b/templates/namelist.input
@@ -43,8 +43,8 @@
  e_sn                                = 201,    43,    43,
  s_vert                              = 1,     1,     1,
  e_vert                              = 101,    41,    41,
- dx                                  = 1000,  666.6666667, 222.2222222
- dy                                  = 1000,  666.6666667, 222.2222222
+ dx                                  = 2000,  666.6666667, 222.2222222
+ dy                                  = 2000,  666.6666667, 222.2222222
  ztop                                = 22000, 20000, 20000,
  grid_id                             = 1,     2,     3,
  parent_id                           = 0,     1,     2,
diff --git a/templates/namelist.input-testsinglenode b/templates/namelist.input-testsinglenode
new file mode 100644
index 0000000..07c2f4d
--- /dev/null
+++ b/templates/namelist.input-testsinglenode
@@ -0,0 +1,130 @@
+ &time_control
+ start_year                          = 2000, 2001, 2001,
+ start_month                         = 01,   01,   01,
+ start_day                           = 01,   01,   01,
+ start_hour                          = 00,   00,   00,
+ start_minute                        = 00,   00,   00,
+ start_second                        = 00,   00,   00,
+ end_year                            = 2001, 2001, 2001,
+ end_month                           = 01,   01,   01,
+ end_day                             = 01,   01,   01,
+ end_hour                            = 00,   00,   00,
+ end_minute                          = 00,   00,   00,
+ end_second                          = 00,   00,   00,
+ interval_seconds                    = 86400
+ history_interval_s                  = 300,
+ write_hist_at_0h_rst                = .true.,
+ frames_per_outfile                  = 1, 1, 1,
+ restart                             = .false.,
+ override_restart_timers             = .true.,
+ restart_interval                    = 99999,
+ io_form_history                     = 2
+ io_form_restart                     = 2
+ io_form_input                       = 2
+ io_form_boundary                    = 2
+ nwp_diagnostics 		     = 0
+ /
+
+ &domains
+ use_adaptive_time_step              = .true.,
+ target_cfl                          = 1.2, 1.2, 1.2,
+ max_step_increase_pct               = 5, 51, 51,
+ starting_time_step                  = 4,
+ max_time_step                       = 16,
+ min_time_step                       = 3,
+ time_step                           = 8,
+ time_step_fract_num                 = 0,
+ time_step_fract_den                 = 1,
+ step_to_output_time		     = .true.,
+ max_dom                             = 1,
+ s_we                                = 1,     1,     1,
+ e_we                                = 201,    43,    43,
+ s_sn                                = 1,     1,     1,
+ e_sn                                = 201,    43,    43,
+ s_vert                              = 1,     1,     1,
+ e_vert                              = 11,    41,    41,
+ dx                                  = 2000,  666.6666667, 222.2222222
+ dy                                  = 2000,  666.6666667, 222.2222222
+ ztop                                = 10000, 20000, 20000,
+ grid_id                             = 1,     2,     3,
+ parent_id                           = 0,     1,     2,
+ i_parent_start                      = 0,     15,    15,
+ j_parent_start                      = 0,     15,    15,
+ parent_grid_ratio                   = 1,     3,     3,
+ parent_time_step_ratio              = 1,     3,     3,
+ !eta_levels = 1.0000, 0.9969, 0.9923, 0.9857, 0.9762, 0.9627, 0.9443, 0.9200, 0.8892, 0.8525, 0.8111, 0.7671, 0.7223, 0.6782, 0.6357, 0.5949, 0.5558, 0.5183, 0.4824, 0.4482, 0.4155, 0.3844, 0.3547, 0.3266, 0.2999, 0.2750, 0.2519, 0.2304, 0.2105, 0.1919, 0.1747, 0.1586, 0.1437, 0.1299, 0.1170, 0.1050, 0.0939, 0.0836, 0.0740, 0.0650, 0.0567, 0.0490, 0.0419, 0.0352, 0.0290, 0.0232, 0.0179, 0.0129, 0.0083, 0.0040, 0.0000
+ !eta_levels =  1.0000, 0.99, 0.98, 0.97, 0.96, 0.95, 0.94, 0.93, 0.92, 0.91, 0.9, 0.89, 0.88, 0.87, 0.86, 0.85, 0.84, 0.83, 0.82, 0.81, 0.8, 0.79, 0.78, 0.77, 0.76, 0.75, 0.74, 0.73, 0.72, 0.71, 0.7, 0.69, 0.68, 0.67, 0.66, 0.65, 0.64, 0.63, 0.62, 0.61, 0.6, 0.59, 0.58, 0.57, 0.56, 0.55, 0.54, 0.53, 0.52, 0.51, 0.5, 0.49, 0.48, 0.47, 0.46, 0.45, 0.44, 0.43, 0.42, 0.41, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.32, 0.31, 0.3, 0.29, 0.28, 0.27, 0.26, 0.25, 0.24, 0.23, 0.22, 0.21, 0.2, 0.19, 0.18, 0.17, 0.16, 0.15, 0.14, 0.13, 0.12, 0.11, 0.1, 0.08999997, 0.07999998, 0.06999999, 0.06, 0.05000001, 0.04000002, 0.02999997, 0.01999998, 0.00999999, 0.0000
+ /
+
+ &physics
+ mp_physics                          = 1,     1,     1,
+ ra_lw_physics                       = 0,     0,     0,
+ ra_sw_physics                       = 0,     0,     0,
+ radt                                = 1,    30,    30,
+ sf_sfclay_physics                   = 1,     0,     0,
+ sf_surface_physics                  = 1,     0,     0,
+ bl_pbl_physics                      = 0,     0,     0,
+ bldt                                = 0,     0,     0,
+ cu_physics                          = 0,     0,     0,
+ cudt                                = 5,     5,     5,
+ do_radar_ref		                 = 0,
+ icloud_bl                           = 1,
+ /
+
+ &fdda
+ /
+
+ &dynamics
+ hybrid_opt                          = 0,
+ rk_ord                              = 3,
+ diff_opt                            = 1,      1,      1,
+ km_opt                              = 4,      4,      2,
+ damp_opt                            = 2,
+ zdamp                               = 5000.,  5000.,  5000.,
+ dampcoef                            = 0.003,  0.003,  0.003
+ w_damping			     = 1,
+ khdif                               = 500,    500,    500,
+ kvdif                               = 500,    500,    500,
+ smdiv                               = 0.1,    0.1,    0.1,
+ emdiv                               = 0.01,   0.01,   0.01,
+ epssm                               = 0.1,    0.1,    0.1
+ time_step_sound                     = 0,      6,      6,
+ h_mom_adv_order                     = 5,      5,      5,
+ v_mom_adv_order                     = 5,      3,      3,
+ h_sca_adv_order                     = 5,      5,      5,
+ v_sca_adv_order                     = 5,      3,      3,
+ moist_adv_opt                       = 1,      1,      1,
+ scalar_adv_opt                      = 1,      1,      1,
+ chem_adv_opt                        = 1,      1,      1,
+ tke_adv_opt                         = 1,      1,      1,
+ non_hydrostatic                     = .true., .true., .true.,
+ mix_full_fields                     = .true., .true., .true.,
+ use_theta_m			             = 1,
+ top_lid                             = .true.,
+ pert_coriolis                       = .true.,
+ /
+
+ &bdy_control
+ periodic_x                          = .true.,
+ symmetric_xs                        = .false.,
+ symmetric_xe                        = .false.,
+ open_xs                             = .false.,
+ open_xe                             = .false.,
+ periodic_y                          = .true.,
+ symmetric_ys                        = .false.,
+ symmetric_ye                        = .false.,
+ open_ys                             = .false.,
+ open_ye                             = .false.,
+ /
+
+ &grib2
+ /
+
+ &namelist_quilt
+ nio_tasks_per_group = 0,
+ nio_groups = 1,
+ /
+
+ &ideal
+ ideal_case = 9 ! les
+ /
diff --git a/test-singlenode.py b/test-singlenode.py
index 5adb862..110f414 100644
--- a/test-singlenode.py
+++ b/test-singlenode.py
@@ -1,6 +1,7 @@
+"""Run experiments in one script without SLURM.
+"""
 from timer import Timer
 
-
 with Timer('imports'):
     import datetime as dt
     import pandas as pd
@@ -11,11 +12,39 @@ with Timer('imports'):
     from config.jet_1node import cluster_defaults
     from config.defaults import dart_nml
 
+def runWRF(cfg):
+    cmd = cfg.wrf_modules +'; '
+    
+    for iens in range(1, cfg.ensemble_size+1):
+        dir_wrf_run = cfg.dir_wrf_run.replace('<exp>', cfg.name).replace('<ens>', str(iens))
+
+        cmd += 'cd ' + dir_wrf_run + '; '
+        cmd += 'echo "'+dir_wrf_run+'"; '
+        cmd += 'mpirun -np 4 ./wrf.exe & '
+
+    cmd += 'wait; '
+    cmd += 'echo "WRF run completed."'
+
+    # Run the command in the specified directory
+    run_bash_command_in_directory(cmd, dir_wrf_run)
+    
+def runIdeal(cfg):
+    cmd = cfg.wrf_modules +'; '
+    
+    for iens in range(1, cfg.ensemble_size+1):
+        dir_wrf_run = cfg.dir_wrf_run.replace('<exp>', cfg.name).replace('<ens>', str(iens))
+
+        cmd += 'cd ' + dir_wrf_run + '; '
+        cmd += 'echo "'+dir_wrf_run+'"; '
+        cmd += 'mpirun -np 1 ./ideal.exe & '
 
-ensemble_size = 5
+    cmd += 'wait; '
+    cmd += 'echo "ideal.exe completed."'
 
-dart_nml['&filter_nml'].update(num_output_state_members=ensemble_size,
-                               ens_size=ensemble_size)
+    # Run the command in the specified directory
+    run_bash_command_in_directory(cmd, dir_wrf_run)
+    
+###############################
 
 
 t = dict(var_name='Temperature', unit='[K]',
@@ -23,17 +52,32 @@ t = dict(var_name='Temperature', unit='[K]',
          # n_obs=22500,
          n_obs=1, obs_locations=[(45., 0.)],
          error_generate=0.2, error_assimilate=0.2,
-         heights=range(1000, 17001, 2000),
+         heights=range(1000, 3001, 1000),
          loc_horiz_km=1000, loc_vert_km=4)
 
-assimilate_these_observations = [t,] #cf3, cf4, cf5,]
+assimilate_these_observations = [t,] 
 
 
-time0 = dt.datetime(2008, 7, 30, 11)
+time0 = dt.datetime(2008, 7, 30, 10)
 time_end = dt.datetime(2008, 7, 30, 11)
 
 id = None
 with Timer('Config()'):
+    # update defaults
+    ensemble_size = 4
+    dart_nml['&filter_nml'].update(num_output_state_members=ensemble_size,
+                                   ens_size=ensemble_size)
+    dart_nml['&model_nml'].update(
+                        dict(wrf_state_variables=[
+                        ['U',     'QTY_U_WIND_COMPONENT',  'TYPE_U',    'UPDATE', '999',],
+                        ['V',     'QTY_V_WIND_COMPONENT',  'TYPE_V',    'UPDATE', '999',],
+                        ['W',     'QTY_VERTICAL_VELOCITY', 'TYPE_W',    'UPDATE', '999',],
+                        ['PH',    'QTY_GEOPOTENTIAL_HEIGHT', 'TYPE_GZ',  'UPDATE', '999',],
+                        ['THM',   'QTY_POTENTIAL_TEMPERATURE', 'TYPE_T', 'UPDATE', '999',],
+                        ['MU',    'QTY_PRESSURE', 'TYPE_MU',  'UPDATE', '999',],
+                        ['QVAPOR', 'QTY_VAPOR_MIXING_RATIO','TYPE_QV',   'UPDATE', '999',],
+                        ]))
+    
     cfg = Config(name='test-1node',
         model_dx = 2000,
         ensemble_size = ensemble_size,
@@ -47,22 +91,43 @@ with Timer('Config()'):
         nature_wrfout_pattern = '/jetfs/home/lkugler/data/sim_archive/exp_v1.18_P1_nature+1/*/1/wrfout_d01_%Y-%m-%d_%H:%M:%S',
         geo_em_nature = '/jetfs/home/lkugler/data/sim_archive/geo_em.d01.nc.2km_200x200',
         
-        update_vars = ['U', 'V', 'W', 'THM', 'PH', 'MU', 'QVAPOR', 'QCLOUD', 'QICE', 'QSNOW', 'PSFC'],
+        update_vars = ['U', 'V', 'W', 'THM', 'PH', 'MU',],
         #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)
 
+    
+
 with Timer('prepare_WRFrundir'):
     w = WorkFlows(cfg)
     import dartwrf.prepare_wrfrundir as prepwrf
     prepwrf.run(cfg)
-    # w.prepare_WRFrundir(cfg)
+    
+
+with Timer('ideal.exe'):
+    runIdeal(cfg)
+
+# spinup
+timedelta_integrate = dt.timedelta(hours=1)
+t_spinup_end = time0 + timedelta_integrate
+restart_interval = timedelta_integrate.total_seconds()/60  # in minutes
+
+cfg.update( WRF_start=time0, 
+            WRF_end=t_spinup_end, 
+            restart=False,  # from wrfinput
+            restart_interval=restart_interval,
+            hist_interval_s=300,
+)
+import dartwrf.prepare_namelist as prepnl
+prepnl.run(cfg)
+
+with Timer('run_WRF'):
+    runWRF(cfg)
 
-# id = w.run_ideal(cfg, depends_on=id)
 
 # assimilate at these times
 timedelta_btw_assim = dt.timedelta(minutes=15)
-assim_times = pd.date_range(time0, time_end, freq=timedelta_btw_assim)
+assim_times = pd.date_range(t_spinup_end, time_end, freq=timedelta_btw_assim)
 #assim_times = [dt.datetime(2008, 7, 30, 12), dt.datetime(2008, 7, 30, 13), dt.datetime(2008, 7, 30, 14),]
 last_assim_time = assim_times[-1]
 
@@ -70,12 +135,12 @@ last_assim_time = assim_times[-1]
 # loop over assimilations
 for i, t in enumerate(assim_times):
 
-    if i == 0 and t == dt.datetime(2008, 7, 30, 11):
+    if i == 0:
         cfg.update(
             time = t,
-            prior_init_time = dt.datetime(2008, 7, 30, 8),
-            prior_valid_time = t,
-            prior_path_exp = '/jetfs/home/lkugler/data/sim_archive/exp_nat250m_noDA/')
+            prior_init_time = time0,
+            prior_valid_time = t_spinup_end,
+            prior_path_exp = '/jetfs/home/lkugler/data/sim_archive/test-1node/')  #'/jetfs/home/lkugler/data/sim_archive/exp_nat250m_noDA/')
     else:
         cfg.update(
             time = t,
@@ -84,19 +149,16 @@ for i, t in enumerate(assim_times):
             prior_path_exp = cfg.dir_archive,)
 
     with Timer('assimilate'):
-        #id = w.assimilate(cfg, depends_on=id)
-        import dartwrf.assimilate as da
-        da.main(cfg)
+        import dartwrf.assimilate as assim
+        assim.main(cfg)
 
     with Timer('prepare_IC_from_prior'):
         # 1) Set posterior = prior
-        #id = w.prepare_IC_from_prior(cfg, depends_on=id)
         import dartwrf.prep_IC_prior as prep
         prep.main(cfg)
 
     with Timer('update_IC_from_DA'):
         # 2) Update posterior += updates from assimilation
-        #id = w.update_IC_from_DA(cfg, depends_on=id)
         import dartwrf.update_IC as upd
         upd.update_initials_in_WRF_rundir(cfg)
     
@@ -115,21 +177,5 @@ for i, t in enumerate(assim_times):
     prepnl.run(cfg)
 
     # 3) Run WRF ensemble
-    #id = w.run_WRF(cfg, depends_on=id)
-
     with Timer('run_WRF'):
-        # Example usage:
-        cmd = cfg.wrf_modules +'; '
-        
-        for iens in range(1, cfg.ensemble_size+1):
-            dir_wrf_run = cfg.dir_wrf_run.replace('<exp>', cfg.name).replace('<ens>', str(iens))
-
-            cmd += 'cd ' + dir_wrf_run + '; '
-            cmd += 'echo "'+dir_wrf_run+'"; '
-            cmd += 'mpirun -np 4 ./wrf.exe & '
-
-        cmd += 'wait; '
-        cmd += 'echo "WRF run completed."'
-
-        # Run the command in the specified directory
-        run_bash_command_in_directory(cmd, dir_wrf_run)
+        runWRF(cfg)
\ No newline at end of file
-- 
GitLab