From 380946ccd18892131e04af0c9bb12a080a9bc93e Mon Sep 17 00:00:00 2001 From: Travis Elless <113720457+TravisElless-NOAA@users.noreply.github.com> Date: Thu, 30 Jan 2025 16:02:02 -0500 Subject: [PATCH 1/4] Add esnowanl to enkfgfs cycle (#3283) This PR adds the capability for this task to run for the enkfgfs cycle, incorporating the rotating background directory structure used by other enkfgfs tasks. Resolves #3276 --------- Co-authored-by: Rahul Mahajan --- jobs/JGLOBAL_SNOWENS_ANALYSIS | 7 +++++++ parm/gdas/snow_stage_ens_update.yaml.j2 | 8 ++++++-- workflow/applications/gfs_cycled.py | 2 +- workflow/rocoto/gfs_tasks.py | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/jobs/JGLOBAL_SNOWENS_ANALYSIS b/jobs/JGLOBAL_SNOWENS_ANALYSIS index ca23347bca..9e532052a8 100755 --- a/jobs/JGLOBAL_SNOWENS_ANALYSIS +++ b/jobs/JGLOBAL_SNOWENS_ANALYSIS @@ -13,6 +13,13 @@ export GDUMP CDUMP=${RUN/enkf} export CDUMP +export NMEM_ENS_MAX=${NMEM_ENS} +if [[ "${RUN}" == "enkfgfs" ]]; then + NMEM_ENS=${NMEM_ENS_GFS} + export mem_offset=$((NMEM_ENS_GFS_OFFSET * cyc/6)) +else + export mem_offset=0 +fi ############################################## # Begin JOB SPECIFIC work ############################################## diff --git a/parm/gdas/snow_stage_ens_update.yaml.j2 b/parm/gdas/snow_stage_ens_update.yaml.j2 index d8b1d42d00..cae119ee74 100644 --- a/parm/gdas/snow_stage_ens_update.yaml.j2 +++ b/parm/gdas/snow_stage_ens_update.yaml.j2 @@ -22,13 +22,17 @@ copy: # copy ensemble background files ###################################### {% for mem in range(1, NMEM_ENS + 1) %} + {% set gmem = mem+mem_offset %} + {% if gmem > NMEM_ENS_MAX %} + {% set gmem = gmem-NMEM_ENS_MAX %} + {% endif %} # define variables # Declare a dict of search and replace terms to run on each template {% set tmpl_dict = {'${ROTDIR}':ROTDIR, - '${RUN}':RUN, + '${RUN}':"enkfgdas", '${YMD}':previous_cycle | to_YMD, '${HH}':previous_cycle | strftime("%H"), - '${MEMDIR}':"mem" + '%03d' % mem} %} + '${MEMDIR}':"mem" + '%03d' % gmem} %} # copy coupler file - ["{{ COM_ATMOS_RESTART_TMPL | replace_tmpl(tmpl_dict) }}/{{ current_cycle | to_fv3time }}.coupler.res", "{{ DATA }}/bkg/mem{{ '%03d' % mem }}/{{ current_cycle | to_fv3time }}.coupler.res"] diff --git a/workflow/applications/gfs_cycled.py b/workflow/applications/gfs_cycled.py index 7a2c812a0d..2bf793eafa 100644 --- a/workflow/applications/gfs_cycled.py +++ b/workflow/applications/gfs_cycled.py @@ -313,8 +313,8 @@ def get_task_names(self): task_names[run] += ['eobs', 'eupd'] task_names[run].append('echgres') if 'gdas' in run else 0 task_names[run] += ['ediag'] if options['lobsdiag_forenkf'] else ['eomg'] - task_names[run].append('esnowanl') if options['do_jedisnowda'] and 'gdas' in run else 0 + task_names[run].append('esnowanl') if options['do_jedisnowda'] else 0 task_names[run].append('efcs') if 'gdas' in run else 0 task_names[run].append('epos') if 'gdas' in run else 0 task_names[run] += ['stage_ic', 'ecen', 'esfc', 'earc', 'cleanup'] diff --git a/workflow/rocoto/gfs_tasks.py b/workflow/rocoto/gfs_tasks.py index 389d157df2..bce3036be7 100644 --- a/workflow/rocoto/gfs_tasks.py +++ b/workflow/rocoto/gfs_tasks.py @@ -619,7 +619,7 @@ def snowanl(self): def esnowanl(self): deps = [] - dep_dict = {'type': 'metatask', 'name': f'{self.run}_epmn', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} + dep_dict = {'type': 'metatask', 'name': 'enkfgdas_epmn', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} deps.append(rocoto.add_dependency(dep_dict)) dep_dict = {'type': 'task', 'name': f"{self.run.replace('enkf', '')}_prep"} deps.append(rocoto.add_dependency(dep_dict)) From 1939dac55932d86cf8bcbc7991456e47f23a2398 Mon Sep 17 00:00:00 2001 From: TerrenceMcGuinness-NOAA Date: Mon, 3 Feb 2025 11:58:33 -0500 Subject: [PATCH 2/4] CTests extended validation for C48_ATM and staged C48_S2SW for gfs_fcst and gfs_atmos (#3256) This PR extends the CTest Functional Tests: - Added `output_files` for **C48_ATM** for the validation step - Added two new JJOB Cases for **C48_S2SW** - gfs_fcts_seg0 - gfs_atmos_prod_f000-f003 --- ci/platforms/config.orion | 2 +- ctests/CMakeLists.txt | 14 +- ctests/README.md | 20 ++- ctests/cases/C48_ATM_gfs_fcst_seg0.yaml | 168 ++++++++++++++++-- .../C48_S2SW_gfs_atmos_prod_f000-f003.yaml | 136 ++++++++++++++ ctests/cases/C48_S2SW_gfs_fcst_seg0.yaml | 50 ++++++ ctests/scripts/execute.sh.in | 2 +- ctests/scripts/stage.py | 13 +- ctests/scripts/stage.sh.in | 4 +- ctests/scripts/validate.py | 120 +++++++++++++ ctests/scripts/validate.sh.in | 31 +++- 11 files changed, 530 insertions(+), 30 deletions(-) create mode 100644 ctests/cases/C48_S2SW_gfs_atmos_prod_f000-f003.yaml create mode 100644 ctests/cases/C48_S2SW_gfs_fcst_seg0.yaml create mode 100755 ctests/scripts/validate.py diff --git a/ci/platforms/config.orion b/ci/platforms/config.orion index 507068d4e7..dbaad7f3d1 100644 --- a/ci/platforms/config.orion +++ b/ci/platforms/config.orion @@ -2,7 +2,7 @@ export GFS_CI_ROOT=/work2/noaa/stmp/GFS_CI_ROOT/ORION export ICSDIR_ROOT=/work/noaa/global/glopara/data/ICSDIR -export STAGED_TESTS_DIR=${GFS_CI_ROOT}/STAGED_TESTS_DIR +export STAGED_TESTS_DIR=/work/noaa/stmp/GFS_CI_ROOT/ORION/STAGED_TESTS_DIR export HPC_ACCOUNT=nems export max_concurrent_cases=5 export max_concurrent_pr=4 diff --git a/ctests/CMakeLists.txt b/ctests/CMakeLists.txt index f8d928f456..19fcfcda75 100644 --- a/ctests/CMakeLists.txt +++ b/ctests/CMakeLists.txt @@ -94,7 +94,7 @@ function(AddJJOBTest) # TODO - This is a stub for the validation step add_test(NAME test_${TEST_NAME}_validate - COMMAND ./validate.sh ${TEST_NAME} ${CASE_YAML} + COMMAND ./validate.sh ${TEST_NAME} ${ARG_TEST_DATE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripts) set_tests_properties(test_${TEST_NAME}_validate PROPERTIES DEPENDS test_${TEST_NAME}_execute LABELS "${ARG_CASE};${ARG_JOB}") endfunction() @@ -104,3 +104,15 @@ AddJJOBTest( JOB "gfs_fcst_seg0" TEST_DATE "2021032312" ) + +AddJJOBTest( + CASE "C48_S2SW" + JOB "gfs_fcst_seg0" + TEST_DATE "2021032312" +) + +AddJJOBTest( + CASE "C48_S2SW" + JOB "gfs_atmos_prod_f000-f003" + TEST_DATE "2021032312" +) diff --git a/ctests/README.md b/ctests/README.md index 95a32cd952..d19b7d0196 100644 --- a/ctests/README.md +++ b/ctests/README.md @@ -8,25 +8,33 @@ The CTest framework consists of the following scripts: - **setup.sh.in**: Prepares the environment and creates the experiment. - **stage.sh.in**: Stages the input files needed to run a JJOB. - **execute.sh.in**: Executes the JJOB and monitors its status. -- **validate.sh.in**: (TODO) Validates the results of the JJOB. +- **validate.sh.in**: Validates the results of the JJOB. + +**NOTE:** So far only test C48_ATM *gfs_fcst_set0* has `output_files` for the validation step using a basic chksum for testing. Further development using grib and NETCDF comparison tools is pending. ## Usage ### CMake Configuration -To configure the CTest framework using CMake, you need to provide several environment variables or default values. Here is an example of how to configure and build the project: +To configure the **CTest** framework using **CMake**, you need to provide several environment variables. Here is an example of how to configure and build the project: ```bash # Set environment variables (may also be include at command line with -D) export HPC_ACCOUNT="your_hpc_account" export ICSDIR_ROOT="/path/to/icsdir_root" export STAGED_TESTS_DIR="/path/to/staged_tests_dir" +``` +**NOTE**: The the specific values for these three enviroment variables can be found in `$HOMEgfs/ci/platforms/config.$MACHINE_ID` and may also be added to the `cmake` command line with the `-D` option # Run CMake to configure the ctest framework -cmake -S /path/to/HOMEgfs -B /path/to/build -DRUNTESTS=/path/to/runtests - +```shell +cd $HOMEgfs/ctests +mkdir build +cd build +cmake ../.. ``` + ### Running Tests with CTest Once the project is configured, you can run the tests using CTest. Here are some examples: @@ -46,6 +54,10 @@ You can use the `-L` option with CTest to run tests for a specific case. For exa cd /path/to/build ctest -L C48_ATM ``` +Or simply use the '-R' switch to run any individual test: +``` +ctest -R test_C48_S2SW_gfs_fcst_seg0_execute -V +``` To add a new test use the **AddJJOBTest()** function at the end of the `$HOMEgfs/ctest/CMakeLists.txt` file as follows: ```cmake diff --git a/ctests/cases/C48_ATM_gfs_fcst_seg0.yaml b/ctests/cases/C48_ATM_gfs_fcst_seg0.yaml index ec0ce88ff1..6d7f746bcb 100644 --- a/ctests/cases/C48_ATM_gfs_fcst_seg0.yaml +++ b/ctests/cases/C48_ATM_gfs_fcst_seg0.yaml @@ -1,17 +1,157 @@ +{% set H_offset = "-6H" %} +{% set H_timedelta = H_offset | to_timedelta %} +{% set TEST_DATE_offset = TEST_DATE | add_to_datetime(H_timedelta) %} + +{% set cyc = TEST_DATE | strftime('%H') %} +{% set cyc_offset = TEST_DATE_offset | strftime('%H') %} + +{% set PDY = TEST_DATE | to_YMD %} +{% set PDY_offset = TEST_DATE_offset | to_YMD %} + input_files: mkdir: - - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input" + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input" copy: - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/gfs_ctrl.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/gfs_ctrl.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/gfs_data.tile1.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/gfs_data.tile1.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/gfs_data.tile2.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/gfs_data.tile2.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/gfs_data.tile3.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/gfs_data.tile3.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/gfs_data.tile4.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/gfs_data.tile4.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/gfs_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/gfs_data.tile5.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/gfs_data.tile6.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/gfs_data.tile6.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/sfc_data.tile1.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/sfc_data.tile1.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/sfc_data.tile2.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/sfc_data.tile2.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/sfc_data.tile3.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/sfc_data.tile3.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/sfc_data.tile4.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/sfc_data.tile4.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/sfc_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/sfc_data.tile5.nc"] - - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ TEST_DATE | to_YMD }}/{{ TEST_DATE | strftime('%H') }}/model/atmos/input/sfc_data.tile6.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{TEST_DATE | to_YMD}}/{{TEST_DATE | strftime('%H')}}/model/atmos/input/sfc_data.tile6.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_ctrl.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_ctrl.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile1.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile1.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile2.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile2.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile3.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile3.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile4.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile4.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile5.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile6.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile6.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile1.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile1.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile2.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile2.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile3.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile3.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile4.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile4.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile6.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile6.nc"] + +output_files: + cmpfiles: + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.diag_table", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.diag_table"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.input.nml", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.input.nml"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.model_configure", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.model_configure"] + + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf000.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf000.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf003.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf003.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf006.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf006.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf009.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf009.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf012.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf012.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf015.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf015.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf018.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf018.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf021.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf021.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf024.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf024.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf027.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf027.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf030.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf030.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf033.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf033.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf036.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf036.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf039.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf039.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf042.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf042.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf045.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf045.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf048.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf048.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf051.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf051.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf054.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf054.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf057.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf057.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf060.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf060.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf063.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf063.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf066.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf066.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf069.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf069.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf072.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf072.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf075.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf075.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf078.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf078.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf081.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf081.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf084.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf084.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf087.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf087.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf090.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf090.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf093.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf093.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf096.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf096.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf099.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf099.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf102.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf102.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf105.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf105.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf108.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf108.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf111.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf111.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf114.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf114.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf117.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf117.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf120.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/history/gfs.t12z.atmf120.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f000", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f000"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f003", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f003"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f006", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f006"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f009", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f009"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f012", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f012"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f015", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f015"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f018", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f018"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f021", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f021"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f024", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f024"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f027", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f027"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f030", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f030"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f033", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f033"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f036", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f036"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f039", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f039"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f042", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f042"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f045", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f045"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f048", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f048"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f051", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f051"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f054", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f054"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f057", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f057"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f060", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f060"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f063", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f063"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f066", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f066"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f069", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f069"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f072", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f072"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f075", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f075"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f078", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f078"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f081", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f081"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f084", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f084"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f087", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f087"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f090", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f090"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f093", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f093"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f096", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f096"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f099", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f099"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f102", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f102"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f105", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f105"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f108", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f108"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f111", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f111"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f114", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f114"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f117", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f117"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f120", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.master.grb2f120"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf000.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf000.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf003.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf003.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf006.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf006.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf009.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf009.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf012.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf012.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf015.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf015.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf018.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf018.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf021.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf021.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf024.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf024.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf027.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf027.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf030.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf030.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf033.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf033.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf036.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf036.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf039.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf039.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf042.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf042.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf045.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf045.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf048.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf048.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf051.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf051.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf054.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf054.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf057.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf057.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf060.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf060.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf063.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf063.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf066.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf066.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf069.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf069.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf072.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf072.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf075.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf075.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf078.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf078.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf081.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf081.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf084.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf084.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf087.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf087.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf090.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf090.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf093.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf093.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf096.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf096.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf099.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf099.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf102.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf102.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf105.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf105.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf108.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf108.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf111.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf111.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf114.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf114.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf117.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf117.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf120.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t12z.sfluxgrbf120.grib2"] diff --git a/ctests/cases/C48_S2SW_gfs_atmos_prod_f000-f003.yaml b/ctests/cases/C48_S2SW_gfs_atmos_prod_f000-f003.yaml new file mode 100644 index 0000000000..80555e4e16 --- /dev/null +++ b/ctests/cases/C48_S2SW_gfs_atmos_prod_f000-f003.yaml @@ -0,0 +1,136 @@ +{% set H_offset = "-6H" %} +{% set H_timedelta = H_offset | to_timedelta %} +{% set TEST_DATE_offset = TEST_DATE | add_to_datetime(H_timedelta) %} + +{% set cyc = TEST_DATE | strftime('%H') %} +{% set cyc_offset = TEST_DATE_offset | strftime('%H') %} + +{% set PDY = TEST_DATE | to_YMD %} +{% set PDY_offset = TEST_DATE_offset | to_YMD %} + +input_files: + mkdir: + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input" + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master" + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep" + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gdas.{{ PDY }}/{{ cyc_offset }}/model/ocean/restart" + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gdas.{{ PDY }}/{{ cyc_offset }}/model/ice/restart" + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gdas.{{ PDY }}/{{ cyc_offset }}/model/ice/restart" + copy: + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_ctrl.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_ctrl.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile1.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile1.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile2.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile2.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile3.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile3.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile4.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile4.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile5.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile6.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile6.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile1.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile1.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile2.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile2.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile3.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile3.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile4.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile4.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile6.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile6.nc"] + + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf000.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf000.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf003.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf003.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf006.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf006.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf009.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf009.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf012.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf012.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf015.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf015.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf018.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf018.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf021.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf021.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf024.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf024.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf027.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf027.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf030.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf030.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf033.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf033.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf036.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf036.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf039.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf039.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf042.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf042.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf045.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf045.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf048.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf048.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf051.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf051.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf054.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf054.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf057.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf057.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf060.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf060.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf063.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf063.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf066.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf066.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf069.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf069.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf072.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf072.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf075.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf075.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf078.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf078.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf081.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf081.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf084.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf084.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf087.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf087.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf090.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf090.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf093.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf093.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf096.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf096.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf099.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf099.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf102.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf102.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf105.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf105.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf108.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf108.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf111.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf111.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf114.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf114.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf117.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf117.grib2"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf120.grib2", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.sfluxgrbf120.grib2"] + + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f000", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f000"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f003", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f003"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f006", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f006"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f009", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f009"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f012", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f012"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f015", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f015"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f018", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f018"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f021", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f021"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f024", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f024"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f027", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f027"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f030", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f030"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f033", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f033"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f036", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f036"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f039", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f039"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f042", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f042"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f045", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f045"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f048", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f048"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f051", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f051"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f054", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f054"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f057", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f057"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f060", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f060"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f063", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f063"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f066", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f066"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f069", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f069"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f072", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f072"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f075", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f075"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f078", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f078"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f081", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f081"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f084", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f084"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f084", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f087"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f090", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f090"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f093", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f093"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f096", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f096"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f099", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f099"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f102", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f102"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f105", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f105"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f108", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f108"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f111", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f111"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f114", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f114"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f117", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f117"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f120", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/master/gfs.t{{ cyc }}z.master.grb2f120"] + + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep/gfswave.mod_def.glo_200", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep/gfswave.mod_def.glo_200"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep/gfswave.mod_def.uglo_100km", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep/gfswave.mod_def.uglo_100km"] + + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gdas.{{ PDY_offset }}/{{ cyc_offset }}/model/ocean/restart/{{ TEST_DATE | strftime('%Y%m%d.%H0000') }}.MOM.res.nc", + "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gdas.{{ PDY_offset }}/{{ cyc_offset }}/model/ocean/restart/{{ TEST_DATE | strftime('%Y%m%d.%H0000') }}.MOM.res.nc" ] + + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gdas.{{ PDY_offset }}/{{ cyc_offset }}/model/ice/restart/{{ TEST_DATE | strftime('%Y%m%d.%H0000') }}.cice_model.res.nc", + "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gdas.{{ PDY_offset }}/{{ cyc_offset }}/model/ice/restart/{{ TEST_DATE | strftime('%Y%m%d.%H0000') }}.cice_model.res.nc" ] + +# TODO - To enable the validation step include specific files to compare against the results from running the test. +# Note: The below three files is only an example. The cmpfiles tag means it will use checksum to compare the files in the two locations. +# Other extentions can be added and/or folded into the FileUtils class in wxflow FileUtilities.py +# +#output_files: +# cmpfiles: +# - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.diag_table", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.diag_table"] +# - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.input.nml", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.input.nml"] +# - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.model_configure", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.model_configure"] diff --git a/ctests/cases/C48_S2SW_gfs_fcst_seg0.yaml b/ctests/cases/C48_S2SW_gfs_fcst_seg0.yaml new file mode 100644 index 0000000000..f7117363a4 --- /dev/null +++ b/ctests/cases/C48_S2SW_gfs_fcst_seg0.yaml @@ -0,0 +1,50 @@ +{% set H_offset = "-6H" %} +{% set H_timedelta = H_offset | to_timedelta %} +{% set TEST_DATE_offset = TEST_DATE | add_to_datetime(H_timedelta) %} + +{% set cyc = TEST_DATE | strftime('%H') %} +{% set cyc_offset = TEST_DATE_offset | strftime('%H') %} + +{% set PDY = TEST_DATE | to_YMD %} +{% set PDY_offset = TEST_DATE_offset | to_YMD %} + +input_files: + mkdir: + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input" + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep" + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gdas.{{ PDY }}/{{cyc_offset}}/model/ocean/restart" + - "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gdas.{{ PDY }}/{{cyc_offset}}/model/ice/restart" + copy: + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_ctrl.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_ctrl.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile1.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile1.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile2.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile2.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile3.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile3.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile4.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile4.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile5.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile6.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_data.tile6.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile1.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile1.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile2.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile2.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile3.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile3.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile4.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile4.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile5.nc"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile6.nc", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/sfc_data.tile6.nc"] + + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep/gfswave.mod_def.glo_200", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep/gfswave.mod_def.glo_200"] + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep/gfswave.mod_def.uglo_100km", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/model/wave/prep/gfswave.mod_def.uglo_100km"] + + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gdas.{{ PDY_offset }}/{{ cyc_offset }}/model/ocean/restart/{{ TEST_DATE | strftime('%Y%m%d.%H0000') }}.MOM.res.nc", + "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gdas.{{ PDY_offset }}/{{ cyc_offset }}/model/ocean/restart/{{ TEST_DATE | strftime('%Y%m%d.%H0000') }}.MOM.res.nc" ] + + - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/input_files/gdas.{{ PDY_offset }}/{{ cyc_offset }}/model/ice/restart/{{ TEST_DATE | strftime('%Y%m%d.%H0000') }}.cice_model.res.nc", + "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gdas.{{ PDY_offset }}/{{ cyc_offset }}/model/ice/restart/{{ TEST_DATE | strftime('%Y%m%d.%H0000') }}.cice_model.res.nc" ] + +# TODO - To enable the validation step include specific files to compare against the results from running the test. +# Note: The below three files is only an example. The cmpfiles tag means it will use checksum to compare the files in the two locations. +# Other extensions can be added and/or folded into the FileUtils class in wxflow FileUtilities.py +# +#output_files: +# cmpfiles: +# - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.diag_table", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.diag_table"] +# - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.input.nml", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.input.nml"] +# - ["{{ 'STAGED_TESTS_DIR' | getenv }}/{{ 'TEST_NAME' | getenv }}/output_files/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.model_configure", "{{ 'RUNTESTS' | getenv }}/COMROOT/{{ 'TEST_NAME' | getenv }}/gfs.{{ PDY }}/{{ cyc }}/conf/ufs.model_configure"] diff --git a/ctests/scripts/execute.sh.in b/ctests/scripts/execute.sh.in index 9cf3ef5917..52ae03a43a 100755 --- a/ctests/scripts/execute.sh.in +++ b/ctests/scripts/execute.sh.in @@ -8,7 +8,7 @@ JOB=${2:?"Job name is required"} idate=$3 #TODO - add rocotoboot_dryrun to repo some how -rocotoboot_dryrun=/work2/noaa/global/mterry/rocoto_dryrun/bin/rocotoboot +rocotoboot_dryrun=$(command -v rocotoboot_dryrun) || true CASEDIR="@CMAKE_CURRENT_BINARY_DIR@/RUNTESTS/EXPDIR/${TEST_NAME}" cd "${CASEDIR}" rm -f ./*.db diff --git a/ctests/scripts/stage.py b/ctests/scripts/stage.py index b8a77a120d..ea4009a495 100755 --- a/ctests/scripts/stage.py +++ b/ctests/scripts/stage.py @@ -24,7 +24,7 @@ from argparse import ArgumentParser from pathlib import Path -from wxflow import parse_j2yaml, FileHandler, Logger +from wxflow import parse_j2yaml, FileHandler, Logger, logit, to_datetime # Initialize logger with environment variable for logging level logger = Logger(level=os.environ.get("LOGGING_LEVEL", "DEBUG"), colored_log=False) @@ -52,16 +52,19 @@ def parse_args(): return parser.parse_args() -if __name__ == '__main__': - - # Parse command line arguments +@logit(logger) +def main(): args = parse_args() data = {} if args.test_date: # Parse test date from string to datetime object - data['TEST_DATE'] = datetime.datetime.strptime(args.test_date, '%Y%m%d%H') + data['TEST_DATE'] = to_datetime(args.test_date) # Parse YAML configuration file with optional data case_cfg = parse_j2yaml(path=args.yaml, data=data) # Synchronize input files as per the parsed configuration FileHandler(case_cfg.input_files).sync() + + +if __name__ == '__main__': + main() diff --git a/ctests/scripts/stage.sh.in b/ctests/scripts/stage.sh.in index 9ced3d8f4e..ca1297b302 100755 --- a/ctests/scripts/stage.sh.in +++ b/ctests/scripts/stage.sh.in @@ -19,12 +19,12 @@ set -x PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${HOMEgfs}/sorc/wxflow/src" export PYTHONPATH -INPUTS_YAML="${HOMEgfs}/ctests/cases/${TEST_NAME}.yaml" +YAML_FILE="${HOMEgfs}/ctests/cases/${TEST_NAME}.yaml" TEST_NAME="${TEST_NAME}" \ RUNTESTS="${RUNTESTS}" \ STAGED_TESTS_DIR="${STAGED_TESTS_DIR}" \ -"${HOMEgfs}/ctests/scripts/stage.py" --yaml "${INPUTS_YAML}" --test_date "${TEST_DATE}" +"${HOMEgfs}/ctests/scripts/stage.py" --yaml "${YAML_FILE}" --test_date "${TEST_DATE}" rc=$? if [[ "${rc}" -ne 0 ]]; then set +x diff --git a/ctests/scripts/validate.py b/ctests/scripts/validate.py new file mode 100755 index 0000000000..0ae82a144b --- /dev/null +++ b/ctests/scripts/validate.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +""" +validate.py + +Validation script that checks file checksums and verifies test outputs. + +Usage +----- +validate.py --yaml --test_date + +Parameters +---------- +--yaml : str + Path to the YAML configuration file. +--test_date : str + Test date in the format YYYYMMDDHH. + +""" + +import sys +import argparse +from pathlib import Path +import hashlib +from wxflow import parse_j2yaml, Logger, logit, to_datetime + +logger = Logger(level="DEBUG", colored_log=True) + + +def parse_args(): + """ + parse_args + Parses command line arguments. + + Returns + ------- + argparse.Namespace + Parsed command line arguments. + """ + parser = argparse.ArgumentParser() + parser.add_argument("--yaml", required=True) + parser.add_argument("--test_date", required=True) + return parser.parse_args() + + +def file_checksum(path): + """ + file_checksum + Computes the MD5 checksum of a file. + + Parameters + ---------- + path : str + Path to the file. + + Returns + ------- + str + MD5 checksum of the file. + """ + hasher = hashlib.md5() + with open(path, "rb") as f: + for chunk in iter(lambda: f.read(4096), b""): + hasher.update(chunk) + return hasher.hexdigest() + + +def validate_cmpfiles(config): + """ + validate_cmpfiles + Validates that the checksums of paired files match. + + Parameters + ---------- + config : dict + Configuration dictionary containing file pairs to compare. + + Raises + ------ + ValueError + If the checksums of any paired files do not match. + """ + cmpfiles = config.get("output_files", {}).get("cmpfiles", []) + for pair in cmpfiles: + file_a, file_b = pair + if file_checksum(file_a) != file_checksum(file_b): + logger.error(f"Checksum mismatch: {file_a} vs {file_b}") + raise ValueError(f"Checksum mismatch: {file_a} vs {file_b}") + logger.info(f"checksums match: {file_a} vs {file_b}") + + +@logit(logger) +def main(): + """ + main + Main function that parses arguments, reads configuration, and validates file checksums. + + Raises + ------ + SystemExit + If no output files are found in the configuration. + """ + args = parse_args() + + data = {} + if args.test_date: + # Parse test date from string to datetime object + data['TEST_DATE'] = to_datetime(args.test_date) + + files = parse_j2yaml(path=args.yaml, data=data) + if 'output_files' not in files: + logger.info(f"No output files found for test: {args.yaml}") + logger.info("Nothing to validate (TODO - Stubbed).") + sys.exit(0) + + validate_cmpfiles(files) + logger.info(f"All files exist and pass checksum for test: {args.yaml}") + + +if __name__ == "__main__": + main() diff --git a/ctests/scripts/validate.sh.in b/ctests/scripts/validate.sh.in index 0277699956..c387098ecd 100755 --- a/ctests/scripts/validate.sh.in +++ b/ctests/scripts/validate.sh.in @@ -2,8 +2,35 @@ set -ux TEST_NAME=${1:?"Name of the test is required"} -YAML_FILE=${2:?"Name of the CI yaml file for validating the test"} +TEST_DATE=${2:?"idate of the test is required"} +# CMake to fill these variables +STAGED_TESTS_DIR="@STAGED_TESTS_DIR@" +RUNTESTS="@RUNTESTS@" +HOMEgfs="@PROJECT_SOURCE_DIR@" + +# Load the runtime environment for this script (needs wxflow and its dependencies) +set +x +source "${HOMEgfs}/workflow/gw_setup.sh" +rc=$? +[[ "${rc}" -ne 0 ]] && exit "${status}" +set -x +PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${HOMEgfs}/sorc/wxflow/src" +export PYTHONPATH + +YAML_FILE="${HOMEgfs}/ctests/cases/${TEST_NAME}.yaml" echo "validating '${TEST_NAME}' with yaml file '${YAML_FILE}'" + +TEST_NAME="${TEST_NAME}" \ +RUNTESTS="${RUNTESTS}" \ +STAGED_TESTS_DIR="${STAGED_TESTS_DIR}" \ +"${HOMEgfs}/ctests/scripts/validate.py" --yaml "${YAML_FILE}" --test_date "${TEST_DATE}" +rc=$? +if [[ "${rc}" -ne 0 ]]; then + set +x + echo "Failed to validate for '${TEST_NAME}' with '${YAML_FILE}'" + set -x + exit "${rc}" +fi -exit 0 \ No newline at end of file +exit 0 From c9011aba3933962bf2a1aa7a42f0bcebceac6256 Mon Sep 17 00:00:00 2001 From: AntonMFernando-NOAA <167725623+AntonMFernando-NOAA@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:36:50 -0500 Subject: [PATCH 3/4] Splitting up the archive task (#3242) In this PR the archive task will be split into two parts. The first will always run and will just be for the copying of verification data to the `VRFY_ARC` and `ARCDIR` directories. The second will only run when `HPSSARCH` or `LOCALARCH` is set to YES and will generate and store tarballs in the `ATARDIR`, either on `HPSS` or locally. Resolves #3152 --- .github/CODEOWNERS | 3 +- docs/source/jobs.rst | 6 +- ...S_ENKF_ARCHIVE => JGDAS_ENKF_ARCHIVE_TARS} | 4 +- jobs/JGDAS_ENKF_ARCHIVE_VRFY | 43 ++++++ .../{JGLOBAL_ARCHIVE => JGLOBAL_ARCHIVE_TARS} | 79 +++++----- jobs/JGLOBAL_ARCHIVE_VRFY | 50 +++++++ jobs/rocoto/{arch.sh => arch_tars.sh} | 4 +- jobs/rocoto/arch_vrfy.sh | 24 ++++ jobs/rocoto/{earc.sh => earc_tars.sh} | 4 +- jobs/rocoto/earc_vrfy.sh | 24 ++++ parm/archive/gfsa.yaml.j2 | 2 +- .../gefs/{config.arch => config.arch_tars} | 8 +- .../config.arch => gefs/config.arch_vrfy} | 8 +- parm/config/gefs/config.base | 7 +- parm/config/gefs/config.resources | 10 +- parm/config/gefs/config.resources.AWSPW | 2 +- parm/config/gfs/config.arch_tars | 15 ++ parm/config/gfs/config.arch_vrfy | 15 ++ parm/config/gfs/config.base | 6 +- .../gfs/{config.earc => config.earc_tars} | 10 +- parm/config/gfs/config.earc_vrfy | 15 ++ parm/config/gfs/config.resources | 14 +- parm/config/gfs/config.resources.AWSPW | 2 +- parm/config/gfs/config.resources.WCOSS2 | 2 +- ..._enkf_earc.py => exgdas_enkf_earc_tars.py} | 5 +- scripts/exgdas_enkf_earc_vrfy.py | 51 +++++++ ...al_archive.py => exglobal_archive_tars.py} | 7 +- scripts/exglobal_archive_vrfy.py | 58 ++++++++ ush/python/pygfs/task/archive.py | 51 +++++-- workflow/applications/applications.py | 1 + workflow/applications/gefs.py | 12 +- workflow/applications/gfs_cycled.py | 24 +++- workflow/applications/gfs_forecast_only.py | 11 +- workflow/rocoto/gefs_tasks.py | 59 +++++++- workflow/rocoto/gfs_tasks.py | 136 +++++++++++++++--- workflow/rocoto/tasks.py | 6 +- 36 files changed, 655 insertions(+), 123 deletions(-) rename jobs/{JGDAS_ENKF_ARCHIVE => JGDAS_ENKF_ARCHIVE_TARS} (91%) create mode 100755 jobs/JGDAS_ENKF_ARCHIVE_VRFY rename jobs/{JGLOBAL_ARCHIVE => JGLOBAL_ARCHIVE_TARS} (51%) create mode 100755 jobs/JGLOBAL_ARCHIVE_VRFY rename jobs/rocoto/{arch.sh => arch_tars.sh} (90%) create mode 100755 jobs/rocoto/arch_vrfy.sh rename jobs/rocoto/{earc.sh => earc_tars.sh} (90%) create mode 100755 jobs/rocoto/earc_vrfy.sh rename parm/config/gefs/{config.arch => config.arch_tars} (56%) rename parm/config/{gfs/config.arch => gefs/config.arch_vrfy} (56%) create mode 100644 parm/config/gfs/config.arch_tars create mode 100644 parm/config/gfs/config.arch_vrfy rename parm/config/gfs/{config.earc => config.earc_tars} (72%) create mode 100644 parm/config/gfs/config.earc_vrfy rename scripts/{exgdas_enkf_earc.py => exgdas_enkf_earc_tars.py} (92%) create mode 100755 scripts/exgdas_enkf_earc_vrfy.py rename scripts/{exglobal_archive.py => exglobal_archive_tars.py} (92%) create mode 100755 scripts/exglobal_archive_vrfy.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b0b51922c5..81e387d361 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -76,7 +76,8 @@ scripts/exgdas_atmos_gempak_gif_ncdc.sh @GwenChen-NOAA scripts/exgdas_atmos_nawips.sh @GwenChen-NOAA scripts/exgdas_atmos_verfozn.sh @EdwardSafford-NOAA scripts/exgdas_atmos_verfrad.sh @EdwardSafford-NOAA -scripts/exgdas_enkf_earc.py @DavidHuber-NOAA +scripts/exgdas_enkf_earc_vrfy.py @DavidHuber-NOAA +scripts/exgdas_enkf_earc_tars.py @DavidHuber-NOAA scripts/exgdas_enkf_ecen.sh @CoryMartin-NOAA @RussTreadon-NOAA @CatherineThomas-NOAA scripts/exgdas_enkf_post.sh @CoryMartin-NOAA @RussTreadon-NOAA @CatherineThomas-NOAA scripts/exgdas_enkf_select_obs.sh @CoryMartin-NOAA @RussTreadon-NOAA @CatherineThomas-NOAA diff --git a/docs/source/jobs.rst b/docs/source/jobs.rst index 2cdecb01de..c5f45b9659 100644 --- a/docs/source/jobs.rst +++ b/docs/source/jobs.rst @@ -18,7 +18,7 @@ An experimental run is different from operations in the following ways: * Addition steps in experimental mode: - - archive (arch) + - archive (arch_vrfy & arch_tars) - cleanup (cleanup) @@ -39,7 +39,9 @@ Jobs in the GFS Configuration | analdiag | Creates netCDF diagnostic files containing observation values, innovation (O-F), error, quality control, as well as | | | other analysis-related quantities (cnvstat, radstat, ozstat files). | +-------------------+-----------------------------------------------------------------------------------------------------------------------+ -| arch | Archives select files from the deterministic model and cleans up older data. | +|arch_tars | Optional archive job that backs up the COM data structure. | ++-------------------+-----------------------------------------------------------------------------------------------------------------------+ +|arch_vrfy | Archives select files from the deterministic model and cleans up older data. | +-------------------+-----------------------------------------------------------------------------------------------------------------------+ | earcN/eamn | Archival script for EnKF: 1) Write select EnKF output to HPSS; 2) Copy select files to online archive; 3) Clean up | | | EnKF temporary run directories; 4) Remove "old" EnKF files from rotating directory. | diff --git a/jobs/JGDAS_ENKF_ARCHIVE b/jobs/JGDAS_ENKF_ARCHIVE_TARS similarity index 91% rename from jobs/JGDAS_ENKF_ARCHIVE rename to jobs/JGDAS_ENKF_ARCHIVE_TARS index 021c454afc..04fe8e3141 100755 --- a/jobs/JGDAS_ENKF_ARCHIVE +++ b/jobs/JGDAS_ENKF_ARCHIVE_TARS @@ -1,7 +1,7 @@ #! /usr/bin/env bash source "${HOMEgfs}/ush/preamble.sh" -source "${HOMEgfs}/ush/jjob_header.sh" -e "earc" -c "base earc" +source "${HOMEgfs}/ush/jjob_header.sh" -e "earc_tars" -c "base earc_tars" ############################################## @@ -17,7 +17,7 @@ MEMDIR="ensstat" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ # Run archive script ############################################################### -"${SCRgfs}/exgdas_enkf_earc.py" +"${SCRgfs}/exgdas_enkf_earc_tars.py" status=$? [[ ${status} -ne 0 ]] && exit "${status}" diff --git a/jobs/JGDAS_ENKF_ARCHIVE_VRFY b/jobs/JGDAS_ENKF_ARCHIVE_VRFY new file mode 100755 index 0000000000..0094401987 --- /dev/null +++ b/jobs/JGDAS_ENKF_ARCHIVE_VRFY @@ -0,0 +1,43 @@ +#! /usr/bin/env bash + +source "${HOMEgfs}/ush/preamble.sh" +source "${HOMEgfs}/ush/jjob_header.sh" -e "earc_vrfy" -c "base earc_vrfy" + + +############################################## +# Set variables used in the script +############################################## +YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COM_TOP +MEMDIR="ensstat" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMIN_ATMOS_ANALYSIS_ENSSTAT:COM_ATMOS_ANALYSIS_TMPL \ + COMIN_ATMOS_HISTORY_ENSSTAT:COM_ATMOS_HISTORY_TMPL \ + COMIN_SNOW_ANALYSIS_ENSSTAT:COM_SNOW_ANALYSIS_TMPL + +############################################################### +# Run archive script +############################################################### + +"${SCRgfs}/exgdas_enkf_earc_vrfy.py" +status=$? +[[ ${status} -ne 0 ]] && exit "${status}" + +############################################################### + +############################################## +# End JOB SPECIFIC work +############################################## + +############################################## +# Final processing +############################################## +if [[ -e "${pgmout}" ]] ; then + cat "${pgmout}" +fi + +########################################## +# Remove the Temporary working directory +########################################## +cd "${DATAROOT}" || (echo "${DATAROOT} does not exist. ABORT!"; exit 1) +[[ ${KEEPDATA} = "NO" ]] && rm -rf "${DATA}" + +exit 0 diff --git a/jobs/JGLOBAL_ARCHIVE b/jobs/JGLOBAL_ARCHIVE_TARS similarity index 51% rename from jobs/JGLOBAL_ARCHIVE rename to jobs/JGLOBAL_ARCHIVE_TARS index f62386cdd9..e89370bd37 100755 --- a/jobs/JGLOBAL_ARCHIVE +++ b/jobs/JGLOBAL_ARCHIVE_TARS @@ -1,48 +1,49 @@ #! /usr/bin/env bash source "${HOMEgfs}/ush/preamble.sh" -source "${HOMEgfs}/ush/jjob_header.sh" -e "arch" -c "base arch wave" -source "${USHgfs}/wave_domain_grid.sh" +source "${HOMEgfs}/ush/jjob_header.sh" -e "arch_tars" -c "base arch_tars wave" +source "${USHgfs}/wave_domain_grid.sh" + ############################################## # Set variables used in the script ############################################## YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ - COMIN_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \ - COMIN_ATMOS_BUFR:COM_ATMOS_BUFR_TMPL \ - COMIN_ATMOS_GEMPAK:COM_ATMOS_GEMPAK_TMPL \ - COMIN_ATMOS_GENESIS:COM_ATMOS_GENESIS_TMPL \ - COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL \ - COMIN_ATMOS_INPUT:COM_ATMOS_INPUT_TMPL \ - COMIN_ATMOS_MASTER:COM_ATMOS_MASTER_TMPL \ - COMIN_ATMOS_RESTART:COM_ATMOS_RESTART_TMPL \ - COMIN_ATMOS_TRACK:COM_ATMOS_TRACK_TMPL \ - COMIN_ATMOS_WMO:COM_ATMOS_WMO_TMPL \ - COMIN_CHEM_HISTORY:COM_CHEM_HISTORY_TMPL \ - COMIN_CHEM_ANALYSIS:COM_CHEM_ANALYSIS_TMPL \ - COMIN_MED_RESTART:COM_MED_RESTART_TMPL \ - COMIN_SNOW_ANALYSIS:COM_SNOW_ANALYSIS_TMPL \ - COMIN_ICE_HISTORY:COM_ICE_HISTORY_TMPL \ - COMIN_ICE_INPUT:COM_ICE_INPUT_TMPL \ - COMIN_ICE_RESTART:COM_ICE_RESTART_TMPL \ - COMIN_ICE_GRIB:COM_ICE_GRIB_TMPL \ - COMIN_OBS:COM_OBS_TMPL \ - COMIN_TOP:COM_TOP_TMPL \ - COMIN_OCEAN_HISTORY:COM_OCEAN_HISTORY_TMPL \ - COMIN_OCEAN_RESTART:COM_OCEAN_RESTART_TMPL \ - COMIN_OCEAN_GRIB:COM_OCEAN_GRIB_TMPL \ - COMIN_OCEAN_NETCDF:COM_OCEAN_NETCDF_TMPL \ - COMIN_OCEAN_ANALYSIS:COM_OCEAN_ANALYSIS_TMPL \ - COMIN_OCEAN_BMATRIX:COM_OCEAN_BMATRIX_TMPL \ - COMIN_ICE_BMATRIX:COM_ICE_BMATRIX_TMPL \ - COMIN_WAVE_GRID:COM_WAVE_GRID_TMPL \ - COMIN_WAVE_HISTORY:COM_WAVE_HISTORY_TMPL \ - COMIN_WAVE_STATION:COM_WAVE_STATION_TMPL \ - COMIN_WAVE_RESTART:COM_WAVE_RESTART_TMPL \ - COMIN_ATMOS_OZNMON:COM_ATMOS_OZNMON_TMPL \ - COMIN_ATMOS_RADMON:COM_ATMOS_RADMON_TMPL \ - COMIN_ATMOS_MINMON:COM_ATMOS_MINMON_TMPL \ - COMIN_CONF:COM_CONF_TMPL \ - COMOUT_ATMOS_TRACK:COM_ATMOS_TRACK_TMPL + COMIN_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \ + COMIN_ATMOS_BUFR:COM_ATMOS_BUFR_TMPL \ + COMIN_ATMOS_GEMPAK:COM_ATMOS_GEMPAK_TMPL \ + COMIN_ATMOS_GENESIS:COM_ATMOS_GENESIS_TMPL \ + COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL \ + COMIN_ATMOS_INPUT:COM_ATMOS_INPUT_TMPL \ + COMIN_ATMOS_MASTER:COM_ATMOS_MASTER_TMPL \ + COMIN_ATMOS_RESTART:COM_ATMOS_RESTART_TMPL \ + COMIN_ATMOS_TRACK:COM_ATMOS_TRACK_TMPL \ + COMIN_ATMOS_WMO:COM_ATMOS_WMO_TMPL \ + COMIN_CHEM_HISTORY:COM_CHEM_HISTORY_TMPL \ + COMIN_CHEM_ANALYSIS:COM_CHEM_ANALYSIS_TMPL \ + COMIN_MED_RESTART:COM_MED_RESTART_TMPL \ + COMIN_SNOW_ANALYSIS:COM_SNOW_ANALYSIS_TMPL \ + COMIN_ICE_HISTORY:COM_ICE_HISTORY_TMPL \ + COMIN_ICE_INPUT:COM_ICE_INPUT_TMPL \ + COMIN_ICE_RESTART:COM_ICE_RESTART_TMPL \ + COMIN_ICE_GRIB:COM_ICE_GRIB_TMPL \ + COMIN_OBS:COM_OBS_TMPL \ + COMIN_TOP:COM_TOP_TMPL \ + COMIN_OCEAN_HISTORY:COM_OCEAN_HISTORY_TMPL \ + COMIN_OCEAN_RESTART:COM_OCEAN_RESTART_TMPL \ + COMIN_OCEAN_GRIB:COM_OCEAN_GRIB_TMPL \ + COMIN_OCEAN_NETCDF:COM_OCEAN_NETCDF_TMPL \ + COMIN_OCEAN_ANALYSIS:COM_OCEAN_ANALYSIS_TMPL \ + COMIN_OCEAN_BMATRIX:COM_OCEAN_BMATRIX_TMPL \ + COMIN_ICE_BMATRIX:COM_ICE_BMATRIX_TMPL \ + COMIN_WAVE_GRID:COM_WAVE_GRID_TMPL \ + COMIN_WAVE_HISTORY:COM_WAVE_HISTORY_TMPL \ + COMIN_WAVE_STATION:COM_WAVE_STATION_TMPL \ + COMIN_WAVE_RESTART:COM_WAVE_RESTART_TMPL \ + COMIN_ATMOS_OZNMON:COM_ATMOS_OZNMON_TMPL \ + COMIN_ATMOS_RADMON:COM_ATMOS_RADMON_TMPL \ + COMIN_ATMOS_MINMON:COM_ATMOS_MINMON_TMPL \ + COMIN_CONF:COM_CONF_TMPL \ + COMOUT_ATMOS_TRACK:COM_ATMOS_TRACK_TMPL for grid in "0p25" "0p50" "1p00"; do YMD=${PDY} HH=${cyc} GRID=${grid} declare_from_tmpl -rx \ @@ -70,7 +71,7 @@ fi # Run archive script ############################################################### -${GLOBALARCHIVESH:-${SCRgfs}/exglobal_archive.py} +${GLOBALARCHIVESH:-${SCRgfs}/exglobal_archive_tars.py} status=$? [[ ${status} -ne 0 ]] && exit "${status}" diff --git a/jobs/JGLOBAL_ARCHIVE_VRFY b/jobs/JGLOBAL_ARCHIVE_VRFY new file mode 100755 index 0000000000..01dd876ee1 --- /dev/null +++ b/jobs/JGLOBAL_ARCHIVE_VRFY @@ -0,0 +1,50 @@ +#! /usr/bin/env bash + +source "${HOMEgfs}/ush/preamble.sh" +source "${HOMEgfs}/ush/jjob_header.sh" -e "arch_vrfy" -c "base arch_vrfy wave" + + +############################################## +# Set variables used in the script +############################################## +YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMIN_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \ + COMIN_ATMOS_GENESIS:COM_ATMOS_GENESIS_TMPL \ + COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL \ + COMIN_ATMOS_TRACK:COM_ATMOS_TRACK_TMPL \ + COMIN_CHEM_ANALYSIS:COM_CHEM_ANALYSIS_TMPL \ + COMIN_SNOW_ANALYSIS:COM_SNOW_ANALYSIS_TMPL \ + COMIN_OBS:COM_OBS_TMPL \ + COMOUT_ATMOS_TRACK:COM_ATMOS_TRACK_TMPL + +for grid in "0p25" "0p50" "1p00"; do + YMD=${PDY} HH=${cyc} GRID=${grid} declare_from_tmpl -rx \ + "COMIN_ATMOS_GRIB_${grid}:COM_ATMOS_GRIB_GRID_TMPL" +done + +############################################################### +# Run archive script +############################################################### + +${GLOBALARCHIVESH:-${SCRgfs}/exglobal_archive_vrfy.py} +status=$? +[[ ${status} -ne 0 ]] && exit "${status}" + +############################################## +# End JOB SPECIFIC work +############################################## + +############################################## +# Final processing +############################################## +if [[ -e "${pgmout}" ]] ; then + cat "${pgmout}" +fi + +########################################## +# Remove the Temporary working directory +########################################## +cd "${DATAROOT}" || (echo "${DATAROOT} does not exist. ABORT!"; exit 1) +[[ ${KEEPDATA} = "NO" ]] && rm -rf "${DATA}" + +exit 0 diff --git a/jobs/rocoto/arch.sh b/jobs/rocoto/arch_tars.sh similarity index 90% rename from jobs/rocoto/arch.sh rename to jobs/rocoto/arch_tars.sh index 083e319bf5..d9c58a9b38 100755 --- a/jobs/rocoto/arch.sh +++ b/jobs/rocoto/arch_tars.sh @@ -13,12 +13,12 @@ status=$? PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${HOMEgfs}/ush/python" export PYTHONPATH -export job="arch" +export job="arch_tars" export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_ARCHIVE +"${HOMEgfs}"/jobs/JGLOBAL_ARCHIVE_TARS status=$? exit "${status}" diff --git a/jobs/rocoto/arch_vrfy.sh b/jobs/rocoto/arch_vrfy.sh new file mode 100755 index 0000000000..fee66c01b6 --- /dev/null +++ b/jobs/rocoto/arch_vrfy.sh @@ -0,0 +1,24 @@ +#! /usr/bin/env bash + +source "${HOMEgfs}/ush/preamble.sh" + +############################################################### +# Source FV3GFS workflow modules +. "${HOMEgfs}"/ush/load_fv3gfs_modules.sh +status=$? +[[ ${status} -ne 0 ]] && exit "${status}" + +############################################################### +# setup python path for workflow utilities and tasks +PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${HOMEgfs}/ush/python" +export PYTHONPATH + +export job="arch_vrfy" +export jobid="${job}.$$" + +############################################################### +# Execute the JJOB +"${HOMEgfs}"/jobs/JGLOBAL_ARCHIVE_VRFY +status=$? + +exit "${status}" diff --git a/jobs/rocoto/earc.sh b/jobs/rocoto/earc_tars.sh similarity index 90% rename from jobs/rocoto/earc.sh rename to jobs/rocoto/earc_tars.sh index 4a9263b509..a796d90232 100755 --- a/jobs/rocoto/earc.sh +++ b/jobs/rocoto/earc_tars.sh @@ -13,12 +13,12 @@ status=$? PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${HOMEgfs}/ush/python" export PYTHONPATH -export job="earc" +export job="earc_tars" export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_ENKF_ARCHIVE" +"${HOMEgfs}/jobs/JGDAS_ENKF_ARCHIVE_TARS" status=$? exit "${status}" diff --git a/jobs/rocoto/earc_vrfy.sh b/jobs/rocoto/earc_vrfy.sh new file mode 100755 index 0000000000..2b8c0db05b --- /dev/null +++ b/jobs/rocoto/earc_vrfy.sh @@ -0,0 +1,24 @@ +#! /usr/bin/env bash + +source "${HOMEgfs}/ush/preamble.sh" + +############################################################### +# Source FV3GFS workflow modules +. "${HOMEgfs}/ush/load_fv3gfs_modules.sh" +status=$? +[[ ${status} -ne 0 ]] && exit "${status}" + +############################################################### +# setup python path for workflow utilities and tasks +PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${HOMEgfs}/ush/python" +export PYTHONPATH + +export job="earc_vrfy" +export jobid="${job}.$$" + +############################################################### +# Execute the JJOB +"${HOMEgfs}/jobs/JGDAS_ENKF_ARCHIVE_VRFY" +status=$? + +exit "${status}" diff --git a/parm/archive/gfsa.yaml.j2 b/parm/archive/gfsa.yaml.j2 index 4efe281120..a7cfaafcd5 100644 --- a/parm/archive/gfsa.yaml.j2 +++ b/parm/archive/gfsa.yaml.j2 @@ -6,7 +6,7 @@ gfsa: # Logs # TODO explicitly name all logs to include {% for log in glob("logs/" ~ cycle_YMDH ~ "/gfs*.log") %} - {% if not "gfs_arch.log" in log %} + {% if not "gfs_arch_tars.log" in log %} - "{{ log }}" {% endif %} {% endfor %} diff --git a/parm/config/gefs/config.arch b/parm/config/gefs/config.arch_tars similarity index 56% rename from parm/config/gefs/config.arch rename to parm/config/gefs/config.arch_tars index a23bcce6ae..7605cc04c1 100644 --- a/parm/config/gefs/config.arch +++ b/parm/config/gefs/config.arch_tars @@ -1,15 +1,15 @@ #! /usr/bin/env bash -########## config.arch ########## +########## config.arch_tars ########## # Archive specific -echo "BEGIN: config.arch" +echo "BEGIN: config.arch_tars" # Get task specific resources -. "${EXPDIR}/config.resources" arch +. "${EXPDIR}/config.resources" arch_tars export ARCH_GAUSSIAN="YES" export ARCH_GAUSSIAN_FHMAX=${FHMAX_GFS} export ARCH_GAUSSIAN_FHINC=${FHOUT_GFS} -echo "END: config.arch" +echo "END: config.arch_tars" diff --git a/parm/config/gfs/config.arch b/parm/config/gefs/config.arch_vrfy similarity index 56% rename from parm/config/gfs/config.arch rename to parm/config/gefs/config.arch_vrfy index a23bcce6ae..cb668a48e2 100644 --- a/parm/config/gfs/config.arch +++ b/parm/config/gefs/config.arch_vrfy @@ -1,15 +1,15 @@ #! /usr/bin/env bash -########## config.arch ########## +########## config.arch_vrfy ########## # Archive specific -echo "BEGIN: config.arch" +echo "BEGIN: config.arch_vrfy" # Get task specific resources -. "${EXPDIR}/config.resources" arch +. "${EXPDIR}/config.resources" arch_vrfy export ARCH_GAUSSIAN="YES" export ARCH_GAUSSIAN_FHMAX=${FHMAX_GFS} export ARCH_GAUSSIAN_FHINC=${FHOUT_GFS} -echo "END: config.arch" +echo "END: config.arch_vrfy" diff --git a/parm/config/gefs/config.base b/parm/config/gefs/config.base index 400be7eb17..e1fb6e587a 100644 --- a/parm/config/gefs/config.base +++ b/parm/config/gefs/config.base @@ -334,11 +334,16 @@ export DO_METP="NO" # Run METPLUS jobs - set METPLUS settings in config. export DO_FIT2OBS="NO" # Run fit to observations package # Archiving options +export VRFYARCH="@VRFYARCH@" # save verification data locally export HPSSARCH="@HPSSARCH@" # save data to HPSS archive export LOCALARCH="@LOCALARCH@" # save data to local archive if [[ ${HPSSARCH} = "YES" ]] && [[ ${LOCALARCH} = "YES" ]]; then echo "Both HPSS and local archiving selected. Please choose one or the other." exit 3 +elif [[ ${HPSSARCH} = "YES" ]] || [[ ${LOCALARCH} = "YES" ]]; then + export DO_ARCHTAR="YES" +else + export DO_ARCHTAR="NO" fi export ARCH_CYC=00 # Archive data at this cycle for warm start and/or forecast-only capabilities export ARCH_WARMICFREQ=4 # Archive frequency in days for warm start capability @@ -348,8 +353,6 @@ export ARCH_EXPDIR_FREQ=0 # How often to archive the EXPDIR in hours or 0 for export ARCH_HASHES='YES' # Archive the hashes of the GW and submodules and 'git status' for each; requires ARCH_EXPDIR export ARCH_DIFFS='NO' # Archive the output of 'git diff' for the GW; requires ARCH_EXPDIR -export DELETE_COM_IN_ARCHIVE_JOB="YES" # NO=retain ROTDIR. YES default in arch.sh and earc.sh. - # Number of regional collectives to create soundings for export NUM_SND_COLLECTIVES=${NUM_SND_COLLECTIVES:-9} diff --git a/parm/config/gefs/config.resources b/parm/config/gefs/config.resources index bb33f3eb02..8270ea92b5 100644 --- a/parm/config/gefs/config.resources +++ b/parm/config/gefs/config.resources @@ -323,7 +323,7 @@ case ${step} in export is_exclusive=False ;; - "arch") + "arch_tars") export walltime="06:00:00" export ntasks=1 export tasks_per_node=1 @@ -331,6 +331,14 @@ case ${step} in export memory="4096M" ;; + "arch_vrfy") + export walltime="00:15:00" + export ntasks=1 + export tasks_per_node=1 + export threads_per_task=1 + export memory="4096M" + ;; + "cleanup") export walltime="00:30:00" export ntasks=1 diff --git a/parm/config/gefs/config.resources.AWSPW b/parm/config/gefs/config.resources.AWSPW index f91460b6aa..43cfcf56cc 100644 --- a/parm/config/gefs/config.resources.AWSPW +++ b/parm/config/gefs/config.resources.AWSPW @@ -18,7 +18,7 @@ case ${step} in max_tasks_per_node=48 ;; - "arch") + "arch_vrfy" | "arch_tars") export PARTITION_BATCH="process" max_tasks_per_node=24 ;; diff --git a/parm/config/gfs/config.arch_tars b/parm/config/gfs/config.arch_tars new file mode 100644 index 0000000000..f46ff45a3a --- /dev/null +++ b/parm/config/gfs/config.arch_tars @@ -0,0 +1,15 @@ +#! /usr/bin/env bash + +########## config.arch_tars ########## +# Archive specific + +echo "BEGIN: config.arch_tars" + +# Get task specific resources +. "${EXPDIR}/config.resources" "arch_tars" + +export ARCH_GAUSSIAN="YES" +export ARCH_GAUSSIAN_FHMAX=${FHMAX_GFS} +export ARCH_GAUSSIAN_FHINC=${FHOUT_GFS} + +echo "END: config.arch_tars" diff --git a/parm/config/gfs/config.arch_vrfy b/parm/config/gfs/config.arch_vrfy new file mode 100644 index 0000000000..6bcbdb57fc --- /dev/null +++ b/parm/config/gfs/config.arch_vrfy @@ -0,0 +1,15 @@ +#! /usr/bin/env bash + +########## config.arch_vrfy ########## +# Archive specific + +echo "BEGIN: config.arch_vrfy" + +# Get task specific resources +. "${EXPDIR}/config.resources" "arch_vrfy" + +export ARCH_GAUSSIAN="YES" +export ARCH_GAUSSIAN_FHMAX=${FHMAX_GFS} +export ARCH_GAUSSIAN_FHINC=${FHOUT_GFS} + +echo "END: config.arch_vrfy" diff --git a/parm/config/gfs/config.base b/parm/config/gfs/config.base index 96954b4acb..e28e7ef226 100644 --- a/parm/config/gfs/config.base +++ b/parm/config/gfs/config.base @@ -82,7 +82,7 @@ export DO_MOS="NO" # GFS Model Output Statistics - Only su # NO for retrospective parallel; YES for real-time parallel # arch.sh uses REALTIME for MOS. Need to set REALTIME=YES -# if want MOS written to HPSS. Should update arch.sh to +# if want MOS written to HPSS. Should update arch_vrfy.sh and arch_tars to # use RUNMOS flag export REALTIME="YES" @@ -485,6 +485,10 @@ export LOCALARCH="@LOCALARCH@" # save data to local archive if [[ ${HPSSARCH} = "YES" ]] && [[ ${LOCALARCH} = "YES" ]]; then echo "FATAL ERROR: Both HPSS and local archiving selected. Please choose one or the other." exit 4 +elif [[ ${HPSSARCH} = "YES" ]] || [[ ${LOCALARCH} = "YES" ]]; then + export DO_ARCHTAR="YES" +else + export DO_ARCHTAR="NO" fi export ARCH_CYC=00 # Archive data at this cycle for warm start and/or forecast-only capabilities export ARCH_WARMICFREQ=4 # Archive frequency in days for warm start capability diff --git a/parm/config/gfs/config.earc b/parm/config/gfs/config.earc_tars similarity index 72% rename from parm/config/gfs/config.earc rename to parm/config/gfs/config.earc_tars index 00a2fa95bd..c87c5e7784 100644 --- a/parm/config/gfs/config.earc +++ b/parm/config/gfs/config.earc_tars @@ -1,14 +1,14 @@ #! /usr/bin/env bash -########## config.earc ########## +########## config.earc_tars ########## # Ensemble archive specific -echo "BEGIN: config.earc" +echo "BEGIN: config.earc_tars" # Get task specific resources -. $EXPDIR/config.resources earc +. "${EXPDIR}/config.resources" "earc_tars" -# Set the number of ensemble members to archive per earc job +# Set the number of ensemble members to archive per earc_tars job case "${CASE_ENS}" in "C48" | "C96") export NMEM_EARCGRP=80 @@ -32,4 +32,4 @@ esac export RMOLDSTD_ENKF=144 export RMOLDEND_ENKF=24 -echo "END: config.earc" +echo "END: config.earc_tars" diff --git a/parm/config/gfs/config.earc_vrfy b/parm/config/gfs/config.earc_vrfy new file mode 100644 index 0000000000..9fe52b7ee4 --- /dev/null +++ b/parm/config/gfs/config.earc_vrfy @@ -0,0 +1,15 @@ +#! /usr/bin/env bash + +########## config.earc_vrfy ########## +# Ensemble archive specific + +echo "BEGIN: config.earc_vrfy" + +# Get task specific resources" +. "${EXPDIR}/config.resources" "earc_vrfy" + +#--starting and ending hours of previous cycles to be removed from rotating directory +export RMOLDSTD_ENKF=144 +export RMOLDEND_ENKF=24 + +echo "END: config.earc_vrfy" diff --git a/parm/config/gfs/config.resources b/parm/config/gfs/config.resources index 06acc4e36e..23fe8cdf18 100644 --- a/parm/config/gfs/config.resources +++ b/parm/config/gfs/config.resources @@ -20,8 +20,8 @@ if (( $# != 1 )); then echo "anal sfcanl analcalc analdiag fcst echgres" echo "upp atmos_products" echo "tracker genesis genesis_fsu" - echo "verfozn verfrad vminmon fit2obs metp arch cleanup" - echo "eobs ediag eomg eupd ecen esfc efcs epos earc" + echo "verfozn verfrad vminmon fit2obs metp arc_vrfy arc_tars cleanup" + echo "eobs ediag eomg eupd ecen esfc efcs epos earc_vrfy earc_tars" echo "init_chem mom6ic oceanice_products" echo "waveinit waveprep wavepostsbs wavepostbndpnt wavepostbndpntbll wavepostpnt" echo "wavegempak waveawipsbulls waveawipsgridded" @@ -1059,7 +1059,7 @@ case ${step} in export is_exclusive=True ;; - "arch" | "earc" | "getic" | "fetch") + "arch_tars" | "earc_tars" | "getic" | "fetch") walltime="06:00:00" ntasks=1 tasks_per_node=1 @@ -1067,6 +1067,14 @@ case ${step} in memory="4096M" ;; + "arch_vrfy" | "earc_vrfy") + walltime="00:15:00" + ntasks=1 + tasks_per_node=1 + threads_per_task=1 + memory="4096M" + ;; + "cleanup") walltime="00:15:00" ntasks=1 diff --git a/parm/config/gfs/config.resources.AWSPW b/parm/config/gfs/config.resources.AWSPW index 22fe110670..d044c475fb 100644 --- a/parm/config/gfs/config.resources.AWSPW +++ b/parm/config/gfs/config.resources.AWSPW @@ -18,7 +18,7 @@ case ${step} in max_tasks_per_node=48 ;; - "arch") + "arch_vrfy" | "arch_tars") export PARTITION_BATCH="process" max_tasks_per_node=24 ;; diff --git a/parm/config/gfs/config.resources.WCOSS2 b/parm/config/gfs/config.resources.WCOSS2 index 342286d008..be55214cac 100644 --- a/parm/config/gfs/config.resources.WCOSS2 +++ b/parm/config/gfs/config.resources.WCOSS2 @@ -37,7 +37,7 @@ case ${step} in export memory="200GB" ;; - "arch" | "earc" | "getic") + "arch_vrfy" | "arch_tars" | "earc_vrfy" | "earc_tars" | "getic") declare -x "memory"="50GB" ;; diff --git a/scripts/exgdas_enkf_earc.py b/scripts/exgdas_enkf_earc_tars.py similarity index 92% rename from scripts/exgdas_enkf_earc.py rename to scripts/exgdas_enkf_earc_tars.py index 107d541a41..63c978d6a8 100755 --- a/scripts/exgdas_enkf_earc.py +++ b/scripts/exgdas_enkf_earc_tars.py @@ -46,10 +46,7 @@ def main(): os.chdir(config.ROTDIR) # Determine which archives to create - arcdir_set, atardir_sets = archive.configure(archive_dict) - - # Populate the product archive (ARCDIR) - archive.execute_store_products(arcdir_set) + atardir_sets = archive.configure_tars(archive_dict) # Create the backup tarballs and store in ATARDIR for atardir_set in atardir_sets: diff --git a/scripts/exgdas_enkf_earc_vrfy.py b/scripts/exgdas_enkf_earc_vrfy.py new file mode 100755 index 0000000000..b7dd33a89a --- /dev/null +++ b/scripts/exgdas_enkf_earc_vrfy.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +import os + +from pygfs.task.archive import Archive +from wxflow import AttrDict, Logger, cast_strdict_as_dtypedict, chdir, logit + +# initialize root logger +logger = Logger(level=os.environ.get("LOGGING_LEVEL", "DEBUG"), colored_log=True) + + +@logit(logger) +def main(): + + config = cast_strdict_as_dtypedict(os.environ) + + # Instantiate the Archive object + archive = Archive(config) + + # Pull out all the configuration keys needed to run the rest of archive steps + keys = ['current_cycle', 'RUN', 'PSLOT', 'ROTDIR', 'PARMgfs', 'VFYARC', + 'ARCDIR', 'MODE', 'DO_JEDIATMENS', 'DO_FIT2OBS', 'DO_JEDIATMVAR', + 'DO_JEDISNOWDA', 'DO_AERO_ANL', 'DO_PREP_OBS_AERO', 'NET', 'MODE', 'FHOUT_GFS', + 'FHMAX_HF_GFS', 'FHOUT_GFS', 'FHMAX_FITS', 'FHMAX', 'FHOUT', 'FHMAX_GFS'] + + archive_dict = AttrDict() + for key in keys: + archive_dict[key] = archive.task_config.get(key) + if archive_dict[key] is None: + print(f"Warning: key ({key}) not found in task_config!") + + # Also import all COMIN* directory and template variables + for key in archive.task_config.keys(): + if key.startswith("COM"): + archive_dict[key] = archive.task_config[key] + + cwd = os.getcwd() + + os.chdir(config.ROTDIR) + + # Determine which archives to create + arcdir_set = archive.configure_vrfy(archive_dict) + + # Populate the product archive (ARCDIR) + archive.execute_store_products(arcdir_set) + + os.chdir(cwd) + + +if __name__ == '__main__': + main() diff --git a/scripts/exglobal_archive.py b/scripts/exglobal_archive_tars.py similarity index 92% rename from scripts/exglobal_archive.py rename to scripts/exglobal_archive_tars.py index f64db172ac..dc8b39050c 100755 --- a/scripts/exglobal_archive.py +++ b/scripts/exglobal_archive_tars.py @@ -35,7 +35,7 @@ def main(): 'ARCH_GAUSSIAN_FHMAX', 'ARCH_GAUSSIAN_FHINC', 'ARCH_GAUSSIAN_FHINC', 'DOIAU', 'OCNRES', 'ICERES', 'NUM_SND_COLLECTIVES', 'FHOUT_WAV', 'FHOUT_HF_WAV', 'FHMAX_WAV', 'FHMAX_HF_WAV', 'FHMAX_WAV_GFS', - 'restart_interval_gdas', 'restart_interval_gfs', + 'restart_interval_gdas', 'restart_interval_gfs', 'DO_ARCHTAR', 'DO_AERO_ANL', 'DO_AERO_FCST', 'DO_CA', 'DOIBP_WAV', 'DO_JEDIOCNVAR', 'DOHYBVAR_OCN', 'NMEM_ENS', 'DO_JEDIATMVAR', 'DO_VRFY_OCEANDA', 'FHMAX_FITS', 'waveGRD', 'IAUFHRS', 'DO_FIT2OBS', 'NET', 'FHOUT_HF_GFS', 'FHMAX_HF_GFS', 'REPLAY_ICS', @@ -57,10 +57,7 @@ def main(): with chdir(config.ROTDIR): # Determine which archives to create - arcdir_set, atardir_sets = archive.configure(archive_dict) - - # Populate the product archive (ARCDIR) - archive.execute_store_products(arcdir_set) + atardir_sets = archive.configure_tars(archive_dict) # Create the backup tarballs and store in ATARDIR for atardir_set in atardir_sets: diff --git a/scripts/exglobal_archive_vrfy.py b/scripts/exglobal_archive_vrfy.py new file mode 100755 index 0000000000..4d08b994f0 --- /dev/null +++ b/scripts/exglobal_archive_vrfy.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +import os + +from pygfs.task.archive import Archive +from wxflow import AttrDict, Logger, cast_strdict_as_dtypedict, logit, chdir + +# initialize root logger +logger = Logger(level=os.environ.get("LOGGING_LEVEL", "DEBUG"), colored_log=True) + + +@logit(logger) +def main(): + + config = cast_strdict_as_dtypedict(os.environ) + + # Instantiate the Archive object + archive = Archive(config) + + # update these keys to be 3 digits if they are part of archive.task_config.keys + for key in ['OCNRES', 'ICERES']: + try: + archive.task_config[key] = f"{archive.task_config[key]:03d}" + except KeyError as ee: + logger.info(f"key ({key}) not found in archive.task_config!") + + # Pull out all the configuration keys needed to run the rest of archive steps + keys = ['current_cycle', 'RUN', 'PSLOT', 'ROTDIR', 'PARMgfs', 'VFYARC', 'REPLAY_ICS', + 'ARCDIR', 'MODE', 'DO_JEDIATMENS', 'DO_FIT2OBS', 'DO_JEDIATMVAR', 'FHMIN_GFS', + 'DO_JEDISNOWDA', 'DO_AERO_ANL', 'DO_PREP_OBS_AERO', 'NET', 'MODE', 'FHOUT_GFS', + 'FHMAX_HF_GFS', 'FHOUT_GFS', 'FHMAX_FITS', 'FHMAX', 'FHOUT', 'FHMAX_GFS'] + + archive_dict = AttrDict() + for key in keys: + try: + archive_dict[key] = archive.task_config[key] + except KeyError as ee: + logger.warning(f"WARNING: key ({key}) not found in archive.task_config!") + + # Also import all COMIN* and COMOUT* directory and template variables + for key in archive.task_config.keys(): + if key.startswith(("COM_", "COMIN_", "COMOUT_")): + archive_dict[key] = archive.task_config.get(key) + + with chdir(config.ROTDIR): + + # Determine which archives to create + arcdir_set = archive.configure_vrfy(archive_dict) + + # Populate the product archive (ARCDIR) + archive.execute_store_products(arcdir_set) + + # Clean up any temporary files + archive.clean() + + +if __name__ == '__main__': + main() diff --git a/ush/python/pygfs/task/archive.py b/ush/python/pygfs/task/archive.py index ed63a22230..2620bc840b 100644 --- a/ush/python/pygfs/task/archive.py +++ b/ush/python/pygfs/task/archive.py @@ -48,8 +48,8 @@ def __init__(self, config: Dict[str, Any]) -> None: self.archive_expdir = False @logit(logger) - def configure(self, arch_dict: Dict[str, Any]) -> (Dict[str, Any], List[Dict[str, Any]]): - """Determine which tarballs will need to be created. + def configure_vrfy(self, arch_dict: Dict[str, Any]) -> (Dict[str, Any]): + """Determine which files will need to be created to archive to arcdir. Parameters ---------- @@ -60,8 +60,6 @@ def configure(self, arch_dict: Dict[str, Any]) -> (Dict[str, Any], List[Dict[str ------ arcdir_set : Dict[str, Any] Set of FileHandler instructions to copy files to the ARCDIR - atardir_sets : List[Dict[str, Any]] - List of tarballs and instructions for creating them via tar or htar """ if not os.path.isdir(arch_dict.ROTDIR): @@ -89,6 +87,44 @@ def configure(self, arch_dict: Dict[str, Any]) -> (Dict[str, Any], List[Dict[str arcdir_set = Archive._construct_arcdir_set(arcdir_j2yaml, arch_dict) + # Collect datasets that need to be archived + self.tar_cmd = "" + + return arcdir_set + + @logit(logger) + def configure_tars(self, arch_dict: Dict[str, Any]) -> (List[Dict[str, Any]]): + """Determine which tarballs will need to be created. + + Parameters + ---------- + arch_dict : Dict[str, Any] + Task specific keys, e.g. runtime options (DO_AERO_FCST, DO_ICE, etc) + + Return + ------ + atardir_sets : List[Dict[str, Any]] + List of tarballs and instructions for creating them via tar or htar + """ + + if not os.path.isdir(arch_dict.ROTDIR): + raise FileNotFoundError(f"FATAL ERROR: The ROTDIR ({arch_dict.ROTDIR}) does not exist!") + + if arch_dict.RUN in ["gdas", "gfs"]: + + # Copy the cyclone track files and rename the experiments + # TODO This really doesn't belong in archiving and should be moved elsewhere + Archive._rename_cyclone_expt(arch_dict) + + archive_parm = os.path.join(arch_dict.PARMgfs, "archive") + + # Add the glob.glob function for capturing log filenames + # TODO remove this kludge once log filenames are explicit + arch_dict['glob'] = glob.glob + + # Add the os.path.exists function to the dict for yaml parsing + arch_dict['path_exists'] = os.path.exists + if not os.path.isdir(arch_dict.ROTDIR): raise FileNotFoundError(f"FATAL ERROR: The ROTDIR ({arch_dict.ROTDIR}) does not exist!") @@ -109,9 +145,8 @@ def configure(self, arch_dict: Dict[str, Any]) -> (Dict[str, Any], List[Dict[str self.chgrp_cmd = chgrp self.chmod_cmd = os.chmod self.rm_cmd = rm_p - else: # Only perform local archiving. Do not create tarballs. - self.tar_cmd = "" - return arcdir_set, [] + else: + raise ValueError("FATAL ERROR: Neither HPSSARCH nor LOCALARCH are set to True!") # Determine if we are archiving the EXPDIR this cycle (always skip for ensembles) if "enkf" not in arch_dict.RUN and arch_dict.ARCH_EXPDIR: @@ -138,7 +173,7 @@ def configure(self, arch_dict: Dict[str, Any]) -> (Dict[str, Any], List[Dict[str atardir_sets.append(dataset) - return arcdir_set, atardir_sets + return atardir_sets @logit(logger) def execute_store_products(self, arcdir_set: Dict[str, Any]) -> None: diff --git a/workflow/applications/applications.py b/workflow/applications/applications.py index 88be488b47..8672034195 100644 --- a/workflow/applications/applications.py +++ b/workflow/applications/applications.py @@ -90,6 +90,7 @@ def _get_run_options(self, conf: Configuration) -> Dict[str, Any]: run_options[run]['do_goes'] = run_base.get('DO_GOES', False) run_options[run]['do_mos'] = run_base.get('DO_MOS', False) run_options[run]['do_extractvars'] = run_base.get('DO_EXTRACTVARS', False) + run_options[run]['do_archtar'] = run_base.get('DO_ARCHTAR', False) run_options[run]['do_atm'] = run_base.get('DO_ATM', True) run_options[run]['do_wave'] = run_base.get('DO_WAVE', False) diff --git a/workflow/applications/gefs.py b/workflow/applications/gefs.py index 2e08ddc21d..9650912459 100644 --- a/workflow/applications/gefs.py +++ b/workflow/applications/gefs.py @@ -28,7 +28,7 @@ def _get_app_configs(self, run): Returns the config_files that are involved in gefs """ options = self.run_options[run] - configs = ['stage_ic', 'fcst', 'atmos_products', 'arch', 'cleanup'] + configs = ['stage_ic', 'fcst', 'atmos_products'] if options['nens'] > 0: configs += ['efcs', 'atmos_ensstat'] @@ -47,6 +47,11 @@ def _get_app_configs(self, run): if options['do_extractvars']: configs += ['extractvars'] + if options['do_archtar']: + configs += ['arch_tars'] + + configs += ['arch_vrfy', 'cleanup'] + return configs @staticmethod @@ -93,6 +98,9 @@ def get_task_names(self): if options['do_extractvars']: tasks += ['extractvars'] - tasks += ['arch', 'cleanup'] + if options['do_archtar']: + tasks += ['arch_tars'] + + tasks += ['arch_vrfy', 'cleanup'] return {f"{self.run}": tasks} diff --git a/workflow/applications/gfs_cycled.py b/workflow/applications/gfs_cycled.py index 2bf793eafa..b348bb4273 100644 --- a/workflow/applications/gfs_cycled.py +++ b/workflow/applications/gfs_cycled.py @@ -76,7 +76,10 @@ def _get_app_configs(self, run): if options['do_ocean'] or options['do_ice']: configs += ['oceanice_products'] - configs += ['stage_ic', 'sfcanl', 'analcalc', 'fcst', 'upp', 'atmos_products', 'arch', 'cleanup'] + configs += ['stage_ic', 'sfcanl', 'analcalc', 'fcst', 'upp', 'atmos_products', 'arch_vrfy', 'cleanup'] + + if options['do_archtar']: + configs += ['arch_tars'] if options['do_hybvar']: if options['do_jediatmens']: @@ -84,7 +87,11 @@ def _get_app_configs(self, run): 'atmensanlletkf', 'atmensanlfv3inc', 'atmensanlfinal'] else: configs += ['eobs', 'eomg', 'ediag', 'eupd'] - configs += ['ecen', 'esfc', 'efcs', 'echgres', 'epos', 'earc'] + + configs += ['ecen', 'esfc', 'efcs', 'echgres', 'epos', 'earc_vrfy'] + + if options['do_archtar']: + configs += ['earc_tars'] if options['do_fit2obs']: configs += ['fit2obs'] @@ -294,8 +301,11 @@ def get_task_names(self): 'mos_stn_prdgen', 'mos_grd_prdgen', 'mos_ext_stn_prdgen', 'mos_ext_grd_prdgen', 'mos_wx_prdgen', 'mos_wx_ext_prdgen'] - # Last two items - task_names[run] += ['arch', 'cleanup'] + # Last items + task_names[run] += ['arch_vrfy'] + if options['do_archtar']: + task_names[run] += ['arch_tars'] + task_names[run] += ['cleanup'] # Ensemble tasks elif 'enkf' in run: @@ -317,6 +327,10 @@ def get_task_names(self): task_names[run].append('esnowanl') if options['do_jedisnowda'] else 0 task_names[run].append('efcs') if 'gdas' in run else 0 task_names[run].append('epos') if 'gdas' in run else 0 - task_names[run] += ['stage_ic', 'ecen', 'esfc', 'earc', 'cleanup'] + + task_names[run] += ['stage_ic', 'ecen', 'esfc'] + if options['do_archtar']: + task_names[run] += ['earc_tars'] + task_names[run] += ['earc_vrfy', 'cleanup'] return task_names diff --git a/workflow/applications/gfs_forecast_only.py b/workflow/applications/gfs_forecast_only.py index 7409d4adec..6645b892d9 100644 --- a/workflow/applications/gfs_forecast_only.py +++ b/workflow/applications/gfs_forecast_only.py @@ -30,10 +30,11 @@ def _get_app_configs(self, run): configs = [] options = self.run_options[run] + if options['do_fetch_hpss'] or options['do_fetch_local']: configs += ['fetch'] - configs += ['stage_ic', 'fcst', 'arch', 'cleanup'] + configs += ['stage_ic', 'fcst', 'arch_vrfy', 'cleanup'] if options['do_atm']: @@ -85,6 +86,9 @@ def _get_app_configs(self, run): 'mos_stn_prdgen', 'mos_grd_prdgen', 'mos_ext_stn_prdgen', 'mos_ext_grd_prdgen', 'mos_wx_prdgen', 'mos_wx_ext_prdgen'] + if options['do_archtar']: + configs += ['arch_tars'] + return configs @staticmethod @@ -173,6 +177,9 @@ def get_task_names(self): 'mos_stn_prdgen', 'mos_grd_prdgen', 'mos_ext_stn_prdgen', 'mos_ext_grd_prdgen', 'mos_wx_prdgen', 'mos_wx_ext_prdgen'] - tasks += ['arch', 'cleanup'] # arch and cleanup **must** be the last tasks + if options['do_archtar']: + tasks += ['arch_tars'] + + tasks += ['arch_vrfy', 'cleanup'] # arch_tar, arch_vrfy, and cleanup **must** be the last tasks return {f"{self.run}": tasks} diff --git a/workflow/rocoto/gefs_tasks.py b/workflow/rocoto/gefs_tasks.py index f1b1cd1ea2..8b1522ae32 100644 --- a/workflow/rocoto/gefs_tasks.py +++ b/workflow/rocoto/gefs_tasks.py @@ -541,7 +541,7 @@ def extractvars(self): return task - def arch(self): + def arch_vrfy(self): deps = [] dep_dict = {'type': 'metatask', 'name': 'gefs_atmos_prod'} deps.append(rocoto.add_dependency(dep_dict)) @@ -568,14 +568,58 @@ def arch(self): deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep=deps, dep_condition='and') - resources = self.get_resource('arch') - task_name = 'gefs_arch' + resources = self.get_resource('arch_vrfy') + task_name = 'gefs_arch_vrfy' task_dict = {'task_name': task_name, 'resources': resources, 'envars': self.envars, 'cycledef': 'gefs', 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/jobs/rocoto/arch.sh', + 'command': f'{self.HOMEgfs}/jobs/rocoto/arch_vrfy.sh', + 'job_name': f'{self.pslot}_{task_name}_@H', + 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', + 'maxtries': '&MAXTRIES;' + } + + task = rocoto.create_task(task_dict) + + return task + + def arch_tars(self): + deps = [] + dep_dict = {'type': 'metatask', 'name': 'gefs_atmos_prod'} + deps.append(rocoto.add_dependency(dep_dict)) + dep_dict = {'type': 'metatask', 'name': 'gefs_atmos_ensstat'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_ice']: + dep_dict = {'type': 'metatask', 'name': 'gefs_ice_prod'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_ocean']: + dep_dict = {'type': 'metatask', 'name': 'gefs_ocean_prod'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_wave']: + dep_dict = {'type': 'metatask', 'name': 'gefs_wave_post_grid'} + deps.append(rocoto.add_dependency(dep_dict)) + dep_dict = {'type': 'metatask', 'name': 'gefs_wave_post_pnt'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_wave_bnd']: + dep_dict = {'type': 'metatask', 'name': 'gefs_wave_post_bndpnt'} + deps.append(rocoto.add_dependency(dep_dict)) + dep_dict = {'type': 'metatask', 'name': 'gefs_wave_post_bndpnt_bull'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_extractvars']: + dep_dict = {'type': 'metatask', 'name': 'gefs_extractvars'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep=deps, dep_condition='and') + + resources = self.get_resource('arch_tars') + task_name = 'gefs_arch_tars' + task_dict = {'task_name': task_name, + 'resources': resources, + 'envars': self.envars, + 'cycledef': 'gefs', + 'dependency': dependencies, + 'command': f'{self.HOMEgfs}/jobs/rocoto/arch_tars.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -587,9 +631,12 @@ def arch(self): def cleanup(self): deps = [] - dep_dict = {'type': 'task', 'name': 'gefs_arch'} + dep_dict = {'type': 'task', 'name': 'gefs_arch_vrfy'} deps.append(rocoto.add_dependency(dep_dict)) - dependencies = rocoto.create_dependency(dep=deps) + if self.options['do_archtar']: + dep_dict = {'type': 'task', 'name': 'gefs_arch_tars'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep=deps, dep_condition='and') resources = self.get_resource('cleanup') task_name = 'gefs_cleanup' task_dict = {'task_name': task_name, diff --git a/workflow/rocoto/gfs_tasks.py b/workflow/rocoto/gfs_tasks.py index bce3036be7..5874125874 100644 --- a/workflow/rocoto/gfs_tasks.py +++ b/workflow/rocoto/gfs_tasks.py @@ -1897,13 +1897,13 @@ def fit2obs(self): def metp(self): deps = [] - dep_dict = {'type': 'task', 'name': f'{self.run}_arch'} + dep_dict = {'type': 'task', 'name': f'{self.run}_arch_vrfy'} deps.append(rocoto.add_dependency(dep_dict)) if self._base["interval_gfs"] < to_timedelta("24H"): n_lookback = self._base["interval_gfs"] // to_timedelta("6H") for lookback in range(1, n_lookback + 1): deps2 = [] - dep_dict = {'type': 'taskvalid', 'name': f'{self.run}_arch', 'condition': 'not'} + dep_dict = {'type': 'taskvalid', 'name': f'{self.run}_arch_vrfy', 'condition': 'not'} deps2.append(rocoto.add_dependency(dep_dict)) for lookback2 in range(1, lookback): offset = timedelta_to_HMS(-to_timedelta(f'{6*lookback2}H')) @@ -1911,7 +1911,7 @@ def metp(self): deps2.append(rocoto.add_dependency(dep_dict)) offset = timedelta_to_HMS(-to_timedelta(f'{6*lookback}H')) - dep_dict = {'type': 'task', 'name': f'{self.run}_arch', 'offset': offset} + dep_dict = {'type': 'task', 'name': f'{self.run}_arch_vrfy', 'offset': offset} deps2.append(rocoto.add_dependency(dep_dict)) deps.append(rocoto.create_dependency(dep_condition='and', dep=deps2)) @@ -2301,7 +2301,59 @@ def mos_wx_ext_prdgen(self): return task - def arch(self): + def arch_vrfy(self): + deps = [] + if self.app_config.mode in ['cycled']: + if self.run in ['gfs']: + dep_dict = {'type': 'task', 'name': f'{self.run}_atmanlprod'} + deps.append(rocoto.add_dependency(dep_dict)) + elif self.run in ['gdas']: + dep_dict = {'type': 'task', 'name': f'{self.run}_atmanlprod'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_fit2obs']: + dep_dict = {'type': 'task', 'name': f'{self.run}_fit2obs'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.run in ['gfs'] and self.options['do_tracker']: + dep_dict = {'type': 'task', 'name': f'{self.run}_tracker'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.run in ['gfs'] and self.options['do_genesis']: + dep_dict = {'type': 'task', 'name': f'{self.run}_genesis'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.run in ['gfs'] and self.options['do_genesis_fsu']: + dep_dict = {'type': 'task', 'name': f'{self.run}_genesis_fsu'} + deps.append(rocoto.add_dependency(dep_dict)) + # Post job dependencies + dep_dict = {'type': 'metatask', 'name': f'{self.run}_atmos_prod'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_ocean']: + if self.run in ['gfs']: + dep_dict = {'type': 'metatask', 'name': f'{self.run}_ocean_prod'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_ice']: + if self.run in ['gfs']: + dep_dict = {'type': 'metatask', 'name': f'{self.run}_ice_prod'} + deps.append(rocoto.add_dependency(dep_dict)) + + dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) + + resources = self.get_resource('arch_vrfy') + task_name = f'{self.run}_arch_vrfy' + task_dict = {'task_name': task_name, + 'resources': resources, + 'dependency': dependencies, + 'envars': self.envars, + 'cycledef': self.run.replace('enkf', ''), + 'command': f'{self.HOMEgfs}/jobs/rocoto/arch_vrfy.sh', + 'job_name': f'{self.pslot}_{task_name}_@H', + 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', + 'maxtries': '&MAXTRIES;' + } + + task = rocoto.create_task(task_dict) + + return task + + def arch_tars(self): deps = [] if self.app_config.mode in ['cycled']: if self.run in ['gfs']: @@ -2363,16 +2415,28 @@ def arch(self): dep_dict = {'type': 'task', 'name': f'{self.run}_mos_{job}'} deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_metp'] and self.run in ['gfs']: + deps2 = [] + # taskvalid only handles regular tasks, so just check the first metp job exists + dep_dict = {'type': 'taskvalid', 'name': f'{self.run}_metpg2g1', 'condition': 'not'} + deps2.append(rocoto.add_dependency(dep_dict)) + dep_dict = {'type': 'metatask', 'name': f'{self.run}_metp'} + deps2.append(rocoto.add_dependency(dep_dict)) + deps.append(rocoto.create_dependency(dep_condition='or', dep=deps2)) + + dep_dict = {'type': 'task', 'name': f'{self.run}_arch_vrfy'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) - resources = self.get_resource('arch') - task_name = f'{self.run}_arch' + resources = self.get_resource('arch_tars') + task_name = f'{self.run}_arch_tars' task_dict = {'task_name': task_name, 'resources': resources, 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/jobs/rocoto/arch.sh', + 'command': f'{self.HOMEgfs}/jobs/rocoto/arch_tars.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2382,15 +2446,22 @@ def arch(self): return task - # Cleanup +# cleanup def cleanup(self): deps = [] if 'enkf' in self.run: - dep_dict = {'type': 'metatask', 'name': f'{self.run}_eamn'} + dep_dict = {'type': 'task', 'name': f'{self.run}_earc_vrfy'} deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_archtar']: + dep_dict = {'type': 'metatask', 'name': f'{self.run}_earc_tars'} + deps.append(rocoto.add_dependency(dep_dict)) + else: - dep_dict = {'type': 'task', 'name': f'{self.run}_arch'} + dep_dict = {'type': 'task', 'name': f'{self.run}_arch_vrfy'} deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_archtar']: + dep_dict = {'type': 'task', 'name': f'{self.run}_arch_tars'} + deps.append(rocoto.add_dependency(dep_dict)) if self.options['do_gempak']: if self.run in ['gdas']: @@ -2944,7 +3015,40 @@ def _get_eposgroups(epos): return task - def earc(self): + def earc_vrfy(self): + + deps = [] + if 'enkfgdas' in self.run: + dep_dict = {'type': 'metatask', 'name': f'{self.run}_epmn'} + else: + dep_dict = {'type': 'task', 'name': f'{self.run}_esfc'} + deps.append(rocoto.add_dependency(dep_dict)) + dep_dict = {'type': 'task', 'name': f'{self.run}_echgres'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) + + earcenvars = self.envars.copy() + earcenvars.append(rocoto.create_envar(name='ENSGRP', value='#grp#')) + + resources = self.get_resource('earc_vrfy') + + task_name = f'{self.run}_earc_vrfy' + task_dict = {'task_name': task_name, + 'resources': resources, + 'dependency': dependencies, + 'envars': earcenvars, + 'cycledef': self.run.replace('enkf', ''), + 'command': f'{self.HOMEgfs}/jobs/rocoto/earc_vrfy.sh', + 'job_name': f'{self.pslot}_{task_name}_@H', + 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', + 'maxtries': '&MAXTRIES;' + } + + task = rocoto.create_task(task_dict) + + return task + + def earc_tars(self): deps = [] if 'enkfgdas' in self.run: @@ -2962,26 +3066,26 @@ def earc(self): earcenvars.append(rocoto.create_envar(name='ENSGRP', value='#grp#')) # Integer division is floor division, but we need ceiling division - n_groups = -(self.nmem // -self._configs['earc']['NMEM_EARCGRP']) + n_groups = -(self.nmem // -self._configs['earc_tars']['NMEM_EARCGRP']) groups = ' '.join([f'{grp:02d}' for grp in range(0, n_groups + 1)]) - resources = self.get_resource('earc') + resources = self.get_resource('earc_tars') var_dict = {'grp': groups} - task_name = f'{self.run}_earc#grp#' + task_name = f'{self.run}_earc_tars_#grp#' task_dict = {'task_name': task_name, 'resources': resources, 'dependency': dependencies, 'envars': earcenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/jobs/rocoto/earc.sh', + 'command': f'{self.HOMEgfs}/jobs/rocoto/earc_tars.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' } - metatask_dict = {'task_name': f'{self.run}_eamn', + metatask_dict = {'task_name': f'{self.run}_earc_tars', 'var_dict': var_dict, 'task_dict': task_dict } diff --git a/workflow/rocoto/tasks.py b/workflow/rocoto/tasks.py index c491f26800..74f5dc4b02 100644 --- a/workflow/rocoto/tasks.py +++ b/workflow/rocoto/tasks.py @@ -11,13 +11,13 @@ class Tasks: - SERVICE_TASKS = ['arch', 'earc', 'stage_ic', 'fetch', 'cleanup'] + SERVICE_TASKS = ['arch_vrfy', 'arch_tars', 'earc_vrfy', 'earc_tars', 'stage_ic', 'fetch', 'cleanup'] VALID_TASKS = ['aerosol_init', 'stage_ic', 'fetch', - 'prep', 'anal', 'sfcanl', 'analcalc', 'analdiag', 'arch', "cleanup", + 'prep', 'anal', 'sfcanl', 'analcalc', 'analdiag', 'arch_vrfy', 'arch_tars', "cleanup", 'prepatmiodaobs', 'atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', 'prepoceanobs', 'marineanlinit', 'marineanlletkf', 'marinebmat', 'marineanlvar', 'ocnanalecen', 'marineanlchkpt', 'marineanlfinal', 'ocnanalvrfy', - 'earc', 'ecen', 'echgres', 'ediag', 'efcs', + 'earc_vrfy', 'earc_tars', 'ecen', 'echgres', 'ediag', 'efcs', 'eobs', 'eomg', 'epos', 'esfc', 'eupd', 'atmensanlinit', 'atmensanlobs', 'atmensanlsol', 'atmensanlletkf', 'atmensanlfv3inc', 'atmensanlfinal', 'aeroanlinit', 'aeroanlvar', 'aeroanlfinal', 'aeroanlgenb', From 8321fcb1c427dfc3baa56ee2555d1da345b8245f Mon Sep 17 00:00:00 2001 From: Jeffrey Whitaker Date: Tue, 4 Feb 2025 06:20:03 -0700 Subject: [PATCH 4/4] Fix ocean restarts when cold starting with DOIAU=YES (#3278) Fixes logic in forecast_predet.sh so that ocean restarts are written correctly when DOIAU="YES" for a cold-started experiment. Note: there are currently no CI tests that cover this. Resolves #3277 --- ush/forecast_predet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index e08b84d932..50d26f14fa 100755 --- a/ush/forecast_predet.sh +++ b/ush/forecast_predet.sh @@ -728,7 +728,7 @@ CMEPS_predet(){ CMEPS_RESTART_FH=("${FHMAX}") fi else - if [[ "${DOIAU:-NO}" == "YES" ]]; then + if [[ "${DOIAU:-NO}" == "YES" ]] && [[ "${warm_start}" == ".true." ]] ; then local restart_interval_start=$(( cmeps_restart_interval + half_window )) local restart_interval_end=$(( FHMAX + half_window )) else