diff --git a/config/cfg.py b/config/cfg.py index 8ce1a1ba38378af9da59b5dbd1a26c7ea716eb30..acadce5092dbe7ecc8993ba401a0e64388ecf0e4 100755 --- a/config/cfg.py +++ b/config/cfg.py @@ -9,7 +9,7 @@ class ExperimentConfiguration(object): exp = ExperimentConfiguration() -exp.expname = "exp_v1.12_LMU_so_VIS2" +exp.expname = "exp_v1.12_conv1" exp.model_dx = 2000 exp.timestep = 10 exp.n_ens = 40 @@ -17,17 +17,24 @@ exp.n_nodes = 10 n_obs = 64 # radar: n_obs for each observation height level -vis = dict(sat=True, channel=1, n_obs=n_obs, err_std=0.03, +vis = dict(sat_channel=1, n_obs=n_obs, err_std=0.03, cov_loc_radius_km=10) -wv = dict(sat=True, channel=6, n_obs=n_obs, err_std=5., +wv = dict(sat_channel=6, n_obs=n_obs, err_std=5., cov_loc_radius_km=10) - -radar = dict(sat=False, kind='RADAR', n_obs=n_obs, err_std=5., - cov_loc_radius_km=10, cov_loc_vert_km=1) -psfc = dict(sat=False, kind='PSFC', n_obs=n_obs, err_std=50., +ir108 = dict(sat_channel=9, n_obs=n_obs, err_std=5., cov_loc_radius_km=10) -exp.observations = [vis, ] +radar = dict(kind='RADAR', n_obs=n_obs, err_std=5., + heights=np.arange(1000, 15001, 1000), + cov_loc_radius_km=10, cov_loc_vert_km=2) + +t2m = dict(kind='SYNOP_TEMPERATURE', n_obs=n_obs, err_std=1.0, + cov_loc_radius_km=32, cov_loc_vert_km=1) +psfc = dict(kind='SYNOP_SURFACE_PRESSURE', n_obs=n_obs, err_std=50., + cov_loc_radius_km=32) + + +exp.observations = [t2m, psfc, ] # directory paths depend on the name of the experiment cluster.expname = exp.expname diff --git a/scheduler.py b/scheduler.py index 240aa3cbea8244b277ccdb2319bbf208fb232a53..e18444c7da3358f365b4fb83f1a935531f4c7724 100755 --- a/scheduler.py +++ b/scheduler.py @@ -16,12 +16,18 @@ from scripts.utils import script_to_str, symlink # allow scripts to access the configuration symlink(cluster.scriptsdir+'/../config', cluster.scriptsdir+'/config') +log_dir = cluster.archivedir()+'/logs/' +slurm_scripts_dir = cluster.archivedir()+'/slurm-scripts/' +print('logging to', log_dir) +print('scripts, which are submitted to SLURM:', slurm_scripts_dir) + def my_Slurm(*args, cfg_update=dict(), **kwargs): - """Shortcut to slurmpy's class; keep default kwargs - and only update according to `cfg_update` + """Shortcut to slurmpy's class; keep certain default kwargs + and only update some with kwarg `cfg_update` see https://github.com/brentp/slurmpy """ - return Slurm(*args, slurm_kwargs=dict(cluster.slurm_cfg, **cfg_update), **kwargs) + return Slurm(*args, slurm_kwargs=dict(cluster.slurm_cfg, **cfg_update), + log_dir=log_dir, scripts_dir=slurm_scripts_dir, **kwargs) class Cmdline(object): def __init__(self, name, cfg_update): @@ -31,18 +37,16 @@ class Cmdline(object): print('running', self.name, 'without SLURM') os.system(cmd) -def clear_logs(backup_existing_to_archive=True): - dirs = ['/logs/', '/slurm-scripts/'] - for d in dirs: - archdir = cluster.archivedir()+d - if backup_existing_to_archive: - os.makedirs(archdir, exist_ok=True) - dir = cluster.scriptsdir+'/../'+d - for f in os.listdir(dir): - if backup_existing_to_archive: - shutil.move(dir+f, archdir+f) - else: - os.remove(dir+f) +def backup_scripts(): + os.makedirs(cluster.archivedir(), exist_ok=True) + dir_backup_scripts = cluster.archivedir()+'/DART-WRF/' + os.makedirs(dir_backup_scripts, exist_ok=True) + os.makedirs(dir_backup_scripts+'/old/', exist_ok=True) + os.system('mv '+dir_backup_scripts+'/* '+dir_backup_scripts+'/old/') # move old logs + shutil.copy(cluster.scriptsdir+'/../scheduler.py', dir_backup_scripts+'/scheduler.py') + shutil.copy(cluster.scriptsdir+'/../config/clusters.py', dir_backup_scripts+'/clusters.py') + shutil.copy(cluster.scriptsdir+'/../config/cfg.py', dir_backup_scripts+'/cfg.py') + os.system('cp -r '+cluster.scriptsdir+' '+dir_backup_scripts+'/') def prepare_wrfinput(): """Create WRF/run directories and wrfinput files @@ -71,7 +75,7 @@ done id = s.run(cmd, depends_on=[id]) return id -def update_wrfinput_from_archive(time, background_init_time, exppath, depends_on=None): +def update_wrfinput_from_archive(valid_time, background_init_time, exppath, depends_on=None): """Given that directories with wrfinput files exist, update these wrfinput files according to wrfout files """ @@ -79,7 +83,7 @@ def update_wrfinput_from_archive(time, background_init_time, exppath, depends_on # path of initial conditions, <iens> is replaced by member index IC_path = exppath + background_init_time.strftime('/%Y-%m-%d_%H:%M/') \ - +'*iens*/'+time.strftime('/wrfout_d01_%Y-%m-%d_%H:%M:%S') + +'*iens*/'+valid_time.strftime('/wrfout_d01_%Y-%m-%d_%H:%M:%S') id = s.run(cluster.python+' '+cluster.scriptsdir+'/update_wrfinput_from_wrfout.py ' +IC_path, depends_on=[depends_on]) return id @@ -92,12 +96,14 @@ def run_ENS(begin, end, depends_on=None): # first minute forecast (needed for validating an assimilation) hist_interval = 1 + radt = 1 # calc CFRAC also in first minute begin_plus1 = begin+dt.timedelta(minutes=1) s = my_Slurm("preWRF1", cfg_update=dict(time="2")) - id = s.run(cluster.python+' '+cluster.scriptsdir+'/prepare_namelist.py ' - + begin.strftime('%Y-%m-%d_%H:%M')+' ' - + begin_plus1.strftime('%Y-%m-%d_%H:%M')+' ' - + str(hist_interval), + id = s.run(' '.join([cluster.python, + cluster.scriptsdir+'/prepare_namelist.py', + begin.strftime('%Y-%m-%d_%H:%M'), + begin_plus1.strftime('%Y-%m-%d_%H:%M'), + str(hist_interval), str(radt),]) depends_on=[id]) s = my_Slurm("runWRF1", cfg_update={"nodes": "1", "array": "1-"+str(exp.n_nodes), @@ -114,11 +120,13 @@ def run_ENS(begin, end, depends_on=None): # whole forecast timespan hist_interval = 5 + radt = 5 s = my_Slurm("preWRF2", cfg_update=dict(time="2")) - id = s.run(cluster.python+' '+cluster.scriptsdir+'/prepare_namelist.py ' - + begin.strftime('%Y-%m-%d_%H:%M')+' ' - + end.strftime('%Y-%m-%d_%H:%M')+' ' - + str(hist_interval), + id = s.run(' '.join([cluster.python, + cluster.scriptsdir+'/prepare_namelist.py', + begin.strftime('%Y-%m-%d_%H:%M'), + begin_plus1.strftime('%Y-%m-%d_%H:%M'), + str(hist_interval), str(radt),]) depends_on=[id]) time_in_simulation_hours = (end-begin).total_seconds()/3600 @@ -134,43 +142,40 @@ def run_ENS(begin, end, depends_on=None): # + begin.strftime('%Y-%m-%d_%H:%M'), depends_on=[id2]) return id -def assimilate(assim_time, background_init_time, - prior_from_different_exp=False, depends_on=None): +def assimilate(assim_time, prior_init_time, + prior_path_exp=False, depends_on=None): """Creates observations from a nature run and assimilates them. Args: assim_time (dt.datetime): timestamp of prior wrfout files - background_init_time (dt.datetime): + prior_init_time (dt.datetime): timestamp to find the directory where the prior wrfout files are - prior_from_different_exp (bool or str): + prior_path_exp (bool or str): put a `str` to take the prior from a different experiment if False: use `archivedir` (defined in config) to get prior state if str: use this directory to get prior state """ - id = depends_on - - if prior_from_different_exp: - prior_expdir = prior_from_different_exp - else: + if prior_path_exp == False: prior_expdir = cluster.archivedir() + elif not isinstance(prior_path_exp, str): + raise TypeError('prior_path_exp either str or False, is '+str(type(prior_path_exp))) # prepare state of nature run, from which observation is sampled - s = my_Slurm("prepNature", cfg_update=dict(time="2")) - id = s.run(cluster.python+' '+cluster.scriptsdir+'/prepare_nature.py ' - +time.strftime('%Y-%m-%d_%H:%M'), depends_on=[depends_on]) + #s = my_Slurm("prepNature", cfg_update=dict(time="2")) + #id = s.run(cluster.python+' '+cluster.scriptsdir+'/prepare_nature.py ' + # +time.strftime('%Y-%m-%d_%H:%M'), depends_on=[depends_on]) # prepare prior model state s = my_Slurm("preAssim", cfg_update=dict(time="2")) id = s.run(cluster.python+' '+cluster.scriptsdir+'/pre_assim.py ' +assim_time.strftime('%Y-%m-%d_%H:%M ') - +background_init_time.strftime('%Y-%m-%d_%H:%M ') - +prior_expdir, depends_on=[id]) + +prior_init_time.strftime('%Y-%m-%d_%H:%M ') + +prior_path_exp, depends_on=[depends_on]) - # generate observations - s = my_Slurm("genSynthObs", cfg_update=dict(ntasks="48", time="10")) + # prepare nature run, generate observations + s = my_Slurm("genSynthObs", cfg_update=dict(ntasks="48", time="12")) id = s.run(cluster.python+' '+cluster.scriptsdir+'/gen_synth_obs.py ' - +time.strftime('%Y-%m-%d_%H:%M'), - depends_on=[id]) + +time.strftime('%Y-%m-%d_%H:%M'), depends_on=[id]) # actuall assimilation step s = my_Slurm("Assim", cfg_update=dict(ntasks="48", time="50", mem="200G")) @@ -184,8 +189,8 @@ def assimilate(assim_time, background_init_time, s = my_Slurm("updateIC", cfg_update=dict(time="8")) id = s.run(cluster.python+' '+cluster.scriptsdir+'/update_wrfinput_from_filteroutput.py ' +assim_time.strftime('%Y-%m-%d_%H:%M ') - +background_init_time.strftime('%Y-%m-%d_%H:%M ') - +prior_expdir, depends_on=[id]) + +prior_init_time.strftime('%Y-%m-%d_%H:%M ') + +prior_path_exp, depends_on=[id]) return id @@ -206,7 +211,7 @@ print('starting osse') timedelta_integrate = dt.timedelta(minutes=45) timedelta_btw_assim = dt.timedelta(minutes=30) -clear_logs(backup_existing_to_archive=False) +backup_scripts() id = None start_from_existing_state = True @@ -225,32 +230,33 @@ if is_new_run: first_guess = False elif start_from_existing_state: - id = prepare_wrfinput() # create initial conditions + #id = prepare_wrfinput() # create initial conditions # get initial conditions from archive background_init_time = dt.datetime(2008, 7, 30, 11, 30) time = dt.datetime(2008, 7, 30, 12) - exppath_arch = '/gpfs/data/fs71386/lkugler/sim_archive/exp_v1.12_LMU_so_VIS2' + exppath_arch = '/gpfs/data/fs71386/lkugler/sim_archive/exp_v1.12_LMU_so_VIS' first_guess = exppath_arch - id = update_wrfinput_from_archive(time, background_init_time, exppath_arch, depends_on=id) + #id = update_wrfinput_from_archive(time, background_init_time, exppath_arch, depends_on=id) -while time <= dt.datetime(2008, 7, 30, 15): +while time <= dt.datetime(2008, 7, 30, 14): assim_time = time - id = assimilate(assim_time, - background_init_time, - prior_from_different_exp=first_guess, - depends_on=id) - first_guess = False - prev_forecast_init = assim_time - timedelta_btw_assim this_forecast_init = assim_time # start integration from here - this_forecast_end = assim_time + timedelta_btw_assim + this_forecast_end = assim_time + timedelta_integrate + + id = assimilate(assim_time, + prev_forecast_init, + prior_path_exp=first_guess, + depends_on=id) + #first_guess = False + + #id = update_wrfinput_from_archive(this_forecast_init, this_forecast_init, cluster.archivedir(), depends_on=id) id = run_ENS(begin=this_forecast_init, - end=this_forecast_end, - depends_on=id) + end=this_forecast_init+dt.timedelta(minutes=10), + depends_on=id) time += timedelta_btw_assim - - create_satimages(depends_on=id) + #create_satimages(depends_on=id) mailme(id) diff --git a/scripts/create_obsseq.py b/scripts/create_obsseq.py index 267af7d7185e7bb306f7c451f79cf256d4fdc4d9..202e42a230ce07ded1e4ccec106194a820e09ca2 100755 --- a/scripts/create_obsseq.py +++ b/scripts/create_obsseq.py @@ -297,23 +297,32 @@ def calc_obs_locations_3d(coords, heights): return coords2 -def generic_obs(obs_type, time_dt, coords, error_var, output_path='./'): - - obs_codes = {'RASO_T': {'name': 'RADIOSONDE_TEMPERATURE', 'nr': '5'}, - 'RADAR': {'name': 'RADAR_REFLECTIVITY', 'nr': '37'}, - 'PSFC': {'name': 'LAND_SFC_PRESSURE', 'nr': '29'},} +def generic_obs(obs_kind, time_dt, coords, error_var, heights=False, output_path='./'): + + obs_kind_nrs = {'RADIOSONDE_TEMPERATURE': '5', + 'RADAR_REFLECTIVITY': '37', + 'SYNOP_SURFACE_PRESSURE': '94', + 'SYNOP_SPECIFIC_HUMIDITY': '95', + 'SYNOP_TEMPERATURE': '96', + } + + if 'SYNOP' in obs_kind: + is_sfc_obs = True + heights = [2,] + else: + is_sfc_obs = False - heights = [5000., ] #np.arange(5000, 15001, 1000) + if not heights: + heights = [5000., ] coords = calc_obs_locations_3d(coords, heights) dart_date_day, secs_thatday = get_dart_date(add_timezone_UTC(time_dt)) print('secs, days:', secs_thatday, dart_date_day) - obs_name = obs_codes[obs_type]['name'] - obs_kind_nr = obs_codes[obs_type]['nr'] - - write_generic_obsseq(obs_name, obs_kind_nr, error_var, coords, - dart_date_day, secs_thatday, output_path) + obs_kind_nr = obs_kind_nrs[obs_kind] + write_generic_obsseq(obs_kind, obs_kind_nr, error_var, coords, + dart_date_day, secs_thatday, output_path, + vert_coord_sfc=is_sfc_obs) if __name__ == '__main__': diff --git a/scripts/gen_synth_obs.py b/scripts/gen_synth_obs.py index fb5945e564d26e680f24cf399bce357d93df39c3..6a0ddba2aac7861ae49d9a0cdc8349d9fa9ff3f0 100755 --- a/scripts/gen_synth_obs.py +++ b/scripts/gen_synth_obs.py @@ -2,9 +2,11 @@ import os, sys, shutil import datetime as dt import numpy as np from scipy.interpolate import interp1d + from config.cfg import exp, cluster from utils import symlink, copy, sed_inplace, append_file import create_obsseq as osq +import wrfout_add_geo earth_radius_km = 6370 @@ -51,6 +53,19 @@ def read_prior_obs(f_obs_prior): OBSs.append(dict(observed=observed, truth=truth, prior_ens=np.array(prior_ens))) return OBSs +def read_obsseqout(f): + obsseq = open(f, 'r').readlines() + true = [] + obs = [] + # read observations from obs_seq.out + for i, line in enumerate(obsseq): + if ' OBS ' in line: + observed = float(obsseq[i+1].strip()) + truth = float(obsseq[i+2].strip()) + true.append(truth) + obs.append(observed) + return true, obs + def edit_obserr_in_obsseq(fpath_obsseqin, OEs): """ overwrite observation errors in a obs_seq.out file @@ -107,6 +122,41 @@ def set_input_nml(sat_channel=False, just_prior_values=False, append_file(cluster.dartrundir+'/input.nml', rttov_nml) +def obs_operator_ensemble(): + os.chdir(cluster.dartrundir) + + if sat_channel: + list_ensemble_truths = [] + + for iens in range(1, exp.n_ens+1): + print('observation operator for ens #'+str(iens)) + # ens members are already linked to advance_temp<i>/wrfout_d01 + copy(cluster.dartrundir+'/advance_temp'+str(iens)+'/wrfout_d01', + cluster.dartrundir+'/wrfout_d01') + + t = dt.datetime.now() + wrfout_add_geo.run(cluster.dartrundir+'/geo_em.d01.nc', cluster.dartrundir+'/wrfout_d01') + print((dt.datetime.now()-t).total_seconds(), 'secs for adding geodata') + + # DART may need a wrfinput file as well, which serves as a template for dimension sizes + symlink(cluster.dartrundir+'/wrfout_d01', cluster.dartrundir+'/wrfinput_d01') + + # run perfect_model obs (forward operator) + os.system('mpirun -np 12 ./perfect_model_obs > /dev/null') + + # truth values in obs_seq.out are H(x) values + vals, _ = read_obsseqout(cluster.dartrundir+'/obs_seq.out') + list_ensemble_truths.append(vals) + + n_obs = len(list_ensemble_truths[0]) + np_array = np.full((exp.n_ens, n_obs), np.nan) + for i in range(exp.n_ens): + np_array[i, :] = list_ensemble_truths[i] + return np_array + else: + raise NotImplementedError() + + if __name__ == "__main__": time = dt.datetime.strptime(sys.argv[1], '%Y-%m-%d_%H:%M') @@ -115,79 +165,100 @@ if __name__ == "__main__": # remove any existing observation files os.chdir(cluster.dartrundir); os.system('rm -f obs_seq_*.out obs_seq.in obs_seq.final') + def prepare_nature_dart(): + # get wrfout_d01 from nature run + shutil.copy(time.strftime(cluster.nature_wrfout), + cluster.dartrundir+'/wrfout_d01') + + wrfout_add_geo.run(cluster.dartrundir+'/geo_em.d01.nc', cluster.dartrundir+'/wrfout_d01') + + # DART may need a wrfinput file as well, which serves as a template for dimension sizes + symlink(cluster.dartrundir+'/wrfout_d01', cluster.dartrundir+'/wrfinput_d01') + + prepare_nature_dart() + # loop over observation types for i_obs, obscfg in enumerate(exp.observations): n_obs = obscfg['n_obs'] error_var = (obscfg['err_std'])**2 - sat_channel = obscfg.get('channel', False) + sat_channel = obscfg.get('sat_channel', False) cov_loc = obscfg['cov_loc_radius_km'] dist_obs = obscfg.get('distance_between_obs_km', False) cov_loc_vert_km = obscfg.get('cov_loc_vert_km', False) + heights = obscfg.get('heights', False) # generate obs_seq.in obs_coords = osq.calc_obs_locations(n_obs, coords_from_domaincenter=False, distance_between_obs_km=dist_obs, fpath_obs_locations=fpath_obs_coords) - if obscfg['sat']: + if sat_channel: osq.sat(time, sat_channel, obs_coords, error_var, output_path=cluster.dartrundir) else: osq.generic_obs(obscfg['kind'], time, obs_coords, error_var, + heights=heights, output_path=cluster.dartrundir) if not os.path.exists(cluster.dartrundir+'/obs_seq.in'): raise RuntimeError('obs_seq.in does not exist in '+cluster.dartrundir) - # generate observations (obs_seq.out) + os.chdir(cluster.dartrundir) + if sat_channel == 6: + """cloud dependent observation error + + # methodologically: + 1) gen H(x_nature) + 2) gen H(x_prior) + 3) find the observation error for a pair of (H(x_nature), H(x_background)) + 4) generate actual observation + with the observation error as function of H(x_nature) and H(x_background) + + # technically: + 4) the file 'obs_seq.in' needs to be edited to show corrected observation errors + """ + # 1) gen H(x_nature) + set_input_nml(sat_channel=sat_channel, + cov_loc_radius_km=cov_loc, + cov_loc_vert_km=cov_loc_vert_km) + os.system('mpirun -np 12 ./perfect_model_obs') + Hx_nature, _ = read_obsseqout(cluster.dartrundir+'/obs_seq.out') + + # 2) gen H(x_prior) for the whole ensemble + Hx_prior = obs_operator_ensemble() # files are already linked to DART directory + + # 3) find the observation error for a pair of (H(x_nature), H(x_background)) + # necessary to achieve a certain FGD distribution which is near to operational + n_obs = len(Hx_nature) + OEs = [] + for iobs in range(n_obs): + + bt_y = Hx_nature[iobs] + bt_x_ens = Hx_prior[:,iobs] + CIs = [cloudimpact_73(bt_x, bt_y) for bt_x in bt_x_ens] + mean_CI = np.mean(CIs) + + oe_nature = oe_73(mean_CI) + print('oe_nature=', oe_nature, ' K') + OEs.append(oe_nature) + + # correct obs_err in obs_seq.in (to produce actual observations later on) + fpath_obsseqout = cluster.dartrundir+'/obs_seq.in' + edit_obserr_in_obsseq(fpath_obsseqout, OEs) + + # ensure correct nature file linked + # nature should be the real nature again (was changed in the meantime) + prepare_nature_dart() + + # correct input.nml for actual assimilation later on set_input_nml(sat_channel=sat_channel, - cov_loc_radius_km=cov_loc, - cov_loc_vert_km=cov_loc_vert_km) + cov_loc_radius_km=cov_loc, + cov_loc_vert_km=cov_loc_vert_km) + + # 4) generate actual observations (with correct error) os.chdir(cluster.dartrundir) - t = dt.datetime.now() os.system('mpirun -np 12 ./perfect_model_obs') - print('1st perfect_model_obs', (dt.datetime.now()-t).total_seconds()) - - # cloud dependent observation error - if obscfg['sat']: - if sat_channel == 6: - # run ./filter to have prior observation estimates from model state - set_input_nml(sat_channel=sat_channel, - just_prior_values=True) - t = dt.datetime.now() - os.system('mv obs_seq.out obs_seq_all.out; mpirun -np 20 ./filter') - print('1st filter', (dt.datetime.now()-t).total_seconds()) - - # find the observation error for a pair of (H(x_nature), H(x_background)) - f_obs_prior = cluster.dartrundir+'/obs_seq.final' - OBSs = read_prior_obs(f_obs_prior) - - # compute the observation error necessary - # to achieve a certain operational FGD distribution - OEs = [] - for obs in OBSs: - bt_y = obs['truth'] - bt_x_ens = obs['prior_ens'] - CIs = [cloudimpact_73(bt_x, bt_y) for bt_x in bt_x_ens] - - oe_nature = oe_73(np.mean(CIs)) - OEs.append(oe_nature) - - # write obs_seq.out - fpath_obsseqout = cluster.dartrundir+'/obs_seq.in' - edit_obserr_in_obsseq(fpath_obsseqout, OEs) - - # generate actual observations (with correct error) - os.chdir(cluster.dartrundir) - t = dt.datetime.now() - os.system('mpirun -np 12 ./perfect_model_obs') - print('real obs gen', (dt.datetime.now()-t).total_seconds()) - - # correct input.nml for actual assimilation later on - set_input_nml(sat_channel=sat_channel, - cov_loc_radius_km=cov_loc, - cov_loc_vert_km=cov_loc_vert_km) # rename according to i_obs os.rename(cluster.dartrundir+'/obs_seq.out', diff --git a/scripts/prepare_namelist.py b/scripts/prepare_namelist.py index 9fab46ac9cd8199c5e195aaae99031e9a2b73c6d..fb6c588e715de04fd60d49d0ea353b65b8e3bc33 100755 --- a/scripts/prepare_namelist.py +++ b/scripts/prepare_namelist.py @@ -5,7 +5,7 @@ sys.path.append(os.getcwd()) from config.cfg import exp, cluster from utils import sed_inplace, copy, symlink, mkdir -def run(cluster, iens, begin, end, hist_interval=5): +def run(cluster, iens, begin, end, hist_interval=5, radt=5): rundir = cluster.wrf_rundir(iens) print(rundir) copy(cluster.namelist, rundir+'/namelist.input') @@ -13,6 +13,7 @@ def run(cluster, iens, begin, end, hist_interval=5): sed_inplace(rundir+'/namelist.input', '<dx>', str(int(exp.model_dx))) sed_inplace(rundir+'/namelist.input', '<timestep>', str(int(exp.timestep))) sed_inplace(rundir+'/namelist.input', '<hist_interval>', str(int(hist_interval))) + sed_inplace(rundir+'/namelist.input', '<radt>', str(int(radt))) archdir = cluster.archivedir()+begin.strftime('/%Y-%m-%d_%H:%M/'+str(iens)+'/') print('namelist for run from', begin, end, 'output to', archdir) @@ -42,8 +43,9 @@ def run(cluster, iens, begin, end, hist_interval=5): if __name__ == '__main__': begin = dt.datetime.strptime(sys.argv[1], '%Y-%m-%d_%H:%M') end = dt.datetime.strptime(sys.argv[2], '%Y-%m-%d_%H:%M') - hist_interval = int(sys.argv[3]) + intv = int(sys.argv[3]) + radt = int(sys.argv[4]) print('prepare namelists for all ens members') for iens in range(1, exp.n_ens+1): - run(cluster, iens, begin, end, hist_interval) + run(cluster, iens, begin, end, hist_interval=intv, radt=radt) diff --git a/scripts/prepare_wrfinput.py b/scripts/prepare_wrfinput.py index 7ba119b5657524184442037389e24f7510198d87..7a2f03a6b5f0c2b1b3dd182bc2ff153820f08177 100755 --- a/scripts/prepare_wrfinput.py +++ b/scripts/prepare_wrfinput.py @@ -5,11 +5,6 @@ from utils import symlink, copy, link_contents import prepare_namelist -# archive configuration -os.makedirs(cluster.archivedir(), exist_ok=True) -shutil.copy(cluster.scriptsdir+'/../config/clusters.py', cluster.archivedir()+'/clusters.py') -shutil.copy(cluster.scriptsdir+'/../config/cfg.py', cluster.archivedir()+'/cfg.py') - for iens in range(1, exp.n_ens+1): print('preparing ens', iens) input_prof = (cluster.input_profile).replace('<iens>', str(iens).zfill(3)) diff --git a/scripts/update_wrfinput_from_wrfout.py b/scripts/update_wrfinput_from_wrfout.py index 38cd1475a8d86deda83a3b3acaebf7d885856cb5..8d58b931c0d83b79b507fd8967d0aa10a5bff257 100644 --- a/scripts/update_wrfinput_from_wrfout.py +++ b/scripts/update_wrfinput_from_wrfout.py @@ -18,7 +18,7 @@ for iens in range(1, exp.n_ens+1): wrfin = cluster.wrf_rundir(iens)+'/wrfinput_d01' print('updating', wrfin, 'to state in', wrfout) - assert os.path.isfile(wrfout) + assert os.path.isfile(wrfout), wrfout # overwrite variables in wrfinput file os.system(cluster.ncks+' -A -v '+vars+' '+wrfout+' '+wrfin) diff --git a/templates/input.nml b/templates/input.nml index 2e593ef49d260b916fee15b9d76bb3315e605882..31d31e1b0f0de28afee45726f0fd082bfd250b18 100644 --- a/templates/input.nml +++ b/templates/input.nml @@ -71,7 +71,7 @@ &quality_control_nml input_qc_threshold = 3.0, - outlier_threshold = 3.0, + outlier_threshold = -1.0, enable_special_outlier_code = .false. / @@ -281,7 +281,7 @@ layout = 1, tasks_per_node = 48 communication_configuration = 1 - debug = .true. + debug = .false. / &obs_def_gps_nml diff --git a/templates/namelist.input b/templates/namelist.input index 6fe6f5ad0388b985f48b7a7e0cfde46563446c48..01e2a2689caaaeff5bbc1108107aac3e96d316f2 100644 --- a/templates/namelist.input +++ b/templates/namelist.input @@ -52,7 +52,7 @@ mp_physics = 8, 1, 1, ra_lw_physics = 4, 0, 0, ra_sw_physics = 4, 0, 0, - radt = 5, 30, 30, + radt = <radt>, 30, 30, sf_sfclay_physics = 5, 0, 0, sf_surface_physics = 2, 0, 0, bl_pbl_physics = 5, 0, 0,