From 8c2706e1468240ddb815b40a21bd5e952aef9d99 Mon Sep 17 00:00:00 2001 From: Guillaume Vernieres Date: Tue, 9 May 2023 07:25:43 -0400 Subject: [PATCH] Adapt the marine DA to the new COM structure (#457) * works but needs tidy * adopted -new com for ctests * code tidy * working state, reverted yamls, started switching to FileHandler * use filehandler for post * fixed com naming * removed module purge/load * code tidy? * first try # 127 * reverted stage.atmos stuff * no module load --------- Co-authored-by: Cory Martin --- .gitignore | 1 + .../exgdas_global_marine_analysis_chkpt.sh | 4 +- scripts/exgdas_global_marine_analysis_post.py | 96 +++++++------ scripts/exgdas_global_marine_analysis_prep.py | 132 ++++++++++-------- scripts/exgdas_global_marine_analysis_vrfy.py | 10 +- .../global-workflow/run_jedi_exe_3denvar.sh | 8 +- .../global-workflow/run_jedi_exe_3dhofx.sh | 8 +- .../atm/global-workflow/run_jedi_exe_3dvar.sh | 8 +- .../atm/global-workflow/run_jedi_exe_letkf.sh | 8 +- test/soca/CMakeLists.txt | 20 --- test/soca/gw/CMakeLists.txt | 7 + test/soca/gw/prep.sh | 40 ++++++ test/soca/gw/run_jjobs.yaml.test | 6 +- test/soca/{ => gw}/static.sh | 0 test/soca/runtime_vars.sh | 52 ------- test/soca/test_bmat.sh | 28 ---- test/soca/test_bmat_vrfy.sh | 26 ---- test/soca/test_prep.sh | 75 ---------- test/soca/test_run.sh | 38 ----- test/soca/test_utils.sh | 10 -- ush/soca/run_jjobs.py | 83 +++++++---- ush/ufsda/stage.py | 11 +- 22 files changed, 264 insertions(+), 407 deletions(-) create mode 100755 test/soca/gw/prep.sh rename test/soca/{ => gw}/static.sh (100%) mode change 100644 => 100755 delete mode 100644 test/soca/runtime_vars.sh delete mode 100755 test/soca/test_bmat.sh delete mode 100755 test/soca/test_bmat_vrfy.sh delete mode 100755 test/soca/test_prep.sh delete mode 100755 test/soca/test_run.sh delete mode 100644 test/soca/test_utils.sh diff --git a/.gitignore b/.gitignore index d11bd354c..4eff16035 100644 --- a/.gitignore +++ b/.gitignore @@ -159,6 +159,7 @@ fv3-jedi-data/ fv3-jedi-lm/ gsibec/ gsw/ +icepack/ /ioda/ ioda-data/ iodaconv/ diff --git a/scripts/exgdas_global_marine_analysis_chkpt.sh b/scripts/exgdas_global_marine_analysis_chkpt.sh index 56bde64d4..6863a29a6 100755 --- a/scripts/exgdas_global_marine_analysis_chkpt.sh +++ b/scripts/exgdas_global_marine_analysis_chkpt.sh @@ -44,8 +44,8 @@ mom6_iau_incr=${DATA}/inc.nc # prepare nsst yaml if [ $DO_MERGENSST = "YES" ]; then cat > nsst.yaml << EOF -sfc_fcst: ${ROTDIR}/${GDUMP}.${gPDY}/${gcyc}/atmos/${GPREFIX}sfcf006.nc -sfc_ana: ${COMOUT}/../atmos/${APREFIX}sfcanl.nc +sfc_fcst: ${COM_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf006.nc +sfc_ana: ${COM_ATMOS_ANALYSIS}/${APREFIX}sfcanl.nc nlayers: 5 EOF diff --git a/scripts/exgdas_global_marine_analysis_post.py b/scripts/exgdas_global_marine_analysis_post.py index 1055d9135..8e375d9b2 100755 --- a/scripts/exgdas_global_marine_analysis_post.py +++ b/scripts/exgdas_global_marine_analysis_post.py @@ -23,71 +23,85 @@ import shutil import logging from datetime import datetime, timedelta -import ufsda +from pygw.file_utils import FileHandler + + +# TODO: Move this somewhere else? +def list_all_files(dir_in, dir_out, wc='*', fh_list=[]): + files = glob.glob(os.path.join(dir_in, wc)) + for file_src in files: + file_dst = os.path.join(dir_out, os.path.basename(file_src)) + fh_list.append([file_src, file_dst]) + return fh_list + # set up logger logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S') logging.info(f"---------------- Copy from RUNDIR to COMOUT") -comout = os.getenv('COMOUT') -comoutice = os.getenv('COMOUTice') +com_ocean_analysis = os.getenv('COM_OCEAN_ANALYSIS') +com_ice_restart = os.getenv('COM_ICE_RESTART') anl_dir = os.getenv('DATA') cdate = os.getenv('CDATE') pdy = os.getenv('PDY') staticsoca_dir = os.getenv('SOCA_INPUT_FIX_DIR') -cdump = os.getenv('CDUMP') -# TODO: this cycle math does the job, but datetime might be safer +RUN = os.getenv('CDUMP') cyc = str(os.getenv('cyc')).zfill(2) bcyc = str((int(cyc) - 3) % 24).zfill(2) gcyc = str((int(cyc) - 6) % 24).zfill(2) # previous cycle bdatedt = datetime.strptime(cdate, '%Y%m%d%H') - timedelta(hours=3) bdate = datetime.strftime(bdatedt, '%Y-%m-%dT%H:00:00Z') -# Make a copy the IAU increment -ufsda.disk_utils.copyfile(os.path.join(anl_dir, 'inc.nc'), - os.path.join(comout, cdump + '.t' + cyc + 'z.ocninc.nc')) +post_file_list = [] -# Copy of the ioda output files, as is for now -ufsda.disk_utils.copytree(os.path.join(anl_dir, 'diags'), - os.path.join(comout, 'diags')) +# Make a copy the IAU increment +post_file_list.append([os.path.join(anl_dir, 'inc.nc'), + os.path.join(com_ocean_analysis, f'{RUN}.t{cyc}z.ocninc.nc')]) # Copy of the diagonal of the background error for the cycle -ufsda.disk_utils.copyfile(os.path.join(anl_dir, 'ocn.bkgerr_stddev.incr.' + bdate + '.nc'), - os.path.join(comout, cdump + '.t' + cyc + 'z.ocn.bkgerr_stddev.nc')) -ufsda.disk_utils.copyfile(os.path.join(anl_dir, 'ice.bkgerr_stddev.incr.' + bdate + '.nc'), - os.path.join(comout, cdump + '.t' + cyc + 'z.ice.bkgerr_stddev.nc')) +post_file_list.append([os.path.join(anl_dir, f'ocn.bkgerr_stddev.incr.{bdate}.nc'), + os.path.join(com_ocean_analysis, f'{RUN}.t{cyc}z.ocn.bkgerr_stddev.nc')]) +post_file_list.append([os.path.join(anl_dir, f'ice.bkgerr_stddev.incr.{bdate}.nc'), + os.path.join(com_ocean_analysis, f'{RUN}.t{cyc}z.ice.bkgerr_stddev.nc')]) # Copy the ice and ocean increments -ufsda.disk_utils.copyfile(os.path.join(anl_dir, 'Data', 'ocn.3dvarfgat_pseudo.incr.' + bdate + '.nc'), - os.path.join(comout, cdump + '.t' + cyc + 'z.ocn.incr.nc')) -ufsda.disk_utils.copyfile(os.path.join(anl_dir, 'Data', 'ice.3dvarfgat_pseudo.incr.' + bdate + '.nc'), - os.path.join(comout, cdump + '.t' + cyc + 'z.ice.incr.nc')) - -# Copy the localization and correlation operators -ufsda.disk_utils.copytree(os.path.join(anl_dir, 'bump'), - os.path.join(comout, 'bump')) +post_file_list.append([os.path.join(anl_dir, 'Data', f'ocn.3dvarfgat_pseudo.incr.{bdate}.nc'), + os.path.join(com_ocean_analysis, f'{RUN}.t{cyc}z.ocn.incr.nc')]) +post_file_list.append([os.path.join(anl_dir, 'Data', f'ice.3dvarfgat_pseudo.incr.{bdate}.nc'), + os.path.join(com_ocean_analysis, f'{RUN}.t{cyc}z.ice.incr.nc')]) # Copy DA grid (computed for the start of the window) -ufsda.disk_utils.copyfile(os.path.join(anl_dir, 'soca_gridspec.nc'), - os.path.join(comout, cdump + '.t' + bcyc + 'z.ocngrid.nc')) +post_file_list.append([os.path.join(anl_dir, 'soca_gridspec.nc'), + os.path.join(com_ocean_analysis, f'{RUN}.t{bcyc}z.ocngrid.nc')]) # Copy the analysis at the start of the window -ufsda.disk_utils.copyfile(os.path.join(anl_dir, 'Data', 'ocn.3dvarfgat_pseudo.an.' + bdate + '.nc'), - os.path.join(comout, cdump + '.t' + cyc + 'z.ocnana.nc')) -ufsda.disk_utils.copyfile(os.path.join(anl_dir, 'Data', 'ice.3dvarfgat_pseudo.an.' + bdate + '.nc'), - os.path.join(comout, cdump + '.t' + cyc + 'z.iceana.nc')) +post_file_list.append([os.path.join(anl_dir, 'Data', f'ocn.3dvarfgat_pseudo.an.{bdate}.nc'), + os.path.join(com_ocean_analysis, f'{RUN}.t{cyc}z.ocnana.nc')]) +post_file_list.append([os.path.join(anl_dir, 'Data', f'ice.3dvarfgat_pseudo.an.{bdate}.nc'), + os.path.join(com_ocean_analysis, f'{RUN}.t{cyc}z.iceana.nc')]) # Copy the CICE analysis restart cdateice = pdy + '.' + cyc + '0000' -ufsda.disk_utils.copyfile(os.path.join(anl_dir, 'Data', cdateice + '.cice_model.res.nc'), - os.path.join(comoutice, 'RESTART', cdate + '.cice_model_anl.res.nc')) - -# Copy logs -ufsda.mkdir(os.path.join(comout, 'logs')) -for file in glob.glob(os.path.join(anl_dir, '*.out')): - ufsda.disk_utils.copyfile(file, os.path.join(comout, 'logs')) - -# Copy var.yaml -ufsda.mkdir(os.path.join(comout, 'yaml')) -for file in glob.glob(os.path.join(anl_dir, '*.yaml')): - ufsda.disk_utils.copyfile(file, os.path.join(comout, 'yaml')) +post_file_list.append([os.path.join(anl_dir, 'Data', f'{cdateice}.cice_model.res.nc'), + os.path.join(com_ice_restart, f'{cdate}.cice_model_anl.res.nc')]) + +FileHandler({'copy': post_file_list}).sync() + +# create COM sub-directories +FileHandler({'mkdir': [os.path.join(com_ocean_analysis, 'diags'), + os.path.join(com_ocean_analysis, 'bump'), + os.path.join(com_ocean_analysis, 'yaml')]}).sync() + +# ioda output files +fh_list = list_all_files(os.path.join(anl_dir, 'diags'), + os.path.join(com_ocean_analysis, 'diags')) + +# localization and correlation operators +fh_list = list_all_files(os.path.join(anl_dir, 'bump'), + os.path.join(com_ocean_analysis, 'bump'), fh_list=fh_list) + +# yaml configurations +fh_list = list_all_files(os.path.join(anl_dir), + os.path.join(com_ocean_analysis, 'yaml'), wc='*.yaml', fh_list=fh_list) + +FileHandler({'copy': fh_list}).sync() diff --git a/scripts/exgdas_global_marine_analysis_prep.py b/scripts/exgdas_global_marine_analysis_prep.py index 53545dc47..c52bd362a 100755 --- a/scripts/exgdas_global_marine_analysis_prep.py +++ b/scripts/exgdas_global_marine_analysis_prep.py @@ -35,7 +35,7 @@ from pygw.attrdict import AttrDict from pygw.template import Template, TemplateConstants from pygw.yaml_file import YAMLFile - +from pygw.file_utils import FileHandler # set up logger logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S') @@ -138,6 +138,7 @@ def gen_bkg_list(bkg_path, out_path, window_begin=' ', yaml_name='bkg.yaml', ice test_hist_date(os.path.join(bkg_path, ocn_filename_ic), bkg_date) # assert date of the history file is correct # Copy/process backgrounds and generate background yaml list + bkg_list_src_dst = [] bkg_list = [] for bkg in files: @@ -158,12 +159,12 @@ def gen_bkg_list(bkg_path, out_path, window_begin=' ', yaml_name='bkg.yaml', ice # Process the CICE history file so they can be read by soca/fms # TODO: Add date check of the cice history # TODO: bkg_path should be 1 level up - cice_hist2fms(os.path.join(bkg_path, '..', 'ice', ice_filename), + cice_hist2fms(os.path.join(os.getenv('COM_ICE_HISTORY_PREV'), ice_filename), os.path.join(out_path, agg_ice_filename)) - # copy ocean bkg to out_path - ufsda.disk_utils.copyfile(os.path.join(bkg_path, ocn_filename), - os.path.join(out_path, ocn_filename)) + # prepare list of ocean bkg to be copied to RUNDIR + bkg_list_src_dst.append([os.path.join(bkg_path, ocn_filename), + os.path.join(out_path, ocn_filename)]) bkg_dict = {'date': bkg_date.strftime('%Y-%m-%dT%H:%M:%SZ'), 'basename': './bkg/', @@ -173,9 +174,14 @@ def gen_bkg_list(bkg_path, out_path, window_begin=' ', yaml_name='bkg.yaml', ice 'remap_filename': './bkg/'+ocn_filename_ic} bkg_date = bkg_date + timedelta(hours=dt_pseudo) # TODO: make the bkg interval a configurable bkg_list.append(bkg_dict) + + # save pseudo model yaml configuration f = open(yaml_name, 'w') yaml.dump(bkg_list[1:], f, sort_keys=False, default_flow_style=False) + # copy ocean backgrounds to RUNDIR + FileHandler({'copy': bkg_list_src_dst}).sync() + def find_bkgerr(input_date, domain): """ @@ -200,31 +206,25 @@ def find_bkgerr(input_date, domain): logging.info(f"---------------- Setup runtime environement") -comout = os.getenv('COMOUT') -comin_obs = os.getenv('COMIN_OBS') +comin_obs = os.getenv('COMIN_OBS') # R2D2 DB for now anl_dir = os.getenv('DATA') staticsoca_dir = os.getenv('SOCA_INPUT_FIX_DIR') -# create analysis directory for files -ufsda.mkdir(anl_dir) - -# create output directory for obs -diags = os.path.join(anl_dir, 'diags') -ufsda.mkdir(diags) - -# create output directory for obs -bkg_dir = os.path.join(anl_dir, 'bkg') -ufsda.mkdir(bkg_dir) - -# create output directory for soca DA -anl_out = os.path.join(anl_dir, 'Data') -ufsda.mkdir(anl_out) +# create analysis directories +diags = os.path.join(anl_dir, 'diags') # output dir for soca DA obs space +obs_in = os.path.join(anl_dir, 'obs') # input " " +bkg_dir = os.path.join(anl_dir, 'bkg') # ice and ocean backgrounds +anl_out = os.path.join(anl_dir, 'Data') # output dir for soca DA +FileHandler({'mkdir': [anl_dir, diags, obs_in, bkg_dir, anl_out]}).sync() # Variables of convenience half_assim_freq = timedelta(hours=int(os.getenv('assim_freq'))/2) window_begin = datetime.strptime(os.getenv('PDY')+os.getenv('cyc'), '%Y%m%d%H') - half_assim_freq window_begin_iso = window_begin.strftime('%Y-%m-%dT%H:%M:%SZ') fcst_begin = datetime.strptime(os.getenv('PDY')+os.getenv('cyc'), '%Y%m%d%H') +RUN = os.getenv('RUN') +cyc = os.getenv('cyc') +PDY = os.getenv('PDY') ################################################################################ # fetch observations @@ -235,17 +235,34 @@ def find_bkgerr(input_date, domain): ufsda.r2d2.setup(r2d2_config_yaml=os.path.join(anl_dir, 'r2d2_config.yaml'), shared_root=comin_obs) # create config dict from runtime env -envconfig = ufsda.misc_utils.get_env_config(component='soca') -stage_cfg = YAMLFile(path=os.path.join(gdas_home, - 'parm', - 'templates', - 'stage.yaml')) +envconfig = {'window_begin': f"{window_begin.strftime('%Y-%m-%dT%H:%M:%SZ')}", + 'r2d2_obs_src': os.getenv('R2D2_OBS_SRC'), + 'r2d2_obs_dump': os.getenv('R2D2_OBS_DUMP'), + 'r2d2_obs_db': os.getenv('R2D2_OBS_DB'), + 'ATM_WINDOW_BEGIN': window_begin_iso, + 'ATM_WINDOW_LENGTH': f"PT{os.getenv('assim_freq')}H"} +stage_cfg = YAMLFile(path=os.path.join(gdas_home, 'parm', 'templates', 'stage.yaml')) stage_cfg = Template.substitute_structure(stage_cfg, TemplateConstants.DOUBLE_CURLY_BRACES, envconfig.get) stage_cfg = Template.substitute_structure(stage_cfg, TemplateConstants.DOLLAR_PARENTHESES, envconfig.get) +stage_cfg['r2d2_obs_out'] = os.getenv('COM_OBS') -# stage observations from R2D2 to COMIN_OBS and then link to analysis subdir +# stage observations from R2D2 COMIN_OBS to COM_OBS ufsda.stage.obs(stage_cfg) +# get the list of observations +obs_files = [] +for ob in stage_cfg['observations']['observers']: + obs_files.append(f"{RUN}.t{cyc}z.{ob['obs space']['name'].lower()}.{PDY}{cyc}.nc4") +obs_list = [] + +# copy obs from COM_OBS to DATA/obs +for obs_file in obs_files: + logging.info(f"******* {obs_file}") + obs_src = os.path.join(os.getenv('COM_OBS'), obs_file) + obs_dst = os.path.join(os.path.abspath(obs_in), obs_file) + obs_list.append([obs_src, obs_dst]) +FileHandler({'copy': obs_list}).sync() + ################################################################################ # stage static files @@ -256,10 +273,12 @@ def find_bkgerr(input_date, domain): # stage background error files logging.info(f"---------------- Stage static files") +bkgerr_list = [] for domain in ['ocn', 'ice']: fname_stddev = find_bkgerr(pytz.utc.localize(window_begin, is_dst=None), domain=domain) fname_out = domain+'.bkgerr_stddev.incr.'+window_begin_iso+'.nc' - ufsda.disk_utils.copyfile(fname_stddev, os.path.join(stage_cfg['stage_dir'], fname_out)) + bkgerr_list.append([fname_stddev, fname_out]) +FileHandler({'copy': bkgerr_list}).sync() ################################################################################ # prepare JEDI yamls @@ -267,15 +286,12 @@ def find_bkgerr(input_date, domain): logging.info(f"---------------- Generate JEDI yaml files") ################################################################################ -# link yaml for grid generation +# copy yaml for grid generation + +gridgen_yaml_src = os.path.abspath(os.path.join(gdas_home, 'parm', 'soca', 'gridgen', 'gridgen.yaml')) +gridgen_yaml_dst = os.path.abspath(os.path.join(stage_cfg['stage_dir'], 'gridgen.yaml')) +FileHandler({'copy': [[gridgen_yaml_src, gridgen_yaml_dst]]}).sync() -gridgen_yaml = os.path.join(gdas_home, - 'parm', - 'soca', - 'gridgen', - 'gridgen.yaml') -ufsda.disk_utils.symlink(gridgen_yaml, - os.path.join(stage_cfg['stage_dir'], 'gridgen.yaml')) ################################################################################ # generate YAML file for parametric diag of B @@ -292,15 +308,11 @@ def find_bkgerr(input_date, domain): config.save(berr_yaml) ################################################################################ -# link yaml for decorrelation length scales +# copy yaml for decorrelation length scales -corscales_yaml = os.path.join(gdas_home, - 'parm', - 'soca', - 'berror', - 'soca_setcorscales.yaml') -ufsda.disk_utils.symlink(corscales_yaml, - os.path.join(stage_cfg['stage_dir'], 'soca_setcorscales.yaml')) +corscales_yaml_src = os.path.join(gdas_home, 'parm', 'soca', 'berror', 'soca_setcorscales.yaml') +corscales_yaml_dst = os.path.join(stage_cfg['stage_dir'], 'soca_setcorscales.yaml') +FileHandler({'copy': [[corscales_yaml_src, corscales_yaml_dst]]}).sync() ################################################################################ # generate yaml for bump/nicas (used for correlation and/or localization) @@ -357,7 +369,7 @@ def find_bkgerr(input_date, domain): 'soca', 'variational', '3dvarfgat.yaml') -gen_bkg_list(bkg_path=os.getenv('COMIN_GES'), +gen_bkg_list(bkg_path=os.getenv('COM_OCEAN_HISTORY_PREV'), out_path=bkg_dir, window_begin=window_begin, yaml_name='bkg_list.yaml') @@ -387,10 +399,9 @@ def find_bkgerr(input_date, domain): # make a copy of the CICE6 restart rst_date = fcst_begin.strftime('%Y%m%d.%H%M%S') -ice_rst = os.path.join(os.getenv('COMIN_GES'), '..', 'ice', 'RESTART', - rst_date+'.cice_model.res.nc') +ice_rst = os.path.join(os.getenv('COM_ICE_RESTART_PREV'), f'{rst_date}.cice_model.res.nc') ice_rst_ana = os.path.join(anl_out, rst_date+'.cice_model.res.nc') -ufsda.disk_utils.copyfile(ice_rst, ice_rst_ana) +FileHandler({'copy': [[ice_rst, ice_rst_ana]]}).sync() # write the two seaice analysis to model change of variable yamls varchgyamls = ['soca_2cice_arctic.yaml', 'soca_2cice_antarctic.yaml'] @@ -408,26 +419,33 @@ def find_bkgerr(input_date, domain): for varchgyaml in varchgyamls: soca2cice_cfg['template'] = os.path.join(gdas_home, 'parm', 'soca', 'varchange', varchgyaml) f = open('tmp.yaml', 'w') + # TODO: use YAMLFile instead yaml.dump(soca2cice_cfg, f, sort_keys=False, default_flow_style=False) ufsda.genYAML.genYAML('tmp.yaml', output=varchgyaml) ################################################################################ -# links of convenience -RUN = os.getenv('RUN') -mom_ic = glob.glob(os.path.join(bkg_dir, f'{RUN}.*.ocnf003.nc'))[0] -ufsda.disk_utils.symlink(mom_ic, os.path.join(anl_dir, 'INPUT', 'MOM.res.nc')) - -cice_ic = glob.glob(os.path.join(bkg_dir, f'{RUN}.*.agg_icef003.nc'))[0] -ufsda.disk_utils.symlink(cice_ic, os.path.join(anl_dir, 'INPUT', 'cice.res.nc')) +# Copy initial condition +ics_list = [] +# ocean IC's +mom_ic_src = glob.glob(os.path.join(bkg_dir, f'{RUN}.*.ocnf003.nc'))[0] +mom_ic_dst = os.path.join(anl_dir, 'INPUT', 'MOM.res.nc') +ics_list.append([mom_ic_src, mom_ic_dst]) + +# seaice IC's +cice_ic_src = glob.glob(os.path.join(bkg_dir, f'{RUN}.*.agg_icef003.nc'))[0] +cice_ic_dst = os.path.join(anl_dir, 'INPUT', 'cice.res.nc') +ics_list.append([cice_ic_src, cice_ic_dst]) +FileHandler({'copy': ics_list}).sync() ################################################################################ # prepare input.nml mom_input_nml_src = os.path.join(gdas_home, 'parm', 'soca', 'fms', 'input.nml') mom_input_nml_tmpl = os.path.join(stage_cfg['stage_dir'], 'mom_input.nml.tmpl') mom_input_nml = os.path.join(stage_cfg['stage_dir'], 'mom_input.nml') -ufsda.disk_utils.copyfile(mom_input_nml_src, mom_input_nml_tmpl) -domain_stack_size = os.getenv('DOMAIN_STACK_SIZE') +FileHandler({'copy': [[mom_input_nml_src, mom_input_nml_tmpl]]}).sync() +# swap date and stack size +domain_stack_size = os.getenv('DOMAIN_STACK_SIZE') ymdhms = [int(s) for s in window_begin.strftime('%Y,%m,%d,%H,%M,%S').split(',')] with open(mom_input_nml_tmpl, 'r') as nml_file: nml = f90nml.read(nml_file) diff --git a/scripts/exgdas_global_marine_analysis_vrfy.py b/scripts/exgdas_global_marine_analysis_vrfy.py index c49025af3..f26cdd631 100755 --- a/scripts/exgdas_global_marine_analysis_vrfy.py +++ b/scripts/exgdas_global_marine_analysis_vrfy.py @@ -120,7 +120,9 @@ def plot_zonal_slice(config): plt.savefig(figname, bbox_inches='tight', dpi=600) -comout = os.getenv('COMOUT') +comout = os.getenv('COM_OCEAN_ANALYSIS') +com_ice_history = os.getenv('COM_ICE_HISTORY_PREV') +com_ocean_history = os.getenv('COM_OCEAN_HISTORY_PREV') data = os.getenv('DATA') pdy = os.getenv('PDY') cyc = os.getenv('cyc') @@ -205,8 +207,8 @@ def plot_zonal_slice(config): ####################################### # Sea ice -data_files = [os.path.join(comout, f'{RUN}.t'+cyc+'z.iceana.nc'), - os.path.join(comout, '..', '..', '..', gcdate.strftime(f'{RUN}.%Y%m%d/%H'), 'ice', f'{RUN}.t'+gcyc+'z.icef006.nc')] +data_files = [os.path.join(comout, f'{RUN}.t{cyc}z.iceana.nc'), + os.path.join(com_ice_history, f'{RUN}.t{gcyc}z.icef006.nc')] dirs_out = ['ana', 'bkg'] ice_vars = {'bkg': ['aice_h', 'hs_h', 'hi_h'], 'ana': ['aicen', 'hicen', 'hsnon']} for data_file, dir_out in zip(data_files, dirs_out): @@ -232,7 +234,7 @@ def plot_zonal_slice(config): ####################################### # Ocean surface data_files = [os.path.join(comout, f'{RUN}.t'+cyc+'z.ocnana.nc'), - os.path.join(comout, '..', '..', '..', gcdate.strftime(f'{RUN}.%Y%m%d/%H'), 'ocean', f'{RUN}.t'+gcyc+'z.ocnf006.nc')] + os.path.join(com_ocean_history, f'{RUN}.t{gcyc}z.ocnf006.nc')] dirs_out = ['ana', 'bkg'] ocn_vars = ['ave_ssh', 'Temp', 'Salt'] for data_file, dir_out in zip(data_files, dirs_out): diff --git a/test/atm/global-workflow/run_jedi_exe_3denvar.sh b/test/atm/global-workflow/run_jedi_exe_3denvar.sh index faa6d09dc..4e7b9b24c 100755 --- a/test/atm/global-workflow/run_jedi_exe_3denvar.sh +++ b/test/atm/global-workflow/run_jedi_exe_3denvar.sh @@ -15,10 +15,10 @@ else fi # Load modules -set +x -module use ${srcdir}/modulefiles -module load GDAS/${machine} -set -x +#set +x +#module use ${srcdir}/modulefiles +#module load GDAS/${machine} +#set -x module list # Set machine dependent variables diff --git a/test/atm/global-workflow/run_jedi_exe_3dhofx.sh b/test/atm/global-workflow/run_jedi_exe_3dhofx.sh index f55fb6415..d7c3b3d86 100755 --- a/test/atm/global-workflow/run_jedi_exe_3dhofx.sh +++ b/test/atm/global-workflow/run_jedi_exe_3dhofx.sh @@ -15,10 +15,10 @@ else fi # Load modules -set +x -module use ${srcdir}/modulefiles -module load GDAS/${machine} -set -x +#set +x +#module use ${srcdir}/modulefiles +#module load GDAS/${machine} +#set -x module list # Set machine dependent variables diff --git a/test/atm/global-workflow/run_jedi_exe_3dvar.sh b/test/atm/global-workflow/run_jedi_exe_3dvar.sh index d333db3cc..ca530f280 100755 --- a/test/atm/global-workflow/run_jedi_exe_3dvar.sh +++ b/test/atm/global-workflow/run_jedi_exe_3dvar.sh @@ -15,10 +15,10 @@ else fi # Load modules -set +x -module use ${srcdir}/modulefiles -module load GDAS/${machine} -set -x +#set +x +#module use ${srcdir}/modulefiles +#module load GDAS/${machine} +#set -x module list # Set machine dependent variables diff --git a/test/atm/global-workflow/run_jedi_exe_letkf.sh b/test/atm/global-workflow/run_jedi_exe_letkf.sh index 287b67641..0574184b1 100755 --- a/test/atm/global-workflow/run_jedi_exe_letkf.sh +++ b/test/atm/global-workflow/run_jedi_exe_letkf.sh @@ -15,10 +15,10 @@ else fi # Load modules -set +x -module use ${srcdir}/modulefiles -module load GDAS/${machine} -set -x +#set +x +#module use ${srcdir}/modulefiles +#module load GDAS/${machine} +#set -x module list # Set machine dependent variables diff --git a/test/soca/CMakeLists.txt b/test/soca/CMakeLists.txt index fbeab7700..a0383f260 100644 --- a/test/soca/CMakeLists.txt +++ b/test/soca/CMakeLists.txt @@ -1,14 +1,6 @@ # Copy the bkg files # ------------------ set( TESTDATA ${PROJECT_BINARY_DIR}/test/testdata ) -file(GLOB bkg_diag "${TESTDATA}/ocn_da_2018_04_15_*.nc") -file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/test/soca/bkg/RESTART) -file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/test/soca/bkg/RESTART_GES) -file(COPY ${bkg_diag} DESTINATION ${PROJECT_BINARY_DIR}/test/soca/bkg/RESTART) -configure_file(${TESTDATA}/iced.2019-04-15-43200.nc - ${PROJECT_BINARY_DIR}/test/soca/ice/RESTART/20180415.120000.cice_model.res.nc - COPYONLY) -file(COPY ${TESTDATA}/cice_hist.nc DESTINATION ${PROJECT_BINARY_DIR}/test/soca/bkg/RESTART) # link input file from iodaconv to test directory # test convert BUFR to IODA @@ -79,18 +71,6 @@ set_tests_properties(test_gdasapp_soca_obsdb PROPERTIES ENVIRONMENT "PYTHONPATH=${PROJECT_BINARY_DIR}/ush:${PROJECT_SOURCE_DIR}/../../ush/python/pygw/src:$ENV{PYTHONPATH};SOCA_TEST_OBS=${PROJECT_SOURCE_DIR}/test/soca/testdata") -# Test exgdas_global_marine_analysis_prep.py -# ------------------------------------------ -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/3dvar) - -# Prep -add_test(NAME test_gdasapp_soca_ana_prep - COMMAND ${PROJECT_SOURCE_DIR}/test/soca/test_prep.sh ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR} - WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test/soca/3dvar) - set_tests_properties(test_gdasapp_soca_ana_prep - PROPERTIES - ENVIRONMENT "PYTHONPATH=${PROJECT_BINARY_DIR}/ush:${PROJECT_SOURCE_DIR}/../../ush/python/pygw/src:$ENV{PYTHONPATH}") - # Test exgdas scripts from the global-worflow if (WORKFLOW_TESTS) add_subdirectory(gw) diff --git a/test/soca/gw/CMakeLists.txt b/test/soca/gw/CMakeLists.txt index 3846dd923..d193095e3 100644 --- a/test/soca/gw/CMakeLists.txt +++ b/test/soca/gw/CMakeLists.txt @@ -2,6 +2,13 @@ file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/test/soca/gw/testrun) file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/test/soca/gw/concatioda) +# Prepare COMROT and static dir +add_test(NAME test_gdasapp_soca_prep + COMMAND ${PROJECT_SOURCE_DIR}/test/soca/gw/prep.sh ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test/soca/gw) + set_tests_properties(test_gdasapp_soca_prep + PROPERTIES + ENVIRONMENT "PYTHONPATH=${PROJECT_BINARY_DIR}/ush:${PROJECT_SOURCE_DIR}/../../ush/python/pygw/src:$ENV{PYTHONPATH}") # Identify machine set(MACHINE "container") diff --git a/test/soca/gw/prep.sh b/test/soca/gw/prep.sh new file mode 100755 index 000000000..436db4636 --- /dev/null +++ b/test/soca/gw/prep.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -e + +project_binary_dir=$1 +project_source_dir=$2 + +# Get low res static files from the soca sandbox +${project_source_dir}/test/soca/gw/static.sh $project_binary_dir $project_source_dir + +# Stage history and restart files following the "COM" structure + +COM=${project_binary_dir}/test/soca/gw/COM/gdas.20180415 + +mkdir -p ${COM}/06/model_data/ice/history +mkdir -p ${COM}/06/model_data/ice/restart +mkdir -p ${COM}/06/model_data/ocean/history +mkdir -p ${COM}/06/model_data/atmos/analysis + +# copy CICE6 restart +ice_rst=${project_binary_dir}/test/testdata/iced.2019-04-15-43200.nc +hist_icef=${project_binary_dir}/test/testdata/cice_hist.nc + +cp ${ice_rst} ${COM}/06/model_data/ice/restart/20180415.120000.cice_model.res.nc + +# invent MOM6 and CICE6 history files +i=3 +lof=`ls ${project_binary_dir}/test/testdata/ocn_da_*` +for ocnf in $lof; do + cp $ocnf ${COM}/06/model_data/ocean/history/gdas.t06z.ocnf00$i.nc + cp $hist_icef ${COM}/06/model_data/ice/history/gdas.t06z.icef00$i.nc + i=$(($i+1)) +done + +# invent background error +for day in $(seq 1 2 9); do + cp ${COM}/06/model_data/ocean/history/gdas.t06z.ocnf003.nc \ + ${project_binary_dir}/soca_static/bkgerr/stddev/ocn.ensstddev.fc.2019-04-0${day}T00:00:00Z.PT0S.nc + cp ${project_source_dir}/soca/test/Data/72x35x25/ice.bkgerror.nc \ + ${project_binary_dir}/soca_static/bkgerr/stddev/ice.ensstddev.fc.2019-04-0${day}T00:00:00Z.PT0S.nc +done diff --git a/test/soca/gw/run_jjobs.yaml.test b/test/soca/gw/run_jjobs.yaml.test index b58843a7b..47b448d04 100644 --- a/test/soca/gw/run_jjobs.yaml.test +++ b/test/soca/gw/run_jjobs.yaml.test @@ -9,7 +9,7 @@ gw environement: PSLOT: gdas_test HOMEgfs: @HOMEgfs@ COMPONENT: ocean - CDUMP: gdas + RUN: gdas cycle info: PDY: 20180415 @@ -17,10 +17,10 @@ gw environement: assym_freq: 6 backgrounds: - COMIN_GES: @HOMEgfs@/sorc/gdas.cd/build/test/soca/bkg + COM_SRC: @HOMEgfs@/sorc/gdas.cd/build/test/soca/gw/COM working directories: - ROTDIR: @HOMEgfs@/sorc/gdas.cd/build/test/soca/gw/testrun/testjjobs/ROTDIRS + ROTDIRS: @HOMEgfs@/sorc/gdas.cd/build/test/soca/gw/testrun/testjjobs/ROTDIRS EXPDIRS: @HOMEgfs@/sorc/gdas.cd/build/test/soca/gw/testrun/testjjobs/experiments STMP: @HOMEgfs@/sorc/gdas.cd/build/test/soca/gw/testrun/testjjobs diff --git a/test/soca/static.sh b/test/soca/gw/static.sh old mode 100644 new mode 100755 similarity index 100% rename from test/soca/static.sh rename to test/soca/gw/static.sh diff --git a/test/soca/runtime_vars.sh b/test/soca/runtime_vars.sh deleted file mode 100644 index 90aa63c46..000000000 --- a/test/soca/runtime_vars.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash -set -e - -project_binary_dir=$1 -project_source_dir=$2 - -# Prepare runtime environement -export PDY=20180415 # Center of current cycle date -export cyc=12 # Center of current cycle date -export GDATE=2018041506 # Center of previous cycle date -export gcyc=$(echo $GDATE | cut -c9-10) -export CDUMP=gdas # still uised in ufsda.misc_utils.get_env_config -export RUN=gdas -export GDUMP=gdas -export OPREFIX=${RUN}.t${cyc}z. -export assim_freq=6 # DA window -export COMOUT=${project_binary_dir}/test/soca/3dvar -export DATA=${project_binary_dir}/test/soca/3dvar/ocnanal_${cyc} -export COMIN_OBS=${project_binary_dir}/test/soca/obs/r2d2-shared -export COMIN_GES=${project_binary_dir}/test/soca/bkg # Backgrounds from previous forecast -export CASE_ANL="C48" # TODO: Replace with or add OCNRES -export CASE="C48" # TODO: Replace with or add OCNRES -export DOHYBVAR=False -export CASE_ENKF="C192" # TODO: Needed but doesn't mean anything in this ctest context -export LEVS="75" # TODO: Same as above -export OBS_LIST=${project_binary_dir}/test/soca/testinput/obs_list.yaml # list of obs for the experiment -export OBS_YAML=${project_binary_dir}/test/soca/testinput/obs_list.yaml # list of obs for the experiment -export OBS_YAML_DIR=${project_source_dir}/parm/soca/obs/config # path to UFO yaml files - -mkdir -p ${project_binary_dir}/test/soca/HOMEgfs/sorc/ -export HOMEgfs=${project_binary_dir}/test/soca/HOMEgfs - -ufsda_link=${project_binary_dir}/test/soca/HOMEgfs/sorc/gdas.cd -[ ! -L "${ufsda_link}" ] && ln -s ${project_source_dir} ${ufsda_link} - -ush_link=${project_binary_dir}/test/soca/HOMEgfs/ush -[ ! -L "${ush_link}" ] && ln -s ${project_source_dir}/ush ${ush_link} - -export JEDI_BIN=${project_binary_dir}/bin -export SOCA_INPUT_FIX_DIR=${project_binary_dir}/soca_static # static soca files -export SOCA_VARS=tocn,socn,ssh,cicen,hicen # Should be renamed, these are the control variables -export DOMAIN_STACK_SIZE=2000000 -export STATICB_DIR=${project_binary_dir}/test/soca/staticb # Static B-matrix -export FV3JEDI_STAGE_YAML=${project_binary_dir}/test/soca/testinput/dumy.yaml # Useless atmospheric stuff -export R2D2_OBS_DB=shared -export R2D2_OBS_DUMP=soca -export R2D2_OBS_SRC=gdasapp -export R2D2_OBS_WINDOW=24 # R2D2 sampling DB window -export SOCA_NINNER=2 -export NICAS_RESOL=1 -export NICAS_GRID_SIZE=15000 -export APRUN_OCNANAL="$MPIEXEC_EXEC $MPIEXEC_NPROC 2" diff --git a/test/soca/test_bmat.sh b/test/soca/test_bmat.sh deleted file mode 100755 index 5560fef99..000000000 --- a/test/soca/test_bmat.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -set -e - -project_binary_dir=$1 -project_source_dir=$2 - -source ${project_source_dir}/test/soca/test_utils.sh - -# Clean test files created during a previous test -echo "============================= Test that the grid has been generated" -rm -f ${DATA}/soca_gridspec.nc -rm -f ${DATA}/ocn.bkgerr_stddev.incr.2018-04-15T09:00:00Z.nc -rm -f ${DATA}/bump/bump[23]d_nicas_local_000002-00000[12].nc - -# Export runtime env. variables -source ${project_source_dir}/test/soca/runtime_vars.sh $project_binary_dir $project_source_dir - -# Run step -echo "============================= Testing exgdas_global_marine_analysis_bmat.sh for clean exit" -${project_source_dir}/scripts/exgdas_global_marine_analysis_bmat.sh > exgdas_global_marine_analysis_bmat.log - -echo "============================= Test that the grid has been generated" -test_file ${DATA}/soca_gridspec.nc - -echo "============================= Test that the parametric diag of B was generated" -test_file ${DATA}/ocn.bkgerr_stddev.incr.2018-04-15T09:00:00Z.nc -test_file ${DATA}/bump/bump2d_nicas_local_000002-000001.nc -test_file ${DATA}/bump/bump3d_nicas_local_000002-000001.nc diff --git a/test/soca/test_bmat_vrfy.sh b/test/soca/test_bmat_vrfy.sh deleted file mode 100755 index 3f8838b5d..000000000 --- a/test/soca/test_bmat_vrfy.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -set -e - -project_binary_dir=$1 -project_source_dir=$2 - -source ${project_source_dir}/test/soca/test_utils.sh - -# Clean test files created during a previous test -echo "============================= Test that the grid has been generated" -rm -f ${DATA}/Data/*dirac* - -# Export runtime env. variables -source ${project_source_dir}/test/soca/runtime_vars.sh $project_binary_dir $project_source_dir - -# B-matrix diagnostic step -echo "============================= Testing exgdas_global_marine_analysis_bamt_vrfy.sh for clean exit" -${project_source_dir}/scripts/exgdas_global_marine_analysis_bmat_vrfy.sh > exgdas_global_marine_analysis_bmat_vrfy.log - -echo "============================= Test that the dirac file has been generated" -arr=("tocn" "socn" "ssh" "cicen" "hicen") -for i in "${!arr[@]}" -do - test_file ${DATA}/Data/ice.dirac_${arr[i]}_1.an.2018-04-15T09:00:00Z.nc - test_file ${DATA}/Data/ocn.dirac_${arr[i]}_1.an.2018-04-15T09:00:00Z.nc -done diff --git a/test/soca/test_prep.sh b/test/soca/test_prep.sh deleted file mode 100755 index 961b16405..000000000 --- a/test/soca/test_prep.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -set -e - -project_binary_dir=$1 -project_source_dir=$2 - -source ${project_source_dir}/test/soca/test_utils.sh - -# Remove previously fetched obs -rm -f ${project_binary_dir}/test/soca/3dvar/ocnanal_12/obs/gdas.t12z.{sst,adt,sss,salt,icec}*.nc4 - -# Export runtime env. variables -source ${project_source_dir}/test/soca/runtime_vars.sh $project_binary_dir $project_source_dir - -# Get low res static files from the soca sandbox -source ${project_source_dir}/test/soca/static.sh $project_binary_dir $project_source_dir - -# MOM6's diag output needs to be renamed, CICE restarts are made up -i=3 -lof=`ls ${project_binary_dir}/test/soca/bkg/RESTART/ocn_da_*` -icef=${project_binary_dir}/test/soca/bkg/RESTART/iced.2019-04-15-43200.nc # TODO: cice restart is made up -hist_icef=${project_binary_dir}/test/soca/bkg/RESTART/cice_hist.nc # TODO: cice hist date is no ggod -mkdir -p ${project_binary_dir}/test/soca/ice -for ocnf in $lof; do - cp $ocnf ${project_binary_dir}/test/soca/bkg/gdas.t06z.ocnf00$i.nc - cp $hist_icef ${project_binary_dir}/test/soca/ice/gdas.t06z.icef00$i.nc - i=$(($i+1)) -done - -# Invent background error -for day in $(seq 1 2 9); do - cp ${project_binary_dir}/test/soca/bkg/gdas.t06z.ocnf003.nc \ - ${project_binary_dir}/soca_static/bkgerr/stddev/ocn.ensstddev.fc.2019-04-0${day}T00:00:00Z.PT0S.nc - cp ${project_source_dir}/soca/test/Data/72x35x25/ice.bkgerror.nc \ - ${project_binary_dir}/soca_static/bkgerr/stddev/ice.ensstddev.fc.2019-04-0${day}T00:00:00Z.PT0S.nc -done - -# Run prep step -echo "============================= Testing exgdas_global_marine_analysis_prep.py for clean exit" -${project_source_dir}/scripts/exgdas_global_marine_analysis_prep.py - -# Test that the obs path in var.yaml exist -echo "============================= Testing the existence of obs and bkg in var.vaml" -obslist=`grep 'gdas.t12z' ${DATA}/var.yaml` -for o in $obslist; do - echo "----------------------- "$o - case $o in - "obsfile:") - base='' - continue - ;; - "ocn_filename:") - base=${project_binary_dir}/test/soca/3dvar/ocnanal_12/bkg/ - continue - ;; - "ice_filename:") - base=${project_binary_dir}/test/soca/3dvar/ocnanal_12/bkg/ - continue - ;; - "remap_filename:") - base=${project_binary_dir}/test/soca/3dvar/ocnanal_12/ - continue - ;; - esac - test_file ${base}$o -done - -# Test that the static files have been linked properly -echo "============================= Test that the static files have been linked properly" -test_file $(readlink ${DATA}/diag_table) -test_file $(readlink ${DATA}/field_table) -test_file $(readlink ${DATA}/fields_metadata.yaml) -test_file $(readlink ${DATA}/godas_sst_bgerr.nc) -test_file $(readlink ${DATA}/rossrad.dat) -test_file $(readlink ${DATA}/MOM_input) diff --git a/test/soca/test_run.sh b/test/soca/test_run.sh deleted file mode 100755 index ba653433b..000000000 --- a/test/soca/test_run.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -set -e - -project_binary_dir=$1 -project_source_dir=$2 - -source ${project_source_dir}/test/soca/test_utils.sh - -# Clean test files created during a previous test -echo "============================= Test that the grid has been generated" -rm -f ${DATA}/soca_gridspec.nc -rm -f ${DATA}/ocn.bkgerr_stddev.incr.2018-04-15T09:00:00Z.nc -rm -f ${DATA}/Data/ocn.iter1.incr.2018-04-15T09:00:00Z.nc -rm -f ${DATA}/Data/ocn.3dvarfgat_pseudo.incr.2018-04-15T09:00:00Z.nc -rm -f ${DATA}/Data/ocn.3dvarfgat_pseudo.an.2018-04-15T09:00:00Z.nc -rm -f ${DATA}/Data/ocn.3dvarfgat_pseudo.an.2018-04-15T12:00:00Z.nc -rm -f ${DATA}/Data/ocn.3dvarfgat_pseudo.an.2018-04-15T15:00:00Z.nc -rm -f ${DATA}/Data/inc.nc - -# Export runtime env. variables -source ${project_source_dir}/test/soca/runtime_vars.sh $project_binary_dir $project_source_dir - -# Run step -echo "============================= Testing exgdas_global_marine_analysis_run.sh for clean exit" -${project_source_dir}/scripts/exgdas_global_marine_analysis_run.sh > exgdas_global_marine_analysis_run.log - -echo "============================= Test that the grid has been generated" -test_file ${DATA}/soca_gridspec.nc - -echo "============================= Test that the parametric diag of B was generated" -test_file ${DATA}/ocn.bkgerr_stddev.incr.2018-04-15T09:00:00Z.nc - -echo "============================= Test that an increment and an analysis were created" -test_file ${DATA}/Data/ocn.iter1.incr.2018-04-15T09:00:00Z.nc -test_file ${DATA}/Data/ocn.3dvarfgat_pseudo.an.2018-04-15T09:00:00Z.nc -test_file ${DATA}/Data/ocn.3dvarfgat_pseudo.an.2018-04-15T12:00:00Z.nc -test_file ${DATA}/Data/ocn.3dvarfgat_pseudo.an.2018-04-15T15:00:00Z.nc -test_file ${COMOUT}/ocnanal_12/inc.nc diff --git a/test/soca/test_utils.sh b/test/soca/test_utils.sh deleted file mode 100644 index 04aced55c..000000000 --- a/test/soca/test_utils.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -test_file () { - if test -f "$1"; then - echo " - $1 exists" - else - echo " - $1 does not exist" - exit 1 - fi -} diff --git a/ush/soca/run_jjobs.py b/ush/soca/run_jjobs.py index 8bb834336..cbb4a3567 100755 --- a/ush/soca/run_jjobs.py +++ b/ush/soca/run_jjobs.py @@ -4,16 +4,12 @@ import sys import subprocess import argparse - +from datetime import datetime, timedelta machines = {"container", "hera", "orion"} -MODS = {'JGDAS_GLOBAL_OCEAN_ANALYSIS_PREP': 'GDAS', - 'JGDAS_GLOBAL_OCEAN_ANALYSIS_BMAT': 'GDAS', - 'JGDAS_GLOBAL_OCEAN_ANALYSIS_BMAT_VRFY': 'GDAS', - 'JGDAS_GLOBAL_OCEAN_ANALYSIS_RUN': 'GDAS', - 'JGDAS_GLOBAL_OCEAN_ANALYSIS_CHKPT': 'GDAS', - 'JGDAS_GLOBAL_OCEAN_ANALYSIS_POST': 'GDAS', - 'JGDAS_GLOBAL_OCEAN_ANALYSIS_VRFY': 'EVA'} + +# Assume the default conda environement is gdassapp +ENVS = {'JGDAS_GLOBAL_OCEAN_ANALYSIS_VRFY': 'eva'} components_short = {'ocean': 'ocn', 'ice': 'ice'} # Short names for components @@ -28,15 +24,27 @@ def __init__(self, scriptname, config): self.name = scriptname self.f = open(self.name, "w") self.f.write("#!/usr/bin/env bash\n") - self.component = config['gw environement']['experiment identifier']['COMPONENT'] self.pslot = config['gw environement']['experiment identifier']['PSLOT'] self.homegfs = config['gw environement']['experiment identifier']['HOMEgfs'] self.stmp = config['gw environement']['working directories']['STMP'] - self.rotdirs = config['gw environement']['working directories']['ROTDIR'] + self.rotdirs = config['gw environement']['working directories']['ROTDIRS'] + self.rotdir = os.path.join(self.rotdirs, self.pslot) self.expdirs = config['gw environement']['working directories']['EXPDIRS'] self.config = config self.machine = config['machine'] + # get cycle info + self.PDY = config['gw environement']['cycle info']['PDY'] + self.cyc = config['gw environement']['cycle info']['cyc'] + self.assim_freq = config['gw environement']['cycle info']['assym_freq'] + self.RUN = config['gw environement']['experiment identifier']['RUN'] + + # compute previous cycle info + gdate = datetime.strptime(f"{self.PDY}{self.cyc}", '%Y%m%d%H') - timedelta(hours=self.assim_freq) + self.gPDY = gdate.strftime("%Y%m%d") + self.gcyc = gdate.strftime("%H") + self.com_src = config['gw environement']['backgrounds']['COM_SRC'] + def header(self): """ Write machine dependent scheduler header @@ -60,12 +68,14 @@ def export_env_vars_script(self): # Compute remaining environment variables config = self.config['gw environement'] EXPDIR = os.path.join(config['working directories']['EXPDIRS'], self.pslot) + ROTDIR = self.rotdir DATAROOT = os.path.join(config['working directories']['STMP'], 'RUNDIRS', self.pslot) gcyc = str((config['cycle info']['cyc'] - config['cycle info']['assym_freq']) % 24).zfill(2) CDATE = f"{config['cycle info']['PDY']}{config['cycle info']['cyc']}" # TODO: Not needed after Andy's PR # Write the export commands for the remaining environment variables self.f.write(f"export EXPDIR='{EXPDIR}'\n") + self.f.write(f"export ROTDIR='{ROTDIR}'\n") self.f.write(f"export DATAROOT='{DATAROOT}'\n") self.f.write(f"export gcyc='{gcyc}'\n") self.f.write(f"export CDATE='{CDATE}'\n") @@ -105,7 +115,7 @@ def setupexpt(self): "nens": "0", "pslot": "${PSLOT}", "configdir": "${PWD}/config", - "comrot": "${ROTDIR}", + "comrot": self.rotdir, "expdir": "${EXPDIRS}", "yaml": "overwrite_defaults.yaml"} @@ -121,32 +131,47 @@ def close(self): self.f.close() subprocess.run(["chmod", "+x", self.name]) - def _modules(self, jjob): + def _conda_envs(self, jjob): """ Write a section that will load the machine dependent modules """ if self.machine != "container": - self.f.write("module purge \n") - self.f.write("module use ${HOMEgfs}/sorc/gdas.cd/modulefiles \n") - self.f.write(f"module load {MODS[jjob]}/{self.machine} \n") + if jjob in ENVS: + # TODO: This does nothing for now. Make the conda activate work! + self.f.write(f"# conda activate {ENVS[jjob]} \n") + + def precom(self, com, tmpl): + cmd = f"RUN={self.RUN} YMD={self.gPDY} HH={self.gcyc} generate_com -xr {com}:{tmpl}" + self.f.write(f"{cmd}\n") def copy_bkgs(self): """ Fill the ROTDIR with backgrounds TODO: replace by fill comrot? """ - file_descriptor = components_short[self.component]+'f0' - self.f.write("mkdir -p ${ROTDIR}/${PSLOT}/gdas.${PDY}/${gcyc}/${COMPONENT}/\n") - command = "cp -r ${COMIN_GES}/*." + file_descriptor + "*.nc" - command += " ${ROTDIR}/${PSLOT}/gdas.${PDY}/${gcyc}/${COMPONENT}/\n" - self.f.write(command) - # Special case for the ocean: DA for ice & ocean - if self.component == 'ocean': - # staging ice backgrounds - ice_file_descriptor = components_short['ice'] - self.f.write("mkdir -p ${ROTDIR}/${PSLOT}/gdas.${PDY}/${gcyc}/ice/RESTART\n") - self.f.write("cp -r ${COMIN_GES}/../ice/*icef0*.nc ${ROTDIR}/${PSLOT}/gdas.${PDY}/${gcyc}/ice/\n") - self.f.write("cp -r ${COMIN_GES}/../ice/RESTART/*cice_model.res.nc ${ROTDIR}/${PSLOT}/gdas.${PDY}/${gcyc}/ice/RESTART/\n") + print(f"gPDY: {self.gPDY}") + print(f"gcyc: {self.gcyc}") + print(f"assim_freq: {self.assim_freq}") + print(f"RUN: {self.RUN}") + + # setup COM variables + self.f.write("source ${HOMEgfs}/parm/config/config.com\n") + self.f.write("source ${HOMEgfs}/ush/preamble.sh\n") + self.precom('COM_OCEAN_HISTORY_PREV', 'COM_OCEAN_HISTORY_TMPL') + self.precom('COM_ICE_HISTORY_PREV', 'COM_ICE_HISTORY_TMPL') + self.precom('COM_ICE_RESTART_PREV', 'COM_ICE_RESTART_TMPL') + + self.f.write("mkdir -p ${COM_OCEAN_HISTORY_PREV}/\n") + self.f.write("mkdir -p ${COM_ICE_HISTORY_PREV}/\n") + self.f.write("mkdir -p ${COM_ICE_RESTART_PREV}/\n") + + model_data = os.path.join(self.com_src, f"{self.RUN}.{self.gPDY}", self.gcyc, "model_data") + com_ocean_history_src = os.path.join(model_data, 'ocean', 'history') + com_ice_history_src = os.path.join(model_data, 'ice', 'history') + com_ice_restart_src = os.path.join(model_data, 'ice', 'restart') + self.f.write(f"cp {com_ocean_history_src}/*ocnf*.nc $COM_OCEAN_HISTORY_PREV \n") + self.f.write(f"cp {com_ice_history_src}/*icef*.nc $COM_ICE_HISTORY_PREV \n") + self.f.write(f"cp {com_ice_restart_src}/*cice_model*.nc $COM_ICE_RESTART_PREV \n") def fixconfigs(self): """ @@ -165,7 +190,7 @@ def fixconfigs(self): # swap a few variables in config.base var2replace = {'HOMEgfs': self.homegfs, 'STMP': self.stmp, - 'ROTDIRS': self.rotdirs, + 'ROTDIR': self.rotdir, 'EXPDIRS': self.expdirs} with open(configbase, 'r') as f: newconfigbase = f.read() @@ -179,7 +204,7 @@ def jjobs(self): Add the list of j-jobs to the job card """ for job in self.config['jjobs']: - self._modules(job) # Add module's jjob + self._conda_envs(job) # Add module's jjob thejob = "${HOMEgfs}/jobs/"+job runjob = f"{thejob} &>{job}.out\n" self.f.write(runjob) diff --git a/ush/ufsda/stage.py b/ush/ufsda/stage.py index 3ed614dd8..32b4d5009 100644 --- a/ush/ufsda/stage.py +++ b/ush/ufsda/stage.py @@ -12,7 +12,7 @@ import logging import glob import numpy as np -from pygw.yaml_file import YAMLFile, parse_j2yaml +from pygw.yaml_file import YAMLFile, parse_yaml, parse_j2yaml import ufsda.soca_utils __all__ = ['atm_background', 'atm_obs', 'bias_obs', 'background', 'background_ens', 'fv3jedi', 'obs', 'berror', 'gdas_fix', 'gdas_single_cycle'] @@ -275,7 +275,7 @@ def gdas_single_cycle(config, local_dict): obs_list_config = ufsda.yamltools.iter_config(config, obs_list_config) for ob in obs_list_config['observers']: - ob_config = parse_j2yaml(ob, local_dict) + ob_config = parse_yaml(ob, local_dict) # first get obs r2d2_config.pop('file_type', None) r2d2_config['type'] = 'ob' @@ -340,12 +340,11 @@ def obs(config): Stage observations using R2D2 based on input `config` dict """ - # create directory - obs_dir = os.path.join(config['DATA'], 'obs') - mkdir(obs_dir) for ob in config['observations']['observers']: obname = ob['obs space']['name'].lower() - outfile = ob['obs space']['obsdatain']['engine']['obsfile'] + outfile = os.path.join(config['r2d2_obs_out'], + os.path.basename(ob['obs space']['obsdatain']['engine']['obsfile'])) + # grab obs using R2D2 window_begin = config['window begin'] window_begin = parser.parse(window_begin, fuzzy=True)