From bc69895964febd1e841df7805e424426956a43c1 Mon Sep 17 00:00:00 2001 From: RussTreadon-NOAA <26926959+RussTreadon-NOAA@users.noreply.github.com> Date: Tue, 25 Nov 2025 09:44:37 -0500 Subject: [PATCH 01/27] Extend GDASApp to run atm JEDI EnVar DA with GSI EnKF (#4236) This contains changes needed to run JEDI atmospheric variational DA with a GSI-based EnKF ensemble. This configuration is currently being used in the near realtime global parallel running on WCOSS2. The changes in this PR do not alter the behavior of GDASApp ctests or g-w CI. --- .github/CODEOWNERS | 3 +- .gitignore | 3 +- dev/ci/cases/pr/C96C48_ufsgsi_hybatmDA.yaml | 31 +++ .../cases/yamls/gcafs_cycled_defaults_ci.yaml | 1 + .../cases/yamls/ufs_hybatmDA_defaults.ci.yaml | 4 + .../yamls/ufsgsi_hybatmDA_defaults.ci.yaml | 32 +++ dev/ci/gitlab-ci-hosts.yml | 4 +- dev/jobs/prep.sh | 60 ++++- dev/jobs/prepatmiodaobs.sh | 18 -- dev/jobs/prepobsaero.sh | 20 -- dev/parm/config/gcafs/config.base.j2 | 2 + dev/parm/config/gcafs/config.prep.j2 | 1 + dev/parm/config/gcafs/config.prepatmiodaobs | 1 - dev/parm/config/gcafs/config.prepobsaero | 17 -- dev/parm/config/gcafs/config.resources | 29 +- dev/parm/config/gcafs/yaml/defaults.yaml | 7 - dev/parm/config/gfs/config.atmanl.j2 | 13 +- dev/parm/config/gfs/config.base.j2 | 12 + dev/parm/config/gfs/config.com | 5 +- dev/parm/config/gfs/config.esfc | 4 +- .../gfs/{config.prep => config.prep.j2} | 7 + dev/parm/config/gfs/config.prepatmiodaobs | 11 - dev/parm/config/gfs/config.prepobsaero | 17 -- dev/parm/config/gfs/config.resources | 19 +- dev/workflow/applications/gcafs_cycled.py | 4 +- dev/workflow/applications/gfs_cycled.py | 15 +- dev/workflow/build_compute.py | 6 - dev/workflow/hosts/awspw.yaml | 1 + dev/workflow/hosts/azurepw.yaml | 1 + dev/workflow/hosts/container.yaml | 1 + dev/workflow/hosts/gaeac5.yaml | 1 + dev/workflow/hosts/gaeac6.yaml | 1 + dev/workflow/hosts/googlepw.yaml | 1 + dev/workflow/hosts/hera.yaml | 1 + dev/workflow/hosts/hercules.yaml | 1 + dev/workflow/hosts/orion.yaml | 1 + dev/workflow/hosts/ursa.yaml | 1 + dev/workflow/hosts/wcoss2.yaml | 1 + dev/workflow/rocoto/gcafs_tasks.py | 106 ++++---- dev/workflow/rocoto/gfs_tasks.py | 81 ++---- dev/workflow/rocoto/tasks.py | 4 +- env/GAEAC5.env | 4 - env/GAEAC6.env | 6 +- env/HERA.env | 5 - env/HERCULES.env | 4 - env/ORION.env | 5 - env/URSA.env | 5 - env/WCOSS2.env | 5 - jobs/JGLOBAL_ARCHIVE_TARS | 1 + jobs/JGLOBAL_ATM_PREP_IODA_OBS | 38 --- jobs/JGLOBAL_PREP_OBS_AERO | 45 ---- parm/archive/enkf.yaml.j2 | 6 +- parm/archive/gdas.yaml.j2 | 12 +- parm/archive/gdas_restarta.yaml.j2 | 5 +- parm/archive/gfs_arcdir.yaml.j2 | 12 +- parm/archive/gfs_netcdfa.yaml.j2 | 7 +- parm/post/upp.yaml | 5 + parm/stage/analysis.yaml.j2 | 10 + scripts/exglobal_archive_tars.py | 2 +- scripts/exglobal_atmos_sfcanl.sh | 9 +- scripts/exglobal_diag.sh | 8 +- scripts/exglobal_prep_obs_aero.py | 27 -- scripts/exglobal_stage_ic.py | 6 +- sorc/build_compute.sh | 29 -- sorc/gdas.cd | 2 +- sorc/link_workflow.sh | 13 +- ush/forecast_postdet.sh | 10 +- ush/getioda.sh | 67 +++++ ush/parsing_model_configure_FV3.sh | 2 +- ush/python/pygfs/task/aero_prepobs.py | 250 ------------------ ush/python/pygfs/task/atm_analysis.py | 4 + versions/run.wcoss2.ver | 2 +- 72 files changed, 421 insertions(+), 733 deletions(-) create mode 100644 dev/ci/cases/pr/C96C48_ufsgsi_hybatmDA.yaml create mode 100644 dev/ci/cases/yamls/ufsgsi_hybatmDA_defaults.ci.yaml delete mode 100755 dev/jobs/prepatmiodaobs.sh delete mode 100755 dev/jobs/prepobsaero.sh create mode 120000 dev/parm/config/gcafs/config.prep.j2 delete mode 120000 dev/parm/config/gcafs/config.prepatmiodaobs delete mode 100644 dev/parm/config/gcafs/config.prepobsaero rename dev/parm/config/gfs/{config.prep => config.prep.j2} (88%) delete mode 100644 dev/parm/config/gfs/config.prepatmiodaobs delete mode 100644 dev/parm/config/gfs/config.prepobsaero delete mode 100755 jobs/JGLOBAL_ATM_PREP_IODA_OBS delete mode 100755 jobs/JGLOBAL_PREP_OBS_AERO delete mode 100755 scripts/exglobal_prep_obs_aero.py create mode 100755 ush/getioda.sh delete mode 100644 ush/python/pygfs/task/aero_prepobs.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 19d3ace9b40..69c6f7499cc 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -74,7 +74,6 @@ jobs/JGLOBAL_MARINE_* @guillaumevernieres @AndrewEichmann-NOAA jobs/JGLOBAL_OCEANICE_PRODUCTS @JesseMeng-NOAA @ChristopherHill-NOAA jobs/JGLOBAL_OFFLINE_ATMOS_ANALYSIS @CoryMartin-NOAA jobs/JGLOBAL_PREP_EMISSIONS @bbakernoaa -jobs/JGLOBAL_PREP_OBS_AERO @CoryMartin-NOAA jobs/JGLOBAL_PREP_OCEAN_OBS @guillaumevernieres @AndrewEichmann-NOAA jobs/JGLOBAL_*SNOW* @jiaruidong2017 jobs/JGLOBAL_STAGE_IC @DavidHuber-NOAA @aerorahul @@ -161,6 +160,7 @@ ush/gaussian_sfcanl.sh @BrianCurtis-NOAA ush/getdump.sh @DavidHuber-NOAA @aerorahul ush/getges.sh @DavidHuber-NOAA @aerorahul ush/getgfsnctime @CoryMartin-NOAA +ush/getioda.sh @nicholasesposito @CoryMartin-NOAA @RussTreadon-NOAA ush/getncdimlen @CoryMartin-NOAA ush/gfs_bfr2gpk.sh @BoCui-NOAA ush/gfs_bufr.sh @BoCui-NOAA @@ -209,7 +209,6 @@ ush/python/pygfs/task/__init__.py @aerorahul ush/python/pygfs/task/aero_analysis.py @DavidNew-NOAA @CoryMartin-NOAA ush/python/pygfs/task/aero_bmatrix.py @DavidNew-NOAA @CoryMartin-NOAA ush/python/pygfs/task/aero_emissions.py @bbakernoaa -ush/python/pygfs/task/aero_prepobs.py @CoryMartin-NOAA ush/python/pygfs/task/analysis.py @DavidNew-NOAA @RussTreadon-NOAA ush/python/pygfs/task/analysis_stats.py @CoryMartin-NOAA @DavidNew-NOAA ush/python/pygfs/task/archive.py @DavidHuber-NOAA diff --git a/.gitignore b/.gitignore index e486214ecce..ac94c46ff30 100644 --- a/.gitignore +++ b/.gitignore @@ -169,11 +169,11 @@ ush/fv3gfs_make_orog.sh ush/global_chgres.sh ush/global_chgres_driver.sh ush/global_cycle_driver.sh +ush/gsi_satbias2ioda_all.sh ush/jediinc2fv3.py ush/imsfv3_scf2ioda.py ush/bufr_snocvr_snomad.py ush/atparse.bash -ush/run_bufr2ioda.py ush/bufr2ioda_insitu* ush/python/gsincdiag_to_ioda ush/python/ufsda @@ -181,6 +181,7 @@ ush/python/pyiodaconv ush/python/soca ush/python/gen_bufr2ioda_json.py ush/python/gen_bufr2ioda_yaml.py +ush/python/run_bufr2ioda.py ush/spoc # ush log file ush/fetch-fix-data.log diff --git a/dev/ci/cases/pr/C96C48_ufsgsi_hybatmDA.yaml b/dev/ci/cases/pr/C96C48_ufsgsi_hybatmDA.yaml new file mode 100644 index 00000000000..14cc30db214 --- /dev/null +++ b/dev/ci/cases/pr/C96C48_ufsgsi_hybatmDA.yaml @@ -0,0 +1,31 @@ +experiment: + net: gfs + mode: cycled + pslot: {{ 'pslot' | getenv }} + app: ATM + resdetatmos: 96 + resensatmos: 48 + comroot: {{ 'RUNTESTS' | getenv }}/COMROOT + expdir: {{ 'RUNTESTS' | getenv }}/EXPDIR + icsdir: {{ 'ICSDIR_ROOT' | getenv }}/C96C48/20250808 + idate: 2024022318 + edate: 2024022406 + nens: 2 + interval: 24 + start: warm + yaml: {{ HOMEgfs }}/dev/ci/cases/yamls/ufsgsi_hybatmDA_defaults.ci.yaml + +skip_ci_on_hosts: + - gaeac5 + - gaeac6 + - orion + - hercules + - awsepicglobalworkflow + +workflow: + engine: rocoto + rocoto: + maxtries: 2 + cyclethrottle: 3 + taskthrottle: 25 + verbosity: 2 diff --git a/dev/ci/cases/yamls/gcafs_cycled_defaults_ci.yaml b/dev/ci/cases/yamls/gcafs_cycled_defaults_ci.yaml index a344a12d16d..8b6fa75db3a 100644 --- a/dev/ci/cases/yamls/gcafs_cycled_defaults_ci.yaml +++ b/dev/ci/cases/yamls/gcafs_cycled_defaults_ci.yaml @@ -3,3 +3,4 @@ defaults: base: DO_TEST_MODE: "NO" AERO_ANL_RUNS: "gcdas" + USE_IODADIR: "YES" diff --git a/dev/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml b/dev/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml index 045a1bc8a4a..bdcc3d90bec 100644 --- a/dev/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml +++ b/dev/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml @@ -5,6 +5,8 @@ base: DO_JEDIATMVAR: "YES" DO_JEDIATMENS: "YES" DO_TEST_MODE: "NO" + CASE_ANL: "C48" + USE_IODADIR: "YES" atmanl: LAYOUT_X_ATMANL: 4 LAYOUT_Y_ATMANL: 4 @@ -23,5 +25,7 @@ esfc: DONST: "NO" nsst: NST_MODEL: "1" +prepatmiodaobs: + DO_CONVERT_IODA: "YES" sfcanl: DONST: "NO" diff --git a/dev/ci/cases/yamls/ufsgsi_hybatmDA_defaults.ci.yaml b/dev/ci/cases/yamls/ufsgsi_hybatmDA_defaults.ci.yaml new file mode 100644 index 00000000000..ab813714613 --- /dev/null +++ b/dev/ci/cases/yamls/ufsgsi_hybatmDA_defaults.ci.yaml @@ -0,0 +1,32 @@ +defaults: + !INC {{ HOMEgfs }}/dev/parm/config/gfs/yaml/defaults.yaml +base: + DOIAU: "NO" + DO_JEDIATMVAR: "YES" + DO_JEDIATMENS: "NO" + DO_TEST_MODE: "NO" + CASE_ANL: "C48" + CASE_HIST: "C96" + DONST: "NO" + USE_IODADIR: "YES" +atmanl: + LAYOUT_X_ATMANL: 4 + LAYOUT_Y_ATMANL: 4 + OBS_LIST_YAML: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/atm_obs_list_ufs_hybatmDA.yaml.j2" + VAR_JEDI_TEST_YAML: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jedi-test_3dvar_ufs_hybatmDA.yaml.j2" + FV3INC_JEDI_TEST_YAML: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jedi-test_3dvar-fv3inc_ufs_hybatmDA.yaml.j2" + NUMBER_OUTER_LOOPS: 2 + NINNER_LOOP1: 2 + NINNER_LOOP2: 4 +esfc: + DONST: "NO" +nsst: + NST_MODEL: "1" +prep: + COPY_BIASCOR_SOURCE: "NO" + COPY_BIASCOR_STATIC: "YES" + CONVERT_BIASCOR: "YES" +prepatmiodaobs: + DO_CONVERT_IODA: "YES" +sfcanl: + DONST: "NO" diff --git a/dev/ci/gitlab-ci-hosts.yml b/dev/ci/gitlab-ci-hosts.yml index 6542fd72e09..97001d7cf2f 100644 --- a/dev/ci/gitlab-ci-hosts.yml +++ b/dev/ci/gitlab-ci-hosts.yml @@ -22,7 +22,7 @@ # Template matrices for case lists .hera_cases_matrix: &hera_cases - - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48_hybatmsnowDA", "C96C48_hybatmsoilDA", "C96C48_ufs_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96_gcafs_cycled", "C96_gcafs_cycled_noDA", "C96mx100_S2S"] + - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48_hybatmsnowDA", "C96C48_hybatmsoilDA", "C96C48_ufsgsi_hybatmDA", "C96C48_ufs_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96_gcafs_cycled", "C96_gcafs_cycled_noDA", "C96mx100_S2S"] .gaeac6_cases_matrix: &gaeac6_cases - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48_hybatmsnowDA", "C96C48_hybatmsoilDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96_gcafs_cycled", "C96_gcafs_cycled_noDA", "C96mx100_S2S"] @@ -34,7 +34,7 @@ - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96mx100_S2S"] .ursa_cases_matrix: &ursa_cases - - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48_hybatmsnowDA", "C96C48_hybatmsoilDA", "C96C48_ufs_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96mx100_S2S"] + - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48_hybatmsnowDA", "C96C48_hybatmsoilDA", "C96C48_ufsgsi_hybatmDA", "C96C48_ufs_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96mx100_S2S"] # Host: Hera - Standard Cases setup_experiments-hera: diff --git a/dev/jobs/prep.sh b/dev/jobs/prep.sh index 4ab3c6795ee..e47b055dc24 100755 --- a/dev/jobs/prep.sh +++ b/dev/jobs/prep.sh @@ -32,15 +32,32 @@ RUN=${RUN_local} YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ COMIN_OBS:COM_OBS_TMPL \ COMOUT_OBS:COM_OBS_TMPL \ COMINobsproc:COM_OBSPROC_TMPL \ - COMIN_TCVITAL:COM_TCVITAL_TMPL + COMINobsforge:COM_OBSFORGE_TMPL \ + COMIN_TCVITAL:COM_TCVITAL_TMPL \ + COMOUT_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ COMOUT_OBS_PREV:COM_OBS_TMPL \ - COMINobsproc_PREV:COM_OBSPROC_TMPL + COMINobsproc_PREV:COM_OBSPROC_TMPL \ + COMOUT_ATMOS_ANALYSIS_PREV:COM_ATMOS_ANALYSIS_TMPL mkdir -p "${COMOUT_OBS}" ############################################################### +# Copy IODA files to ROTDIR +if [[ ${USE_IODADIR:-"NO"} == "YES" ]]; then + "${HOMEgfs}/ush/getioda.sh" "${PDY}" "${cyc}" "${RUN_local}" "${COMINobsforge}" "${COMOUT_OBS}" + status=$? + if [[ ${status} -ne 0 ]]; then + exit "${status}" + fi +fi + +if [[ "${RUN_local}" == "gcdas" ]]; then + echo "GCDAS only needs IODA files; exiting prep.sh" + exit 0 +fi + # Copy dump files to ROTDIR "${HOMEgfs}/ush/getdump.sh" "${PDY}" "${cyc}" "${RUN_local}" "${COMINobsproc}" "${COMOUT_OBS}" status=$? @@ -95,6 +112,28 @@ else cpfs "${COMINobsproc}/${RUN_local}.t${cyc}z.syndata.tcvitals.tm00" "${COMOUT_OBS}/" fi + +############################################################### +# If requested, copy bias correction files from source or stait to analysis directories +# TODO: remove this when JEDI ATM can cycle bias correction coefficents +if [[ ${RUN} == "gdas" && ${COPY_BIASCOR_SOURCE:-"NO"} == "YES" ]]; then + for file in abias abias_pc abias_air; do + if [[ -s "${SOURCE_BIASCOR}/${file}.${GDUMP}.${gPDY}${gcyc}" ]]; then + cpreq "${SOURCE_BIASCOR}/${file}.${GDUMP}.${gPDY}${gcyc}" "${COMOUT_ATMOS_ANALYSIS_PREV}/${GDUMP}.t${gcyc}z.${file}" + cpreq "${SOURCE_BIASCOR}/${file}.${GDUMP}.${gPDY}${gcyc}" "${COMOUT_ATMOS_ANALYSIS_PREV}/${GDUMP}.t${gcyc}z.${file}.txt" + fi + done +fi +if [[ ${RUN} == "gdas" && ${COPY_BIASCOR_STATIC:-"NO"} == "YES" ]]; then + for file in abias abias_pc abias_air; do + if [[ -s "${COMOUT_ATMOS_ANALYSIS_PREV}/${GDUMP}.t${gcyc}z.${file}.txt" ]]; then + mkdir -p "${COMOUT_ATMOS_ANALYSIS}" + cpreq "${COMOUT_ATMOS_ANALYSIS_PREV}/${GDUMP}.t${gcyc}z.${file}.txt" "${COMOUT_ATMOS_ANALYSIS}/${GDUMP}.t${cyc}z.${file}.txt" + fi + done +fi + + ############################################################### # Generate prepbufr files from dumps and prior gdas guess rm -f "${COMOUT_OBS}/${OPREFIX}prepbufr" @@ -160,6 +199,23 @@ if [[ ${err} -ne 0 ]]; then err_exit "Failed to obtain/create ${files}, ABORT!" fi +################################################################################ +# If requested, create radiance bias correction files for JEDI +if [[ ${RUN} == "gdas" && ${CONVERT_BIASCOR:-"NO"} == "YES" ]]; then + cd "${DATAROOT}" || true + "${HOMEgfs}/ush/gsi_satbias2ioda_all.sh" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "gsi_satbias2ioda failed, ABORT!" + fi + + # Remove temporary working directory + cd "${DATAROOT}" || true + if [[ "${KEEPDATA}" == "NO" ]]; then + rm -rf "${DATA}" + fi +fi + ################################################################################ # Exit out cleanly diff --git a/dev/jobs/prepatmiodaobs.sh b/dev/jobs/prepatmiodaobs.sh deleted file mode 100755 index 4633c81b060..00000000000 --- a/dev/jobs/prepatmiodaobs.sh +++ /dev/null @@ -1,18 +0,0 @@ -#! /usr/bin/env bash - -############################################################### -# Source UFSDA workflow modules -source "${HOMEgfs}/dev/ush/load_modules.sh" ufsda -status=$? -if [[ ${status} -ne 0 ]]; then - exit "${status}" -fi - -export job="prepatmobs" -export jobid="${job}.$$" - -############################################################### -# Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATM_PREP_IODA_OBS" -status=$? -exit "${status}" diff --git a/dev/jobs/prepobsaero.sh b/dev/jobs/prepobsaero.sh deleted file mode 100755 index 1996172958f..00000000000 --- a/dev/jobs/prepobsaero.sh +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/bin/env bash - -set -x - -############################################################### -# Source UFSDA workflow modules -source "${HOMEgfs}/dev/ush/load_modules.sh" ufsda -status=$? -if [[ ${status} -ne 0 ]]; then - exit "${status}" -fi - -export job="prepobsaero" -export jobid="${job}.$$" - -############################################################### -# Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_PREP_OBS_AERO" -status=$? -exit "${status}" diff --git a/dev/parm/config/gcafs/config.base.j2 b/dev/parm/config/gcafs/config.base.j2 index 503a9e03bd6..a4c1e8b72fc 100644 --- a/dev/parm/config/gcafs/config.base.j2 +++ b/dev/parm/config/gcafs/config.base.j2 @@ -51,6 +51,8 @@ export PACKAGEROOT="{{ PACKAGEROOT }}" # TODO: set via prod_envir in Ops export COMROOT="{{ COMROOT }}" # TODO: set via prod_envir in Ops export COMINsyn="{{ COMINsyn }}" export DMPDIR="{{ DMPDIR }}" +export IODADIR="{{ IODADIR }}" +export USE_IODADIR="{{ USE_IODADIR }}" # Gempak from external models # Default locations are to dummy locations for testing diff --git a/dev/parm/config/gcafs/config.prep.j2 b/dev/parm/config/gcafs/config.prep.j2 new file mode 120000 index 00000000000..c06426da0f3 --- /dev/null +++ b/dev/parm/config/gcafs/config.prep.j2 @@ -0,0 +1 @@ +../gfs/config.prep.j2 \ No newline at end of file diff --git a/dev/parm/config/gcafs/config.prepatmiodaobs b/dev/parm/config/gcafs/config.prepatmiodaobs deleted file mode 120000 index 4a93cd3b05d..00000000000 --- a/dev/parm/config/gcafs/config.prepatmiodaobs +++ /dev/null @@ -1 +0,0 @@ -../gfs/config.prepatmiodaobs \ No newline at end of file diff --git a/dev/parm/config/gcafs/config.prepobsaero b/dev/parm/config/gcafs/config.prepobsaero deleted file mode 100644 index f70138991c8..00000000000 --- a/dev/parm/config/gcafs/config.prepobsaero +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -x - -########## config.prepobsaero ########## -# Prepare and thin/superob aerosol observations - -echo "BEGIN: config.prepobsaero" - -# Get task specific resources -source "${EXPDIR}/config.resources" prepobsaero - -export OBSPROCYAML="${PARMgfs}/gdas/aero/obs/lists/gdas_aero_obsproc.yaml.j2" -export OBSPROCEXE="${EXECgfs}/gdas_obsprovider2ioda.x" -export VIIRS_DATA_DIR="/scratch2/NCEPDEV/stmp3/Yaping.Wang/VIIRS/AWS/" -export SENSORS="npp,n20" - - -echo "END: config.prepaeroobs" diff --git a/dev/parm/config/gcafs/config.resources b/dev/parm/config/gcafs/config.resources index 1fee7c60684..5308ac6f8fd 100644 --- a/dev/parm/config/gcafs/config.resources +++ b/dev/parm/config/gcafs/config.resources @@ -12,12 +12,12 @@ if (( $# != 1 )); then echo "Must specify an input task argument to set resource variables!" echo "argument can be any one of the following:" echo "stage_ic aerosol_init fetch" - echo "prep prepatmiodaobs" + echo "prep" echo "atmanlinit atmanlvar atmanlfv3inc atmanlfinal" echo "atmensanlinit atmensanlobs atmensanlsol atmensanlletkf atmensanlfv3inc atmensanlfinal ecen_fv3jedi analcalc_fv3jedi" echo "snowanl esnowanl" echo "prep_emissions" - echo "prepobsaero aeroanlinit aeroanlvar aeroanlfinal aeroanlgenb" + echo "aeroanlinit aeroanlvar aeroanlfinal aeroanlgenb" echo "offlineanl" echo "anal sfcanl analcalc analdiag anlstat fcst echgres" echo "upp atmos_products" @@ -28,7 +28,7 @@ if (( $# != 1 )); then echo "waveinit waveprep wavepostsbs wavepostbndpnt wavepostbndpntbll wavepostpnt" echo "wavegempak waveawipsbulls waveawipsgridded" echo "postsnd awips gempak npoess" - echo "marineanlinit prepoceanobs marinebmat marineanlvar marineanlecen marineanalletkf marineanlchkpt marineanlfinal ocnanalvrfy" + echo "marineanlinit marinebmat marineanlvar marineanlecen marineanalletkf marineanlchkpt marineanlfinal ocnanalvrfy" exit 1 fi @@ -147,13 +147,6 @@ case ${step} in memory="${mem_node_max}" ;; - "prepatmiodaobs") - walltime="00:30:00" - ntasks=1 - threads_per_task=1 - tasks_per_node=$(( max_tasks_per_node / threads_per_task )) - ;; - "aerosol_init") walltime="00:05:00" ntasks=1 @@ -370,14 +363,6 @@ case ${step} in tasks_per_node=$(( max_tasks_per_node / threads_per_task )) ;; - "prepobsaero") - walltime="00:30:00" - ntasks=1 - threads_per_task=1 - tasks_per_node=1 - memory="96GB" - ;; - "aeroanlinit") # below lines are for creating JEDI YAML case "${CASE}" in @@ -534,14 +519,6 @@ case ${step} in memory="24GB" ;; - "prepoceanobs") - walltime="00:10:00" - ntasks=1 - threads_per_task=1 - tasks_per_node=${max_tasks_per_node} - memory="48GB" - ;; - "marinebmat") npes=16 ntasks=16 diff --git a/dev/parm/config/gcafs/yaml/defaults.yaml b/dev/parm/config/gcafs/yaml/defaults.yaml index 62e4c78ac89..38f1de65dcc 100644 --- a/dev/parm/config/gcafs/yaml/defaults.yaml +++ b/dev/parm/config/gcafs/yaml/defaults.yaml @@ -83,13 +83,6 @@ marineanlletkf: SOCA_ANL_GEOM: "${FIXgfs}/gdas/soca/72x35x25/soca" SOCA_OBS_LIST: "${PARMgfs}/gdas/marine/obs/obs_list.yaml.j2" -prepoceanobs: - SOCA_INPUT_FIX_DIR: "${FIXgfs}/gdas/soca/72x35x25/soca" - SOCA_OBS_LIST: "${PARMgfs}/gdas/marine/obs/obs_list.yaml" # TODO: This is also repeated in ocnanal - OBSPREP_YAML: "${PARMgfs}/gdas/marine/obsprep/obsprep_config.yaml" - use_exp_obs: "YES" - dmpdir_exp: "${BASE_DATA}/experimental_obs" - fcst: CHECK_LAND_RESTART_OROG: "YES" diff --git a/dev/parm/config/gfs/config.atmanl.j2 b/dev/parm/config/gfs/config.atmanl.j2 index d0e0e8d0f88..29e7279bd63 100644 --- a/dev/parm/config/gfs/config.atmanl.j2 +++ b/dev/parm/config/gfs/config.atmanl.j2 @@ -19,11 +19,14 @@ export BIAS_FILES_YAML="${PARMgfs}/gdas/atm/atm_bias_files.yaml.j2" export LOCALIZATION_TYPE="bump" -if [[ ${DOHYBVAR} = "YES" ]]; then - # shellcheck disable=SC2153 - export CASE_ANL=${CASE_ENS} -else - export CASE_ANL=${CASE} +export CASE_GSIBEC=${CASE_ANL} +if [[ "${DOHYBVAR}" = "YES" && "${ATMINC_GRID}" = "gaussian" ]]; then + export CASE_GSIBEC=${CASE_HIST} + export CASE_HIST=${CASE_ANL} fi +export NUMBER_OUTER_LOOPS="{{ NUMBER_OUTER_LOOPS | default() }}" +export NINNER_LOOP1="{{ NINNER_LOOP1 | default () }}" +export NINNER_LOOP2="{{ NINNER_LOOP2 | default () }}" + echo "END: config.atmanl" diff --git a/dev/parm/config/gfs/config.base.j2 b/dev/parm/config/gfs/config.base.j2 index caeeb9b9a6c..1b703918fb9 100644 --- a/dev/parm/config/gfs/config.base.j2 +++ b/dev/parm/config/gfs/config.base.j2 @@ -51,6 +51,8 @@ export PACKAGEROOT="{{ PACKAGEROOT }}" # TODO: set via prod_envir in Ops export COMROOT="{{ COMROOT }}" # TODO: set via prod_envir in Ops export COMINsyn="{{ COMINsyn }}" export DMPDIR="{{ DMPDIR }}" +export IODADIR="{{ IODADIR }}" +export USE_IODADIR="{{ USE_IODADIR }}" # Gempak from external models # Default locations are to dummy locations for testing @@ -205,6 +207,7 @@ export OPS_RES="C768" # Do not change # TODO: Why is this needed and where is it export LEVS=128 export CASE="{{ CASE_CTL }}" export CASE_ENS="{{ CASE_ENS }}" +export CASE_ANL="{{ CASE_ANL | default('${CASE}') }}" export CASE_HIST="{{ CASE_HIST | default('${CASE}') }}" export OCNRES="{{ OCNRES }}" export ICERES="${OCNRES}" @@ -526,4 +529,13 @@ export OFFSET_START_HOUR=0 # Number of regional collectives to create soundings for export NUM_SND_COLLECTIVES=${NUM_SND_COLLECTIVES:-9} +# Set JEDI atmospheric DA increment type +if [[ "${DO_JEDIATMVAR}" == "YES" ]]; then + if [[ "${DO_JEDIATMENS}" == "YES" ]]; then + export ATMINC_GRID="cubed_sphere_grid" + else + export ATMINC_GRID="gaussian" + fi +fi + echo "END: config.base" diff --git a/dev/parm/config/gfs/config.com b/dev/parm/config/gfs/config.com index bba449b0db3..05615f256b5 100644 --- a/dev/parm/config/gfs/config.com +++ b/dev/parm/config/gfs/config.com @@ -37,22 +37,23 @@ echo "BEGIN: config.com" # shellcheck disable=SC2034 if [[ "${RUN_ENVIR:-emc}" == "nco" ]]; then COM_OBSPROC_TMPL=$(compath.py "${envir}/obsproc/${obsproc_ver}")'/${RUN}.${YMD}/${HH}/atmos' + COM_OBSFORGE_TMPL=$(compath.py "${envir}/obsforge/${obsforge_ver}")'/${RUN}.${YMD}/${HH}/' COM_RTOFS_TMPL=$(compath.py "${envir}/rtofs/${rtofs_ver}") COM_TCVITAL_TMPL=$(compath.py "${envir}/gfs/${gfs_ver}")'/${RUN}.${YMD}/${HH}/atmos' else COM_OBSPROC_TMPL='${DMPDIR}/${RUN}${DUMP_SUFFIX}.${YMD}/${HH}/atmos' + COM_OBSFORGE_TMPL='${IODADIR}/${RUN}${DUMP_SUFFIX}.${YMD}/${HH}' COM_RTOFS_TMPL='${DMPDIR}' COM_TCVITAL_TMPL='${DMPDIR}/${RUN}.${YMD}/${HH}/atmos' fi declare -rx COM_OBS_TMPL='${ROTDIR}/${RUN}.${YMD}/${HH}/obs' -declare -rx COM_OBSPROC_TMPL COM_RTOFS_TMPL +declare -rx COM_OBSPROC_TMPL COM_RTOFS_TMPL COM_OBSFORGE_TMPL COM_BASE='${ROTDIR}/${RUN}.${YMD}/${HH}/${MEMDIR}' declare -rx COM_TOP_TMPL='${ROTDIR}/${RUN}.${YMD}/${HH}' declare -rx COM_CONF_TMPL=${COM_BASE}'/conf' -declare -rx COM_OBS_JEDI=${COM_BASE}'/obs_jedi' declare -rx COM_ATMOS_INPUT_TMPL=${COM_BASE}'/model/atmos/input' declare -rx COM_ATMOS_RESTART_TMPL=${COM_BASE}'/model/atmos/restart' diff --git a/dev/parm/config/gfs/config.esfc b/dev/parm/config/gfs/config.esfc index 156649ace36..0c35240dc31 100644 --- a/dev/parm/config/gfs/config.esfc +++ b/dev/parm/config/gfs/config.esfc @@ -21,8 +21,8 @@ if [[ ${DOIAU_ENKF} = "YES" ]]; then export DOSFCANL_ENKF="NO" fi -# Turn off NST in JEDIATMENS -if [[ "${DO_JEDIATMENS}" == "YES" ]]; then +# Turn off NST in JEDIATMENS or JEDIATMVAR +if [[ "${DO_JEDIATMENS}" == "YES" || "${DO_JEDIATMVAR}" == "YES" ]]; then export DONST="NO" fi diff --git a/dev/parm/config/gfs/config.prep b/dev/parm/config/gfs/config.prep.j2 similarity index 88% rename from dev/parm/config/gfs/config.prep rename to dev/parm/config/gfs/config.prep.j2 index c10e5012e76..a8b8f0c619a 100644 --- a/dev/parm/config/gfs/config.prep +++ b/dev/parm/config/gfs/config.prep.j2 @@ -65,4 +65,11 @@ else export DTYPS_nsst='sfcshp dbuoyb mbuoyb tesac bathy trkob' fi +# Set flags to optionally use external bias correction files +# TODO: remove when JEDI can cycle bias correcdtion files +export SOURCE_BIASCOR="{{ SOURCE_BIASCOR }}" +export COPY_BIASCOR_SOURCE="{{ COPY_BIASCOR_SOURCE }}" +export COPY_BIASCOR_STATIC="{{ COPY_BIASCOR_STATIC }}" +export CONVERT_BIASCOR="{{ CONVERT_BIASCOR }}" + echo "END: config.prep" diff --git a/dev/parm/config/gfs/config.prepatmiodaobs b/dev/parm/config/gfs/config.prepatmiodaobs deleted file mode 100644 index e29cf67b070..00000000000 --- a/dev/parm/config/gfs/config.prepatmiodaobs +++ /dev/null @@ -1,11 +0,0 @@ -#! /usr/bin/env bash - -########## config.prepatmiodaobs ########## -# Atm Obs Prep specific - -echo "BEGIN: config.prepatmiodaobs" - -# Get task specific resources -. "${EXPDIR}/config.resources" prepatmiodaobs - -echo "END: config.prepatmiodaobs" diff --git a/dev/parm/config/gfs/config.prepobsaero b/dev/parm/config/gfs/config.prepobsaero deleted file mode 100644 index 237238809e3..00000000000 --- a/dev/parm/config/gfs/config.prepobsaero +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -x - -########## config.prepobsaero ########## -# Prepare and thin/superob aerosol observations - -echo "BEGIN: config.prepobsaero" - -# Get task specific resources -source "${EXPDIR}/config.resources" prepobsaero - -export OBSPROCYAML="${PARMgfs}/gdas/aero/obs/lists/gdas_aero_obsproc.yaml.j2" -export OBSPROCEXE="${EXECgfs}/gdas_ioda_obsprovider2ioda.x" -export VIIRS_DATA_DIR="/scratch2/NCEPDEV/stmp3/Yaping.Wang/VIIRS/AWS/" -export SENSORS="npp,n20" - - -echo "END: config.prepaeroobs" diff --git a/dev/parm/config/gfs/config.resources b/dev/parm/config/gfs/config.resources index 2f3829622eb..1c8ca9d24a1 100644 --- a/dev/parm/config/gfs/config.resources +++ b/dev/parm/config/gfs/config.resources @@ -12,11 +12,11 @@ if (( $# != 1 )); then echo "Must specify an input task argument to set resource variables!" echo "argument can be any one of the following:" echo "stage_ic aerosol_init fetch" - echo "prep prep_sfc prepatmiodaobs" + echo "prep prep_sfc" echo "atmanlinit atmanlvar atmanlfv3inc atmanlfinal" echo "atmensanlinit atmensanlobs atmensanlsol atmensanlletkf atmensanlfv3inc atmensanlfinal ecen_fv3jedi analcalc_fv3jedi" echo "snowanl esnowanl" - echo "prepobsaero aeroanlinit aeroanlvar aeroanlfinal aeroanlgenb" + echo "aeroanlinit aeroanlvar aeroanlfinal aeroanlgenb" echo "anal sfcanl analcalc analdiag anlstat fcst echgres" echo "upp atmos_products" echo "tracker genesis genesis_fsu" @@ -116,13 +116,6 @@ case ${step} in memory="${mem_node_max}" ;; - "prepatmiodaobs") - walltime="00:30:00" - ntasks=1 - threads_per_task=1 - tasks_per_node=$(( max_tasks_per_node / threads_per_task )) - ;; - "aerosol_init") walltime="00:05:00" ntasks=1 @@ -340,14 +333,6 @@ case ${step} in tasks_per_node=$(( max_tasks_per_node / threads_per_task )) ;; - "prepobsaero") - walltime="00:30:00" - ntasks=1 - threads_per_task=1 - tasks_per_node=1 - memory="96GB" - ;; - "aeroanlinit") # below lines are for creating JEDI YAML case "${CASE}" in diff --git a/dev/workflow/applications/gcafs_cycled.py b/dev/workflow/applications/gcafs_cycled.py index e205fe1709f..7a96b0437aa 100644 --- a/dev/workflow/applications/gcafs_cycled.py +++ b/dev/workflow/applications/gcafs_cycled.py @@ -135,7 +135,7 @@ def _get_app_configs(self, run): if options['do_aero_anl']: configs += ['aeroanlgenb', 'aeroanlinit', 'aeroanlvar', 'aeroanlfinal'] - configs += ['prepobsaero'] + configs += ['prep'] if options['do_anlstat']: configs += ['anlstat'] @@ -203,7 +203,7 @@ def get_task_names(self): if options['do_aero_anl']: task_names[run] += ['aeroanlgenb'] task_names[run] += ['aeroanlinit', 'aeroanlvar', 'aeroanlfinal'] - task_names[run] += ['prepobsaero'] + task_names[run] += ['prep'] if options['do_anlstat']: task_names[run] += ['anlstat'] diff --git a/dev/workflow/applications/gfs_cycled.py b/dev/workflow/applications/gfs_cycled.py index 8a5114c1f82..0d51aed74b4 100644 --- a/dev/workflow/applications/gfs_cycled.py +++ b/dev/workflow/applications/gfs_cycled.py @@ -110,7 +110,10 @@ def _get_app_configs(self, run): configs += ['prep_sfc'] if options['do_jediatmvar']: - configs += ['prepatmiodaobs', 'atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', 'analcalc_fv3jedi'] + if options['do_jediatmens']: + configs += ['atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', 'analcalc_fv3jedi'] + else: + configs += ['atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', 'analcalc'] else: configs += ['anal', 'analdiag', 'analcalc'] @@ -192,8 +195,6 @@ def _get_app_configs(self, run): if options['do_aero_anl']: configs += ['aeroanlgenb', 'aeroanlinit', 'aeroanlvar', 'aeroanlfinal'] - if options['do_prep_obs_aero']: - configs += ['prepobsaero'] if options['do_jedisnowda']: configs += ['snowanl'] @@ -250,7 +251,10 @@ def get_task_names(self): if options['do_prep_sfc']: task_names[run] += ['prep_sfc'] if options['do_jediatmvar']: - task_names[run] += ['prepatmiodaobs', 'atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', 'analcalc_fv3jedi'] + if options['do_jediatmens']: + task_names[run] += ['atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', 'analcalc_fv3jedi'] + else: + task_names[run] += ['atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', 'analcalc'] else: task_names[run] += ['anal', 'analcalc'] @@ -283,9 +287,6 @@ def get_task_names(self): if options['do_aero_anl']: task_names[run] += ['aeroanlinit', 'aeroanlvar', 'aeroanlfinal'] - if options['do_prep_obs_aero']: - task_names[run] += ['prepobsaero'] - # Staging is gdas-specific if run == 'gdas': task_names[run] += ['stage_ic'] diff --git a/dev/workflow/build_compute.py b/dev/workflow/build_compute.py index a1d29f679df..c4a6c985390 100755 --- a/dev/workflow/build_compute.py +++ b/dev/workflow/build_compute.py @@ -185,12 +185,6 @@ def main(*argv): user_yaml_dict = AttrDict(parse_yaml(user_inputs.yaml)) build_specs = get_build_specs(user_yaml_dict, host_specs) - # Temporarily prevent the GDASApp from building on the compute node - # TODO restore the GDASApp when it can be built on compute nodes again and/or 'compute' builds are enabled on head nodes. - # See issue 3933 - if "gdas" in build_specs.build: - build_specs.build.pop("gdas") - systems = user_inputs.systems.split() if "all" not in user_inputs.systems else ["all"] # Determine systems to build diff --git a/dev/workflow/hosts/awspw.yaml b/dev/workflow/hosts/awspw.yaml index 39feb618b12..d3c9cbd9172 100644 --- a/dev/workflow/hosts/awspw.yaml +++ b/dev/workflow/hosts/awspw.yaml @@ -1,4 +1,5 @@ # Paths +IODADIR: '/bucket/dump' DMPDIR: '/bucket/dump' BASE_GIT: '/contrib/git' BASE_DATA: '/bucket/global-workflow-shared-data' diff --git a/dev/workflow/hosts/azurepw.yaml b/dev/workflow/hosts/azurepw.yaml index badc062f880..6b446eab034 100644 --- a/dev/workflow/hosts/azurepw.yaml +++ b/dev/workflow/hosts/azurepw.yaml @@ -1,5 +1,6 @@ # Paths DMPDIR: '' # TODO: This does not yet exist. +IODADIR: '' #TODO: This does not yet exist. BASE_GIT: '' #TODO: This does not yet exist. BASE_DATA: '/bucket/global-workflow-shared-data' BASE_IC: '/bucket/global-workflow-shared-data/ICSDIR' diff --git a/dev/workflow/hosts/container.yaml b/dev/workflow/hosts/container.yaml index cc3d1540356..4868d02d936 100644 --- a/dev/workflow/hosts/container.yaml +++ b/dev/workflow/hosts/container.yaml @@ -1,5 +1,6 @@ # Paths DMPDIR: '/home/${USER}' +IODADIR: '/home/${USER}' BASE_GIT: '' PACKAGEROOT: '' HOMEDIR: '/home/${USER}' diff --git a/dev/workflow/hosts/gaeac5.yaml b/dev/workflow/hosts/gaeac5.yaml index be872943e72..785f0c61149 100644 --- a/dev/workflow/hosts/gaeac5.yaml +++ b/dev/workflow/hosts/gaeac5.yaml @@ -1,5 +1,6 @@ # Paths DMPDIR: '/gpfs/f5/ufs-ard/world-shared/global/glopara/data/dump' +IODADIR: '/gpfs/f5/ufs-ard/world-shared/global/glopara/data/dump' BASE_GIT: '/gpfs/f5/ufs-ard/world-shared/global/glopara/data/git' BASE_DATA: '/gpfs/f5/ufs-ard/world-shared/global/glopara/data' BASE_IC: '/gpfs/f5/ufs-ard/world-shared/global/glopara/data/ICSDIR' diff --git a/dev/workflow/hosts/gaeac6.yaml b/dev/workflow/hosts/gaeac6.yaml index 4a0055208d5..20486fbf38b 100644 --- a/dev/workflow/hosts/gaeac6.yaml +++ b/dev/workflow/hosts/gaeac6.yaml @@ -1,5 +1,6 @@ # Paths DMPDIR: '/gpfs/f6/drsa-precip3/world-shared/role.glopara/dump' +IODADIR: '/gpfs/f6/drsa-precip3/world-shared/role.glopara/dump_ioda' BASE_GIT: '/gpfs/f6/drsa-precip3/world-shared/role.glopara/git' BASE_DATA: '/gpfs/f6/drsa-precip3/world-shared/role.glopara/data' BASE_IC: '/gpfs/f6/drsa-precip3/world-shared/role.glopara/data/ICSDIR' diff --git a/dev/workflow/hosts/googlepw.yaml b/dev/workflow/hosts/googlepw.yaml index 4a0610d7f7d..74c73d2542a 100644 --- a/dev/workflow/hosts/googlepw.yaml +++ b/dev/workflow/hosts/googlepw.yaml @@ -1,6 +1,7 @@ # Paths DMPDIR: '' # TODO: This does not yet exist. +IODADIR: '' #TODO: This does not yet exist. BASE_GIT: '' #TODO: This does not yet exist. BASE_DATA: '/bucket/global-workflow-shared-data' BASE_IC: '/bucket/global-workflow-shared-data/ICSDIR' diff --git a/dev/workflow/hosts/hera.yaml b/dev/workflow/hosts/hera.yaml index 60527625805..1bf18ce67d5 100644 --- a/dev/workflow/hosts/hera.yaml +++ b/dev/workflow/hosts/hera.yaml @@ -1,5 +1,6 @@ # Paths DMPDIR: '/scratch3/NCEPDEV/global/role.glopara/dump' +IODADIR: '/scratch3/NCEPDEV/global/role.glopara/dump_ioda' BASE_GIT: '/scratch3/NCEPDEV/global/role.glopara/git_hera' BASE_DATA: '/scratch3/NCEPDEV/global/role.glopara/data' BASE_IC: '/scratch3/NCEPDEV/global/role.glopara/data/ICSDIR' diff --git a/dev/workflow/hosts/hercules.yaml b/dev/workflow/hosts/hercules.yaml index ce971749e4d..4436589b880 100644 --- a/dev/workflow/hosts/hercules.yaml +++ b/dev/workflow/hosts/hercules.yaml @@ -1,5 +1,6 @@ # Paths DMPDIR: '/work/noaa/rstprod/dump' +IODADIR: '/work/noaa/rstprod/dump_ioda' BASE_GIT: '/work2/noaa/global/role-global/git' BASE_DATA: '/work2/noaa/global/role-global/data' BASE_IC: '/work2/noaa/global/role-global/data/ICSDIR' diff --git a/dev/workflow/hosts/orion.yaml b/dev/workflow/hosts/orion.yaml index caadd3d41e2..ee012819f31 100644 --- a/dev/workflow/hosts/orion.yaml +++ b/dev/workflow/hosts/orion.yaml @@ -1,5 +1,6 @@ # Paths DMPDIR: '/work/noaa/rstprod/dump' +IODADIR: '/work/noaa/rstprod/dump_ioda' BASE_GIT: '/work2/noaa/global/role-global/git' BASE_DATA: '/work2/noaa/global/role-global/data' BASE_IC: '/work2/noaa/global/role-global/data/ICSDIR' diff --git a/dev/workflow/hosts/ursa.yaml b/dev/workflow/hosts/ursa.yaml index 51d42a8bb22..05c2d4bb8ee 100644 --- a/dev/workflow/hosts/ursa.yaml +++ b/dev/workflow/hosts/ursa.yaml @@ -1,5 +1,6 @@ # Paths DMPDIR: '/scratch3/NCEPDEV/global/role.glopara/dump' +IODADIR: '/scratch3/NCEPDEV/global/role.glopara/dump_ioda' BASE_GIT: '/scratch3/NCEPDEV/global/role.glopara/git' BASE_DATA: '/scratch3/NCEPDEV/global/role.glopara/data' BASE_IC: '/scratch3/NCEPDEV/global/role.glopara/data/ICSDIR' diff --git a/dev/workflow/hosts/wcoss2.yaml b/dev/workflow/hosts/wcoss2.yaml index 1b534f7d13e..9f82d8e9e81 100644 --- a/dev/workflow/hosts/wcoss2.yaml +++ b/dev/workflow/hosts/wcoss2.yaml @@ -1,5 +1,6 @@ # Paths DMPDIR: '/lfs/h2/emc/dump/noscrub/dump' +IODADIR: '/lfs/h2/emc/dump/noscrub/dump_ioda' BASE_GIT: '/lfs/h2/emc/global/save/emc.global/git' BASE_DATA: '/lfs/h2/emc/global/noscrub/emc.global/data' BASE_IC: '/lfs/h2/emc/global/noscrub/emc.global/data/ICSDIR' diff --git a/dev/workflow/rocoto/gcafs_tasks.py b/dev/workflow/rocoto/gcafs_tasks.py index 0b13140b06b..4bd63a69f18 100644 --- a/dev/workflow/rocoto/gcafs_tasks.py +++ b/dev/workflow/rocoto/gcafs_tasks.py @@ -110,6 +110,50 @@ def stage_ic(self): return task + def prep(self): + + dump_suffix = self._base["DUMP_SUFFIX"] + iodadir = self._base["IODADIR"] + atm_hist_path = self._template_to_rocoto_cycstring(self._base["COM_ATMOS_HISTORY_TMPL"], {'RUN': 'gcdas'}) + ioda_path = self._template_to_rocoto_cycstring(self._base["COM_OBSFORGE_TMPL"], + {'IODADIR': iodadir, 'DUMP_SUFFIX': dump_suffix}) + + deps = [] + + dep_dict = {'type': 'metatask', 'name': 'gcdas_atmos_prod', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} + deps.append(rocoto.add_dependency(dep_dict)) + data = f'{atm_hist_path}/gcdas.t@Hz.atm.f009.nc' + dep_dict = {'type': 'data', 'data': data, 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} + deps.append(rocoto.add_dependency(dep_dict)) + data = f'{ioda_path}/chem/{self.run}.t@Hz.obsforge_aod_status.log' + dep_dict = {'type': 'data', 'data': data} + deps.append(rocoto.add_dependency(dep_dict)) + dep_dict = {'type': 'metatask', 'name': 'gcdas_fcst', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} + deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_prep_sfc']: + dep_dict = {'type': 'task', 'name': f'{self.run}_prep_sfc'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) + + cycledef = self.run + + resources = self.get_resource('prep') + task_name = f'{self.run}_prep' + task_dict = {'task_name': task_name, + 'resources': resources, + 'dependency': dependencies, + 'envars': self.envars, + 'cycledef': cycledef, + 'command': f'{self.HOMEgfs}/dev/jobs/prep.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 prep_emissions(self): """ Create a task for preparing emissions data. @@ -200,34 +244,10 @@ def sfcanl(self): return task - def prepatmiodaobs(self): - - deps = [] - dep_dict = {'type': 'task', 'name': f'gcdas_prep'} - deps.append(rocoto.add_dependency(dep_dict)) - dependencies = rocoto.create_dependency(dep=deps) - - resources = self.get_resource('prepatmiodaobs') - task_name = f'{self.run}_prepatmiodaobs' - task_dict = {'task_name': task_name, - 'resources': resources, - 'dependency': dependencies, - 'envars': self.envars, - 'cycledef': 'gcdas', - 'command': f'{self.HOMEgfs}/dev/jobs/prepatmiodaobs.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 atmanlinit(self): deps = [] - dep_dict = {'type': 'task', 'name': f'{self.run}_prepatmiodaobs'} + dep_dict = {'type': 'task', 'name': f'{self.run}_prep'} deps.append(rocoto.add_dependency(dep_dict)) if self.options['do_hybvar']: dep_dict = {'type': 'metatask', 'name': 'enkfgdas_epmn', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} @@ -332,36 +352,6 @@ def atmanlfinal(self): return task - def prepobsaero(self): - - dump_suffix = self._base["DUMP_SUFFIX"] - dmpdir = self._base["DMPDIR"] - dump_path = self._template_to_rocoto_cycstring(self._base["COM_OBSPROC_TMPL"], - {'DMPDIR': dmpdir, 'DUMP_SUFFIX': dump_suffix, 'RUN': 'gdas'}) - - deps = [] - data = f'{dump_path}/gdas.t@Hz.updated.status.tm00.bufr_d' - dep_dict = {'type': 'data', 'data': data} - deps.append(rocoto.add_dependency(dep_dict)) - dependencies = rocoto.create_dependency(dep=deps) - - resources = self.get_resource('prepobsaero') - task_name = f'{self.run}_prepobsaero' - task_dict = {'task_name': task_name, - 'resources': resources, - 'dependency': dependencies, - 'envars': self.envars, - 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/prepobsaero.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 aeroanlgenb(self): deps = [] @@ -391,7 +381,7 @@ def aeroanlinit(self): deps = [] dep_dict = {'type': 'task', 'name': 'gcdas_aeroanlgenb', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} deps.append(rocoto.add_dependency(dep_dict)) - dep_dict = {'type': 'task', 'name': 'gcdas_prepobsaero'} + dep_dict = {'type': 'task', 'name': 'gcdas_prep'} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) @@ -792,7 +782,7 @@ def atmanlprod(self): atm_master_path = self._template_to_rocoto_cycstring(self._base["COM_ATMOS_MASTER_TMPL"]) deps = [] - data = f'{atm_master_path}/{self.run}.t@Hz.master.grb2anl' + data = f'{atm_master_path}/{self.run}.t@Hz.master.analysis.grib2' dep_dict = {'type': 'data', 'data': data, 'age': 120} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep=deps) @@ -904,7 +894,7 @@ def _atmosoceaniceprod(self, component: str): fhout_ice_gfs = self._configs['base']['FHOUT_ICE_GFS'] products_dict = {'atmos': {'config': 'atmos_products', 'history_path_tmpl': 'COM_ATMOS_MASTER_TMPL', - 'history_file_tmpl': f'{self.run}.t@Hz.master.grb2f#fhr3_last#'}} + 'history_file_tmpl': f'{self.run}.t@Hz.master.f#fhr3_last#.grib2'}} component_dict = products_dict[component] config = component_dict['config'] diff --git a/dev/workflow/rocoto/gfs_tasks.py b/dev/workflow/rocoto/gfs_tasks.py index 2eb76eea6cc..df2467a85fd 100644 --- a/dev/workflow/rocoto/gfs_tasks.py +++ b/dev/workflow/rocoto/gfs_tasks.py @@ -98,9 +98,12 @@ def prep(self): dump_suffix = self._base["DUMP_SUFFIX"] dmpdir = self._base["DMPDIR"] + iodadir = self._base["IODADIR"] atm_hist_path = self._template_to_rocoto_cycstring(self._base["COM_ATMOS_HISTORY_TMPL"], {'RUN': 'gdas'}) dump_path = self._template_to_rocoto_cycstring(self._base["COM_OBSPROC_TMPL"], {'DMPDIR': dmpdir, 'DUMP_SUFFIX': dump_suffix}) + ioda_path = self._template_to_rocoto_cycstring(self._base["COM_OBSFORGE_TMPL"], + {'IODADIR': iodadir, 'DUMP_SUFFIX': dump_suffix}) gfs_enkf = True if self.options['do_hybvar'] and 'gfs' in self.app_config.ens_runs else False @@ -113,6 +116,19 @@ def prep(self): deps.append(rocoto.add_dependency(dep_dict)) data = f'{dump_path}/{self.run}.t@Hz.updated.status.tm00.bufr_d' dep_dict = {'type': 'data', 'data': data} + if self.options['do_jediatmvar']: + data = f'{ioda_path}/atmos/{self.run}.t@Hz.obsforge_atmos_bufr_status.log' + dep_dict = {'type': 'data', 'data': data} + deps.append(rocoto.add_dependency(dep_dict)) + # TODO enable this for marine observations when ready + # if self.options['do_jediocnvar']: + # data = f'{ioda_path}/ocean/{self.run}.t@Hz.obsforge_marine_status.log' + # dep_dict = {'type': 'data', 'data': data} + # deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_aero_anl']: + data = f'{ioda_path}/chem/{self.run}.t@Hz.obsforge_aod_status.log' + dep_dict = {'type': 'data', 'data': data} + deps.append(rocoto.add_dependency(dep_dict)) deps.append(rocoto.add_dependency(dep_dict)) dep_dict = {'type': 'metatask', 'name': 'gdas_fcst', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} deps.append(rocoto.add_dependency(dep_dict)) @@ -315,7 +331,10 @@ def sfcanl(self): def analcalc(self): deps = [] - dep_dict = {'type': 'task', 'name': f'{self.run}_anal'} + if self.options['do_jediatmvar'] and not self.options['do_jediatmens']: + dep_dict = {'type': 'task', 'name': f'{self.run}_atmanlfinal'} + else: + dep_dict = {'type': 'task', 'name': f'{self.run}_anal'} deps.append(rocoto.add_dependency(dep_dict)) dep_dict = {'type': 'task', 'name': f'{self.run}_sfcanl'} deps.append(rocoto.add_dependency(dep_dict)) @@ -365,34 +384,10 @@ def analdiag(self): return task - def prepatmiodaobs(self): - - deps = [] - dep_dict = {'type': 'task', 'name': f'{self.run}_prep'} - deps.append(rocoto.add_dependency(dep_dict)) - dependencies = rocoto.create_dependency(dep=deps) - - resources = self.get_resource('prepatmiodaobs') - task_name = f'{self.run}_prepatmiodaobs' - task_dict = {'task_name': task_name, - 'resources': resources, - 'dependency': dependencies, - 'envars': self.envars, - 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/prepatmiodaobs.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 atmanlinit(self): deps = [] - dep_dict = {'type': 'task', 'name': f'{self.run}_prepatmiodaobs'} + dep_dict = {'type': 'task', 'name': f'{self.run}_prep'} deps.append(rocoto.add_dependency(dep_dict)) if self.options['do_hybvar']: dep_dict = {'type': 'metatask', 'name': 'enkfgdas_epmn', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} @@ -497,29 +492,6 @@ def atmanlfinal(self): return task - def prepobsaero(self): - deps = [] - dep_dict = {'type': 'task', 'name': f'{self.run}_prep'} - deps.append(rocoto.add_dependency(dep_dict)) - dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) - - resources = self.get_resource('prepobsaero') - task_name = f'{self.run}_prepobsaero' - task_dict = {'task_name': task_name, - 'resources': resources, - 'dependency': dependencies, - 'envars': self.envars, - 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/prepobsaero.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 aeroanlgenb(self): deps = [] @@ -552,9 +524,6 @@ def aeroanlinit(self): dep_dict = {'type': 'task', 'name': f'{self.run}_prep'} deps.append(rocoto.add_dependency(dep_dict)) - if self.options['do_prep_obs_aero']: - dep_dict = {'type': 'task', 'name': f'{self.run}_prepobsaero'} - deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) resources = self.get_resource('aeroanlinit') @@ -1092,13 +1061,13 @@ def atmanlupp(self): atm_anl_path = self._template_to_rocoto_cycstring(self._base["COM_ATMOS_ANALYSIS_TMPL"]) deps = [] - if self.options['do_jediatmvar']: + if self.options['do_jediatmvar'] and self.options['do_jediatmens']: data = f'{atm_anl_path}/{self.run}.t@Hz.jedi_analysis.atm.a006.nc' else: data = f'{atm_anl_path}/{self.run}.t@Hz.analysis.atm.a006.nc' dep_dict = {'type': 'data', 'data': data, 'age': 120} deps.append(rocoto.add_dependency(dep_dict)) - if self.options['do_jediatmvar']: + if self.options['do_jediatmvar'] and self.options['do_jediatmens']: data = f'{atm_anl_path}/{self.run}.t@Hz.jedi_analysis.sfc.a006.nc' else: data = f'{atm_anl_path}/{self.run}.t@Hz.analysis.sfc.a006.nc' @@ -2612,7 +2581,7 @@ def eupd(self): def atmensanlinit(self): deps = [] - dep_dict = {'type': 'task', 'name': f'{self.run.replace("enkf", "")}_prepatmiodaobs'} + dep_dict = {'type': 'task', 'name': f'{self.run.replace("enkf", "")}_prep'} deps.append(rocoto.add_dependency(dep_dict)) dep_dict = {'type': 'metatask', 'name': 'enkfgdas_epmn', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} deps.append(rocoto.add_dependency(dep_dict)) @@ -3106,7 +3075,7 @@ def earc_tars(self): if 'enkfgdas' in self.run: dep_dict = {'type': 'metatask', 'name': f'{self.run}_epmn'} deps.append(rocoto.add_dependency(dep_dict)) - if not self.options['do_jediatmvar']: + if not self.options['do_jediatmens']: dep_dict = {'type': 'task', 'name': f'{self.run}_echgres'} deps.append(rocoto.add_dependency(dep_dict)) if self._base.get('DOLETKF_OCN', True): diff --git a/dev/workflow/rocoto/tasks.py b/dev/workflow/rocoto/tasks.py index 79c380ffeb2..5a892af4d21 100644 --- a/dev/workflow/rocoto/tasks.py +++ b/dev/workflow/rocoto/tasks.py @@ -16,14 +16,14 @@ class Tasks: VALID_TASKS = ['aerosol_init', 'stage_ic', 'gen_control_ic', 'fetch', 'globus', 'ens_globus', 'prep_sfc', 'prep', 'anal', 'sfcanl', 'analcalc', 'analdiag', 'arch_vrfy', 'arch_tars', 'cleanup', 'ecen_fv3jedi', 'analcalc_fv3jedi', 'cleanup', - 'prepatmiodaobs', 'atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', + 'atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', 'prep_emissions', 'prepoceanobs', 'marineanlinit', 'marineanlletkf', 'marinebmatinit', 'marinebmat', 'marineanlvar', 'marineanlecen', 'marineanlchkpt', 'marineanlfinal', 'ocnanalvrfy', 'eobs', 'epos', 'esfc', 'eupd', 'earc_vrfy', 'earc_tars', 'ecen', 'echgres', 'ediag', 'efcs', 'atmensanlinit', 'atmensanlobs', 'atmensanlsol', 'atmensanlletkf', 'atmensanlfv3inc', 'atmensanlfinal', 'atmos_ensstat', - 'aeroanlinit', 'aeroanlvar', 'aeroanlfinal', 'aeroanlgenb', 'prepobsaero', + 'aeroanlinit', 'aeroanlvar', 'aeroanlfinal', 'aeroanlgenb', 'snowanl', 'esnowanl', 'offlineanl', 'fcst', diff --git a/env/GAEAC5.env b/env/GAEAC5.env index 83813f447c5..9f84a8b46ef 100755 --- a/env/GAEAC5.env +++ b/env/GAEAC5.env @@ -102,11 +102,7 @@ case ${step} in export NTHREADS_AEROANLGENB=${NTHREADSmax} export APRUN_AEROANLGENB="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANLGENB}" ;; - "prepobsaero") - export NTHREADS_PREPOBSAERO=${NTHREADS1} - export APRUN_PREPOBSAERO="${APRUN_default} --cpus-per-task=${NTHREADS_PREPOBSAERO}" - ;; "snowanl") export APRUN_CALCFIMS="${launcher} -n 1" diff --git a/env/GAEAC6.env b/env/GAEAC6.env index b37572ba7cf..77e7bdd05d3 100755 --- a/env/GAEAC6.env +++ b/env/GAEAC6.env @@ -105,11 +105,7 @@ case ${step} in export NTHREADS_AEROANLGENB=${NTHREADSmax} export APRUN_AEROANLGENB="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANLGENB}" ;; - "prepobsaero") - - export NTHREADS_PREPOBSAERO=${NTHREADS1} - export APRUN_PREPOBSAERO="${APRUN_default} --cpus-per-task=${NTHREADS_PREPOBSAERO}" - ;; + "snowanl") export APRUN_CALCFIMS="${launcher} -n 1" diff --git a/env/HERA.env b/env/HERA.env index 57aefcc66af..8d6619e0da1 100755 --- a/env/HERA.env +++ b/env/HERA.env @@ -113,11 +113,6 @@ elif [[ "${step}" = "anlstat" ]]; then export NTHREADS_ANLSTAT=${NTHREADSmax} export APRUN_ANLSTAT="${APRUN_default} --cpus-per-task=${NTHREADS_ANLSTAT}" -elif [[ "${step}" = "prepobsaero" ]]; then - - export NTHREADS_PREPOBSAERO=${NTHREADS1} - export APRUN_PREPOBSAERO="${APRUN_default} --cpus-per-task=${NTHREADS_PREPOBSAERO}" - elif [[ "${step}" = "snowanl" ]]; then export APRUN_CALCFIMS="${launcher} -n 1" diff --git a/env/HERCULES.env b/env/HERCULES.env index 46a6db49216..9aa6feb9ed8 100755 --- a/env/HERCULES.env +++ b/env/HERCULES.env @@ -108,11 +108,7 @@ case ${step} in export NTHREADS_AEROANLGENB=${NTHREADSmax} export APRUN_AEROANLGENB="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANLGENB}" ;; - "prepobsaero") - export NTHREADS_PREPOBSAERO=${NTHREADS1} - export APRUN_PREPOBSAERO="${APRUN_default} --cpus-per-task=${NTHREADS_PREPOBSAERO}" - ;; "snowanl") export APRUN_CALCFIMS="${launcher} -n 1" diff --git a/env/ORION.env b/env/ORION.env index 10f896037ab..ca1d9334dc5 100755 --- a/env/ORION.env +++ b/env/ORION.env @@ -99,11 +99,6 @@ elif [[ "${step}" = "aeroanlgenb" ]]; then export NTHREADS_AEROANLGENB=${NTHREADSmax} export APRUN_AEROANLGENB="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANLGENB}" -elif [[ "${step}" = "prepobsaero" ]]; then - - export NTHREADS_PREPOBSAERO=${NTHREADS1} - export APRUN_PREPOBSAERO="${APRUN_default} --cpus-per-task=${NTHREADS_PREPOBSAERO}" - elif [[ "${step}" = "snowanl" ]]; then export APRUN_CALCFIMS="${launcher} -n 1" diff --git a/env/URSA.env b/env/URSA.env index 1b952df431c..4ee5a07b7e5 100644 --- a/env/URSA.env +++ b/env/URSA.env @@ -107,11 +107,6 @@ elif [[ "${step}" = "anlstat" ]]; then export NTHREADS_ANLSTAT=${NTHREADSmax} export APRUN_ANLSTAT="${APRUN_default} --cpus-per-task=${NTHREADS_ANLSTAT}" -elif [[ "${step}" = "prepobsaero" ]]; then - - export NTHREADS_PREPOBSAERO=${NTHREADS1} - export APRUN_PREPOBSAERO="${APRUN_default} --cpus-per-task=${NTHREADS_PREPOBSAERO}" - elif [[ "${step}" = "snowanl" ]]; then export APRUN_CALCFIMS="${launcher} -n 1" diff --git a/env/WCOSS2.env b/env/WCOSS2.env index b0da0aa559a..5d89728674c 100755 --- a/env/WCOSS2.env +++ b/env/WCOSS2.env @@ -85,11 +85,6 @@ elif [[ "${step}" = "aeroanlgenb" ]]; then export NTHREADS_AEROANLGENB=${NTHREADSmax} export APRUN_AEROANLGENB="${APRUN_default}" -elif [[ "${step}" = "prepobsaero" ]]; then - - export NTHREADS_PREPOBSAERO=${NTHREADS1} - export APRUN_PREPOBSAERO="${APRUN_default} --ppn ${tasks_per_node} --cpu-bind depth --depth ${NTHREADS_PREPOBSAERO}" - elif [[ "${step}" = "snowanl" ]]; then export APRUN_CALCFIMS="${launcher} -n 1" diff --git a/jobs/JGLOBAL_ARCHIVE_TARS b/jobs/JGLOBAL_ARCHIVE_TARS index f3b95db93cc..9614ecb18e2 100755 --- a/jobs/JGLOBAL_ARCHIVE_TARS +++ b/jobs/JGLOBAL_ARCHIVE_TARS @@ -11,6 +11,7 @@ fi ############################################## YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ COMIN_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \ + COMIN_ATMOS_ANLMON:COM_ATMOS_ANLMON_TMPL \ COMIN_ATMOS_BUFR:COM_ATMOS_BUFR_TMPL \ COMIN_ATMOS_GEMPAK:COM_ATMOS_GEMPAK_TMPL \ COMIN_ATMOS_GENESIS:COM_ATMOS_GENESIS_TMPL \ diff --git a/jobs/JGLOBAL_ATM_PREP_IODA_OBS b/jobs/JGLOBAL_ATM_PREP_IODA_OBS deleted file mode 100755 index ca0006f11b5..00000000000 --- a/jobs/JGLOBAL_ATM_PREP_IODA_OBS +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/env bash - -source "${HOMEgfs}/ush/jjob_header.sh" -e "prepatmiodaobs" -c "base prepatmiodaobs" - -############################################## -# Set variables used in the script -############################################## - -############################################## -# Begin JOB SPECIFIC work -############################################## -# Generate COM variables from templates -YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ - COMOUT_OBS:COM_OBS_TMPL - -############################################################### -# Run relevant script -EXSCRIPT=${BUFR2IODASH:-${USHgfs}/run_bufr2ioda.py} # FIXME: A j-job should call ex-script, not an ush-script! See EE2 standards -${EXSCRIPT} "${PDY}${cyc}" "${RUN}" "${DMPDIR}" "${PARMgfs}/gdas/ioda/bufr2ioda" "${COMOUT_OBS}/" && true -export err=$? -set +x -if [[ ${err} -ne 0 ]]; then - err_exit "Error executing ${EXSCRIPT}" -fi -set_trace - -############################################## -# End JOB SPECIFIC work -############################################## - -############################################## -# Final processing -############################################## -if [[ -e "${pgmout}" ]]; then - cat "${pgmout}" -fi - -exit 0 diff --git a/jobs/JGLOBAL_PREP_OBS_AERO b/jobs/JGLOBAL_PREP_OBS_AERO deleted file mode 100755 index 7b1d19cf084..00000000000 --- a/jobs/JGLOBAL_PREP_OBS_AERO +++ /dev/null @@ -1,45 +0,0 @@ -#! /usr/bin/env bash - -source "${HOMEgfs}/ush/jjob_header.sh" -e "prepobsaero" -c "base prepobsaero" - -############################################## -# Set variables used in the script -############################################## - -YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COMOUT_OBS:COM_OBS_TMPL -YMD=${PDY} HH=${cyc} RUN='gdas' declare_from_tmpl -rx COMIN_OBSPROC:COM_OBSPROC_TMPL - -############################################## -# Begin JOB SPECIFIC work -############################################## - -############################################################### -# Run relevant script - -EXSCRIPT=${GDASPREPAEROOBSPY:-${SCRgfs}/exglobal_prep_obs_aero.py} -${EXSCRIPT} && true -export err=$? -if [[ ${err} -ne 0 ]]; then - err_exit -fi - -############################################## -# End JOB SPECIFIC work -############################################## - -############################################## -# Final processing -############################################## -if [[ -e "${pgmout}" ]]; then - cat "${pgmout}" -fi - -########################################## -# Remove the Temporary working directory -########################################## -cd "${DATAROOT}" || true -if [[ "${KEEPDATA}" == "NO" ]]; then - rm -rf "${DATA}" -fi - -exit 0 diff --git a/parm/archive/enkf.yaml.j2 b/parm/archive/enkf.yaml.j2 index ab60a2b86dc..c19781a1c3e 100644 --- a/parm/archive/enkf.yaml.j2 +++ b/parm/archive/enkf.yaml.j2 @@ -7,8 +7,10 @@ enkf: {% for mem in range(1, nmem_ens + 1) %} - "logs/{{ cycle_YMDH }}/{{ RUN }}_fcst_mem{{ '%03d' % mem }}.log" {% endfor %} - {% for fhr in range(fhmin, fhmax + 1, fhout) %} - - "logs/{{ cycle_YMDH }}/{{ RUN }}_epos{{ '%03d' % (fhr - fhmin) }}.log" + {% set fhrs = range(fhmin, fhmax + fhout, fhout) %} + {% set ngrps = fhrs | length %} + {% for grp in range(0, ngrps) %} + - "logs/{{ cycle_YMDH }}/{{ RUN }}_epos{{ '%03d' % grp }}.log" {% endfor %} {% if not DO_JEDIATMENS %} - "logs/{{ cycle_YMDH }}/{{ RUN }}_echgres.log" diff --git a/parm/archive/gdas.yaml.j2 b/parm/archive/gdas.yaml.j2 index a3f764a96fc..c0be51bad2a 100644 --- a/parm/archive/gdas.yaml.j2 +++ b/parm/archive/gdas.yaml.j2 @@ -8,7 +8,6 @@ gdas: - "logs/{{ cycle_YMDH }}/{{ RUN }}_atmanlprod.log" - "logs/{{ cycle_YMDH }}/{{ RUN }}_prep.log" {% if DO_JEDIATMVAR %} - - "logs/{{ cycle_YMDH }}/{{ RUN }}_prepatmiodaobs.log" - "logs/{{ cycle_YMDH }}/{{ RUN }}_atmanlinit.log" - "logs/{{ cycle_YMDH }}/{{ RUN }}_atmanlprod.log" - "logs/{{ cycle_YMDH }}/{{ RUN }}_atmanlfinal.log" @@ -57,8 +56,13 @@ gdas: # Analysis netCDF (raw) data {% if DO_JEDIATMVAR %} + {% if ATMINC_GRID == 'gaussian' %} + - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.atm.a006.nc" + - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.sfc.a006.nc" + {% else %} - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}jedi_analysis.atm.a006.nc" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}jedi_analysis.sfc.a006.nc" + {% endif %} {% else %} - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.atm.a006.nc" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.sfc.a006.nc" @@ -82,11 +86,10 @@ gdas: - "{{ COMIN_CONF | relpath(ROTDIR) }}/{{ head }}anlvar.atm.yaml" - "{{ COMIN_CONF | relpath(ROTDIR) }}/{{ head }}anlvar.fv3.atm.yaml" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}stat.atm.tar" + - "{{ COMIN_ATMOS_ANLMON | relpath(ROTDIR) }}/{{ head }}atmos_analysis.ioda_hofx_stats.tar.gz" {% else %} - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}gsistat.txt" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}cnvstat.tar" - - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}oznstat.tar" - - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}radstat.tar" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}abias.txt" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}abias_air.txt" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}abias_pc.txt" @@ -178,6 +181,9 @@ gdas: - "{{ COMIN_ATMOS_MASTER | relpath(ROTDIR) }}/{{ head }}master.f006.grib2" optional: {% if MODE == "cycled" %} + # Ozone and Radiance diagnostic files may not always be created + - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}oznstat.tar" + - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}radstat.tar" # Radiance verification (only created if there are problems) {% if DO_VERFRAD %} - "{{ COMIN_ATMOS_RADMON | relpath(ROTDIR) }}/bad_diag.{{ cycle_YMDH }}" diff --git a/parm/archive/gdas_restarta.yaml.j2 b/parm/archive/gdas_restarta.yaml.j2 index b581c76b986..60615e0c7ad 100644 --- a/parm/archive/gdas_restarta.yaml.j2 +++ b/parm/archive/gdas_restarta.yaml.j2 @@ -4,7 +4,7 @@ gdas_restarta: target: "{{ ATARDIR }}/{{ cycle_YMDH }}/gdas_restarta.tar" required: # Deterministic analysis increments - {% if DO_JEDIATMVAR %} + {% if DO_JEDIATMVAR and not (ATMINC_GRID == 'gaussian') %} {% for iaufhr in IAUFHRS %} {% for itile in range(6) %} - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}jedi_increment.atm.i{{ "%03d" % iaufhr }}.tile{{ itile+1 }}.nc" @@ -43,7 +43,6 @@ gdas_restarta: - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}abias.txt" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}abias_air.txt" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}abias_pc.txt" - - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}radstat.tar" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}cnvstat.tar" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}abias_int.txt" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.dtf.a006.nc" @@ -56,3 +55,5 @@ gdas_restarta: - "{{ COMIN_OBS | relpath(ROTDIR) }}/{{ head }}nsstbufr" - "{{ COMIN_OBS | relpath(ROTDIR) }}/{{ head }}prepbufr" - "{{ COMIN_OBS | relpath(ROTDIR) }}/{{ head }}prepbufr.acft_profiles" + optional: + - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}radstat.tar" diff --git a/parm/archive/gfs_arcdir.yaml.j2 b/parm/archive/gfs_arcdir.yaml.j2 index 82402cdb54f..877691ff5f9 100644 --- a/parm/archive/gfs_arcdir.yaml.j2 +++ b/parm/archive/gfs_arcdir.yaml.j2 @@ -101,6 +101,16 @@ {% do gdas_files.append([COMIN_ATMOS_GRIB_1p00 ~ "/" ~ head ~ "pres_a.1p00.f" ~ '%03d'|format(fhr) ~ ".grib2", ARCDIR ~ "/pgbf" ~ '%02d'|format(fhr) ~ "." ~ RUN ~ "." ~ cycle_YMDH ~ ".grib2"]) %} {% endfor %} + {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "abias.txt", + ARCDIR ~ "/abias." ~ RUN ~ "." ~ cycle_YMDH ]) %} + {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "abias_pc.txt", + ARCDIR ~ "/abias_pc." ~ RUN ~ "." ~ cycle_YMDH ]) %} + {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "abias_air.txt", + ARCDIR ~ "/abias_air." ~ RUN ~ "." ~ cycle_YMDH ]) %} + {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "abias_int.txt", + ARCDIR ~ "/abias_int." ~ RUN ~ "." ~ cycle_YMDH ]) %} + {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "analysis.dtf.a006.nc", + ARCDIR ~ "/dtfanl." ~ RUN ~ "." ~ cycle_YMDH ~ ".nc"]) %} # Now append the necessary file pairs to file_set # Common deterministic files @@ -148,7 +158,7 @@ mkdir: - "{{ VFYARC }}/{{ RUN }}.{{ cycle_YMD }}/{{ cycle_HH }}" {% endif %} -copy: +copy_opt: {% for source_dest_pair in file_set %} - {{ source_dest_pair }} {% endfor %} diff --git a/parm/archive/gfs_netcdfa.yaml.j2 b/parm/archive/gfs_netcdfa.yaml.j2 index 0b9a1b12b02..7d23ad30a77 100644 --- a/parm/archive/gfs_netcdfa.yaml.j2 +++ b/parm/archive/gfs_netcdfa.yaml.j2 @@ -4,14 +4,19 @@ gfs_netcdfa: target: "{{ ATARDIR }}/{{ cycle_YMDH }}/gfs_netcdfa.tar" required: {% if DO_JEDIATMVAR %} + {% if ATMINC_GRID == 'gaussian' %} + - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.atm.a006.nc" + - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.sfc.a006.nc" + {% else %} - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}jedi_analysis.atm.a006.nc" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}jedi_analysis.sfc.a006.nc" + {% endif %} {% else %} - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.atm.a006.nc" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.sfc.a006.nc" {% endif %} {% for iaufhr in IAUFHRS %} - {% if DO_JEDIATMVAR %} + {% if DO_JEDIATMVAR and not (ATMINC_GRID == 'gaussian') %} {% for itile in range(6) %} - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}jedi_increment.atm.i{{ "%03d" % iaufhr }}.tile{{ itile+1 }}.nc" {% endfor %} diff --git a/parm/post/upp.yaml b/parm/post/upp.yaml index c4935104ae4..4c1bd6d889b 100644 --- a/parm/post/upp.yaml +++ b/parm/post/upp.yaml @@ -20,8 +20,13 @@ analysis: copy: - ["{{ PARMgfs }}/post/gfs/postxconfig-NT-gfs-anl.txt", "{{ DATA }}/postxconfig-NT.txt"] {% if DO_JEDIATMVAR %} + {% if ATMINC_GRID == 'gaussian' %} + - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.analysis.atm.a006.nc", "{{ DATA }}/{{ atmos_filename }}"] + - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.analysis.sfc.a006.nc", "{{ DATA }}/{{ flux_filename }}"] + {% else %} - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.jedi_analysis.atm.a006.nc", "{{ DATA }}/{{ atmos_filename }}"] - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.jedi_analysis.sfc.a006.nc", "{{ DATA }}/{{ flux_filename }}"] + {% endif %} {% else %} - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.analysis.atm.a006.nc", "{{ DATA }}/{{ atmos_filename }}"] - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.analysis.sfc.a006.nc", "{{ DATA }}/{{ flux_filename }}"] diff --git a/parm/stage/analysis.yaml.j2 b/parm/stage/analysis.yaml.j2 index 58a61ae3182..c08a1994682 100644 --- a/parm/stage/analysis.yaml.j2 +++ b/parm/stage/analysis.yaml.j2 @@ -13,6 +13,7 @@ analysis: {% if DO_JEDIATMVAR %} + {% if ATMINC_GRID == "cubed_sphere_grid" %} {% for itile in range(6) %} {% if mem == -1 %} {% if DOIAU %} @@ -31,6 +32,15 @@ analysis: - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}.tile{{ itile+1 }}.nc", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}"] {% endfor %} {% endfor %} + {% else %} + {% for ftype in ["increment.atm.i006.nc", "increment.atm.i009.nc", "increment.atm.i003.nc", + "recentered_increment.atm.i006.nc", "recentered_increment.atm.i009.nc", "recentered_increment.atm.i003.nc"] %} + {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}"] + {% endif %} + {% endfor %} + {% endif %} + {% for ftype in ["abias.txt", "abias_air.txt", "abias_int.txt", "abias_pc.txt", "rad_varbc_params.tar"] %} {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}"] diff --git a/scripts/exglobal_archive_tars.py b/scripts/exglobal_archive_tars.py index ece0e4e325a..e05433c14ac 100755 --- a/scripts/exglobal_archive_tars.py +++ b/scripts/exglobal_archive_tars.py @@ -41,7 +41,7 @@ def main(): 'IAUFHRS', 'DO_FIT2OBS', 'NET', 'FHOUT_HF_GFS', 'FHMAX_HF_GFS', 'OFFSET_START_HOUR', 'ARCH_EXPDIR', 'EXPDIR', 'ARCH_EXPDIR_FREQ', 'ARCH_HASHES', 'ARCH_DIFFS', 'SDATE', 'EDATE', 'HOMEgfs', 'DO_GEMPAK', 'DATASETS_YAML', - 'WAVE_OUT_GRIDS', 'DO_GSISOILDA', 'DO_LAND_IAU', 'TARBALL_TYPE'] + 'WAVE_OUT_GRIDS', 'DO_GSISOILDA', 'DO_LAND_IAU', 'TARBALL_TYPE', 'ATMINC_GRID'] archive_dict = AttrDict() for key in keys: diff --git a/scripts/exglobal_atmos_sfcanl.sh b/scripts/exglobal_atmos_sfcanl.sh index 903f28fd967..dd7be82cf0d 100755 --- a/scripts/exglobal_atmos_sfcanl.sh +++ b/scripts/exglobal_atmos_sfcanl.sh @@ -113,8 +113,13 @@ done # There is only a single NSST analysis at the middle of the window # For now use/assume it is the same at the beginning of the window if doing IAU if [[ "${DONST}" == "YES" ]]; then - cpreq "${COMIN_ATMOS_ANALYSIS}/${APREFIX}analysis.dtf.a006.nc" "${DATA}/dtfanl" - export NST_FILE="dtfanl" + export NST_FILE=${NST_FILE:-${COMIN_ATMOS_ANALYSIS}/${APREFIX}analysis.dtf.a006.nc} + if [[ -s "${NST_FILE}" ]]; then + cpreq "${NST_FILE}" "${DATA}/dtfanl" + export NST_FILE="dtfanl" + else + export NST_FILE="NULL" + fi else export NST_FILE="NULL" fi diff --git a/scripts/exglobal_diag.sh b/scripts/exglobal_diag.sh index 8957e6201ca..e5722fd3205 100755 --- a/scripts/exglobal_diag.sh +++ b/scripts/exglobal_diag.sh @@ -265,9 +265,11 @@ EOFdiag fi # Restrict RADSTAT - chmod 750 "${RADSTAT}" - if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then - ${CHGRP_CMD} "${RADSTAT}" + if [[ -s "${RADSTAT}" ]]; then + chmod 750 "${RADSTAT}" + if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then + ${CHGRP_CMD} "${RADSTAT}" + fi fi echo "$(date) END tar diagnostic files" >&2 diff --git a/scripts/exglobal_prep_obs_aero.py b/scripts/exglobal_prep_obs_aero.py deleted file mode 100755 index c9e209471e8..00000000000 --- a/scripts/exglobal_prep_obs_aero.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 -# exglobal_prep_obs_aero.py -# This script collect available viirs -# obs files, combine and preprocess -# them. -import os - -from wxflow import Logger, cast_strdict_as_dtypedict -from pygfs.task.aero_prepobs import AerosolObsPrep - -# Initialize root logger -logger = Logger(level='DEBUG', colored_log=True) - - -if __name__ == '__main__': - - # Take configuration from environment and cast it as python dictionary - config = cast_strdict_as_dtypedict(os.environ) - - AeroObs = AerosolObsPrep(config) - if config.DO_PREP_OBS_AERO: - AeroObs.initialize() - AeroObs.runConverter() - AeroObs.finalize() - else: - # just sync files from DMPDIR - AeroObs.syncObs() diff --git a/scripts/exglobal_stage_ic.py b/scripts/exglobal_stage_ic.py index b442cf1b12a..3c8fc230c40 100755 --- a/scripts/exglobal_stage_ic.py +++ b/scripts/exglobal_stage_ic.py @@ -14,13 +14,17 @@ def main(): config = cast_strdict_as_dtypedict(os.environ) + # Set a default value for ATMINC_GRID if it is not in the environment + # This MUST be done *before* config is passed to the Stage constructor. + config.setdefault('ATMINC_GRID', '') + # Instantiate the Stage object stage = Stage(config) # Pull out all the configuration keys needed to run stage job keys = ['RUN', 'MODE', 'EXP_WARM_START', 'NMEM_ENS', 'assim_freq', 'current_cycle', 'previous_cycle', - 'ROTDIR', 'ICSDIR', 'STAGE_IC_YAML_TMPL', 'DO_JEDIATMVAR', + 'ROTDIR', 'ICSDIR', 'STAGE_IC_YAML_TMPL', 'DO_JEDIATMVAR', 'ATMINC_GRID', 'OCNRES', 'waveGRD', 'ntiles', 'DOIAU', 'DO_JEDIOCNVAR', 'DO_STARTMEM_FROM_JEDIICE', 'DO_WAVE', 'DO_OCN', 'DO_ICE', 'DO_NEST', 'DO_CA', 'DO_AERO_ANL', diff --git a/sorc/build_compute.sh b/sorc/build_compute.sh index 0db25f86119..7e22f3b4f56 100755 --- a/sorc/build_compute.sh +++ b/sorc/build_compute.sh @@ -87,33 +87,6 @@ echo "Generating build.xml for building global-workflow programs on compute node # Catch errors manually from here out set +e -# Temporarily build the GDASApp on the head node -# Cleanup function to kill the GDASApp build on ctrl-c or non-clean exit -build_ids=() -function cleanup() { - echo "Exiting build script. Terminating subprocesses..." - for pid in "${build_ids[@]}"; do - if kill -0 "${pid}" 2>/dev/null; then # Check if process still exists - kill "${pid}" - fi - done - exit 1 -} - -trap cleanup TERM -trap cleanup INT -trap cleanup ERR - -# TODO remove this when all builds move to the head nodes and/or the GDASApp is able to build on all compute nodes again -# See GW issue 3933 -if [[ ${systems} == "all" || ${systems} =~ "gdas" ]]; then - echo "Building the GDASApp locally (on this node)" - gdas_build_log="${HOMEgfs}/sorc/logs/build_gdas.log" - "${HOMEgfs}/sorc/build_gdas.sh" -j 12 >& "${gdas_build_log}" & - build_gdas_id=$! - build_ids+=("${build_gdas_id}") -fi - "${HOMEgfs}/dev/workflow/build_compute.py" --account "${HPC_ACCOUNT}" --yaml "${yaml}" --systems "${systems}" rc=$? if [[ "${rc}" -ne 0 ]]; then @@ -167,8 +140,6 @@ while [[ "${finished}" == "false" ]]; do fi done < rocotostat.out - # Kill the GDASApp build if it is still running - cleanup fi done diff --git a/sorc/gdas.cd b/sorc/gdas.cd index 3e774e7b507..58da1e3bcc8 160000 --- a/sorc/gdas.cd +++ b/sorc/gdas.cd @@ -1 +1 @@ -Subproject commit 3e774e7b50752c5bc40e57f8719058aa8602b2d9 +Subproject commit 58da1e3bcc863fddaf32319efe6b409565dd568b diff --git a/sorc/link_workflow.sh b/sorc/link_workflow.sh index 84eb45134a4..f1d44cce281 100755 --- a/sorc/link_workflow.sh +++ b/sorc/link_workflow.sh @@ -260,19 +260,13 @@ if [[ -d "${HOMEgfs}/sorc/gdas.cd/build" ]]; then ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ufsda" . ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ioda/bufr2ioda/gen_bufr2ioda_json.py" . ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ioda/bufr2ioda/gen_bufr2ioda_yaml.py" . + ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ioda/bufr2ioda/run_bufr2ioda.py" . ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/sorc/da-utils/ush/gsincdiag_to_ioda" . + ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/sorc/da-utils/ush/pyiodaconv" . cd "${HOMEgfs}/ush" || exit 1 - ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ioda/bufr2ioda/run_bufr2ioda.py" . + ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/gsi_satbias2ioda_all.sh" . ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/snow/bufr_snocvr_snomad.py" . ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/build/bin/imsfv3_scf2ioda.py" . - declare -a gdasapp_ocn_insitu_profile_platforms=("argo" "bathy" "glider" "marinemammal" "tesac" "xbtctd") - for platform in "${gdasapp_ocn_insitu_profile_platforms[@]}"; do - ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ioda/bufr2ioda/marine/bufr2ioda_insitu_profile_${platform}.py" . - done - declare -a gdasapp_ocn_insitu_sfc_platforms=("altkob" "trkob") - for platform in "${gdasapp_ocn_insitu_sfc_platforms[@]}"; do - ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ioda/bufr2ioda/marine/bufr2ioda_insitu_surface_${platform}.py" . - done fi #------------------------------ @@ -420,7 +414,6 @@ fi # GDASApp executables if [[ -d "${HOMEgfs}/sorc/gdas.cd/install" ]]; then cp -f "${HOMEgfs}/sorc/gdas.cd/install/bin"/gdas* ./ - cp -f "${HOMEgfs}/sorc/gdas.cd/install/bin/bufr2ioda.x" ./gdas_bufr2ioda.x cp -f "${HOMEgfs}/sorc/gdas.cd/install/bin/calcfIMS.exe" ./gdas_calcfIMS.x cp -f "${HOMEgfs}/sorc/gdas.cd/install/bin/apply_incr.exe" ./gdas_apply_incr.x fi diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index 39a12b3c61c..f4b9b9f47c6 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -199,6 +199,11 @@ EOF inc_files=("jedi_increment.atm.i006.tile1.nc" "jedi_increment.atm.i006.tile2.nc" "jedi_increment.atm.i006.tile3.nc" "jedi_increment.atm.i006.tile4.nc" "jedi_increment.atm.i006.tile5.nc" "jedi_increment.atm.i006.tile6.nc") increment_file_on_native_grid=".true." res_latlon_dynamics="jedi_increment.atm.i006" + if [[ "${DO_JEDIATMENS:-NO}" == "NO" ]]; then + inc_files=("increment.atm.i006.nc") + res_latlon_dynamics="increment.atm.i006.nc" + increment_file_on_native_grid=".false." + fi else inc_files=("increment.atm.i006.nc") res_latlon_dynamics="increment.atm.i006.nc" @@ -224,6 +229,9 @@ EOF for inc_file in "${inc_files[@]}"; do if [[ "${DO_JEDIATMVAR:-NO}" == "YES" ]]; then increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${prefix_atminc}${inc_file}" + if [[ "${DO_JEDIATMENS:-NO}" == "NO" ]]; then + increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${prefix_atminc}${inc_file}" + fi else if [[ "${RUN}" == "gcafs" ]]; then increment_file="${COMIN_ATMOS_ANALYSIS}/gcdas.t${cyc}z.${prefix_atminc}${inc_file}" @@ -295,7 +303,7 @@ EOF ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.atm.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/atmf${FH3}.nc" ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.sfc.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/sfcf${FH3}.nc" ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.log.f${FH3}.txt" "${DATAoutput}/FV3ATM_OUTPUT/log.atm.f${FH3}" - if [[ "${DO_JEDIATMVAR:-}" == "YES" ]]; then + if [[ "${DO_JEDIATMVAR:-}" == "YES" || "${DO_HISTORY_FILE_ON_NATIVE_GRID:-"NO"}" == "YES" ]]; then ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.csg_atm.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/cubed_sphere_grid_atmf${FH3}.nc" ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.csg_sfc.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/cubed_sphere_grid_sfcf${FH3}.nc" fi diff --git a/ush/getioda.sh b/ush/getioda.sh new file mode 100755 index 00000000000..417f6e4c4d1 --- /dev/null +++ b/ush/getioda.sh @@ -0,0 +1,67 @@ +#! /usr/bin/env bash + +YMD=${1:-""} +HH=${2:-""} +RUN=${3:-""} +SOURCE_DIR=${4:-${IODADIR}/${RUN}${DUMP_SUFFIX}.${YMD}/${HH}} +TARGET_DIR=${5:-${ROTDIR}/${RUN}.${YMD}/${HH}} + +DUMP_SUFFIX=${DUMP_SUFFIX:-""} + +# Exit if SOURCE_DIR does not exist +if [[ ! -s "${SOURCE_DIR}" ]]; then + echo "FATAL ERROR: DUMP SOURCE_DIR=${SOURCE_DIR} does not exist" + exit 99 +fi + +# Create TARGET_DIR if is does not exist +if [[ ! -s "${TARGET_DIR}" ]]; then + mkdir -p "${TARGET_DIR}" +fi + +# Set file prefix +prefix="${RUN}.t${HH}z." + +# loop through top level component directories (e.g. atmos, ocean, land, ice) +for compdir in "${SOURCE_DIR}"/*/ ; do + compdir=${compdir%*/} + compdir=${compdir##*/} + # Skip if not a directory + if [[ ! -d "${SOURCE_DIR}/${compdir}/" ]]; then + continue + fi + # check if status file does not exist + # Check if any status log files exist using array expansion + set +f + status_files=("${SOURCE_DIR}/${compdir}/${prefix}"*status.log) + if [[ ! -e "${status_files[0]}" ]]; then + echo "FATAL ERROR: completion log file NOT FOUND in ${SOURCE_DIR}/${compdir}" + exit 99 + fi + echo "Processing component directory: ${compdir}" + set -f + # Create component directory in TARGET_DIR if it does not exist + if [[ ! -s "${TARGET_DIR}/${compdir}" ]]; then + mkdir -p "${TARGET_DIR}/${compdir}" + fi + # Link files from SOURCE_DIR to TARGET_DIR + if [[ ! -d "${SOURCE_DIR}/${compdir}" ]]; then + echo "FATAL ERROR: '${SOURCE_DIR}/${compdir}' does not exist, ABORT!" + exit 99 + fi + # Use shell globbing instead of iterating over ls output. Enable nullglob so the loop + # simply skips when no matches are found. + set +f + shopt -s nullglob + for source_file in "${SOURCE_DIR}/${compdir}/${prefix}"*; do + if [[ ! -e "${source_file}" ]]; then + continue + fi + targ_file=$(basename "${source_file}") + cpreq "${source_file}" "${TARGET_DIR}/${compdir}/${targ_file}" + done + shopt -u nullglob + set -f +done + +exit 0 diff --git a/ush/parsing_model_configure_FV3.sh b/ush/parsing_model_configure_FV3.sh index 40b0814c2c3..c8d2d00f8a8 100755 --- a/ush/parsing_model_configure_FV3.sh +++ b/ush/parsing_model_configure_FV3.sh @@ -32,7 +32,7 @@ local WRITE_GROUP=${WRITE_GROUP:-1} local WRTTASK_PER_GROUP=${WRTTASK_PER_GROUP:-24} local ITASKS=1 local OUTPUT_HISTORY=${OUTPUT_HISTORY:-".true."} -if [[ "${DO_JEDIATMVAR:-}" == "YES" ]]; then +if [[ "${DO_JEDIATMVAR:-}" == "YES" || "${DO_HISTORY_FILE_ON_NATIVE_GRID:-"NO"}" == "YES" ]]; then local HISTORY_FILE_ON_NATIVE_GRID=".true." else local HISTORY_FILE_ON_NATIVE_GRID=".false." diff --git a/ush/python/pygfs/task/aero_prepobs.py b/ush/python/pygfs/task/aero_prepobs.py deleted file mode 100644 index a992ada4111..00000000000 --- a/ush/python/pygfs/task/aero_prepobs.py +++ /dev/null @@ -1,250 +0,0 @@ -#!/usr/bin/env python3 - -import os -import glob -import gzip -import tarfile -import re -from logging import getLogger -from typing import List, Dict, Any, Union - -from wxflow import (AttrDict, FileHandler, rm_p, rmdir, - Task, add_to_datetime, to_timedelta, to_datetime, - datetime_to_YMD, - chdir, Executable, WorkflowException, - parse_j2yaml, save_as_yaml, logit) - -logger = getLogger(__name__.split('.')[-1]) - - -class AerosolObsPrep(Task): - """ - Class for preparing and managing aerosol observations - """ - def __init__(self, config: Dict[str, Any]) -> None: - super().__init__(config) - - _window_begin = add_to_datetime(self.task_config.current_cycle, -to_timedelta(f"{self.task_config['assim_freq']}H") / 2) - _window_end = add_to_datetime(self.task_config.current_cycle, +to_timedelta(f"{self.task_config['assim_freq']}H") / 2) - - local_dict = AttrDict( - { - 'window_begin': _window_begin, - 'window_end': _window_end, - 'sensors': self.task_config['SENSORS'], - 'data_dir': self.task_config['VIIRS_DATA_DIR'], - 'input_files': '', - 'OPREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z.", - 'APREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z." - } - ) - - # task_config is everything that this task should need - self.task_config = AttrDict(**self.task_config, **local_dict) - - @logit(logger) - def initialize(self) -> None: - """ - List needed raw obs files. - Copy the raw obs files to $DATA/obs. - Link over the needed executable. - Generate corresponding YAML file. - Run IODA converter. - """ - self.task_config.DATA_OBS = os.path.join(self.task_config.DATA, 'obs') - if os.path.exists(self.task_config.DATA_OBS): - rmdir(self.task_config.DATA_OBS) - FileHandler({'mkdir': [self.task_config.DATA_OBS]}).sync() - - self.task_config.prepaero_yaml = [] - for sensor in self.task_config.sensors: - raw_files = self.list_raw_files(sensor) - self.task_config.input_files = self.copy_obs(raw_files) - self.link_obsconvexe() - self.task_config.prepaero_config = self.get_obsproc_config(sensor) - - # generate converter YAML file - template = f"{self.task_config.RUN}.t{self.task_config['cyc']:02d}z.prepaero_viirs_{sensor}.yaml" - _prepaero_yaml = os.path.join(self.task_config.DATA, template) - self.task_config.prepaero_yaml.append(_prepaero_yaml) - logger.debug(f"Generate PrepAeroObs YAML file: {_prepaero_yaml}") - save_as_yaml(self.task_config.prepaero_config, _prepaero_yaml) - logger.info(f"Wrote PrepAeroObs YAML to: {_prepaero_yaml}") - - @logit(logger) - def list_raw_files(self, sensor) -> List[str]: - """ - List all files in the predefined directory that match the predefined sensor and within the time window. - """ - if sensor == 'n20': - sensor = 'j01' - dir1 = os.path.join(self.task_config.data_dir, datetime_to_YMD(self.task_config.window_begin)) - dir2 = os.path.join(self.task_config.data_dir, datetime_to_YMD(self.task_config.window_end)) - - if dir1 == dir2: - files = os.listdir(dir1) - allfiles = [os.path.join(dir1, file) for file in files] - allfiles.sort() - else: - files_1 = os.listdir(dir1) - allfiles_1 = [os.path.join(dir1, file) for file in files_1] - files_2 = os.listdir(dir2) - allfiles_2 = [os.path.join(dir2, file) for file in files_2] - allfiles = sorted(allfiles_1, allfiles_2) - matching_files = [] - try: - for file in allfiles: - basename = os.path.basename(file) - pattern = r"s(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{3})" - match = re.match(pattern, basename.split('_')[3]) - yyyy, mm, dd, HH, MM = match.group(1), match.group(2), match.group(3), match.group(4), match.group(5) - fstart = to_datetime(f'{yyyy}-{mm}-{dd}T{HH}:{MM}Z') - if sensor == basename.split('_')[2]: - # temporally select obs files based on time stamp in the filename. - if (fstart > self.task_config.window_begin) and (fstart < self.task_config.window_end): - matching_files.append(os.path.join(self.task_config.data_dir, file)) - logger.info("Found %d matching files.", len(matching_files)) - except FileNotFoundError: - logger.error("The specified file/directory does not exist.") - raise - return matching_files - - @logit(logger) - def copy_obs(self, inputfiles) -> Dict[str, Any]: - """ - Copy the raw obs files to $DATA/obs. - """ - copylist = [] - destlist = [] - for filename in inputfiles: - basename = os.path.basename(filename) - dest = os.path.join(self.task_config.DATA_OBS, basename) - copylist.append([filename, dest]) - destlist.append(dest) - FileHandler({'copy': copylist}).sync() - - return destlist - - @logit(logger) - def get_obsproc_config(self, sensor) -> Dict[str, Any]: - """ - Compile a dictionary of obs proc configuration from OBSPROCYAML template file - Parameters - ---------- - Returns - ---------- - obsproc_config : Dict - a dictionary containing the fully rendered obs proc yaml configuration - """ - self.task_config.sensor = sensor - # generate JEDI YAML file - logger.info(f"Generate gdas_obsprovider2ioda YAML config: {self.task_config.OBSPROCYAML}") - prepaero_config = parse_j2yaml(self.task_config.OBSPROCYAML, self.task_config) - - return prepaero_config - - @logit(logger) - def link_obsconvexe(self) -> None: - """ - This method links the gdas executable to the run directory - Parameters - ---------- - Task: GDAS task - Returns - ---------- - None - """ - exe_src = self.task_config.OBSPROCEXE - - logger.info(f"Link executable {exe_src} to DATA/") - exe_dest = os.path.join(self.task_config.DATA, os.path.basename(exe_src)) - if os.path.exists(exe_dest): - rm_p(exe_dest) - os.symlink(exe_src, exe_dest) - - return - - @logit(logger) - def runConverter(self) -> None: - """ - Run the IODA converter gdas_obsprovider2ioda.x - """ - chdir(self.task_config.DATA) - exec_cmd = Executable(self.task_config.APRUN_PREPOBSAERO) - exec_name = os.path.join(self.task_config.DATA, 'gdas_obsprovider2ioda.x') - exec_cmd.add_default_arg(exec_name) - - for prepaero_yaml in self.task_config.prepaero_yaml: - try: - logger.debug(f"Executing {exec_cmd} on {prepaero_yaml}") - exec_cmd(f"{prepaero_yaml}") - except OSError: - raise OSError(f"Failed to execute {exec_cmd} on {prepaero_yaml}") - except Exception: - raise WorkflowException(f"An error occured during execution of {exec_cmd} on {prepaero_yaml}") - - pass - - @logit(logger) - def finalize(self) -> None: - """ - Copy the output viirs files to COMOUT_OBS. - Tar and archive the output files. - Tar and archive the raw obs files. - """ - # get list of viirs files - obsfiles = glob.glob(os.path.join(self.task_config['DATA'], '*viirs*nc4')) - copylist = [] - for obsfile in obsfiles: - basename = os.path.basename(obsfile) - src = os.path.join(self.task_config['DATA'], basename) - dest = os.path.join(self.task_config.COMOUT_OBS, basename) - copylist.append([src, dest]) - FileHandler({'copy': copylist}).sync() - - # gzip the files first - for obsfile in obsfiles: - with open(obsfile, 'rb') as f_in, gzip.open(f"{obsfile}.gz", 'wb') as f_out: - f_out.writelines(f_in) - - aeroobs = os.path.join(self.task_config.COMOUT_OBS, f"{self.task_config['APREFIX']}aeroobs") - # open tar file for writing - with tarfile.open(aeroobs, "w") as archive: - for obsfile in obsfiles: - aeroobsgzip = f"{obsfile}.gz" - archive.add(aeroobsgzip, arcname=os.path.basename(aeroobsgzip)) - # get list of raw viirs L2 files - rawfiles = glob.glob(os.path.join(self.task_config.DATA_OBS, 'JRR-AOD*')) - # gzip the raw L2 files first - for rawfile in rawfiles: - with open(rawfile, 'rb') as f_in, gzip.open(f"{rawfile}.gz", 'wb') as f_out: - f_out.writelines(f_in) - - aerorawobs = os.path.join(self.task_config.COMOUT_OBS, f"{self.task_config['APREFIX']}aerorawobs") - # open tar file for writing - with tarfile.open(aerorawobs, "w") as archive: - for rawfile in rawfiles: - aerorawobsgzip = f"{rawfile}.gz" - archive.add(aerorawobsgzip, arcname=os.path.basename(aerorawobsgzip)) - copylist = [] - for prepaero_yaml in self.task_config.prepaero_yaml: - basename = os.path.basename(prepaero_yaml) - dest = os.path.join(self.task_config.COMOUT_OBS, basename) - copylist.append([prepaero_yaml, dest]) - FileHandler({'copy': copylist}).sync() - - pass - - @logit(logger) - def syncObs(self) -> None: - """Create COMOUT_OBS and sync relevant obs from DMPDIR to COMOUT_OBS""" - # get list of files to copy - obslist = [] - obsin_list = glob.glob(os.path.join(self.task_config.COMIN_OBSPROC, '*aod*')) - for ob in obsin_list: - # replace gdas with gcdas in the dest - obslist.append([ob, - os.path.join(self.task_config.COMOUT_OBS, - os.path.basename(ob).replace('gdas', 'gcdas'))]) - # create output directory and copy files - FileHandler({'mkdir': [self.task_config.COMOUT_OBS], 'copy': obslist}).sync() diff --git a/ush/python/pygfs/task/atm_analysis.py b/ush/python/pygfs/task/atm_analysis.py index 75abf124e34..13d1069b620 100644 --- a/ush/python/pygfs/task/atm_analysis.py +++ b/ush/python/pygfs/task/atm_analysis.py @@ -35,6 +35,7 @@ def __init__(self, config: Dict[str, Any]): _res = int(self.task_config.CASE[1:]) _res_anl = int(self.task_config.CASE_ANL[1:]) + _res_his = int(self.task_config.CASE_HIST[1:]) if self.task_config.DOHYBVAR: _BERROR_YAML = f"atmosphere_background_error_hybrid_{self.task_config.STATICB_TYPE}_{self.task_config.LOCALIZATION_TYPE}" @@ -50,6 +51,9 @@ def __init__(self, config: Dict[str, Any]): 'npx_anl': _res_anl + 1, 'npy_anl': _res_anl + 1, 'npz_anl': self.task_config.LEVS - 1, + 'npx_his': _res_his + 1, + 'npy_his': _res_his + 1, + 'npz_his': self.task_config.LEVS - 1, 'npz': self.task_config.LEVS - 1, 'BKG_TSTEP': "PT1H", # Placeholder for 4D applications 'BERROR_YAML': _BERROR_YAML, diff --git a/versions/run.wcoss2.ver b/versions/run.wcoss2.ver index fd4db95025e..09398f4f8c0 100644 --- a/versions/run.wcoss2.ver +++ b/versions/run.wcoss2.ver @@ -43,7 +43,7 @@ export esmf_ver=8.8.0 export util_shared_ver=1.4.0 export ncdiag_ver=1.1.2 export g2tmpl_ver=1.10.2 -export crtm_ver=2.4.0.1 +export crtm_ver=2.4.0.2 export met_ver=9.1.3 export metplus_ver=3.1.1 From 6fed11cbe82179298de310abaf2db7aebdffb026 Mon Sep 17 00:00:00 2001 From: RussTreadon-NOAA <26926959+RussTreadon-NOAA@users.noreply.github.com> Date: Tue, 25 Nov 2025 14:04:49 -0500 Subject: [PATCH 02/27] remove obsolete GDASApp logic from build_compute.sh (#4275) (#4276) # Description This PR removes obsolete GDASApp logic from build_compute.sh Resolves #4275 --- sorc/build_compute.sh | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sorc/build_compute.sh b/sorc/build_compute.sh index 7e22f3b4f56..08c80c960bd 100755 --- a/sorc/build_compute.sh +++ b/sorc/build_compute.sh @@ -143,18 +143,6 @@ while [[ "${finished}" == "false" ]]; do fi done -# Wait for the GDASApp to finish building -if [[ -n "${build_gdas_id+0}" ]]; then - echo "Compute builds have completed successfully, but the GDASApp is still building locally. Waiting for it to complete." - wait "${build_gdas_id}" - gdas_stat=$? - if [[ ${gdas_stat} -ne 0 ]]; then - echo "FATAL ERROR The GDASApp failed to build! Check log in ${gdas_build_log}" - # Capture the error log in logs/error.logs - echo "${gdas_build_log}" >> "${err_file}" - exit 3 - fi -fi echo "All builds completed successfully!" exit 0 From add8922534b4e9002f82e072ebd89141a07501e7 Mon Sep 17 00:00:00 2001 From: Walter Kolczynski Date: Wed, 26 Nov 2025 07:42:13 -0500 Subject: [PATCH 03/27] Update bash ex-scripts to be linter compliant (#4151) Updates the ex-scripts to be compliant with both `shellcheck` and `shfmt`. This does _not_ necessarily enforce some standards not checked by `shellcheck`. Export statements are added to some variables to avoid 'not used' errors. In the future, a more careful analysis should be done to see if these variables are used downstream by executables or if they are truly unused, in which case they should be removed. Scripts employing MPMD are also updated to use `run_mpmd.sh`. This resulted in some retooling of those scripts. --- jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX | 1 - jobs/JGDAS_ENKF_SFC | 2 +- jobs/JGDAS_ENKF_UPDATE | 4 +- jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI | 4 +- jobs/JGLOBAL_ATMOS_SFCANL | 2 +- scripts/exgdas_atmos_chgres_forenkf.sh | 154 ++-- scripts/exgdas_atmos_gempak_gif_ncdc.sh | 8 +- scripts/exgdas_atmos_nawips.sh | 22 +- scripts/exgdas_atmos_verfozn.sh | 53 +- scripts/exgdas_atmos_verfrad.sh | 97 +-- scripts/exgdas_enkf_ecen.sh | 453 ++++++----- scripts/exgdas_enkf_post.sh | 152 ++-- scripts/exgdas_enkf_select_obs.sh | 12 +- scripts/exgdas_enkf_sfc.sh | 135 ++-- scripts/exgdas_enkf_update.sh | 185 ++--- scripts/exgfs_atmos_awips_20km_1p0deg.sh | 287 +++---- scripts/exgfs_atmos_fbwind.sh | 34 +- scripts/exgfs_atmos_gempak_gif_ncdc_skew_t.sh | 17 +- scripts/exgfs_atmos_gempak_meta.sh | 134 ++-- scripts/exgfs_atmos_goes_nawips.sh | 58 +- scripts/exgfs_atmos_grib2_special_npoess.sh | 219 +++--- scripts/exgfs_atmos_nawips.sh | 45 +- scripts/exgfs_atmos_postsnd.sh | 93 +-- scripts/exgfs_pmgr.sh | 80 +- scripts/exgfs_prdgen_manager.sh | 77 +- scripts/exgfs_wave_init.sh | 57 +- scripts/exgfs_wave_nawips.sh | 164 ++-- scripts/exgfs_wave_post_gridded_sbs.sh | 86 +- scripts/exgfs_wave_post_pnt.sh | 231 +++--- scripts/exgfs_wave_prdgen_bulls.sh | 154 ++-- scripts/exgfs_wave_prdgen_gridded.sh | 226 +++--- scripts/exgfs_wave_prep.sh | 579 ++++++-------- scripts/exglobal_atmos_analysis.sh | 736 +++++++++--------- scripts/exglobal_atmos_analysis_calc.sh | 177 ++--- scripts/exglobal_atmos_chgres_gen_control.sh | 26 +- scripts/exglobal_atmos_ensstat.sh | 6 +- scripts/exglobal_atmos_pmgr.sh | 79 +- scripts/exglobal_atmos_products.sh | 419 +++++----- scripts/exglobal_atmos_sfcanl.sh | 156 ++-- scripts/exglobal_atmos_tropcy_qc_reloc.sh | 241 +++--- scripts/exglobal_atmos_vminmon.sh | 13 +- scripts/exglobal_cleanup.sh | 30 +- scripts/exglobal_diag.sh | 348 ++++----- scripts/exglobal_extractvars.sh | 22 +- scripts/exglobal_forecast.sh | 20 +- scripts/exglobal_prep_sfc.sh | 90 +-- ush/preamble.sh | 1 + 47 files changed, 2944 insertions(+), 3245 deletions(-) diff --git a/jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX b/jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX index 2824af6cdd6..11e35d01590 100755 --- a/jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX +++ b/jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX @@ -16,7 +16,6 @@ YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COMIN_OBS:COM_OBS_TMPL \ COMIN_ATMOS_RESTART:COM_ATMOS_RESTART_TMPL \ COMOUT_CONF:COM_CONF_TMPL - mkdir -p "${COMOUT_CHEM_BMAT}" mkdir -p "${COMOUT_CONF}" diff --git a/jobs/JGDAS_ENKF_SFC b/jobs/JGDAS_ENKF_SFC index ee2bb8112a9..c2bfc6f33e4 100755 --- a/jobs/JGDAS_ENKF_SFC +++ b/jobs/JGDAS_ENKF_SFC @@ -37,7 +37,7 @@ RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ COMIN_ATMOS_ANALYSIS_DET_PREV:COM_ATMOS_ANALYSIS_TMPL # Use CFP to stage and save files in parallel - export USE_CFP=YES +export USE_CFP=YES ############################################################### # Run relevant script diff --git a/jobs/JGDAS_ENKF_UPDATE b/jobs/JGDAS_ENKF_UPDATE index 96d5dff079a..3b0d829591b 100755 --- a/jobs/JGDAS_ENKF_UPDATE +++ b/jobs/JGDAS_ENKF_UPDATE @@ -40,8 +40,8 @@ fi ############################################## # Send Alerts ############################################## -if [[ "${SENDDBN}" == "YES" ]] ; then - "${DBNROOT}/bin/dbn_alert" "MODEL" "ENKF1_MSC_enkfstat" "${job}" "${COMOUT_ATMOS_ANALYSIS_STAT}/${APREFIX}enkfstat.txt" +if [[ "${SENDDBN}" == "YES" ]]; then + "${DBNROOT}/bin/dbn_alert" "MODEL" "ENKF1_MSC_enkfstat" "${job}" "${COMOUT_ATMOS_ANALYSIS_STAT}/${APREFIX}enkfstat.txt" fi ############################################## diff --git a/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI b/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI index e14bf395744..e343fd235ca 100755 --- a/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI +++ b/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI @@ -26,9 +26,9 @@ YMD=${PDY} HH=${cyc} RUN=${RUN} declare_from_tmpl -rx \ YMD=${PDY} HH=${cyc} RUN=${RUN} declare_from_tmpl -rx \ COMOUT_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ - COMIN_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL + COMIN_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ - COMOUT_CONF:COM_CONF_TMPL + COMOUT_CONF:COM_CONF_TMPL mkdir -m 775 -p "${COMOUT_CONF}" diff --git a/jobs/JGLOBAL_ATMOS_SFCANL b/jobs/JGLOBAL_ATMOS_SFCANL index 41fdeec5969..59f542b729d 100755 --- a/jobs/JGLOBAL_ATMOS_SFCANL +++ b/jobs/JGLOBAL_ATMOS_SFCANL @@ -33,7 +33,7 @@ RUN="enkfgdas" MEMDIR="ensstat" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ mkdir -p "${COMOUT_ATMOS_RESTART}" # Use CFP to stage and save files in parallel - export USE_CFP=YES +export USE_CFP=YES ############################################################### # Run relevant script diff --git a/scripts/exgdas_atmos_chgres_forenkf.sh b/scripts/exgdas_atmos_chgres_forenkf.sh index 04e720d3e64..f51be67b285 100755 --- a/scripts/exgdas_atmos_chgres_forenkf.sh +++ b/scripts/exgdas_atmos_chgres_forenkf.sh @@ -26,9 +26,10 @@ GDUMP=${GDUMP:-"gdas"} # Derived base variables # shellcheck disable=SC2153 GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") +export GDATE BDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - 3 hours") -bPDY=${BDATE:0:8} -bcyc=${BDATE:8:2} +export bPDY=${BDATE:0:8} +export bcyc=${BDATE:8:2} # Utilities export CHGRP_CMD=${CHGRP_CMD:-"chgrp ${group_name:-rstprod}"} @@ -73,111 +74,80 @@ DOHYBVAR=${DOHYBVAR:-"NO"} lrun_subdirs=${lrun_subdirs:-".true."} USE_CFP=${USE_CFP:-"NO"} CFP_MP=${CFP_MP:-"NO"} -nm="" -if [ $CFP_MP = "YES" ]; then - nm=0 -fi -if [ $DOHYBVAR = "YES" ]; then - l_hyb_ens=.true. - export l4densvar=${l4densvar:-".false."} - export lwrite4danl=${lwrite4danl:-".false."} + +if [[ "${DOHYBVAR}" == "YES" ]]; then + export l_hyb_ens=.true. + export l4densvar=${l4densvar:-".false."} + export lwrite4danl=${lwrite4danl:-".false."} else - echo "DOHYBVAR != YES, this script will exit without regridding deterministic forecast" - exit 0 + echo "DOHYBVAR != YES, this script will exit without regridding deterministic forecast" + exit 0 fi ################################################################################ ################################################################################ # get resolution information -LONB_ENKF=${LONB_ENKF:-$($NCLEN $ATMFCST_ENSRES grid_xt)} # get LONB_ENKF -LATB_ENKF=${LATB_ENKF:-$($NCLEN $ATMFCST_ENSRES grid_yt)} # get LATB_ENFK -LEVS_ENKF=${LEVS_ENKF:-$($NCLEN $ATMFCST_ENSRES pfull)} # get LATB_ENFK +LONB_ENKF=${LONB_ENKF:-$(${NCLEN} "${ATMFCST_ENSRES}" grid_xt)} # get LONB_ENKF +LATB_ENKF=${LATB_ENKF:-$(${NCLEN} "${ATMFCST_ENSRES}" grid_yt)} # get LATB_ENFK +LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} "${ATMFCST_ENSRES}" pfull)} # get LATB_ENFK ############################################################## # If analysis increment is written by GSI, regrid forecasts to increment resolution -if [ $DO_CALC_ANALYSIS == "YES" ]; then - $NLN $ATMF06 fcst.06 - $NLN $ATMF06ENS fcst.ensres.06 - $NLN $ATMFCST_ENSRES atmens_fcst - if [ $DOHYBVAR = "YES" -a $l4densvar = ".true." -a $lwrite4danl = ".true." ]; then - $NLN $ATMF03 fcst.03 - $NLN $ATMF03ENS fcst.ensres.03 - $NLN $ATMF04 fcst.04 - $NLN $ATMF04ENS fcst.ensres.04 - $NLN $ATMF05 fcst.05 - $NLN $ATMF05ENS fcst.ensres.05 - $NLN $ATMF07 fcst.07 - $NLN $ATMF07ENS fcst.ensres.07 - $NLN $ATMF08 fcst.08 - $NLN $ATMF08ENS fcst.ensres.08 - $NLN $ATMF09 fcst.09 - $NLN $ATMF09ENS fcst.ensres.09 - fi - export OMP_NUM_THREADS=$NTHREADS_CHGRES - SIGLEVEL=${SIGLEVEL:-${FIXgfs}/am/global_hyblev.l${LEVS_ENKF}.txt} - - if [[ "${USE_CFP}" == "YES" ]]; then - rm -f "${DATA}/mp_chgres.sh" - fi - - nfhrs=$(echo "${IAUFHRS_ENKF}" | sed 's/,/ /g') - for FHR in $nfhrs; do - echo "Regridding deterministic forecast for forecast hour $FHR" - rm -f chgres_nc_gauss0$FHR.nml -cat > chgres_nc_gauss0$FHR.nml << EOF +if [[ ${DO_CALC_ANALYSIS} == "YES" ]]; then + ${NLN} "${ATMF06}" fcst.06 + ${NLN} "${ATMF06ENS}" fcst.ensres.06 + ${NLN} "${ATMFCST_ENSRES}" atmens_fcst + if [[ "${DOHYBVAR}" == "YES" ]] && [[ "${l4densvar}" == ".true." ]] && [[ "${lwrite4danl}" == ".true." ]]; then + ${NLN} "${ATMF03}" fcst.03 + ${NLN} "${ATMF03ENS}" fcst.ensres.03 + ${NLN} "${ATMF04}" fcst.04 + ${NLN} "${ATMF04ENS}" fcst.ensres.04 + ${NLN} "${ATMF05}" fcst.05 + ${NLN} "${ATMF05ENS}" fcst.ensres.05 + ${NLN} "${ATMF07}" fcst.07 + ${NLN} "${ATMF07ENS}" fcst.ensres.07 + ${NLN} "${ATMF08}" fcst.08 + ${NLN} "${ATMF08ENS}" fcst.ensres.08 + ${NLN} "${ATMF09}" fcst.09 + ${NLN} "${ATMF09ENS}" fcst.ensres.09 + fi + export OMP_NUM_THREADS=${NTHREADS_CHGRES} + SIGLEVEL=${SIGLEVEL:-${FIXgfs}/am/global_hyblev.l${LEVS_ENKF}.txt} + + if [[ "${USE_CFP}" == "YES" ]]; then + rm -f "${DATA}/mp_chgres.sh" + fi + + nfhrs="${IAUFHRS_ENKF//,/ }" + for FHR in ${nfhrs}; do + echo "Regridding deterministic forecast for forecast hour ${FHR}" + rm -f "chgres_nc_gauss0${FHR}.nml" + cat > "chgres_nc_gauss0${FHR}.nml" << EOF &chgres_setup -i_output=$LONB_ENKF -j_output=$LATB_ENKF -input_file="fcst.0$FHR" -output_file="fcst.ensres.0$FHR" -terrain_file="atmens_fcst" -ref_file="atmens_fcst" + i_output=${LONB_ENKF} + j_output=${LATB_ENKF} + input_file="fcst.0${FHR}" + output_file="fcst.ensres.0${FHR}" + terrain_file="atmens_fcst" + ref_file="atmens_fcst" / EOF - if [[ $USE_CFP == "YES" ]]; then - echo "$nm $APRUN_CHGRES $CHGRESNCEXEC chgres_nc_gauss0$FHR.nml" | tee -a $DATA/mp_chgres.sh - if [[ ${CFP_MP:-"NO"} = "YES" ]]; then - nm=$((nm+1)) - fi - else - - export pgm=$CHGRESNCEXEC - . prep_step - - ${APRUN_CHGRES} "${CHGRESNCEXEC}" "chgres_nc_gauss0${FHR}.nml" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit - fi - fi - done - - if [[ ${USE_CFP} == "YES" ]]; then - chmod 755 ${DATA}/mp_chgres.sh - ncmd=$(wc -l < "${DATA}/mp_chgres.sh") - if [[ ${ncmd} -gt 0 ]]; then - ncmd_max=$((ncmd < max_tasks_per_node ? ncmd : max_tasks_per_node)) - APRUNCFP_CHGRES=$(eval echo "${APRUNCFP}") - - export pgm=${CHGRESNCEXEC} - source prep_step - - ${APRUNCFP_CHGRES} "${DATA}/mp_chgres.sh" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit - fi - fi - fi + echo "${APRUN_CHGRES} ${CHGRESNCEXEC} chgres_nc_gauss0${FHR}.nml" | tee -a "${DATA}/mp_chgres.sh" + + done + + # Run with MPMD + "${USHgfs}/run_mpmd.sh" "${DATA}/mp_chgres.sh" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit + fi else - echo "DO_CALC_ANALYSIS != YES, doing nothing" + echo "DO_CALC_ANALYSIS != YES, doing nothing" fi +cd "${pwd}" || exit -################################################################################ -# Postprocessing -cd $pwd - -exit $err +exit "${err}" diff --git a/scripts/exgdas_atmos_gempak_gif_ncdc.sh b/scripts/exgdas_atmos_gempak_gif_ncdc.sh index 06c6f2ce496..aaa4072cc7f 100755 --- a/scripts/exgdas_atmos_gempak_gif_ncdc.sh +++ b/scripts/exgdas_atmos_gempak_gif_ncdc.sh @@ -18,17 +18,17 @@ if [[ ${MODEL} == GDAS ]]; then export fhr3 for fhr3 in ${fcsthrs}; do gempak_file="${COMIN_ATMOS_GEMPAK_1p00}/${RUN}_1p00_${PDY}${cyc}f${fhr3}" - if ! wait_for_file "${gempak_file}" "${sleep_interval}" "${max_tries}" ; then + if ! wait_for_file "${gempak_file}" "${sleep_interval}" "${max_tries}"; then export err=10 if [[ ${err} -ne 0 ]]; then - err_exit "${gempak_file} not found after ${max_tries} iterations" + err_exit "${gempak_file} not found after ${max_tries} iterations" fi fi if [[ ! -f "${gempak_file}" ]]; then export err=1 if [[ ${err} -ne 0 ]]; then - err_exit "Could not copy ${gempak_file}" + err_exit "Could not copy ${gempak_file}" fi fi @@ -37,7 +37,7 @@ if [[ ${MODEL} == GDAS ]]; then "${HOMEgfs}/gempak/ush/gempak_${RUN}_f${fhr3}_gif.sh" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit + err_exit fi done fi diff --git a/scripts/exgdas_atmos_nawips.sh b/scripts/exgdas_atmos_nawips.sh index 786b1c2b431..7bebb7766df 100755 --- a/scripts/exgdas_atmos_nawips.sh +++ b/scripts/exgdas_atmos_nawips.sh @@ -18,11 +18,11 @@ cd "${DATA_RUN}" || exit 1 source "${USHgfs}/product_functions.sh" for table in g2varswmo2.tbl g2vcrdwmo2.tbl g2varsncep1.tbl g2vcrdncep1.tbl; do - source_table="${HOMEgfs}/gempak/fix/${table}" - if [[ ! -f "${source_table}" ]]; then - err_exit "${table} is missing" - fi - cpreq "${source_table}" "${table}" + source_table="${HOMEgfs}/gempak/fix/${table}" + if [[ ! -f "${source_table}" ]]; then + err_exit "${table} is missing" + fi + cpreq "${source_table}" "${table}" done NAGRIB="${GEMEXE}/nagrib2" @@ -37,15 +37,13 @@ proj= output=T pdsext=no - - GEMGRD="${RUN}_${grid}_${PDY}${cyc}f${fhr3}" source_dirvar="COMOUT_ATMOS_GRIB_${grid}" export GRIBIN="${!source_dirvar}/${RUN}.${cycle}.pres_a.${grid}.f${fhr3}.grib2" GRIBIN_chk="${GRIBIN}.idx" if [[ ! -r "${GRIBIN_chk}" ]]; then - err_exit "GRIB index file ${GRIBIN_chk} not found!" + err_exit "GRIB index file ${GRIBIN_chk} not found!" fi cpreq "${GRIBIN}" "grib${fhr3}" @@ -73,13 +71,13 @@ EOF export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "${NAGRIB} failed to create ${GEMGRD}!" + err_exit "${NAGRIB} failed to create ${GEMGRD}!" fi cpfs "${GEMGRD}" "${destination}/${GEMGRD}" -if [[ "${SENDDBN}" == "YES" ]] ; then - "${DBNROOT}/bin/dbn_alert" MODEL "${DBN_ALERT_TYPE}" "${job}" \ - "${destination}/${GEMGRD}" +if [[ "${SENDDBN}" == "YES" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${DBN_ALERT_TYPE}" "${job}" \ + "${destination}/${GEMGRD}" fi "${GEMEXE}/gpend" diff --git a/scripts/exgdas_atmos_verfozn.sh b/scripts/exgdas_atmos_verfozn.sh index 30a945ab914..e6f3a369da8 100755 --- a/scripts/exgdas_atmos_verfozn.sh +++ b/scripts/exgdas_atmos_verfozn.sh @@ -9,42 +9,35 @@ ################################################################################ export err=0 -data_available=0 +if [[ -s "${oznstat}" ]]; then + #------------------------------------------------------------------ + # Copy data files file to local data directory. + # Untar oznstat file. + #------------------------------------------------------------------ -if [[ -s ${oznstat} ]]; then - data_available=1 + cpreq "${oznstat}" "./oznstat.${PDY}${cyc}" - #------------------------------------------------------------------ - # Copy data files file to local data directory. - # Untar oznstat file. - #------------------------------------------------------------------ + tar -xvf "oznstat.${PDY}${cyc}" + rm -f "oznstat.${PDY}${cyc}" - cpreq "${oznstat}" "./oznstat.${PDY}${cyc}" + netcdf=0 + for filenc4 in diag*nc4.gz; do + netcdf=1 + file=$(echo "${filenc4}" | cut -d'.' -f1-2).gz + mv "${filenc4}" "${file}" + done - tar -xvf "oznstat.${PDY}${cyc}" - rm -f "oznstat.${PDY}${cyc}" + export OZNMON_NETCDF=${netcdf} - netcdf=0 - count=$(ls diag* | grep ".nc4" | wc -l) - if [ "${count}" -gt 0 ] ; then - netcdf=1 - for filenc4 in $(ls diag*nc4.gz); do - file=$(echo "${filenc4}" | cut -d'.' -f1-2).gz - mv "${filenc4}" "${file}" - done - fi - - export OZNMON_NETCDF=${netcdf} - - "${USHgfs}/ozn_xtrct.sh" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "ozn_xtrct.sh failed!" - fi + "${USHgfs}/ozn_xtrct.sh" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "ozn_xtrct.sh failed!" + fi else - # oznstat file not found - export err=1 - err_exit "${oznstat} does not exist!" + # oznstat file not found + export err=1 + err_exit "${oznstat} does not exist!" fi exit 0 diff --git a/scripts/exgdas_atmos_verfrad.sh b/scripts/exgdas_atmos_verfrad.sh index aece88c12a9..7fe7dbc0934 100755 --- a/scripts/exgdas_atmos_verfrad.sh +++ b/scripts/exgdas_atmos_verfrad.sh @@ -20,9 +20,9 @@ # Do not exit on errors so that restricted data can be protected set +eu -if [[ ! -s ${radstat} || ! -s ${biascr} ]]; then - export err=1 - err_exit "Required data files ${radstat} and/or ${biascr} are missing!!" +if [[ ! -s "${radstat}" || ! -s "${biascr}" ]]; then + export err=1 + err_exit "Required data files ${radstat} and/or ${biascr} are missing!!" fi #------------------------------------------------------------------ @@ -30,7 +30,7 @@ fi # Untar radstat file. #------------------------------------------------------------------ -cpreq "${biascr}" "./biascr.${PDY}${cyc}" +cpreq "${biascr}" "./biascr.${PDY}${cyc}" cpreq "${radstat}" "./radstat.${PDY}${cyc}" tar -xvf "radstat.${PDY}${cyc}" @@ -44,9 +44,10 @@ rm "radstat.${PDY}${cyc}" # new sources to the list before writing back out. #------------------------------------------------------------------ -radstat_satype=$(ls d*ges* | awk -F_ '{ print $2 "_" $3 }') -if [[ "${VERBOSE}" = "YES" ]]; then - echo "${radstat_satype}" +radstat_files=$(find ./ -name 'd*ges*') +radstat_satype=$(awk -F_ '{ print $2 "_" $3 }' <<< "${radstat_files}") +if [[ "${VERBOSE}" == "YES" ]]; then + echo "${radstat_satype}" fi echo satype_file = "${satype_file}" @@ -57,14 +58,15 @@ echo satype_file = "${satype_file}" # the cycle being processed is 00z. #------------------------------------------------------------------ if [[ ${cyc} = "00" ]]; then - use_tankdir=${TANKverf_radM1} + use_tankdir=${TANKverf_radM1} else - use_tankdir=${TANKverf_rad} + use_tankdir=${TANKverf_rad} fi +export use_tankdir echo satype_file = "${satype_file}" -export SATYPE=$(cat "${satype_file}") - +SATYPE=$(cat "${satype_file}") +export SATYPE #------------------------------------------------------------- # Update the SATYPE if any new sat/instrument was @@ -74,19 +76,19 @@ export SATYPE=$(cat "${satype_file}") satype_changes=0 new_satype=${SATYPE} for type in ${radstat_satype}; do - type_count=$(echo "${SATYPE}" | grep "${type}" | wc -l) - - if [[ ${type_count} -eq 0 ]]; then - if [[ "${VERBOSE}" = "YES" ]]; then - echo "Found ${type} in radstat file but not in SATYPE list. Adding it now." - fi - satype_changes=1 - new_satype="${new_satype} ${type}" - fi + type_count=$(grep -c "${type}" <<< "${SATYPE}") + + if [[ ${type_count} -eq 0 ]]; then + if [[ "${VERBOSE}" = "YES" ]]; then + echo "Found ${type} in radstat file but not in SATYPE list. Adding it now." + fi + satype_changes=1 + new_satype="${new_satype} ${type}" + fi done if [[ ${satype_changes} -eq 1 ]]; then - SATYPE=${new_satype} + SATYPE=${new_satype} fi #------------------------------------------------------------------ @@ -96,31 +98,32 @@ netcdf=0 for type in ${SATYPE}; do - if [[ ${netcdf} -eq 0 && -e "diag_${type}_ges.${PDY}${cyc}.nc4.${Z}" ]]; then - netcdf=1 - fi - - if [[ $(find . -maxdepth 1 -type f -name "diag_${type}_ges.${PDY}${cyc}*.${Z}" | wc -l) -gt 0 ]]; then - mv "diag_${type}_ges.${PDY}${cyc}"*".${Z}" "${type}.${Z}" - ${UNCOMPRESS} "./${type}.${Z}" - else - echo "WARNING: diag_${type}_ges.${PDY}${cyc}*.${Z} not available, skipping" - fi - - if [[ ${USE_ANL} -eq 1 ]]; then - file_count=$(find . -maxdepth 1 -type f -name "diag_${type}_anl.${PDY}${cyc}*.${Z}" | wc -l) - if [[ ${file_count} -gt 0 ]]; then - mv "diag_${type}_anl.${PDY}${cyc}"*".${Z}" "${type}_anl.${Z}" - ${UNCOMPRESS} "./${type}_anl.${Z}" - else - echo "WARNING: diag_${type}_anl.${PDY}${cyc}*.${Z} not available, skipping" - fi - fi + if [[ ${netcdf} -eq 0 && -e "diag_${type}_ges.${PDY}${cyc}.nc4.${Z}" ]]; then + netcdf=1 + fi + + # shellcheck disable=SC2312 + if [[ $(find . -maxdepth 1 -type f -name "diag_${type}_ges.${PDY}${cyc}*.${Z}" | wc -l) -gt 0 ]]; then + mv "diag_${type}_ges.${PDY}${cyc}"*".${Z}" "${type}.${Z}" + ${UNCOMPRESS} "./${type}.${Z}" + else + echo "WARNING: diag_${type}_ges.${PDY}${cyc}*.${Z} not available, skipping" + fi + + if [[ ${USE_ANL} -eq 1 ]]; then + # shellcheck disable=SC2312 + file_count=$(find . -maxdepth 1 -type f -name "diag_${type}_anl.${PDY}${cyc}*.${Z}" | wc -l) + if [[ ${file_count} -gt 0 ]]; then + mv "diag_${type}_anl.${PDY}${cyc}"*".${Z}" "${type}_anl.${Z}" + ${UNCOMPRESS} "./${type}_anl.${Z}" + else + echo "WARNING: diag_${type}_anl.${PDY}${cyc}*.${Z} not available, skipping" + fi + fi done export RADMON_NETCDF=${netcdf} - #------------------------------------------------------------------ # Run the child scripts. #------------------------------------------------------------------ @@ -131,7 +134,7 @@ rc_angle=$? # Allow all scripts to run. Call err_exit at the end, after files are restricted. if [[ ${rc_angle} -ne 0 ]]; then - echo "FATAL ERROR: radmon_verf_angle.sh failed!" + echo "FATAL ERROR: radmon_verf_angle.sh failed!" fi "${USHgfs}/radmon_verf_bcoef.sh" && true @@ -139,7 +142,7 @@ rc_bcoef=$? "${USHgfs}/rstprod.sh" if [[ ${rc_bcoef} -ne 0 ]]; then - echo "FATAL ERROR: radmon_verf_bcoef.sh failed!" + echo "FATAL ERROR: radmon_verf_bcoef.sh failed!" fi "${USHgfs}/radmon_verf_bcor.sh" && true @@ -147,7 +150,7 @@ rc_bcor=$? "${USHgfs}/rstprod.sh" if [[ ${rc_bcoef} -ne 0 ]]; then - echo "FATAL ERROR: radmon_verf_bcor.sh failed!" + echo "FATAL ERROR: radmon_verf_bcor.sh failed!" fi "${USHgfs}/radmon_verf_time.sh" && true @@ -155,7 +158,7 @@ rc_time=$? "${USHgfs}/rstprod.sh" if [[ ${rc_bcoef} -ne 0 ]]; then - echo "FATAL ERROR: radmon_verf_time.sh failed!" + echo "FATAL ERROR: radmon_verf_time.sh failed!" fi ##################################################################### @@ -164,7 +167,7 @@ fi export err=$((rc_angle + rc_bcoef + rc_bcor + rc_time)) if [[ ${err} -ne 0 ]]; then - err_exit "One or more radiance monitor subtasks failed!" + err_exit "One or more radiance monitor subtasks failed!" fi exit 0 diff --git a/scripts/exgdas_enkf_ecen.sh b/scripts/exgdas_enkf_ecen.sh index d2a4ff726aa..b20099bfe2c 100755 --- a/scripts/exgdas_enkf_ecen.sh +++ b/scripts/exgdas_enkf_ecen.sh @@ -46,21 +46,21 @@ GPREFIX_ENS=${GPREFIX_ENS:-${GPREFIX}} # Variables imp_physics=${imp_physics:-99} INCREMENTS_TO_ZERO=${INCREMENTS_TO_ZERO:-"'NONE'"} -DOIAU=${DOIAU_ENKF:-"NO"} +export DOIAU=${DOIAU_ENKF:-"NO"} FHMIN=${FHMIN_ECEN:-3} FHMAX=${FHMAX_ECEN:-9} FHOUT=${FHOUT_ECEN:-3} -FHSFC=${FHSFC_ECEN:-${FHMIN}} +export FHSFC=${FHSFC_ECEN:-${FHMIN}} NMEM_ENS_MAX=${NMEM_ENS:-80} if [[ "${RUN}" = "enkfgfs" ]]; then - DO_CALC_INCREMENT=${DO_CALC_INCREMENT_ENKF_GFS:-"NO"} - NMEM_ENS=${NMEM_ENS_GFS:-30} - ec_offset=${NMEM_ENS_GFS_OFFSET:-20} - mem_offset=$((ec_offset * cyc/6)) + DO_CALC_INCREMENT=${DO_CALC_INCREMENT_ENKF_GFS:-"NO"} + NMEM_ENS=${NMEM_ENS_GFS:-30} + ec_offset=${NMEM_ENS_GFS_OFFSET:-20} + mem_offset=$((ec_offset * cyc / 6)) else - DO_CALC_INCREMENT=${DO_CALC_INCREMENT:-"NO"} - NMEM_ENS=${NMEM_ENS:-80} - mem_offset=0 + DO_CALC_INCREMENT=${DO_CALC_INCREMENT:-"NO"} + NMEM_ENS=${NMEM_ENS:-80} + mem_offset=0 fi # global_chgres stuff @@ -78,7 +78,6 @@ export CYCLVARS=${CYCLVARS:-"FSNOL=-2.,FSNOS=99999.,"} export FHOUR=${FHOUR:-0} export DELTSFC=${DELTSFC:-6} - RECENTER_ENKF=${RECENTER_ENKF:-"YES"} SMOOTH_ENKF=${SMOOTH_ENKF:-"YES"} @@ -97,141 +96,137 @@ fi ################################################################################ # Link ensemble member guess, analysis and increment files -for FHR in $(seq ${FHMIN} ${FHOUT} ${FHMAX}); do - -for imem in $(seq 1 ${NMEM_ENS}); do - smem=$((imem + mem_offset)) - if (( smem > NMEM_ENS_MAX )); then - smem=$((smem - NMEM_ENS_MAX)) - fi - gmemchar="mem"$(printf %03i ${smem}) - memchar="mem"$(printf %03i ${imem}) - - MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl -x \ - COMOUT_ATMOS_ANALYSIS_MEM:COM_ATMOS_ANALYSIS_TMPL - - MEMDIR=${gmemchar} RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -x \ - COMIN_ATMOS_HISTORY_MEM_PREV:COM_ATMOS_HISTORY_TMPL - - ${NLN} "${COMIN_ATMOS_HISTORY_MEM_PREV}/${GPREFIX_ENS}atm.f00${FHR}${ENKF_SUFFIX}.nc" "./atmges_${memchar}" - if [[ ${DO_CALC_INCREMENT} = "YES" ]]; then - ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX_ENS}analysis.atm.a00${FHR}.nc" "./atmanl_${memchar}" - fi - mkdir -p "${COMOUT_ATMOS_ANALYSIS_MEM}" - ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX_ENS}increment.atm.i00${FHR}.nc" "./atminc_${memchar}" - if [[ ${RECENTER_ENKF} = "YES" ]]; then - if [[ ${DO_CALC_INCREMENT} = "YES" ]]; then - ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX_ENS}recentered_analysis.atm.a006.nc" "./ratmanl_${memchar}" - else - ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX_ENS}recentered_increment.atm.i00${FHR}.nc" "./ratminc_${memchar}" - fi - fi -done - -if [[ ${DO_CALC_INCREMENT} = "YES" ]]; then - # Link ensemble mean analysis - ${NLN} "${COMOUT_ATMOS_ANALYSIS_STAT}/${APREFIX_ENS}ensmean_analysis.atm.a00${FHR}.nc" "./atmanl_ensmean" - - # Compute ensemble mean analysis - DATAPATH="./" - ATMANLNAME="atmanl" - ATMANLMEANNAME="atmanl_ensmean" - - export OMP_NUM_THREADS=${NTHREADS_ECEN} - export pgm=${GETATMENSMEANEXEC} - source prep_step - - cpreq ${GETATMENSMEANEXEC} ${DATA} - ${APRUN_ECEN} ${DATA}/$(basename ${GETATMENSMEANEXEC}) ${DATAPATH} ${ATMANLMEANNAME} ${ATMANLNAME} ${NMEM_ENS} - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to recenter the ensemble analyses!" - fi -else - # Link ensemble mean increment - ${NLN} "${COMOUT_ATMOS_ANALYSIS_STAT}/${APREFIX_ENS}ensmean_increment.atm.i00${FHR}.nc" "./atminc_ensmean" - - # Compute ensemble mean increment - DATAPATH="./" - ATMINCNAME="atminc" - ATMINCMEANNAME="atminc_ensmean" - - export OMP_NUM_THREADS=${NTHREADS_ECEN} - export pgm=${GETATMENSMEANEXEC} - source prep_step - - cpreq ${GETATMENSMEANEXEC} ${DATA} - ${APRUN_ECEN} ${DATA}/$(basename ${GETATMENSMEANEXEC}) ${DATAPATH} ${ATMINCMEANNAME} ${ATMINCNAME} ${NMEM_ENS} - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to recenter the ensemble increments!" - fi - - # If available, link to ensemble mean guess. Otherwise, compute ensemble mean guess - if [[ -s "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX_ENS}ensmean.atm.f00${FHR}.nc" ]]; then - ${NLN} "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX_ENS}ensmean.atm.f00${FHR}.nc" "./atmges_ensmean" - else - DATAPATH="./" - ATMGESNAME="atmges" - ATMGESMEANNAME="atmges_ensmean" - - export OMP_NUM_THREADS=${NTHREADS_ECEN} - export pgm=${GETATMENSMEANEXEC} - source prep_step - - cpreq ${GETATMENSMEANEXEC} ${DATA} - ${APRUN_ECEN} ${DATA}/$(basename ${GETATMENSMEANEXEC}) ${DATAPATH} ${ATMGESMEANNAME} ${ATMGESNAME} ${NMEM_ENS} - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to recenter the ensemble mean guess!" - fi - fi -fi - -if [[ ${DO_CALC_INCREMENT} = "YES" ]]; then - LONB_ENKF=${LONB_ENKF:-$(${NCLEN} atmanl_ensmean grid_xt)} # get LONB - LATB_ENKF=${LATB_ENKF:-$(${NCLEN} atmanl_ensmean grid_yt)} # get LATB - LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} atmanl_ensmean pfull)} # get LEVS -else - LONB_ENKF=${LONB_ENKF:-$(${NCLEN} atminc_ensmean lon)} # get LONB - LATB_ENKF=${LATB_ENKF:-$(${NCLEN} atminc_ensmean lat)} # get LATB - LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} atminc_ensmean lev)} # get LEVS -fi -JCAP_ENKF=${JCAP_ENKF:--9999} # there is no jcap in these files -if [[ ${JCAP_ENKF} -eq -9999 && ${LATB_ENKF} -ne -9999 ]]; then - JCAP_ENKF=$((LATB_ENKF-2)) -fi -if [[ ${LONB_ENKF} -eq -9999 || ${LATB_ENKF} -eq -9999 || ${LEVS_ENKF} -eq -9999 || ${JCAP_ENKF} -eq -9999 ]]; then - export err=9 - err_exit "One or more EnKF background parameters are undefined!" -fi - -################################################################################ -# This is to give the user the option to recenter, default is YES -if [[ ${RECENTER_ENKF} = "YES" ]]; then - - # GSI EnVar analysis - ATMANL_GSI="${COMIN_ATMOS_ANALYSIS_DET}/${APREFIX}analysis.atm.a00${FHR}.nc" - ATMANL_GSI_ENSRES="${COMIN_ATMOS_ANALYSIS_DET}/${APREFIX}ensres_analysis.atm.a00${FHR}.nc" - - # if we already have a ensemble resolution GSI analysis then just link to it - if [[ -f ${ATMANL_GSI_ENSRES} ]]; then - - ${NLN} ${ATMANL_GSI_ENSRES} atmanl_gsi_ensres - - else - - ${NLN} ${ATMANL_GSI} atmanl_gsi - ${NLN} ${ATMANL_GSI_ENSRES} atmanl_gsi_ensres - SIGLEVEL=${SIGLEVEL:-${FIXgfs}/am/global_hyblev.l${LEVS}.txt} - ${NLN} ${CHGRESNC} chgres.x - chgresnml=chgres_nc_gauss.nml - nmltitle=chgres - - export OMP_NUM_THREADS=${NTHREADS_CHGRES} - - rm -f "${chgresnml}" - cat > "${chgresnml}" << EOF +for FHR in $(seq "${FHMIN}" "${FHOUT}" "${FHMAX}"); do + + for imem in $(seq 1 "${NMEM_ENS}"); do + smem=$((imem + mem_offset)) + if ((smem > NMEM_ENS_MAX)); then + smem=$((smem - NMEM_ENS_MAX)) + fi + gmemchar="mem"$(printf %03i "${smem}") + memchar="mem"$(printf %03i "${imem}") + + MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl -x \ + COMOUT_ATMOS_ANALYSIS_MEM:COM_ATMOS_ANALYSIS_TMPL + + MEMDIR=${gmemchar} RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -x \ + COMIN_ATMOS_HISTORY_MEM_PREV:COM_ATMOS_HISTORY_TMPL + + ${NLN} "${COMIN_ATMOS_HISTORY_MEM_PREV}/${GPREFIX_ENS}atm.f00${FHR}${ENKF_SUFFIX}.nc" "./atmges_${memchar}" + if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then + ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX_ENS}analysis.atm.a00${FHR}.nc" "./atmanl_${memchar}" + fi + mkdir -p "${COMOUT_ATMOS_ANALYSIS_MEM}" + ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX_ENS}increment.atm.i00${FHR}.nc" "./atminc_${memchar}" + if [[ "${RECENTER_ENKF}" == "YES" ]]; then + if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then + ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX_ENS}recentered_analysis.atm.a006.nc" "./ratmanl_${memchar}" + else + ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX_ENS}recentered_increment.atm.i00${FHR}.nc" "./ratminc_${memchar}" + fi + fi + done + + if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then + # Link ensemble mean analysis + ${NLN} "${COMOUT_ATMOS_ANALYSIS_STAT}/${APREFIX_ENS}ensmean_analysis.atm.a00${FHR}.nc" "./atmanl_ensmean" + + # Compute ensemble mean analysis + DATAPATH="./" + ATMANLNAME="atmanl" + ATMANLMEANNAME="atmanl_ensmean" + + export OMP_NUM_THREADS=${NTHREADS_ECEN} + export pgm=${GETATMENSMEANEXEC} + source prep_step + + cpreq "${GETATMENSMEANEXEC}" "${DATA}" + ${APRUN_ECEN} "${DATA}/$(basename "${GETATMENSMEANEXEC}")" "${DATAPATH}" "${ATMANLMEANNAME}" "${ATMANLNAME}" "${NMEM_ENS}" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "FATAL ERROR: Failed to recenter the ensemble analyses!" + fi + else + # Link ensemble mean increment + ${NLN} "${COMOUT_ATMOS_ANALYSIS_STAT}/${APREFIX_ENS}ensmean_increment.atm.i00${FHR}.nc" "./atminc_ensmean" + + # Compute ensemble mean increment + DATAPATH="./" + ATMINCNAME="atminc" + ATMINCMEANNAME="atminc_ensmean" + + export OMP_NUM_THREADS=${NTHREADS_ECEN} + export pgm=${GETATMENSMEANEXEC} + source prep_step + + cpreq "${GETATMENSMEANEXEC}" "${DATA}" + ${APRUN_ECEN} "${DATA}/$(basename "${GETATMENSMEANEXEC}")" "${DATAPATH}" "${ATMINCMEANNAME}" "${ATMINCNAME}" "${NMEM_ENS}" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to recenter the ensemble increments!" + fi + + # If available, link to ensemble mean guess. Otherwise, compute ensemble mean guess + if [[ -s "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX_ENS}ensmean.atm.f00${FHR}.nc" ]]; then + ${NLN} "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX_ENS}ensmean.atm.f00${FHR}.nc" "./atmges_ensmean" + else + DATAPATH="./" + ATMGESNAME="atmges" + ATMGESMEANNAME="atmges_ensmean" + + export OMP_NUM_THREADS=${NTHREADS_ECEN} + export pgm=${GETATMENSMEANEXEC} + source prep_step + + cpreq "${GETATMENSMEANEXEC}" "${DATA}" + ${APRUN_ECEN} "${DATA}/$(basename "${GETATMENSMEANEXEC}")" "${DATAPATH}" "${ATMGESMEANNAME}" "${ATMGESNAME}" "${NMEM_ENS}" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to recenter the ensemble mean guess!" + fi + fi + fi + + if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then + LONB_ENKF=${LONB_ENKF:-$(${NCLEN} atmanl_ensmean grid_xt)} # get LONB + LATB_ENKF=${LATB_ENKF:-$(${NCLEN} atmanl_ensmean grid_yt)} # get LATB + LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} atmanl_ensmean pfull)} # get LEVS + else + LONB_ENKF=${LONB_ENKF:-$(${NCLEN} atminc_ensmean lon)} # get LONB + LATB_ENKF=${LATB_ENKF:-$(${NCLEN} atminc_ensmean lat)} # get LATB + LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} atminc_ensmean lev)} # get LEVS + fi + JCAP_ENKF=${JCAP_ENKF:--9999} # there is no jcap in these files + if [[ "${JCAP_ENKF}" -eq -9999 && "${LATB_ENKF}" -ne -9999 ]]; then + JCAP_ENKF=$((LATB_ENKF - 2)) + fi + if [[ "${LONB_ENKF}" -eq -9999 || "${LATB_ENKF}" -eq -9999 || "${LEVS_ENKF}" -eq -9999 || "${JCAP_ENKF}" -eq -9999 ]]; then + export err=9 + err_exit "One or more EnKF background parameters are undefined!" + fi + + ################################################################################ + # This is to give the user the option to recenter, default is YES + if [[ "${RECENTER_ENKF}" == "YES" ]]; then + # GSI EnVar analysis + ATMANL_GSI="${COMIN_ATMOS_ANALYSIS_DET}/${APREFIX}analysis.atm.a00${FHR}.nc" + ATMANL_GSI_ENSRES="${COMIN_ATMOS_ANALYSIS_DET}/${APREFIX}ensres_analysis.atm.a00${FHR}.nc" + + # if we already have a ensemble resolution GSI analysis then just link to it + if [[ -f ${ATMANL_GSI_ENSRES} ]]; then + ${NLN} "${ATMANL_GSI_ENSRES}" atmanl_gsi_ensres + else + ${NLN} "${ATMANL_GSI}" atmanl_gsi + ${NLN} "${ATMANL_GSI_ENSRES}" atmanl_gsi_ensres + SIGLEVEL="${SIGLEVEL:-"${FIXgfs}/am/global_hyblev.l${LEVS}.txt"}" + ${NLN} "${CHGRESNC}" chgres.x + chgresnml=chgres_nc_gauss.nml + nmltitle=chgres + + export OMP_NUM_THREADS=${NTHREADS_CHGRES} + + rm -f "${chgresnml}" + cat > "${chgresnml}" << EOF &${nmltitle}_setup i_output=${LONB_ENKF} j_output=${LATB_ENKF} @@ -241,86 +236,86 @@ if [[ ${RECENTER_ENKF} = "YES" ]]; then vcoord_file="${SIGLEVEL}" / EOF - cat ${chgresnml} - ${APRUN_CHGRES} ./chgres.x - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to change the resolution of the deterministic analysis to the ensemble resolution!" - fi - fi - - if [[ ${DO_CALC_INCREMENT} = "YES" ]]; then - ################################################################################ - # Recenter ensemble member atmospheric analyses about hires analysis - - FILENAMEIN="atmanl" - FILENAME_MEANIN="atmanl_ensmean" # EnKF ensemble mean analysis - FILENAME_MEANOUT="atmanl_gsi_ensres" # recenter around GSI analysis at ensemble resolution - FILENAMEOUT="ratmanl" - - export OMP_NUM_THREADS=${NTHREADS_ECEN} - export pgm=${RECENATMEXEC} - source prep_step - - cpreq ${RECENATMEXEC} ${DATA} - ${APRUN_ECEN} ${DATA}/$(basename ${RECENATMEXEC}) ${FILENAMEIN} ${FILENAME_MEANIN} ${FILENAME_MEANOUT} ${FILENAMEOUT} ${NMEM_ENS} - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to recenter the ensemble resolution mean analysis" - fi - else - ################################################################################ - # Recenter ensemble member atmospheric increments about hires analysis - - FILENAMEIN="atminc" - FILENAME_INCMEANIN="atminc_ensmean" # EnKF ensemble mean increment - FILENAME_GESMEANIN="atmges_ensmean" # EnKF ensemble mean guess - FILENAME_GSIDET="atmanl_gsi_ensres" # recenter around GSI analysis at ensemble resolution - FILENAMEOUT="ratminc" - - export OMP_NUM_THREADS=${NTHREADS_ECEN} - - # make the small namelist file for incvars_to_zero - - rm -f recenter.nml - cat > recenter.nml << EOF + cat "${chgresnml}" + ${APRUN_CHGRES} ./chgres.x + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to change the resolution of the deterministic analysis to the ensemble resolution!" + fi + fi + + if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then + ################################################################################ + # Recenter ensemble member atmospheric analyses about hires analysis + + FILENAMEIN="atmanl" + FILENAME_MEANIN="atmanl_ensmean" # EnKF ensemble mean analysis + FILENAME_MEANOUT="atmanl_gsi_ensres" # recenter around GSI analysis at ensemble resolution + FILENAMEOUT="ratmanl" + + export OMP_NUM_THREADS=${NTHREADS_ECEN} + export pgm=${RECENATMEXEC} + source prep_step + + cpreq "${RECENATMEXEC}" "${DATA}" + ${APRUN_ECEN} "${DATA}/$(basename "${RECENATMEXEC}")" "${FILENAMEIN}" "${FILENAME_MEANIN}" "${FILENAME_MEANOUT}" "${FILENAMEOUT}" "${NMEM_ENS}" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to recenter the ensemble resolution mean analysis" + fi + else + ################################################################################ + # Recenter ensemble member atmospheric increments about hires analysis + + FILENAMEIN="atminc" + FILENAME_INCMEANIN="atminc_ensmean" # EnKF ensemble mean increment + FILENAME_GESMEANIN="atmges_ensmean" # EnKF ensemble mean guess + FILENAME_GSIDET="atmanl_gsi_ensres" # recenter around GSI analysis at ensemble resolution + FILENAMEOUT="ratminc" + + export OMP_NUM_THREADS=${NTHREADS_ECEN} + + # make the small namelist file for incvars_to_zero + + rm -f recenter.nml + cat > recenter.nml << EOF &recenter incvars_to_zero = ${INCREMENTS_TO_ZERO} / EOF -cat recenter.nml - - export pgm=${RECENATMEXEC} - source prep_step - - cpreq ${RECENATMEXEC} ${DATA} - ${APRUN_ECEN} ${DATA}/$(basename ${RECENATMEXEC}) ${FILENAMEIN} ${FILENAME_INCMEANIN} ${FILENAME_GSIDET} ${FILENAMEOUT} ${NMEM_ENS} ${FILENAME_GESMEANIN} - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to recenter the mean ensemble resolution increments!" - fi - fi -fi - -################################################################################ -# Calculate ensemble analysis increment -if [[ ${DO_CALC_INCREMENT} = "YES" ]]; then - if [[ ${RECENTER_ENKF} = "YES" ]]; then - ATMANLNAME='ratmanl' - else - ATMANLNAME='atmanl' - fi - - export OMP_NUM_THREADS=${NTHREADS_CALCINC} - CALCINCEXEC=${CALCINCNCEXEC} - - export pgm=${CALCINCEXEC} - source prep_step - - cpreq "${CALCINCEXEC}" "${DATA}" - rm -f calc_increment.nml - - cat > calc_increment.nml << EOF + cat recenter.nml + + export pgm=${RECENATMEXEC} + source prep_step + + cpreq "${RECENATMEXEC}" "${DATA}" + ${APRUN_ECEN} "${DATA}/$(basename "${RECENATMEXEC}")" "${FILENAMEIN}" "${FILENAME_INCMEANIN}" "${FILENAME_GSIDET}" "${FILENAMEOUT}" "${NMEM_ENS}" "${FILENAME_GESMEANIN}" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to recenter the mean ensemble resolution increments!" + fi + fi + fi + + ################################################################################ + # Calculate ensemble analysis increment + if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then + if [[ "${RECENTER_ENKF}" == "YES" ]]; then + ATMANLNAME='ratmanl' + else + ATMANLNAME='atmanl' + fi + + export OMP_NUM_THREADS=${NTHREADS_CALCINC} + CALCINCEXEC=${CALCINCNCEXEC} + + export pgm=${CALCINCEXEC} + source prep_step + + cpreq "${CALCINCEXEC}" "${DATA}" + rm -f calc_increment.nml + + cat > calc_increment.nml << EOF &setup datapath = './' analysis_filename = '${ATMANLNAME}' @@ -334,14 +329,14 @@ if [[ ${DO_CALC_INCREMENT} = "YES" ]]; then incvars_to_zero = ${INCREMENTS_TO_ZERO} / EOF -cat calc_increment.nml - - ${APRUN_CALCINC} ${DATA}/$(basename ${CALCINCEXEC}) - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to calculate the increment from the ensemble guess!" - fi -fi + cat calc_increment.nml + + ${APRUN_CALCINC} "${DATA}/$(basename "${CALCINCEXEC}")" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to calculate the increment from the ensemble guess!" + fi + fi done # loop over analysis times in window ################################################################################ diff --git a/scripts/exgdas_enkf_post.sh b/scripts/exgdas_enkf_post.sh index 2c75d25619c..99b53593cf3 100755 --- a/scripts/exgdas_enkf_post.sh +++ b/scripts/exgdas_enkf_post.sh @@ -38,9 +38,9 @@ FHMAX=${FHMAX_EPOS:-9} FHOUT=${FHOUT_EPOS:-3} if [[ "${RUN}" == "enkfgfs" ]]; then - NMEM_ENS=${NMEM_ENS_GFS:-${NMEM_ENS:-30}} + NMEM_ENS=${NMEM_ENS_GFS:-${NMEM_ENS:-30}} else - NMEM_ENS=${NMEM_ENS:-80} + NMEM_ENS=${NMEM_ENS:-80} fi SMOOTH_ENKF=${SMOOTH_ENKF:-"NO"} ENKF_SPREAD=${ENKF_SPREAD:-"NO"} @@ -61,40 +61,40 @@ export OMP_NUM_THREADS=${NTHREADS_EPOS} ################################################################################ # Forecast ensemble member files -for imem in $(seq 1 ${NMEM_ENS}); do - memchar="mem"$(printf %03i "${imem}") - MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl -x \ - COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL - - for fhr in $(seq ${FHMIN} ${FHOUT} ${FHMAX}); do - fhrchar=$(printf %03i "${fhr}") - ${NLN} "${COMIN_ATMOS_HISTORY}/${PREFIX}sfc.f${fhrchar}.nc" "sfcf${fhrchar}_${memchar}" - ${NLN} "${COMIN_ATMOS_HISTORY}/${PREFIX}atm.f${fhrchar}.nc" "atmf${fhrchar}_${memchar}" - done +for imem in $(seq 1 "${NMEM_ENS}"); do + memchar="mem"$(printf %03i "${imem}") + MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl -x \ + COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL + + for fhr in $(seq "${FHMIN}" "${FHOUT}" "${FHMAX}"); do + fhrchar=$(printf %03i "${fhr}") + ${NLN} "${COMIN_ATMOS_HISTORY}/${PREFIX}sfc.f${fhrchar}.nc" "sfcf${fhrchar}_${memchar}" + ${NLN} "${COMIN_ATMOS_HISTORY}/${PREFIX}atm.f${fhrchar}.nc" "atmf${fhrchar}_${memchar}" + done done # Forecast ensemble mean and smoothed files MEMDIR="ensstat" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ - COMOUT_ATMOS_HISTORY_STAT:COM_ATMOS_HISTORY_TMPL + COMOUT_ATMOS_HISTORY_STAT:COM_ATMOS_HISTORY_TMPL if [[ ! -d "${COMOUT_ATMOS_HISTORY_STAT}" ]]; then - mkdir -p "${COMOUT_ATMOS_HISTORY_STAT}" + mkdir -p "${COMOUT_ATMOS_HISTORY_STAT}" fi -for fhr in $(seq ${FHMIN} ${FHOUT} ${FHMAX}); do - fhrchar=$(printf %03i "${fhr}") - ${NLN} "${COMOUT_ATMOS_HISTORY_STAT}/${PREFIX}ensmean.sfc.f${fhrchar}.nc" "sfcf${fhrchar}.ensmean" - ${NLN} "${COMOUT_ATMOS_HISTORY_STAT}/${PREFIX}ensmean.atm.f${fhrchar}.nc" "atmf${fhrchar}.ensmean" - if [[ "${SMOOTH_ENKF}" == "YES" ]]; then - for imem in $(seq 1 ${NMEM_ENS}); do - memchar="mem"$(printf %03i "${imem}") - MEMDIR="${memchar}" YMD=${PDY} HH=${cyc} declare_from_tmpl -x \ - COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL - ${NLN} "${COMIN_ATMOS_HISTORY}/${PREFIX}atm.f${fhrchar}${ENKF_SUFFIX}.nc" "atmf${fhrchar}${ENKF_SUFFIX}_${memchar}" - done - fi - if [[ "${ENKF_SPREAD}" == "YES" ]]; then - ${NLN} "${COMOUT_ATMOS_HISTORY_STAT}/${PREFIX}ensspread.atm.f${fhrchar}.nc" "atmf${fhrchar}.ensspread" - fi +for fhr in $(seq "${FHMIN}" "${FHOUT}" "${FHMAX}"); do + fhrchar=$(printf %03i "${fhr}") + ${NLN} "${COMOUT_ATMOS_HISTORY_STAT}/${PREFIX}ensmean.sfc.f${fhrchar}.nc" "sfcf${fhrchar}.ensmean" + ${NLN} "${COMOUT_ATMOS_HISTORY_STAT}/${PREFIX}ensmean.atm.f${fhrchar}.nc" "atmf${fhrchar}.ensmean" + if [[ "${SMOOTH_ENKF}" == "YES" ]]; then + for imem in $(seq 1 "${NMEM_ENS}"); do + memchar="mem"$(printf %03i "${imem}") + MEMDIR="${memchar}" YMD=${PDY} HH=${cyc} declare_from_tmpl -x \ + COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL + ${NLN} "${COMIN_ATMOS_HISTORY}/${PREFIX}atm.f${fhrchar}${ENKF_SUFFIX}.nc" "atmf${fhrchar}${ENKF_SUFFIX}_${memchar}" + done + fi + if [[ "${ENKF_SPREAD}" == "YES" ]]; then + ${NLN} "${COMOUT_ATMOS_HISTORY_STAT}/${PREFIX}ensspread.atm.f${fhrchar}.nc" "atmf${fhrchar}.ensspread" + fi done ################################################################################ @@ -104,64 +104,62 @@ if [[ "${SMOOTH_ENKF}" == "YES" ]]; then cpreq "${HYBENSMOOTH}" ./hybens_smoothinfo fi -for fhr in $(seq ${FHMIN} ${FHOUT} ${FHMAX}); do - fhrchar=$(printf %03i ${fhr}) - - export pgm=${GETSFCENSMEANEXEC} - source prep_step - - ${APRUN_EPOS} "${DATA}/$(basename "${GETSFCENSMEANEXEC}")" ./ "sfcf${fhrchar}.ensmean" "sfcf${fhrchar}" "${NMEM_ENS}" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to calculate ensemble surface mean for forecast hour ${fhr}" - fi - - export pgm=${GETATMENSMEANEXEC} - source prep_step - - if [[ "${ENKF_SPREAD}" == "YES" ]]; then - ${APRUN_EPOS} "${DATA}/$(basename "${GETATMENSMEANEXEC}")" ./ "atmf${fhrchar}.ensmean" "atmf${fhrchar}" "${NMEM_ENS}" "atmf${fhrchar}.ensspread" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to calculate ensemble atmospheric mean and spread for forecast hour ${fhr}" - fi - else - ${APRUN_EPOS} "${DATA}/$(basename "${GETATMENSMEANEXEC}")" ./ "atmf${fhrchar}.ensmean" "atmf${fhrchar}" "${NMEM_ENS}" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to calculate ensemble atmospheric mean for forecast hour ${fhr}" - fi - fi +for fhr in $(seq "${FHMIN}" "${FHOUT}" "${FHMAX}"); do + fhrchar=$(printf %03i "${fhr}") + + export pgm=${GETSFCENSMEANEXEC} + source prep_step + + ${APRUN_EPOS} "${DATA}/$(basename "${GETSFCENSMEANEXEC}")" ./ "sfcf${fhrchar}.ensmean" "sfcf${fhrchar}" "${NMEM_ENS}" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to calculate ensemble surface mean for forecast hour ${fhr}" + fi + + export pgm=${GETATMENSMEANEXEC} + source prep_step + + if [[ "${ENKF_SPREAD}" == "YES" ]]; then + ${APRUN_EPOS} "${DATA}/$(basename "${GETATMENSMEANEXEC}")" ./ "atmf${fhrchar}.ensmean" "atmf${fhrchar}" "${NMEM_ENS}" "atmf${fhrchar}.ensspread" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to calculate ensemble atmospheric mean and spread for forecast hour ${fhr}" + fi + else + ${APRUN_EPOS} "${DATA}/$(basename "${GETATMENSMEANEXEC}")" ./ "atmf${fhrchar}.ensmean" "atmf${fhrchar}" "${NMEM_ENS}" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to calculate ensemble atmospheric mean for forecast hour ${fhr}" + fi + fi done ################################################################################ # If smoothing on but no smoothing output, copy smoothed ensemble atmospheric files if [[ "${SMOOTH_ENKF}" == "YES" ]]; then - for fhr in $(seq ${FHMIN} ${FHOUT} ${FHMAX}); do - fhrchar=$(printf "%03i" "${fhr}") - if [[ ! -s "atmf${fhrchar}${ENKF_SUFFIX}_mem001" ]]; then - echo "WARNING! no smoothed ensemble member for fhour = ${fhrchar}" >&2 - for imem in $(seq 1 ${NMEM_ENS}); do - memchar="mem"$(printf "%03i" "${imem}") - cpreq "atmf${fhrchar}_${memchar}" "atmf${fhrchar}${ENKF_SUFFIX}_${memchar}" - done - fi - done + for fhr in $(seq "${FHMIN}" "${FHOUT}" "${FHMAX}"); do + fhrchar=$(printf "%03i" "${fhr}") + if [[ ! -s "atmf${fhrchar}${ENKF_SUFFIX}_mem001" ]]; then + echo "WARNING! no smoothed ensemble member for fhour = ${fhrchar}" >&2 + for imem in $(seq 1 "${NMEM_ENS}"); do + memchar="mem"$(printf "%03i" "${imem}") + cpreq "atmf${fhrchar}_${memchar}" "atmf${fhrchar}${ENKF_SUFFIX}_${memchar}" + done + fi + done fi ################################################################################ # Send DBN alerts if [[ "${SENDDBN}" == "YES" ]]; then - - for fhr in $(seq ${FHMIN} ${FHOUT} ${FHMAX}); do - fhrchar=$(printf "%03i" "${fhr}") - if [[ $(expr ${fhr} % 3) -eq 0 ]]; then - if [[ -s "./sfcf${fhrchar}.ensmean" ]]; then - "${DBNROOT}/bin/dbn_alert" "MODEL" "GFS_ENKF" "${job}" "${COMOUT_ATMOS_HISTORY_STAT}/${PREFIX}ensmean.sfc.f${fhrchar}.nc" - fi - fi - done - + for fhr in $(seq "${FHMIN}" "${FHOUT}" "${FHMAX}"); do + fhrchar=$(printf "%03i" "${fhr}") + if ((fhr % 3 == 0)); then + if [[ -s "./sfcf${fhrchar}.ensmean" ]]; then + "${DBNROOT}/bin/dbn_alert" "MODEL" "GFS_ENKF" "${job}" "${COMOUT_ATMOS_HISTORY_STAT}/${PREFIX}ensmean.sfc.f${fhrchar}.nc" + fi + fi + done fi ################################################################################ diff --git a/scripts/exgdas_enkf_select_obs.sh b/scripts/exgdas_enkf_select_obs.sh index c6dc219e098..921057bb3f9 100755 --- a/scripts/exgdas_enkf_select_obs.sh +++ b/scripts/exgdas_enkf_select_obs.sh @@ -50,11 +50,11 @@ ${NLN} "${SELECT_OBS}" obsinput.tar # Whether to save or skip obs if [[ "${RUN_SELECT}" == "YES" && "${USE_SELECT}" == "NO" ]]; then - lread_obs_save=".true." - lread_obs_skip=".false." + lread_obs_save=".true." + lread_obs_skip=".false." elif [[ "${RUN_SELECT}" == "NO" && "${USE_SELECT}" == "YES" ]]; then - lread_obs_save=".false." - lread_obs_skip=".true." + lread_obs_save=".false." + lread_obs_skip=".true." fi ################################################################################ @@ -90,11 +90,11 @@ export CHEM="${CHEM_INVOBS}" "${ANALYSISSH}" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to run the GSI!" + err_exit "Failed to run the GSI!" fi ################################################################################ # Postprocessing cd "${pwd}" || exit 1 -exit ${err} +exit "${err}" diff --git a/scripts/exgdas_enkf_sfc.sh b/scripts/exgdas_enkf_sfc.sh index 9215edcd5f7..e0fa15ab5ee 100755 --- a/scripts/exgdas_enkf_sfc.sh +++ b/scripts/exgdas_enkf_sfc.sh @@ -38,19 +38,19 @@ NCLEN=${NCLEN:-${USHgfs}/getncdimlen} OPREFIX=${OPREFIX:-""} OSUFFIX=${OSUFFIX:-""} APREFIX=${APREFIX:-""} -APREFIX_ENS=${APREFIX_ENS:-$APREFIX} +APREFIX_ENS=${APREFIX_ENS:-${APREFIX}} GPREFIX=${GPREFIX:-""} GPREFIX_ENS=${GPREFIX_ENS:-${GPREFIX}} # Variables NMEM_ENS_MAX=${NMEM_ENS:-80} if [[ "${RUN}" == "enkfgfs" ]]; then - NMEM_ENS=${NMEM_ENS_GFS:-30} - ec_offset=${NMEM_ENS_GFS_OFFSET:-20} - mem_offset=$((ec_offset * cyc/6)) + NMEM_ENS=${NMEM_ENS_GFS:-30} + ec_offset=${NMEM_ENS_GFS_OFFSET:-20} + mem_offset=$((ec_offset * cyc / 6)) else - NMEM_ENS=${NMEM_ENS:-80} - mem_offset=0 + NMEM_ENS=${NMEM_ENS:-80} + mem_offset=0 fi DOIAU=${DOIAU_ENKF:-"NO"} @@ -79,9 +79,9 @@ bcyc=${BDATE:8:2} # Get dimension information based on CASE res=${CASE:1} -JCAP_CASE=$((res*2-2)) -LATB_CASE=$((res*2)) -LONB_CASE=$((res*4)) +JCAP_CASE=$((res * 2 - 2)) +LATB_CASE=$((res * 2)) +LONB_CASE=$((res * 4)) # Global cycle requires these files export FNTSFA=${FNTSFA:-' '} @@ -92,42 +92,44 @@ if [[ ! -f "${FNSNOA}" ]]; then export FNSNOA="${COMIN_OBS}/${OPREFIX}snogrb_t1534.3072.1536" fi if [[ ! -f "${FNSNOA}" ]]; then - echo "WARNING: Current cycle snow file ${FNSNOA} is missing. Snow coverage will not be updated." + echo "WARNING: Current cycle snow file ${FNSNOA} is missing. Snow coverage will not be updated." else - echo "INFO: Current cycle snow file is ${FNSNOA}" + echo "INFO: Current cycle snow file is ${FNSNOA}" fi export FNSNOG=${FNSNOG:-${COMIN_OBS_PREV}/${GPREFIX}snogrb_t${JCAP_CASE}.${LONB_CASE}.${LATB_CASE}} # Check if resolution specific FNSNOG exists, if not use t1534 version if [[ ! -f "${FNSNOG}" ]]; then - export FNSNOG="${COMIN_OBS_PREV}/${GPREFIX}snogrb_t1534.3072.1536" + export FNSNOG="${COMIN_OBS_PREV}/${GPREFIX}snogrb_t1534.3072.1536" fi if [[ ! -f "${FNSNOG}" ]]; then - echo "WARNING: Previous cycle snow file ${FNSNOG} is missing. Snow coverage will not be updated." + echo "WARNING: Previous cycle snow file ${FNSNOG} is missing. Snow coverage will not be updated." else - echo "INFO: Previous cycle snow file is ${FNSNOG}" + echo "INFO: Previous cycle snow file is ${FNSNOG}" fi # If any snow files are missing, don't apply snow in the global_cycle step. if [[ ! -f "${FNSNOA}" || ! -f "${FNSNOG}" ]]; then - export FNSNOA=" " - export CYCLVARS="FSNOL=99999.,FSNOS=99999.," -else - # Set CYCLVARS by checking grib date of current snogrb vs that of prev cycle - snoa_count=$("${WGRIB}" -4yr "${FNSNOA}" 2>/dev/null | grep -i snowc | awk -F: '{print $3}' | awk -F= '{print $2}') - snog_count=$("${WGRIB}" -4yr "${FNSNOG}" 2>/dev/null | grep -i snowc | awk -F: '{print $3}' | awk -F= '{print $2}') - if [[ ${snoa_count} -le ${snog_count} ]]; then export FNSNOA=" " export CYCLVARS="FSNOL=99999.,FSNOS=99999.," - else - export SNOW_NUDGE_COEFF=${SNOW_NUDGE_COEFF:-0.} - export CYCLVARS="FSNOL=${SNOW_NUDGE_COEFF},$CYCLVARS" - fi +else + # Set CYCLVARS by checking grib date of current snogrb vs that of prev cycle + # shellcheck disable=SC2312 + snoa_count=$("${WGRIB}" -4yr "${FNSNOA}" 2> /dev/null | grep -i snowc | awk -F: '{print $3}' | awk -F= '{print $2}') + # shellcheck disable=SC2312 + snog_count=$("${WGRIB}" -4yr "${FNSNOG}" 2> /dev/null | grep -i snowc | awk -F: '{print $3}' | awk -F= '{print $2}') + if [[ ${snoa_count} -le ${snog_count} ]]; then + export FNSNOA=" " + export CYCLVARS="FSNOL=99999.,FSNOS=99999.," + else + export SNOW_NUDGE_COEFF=${SNOW_NUDGE_COEFF:-0.} + export CYCLVARS="FSNOL=${SNOW_NUDGE_COEFF},${CYCLVARS}" + fi fi if [[ "${DONST}" == "YES" ]]; then - export NST_FILE=${NST_FILE:-${COMIN_ATMOS_ANALYSIS_DET}/${APREFIX}analysis.dtf.a006.nc} + export NST_FILE=${NST_FILE:-${COMIN_ATMOS_ANALYSIS_DET}/${APREFIX}analysis.dtf.a006.nc} else - export NST_FILE="NULL" + export NST_FILE="NULL" fi # regrid the surface increment files @@ -139,39 +141,39 @@ if [[ "${DO_GSISOILDA}" == "YES" ]]; then export NMEM_REGRID=${NMEM_ENS} if [[ "${DOIAU}" == "YES" ]]; then export LFHR=3 # match BDATE - else # DOSFCANL_ENKF + else # DOSFCANL_ENKF export LFHR=6 # PDYcyc fi "${REGRIDSH}" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to regrid the surface inrement file!" + err_exit "Failed to regrid the surface inrement file!" fi fi -export APRUNCY=${APRUN_CYCLE:-$APRUN_ESFC} -export OMP_NUM_THREADS_CY=${NTHREADS_CYCLE:-$NTHREADS_ESFC} -export MAX_TASKS_CY=$NMEM_ENS +export APRUNCY=${APRUN_CYCLE:-${APRUN_ESFC}} +export OMP_NUM_THREADS_CY=${NTHREADS_CYCLE:-${NTHREADS_ESFC}} +export MAX_TASKS_CY=${NMEM_ENS} -if [[ "$DOIAU" == "YES" ]]; then +if [[ "${DOIAU}" == "YES" ]]; then # Update surface restarts at beginning of window when IAU is ON # For now assume/hold analysis.dtf.nc is valid at beginning of window. - for n in $(seq 1 $ntiles); do + for n in $(seq 1 "${ntiles}"); do - export TILE_NUM=$n + export TILE_NUM=${n} # Copy inputs from COMIN to DATA - for imem in $(seq 1 $NMEM_ENS); do + for imem in $(seq 1 "${NMEM_ENS}"); do smem=$((imem + mem_offset)) - if (( smem > NMEM_ENS_MAX )); then - smem=$((smem - NMEM_ENS_MAX)) + if ((smem > NMEM_ENS_MAX)); then + smem=$((smem - NMEM_ENS_MAX)) fi - gmemchar="mem"$(printf %03i "$smem") - cmem=$(printf %03i $imem) - memchar="mem$cmem" + gmemchar="mem"$(printf %03i "${smem}") + cmem=$(printf %03i "${imem}") + memchar="mem${cmem}" MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl \ COMOUT_ATMOS_RESTART_MEM:COM_ATMOS_RESTART_TMPL @@ -200,12 +202,12 @@ if [[ "$DOIAU" == "YES" ]]; then cpreq "${sfcdata_dir}/${bPDY}.${bcyc}0000.${snow_prefix}sfc_data.tile${n}.nc" \ "${DATA}/fnbgsi.${cmem}" cpreq "${DATA}/fnbgsi.${cmem}" "${DATA}/fnbgso.${cmem}" - cpreq "${FIXgfs}/orog/${CASE}/${CASE}_grid.tile${n}.nc" "${DATA}/fngrid.${cmem}" + cpreq "${FIXgfs}/orog/${CASE}/${CASE}_grid.tile${n}.nc" "${DATA}/fngrid.${cmem}" cpreq "${FIXgfs}/orog/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile${n}.nc" "${DATA}/fnorog.${cmem}" - if [[ "${DO_GSISOILDA}" == "YES" && "${GCYCLE_DO_SOILINCR}" == ".true." ]]; then - cpreq "${COMIN_ATMOS_ANALYSIS_MEM}/increment.sfc.i00${LFHR}.tile${n}.nc" \ - "${DATA}/soil_xainc.${cmem}" + if [[ "${DO_GSISOILDA}" == "YES" ]] && [[ "${GCYCLE_DO_SOILINCR}" == ".true." ]]; then + cpreq "${COMIN_ATMOS_ANALYSIS_MEM}/increment.sfc.i00${LFHR}.tile${n}.nc" \ + "${DATA}/soil_xainc.${cmem}" fi done # ensembles @@ -213,18 +215,18 @@ if [[ "$DOIAU" == "YES" ]]; then "${CYCLESH}" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to update surface fields!" + err_exit "Failed to update surface fields!" fi # Copy outputs from DATA to COMOUT - for imem in $(seq 1 $NMEM_ENS); do + for imem in $(seq 1 "${NMEM_ENS}"); do smem=$((imem + mem_offset)) - if (( smem > NMEM_ENS_MAX )); then - smem=$((smem - NMEM_ENS_MAX)) + if ((smem > NMEM_ENS_MAX)); then + smem=$((smem - NMEM_ENS_MAX)) fi - gmemchar="mem"$(printf %03i "$smem") - cmem=$(printf %03i $imem) - memchar="mem$cmem" + gmemchar="mem"$(printf %03i "${smem}") + cmem=$(printf %03i "${imem}") + memchar="mem${cmem}" MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl \ COMOUT_ATMOS_RESTART_MEM:COM_ATMOS_RESTART_TMPL @@ -242,18 +244,18 @@ if [[ "$DOIAU" == "YES" ]]; then fi if [[ "${DOSFCANL_ENKF}" == "YES" ]]; then - for n in $(seq 1 $ntiles); do + for n in $(seq 1 "${ntiles}"); do - export TILE_NUM=$n + export TILE_NUM=${n} # Copy inputs from COMIN to DATA - for imem in $(seq 1 $NMEM_ENS); do + for imem in $(seq 1 "${NMEM_ENS}"); do smem=$((imem + mem_offset)) - if (( smem > NMEM_ENS_MAX )); then - smem=$((smem - NMEM_ENS_MAX)) + if ((smem > NMEM_ENS_MAX)); then + smem=$((smem - NMEM_ENS_MAX)) fi - gmemchar="mem"$(printf %03i "$smem") - cmem=$(printf %03i ${imem}) + gmemchar="mem"$(printf %03i "${smem}") + cmem=$(printf %03i "${imem}") memchar="mem${cmem}" RUN="${GDUMP_ENS}" MEMDIR=${gmemchar} YMD=${PDY} HH=${cyc} declare_from_tmpl \ @@ -277,26 +279,26 @@ if [[ "${DOSFCANL_ENKF}" == "YES" ]]; then cpreq "${sfcdata_dir}/${PDY}.${cyc}0000.${snow_prefix}sfc_data.tile${n}.nc" \ "${DATA}/fnbgsi.${cmem}" cpreq "${DATA}/fnbgsi.${cmem}" "${DATA}/fnbgso.${cmem}" - cpreq "${FIXgfs}/orog/${CASE}/${CASE}_grid.tile${n}.nc" "${DATA}/fngrid.${cmem}" + cpreq "${FIXgfs}/orog/${CASE}/${CASE}_grid.tile${n}.nc" "${DATA}/fngrid.${cmem}" cpreq "${FIXgfs}/orog/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile${n}.nc" "${DATA}/fnorog.${cmem}" - if [[ "${DO_GSISOILDA}" == "YES" && "${GCYCLE_DO_SOILINCR}" == ".true." ]]; then - cpreq "${COMIN_ATMOS_ANALYSIS_MEM}/${APREFIX}increment.sfc.i00${LFHR}.tile${n}.nc" \ - "${DATA}/soil_xainc.${cmem}" + if [[ "${DO_GSISOILDA}" == "YES" ]] && [[ "${GCYCLE_DO_SOILINCR}" == ".true." ]]; then + cpreq "${COMIN_ATMOS_ANALYSIS_MEM}/${APREFIX}increment.sfc.i00${LFHR}.tile${n}.nc" \ + "${DATA}/soil_xainc.${cmem}" fi done "${CYCLESH}" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to update surface increment!" + err_exit "Failed to update surface increment!" fi # Copy outputs from DATA to COMOUT for imem in $(seq 1 "${NMEM_ENS}"); do smem=$((imem + mem_offset)) - if (( smem > NMEM_ENS_MAX )); then - smem=$((smem - NMEM_ENS_MAX)) + if ((smem > NMEM_ENS_MAX)); then + smem=$((smem - NMEM_ENS_MAX)) fi gmemchar="mem"$(printf %03i "${smem}") cmem=$(printf %03i "${imem}") @@ -322,5 +324,4 @@ fi # Postprocessing cd "${pwd}" || exit 1 - exit "${err}" diff --git a/scripts/exgdas_enkf_update.sh b/scripts/exgdas_enkf_update.sh index b6fdb47098b..df981d16973 100755 --- a/scripts/exgdas_enkf_update.sh +++ b/scripts/exgdas_enkf_update.sh @@ -24,10 +24,6 @@ pwd=$(pwd) NCLEN=${NCLEN:-${USHgfs}/getncdimlen} USE_CFP=${USE_CFP:-"NO"} CFP_MP=${CFP_MP:-"NO"} -nm="" -if [[ "${CFP_MP}" == "YES" ]]; then - nm=0 -fi APRUNCFP=${APRUNCFP:-""} APRUN_ENKF=${APRUN_ENKF:-${APRUN:-""}} NTHREADS_ENKF=${NTHREADS_ENKF:-${NTHREADS:-1}} @@ -54,7 +50,7 @@ SATOBS_ENKF=${SATOBS_ENKF:-""} OZOBS_ENKF=${OZOBS_ENKF:-""} use_correlated_oberrs=${use_correlated_oberrs:-".false."} if [[ "${USE_CORRELATED_OBERRS}" == "YES" ]]; then - use_correlated_oberrs=".true." + use_correlated_oberrs=".true." fi imp_physics=${imp_physics:-"99"} lupp=${lupp:-".true."} @@ -75,14 +71,14 @@ taperanalperts=${taperanalperts:-".false."} IAUFHRS_ENKF=${IAUFHRS_ENKF:-"6,"} NMEM_ENS_MAX=${NMEM_ENS:-80} if [[ "${RUN}" == "enkfgfs" ]]; then - DO_CALC_INCREMENT=${DO_CALC_INCREMENT_ENKF_GFS:-"NO"} - NMEM_ENS=${NMEM_ENS_GFS:-30} - ec_offset=${NMEM_ENS_GFS_OFFSET:-20} - mem_offset=$((ec_offset * cyc/6)) + DO_CALC_INCREMENT=${DO_CALC_INCREMENT_ENKF_GFS:-"NO"} + NMEM_ENS=${NMEM_ENS_GFS:-30} + ec_offset=${NMEM_ENS_GFS_OFFSET:-20} + mem_offset=$((ec_offset * cyc / 6)) else - DO_CALC_INCREMENT=${DO_CALC_INCREMENT:-"NO"} - NMEM_ENS=${NMEM_ENS:-80} - mem_offset=0 + DO_CALC_INCREMENT=${DO_CALC_INCREMENT:-"NO"} + NMEM_ENS=${NMEM_ENS:-80} + mem_offset=0 fi INCREMENTS_TO_ZERO=${INCREMENTS_TO_ZERO:-"'NONE'"} DO_GSISOILDA=${DO_GSISOILDA:-"NO"} @@ -93,15 +89,15 @@ hofx_2m_sfcfile=${hofx_2m_sfcfile:-".false."} ATMGES_ENSMEAN="${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX}ensmean.atm.f006.nc" LONB_ENKF=${LONB_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" grid_xt)} # get LONB_ENKF LATB_ENKF=${LATB_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" grid_yt)} # get LATB_ENFK -LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" pfull)} # get LEVS_ENFK +LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" pfull)} # get LEVS_ENFK use_gfs_ncio=".true." use_gfs_nemsio=".false." paranc=${paranc:-".true."} WRITE_INCR_ZERO="incvars_to_zero= ${INCREMENTS_TO_ZERO}," if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then - write_fv3_incr=".false." + write_fv3_incr=".false." else - write_fv3_incr=".true." + write_fv3_incr=".true." fi LATA_ENKF=${LATA_ENKF:-${LATB_ENKF}} LONA_ENKF=${LONA_ENKF:-${LONB_ENKF}} @@ -120,26 +116,26 @@ fi ################################################################################ # Fixed files -${NLN} "${SATANGL}" satbias_angle if [[ "${SATINFO}" == "generate" ]]; then - "${USHgfs}/create_gsi_info.sh" sat "${PDY}${cyc}" "${DATA}" + "${USHgfs}/create_gsi_info.sh" sat "${PDY}${cyc}" "${DATA}" else - ${NLN} "${SATINFO}" satinfo + ${NLN} "${SATINFO}" satinfo fi if [[ "${CONVINFO}" == "generate" ]]; then - "${USHgfs}/create_gsi_info.sh" conv "${PDY}${cyc}" "${DATA}" "${USE_2M_OBS}" + "${USHgfs}/create_gsi_info.sh" conv "${PDY}${cyc}" "${DATA}" "${USE_2M_OBS}" else - ${NLN} "${CONVINFO}" convinfo + ${NLN} "${CONVINFO}" convinfo fi if [[ "${OZINFO}" == "generate" ]]; then - "${USHgfs}/create_gsi_info.sh" oz "${PDY}${cyc}" "${DATA}" + "${USHgfs}/create_gsi_info.sh" oz "${PDY}${cyc}" "${DATA}" else - ${NLN} "${OZINFO}" ozinfo + ${NLN} "${OZINFO}" ozinfo fi -${NLN} "${SCANINFO}" scaninfo +${NLN} "${SATANGL}" satbias_angle +${NLN} "${SCANINFO}" scaninfo ${NLN} "${HYBENSINFO}" hybens_info -${NLN} "${ANAVINFO}" anavinfo -${NLN} "${VLOCALEIG}" vlocal_eig.dat +${NLN} "${ANAVINFO}" anavinfo +${NLN} "${VLOCALEIG}" vlocal_eig.dat # Bias correction coefficients based on the ensemble mean ${NLN} "${COMIN_ATMOS_ANALYSIS_STAT}/${GBIASe}" "satbias_in" @@ -147,8 +143,8 @@ ${NLN} "${COMIN_ATMOS_ANALYSIS_STAT}/${GBIASe}" "satbias_in" ################################################################################ if [[ "${USE_CFP}" == "YES" ]]; then - rm -f "${DATA}/untar.sh" "${DATA}/mp_untar.sh" - cat > "${DATA}/untar.sh" << EOFuntar + rm -f "${DATA}/untar.sh" "${DATA}/mp_untar.sh" + cat > "${DATA}/untar.sh" << EOFuntar #!/bin/sh memchar=\$1 COMOUT_ATMOS_ANALYSIS=\$2 @@ -162,95 +158,78 @@ for ftype in \$flist; do tar -xvf \$fname done EOFuntar - chmod 755 "${DATA}/untar.sh" + chmod 755 "${DATA}/untar.sh" fi ################################################################################ # Ensemble guess, observational data and analyses/increments -flist="${CNVSTAT} ${OZNSTAT} ${RADSTAT}" -if [[ "${USE_CFP}" == "YES" ]]; then - echo "${nm} ${DATA}/untar.sh ensmean ${COMIN_ATMOS_ANALYSIS_STAT}" | tee -a "${DATA}/mp_untar.sh" - if [[ "${CFP_MP:-NO}" == "YES" ]]; then - nm=$((nm+1)) - fi -else - for ftype in ${flist}; do - fname="${COMIN_ATMOS_ANALYSIS_STAT}/${ftype}.tar" - tar -xvf "${fname}" - done -fi -nfhrs=$(echo "${IAUFHRS_ENKF}" | sed 's/,/ /g') -for imem in $(seq 1 ${NMEM_ENS}); do - smem=$((imem + mem_offset)) - if (( smem > NMEM_ENS_MAX )); then - smem=$((smem - NMEM_ENS_MAX)) - fi - gmemchar="mem"$(printf "%03i" "${smem}") - memchar="mem"$(printf "%03i" "${imem}") +echo "${DATA}/untar.sh ensmean ${COMIN_ATMOS_ANALYSIS_STAT}" | tee -a "${DATA}/mp_untar.sh" +nfhrs="${IAUFHRS_ENKF//,/ }" +for imem in $(seq 1 "${NMEM_ENS}"); do + smem=$((imem + mem_offset)) + if ((smem > NMEM_ENS_MAX)); then + smem=$((smem - NMEM_ENS_MAX)) + fi + gmemchar="mem"$(printf "%03i" "${smem}") + memchar="mem"$(printf "%03i" "${imem}") + + MEMDIR=${gmemchar} RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -x \ + COMIN_ATMOS_HISTORY_MEM_PREV:COM_ATMOS_HISTORY_TMPL - MEMDIR=${gmemchar} RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -x \ - COMIN_ATMOS_HISTORY_MEM_PREV:COM_ATMOS_HISTORY_TMPL + MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl -x \ + COMOUT_ATMOS_ANALYSIS_MEM:COM_ATMOS_ANALYSIS_TMPL - MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl -x \ - COMOUT_ATMOS_ANALYSIS_MEM:COM_ATMOS_ANALYSIS_TMPL + mkdir -p "${COMOUT_ATMOS_ANALYSIS_MEM}" - mkdir -p "${COMOUT_ATMOS_ANALYSIS_MEM}" + for FHR in ${nfhrs}; do + ${NLN} "${COMIN_ATMOS_HISTORY_MEM_PREV}/${GPREFIX}atm.f00${FHR}${ENKF_SUFFIX}.nc" \ + "sfg_${PDY}${cyc}_fhr0${FHR}_${memchar}" + if [[ "${hofx_2m_sfcfile}" == ".true." ]]; then + ${NLN} "${COMIN_ATMOS_HISTORY_MEM_PREV}/${GPREFIX}sfc.f00${FHR}${ENKF_SUFFIX}.nc" \ + "bfg_${PDY}${cyc}_fhr0${FHR}_${memchar}" + fi + if [[ "${cnvw_option}" == ".true." ]]; then + ${NLN} "${COMIN_ATMOS_HISTORY_MEM_PREV}/${GPREFIX}sfc.f00${FHR}.nc" \ + "sfgsfc_${PDY}${cyc}_fhr0${FHR}_${memchar}" + fi - for FHR in ${nfhrs}; do - ${NLN} "${COMIN_ATMOS_HISTORY_MEM_PREV}/${GPREFIX}atm.f00${FHR}${ENKF_SUFFIX}.nc" \ - "sfg_${PDY}${cyc}_fhr0${FHR}_${memchar}" - if [[ "${hofx_2m_sfcfile}" == ".true." ]]; then - ${NLN} "${COMIN_ATMOS_HISTORY_MEM_PREV}/${GPREFIX}sfc.f00${FHR}${ENKF_SUFFIX}.nc" \ - "bfg_${PDY}${cyc}_fhr0${FHR}_${memchar}" - fi - if [[ "${cnvw_option}" == ".true." ]]; then - ${NLN} "${COMIN_ATMOS_HISTORY_MEM_PREV}/${GPREFIX}sfc.f00${FHR}.nc" \ - "sfgsfc_${PDY}${cyc}_fhr0${FHR}_${memchar}" - fi - if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then - ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX}analysis.atm.a00${FHR}.nc" \ - "sanl_${PDY}${cyc}_fhr0${FHR}_${memchar}" - else - ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX}increment.atm.i00${FHR}.nc" \ - "incr_${PDY}${cyc}_fhr0${FHR}_${memchar}" - fi - if [[ "${DO_GSISOILDA}" == "YES" ]]; then - ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX}increment.sfc.i00${FHR}.nc" \ - "sfcincr_${PDY}${cyc}_fhr0${FHR}_${memchar}" - fi - done + if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then + ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX}analysis.atm.a00${FHR}.nc" \ + "sanl_${PDY}${cyc}_fhr0${FHR}_${memchar}" + else + ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX}increment.atm.i00${FHR}.nc" \ + "incr_${PDY}${cyc}_fhr0${FHR}_${memchar}" + fi + + if [[ "${DO_GSISOILDA}" == "YES" ]]; then + ${NLN} "${COMOUT_ATMOS_ANALYSIS_MEM}/${APREFIX}increment.sfc.i00${FHR}.nc" \ + "sfcincr_${PDY}${cyc}_fhr0${FHR}_${memchar}" + fi + done done # Ensemble mean guess for FHR in ${nfhrs}; do - - ${NLN} "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX}ensmean.atm.f00${FHR}.nc" \ - "sfg_${PDY}${cyc}_fhr0${FHR}_ensmean" - if [[ "${cnvw_option}" == ".true." ]]; then - ${NLN} "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX}ensmean.sfc.f00${FHR}.nc" \ - "sfgsfc_${PDY}${cyc}_fhr0${FHR}_ensmean" - fi - if [[ "${DO_GSISOILDA}" == "YES" ]]; then - ${NLN} "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX}ensmean.sfc.f00${FHR}.nc" \ - "bfg_${PDY}${cyc}_fhr0${FHR}_ensmean" - ${NLN} "${COMIN_ATMOS_ANALYSIS_STAT}/${APREFIX}increment.sfc.i00${FHR}.nc" \ - "sfcincr_${PDY}${cyc}_fhr0${FHR}_ensmean" - fi + ${NLN} "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX}ensmean.atm.f00${FHR}.nc" \ + "sfg_${PDY}${cyc}_fhr0${FHR}_ensmean" + if [[ "${cnvw_option}" == ".true." ]]; then + ${NLN} "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX}ensmean.sfc.f00${FHR}.nc" \ + "sfgsfc_${PDY}${cyc}_fhr0${FHR}_ensmean" + fi + if [[ "${DO_GSISOILDA}" == "YES" ]]; then + ${NLN} "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX}ensmean.sfc.f00${FHR}.nc" \ + "bfg_${PDY}${cyc}_fhr0${FHR}_ensmean" + ${NLN} "${COMIN_ATMOS_ANALYSIS_STAT}/${APREFIX}increment.sfc.i00${FHR}.nc" \ + "sfcincr_${PDY}${cyc}_fhr0${FHR}_ensmean" + fi done -if [[ "${USE_CFP}" == "YES" ]]; then - chmod 755 "${DATA}/mp_untar.sh" - ncmd=$(wc -l < "${DATA}/mp_untar.sh") - if [[ ${ncmd} -gt 0 ]]; then - ncmd_max=$((ncmd < max_tasks_per_node ? ncmd : max_tasks_per_node)) - APRUNCFP=$(eval echo "${APRUNCFP}") - ${APRUNCFP} "${DATA}/mp_untar.sh" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to untar input data!" - fi - fi +# Run with MPMD or serial +"${USHgfs}/run_mpmd.sh" "${DATA}/mp_untar.sh" && true +export err=$? +if [[ ${err} -ne 0 ]]; then + err_exit "Failed to untar input data!" fi ################################################################################ @@ -395,10 +374,10 @@ export pgm=${ENKFEXEC} source prep_step cpreq "${ENKFEXEC}" "${DATA}" -${APRUN_ENKF} "${DATA}/$(basename ${ENKFEXEC})" 1>stdout 2>stderr && true +${APRUN_ENKF} "${DATA}/$(basename "${ENKFEXEC}")" 1> stdout 2> stderr && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to run the EnKF!" + err_exit "Failed to run the EnKF!" fi # Cat runtime output files. diff --git a/scripts/exgfs_atmos_awips_20km_1p0deg.sh b/scripts/exgfs_atmos_awips_20km_1p0deg.sh index d2bfe23d7eb..267a0623791 100755 --- a/scripts/exgfs_atmos_awips_20km_1p0deg.sh +++ b/scripts/exgfs_atmos_awips_20km_1p0deg.sh @@ -24,13 +24,13 @@ fcsthr="$1" num=$# if [[ ${num} -ne 1 ]]; then - echo "" - echo " FATAL ERROR: Incorrect number of arguments " - echo "" - echo "" - echo "Usage: $0 \${fcsthr} (3 digits) " - echo "" - exit 16 + echo "" + echo " FATAL ERROR: Incorrect number of arguments " + echo "" + echo "" + echo "Usage: $0 \${fcsthr} (3 digits) " + echo "" + exit 16 fi cd "${DATA}" || exit 2 @@ -45,8 +45,8 @@ sleep_interval=10 max_tries=180 idxfile="${COMIN_ATMOS_GRIB_0p25}/${RUN}.${cycle}.pres_b.0p25.f${fcsthr}.grib2.idx" if ! wait_for_file "${idxfile}" "${sleep_interval}" "${max_tries}"; then - msg="FATAL ERROR: No GFS pgrb2 file after waiting" - err_exit "${msg}" + msg="FATAL ERROR: No GFS pgrb2 file after waiting" + err_exit "${msg}" fi ######################################## @@ -82,14 +82,16 @@ export opt28=' -new_grid_interpolation budget -fi ' cpreq "${COMIN_ATMOS_GRIB_0p25}/gfs.t${cyc}z.pres_a.0p25.f${fcsthr}.grib2" "tmpfile2${fcsthr}" cpreq "${COMIN_ATMOS_GRIB_0p25}/gfs.t${cyc}z.pres_b.0p25.f${fcsthr}.grib2" "tmpfile2b${fcsthr}" cat "tmpfile2${fcsthr}" "tmpfile2b${fcsthr}" > "tmpfile${fcsthr}" -${WGRIB2} "tmpfile${fcsthr}" | grep -F -f "${PARMgfs}/product/gfs_awips_parmlist_g2" | \ - ${WGRIB2} -i -grib masterfile "tmpfile${fcsthr}" && true +# shellcheck disable=SC2312 +${WGRIB2} "tmpfile${fcsthr}" | grep -F -f "${PARMgfs}/product/gfs_awips_parmlist_g2" | + ${WGRIB2} -i -grib masterfile "tmpfile${fcsthr}" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "masterfile does not exist." + err_exit "masterfile does not exist." fi ${WGRIB2} masterfile -match ":PWAT:entire atmosphere" -grib gfs_pwat.grb +# shellcheck disable=SC2312 ${WGRIB2} masterfile | grep -v ":PWAT:entire atmosphere" | ${WGRIB2} -i -grib temp_gfs masterfile ################################################################## # Process to change PWAT from level 200 to 10 (Entire Atmosphere) @@ -98,144 +100,145 @@ ${WGRIB2} masterfile | grep -v ":PWAT:entire atmosphere" | ${WGRIB2} -i -grib te ${WGRIB2} gfs_pwat.grb -set_byte 4 23 10 -grib gfs_pwat_levels_10.grb && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to redefine PWAT for the entire atmosphere!" + err_exit "Failed to redefine PWAT for the entire atmosphere!" fi -cat temp_gfs gfs_pwat_levels_10.grb > tmp_masterfile +cat temp_gfs gfs_pwat_levels_10.grb > tmp_masterfile for GRID in conus ak prico pac 003; do - case ${GRID} in - conus) - gridconus="lambert:265.0:25.0:25.0 226.541:369:20318.0 12.19:257:20318.0" - # shellcheck disable=SC2086,SC2248 - ${WGRIB2} tmp_masterfile ${opt1uv} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ - ${opt27} ${opt28} -new_grid ${gridconus} "awps_file_f${fcsthr}_${GRID}" - ;; - ak) - gridak="nps:210.0:60.0 170.0:277:22500 35.0:225:22500" - # shellcheck disable=SC2086,SC2248 - ${WGRIB2} tmp_masterfile ${opt1uv} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ - ${opt27} ${opt28} -new_grid ${gridak} "awps_file_f${fcsthr}_${GRID}" - ;; - prico) - gridprico="latlon 271.75:275:0.25 50.75:205:-0.25" - # shellcheck disable=SC2086,SC2248 - ${WGRIB2} tmp_masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ - ${opt27} ${opt28} -new_grid ${gridprico} "awps_file_f${fcsthr}_${GRID}" - ;; - pac) - gridpac="mercator:20.0 110.0:837:20000:270.0 -45.0:725:20000:65.7345" - # shellcheck disable=SC2086,SC2248 - ${WGRIB2} tmp_masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ - ${opt27} ${opt28} -new_grid ${gridpac} "awps_file_f${fcsthr}_${GRID}" - ;; - 003) - ###################################################################### - # Process GFS GRIB AWIP 1.0 DEGREE (GRID 003) PRODUCTS IN GRIB2 # - ###################################################################### - grid003="latlon 0:360:1.0 90:181:-1.0" - # shellcheck disable=SC2086,SC2248 - ${WGRIB2} tmp_masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ - ${opt27} ${opt28} -new_grid ${grid003} "awps_file_f${fcsthr}_${GRID}" - ;; - *) - export err=2 - err_exit "Unknown output grid ${GRID}" - ;; - esac - trim_rh "awps_file_f${fcsthr}_${GRID}" - scale_dec "awps_file_f${fcsthr}_${GRID}" - ${GRB2INDEX} "awps_file_f${fcsthr}_${GRID}" "awps_file_fi${fcsthr}_${GRID}" - - ########################################################################### - # Checking fields in awps_file_f${fcsthr}_${GRID} file - # before TOCGRIB2 adding WMO headers for AWIPS products. - # - # NOTE: numparm is the total of fields in grib2_awpgfs_20km_conusf000 file - ########################################################################### - numparm=247 - numrec=$( ${WGRIB2} "awps_file_f${fcsthr}_${GRID}" | wc -l ) - - if [[ ${numrec} -lt ${numparm} ]]; then - export err=1 - msg="awps_file_f${fcsthr}_${GRID} file is missing fields for AWIPS !" - err_exit "${msg}" - fi - - # Processing AWIPS GRIB2 grids with WMO headers - - pgm=tocgrib2 - export pgm; prep_step - startmsg - - if [[ ${GRID} = "003" && $(( 10#${fcsthr} % 6 )) == 0 ]]; then - export FORT11="awps_file_f${fcsthr}_${GRID}" - export FORT31="awps_file_fi${fcsthr}_${GRID}" - export FORT51="grib2.awpgfs${fcsthr}.${GRID}" - - cpreq "${PARMgfs}/wmo/grib2_awpgfs${fcsthr}.${GRID}" "parm_list" - - ${TOCGRIB2} < "parm_list" >> "${pgmout}" 2> errfile && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to generate the awips Grib2 file!" - fi - - ############################## - # Post Files to ${COMOUT_ATMOS_WMO} - ############################## - - cpfs "grib2.awpgfs${fcsthr}.${GRID}" \ - "${COMOUT_ATMOS_WMO}/grib2.awpgfs${fcsthr}.${GRID}" - - ############################## - # Distribute Data - ############################## - - if [[ "${SENDDBN}" == "YES" || "${SENDAWIP}" == "YES" ]]; then - "${DBNROOT}/bin/dbn_alert" NTC_LOW "${NET}" "${job}" \ - "${COMOUT_ATMOS_WMO}/grib2.awpgfs${fcsthr}.${GRID}" - else - echo "File ${COMOUT_ATMOS_WMO}/grib2.awpgfs${fcsthr}.${GRID} not posted to db_net." - fi - elif [[ ${GRID} != "003" ]]; then - export FORT11="awps_file_f${fcsthr}_${GRID}" - export FORT31="awps_file_fi${fcsthr}_${GRID}" - export FORT51="grib2.awpgfs_20km_${GRID}_f${fcsthr}" - - cpreq "${PARMgfs}/wmo/grib2_awpgfs_20km_${GRID}f${fcsthr}" "parm_list" - - ${TOCGRIB2} < "parm_list" >> "${pgmout}" 2> errfile && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to write the AWIPS grib2 file" - fi - - ############################## - # Post Files to ${COMOUT_ATMOS_WMO} - ############################## - - cpfs "grib2.awpgfs_20km_${GRID}_f${fcsthr}" \ - "${COMOUT_ATMOS_WMO}/grib2.awpgfs_20km_${GRID}_f${fcsthr}" - - ############################## - # Distribute Data - ############################## - - if [[ "${SENDDBN}" == "YES" || "${SENDAWIP}" == "YES" ]]; then - "${DBNROOT}/bin/dbn_alert" NTC_LOW "${NET}" "${job}" \ - "${COMOUT_ATMOS_WMO}/grib2.awpgfs_20km_${GRID}_f${fcsthr}" - else - echo "File ${COMOUT_ATMOS_WMO}/grib2.awpgfs_20km_${GRID}_f${fcsthr} not posted to db_net." - fi - fi - echo "Awip Processing ${fcsthr} hour completed normally" + case ${GRID} in + conus) + gridconus="lambert:265.0:25.0:25.0 226.541:369:20318.0 12.19:257:20318.0" + # shellcheck disable=SC2086,SC2248 + ${WGRIB2} tmp_masterfile ${opt1uv} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ + ${opt27} ${opt28} -new_grid ${gridconus} "awps_file_f${fcsthr}_${GRID}" + ;; + ak) + gridak="nps:210.0:60.0 170.0:277:22500 35.0:225:22500" + # shellcheck disable=SC2086,SC2248 + ${WGRIB2} tmp_masterfile ${opt1uv} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ + ${opt27} ${opt28} -new_grid ${gridak} "awps_file_f${fcsthr}_${GRID}" + ;; + prico) + gridprico="latlon 271.75:275:0.25 50.75:205:-0.25" + # shellcheck disable=SC2086,SC2248 + ${WGRIB2} tmp_masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ + ${opt27} ${opt28} -new_grid ${gridprico} "awps_file_f${fcsthr}_${GRID}" + ;; + pac) + gridpac="mercator:20.0 110.0:837:20000:270.0 -45.0:725:20000:65.7345" + # shellcheck disable=SC2086,SC2248 + ${WGRIB2} tmp_masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ + ${opt27} ${opt28} -new_grid ${gridpac} "awps_file_f${fcsthr}_${GRID}" + ;; + 003) + ###################################################################### + # Process GFS GRIB AWIP 1.0 DEGREE (GRID 003) PRODUCTS IN GRIB2 # + ###################################################################### + grid003="latlon 0:360:1.0 90:181:-1.0" + # shellcheck disable=SC2086,SC2248 + ${WGRIB2} tmp_masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ + ${opt27} ${opt28} -new_grid ${grid003} "awps_file_f${fcsthr}_${GRID}" + ;; + *) + export err=2 + err_exit "Unknown output grid ${GRID}" + ;; + esac + trim_rh "awps_file_f${fcsthr}_${GRID}" + scale_dec "awps_file_f${fcsthr}_${GRID}" + ${GRB2INDEX} "awps_file_f${fcsthr}_${GRID}" "awps_file_fi${fcsthr}_${GRID}" + + ########################################################################### + # Checking fields in awps_file_f${fcsthr}_${GRID} file + # before TOCGRIB2 adding WMO headers for AWIPS products. + # + # NOTE: numparm is the total of fields in grib2_awpgfs_20km_conusf000 file + ########################################################################### + numparm=247 + # shellcheck disable=SC2312 + numrec=$(${WGRIB2} "awps_file_f${fcsthr}_${GRID}" | wc -l) + + if [[ ${numrec} -lt ${numparm} ]]; then + export err=1 + msg="awps_file_f${fcsthr}_${GRID} file is missing fields for AWIPS !" + err_exit "${msg}" + fi + + # Processing AWIPS GRIB2 grids with WMO headers + + pgm=tocgrib2 + export pgm + prep_step + startmsg + + if [[ ${GRID} = "003" && $((10#${fcsthr} % 6)) == 0 ]]; then + export FORT11="awps_file_f${fcsthr}_${GRID}" + export FORT31="awps_file_fi${fcsthr}_${GRID}" + export FORT51="grib2.awpgfs${fcsthr}.${GRID}" + + cpreq "${PARMgfs}/wmo/grib2_awpgfs${fcsthr}.${GRID}" "parm_list" + + ${TOCGRIB2} < "parm_list" >> "${pgmout}" 2> errfile && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to generate the awips Grib2 file!" + fi + + ############################## + # Post Files to ${COMOUT_ATMOS_WMO} + ############################## + + cpfs "grib2.awpgfs${fcsthr}.${GRID}" \ + "${COMOUT_ATMOS_WMO}/grib2.awpgfs${fcsthr}.${GRID}" + + ############################## + # Distribute Data + ############################## + + if [[ "${SENDDBN}" == "YES" || "${SENDAWIP}" == "YES" ]]; then + "${DBNROOT}/bin/dbn_alert" NTC_LOW "${NET}" "${job}" \ + "${COMOUT_ATMOS_WMO}/grib2.awpgfs${fcsthr}.${GRID}" + else + echo "File ${COMOUT_ATMOS_WMO}/grib2.awpgfs${fcsthr}.${GRID} not posted to db_net." + fi + elif [[ ${GRID} != "003" ]]; then + export FORT11="awps_file_f${fcsthr}_${GRID}" + export FORT31="awps_file_fi${fcsthr}_${GRID}" + export FORT51="grib2.awpgfs_20km_${GRID}_f${fcsthr}" + + cpreq "${PARMgfs}/wmo/grib2_awpgfs_20km_${GRID}f${fcsthr}" "parm_list" + + ${TOCGRIB2} < "parm_list" >> "${pgmout}" 2> errfile && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to write the AWIPS grib2 file" + fi + + ############################## + # Post Files to ${COMOUT_ATMOS_WMO} + ############################## + + cpfs "grib2.awpgfs_20km_${GRID}_f${fcsthr}" \ + "${COMOUT_ATMOS_WMO}/grib2.awpgfs_20km_${GRID}_f${fcsthr}" + + ############################## + # Distribute Data + ############################## + + if [[ "${SENDDBN}" == "YES" || "${SENDAWIP}" == "YES" ]]; then + "${DBNROOT}/bin/dbn_alert" NTC_LOW "${NET}" "${job}" \ + "${COMOUT_ATMOS_WMO}/grib2.awpgfs_20km_${GRID}_f${fcsthr}" + else + echo "File ${COMOUT_ATMOS_WMO}/grib2.awpgfs_20km_${GRID}_f${fcsthr} not posted to db_net." + fi + fi + echo "Awip Processing ${fcsthr} hour completed normally" done if [[ -e "${pgmout}" ]]; then - cat "${pgmout}" + cat "${pgmout}" fi - ############## END OF SCRIPT ####################### diff --git a/scripts/exgfs_atmos_fbwind.sh b/scripts/exgfs_atmos_fbwind.sh index 8f9bbb8094f..2c76bb097c4 100755 --- a/scripts/exgfs_atmos_fbwind.sh +++ b/scripts/exgfs_atmos_fbwind.sh @@ -22,27 +22,27 @@ cd "${DATA}" || exit 2 outfile_name="${COMOUT}/${RUN}.atmos.t${cyc}z.fbwind.pacific.ascii" -set +x -echo " " -echo "#############################################################" -echo " Process Bulletins of forecast winds and temps for Hawaii " -echo " and 15 sites outside of the Hawaiian Islands. " -echo "#############################################################" -echo " " -set_trace +cat << EOF + +############################################################# + Process Bulletins of forecast winds and temps for Hawaii + and 15 sites outside of the Hawaiian Islands. +############################################################# + +EOF export pgm=bulls_fbwndgfs source prep_step for fhr3 in 006 012 024; do - cpreq "${COMIN_ATMOS_GRIB_0p25}/gfs.${cycle}.pres_a.0p25.f${fhr3}.grib2" "tmp_pgrb2_0p25${fhr3}" - cpreq "${COMIN_ATMOS_GRIB_0p25}/gfs.${cycle}.pres_b.0p25.f${fhr3}.grib2" "tmp_pgrb2b_0p25${fhr3}" - cat "tmp_pgrb2_0p25${fhr3}" "tmp_pgrb2b_0p25${fhr3}" > "tmp0p25filef${fhr3}" - # shellcheck disable=SC2312 - ${WGRIB2} "tmp0p25filef${fhr3}" | grep -F -f "${PARMgfs}/product/gfs_fbwnd_parmlist_g2" | \ - ${WGRIB2} -i -grib "tmpfilef${fhr3}" "tmp0p25filef${fhr3}" - ${CNVGRIB} -g21 "tmpfilef${fhr3}" "gfs.t${cyc}z.grbf${fhr3}_grb1" - ${GRBINDEX} "gfs.t${cyc}z.grbf${fhr3}_grb1" "gfs.t${cyc}z.grbf${fhr3}_grb1.idx" + cpreq "${COMIN_ATMOS_GRIB_0p25}/gfs.${cycle}.pres_a.0p25.f${fhr3}.grib2" "tmp_pgrb2_0p25${fhr3}" + cpreq "${COMIN_ATMOS_GRIB_0p25}/gfs.${cycle}.pres_b.0p25.f${fhr3}.grib2" "tmp_pgrb2b_0p25${fhr3}" + cat "tmp_pgrb2_0p25${fhr3}" "tmp_pgrb2b_0p25${fhr3}" > "tmp0p25filef${fhr3}" + # shellcheck disable=SC2312 + ${WGRIB2} "tmp0p25filef${fhr3}" | grep -F -f "${PARMgfs}/product/gfs_fbwnd_parmlist_g2" | + ${WGRIB2} -i -grib "tmpfilef${fhr3}" "tmp0p25filef${fhr3}" + ${CNVGRIB} -g21 "tmpfilef${fhr3}" "gfs.t${cyc}z.grbf${fhr3}_grb1" + ${GRBINDEX} "gfs.t${cyc}z.grbf${fhr3}_grb1" "gfs.t${cyc}z.grbf${fhr3}_grb1.idx" done export FORT11="gfs.t${cyc}z.grbf006_grb1" @@ -66,7 +66,7 @@ cpreq "${PARMgfs}/product/fbwnd_pacific.stnlist" fbwnd_pacific.stnlist "${EXECgfs}/fbwndgfs.x" < fbwnd_pacific.stnlist >> "${pgmout}" 2> errfile && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to run fbwnd for the Pacific!" + err_exit "Failed to run fbwnd for the Pacific!" fi "${USHgfs}/make_ntc_bull.pl" WMOBH NONE KWNO NONE tran.fbwnd_pacific "${outfile_name}" diff --git a/scripts/exgfs_atmos_gempak_gif_ncdc_skew_t.sh b/scripts/exgfs_atmos_gempak_gif_ncdc_skew_t.sh index dae24b09cbe..0e84508a149 100755 --- a/scripts/exgfs_atmos_gempak_gif_ncdc_skew_t.sh +++ b/scripts/exgfs_atmos_gempak_gif_ncdc_skew_t.sh @@ -13,8 +13,8 @@ export NTS="${HOMEgfs}/gempak/ush/restore" if [[ "${MODEL}" == GDAS ]] || [[ "${MODEL}" == GFS ]]; then case "${MODEL}" in - GDAS) fcsthrs="0";; - GFS) fcsthrs="0 12 24 36 48";; + GDAS) fcsthrs="0" ;; + GFS) fcsthrs="0 12 24 36 48" ;; *) echo "FATAL ERROR: Unrecognized model type ${MODEL}" exit 5 @@ -26,7 +26,7 @@ if [[ "${MODEL}" == GDAS ]] || [[ "${MODEL}" == GFS ]]; then for fhr in ${fcsthrs}; do fhr3=$(printf %03d "${fhr}") export GRIBFILE=${COMIN_ATMOS_GEMPAK_1p00}/${RUN}_1p00_${PDY}${cyc}f${fhr3} - if ! wait_for_file "${GRIBFILE}" "${sleep_interval}" "${max_tries}" ; then + if ! wait_for_file "${GRIBFILE}" "${sleep_interval}" "${max_tries}"; then echo "FATAL ERROR: ${GRIBFILE} not found after ${max_tries} iterations" exit 10 fi @@ -43,7 +43,7 @@ fi cd "${DATA}" || exit 1 -export RSHPDY="${PDY:4:}${PDY:2:2}" +export RSHPDY="${PDY:4}${PDY:2:2}" cpreq "${HOMEgfs}/gempak/dictionaries/sonde.land.tbl" sonde.land.tbl cpreq "${HOMEgfs}/gempak/dictionaries/metar.tbl" metar.tbl @@ -53,11 +53,11 @@ cpreq "${COMIN_OBS}/${RUN}.${cycle}.adpupa.tm00.bufr_d" fort.40 "${HOMEgfs}/exec/rdbfmsua.x" >> "${pgmout}" 2> errfile export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to run rdbfmsua!" + err_exit "Failed to run rdbfmsua!" fi # shellcheck disable=SC2012,SC2155 -export filesize=$( ls -l rdbfmsua.out | awk '{print $5}' ) +export filesize=$(ls -l rdbfmsua.out | awk '{print $5}') ################################################################ # only run script if rdbfmsua.out contained upper air data. @@ -74,9 +74,8 @@ fi ############################################################ -if [[ -e "${pgmout}" ]] ; then - cat "${pgmout}" +if [[ -e "${pgmout}" ]]; then + cat "${pgmout}" fi - exit diff --git a/scripts/exgfs_atmos_gempak_meta.sh b/scripts/exgfs_atmos_gempak_meta.sh index 0dcabd76a55..130913e918e 100755 --- a/scripts/exgfs_atmos_gempak_meta.sh +++ b/scripts/exgfs_atmos_gempak_meta.sh @@ -5,11 +5,11 @@ GEMGRD1="${RUN}_1p00_${PDY}${cyc}f" export numproc=23 # Find the last hour available -for (( fhr = fhend; fhr >= fhbeg; fhr = fhr - fhinc )) ; do - fhr3=$(printf "%03d" "${fhr}") - if [[ -r "${COMIN_ATMOS_GEMPAK_1p00}/${GEMGRD1}${fhr3}" ]]; then - break - fi +for ((fhr = fhend; fhr >= fhbeg; fhr = fhr - fhinc)); do + fhr3=$(printf "%03d" "${fhr}") + if [[ -r "${COMIN_ATMOS_GEMPAK_1p00}/${GEMGRD1}${fhr3}" ]]; then + break + fi done sleep_interval=20 @@ -19,71 +19,71 @@ do_all=0 #loop through and process needed forecast hours while [[ ${fhr} -le ${fhend} ]]; do - # - # First check to see if this is a rerun. If so make all Meta files - if [[ ${fhr} -gt 126 && ${first_time} -eq 0 ]]; then - do_all=1 - fi - first_time=1 - - if [[ ${fhr} -eq 120 ]]; then - fhr=126 - fi - - gempak_file="${COMIN_ATMOS_GEMPAK_1p00}/${GEMGRD1}${fhr3}" - if ! wait_for_file "${gempak_file}" "${sleep_interval}" "${max_tries}"; then - err_exit "FATAL ERROR: gempak grid file ${gempak_file} not available after maximum wait time." - fi - - export fhr - - ######################################################## - # Create a script to be poe'd - # - # Note: The number of scripts to be run MUST match the number - # of total_tasks set in the ecf script, or the job will fail. - # - rm -f poescript - - fhr3=$(printf "%03d" "${fhr}") - - if [[ ${do_all} -eq 1 ]] ; then - do_all=0 - # shellcheck disable=SC2312 - awk '{print $1}' "${HOMEgfs}/gempak/fix/gfs_meta" | envsubst > "poescript" - else # - # Do not try to grep out 12, it will grab the 12 from 126. - # This will work as long as we don't need 12 fhr metafiles + # First check to see if this is a rerun. If so make all Meta files + if [[ ${fhr} -gt 126 && ${first_time} -eq 0 ]]; then + do_all=1 + fi + first_time=1 + + if [[ ${fhr} -eq 120 ]]; then + fhr=126 + fi + + gempak_file="${COMIN_ATMOS_GEMPAK_1p00}/${GEMGRD1}${fhr3}" + if ! wait_for_file "${gempak_file}" "${sleep_interval}" "${max_tries}"; then + err_exit "FATAL ERROR: gempak grid file ${gempak_file} not available after maximum wait time." + fi + + export fhr + + ######################################################## + # Create a script to be poe'd + # + # Note: The number of scripts to be run MUST match the number + # of total_tasks set in the ecf script, or the job will fail. # - if [[ ${fhr} -ne 12 ]] ; then - # shellcheck disable=SC2312 - grep "${fhr}" "${HOMEgfs}/gempak/fix/gfs_meta" | awk -F" [0-9]" '{print $1}' | envsubst > "poescript" + rm -f poescript + + fhr3=$(printf "%03d" "${fhr}") + + if [[ ${do_all} -eq 1 ]]; then + do_all=0 + # shellcheck disable=SC2312 + awk '{print $1}' "${HOMEgfs}/gempak/fix/gfs_meta" | envsubst > "poescript" + else + # + # Do not try to grep out 12, it will grab the 12 from 126. + # This will work as long as we don't need 12 fhr metafiles + # + if [[ ${fhr} -ne 12 ]]; then + # shellcheck disable=SC2312 + grep "${fhr}" "${HOMEgfs}/gempak/fix/gfs_meta" | awk -F" [0-9]" '{print $1}' | envsubst > "poescript" + fi + fi + + # If this is the final fcst hour, alert the + # file to all centers. + # + if [[ ${fhr} -ge ${fhend} ]]; then + export DBN_ALERT_TYPE=GFS_METAFILE_LAST + fi + + export fend=${fhr} + + cat poescript + + "${HOMEgfs}/ush/run_mpmd.sh" poescript && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to generate one or more gempak meta plots!" + fi + + if [[ ${fhr} -eq 126 ]]; then + fhr=$((fhr + 6)) + else + fhr=$((fhr + fhinc)) fi - fi - - # If this is the final fcst hour, alert the - # file to all centers. - # - if [[ ${fhr} -ge ${fhend} ]] ; then - export DBN_ALERT_TYPE=GFS_METAFILE_LAST - fi - - export fend=${fhr} - - cat poescript - - "${HOMEgfs}/ush/run_mpmd.sh" poescript && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to generate one or more gempak meta plots!" - fi - - if [[ ${fhr} -eq 126 ]] ; then - fhr=$((fhr + 6)) - else - fhr=$((fhr + fhinc)) - fi done exit diff --git a/scripts/exgfs_atmos_goes_nawips.sh b/scripts/exgfs_atmos_goes_nawips.sh index 083de278498..da085ca4ce1 100755 --- a/scripts/exgfs_atmos_goes_nawips.sh +++ b/scripts/exgfs_atmos_goes_nawips.sh @@ -11,11 +11,11 @@ fhr3=$1 source "${USHgfs}/product_functions.sh" for table in g2varswmo2.tbl g2vcrdwmo2.tbl g2varsncep1.tbl g2vcrdncep1.tbl; do - source_table="${HOMEgfs}/gempak/fix/${table}" - if [[ ! -f "${source_table}" ]]; then - err_exit "FATAL ERROR: ${table} is missing" - fi - cpreq "${source_table}" "${table}" + source_table="${HOMEgfs}/gempak/fix/${table}" + if [[ ! -f "${source_table}" ]]; then + err_exit "FATAL ERROR: ${table} is missing" + fi + cpreq "${source_table}" "${table}" done NAGRIB_TABLE="${HOMEgfs}/gempak/fix/nagrib.tbl" @@ -24,36 +24,34 @@ NAGRIB="${GEMEXE}/nagrib2" # shellcheck disable=SC2312 entry=$(grep "^${RUN2} " "${NAGRIB_TABLE}" | awk 'index($1,"#") != 1 {print $0}') -if [[ "${entry}" != "" ]] ; then - cpyfil=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $2}') - garea=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $3}') - gbtbls=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $4}') - maxgrd=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $5}') - kxky=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $6}') - grdarea=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $7}') - proj=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $8}') - output=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $9}') +if [[ "${entry}" != "" ]]; then + cpyfil=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $2}') + garea=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $3}') + gbtbls=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $4}') + maxgrd=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $5}') + kxky=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $6}') + grdarea=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $7}') + proj=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $8}') + output=$(echo "${entry}" | awk 'BEGIN {FS="|"} {print $9}') else - cpyfil=gds - garea=dset - gbtbls= - maxgrd=4999 - kxky= - grdarea= - proj= - output=T + cpyfil=gds + garea=dset + gbtbls= + maxgrd=4999 + kxky= + grdarea= + proj= + output=T fi pdsext=no - - GEMGRD="${RUN2}_${PDY}${cyc}f${fhr3}" GRIBIN="${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.${GRIB}${fhr3}${EXT}" GRIBIN_chk="${GRIBIN}" if [[ ! -r "${GRIBIN_chk}" ]]; then - export err=7 - err_exit "GRIB index file ${GRIBIN_chk} not found!" + export err=7 + err_exit "GRIB index file ${GRIBIN_chk} not found!" fi cpreq "${GRIBIN}" "grib${fhr3}" @@ -81,13 +79,13 @@ EOF export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to run ${NAGRIB}!" + err_exit "Failed to run ${NAGRIB}!" fi cpfs "${GEMGRD}" "${COMOUT_ATMOS_GEMPAK_0p25}/${GEMGRD}" -if [[ ${SENDDBN} == "YES" ]] ; then - "${DBNROOT}/bin/dbn_alert" MODEL "${DBN_ALERT_TYPE}" "${job}" \ - "${COMOUT_ATMOS_GEMPAK_0p25}/${GEMGRD}" +if [[ ${SENDDBN} == "YES" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${DBN_ALERT_TYPE}" "${job}" \ + "${COMOUT_ATMOS_GEMPAK_0p25}/${GEMGRD}" fi "${GEMEXE}/gpend" diff --git a/scripts/exgfs_atmos_grib2_special_npoess.sh b/scripts/exgfs_atmos_grib2_special_npoess.sh index 3c2dae8e8c1..d1c37c56dd8 100755 --- a/scripts/exgfs_atmos_grib2_special_npoess.sh +++ b/scripts/exgfs_atmos_grib2_special_npoess.sh @@ -49,7 +49,7 @@ export opt28=' -new_grid_interpolation budget -fi ' export SLEEP_TIME=${SLEEP_TIME:-900} export SLEEP_INT=${SLEEP_TIME:-5} -SLEEP_LOOP_MAX=$(( SLEEP_TIME / SLEEP_INT )) +SLEEP_LOOP_MAX=$((SLEEP_TIME / SLEEP_INT)) # TODO: Does this section do anything? I retained if for clarity of # changes/updates, but it does not appear to do anything. @@ -58,21 +58,21 @@ SLEEP_LOOP_MAX=$(( SLEEP_TIME / SLEEP_INT )) # Check if this is a restart #################################### if [[ -f "${COMOUT_ATMOS_GOES}/${RUN}.t${cyc}z.control.goessimpgrb2" ]]; then - modelrecvy=$(cat < "${COMOUT_ATMOS_GOES}/${RUN}.t${cyc}z.control.goessimpgrb") - recvy_cyc="${modelrecvy:8:2}" - recvy_shour="${modelrecvy:10:13}" - - if [[ ${RERUN} == "NO" ]]; then - NEW_SHOUR=$(( recvy_shour + FHINC )) - if (( NEW_SHOUR >= SHOUR )); then - export SHOUR="${NEW_SHOUR}" - fi - if (( recvy_shour >= FHOUR )); then - echo "Forecast Pgrb Generation Already Completed to ${FHOUR}" - else - echo "Starting: PDY=${PDY} cycle=t${recvy_cyc}z SHOUR=${SHOUR}" - fi - fi + modelrecvy=$(cat < "${COMOUT_ATMOS_GOES}/${RUN}.t${cyc}z.control.goessimpgrb") + recvy_cyc="${modelrecvy:8:2}" + recvy_shour="${modelrecvy:10:13}" + + if [[ ${RERUN} == "NO" ]]; then + NEW_SHOUR=$((recvy_shour + FHINC)) + if ((NEW_SHOUR >= SHOUR)); then + export SHOUR="${NEW_SHOUR}" + fi + if ((recvy_shour >= FHOUR)); then + echo "Forecast Pgrb Generation Already Completed to ${FHOUR}" + else + echo "Starting: PDY=${PDY} cycle=t${recvy_cyc}z SHOUR=${SHOUR}" + fi + fi fi ############################################################################## @@ -81,52 +81,52 @@ fi export SHOUR=0 export FHOUR=24 export FHINC=3 -if (( FHOUR > FHMAX_GFS )); then - export FHOUR="${FHMAX_GFS}" +if ((FHOUR > FHMAX_GFS)); then + export FHOUR="${FHMAX_GFS}" fi ############################################################ # Loop Through the Post Forecast Files ############################################################ -for (( fhr=SHOUR; fhr <= FHOUR; fhr = fhr + FHINC )); do - - fhr3=$(printf "%03d" "${fhr}") - - ############################### - # Start Looping for the - # existence of the restart files - ############################### - export pgm="postcheck" - grib_file="${COMIN_ATMOS_GRIB_0p50}/gfs.t${cyc}z.pres_b.0p50.f${fhr3}.grib2.idx" - if ! wait_for_file "${grib_file}" "${SLEEP_INT}" "${SLEEP_LOOP_MAX}"; then - export err=9 - err_exit "0p50 grib file not available after max sleep time" - fi - - ###################################################################### - # Process Global NPOESS 0.50 GFS GRID PRODUCTS IN GRIB2 F000 - F024 # - ###################################################################### - paramlist="${PARMgfs}/product/global_npoess_paramlist_g2" - cpreq "${COMIN_ATMOS_GRIB_0p50}/gfs.t${cyc}z.pres_a.0p50.f${fhr3}.grib2" tmpfile2 - cpreq "${COMIN_ATMOS_GRIB_0p50}/gfs.t${cyc}z.pres_b.0p50.f${fhr3}.grib2" tmpfile2b - cat tmpfile2 tmpfile2b > tmpfile - # shellcheck disable=SC2312 - ${WGRIB2} tmpfile | grep -F -f "${paramlist}" | ${WGRIB2} -i -grib pgb2file tmpfile && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to write pgb2file from the specified parm file \"${paramlist}\"!" - fi - - cpfs pgb2file "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.pgrb2f${fhr3}.npoess" - - if [[ ${SENDDBN} == "YES" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL GFS_PGBNPOESS "${job}" \ - "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.pgrb2f${fhr3}.npoess" - else - echo "File ${RUN}.${cycle}.pgrb2f${fhr3}.npoess not posted to db_net." - fi - echo "${PDY}${cyc}${fhr3}" > "${COMOUT_ATMOS_GOES}/${RUN}.t${cyc}z.control.halfdeg.npoess" - rm -f tmpfile pgb2file +for ((fhr = SHOUR; fhr <= FHOUR; fhr = fhr + FHINC)); do + + fhr3=$(printf "%03d" "${fhr}") + + ############################### + # Start Looping for the + # existence of the restart files + ############################### + export pgm="postcheck" + grib_file="${COMIN_ATMOS_GRIB_0p50}/gfs.t${cyc}z.pres_b.0p50.f${fhr3}.grib2.idx" + if ! wait_for_file "${grib_file}" "${SLEEP_INT}" "${SLEEP_LOOP_MAX}"; then + export err=9 + err_exit "FATAL ERROR: 0p50 grib file not available after max sleep time" + fi + + ###################################################################### + # Process Global NPOESS 0.50 GFS GRID PRODUCTS IN GRIB2 F000 - F024 # + ###################################################################### + paramlist="${PARMgfs}/product/global_npoess_paramlist_g2" + cpreq "${COMIN_ATMOS_GRIB_0p50}/gfs.t${cyc}z.pres_a.0p50.f${fhr3}.grib2" tmpfile2 + cpreq "${COMIN_ATMOS_GRIB_0p50}/gfs.t${cyc}z.pres_b.0p50.f${fhr3}.grib2" tmpfile2b + cat tmpfile2 tmpfile2b > tmpfile + # shellcheck disable=SC2312 + ${WGRIB2} tmpfile | grep -F -f "${paramlist}" | ${WGRIB2} -i -grib pgb2file tmpfile && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "FATAL ERROR: Failed to write pgb2file from the specified parm file \"${paramlist}\"!" + fi + + cpfs pgb2file "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.pgrb2f${fhr3}.npoess" + + if [[ "${SENDDBN}" == "YES" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL GFS_PGBNPOESS "${job}" \ + "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.pgrb2f${fhr3}.npoess" + else + echo "File ${RUN}.${cycle}.pgrb2f${fhr3}.npoess not posted to db_net." + fi + echo "${PDY}${cyc}${fhr3}" > "${COMOUT_ATMOS_GOES}/${RUN}.t${cyc}z.control.halfdeg.npoess" + rm -f tmpfile pgb2file done @@ -141,60 +141,59 @@ export FHINC=${FHOUT_GOES} # Process GFS PGRB2_SPECIAL_POST ################################# -for (( fhr=SHOUR; fhr <= FHOUR; fhr = fhr + FHINC )); do - - fhr3=$(printf "%03d" "${fhr}") - - ############################### - # Start Looping for the - # existence of the restart files - ############################### - export pgm="postcheck" - # grib_file="${COMIN_ATMOS_MASTER}/${RUN}.t${cyc}z.goesmasterf${fhr3}.grb2" - grib_file="${COMIN_ATMOS_MASTER}/${RUN}.t${cyc}z.master-goes.f${fhr3}.grib2" - if ! wait_for_file "${grib_file}" "${SLEEP_INT}" "${SLEEP_LOOP_MAX}"; then - export err=9 - err_exit "GOES master grib file ${grib_file} not available after max sleep time" - fi - ############################### - # Put restart files into /nwges - # for backup to start Model Fcst - ############################### - cpreq "${grib_file}" masterfile - export grid0p25="latlon 0:1440:0.25 90:721:-0.25" - # shellcheck disable=SC2086,SC2248 - ${WGRIB2} masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ - ${opt27} ${opt28} -new_grid ${grid0p25} pgb2file - - export gridconus="lambert:253.0:50.0:50.0 214.5:349:32463.0 1.0:277:32463.0" - # shellcheck disable=SC2086,SC2248 - ${WGRIB2} masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ - ${opt27} ${opt28} -new_grid ${gridconus} pgb2file2 - - ${WGRIB2} pgb2file -s > pgb2ifile - - cpfs pgb2file "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2.0p25.f${fhr3}" - cpfs pgb2ifile "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2.0p25.f${fhr3}.idx" - cpfs pgb2file2 "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2f${fhr3}.grd221" - - if [[ ${SENDDBN} == "YES" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL GFS_GOESSIMPGB2_0P25 "${job}" \ - "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2.0p25.f${fhr}" - "${DBNROOT}/bin/dbn_alert" MODEL GFS_GOESSIMPGB2_0P25_WIDX "${job}" \ - "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2.0p25.f${fhr}.idx" - "${DBNROOT}/bin/dbn_alert" MODEL GFS_GOESSIMGRD221_PGB2 "${job}" \ - "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2f${fhr}.grd221" - fi - - echo "${PDY}${cyc}${fhr}" > "${COMOUT_ATMOS_GOES}/${RUN}.t${cyc}z.control.goessimpgrb" - rm -f pgb2file2 pgb2ifile - - if [[ ${SENDECF} == "YES" ]]; then - # TODO Does this even do anything? - export fhour=$(( fhr % 6 )) - fi +for ((fhr = SHOUR; fhr <= FHOUR; fhr = fhr + FHINC)); do + + fhr3=$(printf "%03d" "${fhr}") + + ############################### + # Start Looping for the + # existence of the restart files + ############################### + export pgm="postcheck" + # grib_file="${COMIN_ATMOS_MASTER}/${RUN}.t${cyc}z.goesmasterf${fhr3}.grb2" + grib_file="${COMIN_ATMOS_MASTER}/${RUN}.t${cyc}z.master-goes.f${fhr3}.grib2" + if ! wait_for_file "${grib_file}" "${SLEEP_INT}" "${SLEEP_LOOP_MAX}"; then + export err=9 + err_exit "FATAL ERROR: GOES master grib file ${grib_file} not available after max sleep time" + fi + ############################### + # Put restart files into /nwges + # for backup to start Model Fcst + ############################### + cpreq "${grib_file}" masterfile + export grid0p25="latlon 0:1440:0.25 90:721:-0.25" + # shellcheck disable=SC2086,SC2248 + ${WGRIB2} masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ + ${opt27} ${opt28} -new_grid ${grid0p25} pgb2file + + export gridconus="lambert:253.0:50.0:50.0 214.5:349:32463.0 1.0:277:32463.0" + # shellcheck disable=SC2086,SC2248 + ${WGRIB2} masterfile ${opt1} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} \ + ${opt27} ${opt28} -new_grid ${gridconus} pgb2file2 + + ${WGRIB2} pgb2file -s > pgb2ifile + + cpfs pgb2file "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2.0p25.f${fhr3}" + cpfs pgb2ifile "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2.0p25.f${fhr3}.idx" + cpfs pgb2file2 "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2f${fhr3}.grd221" + + if [[ ${SENDDBN} == "YES" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL GFS_GOESSIMPGB2_0P25 "${job}" \ + "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2.0p25.f${fhr}" + "${DBNROOT}/bin/dbn_alert" MODEL GFS_GOESSIMPGB2_0P25_WIDX "${job}" \ + "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2.0p25.f${fhr}.idx" + "${DBNROOT}/bin/dbn_alert" MODEL GFS_GOESSIMGRD221_PGB2 "${job}" \ + "${COMOUT_ATMOS_GOES}/${RUN}.${cycle}.goessimpgrb2f${fhr}.grd221" + fi + + echo "${PDY}${cyc}${fhr}" > "${COMOUT_ATMOS_GOES}/${RUN}.t${cyc}z.control.goessimpgrb" + rm -f pgb2file2 pgb2ifile + + if [[ ${SENDECF} == "YES" ]]; then + # TODO Does this even do anything? + export fhour=$((fhr % 6)) + fi done - ################## END OF SCRIPT ####################### diff --git a/scripts/exgfs_atmos_nawips.sh b/scripts/exgfs_atmos_nawips.sh index f3d288bdd09..66cbfa2d8d0 100755 --- a/scripts/exgfs_atmos_nawips.sh +++ b/scripts/exgfs_atmos_nawips.sh @@ -37,16 +37,15 @@ pdsext=no sleep_interval=10 max_tries=360 - mkdir -p "lock.${fhr3}" cd "lock.${fhr3}" || exit 1 for table in g2varswmo2.tbl g2vcrdwmo2.tbl g2varsncep1.tbl g2vcrdncep1.tbl; do - source_table="${HOMEgfs}/gempak/fix/${table}" - if [[ ! -f "${source_table}" ]]; then - err_exit "FATAL ERROR: ${table} is missing" - fi - cpreq "${source_table}" "${table}" + source_table="${HOMEgfs}/gempak/fix/${table}" + if [[ ! -f "${source_table}" ]]; then + err_exit "FATAL ERROR: ${table} is missing" + fi + cpreq "${source_table}" "${table}" done GEMGRD="${RUN}_${grid}_${PDY}${cyc}f${fhr3}" @@ -64,9 +63,9 @@ export opt27=":(APCP|ACPCP|PRATE|CPRAT|DZDT):" export opt28=' -new_grid_interpolation budget -fi ' case ${grid} in - # TODO: Why aren't we interpolating from the 0p25 grids for 35-km and 40-km? - '0p50' | '0p25') grid_in=${grid};; - *) grid_in="1p00";; + # TODO: Why aren't we interpolating from the 0p25 grids for 35-km and 40-km? + '0p50' | '0p25') grid_in=${grid} ;; + *) grid_in="1p00" ;; esac source_var="COMIN_ATMOS_GRIB_${grid_in}" @@ -74,23 +73,23 @@ export GRIBIN="${!source_var}/${RUN}.${cycle}.pres_a.${grid_in}.f${fhr3}.grib2" GRIBIN_chk="${!source_var}/${RUN}.${cycle}.pres_a.${grid_in}.f${fhr3}.grib2.idx" if ! wait_for_file "${GRIBIN_chk}" "${sleep_interval}" "${max_tries}"; then - export err=7 - err_exit "After 1 hour of waiting for ${GRIBIN_chk} file at F${fhr3} to end." + export err=7 + err_exit "After 1 hour of waiting for ${GRIBIN_chk} file at F${fhr3} to end." fi case "${grid}" in - 35km_pac) grid_spec='latlon 130.0:416:0.312 75.125:186:-0.312';; - 35km_atl) grid_spec='latlon 230.0:480:0.312 75.125:242:-0.312';; - 40km) grid_spec='lambert:265.0:25.0:25.0 226.541:185:40635.0 12.19:129:40635.0';; - *) grid_spec='';; + 35km_pac) grid_spec='latlon 130.0:416:0.312 75.125:186:-0.312' ;; + 35km_atl) grid_spec='latlon 230.0:480:0.312 75.125:242:-0.312' ;; + 40km) grid_spec='lambert:265.0:25.0:25.0 226.541:185:40635.0 12.19:129:40635.0' ;; + *) grid_spec='' ;; esac if [[ "${grid_spec}" != "" ]]; then - # shellcheck disable=SC2086,SC2248 - "${WGRIB2}" "${GRIBIN}" ${opt1uv} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} ${opt27} ${opt28} -new_grid ${grid_spec} "grib${fhr3}" - trim_rh "grib${fhr3}" + # shellcheck disable=SC2086,SC2248 + "${WGRIB2}" "${GRIBIN}" ${opt1uv} ${opt21} ${opt22} ${opt23} ${opt24} ${opt25} ${opt26} ${opt27} ${opt28} -new_grid ${grid_spec} "grib${fhr3}" + trim_rh "grib${fhr3}" else - cpreq "${GRIBIN}" "grib${fhr3}" + cpreq "${GRIBIN}" "grib${fhr3}" fi export pgm="nagrib2 F${fhr3}" @@ -116,20 +115,20 @@ EOF export err=$? if [[ ${err} -ne 0 ]]; then - err_exit + err_exit fi "${GEMEXE}/gpend" export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "${GEMEXE}/gpend failed!" + err_exit "${GEMEXE}/gpend failed!" fi cpfs "${GEMGRD}" "${destination}/${GEMGRD}" -if [[ ${SENDDBN} == "YES" ]] ; then +if [[ ${SENDDBN} == "YES" ]]; then "${DBNROOT}/bin/dbn_alert" MODEL "${DBN_ALERT_TYPE}" "${job}" \ - "${destination}/${GEMGRD}" + "${destination}/${GEMGRD}" fi cd "${DATA_RUN}" || exit 1 diff --git a/scripts/exgfs_atmos_postsnd.sh b/scripts/exgfs_atmos_postsnd.sh index a366b1fad50..53b84caa68c 100755 --- a/scripts/exgfs_atmos_postsnd.sh +++ b/scripts/exgfs_atmos_postsnd.sh @@ -23,7 +23,7 @@ # it requires 7 nodes & allocate 21 processes per node(num_ppn=21) ################################################################ -runscript=${USHgfs}/gfs_bufr.sh +runscript="${USHgfs}/gfs_bufr.sh" cd "${DATA}" || exit 2 @@ -53,13 +53,13 @@ declare -x LEVS hour_list=() # Generate hours from 0 to NEND1 with interval NINT1 -for (( hour=0; hour<=NEND1 && hour<=ENDHOUR; hour+=NINT1 )); do - hour_list+=("$(printf "%03d" "$hour")") +for ((hour = 0; hour <= NEND1 && hour <= ENDHOUR; hour += NINT1)); do + hour_list+=("$(printf "%03d" "${hour}")") done # Generate hours from NEND1 + NINT3 to ENDHOUR with interval NINT3 -for (( hour=NEND1+NINT3; hour<=ENDHOUR; hour+=NINT3 )); do - hour_list+=("$(printf "%03d" "$hour")") +for ((hour = NEND1 + NINT3; hour <= ENDHOUR; hour += NINT3)); do + hour_list+=("$(printf "%03d" "${hour}")") done # Print the hour list @@ -69,55 +69,55 @@ echo "Hour List:" "${hour_list[@]}" export ntasks="${#hour_list[@]}" # Print the total number of hours -echo "Total number of hours: $ntasks" +echo "Total number of hours: ${ntasks}" # allocate 21 processes per node # don't allocate more processes, or it might have memory issue #export tasks_per_node=21 #export APRUN="mpiexec -np ${ntasks} -ppn ${tasks_per_node} --cpu-bind core cfp " -rm -f ${DATA}/poescript_bufr +rm -f "${DATA}/poescript_bufr" for fhr in "${hour_list[@]}"; do - if [ ! -s "${DATA}/${fhr}" ]; then mkdir -p ${DATA}/${fhr}; fi - export FINT=${NINT1} - ## 1-hourly output before $NEND1, 3-hourly output after - if [[ $((10#${fhr})) -gt $((10#${NEND1})) ]]; then - export FINT=${NINT3} - fi - if [[ $((10#${fhr})) -eq 0 ]]; then - export F00FLAG="YES" - else - export F00FLAG="NO" - fi - - # Convert fhr to integer - fhr_int=$((10#$fhr)) - - # Get previous hour - if (( fhr_int == STARTHOUR )); then - fhr_p=${fhr_int} - else - fhr_p=$(( fhr_int - FINT )) - fi - - # Format fhr_p with leading zeros - fhr_p="$(printf "%03d" "$fhr_p")" - - filename="${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.atm.logf${fhr}.${logfm}" - if [[ -z ${filename} ]]; then - err_exit "File ${filename} not found." - else - echo "${runscript} ${fhr} ${fhr_p} ${FINT} ${F00FLAG} ${DATA}/${fhr}" >> "${DATA}/poescript_bufr" - fi + if [[ ! -s "${DATA}/${fhr}" ]]; then mkdir -p "${DATA}/${fhr}"; fi + export FINT=${NINT1} + ## 1-hourly output before $NEND1, 3-hourly output after + if [[ $((10#${fhr})) -gt $((10#${NEND1})) ]]; then + export FINT=${NINT3} + fi + if [[ $((10#${fhr})) -eq 0 ]]; then + export F00FLAG="YES" + else + export F00FLAG="NO" + fi + + # Convert fhr to integer + fhr_int=$((10#${fhr})) + + # Get previous hour + if ((fhr_int == STARTHOUR)); then + fhr_p=${fhr_int} + else + fhr_p=$((fhr_int - FINT)) + fi + + # Format fhr_p with leading zeros + fhr_p="$(printf "%03d" "${fhr_p}")" + + filename="${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.atm.logf${fhr}.${logfm}" + if [[ -z ${filename} ]]; then + err_exit "FATAL ERROR: File ${filename} not found." + else + echo "${runscript} ${fhr} ${fhr_p} ${FINT} ${F00FLAG} ${DATA}/${fhr}" >> "${DATA}/poescript_bufr" + fi done # Run with MPMD "${USHgfs}/run_mpmd.sh" "${DATA}/poescript_bufr" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "One or more BUFR MPMD tasks failed!" + err_exit "One or more BUFR MPMD tasks failed!" fi cd "${DATA}" || exit 2 @@ -135,16 +135,17 @@ done # start to generate bufr products at fhr=${ENDHOUR} export MAKEBUFR=YES -export fhr="$(printf "%03d" "$ENDHOUR")" +fhr="$(printf "%03d" "${ENDHOUR}")" +export fhr export FINT=${NINT1} ## 1-hourly output before $NEND1, 3-hourly output after if [[ $((10#${fhr})) -gt $((10#${NEND1})) ]]; then - export FINT=${NINT3} + export FINT=${NINT3} fi if [[ $((10#${fhr})) -eq 0 ]]; then - export F00FLAG="YES" + export F00FLAG="YES" else - export F00FLAG="NO" + export F00FLAG="NO" fi ${runscript} "${fhr}" "${fhr_p}" "${FINT}" "${F00FLAG}" "${DATA}" @@ -152,6 +153,7 @@ ${runscript} "${fhr}" "${fhr_p}" "${FINT}" "${F00FLAG}" "${DATA}" # Tar and gzip the individual bufr files and send them to /com ############################################################## cd "${COMOUT_ATMOS_BUFR}" || exit 2 +# shellcheck disable=SC2312 tar -cf - . | /usr/bin/gzip > "${RUN}.${cycle}.bufrsnd.tar.gz" cd "${DATA}" || exit 2 @@ -168,7 +170,7 @@ fi # data and add appropriate WMO Headers ######################################## rm -rf poe_col -for (( m = 1; m <= NUM_SND_COLLECTIVES; m++ )); do +for ((m = 1; m <= NUM_SND_COLLECTIVES; m++)); do echo "${USHgfs}/gfs_sndp.sh ${m} " >> poe_col done @@ -188,8 +190,7 @@ ${APRUN_POSTSNDCFP} cmdfile # GEMPAK surface and sounding data files ######################################## if [[ "${DO_GEMPAK:-"NO"}" == "YES" ]]; then - sh "${USHgfs}/gfs_bfr2gpk.sh" + sh "${USHgfs}/gfs_bfr2gpk.sh" fi - ############## END OF SCRIPT ####################### diff --git a/scripts/exgfs_pmgr.sh b/scripts/exgfs_pmgr.sh index ddd5257928a..101c5bb4649 100755 --- a/scripts/exgfs_pmgr.sh +++ b/scripts/exgfs_pmgr.sh @@ -6,69 +6,43 @@ # This script monitors the progress of the gfs_fcst job # -hour=00 +hour=0 TEND=384 -TCP=385 -if [ -e posthours ]; then - rm -f posthours +if [[ -e posthours ]]; then + rm -f posthours fi -while [ $hour -lt $TCP ]; -do - hour=$(printf "%02d" $hour) - echo $hour >>posthours - if [ 10#$hour -lt 240 ] - then - # JY if [ $hour -lt 12 ] - if [ 10#$hour -lt 120 ] - then - let "hour=hour+1" - else - let "hour=hour+3" - fi - else - let "hour=hour+12" - fi +declare -a posthours +while [[ "${hour}" -le "${TEND}" ]]; do + posthours+=("${hour}") + if [[ ${hour} -lt 240 ]]; then + if [[ ${hour} -lt 120 ]]; then + hour=$((hour + 1)) + else + hour=$((hour + 3)) + fi + else + hour=$((hour + 12)) + fi done -postjobs=$(cat posthours) # -# Wait for all fcst hours to finish +# Wait for all fcst hours to finish # -icnt=1 -while [ $icnt -lt 1000 ] -do - for fhr in $postjobs - do - fhr3=$(printf "%03d" $fhr) - if [ -s ${COMIN}/gfs.${cycle}.logf${fhr}.txt -o -s ${COMIN}/gfs.${cycle}.logf${fhr3}.txt ] - then - if [ $fhr -eq 0 ] - then +sleep_interval=10 +max_tries=1000 +for fhr in "${posthours[@]}"; do + fhr3=$(sprintf "%03d" "${fhr}") + log_file="${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.atm.logf${fhr3}.txt" + if ! wait_for_file "${log_file}" "${sleep_interval}" "${max_tries}"; then + msg="FATAL ERROR: After 2 hours of waiting for GFS FCST hour ${fhr3}." + err_exit "${msg}" + fi + if [[ ${fhr} -eq 0 ]]; then ecflow_client --event release_postanl - fi - ecflow_client --event release_post${fhr} - # Remove current fhr from list - postjobs=$(echo $postjobs | sed "s/${fhr}//") fi - done - - result_check=$(echo $postjobs | wc -w) - if [ $result_check -eq 0 ] - then - break - fi - - sleep 10 - icnt=$((icnt + 1)) - if [ $icnt -ge 720 ] - then - msg="ABORTING after 2 hours of waiting for GFS FCST hours $postjobs." - err_exit $msg - fi - + ecflow_client --event "release_post${fhr3}" done - exit diff --git a/scripts/exgfs_prdgen_manager.sh b/scripts/exgfs_prdgen_manager.sh index 17913f5d552..7e4496cc1e8 100755 --- a/scripts/exgfs_prdgen_manager.sh +++ b/scripts/exgfs_prdgen_manager.sh @@ -6,67 +6,40 @@ # This script monitors the progress of the gfs_fcst job # -hour=00 +hour=0 TEND=384 -TCP=385 -if [ -e pgrb2_hours ]; then - rm -f pgrb2_hours +if [[ -e pgrb2_hours ]]; then + rm -f pgrb2_hours fi -while [ $hour -lt $TCP ]; -do - hour=$(printf "%02d" $hour) - echo $hour >>pgrb2_hours - if [ 10#$hour -lt 240 ] - then - if [ 10#$hour -lt 120 ] - then - let "hour=hour+1" - else - let "hour=hour+3" - fi - else - let "hour=hour+12" - fi +declare -a pgrb2_hours +while [[ "${hour}" -le "${TEND}" ]]; do + pgrb2_hours+=("${hour}") + if [[ ${hour} -lt 240 ]]; then + if [[ ${hour} -lt 120 ]]; then + hour=$((hour + 1)) + else + hour=$((hour + 3)) + fi + else + hour=$((hour + 12)) + fi done -pgrb2_jobs=$(cat pgrb2_hours) # -# Wait for all fcst hours to finish +# Wait for all fcst hours to finish # -icnt=1 -while [ $icnt -lt 1000 ] -do - for fhr in ${pgrb2_jobs} - do - if [ -s ${COMIN}/gfs.${cycle}.master.grb2if${fhr} ] - then -# if [ $fhr -eq 0 ] -# then -# ecflow_client --event release_pgrb2_anl -# fi - ecflow_client --event release_pgrb2_${fhr} - # Remove current fhr from list - pgrb2_jobs=$(echo ${pgrb2_jobs} | sed "s/${fhr}//") +sleep_interval=10 +max_tries=1000 +for fhr in "${pgrb2_hours[@]}"; do + fhr3=$(sprintf "%03d" "${fhr}") + master_file="${COMIN_ATMOS_MASTER}/gfs.${cycle}.master.grb2f${fhr3}" + if ! wait_for_file "${master_file}" "${sleep_interval}" "${max_tries}"; then + export err=1 + err_exit "After 2 hours of waiting for GFS POST hour ${fhr3}." fi - done - - result_check=$(echo ${pgrb2_jobs} | wc -w) - if [ $result_check -eq 0 ] - then - break - fi - - sleep 10 - icnt=$((icnt + 1)) - if [ $icnt -ge 720 ] - then - msg="ABORTING after 2 hours of waiting for GFS POST hours ${pgrb2_jobs}." - err_exit $msg - fi - + ecflow_client --event "release_pgrb2_${fhr3}" done - exit diff --git a/scripts/exgfs_wave_init.sh b/scripts/exgfs_wave_init.sh index 74e328bcccb..19f3bc6992f 100755 --- a/scripts/exgfs_wave_init.sh +++ b/scripts/exgfs_wave_init.sh @@ -28,59 +28,58 @@ EOF # 1.a Model definition files - # Eliminate duplicate grids # Use an associative array, since they don't allow duplicate keys declare -A grdALL for grd in ${WAVECUR_FID} ${WAVEICE_FID} ${WAVEWND_FID} ${waveuoutpGRD} ${waveGRD} ${wavepostGRD} ${waveinterpGRD}; do - # For ease of access, make the value the same as the key - grdALL["${grd}"]="${grd}" + # For ease of access, make the value the same as the key + grdALL["${grd}"]="${grd}" done for grdID in "${grdALL[@]}"; do - echo "INFO: Setting up to generate mod_def file for ${grdID}" - if [[ -f "${FIXgfs}/wave/ww3_grid.inp.${grdID}" ]]; then - cpreq "${FIXgfs}/wave/ww3_grid.inp.${grdID}" "ww3_grid.inp.${grdID}" - echo "INFO: ww3_grid.inp.${grdID} copied (${FIXgfs}/wave/ww3_grid.inp.${grdID})." - else - export err=2 - err_exit "No inp file for model definition file for grid ${grdID}" - fi + echo "INFO: Setting up to generate mod_def file for ${grdID}" + if [[ -f "${FIXgfs}/wave/ww3_grid.inp.${grdID}" ]]; then + cpreq "${FIXgfs}/wave/ww3_grid.inp.${grdID}" "ww3_grid.inp.${grdID}" + echo "INFO: ww3_grid.inp.${grdID} copied (${FIXgfs}/wave/ww3_grid.inp.${grdID})." + else + export err=2 + err_exit "No inp file for model definition file for grid ${grdID}" + fi - if [[ -f "${FIXgfs}/wave/${grdID}.msh" ]]; then - cpreq "${FIXgfs}/wave/${grdID}.msh" "${grdID}.msh" - fi - #TODO: how do we say "it's unstructured, and therefore need to have error check here" + if [[ -f "${FIXgfs}/wave/${grdID}.msh" ]]; then + cpreq "${FIXgfs}/wave/${grdID}.msh" "${grdID}.msh" + fi + #TODO: how do we say "it's unstructured, and therefore need to have error check here" - echo "${USHgfs}/wave_grid_moddef.sh ${grdID}" >> mpmd_script + echo "${USHgfs}/wave_grid_moddef.sh ${grdID}" >> mpmd_script done # 1.a.1 Execute MPMD or process serially "${USHgfs}/run_mpmd.sh" "${DATA}/mpmd_script" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "run_mpmd.sh failed!" + err_exit "run_mpmd.sh failed!" fi # 1.a.3 File check for grdID in "${grdALL[@]}"; do - if [[ -f "${COMOUT_WAVE_PREP}/${RUN}.t${cyc}z.mod_def.${grdID}.bin" ]]; then - echo "INFO: mod_def.${grdID} succesfully created/copied" - else - export err=3 - err_exit "No model definition file for grid ${grdID}" - fi + if [[ -f "${COMOUT_WAVE_PREP}/${RUN}.t${cyc}z.mod_def.${grdID}.bin" ]]; then + echo "INFO: mod_def.${grdID} succesfully created/copied" + else + export err=3 + err_exit "No model definition file for grid ${grdID}" + fi done # Copy to other members if needed if [[ "${NET}" == "gefs" && ${NMEM_ENS} -gt 0 ]]; then - for mem in $(seq -f "%03g" 1 "${NMEM_ENS}"); do - MEMDIR="mem${mem}" YMD="${PDY}" HH="${cyc}" declare_from_tmpl COMOUT_WAVE_PREP_MEM:COM_WAVE_PREP_TMPL - mkdir -p "${COMOUT_WAVE_PREP_MEM}" - for grdID in "${grdALL[@]}"; do - cpfs "${COMOUT_WAVE_PREP}/${RUN}.t${cyc}z.mod_def.${grdID}.bin" "${COMOUT_WAVE_PREP_MEM}/${RUN}.t${cyc}z.mod_def.${grdID}.bin" + for mem in $(seq -f "%03g" 1 "${NMEM_ENS}"); do + MEMDIR="mem${mem}" YMD="${PDY}" HH="${cyc}" declare_from_tmpl COMOUT_WAVE_PREP_MEM:COM_WAVE_PREP_TMPL + mkdir -p "${COMOUT_WAVE_PREP_MEM}" + for grdID in "${grdALL[@]}"; do + cpfs "${COMOUT_WAVE_PREP}/${RUN}.t${cyc}z.mod_def.${grdID}.bin" "${COMOUT_WAVE_PREP_MEM}/${RUN}.t${cyc}z.mod_def.${grdID}.bin" + done done - done fi # End of MWW3 init config script ------------------------------------------- # diff --git a/scripts/exgfs_wave_nawips.sh b/scripts/exgfs_wave_nawips.sh index b703f9399c2..5400a29962d 100755 --- a/scripts/exgfs_wave_nawips.sh +++ b/scripts/exgfs_wave_nawips.sh @@ -43,90 +43,90 @@ EOF # Loop over the grids for grid in ${grids}; do - case ${grid} in - aoc_9km) - grdIDout='gfswavearc' - ;; - at_10m) - grdIDout='gfswaveat10m' - ;; - ep_10m) - grdIDout='gfswaveep10m' - ;; - wc_10m) - grdIDout='gfswavewc10m' - ;; - glo_30m) - grdIDout='gfswavegl30m' - ;; - gnh_10m) - grdIDout='gfswavenh' - ;; - gsh_15m) - grdIDout='gfswavesh' - ;; - glo_200) - grdIDout='gfswaves200k' - ;; - *) - echo "FATAL ERROR: Unspecified grid '${grid}'" - exit 9 - ;; - esac - process_grdID "${grid}" - - com_varname="COMIN_WAVE_GRID_${GRDREGION}_${GRDRES}" - com_dir=${!com_varname} - GRIBIN="${RUN}.${cycle}.${GRDREGION}.${GRDRES}.f${fhr3}.grib2" - cpreq "${com_dir}/${GRIBIN}" "./${GRIBIN}" - - nagrib_file="${GRIBIN}" - if [[ "${GRDREGION}.${GRDRES}" = "global.0p25" ]]; then - nagrib_file="${RUN}.${cycle}.global.${gridIDout}.${fhr3}.grib2" - ${WGRIB2} -lola 0:720:0.5 -90:361:0.5 "${nagrib_file}" grib "${GRIBIN}" + case ${grid} in + aoc_9km) + grdIDout='gfswavearc' + ;; + at_10m) + grdIDout='gfswaveat10m' + ;; + ep_10m) + grdIDout='gfswaveep10m' + ;; + wc_10m) + grdIDout='gfswavewc10m' + ;; + glo_30m) + grdIDout='gfswavegl30m' + ;; + gnh_10m) + grdIDout='gfswavenh' + ;; + gsh_15m) + grdIDout='gfswavesh' + ;; + glo_200) + grdIDout='gfswaves200k' + ;; + *) + echo "FATAL ERROR: Unspecified grid '${grid}'" + exit 9 + ;; + esac + process_grdID "${grid}" + + com_varname="COMIN_WAVE_GRID_${GRDREGION}_${GRDRES}" + com_dir=${!com_varname} + GRIBIN="${RUN}.${cycle}.${GRDREGION}.${GRDRES}.f${fhr3}.grib2" + cpreq "${com_dir}/${GRIBIN}" "./${GRIBIN}" + + nagrib_file="${GRIBIN}" + if [[ "${GRDREGION}.${GRDRES}" = "global.0p25" ]]; then + nagrib_file="${RUN}.${cycle}.global.${gridIDout}.${fhr3}.grib2" + ${WGRIB2} -lola 0:720:0.5 -90:361:0.5 "${nagrib_file}" grib "${GRIBIN}" + export err=$? + if [[ ${err} -ne 0 ]]; then + export pgm="${WGRIB2}" + err_exit "wgrib2 failed to interpolate" + fi + fi + + GEMGRD="${grdIDout}_${PDY}${cyc}f${fhr3}" + GBFILE="grib_${grid}" + + cpreq "${nagrib_file}" "${GBFILE}" + + rm -f "gempak.parm.${grid}" + atparse < "${DATA}/gempak.parm.tmpl" >> "${DATA}/gempak.parm.${grid}" + cat "${DATA}/gempak.parm.${grid}" + + startmsg + export pgm="${NAGRIB}" + ${pgm} < "${DATA}/gempak.parm.${grid}" && true export err=$? if [[ ${err} -ne 0 ]]; then - export pgm="${WGRIB2}" - err_exit "wgrib2 failed to interpolate" + err_exit "${pgm} failed during the generation of ${GEMGRD}" + fi + ##################################################### + # GEMPAK DOES NOT ALWAYS HAVE A NON ZERO RETURN CODE + # WHEN IT CAN NOT PRODUCE THE DESIRED GRID. CHECK + # FOR THIS CASE HERE. + ##################################################### + if [[ -f "${GEMGRD}" ]]; then + ls -l "${GEMGRD}" + else + export err=1 + export pgm="GEMPAK CHECK FILE" + err_exit "Gempak failed to generate the desired grid ${GEMGRD}" + fi + + if [[ "${NAGRIB}" == "nagrib2" ]]; then gpend; fi + + # Copy output to COMOUT + cpfs "${GEMGRD}" "${COMOUT_WAVE_GEMPAK}/${GEMGRD}" + + if [[ "${SENDDBN}" == "YES" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${DBN_ALERT_TYPE}" "${job}" "${COMOUT_WAVE_GEMPAK}/${GEMGRD}" fi - fi - - GEMGRD="${grdIDout}_${PDY}${cyc}f${fhr3}" - GBFILE="grib_${grid}" - - cpreq "${nagrib_file}" "${GBFILE}" - - rm -f "gempak.parm.${grid}" - atparse < "${DATA}/gempak.parm.tmpl" >> "${DATA}/gempak.parm.${grid}" - cat "${DATA}/gempak.parm.${grid}" - - startmsg - export pgm="${NAGRIB}" - ${pgm} < "${DATA}/gempak.parm.${grid}" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "${pgm} failed during the generation of ${GEMGRD}" - fi - ##################################################### - # GEMPAK DOES NOT ALWAYS HAVE A NON ZERO RETURN CODE - # WHEN IT CAN NOT PRODUCE THE DESIRED GRID. CHECK - # FOR THIS CASE HERE. - ##################################################### - if [[ -f "${GEMGRD}" ]]; then - ls -l "${GEMGRD}" - else - export err=1 - export pgm="GEMPAK CHECK FILE" - err_exit "Gempak failed to generate the desired grid ${GEMGRD}" - fi - - if [[ "${NAGRIB}" == "nagrib2" ]]; then gpend; fi - - # Copy output to COMOUT - cpfs "${GEMGRD}" "${COMOUT_WAVE_GEMPAK}/${GEMGRD}" - - if [[ "${SENDDBN}" == "YES" ]] ; then - "${DBNROOT}/bin/dbn_alert" MODEL "${DBN_ALERT_TYPE}" "${job}" "${COMOUT_WAVE_GEMPAK}/${GEMGRD}" - fi done diff --git a/scripts/exgfs_wave_post_gridded_sbs.sh b/scripts/exgfs_wave_post_gridded_sbs.sh index 6d17b35521b..0d12e48075c 100755 --- a/scripts/exgfs_wave_post_gridded_sbs.sh +++ b/scripts/exgfs_wave_post_gridded_sbs.sh @@ -37,12 +37,12 @@ cat << EOF INFO: Post-process grids: ${wavepostGRD} EOF -fhr3=$(printf %03i ${FORECAST_HOUR}) +fhr3=$(printf %03i "${FORECAST_HOUR}") valid_time=$(date -u -d "${PDY} ${cyc} + ${FORECAST_HOUR} hours" "+%Y%m%d%H") # Copy model definition files for grdID in ${waveGRD} ${wavepostGRD} ${waveinterpGRD}; do - cpreq "${COMIN_WAVE_PREP}/${RUN}.t${cyc}z.mod_def.${grdID}.bin" "mod_def.${grdID}" + cpreq "${COMIN_WAVE_PREP}/${RUN}.t${cyc}z.mod_def.${grdID}.bin" "mod_def.${grdID}" done # Copy model forecast data to DATA @@ -50,12 +50,12 @@ cpreq "${COMIN_WAVE_HISTORY}/${RUN}.t${cyc}z.${waveGRD}.f${fhr3}.bin" "./out_grd # Check for input templates for grib2 products (copying will be done in the grib2 script) if [[ "${DOGRB_WAV}" == "YES" ]]; then - for grbGRD in ${waveinterpGRD} ${wavepostGRD}; do - if [[ ! -f "${PARMgfs}/wave/ww3_grib2.${grbGRD}.inp.tmpl" ]]; then - export err=1 - err_exit "No template for grib generation" - fi - done + for grbGRD in ${waveinterpGRD} ${wavepostGRD}; do + if [[ ! -f "${PARMgfs}/wave/ww3_grib2.${grbGRD}.inp.tmpl" ]]; then + export err=1 + err_exit "No template for grib generation" + fi + done fi # Data summary @@ -68,53 +68,53 @@ cat << EOF EOF if [[ "${DOGRB_WAV}" == "NO" ]]; then - export err=1 - err_exit "DOGRB_WAV = NO; No grib2 products will be created, ABORT!" + export err=1 + err_exit "DOGRB_WAV = NO; No grib2 products will be created, ABORT!" fi # 2.a Command file set-up rm -f cmdfile.* cmdfile -count=0 # Counter for command files +count=0 # Counter for command files # Products on the interpolation grid "waveinterpGRD" if [[ "${DOGRI_WAV}" == "YES" ]]; then - dt_int=3600. - n_int=9999 - ymdh_int=$(date -u -d "${valid_time:0:8} ${valid_time:8:2} - ${WAVHINDH} hours" "+%Y%m%d%H") - for grdID in ${waveinterpGRD}; do - count=$(( count+1 )) - echo "#!/bin/bash" > "cmdfile.${count}" - echo "${USHgfs}/wave_grid_interp_sbs.sh ${grdID} ${ymdh_int} ${dt_int} ${n_int} > ${DATA}/grid_interp_${grdID}.out 2>&1" >> "${DATA}/cmdfile.${count}" - echo "cat ${DATA}/grid_interp_${grdID}.out" >> "cmdfile.${count}" - if [[ "${DOGRB_WAV}" == "YES" ]]; then - process_grdID "${grdID}" - echo "${USHgfs}/wave_grib2_sbs.sh ${grdID} ${GRIDNR} ${MODNR} ${valid_time} ${FORECAST_HOUR} ${GRDREGION} ${GRDRES} '${OUTPARS_WAV}' > ${DATA}/grib2_${grdID}.out 2>&1" >> "${DATA}/cmdfile.${count}" - echo "cat ${DATA}/grib2_${grdID}.out" >> "${DATA}/cmdfile.${count}" - fi - chmod 755 "cmdfile.${count}" - echo "${DATA}/cmdfile.${count}" >> "${DATA}/cmdfile" - done + dt_int=3600. + n_int=9999 + ymdh_int=$(date -u -d "${valid_time:0:8} ${valid_time:8:2} - ${WAVHINDH} hours" "+%Y%m%d%H") + for grdID in ${waveinterpGRD}; do + count=$((count + 1)) + echo "#!/bin/bash" > "cmdfile.${count}" + echo "${USHgfs}/wave_grid_interp_sbs.sh ${grdID} ${ymdh_int} ${dt_int} ${n_int} > ${DATA}/grid_interp_${grdID}.out 2>&1" >> "${DATA}/cmdfile.${count}" + echo "cat ${DATA}/grid_interp_${grdID}.out" >> "cmdfile.${count}" + if [[ "${DOGRB_WAV}" == "YES" ]]; then + process_grdID "${grdID}" + echo "${USHgfs}/wave_grib2_sbs.sh ${grdID} ${GRIDNR} ${MODNR} ${valid_time} ${FORECAST_HOUR} ${GRDREGION} ${GRDRES} '${OUTPARS_WAV}' > ${DATA}/grib2_${grdID}.out 2>&1" >> "${DATA}/cmdfile.${count}" + echo "cat ${DATA}/grib2_${grdID}.out" >> "${DATA}/cmdfile.${count}" + fi + chmod 755 "cmdfile.${count}" + echo "${DATA}/cmdfile.${count}" >> "${DATA}/cmdfile" + done fi # Products on the post-processing grid "wavepostGRD" if [[ "${DOGRB_WAV}" == "YES" ]]; then - for grdID in ${wavepostGRD}; do # First concatenate grib files for sbs grids - count=$(( count+1 )) - process_grdID "${grdID}" - echo "#!/bin/bash" > "cmdfile.${count}" - echo "${USHgfs}/wave_grib2_sbs.sh ${grdID} ${GRIDNR} ${MODNR} ${valid_time} ${FORECAST_HOUR} ${GRDREGION} ${GRDRES} '${OUTPARS_WAV}' > grib2_${grdID}.out 2>&1" >> "${DATA}/cmdfile.${count}" - echo "cat ${DATA}/grib2_${grdID}.out" >> "${DATA}/cmdfile.${count}" - chmod 755 "cmdfile.${count}" - echo "${DATA}/cmdfile.${count}" >> "${DATA}/cmdfile" - done + for grdID in ${wavepostGRD}; do # First concatenate grib files for sbs grids + count=$((count + 1)) + process_grdID "${grdID}" + echo "#!/bin/bash" > "cmdfile.${count}" + echo "${USHgfs}/wave_grib2_sbs.sh ${grdID} ${GRIDNR} ${MODNR} ${valid_time} ${FORECAST_HOUR} ${GRDREGION} ${GRDRES} '${OUTPARS_WAV}' > grib2_${grdID}.out 2>&1" >> "${DATA}/cmdfile.${count}" + echo "cat ${DATA}/grib2_${grdID}.out" >> "${DATA}/cmdfile.${count}" + chmod 755 "cmdfile.${count}" + echo "${DATA}/cmdfile.${count}" >> "${DATA}/cmdfile" + done fi # Ensure there are enough processors for MPMD else use serial if [[ ${ntasks} -lt ${count} ]]; then - if [[ "${USE_CFP:-}" == "YES" ]]; then - echo "WARNING: Not enough processors for MPMD, '${ntasks} < ${count}', running in serial mode" - export USE_CFP="NO" - fi + if [[ "${USE_CFP:-}" == "YES" ]]; then + echo "WARNING: Not enough processors for MPMD, '${ntasks} < ${count}', running in serial mode" + export USE_CFP="NO" + fi fi # Execute command file @@ -122,7 +122,7 @@ echo "INFO: Running MPMD job with ${count} commands" "${USHgfs}/run_mpmd.sh" "${DATA}/cmdfile" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "run_mpmd.sh failed!" + err_exit "run_mpmd.sh failed!" fi # Check if grib2 file created @@ -131,8 +131,8 @@ com_varname="COMOUT_WAVE_GRID_${GRDREGION}_${GRDRES}" com_dir=${!com_varname} gribchk="${RUN}.t${cyc}z.${GRDREGION}.${GRDRES}.f${fhr3}.grib2" if [[ ! -s "${com_dir}/${gribchk}" ]]; then - export err=2 - err_exit "'${gribchk}' not generated in this job" + export err=2 + err_exit "'${gribchk}' not generated in this job" fi exit 0 diff --git a/scripts/exgfs_wave_post_pnt.sh b/scripts/exgfs_wave_post_pnt.sh index 93ba602ff04..6525a18339c 100755 --- a/scripts/exgfs_wave_post_pnt.sh +++ b/scripts/exgfs_wave_post_pnt.sh @@ -30,25 +30,11 @@ export WAV_MOD_TAG="${RUN}.t${cyc}z" -echo "HAS BEGUN on $(hostname)" -echo "Starting WAVE PNT POSTPROCESSOR SCRIPT for ${WAV_MOD_TAG}" - -cat << EOF - - ************************************* - *** WAVE PNT POSTPROCESSOR SCRIPT *** - ************************************* - -Starting at : $(date) -------------- - -EOF - # Script will run only if pre-defined NTASKS # The actual work is distributed over these tasks. if [[ -z "${NTASKS}" ]]; then - export err=1 - err_exit "Requires NTASKS to be set" + export err=1 + err_exit "Requires NTASKS to be set" fi # 0.c Defining model grids @@ -77,69 +63,71 @@ printf "\nPreparing input files :\n-------------------------\n" # Copy model definition files iloop=0 for grdID in ${waveuoutpGRD}; do - if [[ -f "${COMIN_WAVE_PREP}/${WAV_MOD_TAG}.mod_def.${grdID}.bin" ]]; then - echo " Mod def file for ${grdID} found in ${COMIN_WAVE_PREP}. copying ...." - cpreq -f "${COMIN_WAVE_PREP}/${WAV_MOD_TAG}.mod_def.${grdID}.bin" "mod_def.${grdID}" - iloop=$((iloop + 1)) - fi + if [[ -f "${COMIN_WAVE_PREP}/${WAV_MOD_TAG}.mod_def.${grdID}.bin" ]]; then + echo " Mod def file for ${grdID} found in ${COMIN_WAVE_PREP}. copying ...." + cpreq -f "${COMIN_WAVE_PREP}/${WAV_MOD_TAG}.mod_def.${grdID}.bin" "mod_def.${grdID}" + iloop=$((iloop + 1)) + fi done for grdID in ${waveuoutpGRD}; do - if [[ -f "mod_def.${grdID}" ]]; then - echo "File mod_def.${grdID} found. Syncing to all nodes ..." - else - export err=2 - err_exit "NO MOD_DEF FILE mod_def.${grdID}" - fi + if [[ -f "mod_def.${grdID}" ]]; then + echo "File mod_def.${grdID} found. Syncing to all nodes ..." + else + export err=2 + err_exit "NO MOD_DEF FILE mod_def.${grdID}" + fi done # 1.b Output locations file rm -f buoy.loc if [[ -f "${PARMgfs}/wave/wave_${NET}.buoys" ]]; then - cpreq -f "${PARMgfs}/wave/wave_${NET}.buoys" buoy.loc.temp - if [[ "${DOBNDPNT_WAV}" == "YES" ]]; then - #only do boundary points - sed -n '/^\$.*/!p' buoy.loc.temp | grep IBP > buoy.loc || { - echo "WARNING: No boundary points found in buoy file ${PARMgfs}/wave/wave_${NET}.buoys" - echo " Ending job without doing anything." - exit 0 - } - else - #exclude boundary points - sed -n '/^\$.*/!p' buoy.loc.temp | grep -v IBP > buoy.loc - fi + cpreq -f "${PARMgfs}/wave/wave_${NET}.buoys" buoy.loc.temp + if [[ "${DOBNDPNT_WAV}" == "YES" ]]; then + #only do boundary points + # shellcheck disable=SC2312 + sed -n '/^\$.*/!p' buoy.loc.temp | grep IBP > buoy.loc || { + echo "WARNING: No boundary points found in buoy file ${PARMgfs}/wave/wave_${NET}.buoys" + echo " Ending job without doing anything." + exit 0 + } + else + #exclude boundary points + # shellcheck disable=SC2312 + sed -n '/^\$.*/!p' buoy.loc.temp | grep -v IBP > buoy.loc + fi fi if [[ -s buoy.loc ]]; then - echo " buoy.loc and buoy.ibp copied and processed (${PARMgfs}/wave/wave_${NET}.buoys)." + echo " buoy.loc and buoy.ibp copied and processed (${PARMgfs}/wave/wave_${NET}.buoys)." else - export err=3 - err_exit 'NO BUOY LOCATION FILE' + export err=3 + err_exit 'NO BUOY LOCATION FILE' fi # 1.c Input template files if [[ -f "${PARMgfs}/wave/ww3_outp_spec.inp.tmpl" ]]; then - cpreq -f "${PARMgfs}/wave/ww3_outp_spec.inp.tmpl" ww3_outp_spec.inp.tmpl + cpreq -f "${PARMgfs}/wave/ww3_outp_spec.inp.tmpl" ww3_outp_spec.inp.tmpl fi if [[ -f ww3_outp_spec.inp.tmpl ]]; then - echo " ww3_outp_spec.inp.tmpl copied. Syncing to all grids ..." + echo " ww3_outp_spec.inp.tmpl copied. Syncing to all grids ..." else - export err=3 - err_exit "NO TEMPLATE FOR SPEC INPUT FILE" + export err=3 + err_exit "NO TEMPLATE FOR SPEC INPUT FILE" fi if [[ -f "${PARMgfs}/wave/ww3_outp_bull.inp.tmpl" ]]; then - cpreq "${PARMgfs}/wave/ww3_outp_bull.inp.tmpl" ww3_outp_bull.inp.tmpl + cpreq "${PARMgfs}/wave/ww3_outp_bull.inp.tmpl" ww3_outp_bull.inp.tmpl fi if [[ -f ww3_outp_bull.inp.tmpl ]]; then - echo " ww3_outp_bull.inp.tmpl copied. Syncing to all nodes ..." + echo " ww3_outp_bull.inp.tmpl copied. Syncing to all nodes ..." else - export err=4 - err_exit "NO TEMPLATE FOR BULLETIN INPUT FILE" + export err=4 + err_exit "NO TEMPLATE FOR BULLETIN INPUT FILE" fi # 1.d Linking the output files @@ -147,18 +135,18 @@ fi # Loop through forecast hours to link output file fhr=${FHMIN_WAV} while [[ ${fhr} -le ${FHMAX_WAV_PNT} ]]; do - ymdhms=$(date --utc +%Y%m%d.%H0000 -d "${PDY} ${cyc} + ${fhr} hours") - FH3=$(printf %03i ${fhr}) - pfile="${COMIN_WAVE_HISTORY}/${WAV_MOD_TAG}.points.f${FH3}.nc" - if [[ -f "${pfile}" ]]; then - ${NLN} "${pfile}" "./${ymdhms}.out_pnt.ww3.nc" - else - export err=7 - err_exit "NO RAW POINT OUTPUT FILE ${ymdhms}.out_pnt.ww3.nc" - fi - - FHINCP=$(( DTPNT_WAV / 3600 )) - fhr=$(( fhr + FHINCP )) # no gridded output, loop with out_pnt stride + ymdhms=$(date --utc +%Y%m%d.%H0000 -d "${PDY} ${cyc} + ${fhr} hours") + FH3=$(printf %03i "${fhr}") + pfile="${COMIN_WAVE_HISTORY}/${WAV_MOD_TAG}.points.f${FH3}.nc" + if [[ -f "${pfile}" ]]; then + ${NLN} "${pfile}" "./${ymdhms}.out_pnt.ww3.nc" + else + export err=7 + err_exit "NO RAW POINT OUTPUT FILE ${ymdhms}.out_pnt.ww3.nc" + fi + + FHINCP=$((DTPNT_WAV / 3600)) + fhr=$((fhr + FHINCP)) # no gridded output, loop with out_pnt stride done # 1.e Getting buoy information for points @@ -166,21 +154,21 @@ done ymdh=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${WAVHINDH} hours") tstart="${ymdh:0:8} ${ymdh:8:2}0000" truntime="${PDY} ${cyc}0000" -N=$(( (FHMAX_WAV_PNT - FHMIN_WAV) * 3600 / DTPNT_WAV + 1 )) +N=$(((FHMAX_WAV_PNT - FHMIN_WAV) * 3600 / DTPNT_WAV + 1)) if [[ "${DOSPC_WAV}" == "YES" || "${DOBLL_WAV}" == "YES" ]]; then - sed -e "s/TIME/${tstart}/g" \ - -e "s/DT/${DTPNT_WAV}/g" \ - -e "s/999/${N}/g" \ - -e "s/PREFIX/${RUN}/g" \ - -e "s/^.*POINT.*/\$ &/g" \ - -e "s/ITYPE/0/g" \ - -e "s/FORMAT/F/g" \ - ww3_outp_spec.inp.tmpl > ww3_outp.inp + sed -e "s/TIME/${tstart}/g" \ + -e "s/DT/${DTPNT_WAV}/g" \ + -e "s/999/${N}/g" \ + -e "s/PREFIX/${RUN}/g" \ + -e "s/^.*POINT.*/\$ &/g" \ + -e "s/ITYPE/0/g" \ + -e "s/FORMAT/F/g" \ + ww3_outp_spec.inp.tmpl > ww3_outp.inp fi rm -f buoy_tmp.loc buoy_log.ww3 ww3_oup.inp -${NLN} ./mod_def.${waveuoutpGRD} ./mod_def.ww3 +${NLN} "./mod_def.${waveuoutpGRD}" ./mod_def.ww3 export pgm="${NET,,}_ww3_outp.x" source prep_step @@ -188,28 +176,30 @@ source prep_step "${EXECgfs}/${pgm}" > buoy_lst.loc 2>&1 export err=$? if [[ ${err} -ne 0 && ! -f buoy_log.ww3 ]]; then - cat buoy_tmp.loc || true - export err=5 - err_exit "${WAV_MOD_TAG} post ${date} ${cycle} : buoy log file failed to be created." + cat buoy_tmp.loc || true + export err=5 + err_exit "${WAV_MOD_TAG} post ${date} ${cycle} : buoy log file failed to be created." fi # Create new buoy_log.ww3 +# shellcheck disable=SC2312 awk '{print $3}' buoy.loc | sed 's/'\''//g' > ibp_tags grep -F -f ibp_tags buoy_log.ww3 > buoy_log.tmp rm -f buoy_log.dat mv buoy_log.tmp buoy_log.dat -Nb=$(wc buoy_log.dat | awk '{ print $1 }') +Nb=$(wc -l < buoy_log.dat) if [[ -s buoy_log.dat ]]; then - echo 'Buoy log file created. Syncing to all nodes ...' + echo 'Buoy log file created. Syncing to all nodes ...' else - export err=6 - err_exit "NO BUOY LOG FILE CREATED" + export err=6 + err_exit "NO BUOY LOG FILE CREATED" fi # 1.f Data summary +# shellcheck disable=SC2312 cat << EOF Input files read and processed at : $(date) @@ -229,36 +219,39 @@ EOF echo ' Making command file for wave post points ' +# shellcheck disable=SC2312 grep -F -f ibp_tags buoy_log.dat | awk '{ print $2 }' > buoys +# shellcheck disable=SC2312 grep -F -f buoys buoy_log.ww3 | awk '{ print $1 }' > points +# shellcheck disable=SC2312 points=$(awk '{print $0 "\\n"}' points | tr -d '\n') rm -f buoys # Generate the ww3_outp.inp file from the template if [[ "${DOSPC_WAV}" == "YES" ]]; then - sed -e "s/TIME/${tstart}/g" \ - -e "s/DT/${DTPNT_WAV}/g" \ - -e "s/999/${N}/g" \ - -e "s/PREFIX/${RUN}/g" \ - -e "s|POINT|${points}|g" \ - -e "s/ITYPE/1/g" \ - -e "s/FORMAT/F/g" \ - ww3_outp_spec.inp.tmpl > ww3_outp.inp - - export pgm="${NET,,}_ww3_outp.x" - "${EXECgfs}/${pgm}" + sed -e "s/TIME/${tstart}/g" \ + -e "s/DT/${DTPNT_WAV}/g" \ + -e "s/999/${N}/g" \ + -e "s/PREFIX/${RUN}/g" \ + -e "s|POINT|${points}|g" \ + -e "s/ITYPE/1/g" \ + -e "s/FORMAT/F/g" \ + ww3_outp_spec.inp.tmpl > ww3_outp.inp + + export pgm="${NET,,}_ww3_outp.x" + "${EXECgfs}/${pgm}" fi if [[ "${DOBLL_WAV}" == "YES" ]]; then - sed -e "s/TIME/${tstart}/g" \ - -e "s/DT/${DTPNT_WAV}/g" \ - -e "s/999/${N}/g" \ - -e "s/PREFIX/${RUN}/g" \ - -e "s|POINT|${points}|g" \ - -e "s/REFT/${truntime}/g" \ - ww3_outp_bull.inp.tmpl > ww3_outp.inp - export pgm="${NET,,}_ww3_outp.x" - "${EXECgfs}/${pgm}" + sed -e "s/TIME/${tstart}/g" \ + -e "s/DT/${DTPNT_WAV}/g" \ + -e "s/999/${N}/g" \ + -e "s/PREFIX/${RUN}/g" \ + -e "s|POINT|${points}|g" \ + -e "s/REFT/${truntime}/g" \ + ww3_outp_bull.inp.tmpl > ww3_outp.inp + export pgm="${NET,,}_ww3_outp.x" + "${EXECgfs}/${pgm}" fi # --------------------------------------------------------------------------- # @@ -275,37 +268,37 @@ printf "\n Making command file for taring all point output files." # 3.b Execute the taring if [[ "${DOBNDPNT_WAV}" == "YES" ]]; then - if [[ "${DOSPC_WAV}" == "YES" ]]; then - echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} ibp ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_ibp_tar.out" >> cmdtarfile - fi - if [[ "${DOBLL_WAV}" == "YES" ]]; then - echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} ibpbull ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_ibpbull_tar.out" >> cmdtarfile - echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} ibpcbull ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_ibpcbull_tar.out" >> cmdtarfile - fi + if [[ "${DOSPC_WAV}" == "YES" ]]; then + echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} ibp ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_ibp_tar.out" >> cmdtarfile + fi + if [[ "${DOBLL_WAV}" == "YES" ]]; then + echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} ibpbull ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_ibpbull_tar.out" >> cmdtarfile + echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} ibpcbull ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_ibpcbull_tar.out" >> cmdtarfile + fi else - if [[ "${DOSPC_WAV}" == "YES" ]]; then - echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} spec ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_spec_tar.out" >> cmdtarfile - fi - if [[ "${DOBLL_WAV}" == "YES" ]]; then - echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} bull ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_bull_tar.out" >> cmdtarfile - echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} cbull ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_cbull_tar.out" >> cmdtarfile - fi + if [[ "${DOSPC_WAV}" == "YES" ]]; then + echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} spec ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_spec_tar.out" >> cmdtarfile + fi + if [[ "${DOBLL_WAV}" == "YES" ]]; then + echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} bull ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_bull_tar.out" >> cmdtarfile + echo "${USHgfs}/wave_tar.sh ${WAV_MOD_TAG} cbull ${Nb} 2>&1 | tee ${WAV_MOD_TAG}_cbull_tar.out" >> cmdtarfile + fi fi # Ensure there are enough processors for MPMD else use serial ncmds=$(wc -l < cmdtarfile) if [[ ${NTASKS} -lt ${ncmds} ]]; then - if [[ "${USE_CFP:-}" == "YES" ]]; then - echo "WARNING: Not enough processors for MPMD, '${NTASKS} < ${ncmd}', running in serial mode" - export USE_CFP="NO" - fi + if [[ "${USE_CFP:-}" == "YES" ]]; then + echo "WARNING: Not enough processors for MPMD, '${NTASKS} < ${ncmd}', running in serial mode" + export USE_CFP="NO" + fi fi "${USHgfs}/run_mpmd.sh" "${DATA}/cmdtarfile" && true export err=$? if [[ ${err} -ne 0 ]]; then - export pgm="run_mpmd.sh" - err_exit "run_mpmd failed while tarring point outputs." + export pgm="run_mpmd.sh" + err_exit "run_mpmd failed while tarring point outputs." fi # End of WW3 point postprocessor script ---------------------------------------- # diff --git a/scripts/exgfs_wave_prdgen_bulls.sh b/scripts/exgfs_wave_prdgen_bulls.sh index afe487fc4e0..e1f89b217da 100755 --- a/scripts/exgfs_wave_prdgen_bulls.sh +++ b/scripts/exgfs_wave_prdgen_bulls.sh @@ -22,125 +22,117 @@ # 0.a Basic modes of operation # PATH for working and home directories - export envir=${envir:-ops} - export cyc=${cyc:-00} - export cycle=${cycle:-t${cyc}z} - export pgmout=OUTPUT.$$ - export pgm="wave prdgen" +export envir=${envir:-ops} +export cyc=${cyc:-00} +export cycle=${cycle:-t${cyc}z} +export pgmout=OUTPUT.$$ +export pgm="wave prdgen" # 0.b Date and time stuff - export date=${PDY} - export YMDH=${PDY}${cyc} - cat << EOF - - ************************************** - *** MWW3 BULLETINS PRODUCTS SCRIPT *** - ************************************** - ${date} ${cycle} - - Starting at : $(date) - - -EOF +export date=${PDY} +export YMDH=${PDY}${cyc} # 1. Get necessary files - echo " Copying bulletins from ${COMIN_WAVE_STATION}" +echo " Copying bulletins from ${COMIN_WAVE_STATION}" # 1.a Link the input file and untar it - BullIn="${COMIN_WAVE_STATION}/${RUN}.${cycle}.cbull.tar" - if [[ -f "${BullIn}" ]]; then - cpreq "${BullIn}" "cbull.tar" - else - export err=1 - err_exit "${RUN} wave prdgen ${date} ${cycle} : bulletin tar file missing." - fi - - echo " Untarring bulletins ..." - tar -xf cbull.tar - OK=$? - - if [[ ${OK} -eq 0 ]]; then - echo " Unpacking successfull ..." - rm -f cbull.tar - else - export err=2 - err_exit "ERROR IN BULLETIN TAR FILE" - fi +BullIn="${COMIN_WAVE_STATION}/${RUN}.${cycle}.cbull.tar" +if [[ -f "${BullIn}" ]]; then + cpreq "${BullIn}" "cbull.tar" +else + export err=1 + err_exit "${RUN} wave prdgen ${date} ${cycle} : bulletin tar file missing." +fi + +echo " Untarring bulletins ..." +tar -xf cbull.tar +OK=$? + +if [[ ${OK} -eq 0 ]]; then + echo " Unpacking successfull ..." + rm -f cbull.tar +else + export err=2 + err_exit "ERROR IN BULLETIN TAR FILE" +fi # 1.b Output locations from bulletin files - Nb=$(ls -1 *.cbull | wc -l) - echo ' ' - echo " Number of bulletin files : ${Nb}" - echo ' --------------------------' - echo ' ' +# shellcheck disable=SC2312 +Nb=$(find . -type f -name "*.cbull" -printf '.' | wc -c) +echo ' ' +echo " Number of bulletin files : ${Nb}" +echo ' --------------------------' +echo ' ' # 1.c Get the datat cards - if [ -f "${PARMgfs}/wave/bull_awips_gfswave.${waveGRD}" ]; then - cpreq "${PARMgfs}/wave/bull_awips_gfswave.${waveGRD}" "awipsbull.data" - else - export err=3 - err_exit "Bulletin header data file missing." - fi +if [[ -f "${PARMgfs}/wave/bull_awips_gfswave.${waveGRD}" ]]; then + cpreq "${PARMgfs}/wave/bull_awips_gfswave.${waveGRD}" "awipsbull.data" +else + export err=3 + err_exit "Bulletin header data file missing." +fi # 2. AWIPS bulletins for output points - printf "\nAWIPS bulletins ...\n------------------\n Sourcing data file with header info ..." +printf "\nAWIPS bulletins ...\n------------------\n Sourcing data file with header info ..." # 2.b Set up environment variables - source awipsbull.data +source awipsbull.data # 2.c Generate list of bulletins to process - echo ' Generating buoy list ...' - bulls=$(sed -e 's/export b//g' -e 's/=/ /' awipsbull.data | grep -v "#" |awk '{print $1}') +echo ' Generating buoy list ...' +# shellcheck disable=SC2312 +bulls=$(sed -e 's/export b//g' -e 's/=/ /' awipsbull.data | grep -v "#" | awk '{print $1}') # 2.d Looping over buoys running formbul - echo ' Looping over buoys ... \n' - - for bull in ${bulls}; do - fname="${RUN}.${bull}.cbull" - oname="awipsbull.${bull}.${cycle}.${RUN}.wave" - headr=$(grep "b${bull}=" awipsbull.data | sed 's/=/ /g' | awk '{ print $3}') - echo "Processing ${bull} (${headr} ${oname}) ..." - - if [[ -z "${headr}" ]] || [[ ! -s "${fname}" ]]; then - export err=4 - err_exit "MISSING BULLETIN INFO" - fi +echo ' Looping over buoys ...' +echo + +for bull in ${bulls}; do + fname="${RUN}.${bull}.cbull" + oname="awipsbull.${bull}.${cycle}.${RUN}.wave" + # shellcheck disable=SC2312 + headr=$(grep "b${bull}=" awipsbull.data | sed 's/=/ /g' | awk '{ print $3}') + echo "Processing ${bull} (${headr} ${oname}) ..." + + if [[ -z "${headr}" ]] || [[ ! -s "${fname}" ]]; then + export err=4 + err_exit "MISSING BULLETIN INFO" + fi - formbul.pl -d "${headr}" -f "${fname}" -j "${job}" -m "${RUN}.wave" \ - -p "${COMOUT_WAVE_WMO}" -s "NO" -o "${oname}" > formbul.out 2>&1 - OK=$? + formbul.pl -d "${headr}" -f "${fname}" -j "${job}" -m "${RUN}.wave" \ + -p "${COMOUT_WAVE_WMO}" -s "NO" -o "${oname}" > formbul.out 2>&1 + OK=$? - if [[ ${OK} -ne 0 || ! -f "${oname}" ]]; then - cat formbul.out - export err=5 - export pgm="formbul" - err_exit "error in formbul.pl failed for bulletin ${bull}" - fi + if [[ ${OK} -ne 0 || ! -f "${oname}" ]]; then + cat formbul.out + export err=5 + export pgm="formbul" + err_exit "error in formbul.pl failed for bulletin ${bull}" + fi - cat "${oname}" >> "awipsbull.${cycle}.${RUN}.wave" + cat "${oname}" >> "awipsbull.${cycle}.${RUN}.wave" - done +done # 3. Send output files to the proper destination cpfs "awipsbull.${cycle}.${RUN}.wave" "${COMOUT_WAVE_WMO}/awipsbull.${cycle}.${RUN}.wave" if [[ "${SENDDBN_NTC}" == YES ]]; then make_ntc_bull.pl "WMOBH" "NONE" "KWBC" "NONE" "${DATA}/awipsbull.${cycle}.${RUN}.wave" \ - "${COMOUT_WAVE_WMO}/awipsbull.${cycle}.${RUN}.wave" + "${COMOUT_WAVE_WMO}/awipsbull.${cycle}.${RUN}.wave" else if [[ "${envir}" == "para" || "${envir}" == "test" || "${envir}" == "dev" ]]; then echo "Making NTC bulletin for parallel environment, but do not alert." SENDDBN=NO make_ntc_bull.pl "WMOBH" "NONE" "KWBC" "NONE" \ - "${DATA}/awipsbull.${cycle}.${RUN}.wave" \ - "${COMOUT_WAVE_WMO}/awipsbull.${cycle}.${RUN}.wave" + "${DATA}/awipsbull.${cycle}.${RUN}.wave" \ + "${COMOUT_WAVE_WMO}/awipsbull.${cycle}.${RUN}.wave" fi fi # --------------------------------------------------------------------------- # # 4. Clean up - rm -f "${RUN}".*.cbull awipsbull.data +rm -f "${RUN}".*.cbull awipsbull.data # --------------------------------------------------------------------------- # # 5. Ending output - # End of MWW3 product generation script -------------------------------------- # diff --git a/scripts/exgfs_wave_prdgen_gridded.sh b/scripts/exgfs_wave_prdgen_gridded.sh index 0c0a7829b19..07ee67f5d49 100755 --- a/scripts/exgfs_wave_prdgen_gridded.sh +++ b/scripts/exgfs_wave_prdgen_gridded.sh @@ -55,9 +55,9 @@ printf "\nPreparing input files\n-----------------------" ASWELL=(SWELL1 SWELL2) # Indices of HS from partitions ASWPER=(SWPER1 SWPER2) # Indices of PERIODS from partitions ASWDIR=(SWDIR1 SWDIR2) # Indices of DIRECTIONS from partitions - # (should be same as ASWELL) +# (should be same as ASWELL) #declare -a arrpar=(WIND UGRD VGRD HTSGW PERPW DIRPW WVHGT WVPER WVDIR WDIR ${ASWELL[@]} ${ASWDIR[@]} ${ASWPER[@]}) -declare -a arrpar=(WIND WDIR UGRD VGRD HTSGW PERPW DIRPW WVHGT "${ASWELL[@]}" WVPER "${ASWPER[@]}" WVDIR "${ASWDIR[@]}" ) +declare -a arrpar=(WIND WDIR UGRD VGRD HTSGW PERPW DIRPW WVHGT "${ASWELL[@]}" WVPER "${ASWPER[@]}" WVDIR "${ASWDIR[@]}") nparam=$(echo "${arrpar[@]}" | wc -w) # 1.a Grib file (AWIPS and FAX charts) @@ -68,119 +68,119 @@ max_tries=1000 fhcnt="${fstart}" while [[ "${fhcnt}" -le "${FHMAX_WAV}" ]]; do - fhr=$(printf "%03d" "${fhcnt}") - for grdOut in ${grids}; do - process_grdID "${grdOut}" - - com_varname="COMIN_WAVE_GRID_${GRDREGION}_${GRDRES}" - com_dir=${!com_varname} - - GRIBIN="${com_dir}/${RUN}.${cycle}.${GRDREGION}.${GRDRES}.f${fhr}.grib2" - GRIBIN_chk="${GRIBIN}.idx" - if ! wait_for_file "${GRIBIN_chk}" "${sleep_interval}" "${max_tries}"; then - export err=1 - err_exit "${GRIBIN_chk} not found after waiting $((sleep_interval * ( max_tries - 1))) secs" - fi - GRIBOUT="${RUN}.${cycle}.${grdID}.f${fhr}.clipped.grib2" - - iparam=1 - while [[ ${iparam} -le ${nparam} ]]; do - nip=${arrpar[${iparam}-1]} - prepar=${nip::-1} # Part prefix (assumes 1 digit index) - paridx="${nip:0-1}" - npart=0 - case ${prepar} in - SWELL) npart=1 ;; - SWDIR) npart=1 ;; - SWPER) npart=1 ;; - *) npart=0 ;; - esac - echo "${nip} ${prepar} ${paridx} ${npart}" - rm -f temp.grib2 - if [[ ${npart} -eq 0 ]]; then - #shellcheck disable=SC2312 - ${WGRIB2} "${GRIBIN}" -s | grep ":${nip}" | "${WGRIB2}" -i "${GRIBIN}" -grib temp.grib2 > wgrib.out 2>&1 - #shellcheck disable=SC2312 - ${WGRIB2} temp.grib2 -append -grib "${GRIBOUT}" - else - #shellcheck disable=SC2312 - ${WGRIB2} "${GRIBIN}" -s | grep ":${prepar}" | grep "${paridx} in sequence" | \ - ${WGRIB2} -i "${GRIBIN}" -grib temp.grib2 > wgrib.out 2>&1 - ${WGRIB2} temp.grib2 -append -grib "${GRIBOUT}" - fi - iparam=$(( iparam + 1 )) - done #end wave param loop -#====================================================================== - GRIBIN="${RUN}.${cycle}.${grdID}.f${fhr}.clipped.grib2" - - ${NLN} "${GRIBIN}" "gribfile.${grdID}.f${fhr}" - -# 1.d Input template files - parmfile="${PARMgfs}/wave/grib2_${RUN}wave.${grdOut}.f${fhr}" - if [[ -f "${parmfile}" ]]; then - ${NLN} "${parmfile}" "awipsgrb.${grdID}.f${fhr}" - else - export err=3 - err_exit "NO template grib2_${RUN}wave.${grdID}.f${fhr}" - fi - -# 2. AWIPS product generation -# 2.a AWIPS GRIB file with headers - echo ' ' - echo 'AWIPS headers to GRIB file ...' - echo '------------------------------' - -# 2.a.1 Set up for tocgrib2 - echo " Do set up for tocgrib2." -# 2.a.2 Make GRIB index - echo " Make GRIB index for tocgrib2." - export pgm="${GRB2INDEX}" - ${GRB2INDEX} "gribfile.${grdID}.f${fhr}" "gribindex.${grdID}.f${fhr}" - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "ERROR IN grb2index MWW3 for grid ${grdID}" - fi - -# 2.a.3 Run AWIPS GRIB packing program tocgrib2 - - echo " Run tocgrib2" - export pgm="${TOCGRIB2}" - export pgmout=tocgrib2.out - source prep_step - - AWIPSGRB="awipsgrib" - export FORT11="gribfile.${grdID}.f${fhr}" - export FORT31="gribindex.${grdID}.f${fhr}" - export FORT51="${AWIPSGRB}.${grdID}.f${fhr}" - - ${TOCGRIB2} < "awipsgrb.${grdID}.f${fhr}" > "${pgmout}" 2>&1 - export err=$? - if [[ ${err} -ne 0 ]]; then - cat "${pgmout}" - err_exit "ERROR IN tocgrib2" + fhr=$(printf "%03d" "${fhcnt}") + for grdOut in ${grids}; do + process_grdID "${grdOut}" + + com_varname="COMIN_WAVE_GRID_${GRDREGION}_${GRDRES}" + com_dir=${!com_varname} + + GRIBIN="${com_dir}/${RUN}.${cycle}.${GRDREGION}.${GRDRES}.f${fhr}.grib2" + GRIBIN_chk="${GRIBIN}.idx" + if ! wait_for_file "${GRIBIN_chk}" "${sleep_interval}" "${max_tries}"; then + export err=1 + err_exit "${GRIBIN_chk} not found after waiting $((sleep_interval * (max_tries - 1))) secs" + fi + GRIBOUT="${RUN}.${cycle}.${grdID}.f${fhr}.clipped.grib2" + + iparam=1 + while [[ ${iparam} -le ${nparam} ]]; do + nip=${arrpar[${iparam} - 1]} + prepar=${nip::-1} # Part prefix (assumes 1 digit index) + paridx="${nip:0-1}" + npart=0 + case ${prepar} in + SWELL) npart=1 ;; + SWDIR) npart=1 ;; + SWPER) npart=1 ;; + *) npart=0 ;; + esac + echo "${nip} ${prepar} ${paridx} ${npart}" + rm -f temp.grib2 + if [[ ${npart} -eq 0 ]]; then + #shellcheck disable=SC2312 + ${WGRIB2} "${GRIBIN}" -s | grep ":${nip}" | "${WGRIB2}" -i "${GRIBIN}" -grib temp.grib2 > wgrib.out 2>&1 + #shellcheck disable=SC2312 + ${WGRIB2} temp.grib2 -append -grib "${GRIBOUT}" + else + #shellcheck disable=SC2312 + ${WGRIB2} "${GRIBIN}" -s | grep ":${prepar}" | grep "${paridx} in sequence" | + ${WGRIB2} -i "${GRIBIN}" -grib temp.grib2 > wgrib.out 2>&1 + ${WGRIB2} temp.grib2 -append -grib "${GRIBOUT}" + fi + iparam=$((iparam + 1)) + done #end wave param loop + #====================================================================== + GRIBIN="${RUN}.${cycle}.${grdID}.f${fhr}.clipped.grib2" + + ${NLN} "${GRIBIN}" "gribfile.${grdID}.f${fhr}" + + # 1.d Input template files + parmfile="${PARMgfs}/wave/grib2_${RUN}wave.${grdOut}.f${fhr}" + if [[ -f "${parmfile}" ]]; then + ${NLN} "${parmfile}" "awipsgrb.${grdID}.f${fhr}" + else + export err=3 + err_exit "NO template grib2_${RUN}wave.${grdID}.f${fhr}" + fi + + # 2. AWIPS product generation + # 2.a AWIPS GRIB file with headers + echo ' ' + echo 'AWIPS headers to GRIB file ...' + echo '------------------------------' + + # 2.a.1 Set up for tocgrib2 + echo " Do set up for tocgrib2." + # 2.a.2 Make GRIB index + echo " Make GRIB index for tocgrib2." + export pgm="${GRB2INDEX}" + ${GRB2INDEX} "gribfile.${grdID}.f${fhr}" "gribindex.${grdID}.f${fhr}" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "ERROR IN grb2index MWW3 for grid ${grdID}" + fi + + # 2.a.3 Run AWIPS GRIB packing program tocgrib2 + + echo " Run tocgrib2" + export pgm="${TOCGRIB2}" + export pgmout=tocgrib2.out + source prep_step + + AWIPSGRB="awipsgrib" + export FORT11="gribfile.${grdID}.f${fhr}" + export FORT31="gribindex.${grdID}.f${fhr}" + export FORT51="${AWIPSGRB}.${grdID}.f${fhr}" + + ${TOCGRIB2} < "awipsgrb.${grdID}.f${fhr}" > "${pgmout}" 2>&1 + export err=$? + if [[ ${err} -ne 0 ]]; then + cat "${pgmout}" + err_exit "ERROR IN tocgrib2" + else + echo '*** tocgrib2 ran succesfully *** ' + fi + + # 2.a.7 Get the AWIPS grib bulletin out ... + echo " Get awips GRIB bulletins out ..." + echo " Saving ${AWIPSGRB}.${grdOut}.f${fhr} as grib2.${cycle}.awipsww3_${grdID}.f${fhr}" + echo " in ${COMOUT_WAVE_WMO}" + cpfs "${AWIPSGRB}.${grdID}.f${fhr}" "${COMOUT_WAVE_WMO}/grib2.${cycle}.f${fhr}.awipsww3_${grdOut}" + + if [[ "${SENDDBN}" == "YES" ]]; then + echo " Sending ${AWIPSGRB}.${grdID}.f${fhr} to DBRUN." + "${DBNROOT}/bin/dbn_alert" GRIB_LOW "${RUN}" "${job}" "${COMOUT_WAVE_WMO}/grib2.${cycle}.f${fhr}.awipsww3_${grdOut}" + fi + rm -f "${AWIPSGRB}.${grdID}.f${fhr}" "${pgmout}" + done # For grids + + if [[ ${fhcnt} -ge ${FHMAX_HF_WAV} ]]; then + inc="${FHOUT_WAV}" else - echo '*** tocgrib2 ran succesfully *** ' - fi - -# 2.a.7 Get the AWIPS grib bulletin out ... - echo " Get awips GRIB bulletins out ..." - echo " Saving ${AWIPSGRB}.${grdOut}.f${fhr} as grib2.${cycle}.awipsww3_${grdID}.f${fhr}" - echo " in ${COMOUT_WAVE_WMO}" - cpfs "${AWIPSGRB}.${grdID}.f${fhr}" "${COMOUT_WAVE_WMO}/grib2.${cycle}.f${fhr}.awipsww3_${grdOut}" - - if [[ "${SENDDBN}" == "YES" ]]; then - echo " Sending ${AWIPSGRB}.${grdID}.f${fhr} to DBRUN." - "${DBNROOT}/bin/dbn_alert" GRIB_LOW "${RUN}" "${job}" "${COMOUT_WAVE_WMO}/grib2.${cycle}.f${fhr}.awipsww3_${grdOut}" + inc="${FHOUT_HF_WAV}" fi - rm -f "${AWIPSGRB}.${grdID}.f${fhr}" "${pgmout}" - done # For grids - - if [[ ${fhcnt} -ge ${FHMAX_HF_WAV} ]]; then - inc="${FHOUT_WAV}" - else - inc="${FHOUT_HF_WAV}" - fi - ((fhcnt = fhcnt+inc)) + ((fhcnt = fhcnt + inc)) done #For fcst time # --------------------------------------------------------------------------- # diff --git a/scripts/exgfs_wave_prep.sh b/scripts/exgfs_wave_prep.sh index 3508555bff7..bb139147b35 100755 --- a/scripts/exgfs_wave_prep.sh +++ b/scripts/exgfs_wave_prep.sh @@ -34,80 +34,70 @@ # 0.a Basic modes of operation - # Set wave model ID tag to include member number - # if ensemble; waveMEMB var empty in deterministic - export WAV_MOD_TAG="${RUN}wave${waveMEMB}" - - mkdir outtmp - -cat << EOF -HAS BEGUN on $(hostname) -Starting MWW3 PREPROCESSOR SCRIPT for ${WAV_MOD_TAG} - - ******************************** - *** WW3 PREPROCESSOR SCRIPT *** - ******************************** - PREP for wave component of NCEP coupled system - Wave component identifier : ${WAV_MOD_TAG} - - -EOF - - # 0.b Date and time stuff - - # Beginning time for outpupt may differ from SDATE if DOIAU=YES - # Roll back ${IAU_FHROT} hours of DOIAU=YES - IAU_FHROT=3 - if [[ "${DOIAU}" == "YES" ]] - then - WAVHINDH=$(( WAVHINDH + IAU_FHROT )) - fi - # Set time stamps for model start and output - # For special case when IAU is on but this is an initial half cycle - if [[ ${IAU_OFFSET} -eq 0 ]]; then - ymdh_beg=${PDY}${cyc} - else +# Set wave model ID tag to include member number +# if ensemble; waveMEMB var empty in deterministic +export WAV_MOD_TAG="${RUN}wave${waveMEMB}" + +mkdir outtmp + +# 0.b Date and time stuff + +# Beginning time for outpupt may differ from SDATE if DOIAU=YES +# Roll back ${IAU_FHROT} hours of DOIAU=YES +IAU_FHROT=3 +if [[ "${DOIAU}" == "YES" ]]; then + WAVHINDH=$((WAVHINDH + IAU_FHROT)) +fi +# Set time stamps for model start and output +# For special case when IAU is on but this is an initial half cycle +if [[ ${IAU_OFFSET} -eq 0 ]]; then + # shellcheck disable=SC2153 + ymdh_beg="${PDY}${cyc}" +else ymdh_beg=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${WAVHINDH} hours") - fi - time_beg=$(date --utc -d "${ymdh_beg:0:8} ${ymdh_beg:8:2}" +"%Y%m%d %H0000") - ymdh_end=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${FHMAX_WAV} hours") - time_end=$(date --utc -d "${ymdh_end:0:8} ${ymdh_end:8:2}" +"%Y%m%d %H0000") - ymdh_beg_out=${PDY}${cyc} - time_beg_out="$(echo ${ymdh_beg_out} | cut -c1-8) $(echo ${ymdh_beg_out} | cut -c9-10)0000" - - # Restart file times (already has IAU_FHROT in WAVHINDH) - RSTOFFSET=$(( ${WAVHCYC} - ${WAVHINDH} )) - # Update restart time is added offset relative to model start - RSTOFFSET=$(( ${RSTOFFSET} + ${RSTIOFF_WAV} )) - ymdh_rst_ini=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${RSTOFFSET} hours") - RST2OFFSET=$(( DT_2_RST_WAV / 3600 )) - # DT2 relative to first-first-cycle restart file - ymdh_rst2_ini=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${RST2OFFSET} hours") - # First restart file for cycling - time_rst_ini="$(echo ${ymdh_rst_ini} | cut -c1-8) $(echo ${ymdh_rst_ini} | cut -c9-10)0000" - if [[ ${DT_1_RST_WAV} -eq 1 ]]; then +fi +ymdh_end=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${FHMAX_WAV} hours") +time_beg=$(date --utc -d "${ymdh_beg:0:8} ${ymdh_beg:8:2}" +"%Y%m%d %H0000") +time_end=$(date --utc -d "${ymdh_end:0:8} ${ymdh_end:8:2}" +"%Y%m%d %H0000") +export ymdh_beg_out="${PDY}${cyc}" +export time_beg_out="${PDY} ${cyc}0000" + +# Restart file times (already has IAU_FHROT in WAVHINDH) +RSTOFFSET=$((WAVHCYC - WAVHINDH)) +# Update restart time is added offset relative to model start +RSTOFFSET=$((RSTOFFSET + RSTIOFF_WAV)) +ymdh_rst_ini=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${RSTOFFSET} hours") +RST2OFFSET=$((DT_2_RST_WAV / 3600)) +# DT2 relative to first-first-cycle restart file +ymdh_rst2_ini=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${RST2OFFSET} hours") +# First restart file for cycling +time_rst_ini="${ymdh_rst_ini:0:8} ${ymdh_rst_ini:8:2}0000" +# shellcheck disable=SC2153 +if [[ ${DT_1_RST_WAV} -eq 1 ]]; then time_rst1_end=${time_rst_ini} - else - RST1OFFSET=$(( DT_1_RST_WAV / 3600 )) +else + RST1OFFSET=$((DT_1_RST_WAV / 3600)) ymdh_rst1_end=$(date --utc +%Y%m%d%H -d "${ymdh_rst_ini} + ${RST1OFFSET} hours") - time_rst1_end="$(echo ${ymdh_rst1_end} | cut -c1-8) $(echo ${ymdh_rst1_end} | cut -c9-10)0000" - fi - # Second restart file for checkpointing - if [[ "${RSTTYPE_WAV}" == "T" ]]; then - time_rst2_ini="$(echo ${ymdh_rst2_ini} | cut -c1-8) $(echo ${ymdh_rst2_ini} | cut -c9-10)0000" + time_rst1_end="${ymdh_rst1_end:0:8} ${ymdh_rst1_end:8:2}0000" +fi +export time_rst1_end +# Second restart file for checkpointing +if [[ "${RSTTYPE_WAV}" == "T" ]]; then + time_rst2_ini="${ymdh_rst2_ini:0:8} ${ymdh_rst2_ini:8:2}0000" time_rst2_end=${time_end} - # Condition for gdas run or any other run when checkpoint stamp is > ymdh_end + # Condition for gdas run or any other run when checkpoint stamp is > ymdh_end if [[ ${ymdh_rst2_ini} -ge ${ymdh_end} ]]; then - ymdh_rst2_ini=$(date --utc +%Y%m%d%H -d "${ymdh_end} + 3 hours") - time_rst2_ini="$(echo ${ymdh_rst2_ini} | cut -c1-8) $(echo ${ymdh_rst2_ini} | cut -c9-10)0000" - time_rst2_end=${time_rst2_ini} + ymdh_rst2_ini=$(date --utc +%Y%m%d%H -d "${ymdh_end} + 3 hours") + time_rst2_ini="${ymdh_rst2_ini:0:8} ${ymdh_rst2_ini:8:2}0000" + time_rst2_end=${time_rst2_ini} fi - else +else time_rst2_ini="$" time_rst2_end= DT_2_RST_WAV= - fi - cat << EOF +fi +export time_rst2_end +cat << EOF Times in wave model format : ---------------------------- @@ -117,317 +107,250 @@ Times in wave model format : EOF - # Script will run only if pre-defined NTASKS - # The actual work is distributed over these tasks. - if [[ -z ${NTASKS} ]] - then +# Script will run only if pre-defined NTASKS +# The actual work is distributed over these tasks. +if [[ -z ${NTASKS} ]]; then export err=1 err_exit "Requires NTASKS to be set" - fi - - # --------------------------------------------------------------------------- # - # 1. Get files that are used by most child scripts +fi - printf "Preparing input files :\n-----------------------\n" - - # 1.a Model definition files - - rm -f cmdfile - touch cmdfile - - grdINP='' - if [[ "${WW3ATMINP}" == 'YES' ]]; then - grdINP="${grdINP} ${WAVEWND_FID}" - fi - if [[ "${WW3ICEINP}" == 'YES' ]]; then - grdINP="${grdINP} ${WAVEICE_FID}" - fi - if [[ "${WW3CURINP}" == 'YES' ]]; then - grdINP="${grdINP} ${WAVECUR_FID}" - fi - - ifile=1 - - for grdID in ${grdINP} ${waveGRD} - do - if [[ -f "${COMIN_WAVE_PREP}/${RUN}.wave.mod_def.${grdID}" ]] - then - echo " Mod def file for ${grdID} found in ${COMIN_WAVE_PREP}. copying ...." - cpreq ${COMIN_WAVE_PREP}/${RUN}.wave.mod_def.${grdID} mod_def.${grdID} - - else - export err=2 - err_exit "NO MODEL DEFINITION FILE" - fi - done - - # 1.b Netcdf Preprocessor template files - if [[ "${WW3ATMINP}" == 'YES' ]]; then - itype="${itype:-} wind" - fi - if [[ "${WW3ICEINP}" == 'YES' ]]; then - itype="${itype:-} ice" - fi - if [[ "${WW3CURINP}" == 'YES' ]]; then - itype="${itype:-} cur" - fi - - for type in ${itype} - do - - case ${type} in - wind ) - grdID=${WAVEWND_FID} - ;; - ice ) - grdID=${WAVEICE_FID} - ;; - cur ) - grdID=${WAVECUR_FID} - ;; - * ) - export err=3 - err_exit 'Input type not yet implemented' - ;; - esac - - if [[ -f ${PARMgfs}/wave/ww3_prnc.${type}.${grdID}.inp.tmpl ]] - then - cpreq ${PARMgfs}/wave/ww3_prnc.${type}.${grdID}.inp.tmpl . - fi - - if [[ -f ww3_prnc.${type}.${grdID}.inp.tmpl ]] - then - printf"\n ww3_prnc.${type}.${grdID}.inp.tmpl copied (${PARMgfs}/wave).\n" - else - export err=4 - err_exit "NO TEMPLATE FILE ww3_prnc.${type}.${grdID}.inp.tmpl" - fi - done +# --------------------------------------------------------------------------- # +# 1. Get files that are used by most child scripts + +printf "Preparing input files :\n-----------------------\n" + +# 1.a Model definition files + +rm -f cmdfile +touch cmdfile + +grdINP='' +if [[ "${WW3ATMINP}" == 'YES' ]]; then + grdINP="${grdINP} ${WAVEWND_FID}" +fi +if [[ "${WW3ICEINP}" == 'YES' ]]; then + grdINP="${grdINP} ${WAVEICE_FID}" +fi +if [[ "${WW3CURINP}" == 'YES' ]]; then + grdINP="${grdINP} ${WAVECUR_FID}" +fi + +for grdID in ${grdINP} ${waveGRD}; do + cpreq "${COMIN_WAVE_PREP}/${RUN}.wave.mod_def.${grdID}" "mod_def.${grdID}" +done + +# 1.b Netcdf Preprocessor template files +declare -a itype +if [[ "${WW3ATMINP}" == 'YES' ]]; then + itype+=(wind) +fi +if [[ "${WW3ICEINP}" == 'YES' ]]; then + itype+=("ice") +fi +if [[ "${WW3CURINP}" == 'YES' ]]; then + itype+=("cur") +fi + +for type in "${itype[@]}"; do + case ${type} in + wind) + grdID=${WAVEWND_FID} + ;; + ice) + grdID=${WAVEICE_FID} + ;; + cur) + grdID=${WAVECUR_FID} + ;; + *) + export err=3 + err_exit 'Input type not yet implemented' + ;; + esac + cpreq "${PARMgfs}/wave/ww3_prnc.${type}.${grdID}.inp.tmpl" ./ +done # --------------------------------------------------------------------------- # # ICEC processing - if [[ "${WW3ICEINP}" == 'YES' ]]; then +if [[ "${WW3ICEINP}" == 'YES' ]]; then -# --------------------------------------------------------------------------- # -# 2. Ice pre - processing + # --------------------------------------------------------------------------- # + # 2. Ice pre - processing -# 2.a Check if ice input is perturbed (number of inputs equal to number of wave -# ensemble members - if [[ "${RUNMEM}" == "-1" || "${WW3ICEIENS}" == "T" || "${waveMEMB}" == "00" ]] - then + # 2.a Check if ice input is perturbed (number of inputs equal to number of wave + # ensemble members + if [[ "${RUNMEM}" == "-1" || "${WW3ICEIENS}" == "T" || "${waveMEMB}" == "00" ]]; then - ${USHgfs}/wave_prnc_ice.sh > wave_prnc_ice.out && true - ERR=$? + "${USHgfs}/wave_prnc_ice.sh" > wave_prnc_ice.out && true + ERR=$? - if [[ -d ice || ${ERR} -ne 0 ]] - then - sed "s/^/wave_prnc_ice.out : /g" wave_prnc_ice.out - echo ' ' - if [[ ${ERR} -ne 0 ]]; then - export err=${ERR} + if [[ -d ice || ${ERR} -ne 0 ]]; then + sed "s/^/wave_prnc_ice.out : /g" wave_prnc_ice.out + echo ' ' + if [[ ${ERR} -ne 0 ]]; then + export err=${ERR} + else + export err=5 + fi + err_exit "ice field not generated" else - export err=5 + mv -f wave_prnc_ice.out "${DATA}/outtmp" + printf "\n Ice field unpacking successful.\n" fi - err_exit "ice field not generated" - else - mv -f wave_prnc_ice.out ${DATA}/outtmp - printf "\n Ice field unpacking successful.\n" - fi else - echo ' ' - echo "WARNING: Ice input is not perturbed, single ice file generated, skipping ${WAV_MOD_TAG}" - echo ' ' + echo ' ' + echo "WARNING: Ice input is not perturbed, single ice file generated, skipping ${WAV_MOD_TAG}" + echo ' ' fi - else - echo ' ' - echo "WARNING: No input ice file generated, this run did not request pre-processed ice data" - echo ' ' - fi +else + echo ' ' + echo "WARNING: No input ice file generated, this run did not request pre-processed ice data" + echo ' ' +fi # --------------------------------------------------------------------------- # # WIND processing - if [[ "${WW3ATMINP}" == 'YES' ]]; then +if [[ "${WW3ATMINP}" == 'YES' ]]; then export err=6 err_exit "Not set-up to preprocess wind" - fi +fi #------------------------------------------------------------------- # 3. Process current fields - if [[ "${WW3CURINP}" == 'YES' ]]; then - -# Get into single file - if [[ "${RUNMEM}" == "-1" || "${WW3CURIENS}" == "T" || "${waveMEMB}" == "00" ]] - then - - printf "\n Concatenate binary current fields ...\n" - -# Prepare files for cfp process - rm -f cmdfile - touch cmdfile - chmod 744 cmdfile - - BDATE=$(date --utc +%Y%m%d%H -d "${RPDY}00 - 24 hours") - bPDY=${BDATE:0:8} - - ymdh_rtofs=${RPDY}00 # RTOFS runs once daily use ${PDY}00 - if [[ ${ymdh_beg} -lt ${ymdh_rtofs} ]]; then - #If the start time is before the first hour of RTOFS, use the previous cycle - export RPDY=${bPDY} - fi - #Set the first time for RTOFS files to be the beginning time of simulation - ymdh_rtofs=${ymdh_beg} - - if [[ "${FHMAX_WAV_CUR}" -le 72 ]]; then - rtofsfile1="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f024_prog.nc" - rtofsfile2="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f048_prog.nc" - rtofsfile3="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f072_prog.nc" - if [[ ! -f ${rtofsfile1} ]] || [[ ! -f ${rtofsfile2} ]] || [[ ! -f ${rtofsfile3} ]]; then - #Needed current files are not available, so use RTOFS from previous day - export RPDY=${bPDY} - fi - else - rtofsfile1="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f096_prog.nc" - rtofsfile2="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f120_prog.nc" - rtofsfile3="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f144_prog.nc" - rtofsfile4="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f168_prog.nc" - rtofsfile5="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f192_prog.nc" - if [[ ! -f ${rtofsfile1} ]] || [[ ! -f ${rtofsfile2} ]] || [[ ! -f ${rtofsfile3} ]] || - [[ ! -f ${rtofsfile4} ]] || [[ ! -f ${rtofsfile5} ]]; then - #Needed current files are not available, so use RTOFS from previous day +if [[ "${WW3CURINP}" == 'YES' ]]; then + + # Get into single file + if [[ "${RUNMEM}" == "-1" || "${WW3CURIENS}" == "T" || "${waveMEMB}" == "00" ]]; then + + printf "\n Concatenate binary current fields ...\n" + + # Prepare files for cfp process + rm -f cmdfile + touch cmdfile + chmod 744 cmdfile + + BDATE=$(date --utc +%Y%m%d%H -d "${RPDY}00 - 24 hours") + bPDY=${BDATE:0:8} + + ymdh_rtofs=${RPDY}00 # RTOFS runs once daily use ${PDY}00 + if [[ ${ymdh_beg} -lt ${ymdh_rtofs} ]]; then + #If the start time is before the first hour of RTOFS, use the previous cycle export RPDY=${bPDY} fi - fi - - ymdh_end_rtofs=$(date --utc +%Y%m%d%H -d "${RPDY}00 + ${FHMAX_WAV_CUR} hours") - if [[ ${ymdh_end} -lt ${ymdh_end_rtofs} ]]; then - ymdh_end_rtofs=${ymdh_end} - fi - - DATE_DT=${WAV_CUR_HF_DT} - FLGHF='T' - FLGFIRST='T' - fext='f' - - if [[ ${CFP_MP:-"NO"} == "YES" ]]; then - # Counter for MP CFP - nm=0 - fi - while [[ ${ymdh_rtofs} -le ${ymdh_end_rtofs} ]] - do - # Timing has to be made relative to the single 00z RTOFS cycle for RTOFS PDY (RPDY) - # Start at first fhr for - fhr_rtofs=$(${NHOUR} ${ymdh_rtofs} ${RPDY}00) - fh3_rtofs=$(printf "%03d" "${fhr_rtofs#0}") - - curfile1h=${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_${fext}${fh3_rtofs}_prog.nc - curfile3h=${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_${fext}${fh3_rtofs}_prog.nc - - if [[ -s ${curfile1h} && "${FLGHF}" == "T" ]] ; then - curfile=${curfile1h} - elif [[ -s ${curfile3h} ]]; then - curfile=${curfile3h} - FLGHF='F' + #Set the first time for RTOFS files to be the beginning time of simulation + ymdh_rtofs=${ymdh_beg} + + if [[ "${FHMAX_WAV_CUR}" -le 72 ]]; then + rtofsfile1="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f024_prog.nc" + rtofsfile2="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f048_prog.nc" + rtofsfile3="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f072_prog.nc" + if [[ ! -f ${rtofsfile1} ]] || [[ ! -f ${rtofsfile2} ]] || [[ ! -f ${rtofsfile3} ]]; then + #Needed current files are not available, so use RTOFS from previous day + export RPDY=${bPDY} + fi else - echo ' ' - if [[ "${FLGHF}" == "T" ]] ; then - curfile=${curfile1h} - else - curfile=${curfile3h} - fi - export err=11 - err_exit "NO CURRENT FILE (RTOFS): ${curfile}" + rtofsfile1="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f096_prog.nc" + rtofsfile2="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f120_prog.nc" + rtofsfile3="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f144_prog.nc" + rtofsfile4="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f168_prog.nc" + rtofsfile5="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_f192_prog.nc" + if [[ ! -f ${rtofsfile1} ]] || [[ ! -f ${rtofsfile2} ]] || [[ ! -f ${rtofsfile3} ]] || + [[ ! -f ${rtofsfile4} ]] || [[ ! -f ${rtofsfile5} ]]; then + #Needed current files are not available, so use RTOFS from previous day + export RPDY=${bPDY} + fi fi - if [[ ${CFP_MP:-"NO"} == "YES" ]]; then - echo "${nm} ${USHgfs}/wave_prnc_cur.sh ${ymdh_rtofs} ${curfile} ${fhr_rtofs} ${FLGFIRST} > cur_${ymdh_rtofs}.out 2>&1" >> cmdfile - nm=$(expr ${nm} + 1) - else - echo "${USHgfs}/wave_prnc_cur.sh ${ymdh_rtofs} ${curfile} ${fhr_rtofs} ${FLGFIRST} > cur_${ymdh_rtofs}.out 2>&1" >> cmdfile + ymdh_end_rtofs=$(date --utc +%Y%m%d%H -d "${RPDY}00 + ${FHMAX_WAV_CUR} hours") + if [[ ${ymdh_end} -lt ${ymdh_end_rtofs} ]]; then + ymdh_end_rtofs=${ymdh_end} fi - if [[ "${FLGFIRST}" == "T" ]] ; then - FLGFIRST='F' + DATE_DT=${WAV_CUR_HF_DT} + FLGHF='T' + FLGFIRST='T' + fext='f' + + while [[ ${ymdh_rtofs} -le ${ymdh_end_rtofs} ]]; do + # Timing has to be made relative to the single 00z RTOFS cycle for RTOFS PDY (RPDY) + # Start at first fhr for + fhr_rtofs=$(${NHOUR} "${ymdh_rtofs}" "${RPDY}00") + fh3_rtofs=$(printf "%03d" "${fhr_rtofs#0}") + + curfile1h="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_${fext}${fh3_rtofs}_prog.nc" + curfile3h="${COMINrtofs}/rtofs.${RPDY}/rtofs_glo_2ds_${fext}${fh3_rtofs}_prog.nc" + + if [[ -s ${curfile1h} && "${FLGHF}" == "T" ]]; then + curfile="${curfile1h}" + elif [[ -s ${curfile3h} ]]; then + curfile="${curfile3h}" + FLGHF='F' + else + echo ' ' + if [[ "${FLGHF}" == "T" ]]; then + curfile="${curfile1h}" + else + curfile="${curfile3h}" + fi + export err=11 + err_exit "NO CURRENT FILE (RTOFS): ${curfile}" + fi + + echo "${USHgfs}/wave_prnc_cur.sh ${ymdh_rtofs} ${curfile} ${fhr_rtofs} ${FLGFIRST} > cur_${ymdh_rtofs}.out 2>&1" >> cmdfile + + if [[ "${FLGFIRST}" == "T" ]]; then + FLGFIRST='F' + fi + + if [[ ${fhr_rtofs} -ge ${WAV_CUR_HF_FH} ]]; then + DATE_DT=${WAV_CUR_DT} + fi + ymdh_rtofs=$(date --utc +%Y%m%d%H -d "${ymdh_rtofs} + ${DATE_DT} hours") + done + + "${USHgfs}/run_mpmd.sh" "${DATA}/cmdfile" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + export pgm="run_mpmd.sh" + echo "run_mpmd failed while generating currents." + # TODO: Should this raise a fatal error whether or not rtofs files are found? fi - if [[ ${fhr_rtofs} -ge ${WAV_CUR_HF_FH} ]] ; then - DATE_DT=${WAV_CUR_DT} - fi - ymdh_rtofs=$(date --utc +%Y%m%d%H -d "${ymdh_rtofs} + ${DATE_DT} hours") - done - -# Set number of processes for mpmd - wavenproc=$(wc -l < cmdfile) - wavenproc=$(echo $((${wavenproc}<${NTASKS}?${wavenproc}:${NTASKS}))) - - printf "\n Executing the curr prnc cmdfile at : %s\n ------------------------------------\n" "$(date)" + files=$(find ./ -name "rtofs.*") - if [[ ${wavenproc} -gt 1 ]] - then - if [[ ${CFP_MP:-"NO"} == "YES" ]]; then - ${wavempexec} -n "${wavenproc}" "${wave_mpmd}" cmdfile && true - else - ${wavempexec} "${wavenproc}" "${wave_mpmd}" cmdfile && true + if [[ -z "${files}" ]]; then + export err=11 + err_exit "NO ${WAVECUR_FID}.* FILES FOUND" fi - export stat=$? - else - chmod 744 ./cmdfile - ./cmdfile - export stat=$? - fi - - if [[ ${stat} -ne 0 ]] - then - set +x - echo ' ' - echo '********************************************' - echo '*** CMDFILE FAILED IN CUR GENERATION ***' - echo '********************************************' - echo ' See Details Below ' - # TODO: What details should be expected? - echo ' ' - # TODO: Should this raise a fatal error whether or not rtofs files are found? - set_trace - fi - - files=$(ls rtofs.* 2> /dev/null) - if [[ -z "${files}" ]] - then - export err=11 - err_exit "NO ${WAVECUR_FID}.* FILES FOUND" - fi + rm -f "cur.${WAVECUR_FID}" - rm -f cur.${WAVECUR_FID} + for file in ${files}; do + echo "${file}" + cat "${file}" >> "cur.${WAVECUR_FID}" + done - for file in ${files} - do - echo ${file} - cat ${file} >> cur.${WAVECUR_FID} - done - - cpfs cur.${WAVECUR_FID} ${COMOUT_WAVE_PREP}/${RUN}.wave.${WAVECUR_FID}.${cycle}.cur + cpfs "cur.${WAVECUR_FID}" "${COMOUT_WAVE_PREP}/${RUN}.wave.${WAVECUR_FID}.${cycle}.cur" else - echo ' ' - echo " Current input is not perturbed, single cur file generated, skipping ${WAV_MOD_TAG}" - echo ' ' + echo + echo " Current input is not perturbed, single cur file generated, skipping ${WAV_MOD_TAG}" + echo fi - else +else - echo ' ' - echo ' Current inputs not generated, this run did not request pre-processed currents ' - echo ' ' + echo + echo ' Current inputs not generated, this run did not request pre-processed currents ' + echo - fi +fi # --------------------------------------------------------------------------- # # 4. Ending output - # End of MWW3 preprocessor script ------------------------------------------- # diff --git a/scripts/exglobal_atmos_analysis.sh b/scripts/exglobal_atmos_analysis.sh index a8b800a1ac5..604350dcf45 100755 --- a/scripts/exglobal_atmos_analysis.sh +++ b/scripts/exglobal_atmos_analysis.sh @@ -29,9 +29,10 @@ GDUMP=${GDUMP:-"gdas"} # Derived base variables # shellcheck disable=SC2153 GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") +export GDATE BDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - 3 hours") -bPDY=${BDATE:0:8} -bcyc=${BDATE:8:2} +export bPDY=${BDATE:0:8} +export bcyc=${BDATE:8:2} # Utilities export CHGRP_CMD=${CHGRP_CMD:-"chgrp ${group_name:-rstprod}"} @@ -201,17 +202,13 @@ USE_RADSTAT=${USE_RADSTAT:-"YES"} SELECT_OBS=${SELECT_OBS:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}obsinput} GENDIAG=${GENDIAG:-"YES"} DIAG_SUFFIX=${DIAG_SUFFIX:-""} -if [[ ${netcdf_diag} == ".true." ]] ; then - DIAG_SUFFIX="${DIAG_SUFFIX}.nc4" +if [[ "${netcdf_diag}" == ".true." ]]; then + DIAG_SUFFIX="${DIAG_SUFFIX}.nc4" fi DIAG_COMPRESS=${DIAG_COMPRESS:-"YES"} DIAG_TARBALL=${DIAG_TARBALL:-"YES"} USE_CFP=${USE_CFP:-"NO"} CFP_MP=${CFP_MP:-"NO"} -nm="" -if [[ ${CFP_MP} == "YES" ]]; then - nm=0 -fi DIAG_DIR=${DIAG_DIR:-${COMOUT_ATMOS_ANALYSIS}/gsidiags} # Set script / GSI control parameters @@ -234,67 +231,68 @@ export INCREMENTS_TO_ZERO=${INCREMENTS_TO_ZERO:-"'NONE'"} USE_CORRELATED_OBERRS=${USE_CORRELATED_OBERRS:-"YES"} # Get header information from Guess files -LONB=${LONB:-$(${NCLEN} ${ATMGES} grid_xt)} # get LONB -LATB=${LATB:-$(${NCLEN} ${ATMGES} grid_yt)} # get LATB -LEVS=${LEVS:-$(${NCLEN} ${ATMGES} pfull)} # get LEVS -JCAP=${JCAP:--9999} # there is no jcap in these files -if [[ ${JCAP} -eq -9999 && ${LATB} -ne -9999 ]]; then - JCAP=$((LATB-2)) +LONB=${LONB:-$(${NCLEN} "${ATMGES}" grid_xt)} # get LONB +LATB=${LATB:-$(${NCLEN} "${ATMGES}" grid_yt)} # get LATB +LEVS=${LEVS:-$(${NCLEN} "${ATMGES}" pfull)} # get LEVS +JCAP=${JCAP:--9999} # there is no jcap in these files +if [[ "${JCAP}" -eq -9999 && "${LATB}" -ne -9999 ]]; then + JCAP=$((LATB - 2)) fi -if [[ ${LONB} -eq -9999 || ${LATB} -eq -9999 || ${LEVS} -eq -9999 || ${JCAP} -eq -9999 ]]; then - exit 9 +if [[ "${LONB}" -eq -9999 || "${LATB}" -eq -9999 || "${LEVS}" -eq -9999 || "${JCAP}" -eq -9999 ]]; then + exit 9 fi # Get header information from Ensemble Guess files -if [[ ${DOHYBVAR} == "YES" ]]; then - SFCGES_ENSMEAN=${SFCGES_ENSMEAN:-${COMIN_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}ensmean.sfc.f006.nc} - export ATMGES_ENSMEAN=${ATMGES_ENSMEAN:-${COMIN_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}ensmean.atm.f006.nc} - LONB_ENKF=${LONB_ENKF:-$(${NCLEN} ${ATMGES_ENSMEAN} grid_xt)} # get LONB_ENKF - LATB_ENKF=${LATB_ENKF:-$(${NCLEN} ${ATMGES_ENSMEAN} grid_yt)} # get LATB_ENFK - LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} ${ATMGES_ENSMEAN} pfull)} # get LATB_ENFK - JCAP_ENKF=${JCAP_ENKF:--9999} # again, no jcap in the netcdf files - NLON_ENKF=${NLON_ENKF:-${LONB_ENKF}} - NLAT_ENKF=${NLAT_ENKF:-$((${LATB_ENKF}+2))} - if [[ ${JCAP_ENKF} -eq -9999 && ${LATB_ENKF} -ne -9999 ]]; then - JCAP_ENKF=$((LATB_ENKF-2)) - fi - if [[ ${LONB_ENKF} -eq -9999 || ${LATB_ENKF} -eq -9999 || ${LEVS_ENKF} -eq -9999 || ${JCAP_ENKF} -eq -9999 ]]; then - exit 9 - fi +if [[ "${DOHYBVAR}" == "YES" ]]; then + SFCGES_ENSMEAN=${SFCGES_ENSMEAN:-${COMIN_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}ensmean.sfc.f006.nc} + export ATMGES_ENSMEAN=${ATMGES_ENSMEAN:-${COMIN_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}ensmean.atm.f006.nc} + LONB_ENKF=${LONB_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" grid_xt)} # get LONB_ENKF + LATB_ENKF=${LATB_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" grid_yt)} # get LATB_ENFK + LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" pfull)} # get LATB_ENFK + JCAP_ENKF=${JCAP_ENKF:--9999} # again, no jcap in the netcdf files + NLON_ENKF=${NLON_ENKF:-${LONB_ENKF}} + NLAT_ENKF=${NLAT_ENKF:-$((LATB_ENKF + 2))} + if [[ "${JCAP_ENKF}" -eq -9999 && "${LATB_ENKF}" -ne -9999 ]]; then + JCAP_ENKF=$((LATB_ENKF - 2)) + fi + if [[ "${LONB_ENKF}" -eq -9999 || "${LATB_ENKF}" -eq -9999 || "${LEVS_ENKF}" -eq -9999 || "${JCAP_ENKF}" -eq -9999 ]]; then + exit 9 + fi else - LONB_ENKF=0 # just for if statement later + LONB_ENKF=0 # just for if statement later fi # Get dimension information based on CASE res=${CASE_HIST:1} -JCAP_CASE=$((res*2-2)) -LATB_CASE=$((res*2)) -LONB_CASE=$((res*4)) +JCAP_CASE=$((res * 2 - 2)) +LATB_CASE=$((res * 2)) +LONB_CASE=$((res * 4)) +export JCAP_CASE LATB_CASE LONB_CASE # Set analysis resolution information -if [[ ${DOHYBVAR} == "YES" ]]; then - JCAP_A=${JCAP_A:-${JCAP_ENKF:-${JCAP}}} - LONA=${LONA:-${LONB_ENKF:-${LONB}}} - LATA=${LATA:-${LATB_ENKF:-${LATB}}} +if [[ "${DOHYBVAR}" == "YES" ]]; then + JCAP_A=${JCAP_A:-${JCAP_ENKF:-${JCAP}}} + LONA=${LONA:-${LONB_ENKF:-${LONB}}} + LATA=${LATA:-${LATB_ENKF:-${LATB}}} else - JCAP_A=${JCAP_A:-${JCAP}} - LONA=${LONA:-${LONB}} - LATA=${LATA:-${LATB}} + JCAP_A=${JCAP_A:-${JCAP}} + LONA=${LONA:-${LONB}} + LATA=${LATA:-${LATB}} fi NLON_A=${NLON_A:-${LONA}} -NLAT_A=${NLAT_A:-$((${LATA}+2))} +NLAT_A=${NLAT_A:-$((LATA + 2))} -DELTIM=${DELTIM:-$((3600/(${JCAP_A}/20)))} +DELTIM=${DELTIM:-$((3600 / (JCAP_A / 20)))} # determine if writing or calculating increment -if [[ ${DO_CALC_INCREMENT} == "YES" ]]; then - write_fv3_increment=".false." +if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then + write_fv3_increment=".false." else - write_fv3_increment=".true." - WRITE_INCR_ZERO="incvars_to_zero= ${INCREMENTS_TO_ZERO}," - WRITE_ZERO_STRAT="incvars_zero_strat= ${INCVARS_ZERO_STRAT}," - WRITE_STRAT_EFOLD="incvars_efold= ${INCVARS_EFOLD}," + write_fv3_increment=".true." + WRITE_INCR_ZERO="incvars_to_zero= ${INCREMENTS_TO_ZERO}," + WRITE_ZERO_STRAT="incvars_zero_strat= ${INCVARS_ZERO_STRAT}," + WRITE_STRAT_EFOLD="incvars_efold= ${INCVARS_EFOLD}," fi # GSI Fix files @@ -336,204 +334,209 @@ NST=${NST:-""} #uGSI Namelist parameters lrun_subdirs=${lrun_subdirs:-".true."} -if [[ ${DOHYBVAR} == "YES" ]]; then - l_hyb_ens=.true. - export l4densvar=${l4densvar:-".false."} - export lwrite4danl=${lwrite4danl:-".false."} +if [[ "${DOHYBVAR}" == "YES" ]]; then + l_hyb_ens=.true. + export l4densvar=${l4densvar:-".false."} + export lwrite4danl=${lwrite4danl:-".false."} else - l_hyb_ens=.false. - export l4densvar=.false. - export lwrite4danl=.false. + l_hyb_ens=.false. + export l4densvar=.false. + export lwrite4danl=.false. fi # Set 4D-EnVar specific variables -if [[ ${DOHYBVAR} == "YES" && ${l4densvar} == ".true." && ${lwrite4danl} == ".true." ]]; then - ATMA03=${ATMA03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a003.nc} - ATMI03=${ATMI03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i003.nc} - ATMA04=${ATMA04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a004.nc} - ATMI04=${ATMI04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i004.nc} - ATMA05=${ATMA05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a005.nc} - ATMI05=${ATMI05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i005.nc} - ATMA07=${ATMA07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a007.nc} - ATMI07=${ATMI07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i007.nc} - ATMA08=${ATMA08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a008.nc} - ATMI08=${ATMI08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i008.nc} - ATMA09=${ATMA09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a009.nc} - ATMI09=${ATMI09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i009.nc} +if [[ "${DOHYBVAR}" == "YES" && "${l4densvar}" == ".true." && "${lwrite4danl}" == ".true." ]]; then + ATMA03=${ATMA03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a003.nc} + ATMI03=${ATMI03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i003.nc} + ATMA04=${ATMA04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a004.nc} + ATMI04=${ATMI04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i004.nc} + ATMA05=${ATMA05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a005.nc} + ATMI05=${ATMI05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i005.nc} + ATMA07=${ATMA07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a007.nc} + ATMI07=${ATMI07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i007.nc} + ATMA08=${ATMA08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a008.nc} + ATMI08=${ATMI08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i008.nc} + ATMA09=${ATMA09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a009.nc} + ATMI09=${ATMI09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i009.nc} fi ############################################################## # Fixed files -${NLN} ${BERROR} berror_stats -${NLN} ${SATANGL} satbias_angle -if [[ ${SATINFO} == "generate" ]]; then - ${USHgfs}/create_gsi_info.sh sat "${PDY}${cyc}" "${DATA}" +${NLN} "${BERROR}" berror_stats +${NLN} "${SATANGL}" satbias_angle +if [[ "${SATINFO}" == "generate" ]]; then + # shellcheck disable=SC2153 + "${USHgfs}/create_gsi_info.sh" sat "${PDY}${cyc}" "${DATA}" else - ${NLN} ${SATINFO} satinfo + ${NLN} "${SATINFO}" satinfo fi -${NLN} ${RADCLOUDINFO} cloudy_radiance_info.txt -${NLN} ${ATMSFILTER} atms_beamwidth.txt -${NLN} ${ANAVINFO} anavinfo -if [[ ${CONVINFO} == "generate" ]]; then - ${USHgfs}/create_gsi_info.sh conv "${PDY}${cyc}" "${DATA}" "${USE_2M_OBS}" +${NLN} "${RADCLOUDINFO}" cloudy_radiance_info.txt +${NLN} "${ATMSFILTER}" atms_beamwidth.txt +${NLN} "${ANAVINFO}" anavinfo +if [[ "${CONVINFO}" == "generate" ]]; then + "${USHgfs}/create_gsi_info.sh" conv "${PDY}${cyc}" "${DATA}" "${USE_2M_OBS}" else - ${NLN} "${CONVINFO}" convinfo + ${NLN} "${CONVINFO}" convinfo fi -${NLN} "${vqcdat}" vqctp001.dat -${NLN} "${INSITUINFO}" insituinfo -if [[ ${OZINFO} == "generate" ]]; then - ${USHgfs}/create_gsi_info.sh oz "${PDY}${cyc}" "${DATA}" +${NLN} "${vqcdat}" vqctp001.dat +${NLN} "${INSITUINFO}" insituinfo +if [[ "${OZINFO}" == "generate" ]]; then + "${USHgfs}/create_gsi_info.sh" oz "${PDY}${cyc}" "${DATA}" else - ${NLN} "${OZINFO}" ozinfo + ${NLN} "${OZINFO}" ozinfo fi -${NLN} "${PCPINFO}" pcpinfo -${NLN} "${AEROINFO}" aeroinfo -${NLN} "${SCANINFO}" scaninfo -${NLN} "${HYBENSINFO}" hybens_info -${NLN} "${OBERROR}" errtable -${NLN} "${BLACKLST}" blacklist +${NLN} "${PCPINFO}" pcpinfo +${NLN} "${AEROINFO}" aeroinfo +${NLN} "${SCANINFO}" scaninfo +${NLN} "${HYBENSINFO}" hybens_info +${NLN} "${OBERROR}" errtable +${NLN} "${BLACKLST}" blacklist -${NLN} "${FIXgfs}/gsi/AIRS_CLDDET.NL" AIRS_CLDDET.NL -${NLN} "${FIXgfs}/gsi/CRIS_CLDDET.NL" CRIS_CLDDET.NL -${NLN} "${FIXgfs}/gsi/IASI_CLDDET.NL" IASI_CLDDET.NL +${NLN} "${FIXgfs}/gsi/AIRS_CLDDET.NL" AIRS_CLDDET.NL +${NLN} "${FIXgfs}/gsi/CRIS_CLDDET.NL" CRIS_CLDDET.NL +${NLN} "${FIXgfs}/gsi/IASI_CLDDET.NL" IASI_CLDDET.NL #If using correlated error, link to the covariance files -if [[ ${USE_CORRELATED_OBERRS} == "YES" ]]; then - if grep -q "Rcov" ${ANAVINFO} ; then - # shellcheck disable=SC2312 - mapfile -t covfile_array < <(find "${FIXgfs}/gsi/" -name "Rcov*") - if (( ${#covfile_array[@]} > 0 )); then - for covfile in "${covfile_array[@]}"; do - covfile_base=$(basename "${covfile}") - ${NLN} "${covfile}" "${DATA}/${covfile_base}" - done - echo "using correlated obs error" - else - echo "FATAL ERROR: Satellite error covariance files (Rcov) are missing." - echo "Check for the required Rcov files in " ${ANAVINFO} - exit 1 - fi - else - echo "FATAL ERROR: Satellite error covariance info missing in " ${ANAVINFO} - exit 1 - fi - -# Correlated error utlizes mkl lapack. Found it necesary to fix the -# number of mkl threads to ensure reproducible results independent -# of the job configuration. - export MKL_NUM_THREADS=1 +if [[ "${USE_CORRELATED_OBERRS}" == "YES" ]]; then + if grep -q "Rcov" "${ANAVINFO}"; then + # shellcheck disable=SC2312 + mapfile -t covfile_array < <(find "${FIXgfs}/gsi/" -name "Rcov*") + if ((${#covfile_array[@]} > 0)); then + for covfile in "${covfile_array[@]}"; do + covfile_base=$(basename "${covfile}") + # shellcheck disable=SC2153 + ${NLN} "${covfile}" "${DATA}/${covfile_base}" + done + echo "using correlated obs error" + else + export err=1 + err_exit "FATAL ERROR: Satellite error covariance files (Rcov) are missing. Check for the required Rcov files in ${ANAVINFO}" + fi + else + export err=1 + err_exit "FATAL ERROR: Satellite error covariance info missing in ${ANAVINFO}" + fi + + # Correlated error utlizes mkl lapack. Found it necesary to fix the + # number of mkl threads to ensure reproducible results independent + # of the job configuration. + export MKL_NUM_THREADS=1 else - echo "not using correlated obs error" + echo "not using correlated obs error" fi ############################################################## # CRTM Spectral and Transmittance coefficients mkdir -p crtm_coeffs +# shellcheck disable=SC2312 for file in $(awk '{if($1!~"!"){print $1}}' satinfo | sort | uniq); do - instr=$(echo ${file} | cut -c1-4) - if [[ ${instr} == "hirs" ]]; then - ${NLN} "${HIRS_FIX}/${file}.SpcCoeff.bin" "./crtm_coeffs/${file}.SpcCoeff.bin" - else - ${NLN} "${CRTM_FIX}/${file}.SpcCoeff.bin" "./crtm_coeffs/${file}.SpcCoeff.bin" - fi - ${NLN} "${CRTM_FIX}/${file}.TauCoeff.bin" "./crtm_coeffs/${file}.TauCoeff.bin" + if [[ ${file:0:4} == "hirs" ]]; then + ${NLN} "${HIRS_FIX}/${file}.SpcCoeff.bin" "./crtm_coeffs/${file}.SpcCoeff.bin" + else + ${NLN} "${CRTM_FIX}/${file}.SpcCoeff.bin" "./crtm_coeffs/${file}.SpcCoeff.bin" + fi + ${NLN} "${CRTM_FIX}/${file}.TauCoeff.bin" "./crtm_coeffs/${file}.TauCoeff.bin" done ${NLN} "${CRTM_FIX}/amsua_metop-a_v2.SpcCoeff.bin" "./crtm_coeffs/amsua_metop-a_v2.SpcCoeff.bin" -${NLN} "${CRTM_FIX}/Nalli.IRwater.EmisCoeff.bin" "./crtm_coeffs/Nalli.IRwater.EmisCoeff.bin" -${NLN} "${CRTM_FIX}/NPOESS.IRice.EmisCoeff.bin" "./crtm_coeffs/NPOESS.IRice.EmisCoeff.bin" -${NLN} "${CRTM_FIX}/NPOESS.IRland.EmisCoeff.bin" "./crtm_coeffs/NPOESS.IRland.EmisCoeff.bin" -${NLN} "${CRTM_FIX}/NPOESS.IRsnow.EmisCoeff.bin" "./crtm_coeffs/NPOESS.IRsnow.EmisCoeff.bin" -${NLN} "${CRTM_FIX}/NPOESS.VISice.EmisCoeff.bin" "./crtm_coeffs/NPOESS.VISice.EmisCoeff.bin" -${NLN} "${CRTM_FIX}/NPOESS.VISland.EmisCoeff.bin" "./crtm_coeffs/NPOESS.VISland.EmisCoeff.bin" -${NLN} "${CRTM_FIX}/NPOESS.VISsnow.EmisCoeff.bin" "./crtm_coeffs/NPOESS.VISsnow.EmisCoeff.bin" +${NLN} "${CRTM_FIX}/Nalli.IRwater.EmisCoeff.bin" "./crtm_coeffs/Nalli.IRwater.EmisCoeff.bin" +${NLN} "${CRTM_FIX}/NPOESS.IRice.EmisCoeff.bin" "./crtm_coeffs/NPOESS.IRice.EmisCoeff.bin" +${NLN} "${CRTM_FIX}/NPOESS.IRland.EmisCoeff.bin" "./crtm_coeffs/NPOESS.IRland.EmisCoeff.bin" +${NLN} "${CRTM_FIX}/NPOESS.IRsnow.EmisCoeff.bin" "./crtm_coeffs/NPOESS.IRsnow.EmisCoeff.bin" +${NLN} "${CRTM_FIX}/NPOESS.VISice.EmisCoeff.bin" "./crtm_coeffs/NPOESS.VISice.EmisCoeff.bin" +${NLN} "${CRTM_FIX}/NPOESS.VISland.EmisCoeff.bin" "./crtm_coeffs/NPOESS.VISland.EmisCoeff.bin" +${NLN} "${CRTM_FIX}/NPOESS.VISsnow.EmisCoeff.bin" "./crtm_coeffs/NPOESS.VISsnow.EmisCoeff.bin" ${NLN} "${CRTM_FIX}/NPOESS.VISwater.EmisCoeff.bin" "./crtm_coeffs/NPOESS.VISwater.EmisCoeff.bin" ${NLN} "${CRTM_FIX}/FASTEM6.MWwater.EmisCoeff.bin" "./crtm_coeffs/FASTEM6.MWwater.EmisCoeff.bin" -${NLN} "${CRTM_FIX}/AerosolCoeff.bin" "./crtm_coeffs/AerosolCoeff.bin" -if (( imp_physics == 8 )); then - echo "using CRTM Thompson cloud optical table" - ${NLN} "${CRTM_FIX}/CloudCoeff.Thompson08.-109z-1.bin" ./crtm_coeffs/CloudCoeff.bin -elif (( imp_physics == 11 )); then - echo "using CRTM GFDL cloud optical table" - ${NLN} "${CRTM_FIX}/CloudCoeff.GFDLFV3.-109z-1.bin" ./crtm_coeffs/CloudCoeff.bin -else - echo "FATAL ERROR: INVALID imp_physics = ${imp_physics}" - export err=1 - err_exit "No valid CRTM cloud optical table found for imp_physics = ${imp_physics}" -fi - +${NLN} "${CRTM_FIX}/AerosolCoeff.bin" "./crtm_coeffs/AerosolCoeff.bin" + +case "${imp_physics}" in + 8) + echo "Using CRTM Thompson cloud optical table" + ${NLN} "${CRTM_FIX}/CloudCoeff.Thompson08.-109z-1.bin" ./crtm_coeffs/CloudCoeff.bin + ;; + 11) + echo "Using CRTM GFDL cloud optical table" + ${NLN} "${CRTM_FIX}/CloudCoeff.GFDLFV3.-109z-1.bin" ./crtm_coeffs/CloudCoeff.bin + ;; + *) + echo "FATAL ERROR: INVALID imp_physics = ${imp_physics}" + export err=1 + err_exit "No valid CRTM cloud optical table found for imp_physics = ${imp_physics}" + ;; +esac ############################################################## # Observational data -${NLN} "${PREPQC}" prepbufr -${NLN} "${PREPQCPF}" prepbufr_profl -${NLN} "${SATWND}" satwndbufr -${NLN} "${OSCATBF}" oscatbufr -${NLN} "${RAPIDSCATBF}" rapidscatbufr -${NLN} "${GSNDBF}" gsndrbufr -${NLN} "${GSNDBF1}" gsnd1bufr -${NLN} "${B1MSU}" msubufr -${NLN} "${B1AMUA}" amsuabufr -${NLN} "${B1AMUB}" amsubbufr -${NLN} "${B1MHS}" mhsbufr -${NLN} "${B1HRS2}" hirs2bufr -${NLN} "${B1HRS3}" hirs3bufr -${NLN} "${B1HRS4}" hirs4bufr -${NLN} "${ESAMUA}" amsuabufrears -${NLN} "${ESAMUB}" amsubbufrears +${NLN} "${PREPQC}" prepbufr +${NLN} "${PREPQCPF}" prepbufr_profl +${NLN} "${SATWND}" satwndbufr +${NLN} "${OSCATBF}" oscatbufr +${NLN} "${RAPIDSCATBF}" rapidscatbufr +${NLN} "${GSNDBF}" gsndrbufr +${NLN} "${GSNDBF1}" gsnd1bufr +${NLN} "${B1MSU}" msubufr +${NLN} "${B1AMUA}" amsuabufr +${NLN} "${B1AMUB}" amsubbufr +${NLN} "${B1MHS}" mhsbufr +${NLN} "${B1HRS2}" hirs2bufr +${NLN} "${B1HRS3}" hirs3bufr +${NLN} "${B1HRS4}" hirs4bufr +${NLN} "${ESAMUA}" amsuabufrears +${NLN} "${ESAMUB}" amsubbufrears #${NLN} "${ESMHS}" mhsbufrears -${NLN} "${AMUADB}" amsuabufr_db -${NLN} "${AMUBDB}" amsubbufr_db +${NLN} "${AMUADB}" amsuabufr_db +${NLN} "${AMUBDB}" amsubbufr_db #${NLN} "${MHSDB}" mhsbufr_db -${NLN} "${SBUVBF}" sbuvbufr -${NLN} "${OMPSNPBF}" ompsnpbufr -${NLN} "${OMPSLPBF}" ompslpbufr -${NLN} "${OMPSTCBF}" ompstcbufr -${NLN} "${GOMEBF}" gomebufr -${NLN} "${OMIBF}" omibufr -${NLN} "${MLSBF}" mlsbufr -${NLN} "${SMIPCP}" ssmirrbufr -${NLN} "${TMIPCP}" tmirrbufr -${NLN} "${AIRSBF}" airsbufr -${NLN} "${IASIBF}" iasibufr -${NLN} "${ESIASI}" iasibufrears -${NLN} "${IASIDB}" iasibufr_db -${NLN} "${AMSREBF}" amsrebufr -${NLN} "${AMSR2BF}" amsr2bufr -${NLN} "${GMI1CRBF}" gmibufr -${NLN} "${SAPHIRBF}" saphirbufr -${NLN} "${SEVIRIBF}" seviribufr -${NLN} "${CRISBF}" crisbufr -${NLN} "${ESCRIS}" crisbufrears -${NLN} "${CRISDB}" crisbufr_db -${NLN} "${CRISFSBF}" crisfsbufr -${NLN} "${ESCRISFS}" crisfsbufrears -${NLN} "${CRISFSDB}" crisfsbufr_db -${NLN} "${ATMSBF}" atmsbufr -${NLN} "${ESATMS}" atmsbufrears -${NLN} "${ATMSDB}" atmsbufr_db -${NLN} "${SSMITBF}" ssmitbufr -${NLN} "${SSMISBF}" ssmisbufr -${NLN} "${GPSROBF}" gpsrobufr -${NLN} "${TCVITL}" tcvitl -${NLN} "${B1AVHAM}" avhambufr -${NLN} "${B1AVHPM}" avhpmbufr -${NLN} "${AHIBF}" ahibufr -${NLN} "${ABIBF}" abibufr -${NLN} "${HDOB}" hdobbufr -${NLN} "${SSTVIIRS}" sstviirs -${NLN} "${SAILDRONE}" sdbufr -${NLN} "${GSBBF}" wbbufr +${NLN} "${SBUVBF}" sbuvbufr +${NLN} "${OMPSNPBF}" ompsnpbufr +${NLN} "${OMPSLPBF}" ompslpbufr +${NLN} "${OMPSTCBF}" ompstcbufr +${NLN} "${GOMEBF}" gomebufr +${NLN} "${OMIBF}" omibufr +${NLN} "${MLSBF}" mlsbufr +${NLN} "${SMIPCP}" ssmirrbufr +${NLN} "${TMIPCP}" tmirrbufr +${NLN} "${AIRSBF}" airsbufr +${NLN} "${IASIBF}" iasibufr +${NLN} "${ESIASI}" iasibufrears +${NLN} "${IASIDB}" iasibufr_db +${NLN} "${AMSREBF}" amsrebufr +${NLN} "${AMSR2BF}" amsr2bufr +${NLN} "${GMI1CRBF}" gmibufr +${NLN} "${SAPHIRBF}" saphirbufr +${NLN} "${SEVIRIBF}" seviribufr +${NLN} "${CRISBF}" crisbufr +${NLN} "${ESCRIS}" crisbufrears +${NLN} "${CRISDB}" crisbufr_db +${NLN} "${CRISFSBF}" crisfsbufr +${NLN} "${ESCRISFS}" crisfsbufrears +${NLN} "${CRISFSDB}" crisfsbufr_db +${NLN} "${ATMSBF}" atmsbufr +${NLN} "${ESATMS}" atmsbufrears +${NLN} "${ATMSDB}" atmsbufr_db +${NLN} "${SSMITBF}" ssmitbufr +${NLN} "${SSMISBF}" ssmisbufr +${NLN} "${GPSROBF}" gpsrobufr +${NLN} "${TCVITL}" tcvitl +${NLN} "${B1AVHAM}" avhambufr +${NLN} "${B1AVHPM}" avhpmbufr +${NLN} "${AHIBF}" ahibufr +${NLN} "${ABIBF}" abibufr +${NLN} "${HDOB}" hdobbufr +${NLN} "${SSTVIIRS}" sstviirs +${NLN} "${SAILDRONE}" sdbufr +${NLN} "${GSBBF}" wbbufr # NASA ozone (netcdf) from NNJA -${NLN} "${OMIEFFNC}" omieffnc +${NLN} "${OMIEFFNC}" omieffnc ${NLN} "${OMPSNMEFFNC}" ompsnmeffnc -${NLN} "${OMPSNPNC}" ompsnpnc -${NLN} "${OMPSLPNC}" ompslpnc -${NLN} "${MLS55NC}" mls55nc +${NLN} "${OMPSNPNC}" ompsnpnc +${NLN} "${OMPSLPNC}" ompslpnc +${NLN} "${MLS55NC}" mls55nc # NASA airs aqua amsua (bufr) from NNJA -${NLN} "${AQUAAMUA}" aquabufr +${NLN} "${AQUAAMUA}" aquabufr if [[ "${DONST}" == "YES" ]]; then ${NLN} "${NSSTBF}" nsstbufr @@ -541,8 +544,8 @@ fi ############################################################## # Required bias guess files -${NLN} "${GBIAS}" satbias_in -${NLN} "${GBIASPC}" satbias_pc +${NLN} "${GBIAS}" satbias_in +${NLN} "${GBIASPC}" satbias_pc ${NLN} "${GBIASAIR}" aircftbias_in ${NLN} "${GRADSTAT}" radstat.gdas @@ -584,124 +587,124 @@ fi if [[ "${DOHYBVAR}" == "YES" ]]; then - # Link ensemble members - mkdir -p ensemble_data + # Link ensemble members + mkdir -p ensemble_data - ENKF_SUFFIX="smooth." - if [[ "${SMOOTH_ENKF}" == "NO" ]]; then - ENKF_SUFFIX="" - fi + ENKF_SUFFIX="smooth" + if [[ "${SMOOTH_ENKF}" == "NO" ]]; then + ENKF_SUFFIX="" + fi - fhrs="06" - if [[ ${l4densvar} == ".true." ]]; then - fhrs="03 04 05 06 07 08 09" - nhr_obsbin=1 - fi + fhrs="06" + if [[ "${l4densvar}" == ".true." ]]; then + fhrs=$(seq -s ' ' -f '%02g' 3 9) + nhr_obsbin=1 + fi - for imem in $(seq 1 ${NMEM_ENS}); do - memchar="mem$(printf %03i "${imem}")" - MEMDIR=${memchar} RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl \ - COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL + for imem in $(seq 1 "${NMEM_ENS}"); do + memchar="mem$(printf %03i "${imem}")" + MEMDIR=${memchar} RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl \ + COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL - for fhr in ${fhrs}; do - ${NLN} "${COMIN_ATMOS_HISTORY}/${GPREFIX_ENS}${ENKF_SUFFIX}atm.f0${fhr}.nc" "./ensemble_data/sigf${fhr}_ens_${memchar}" - if [[ ${cnvw_option} == ".true." ]]; then - ${NLN} "${COMIN_ATMOS_HISTORY}/${GPREFIX_ENS}sfc.f0${fhr}.nc" "./ensemble_data/sfcf${fhr}_ens_${memchar}" - fi - done - done + for fhr in ${fhrs}; do + ${NLN} "${COMIN_ATMOS_HISTORY}/${GPREFIX_ENS}${ENKF_SUFFIX}atm.f0${fhr}.nc" "./ensemble_data/sigf${fhr}_ens_${memchar}" + if [[ "${cnvw_option}" == ".true." ]]; then + ${NLN} "${COMIN_ATMOS_HISTORY}/${GPREFIX_ENS}sfc.f0${fhr}.nc" "./ensemble_data/sfcf${fhr}_ens_${memchar}" + fi + done + done fi ############################################################## # Handle inconsistent surface mask between background, ensemble and analysis grids # This needs re-visiting in the context of NSST; especially references to JCAP* -if [[ ${JCAP} -ne ${JCAP_A} ]]; then - if [[ ${DOHYBVAR} == "YES" && ${JCAP_A} == "${JCAP_ENKF}" ]]; then - if [[ -e ${SFCGES_ENSMEAN} ]]; then - USE_READIN_ANL_SFCMASK=.true. - ${NLN} "${SFCGES_ENSMEAN}" sfcf06_anlgrid - else - echo "Warning: Inconsistent sfc mask between analysis and ensemble grids, GSI will interpolate" - fi +if [[ "${JCAP}" -ne "${JCAP_A}" ]]; then + if [[ "${DOHYBVAR}" == "YES" && "${JCAP_A}" == "${JCAP_ENKF}" ]]; then + if [[ -e "${SFCGES_ENSMEAN}" ]]; then + USE_READIN_ANL_SFCMASK=.true. + ${NLN} "${SFCGES_ENSMEAN}" sfcf06_anlgrid + else + echo "Warning: Inconsistent sfc mask between analysis and ensemble grids, GSI will interpolate" + fi else - echo "Warning: Inconsistent sfc mask between analysis and background grids, GSI will interpolate" - fi + echo "Warning: Inconsistent sfc mask between analysis and background grids, GSI will interpolate" + fi fi ############################################################## # Diagnostic files # if requested, link GSI diagnostic file directories for use later -if [[ ${GENDIAG} == "YES" ]] ; then - if [[ ${lrun_subdirs} == ".true." ]] ; then - if [[ -d ${DIAG_DIR} ]]; then - rm -rf "${DIAG_DIR}" - fi - ntasks_m1="$((ntasks-1))" - for pe in $(seq 0 ${ntasks_m1}); do - pedir="dir."$(printf %04i ${pe}) - mkdir -p "${DIAG_DIR}/${pedir}" - ${NLN} "${DIAG_DIR}/${pedir}" "${pedir}" - done - else - err_exit "lrun_subdirs must be true. lrun_subdirs=${lrun_subdirs}" - fi +if [[ "${GENDIAG}" == "YES" ]]; then + if [[ "${lrun_subdirs}" == ".true." ]]; then + if [[ -d "${DIAG_DIR}" ]]; then + rm -rf "${DIAG_DIR}" + fi + ntasks_m1="$((ntasks - 1))" + for pe in $(seq 0 "${ntasks_m1}"); do + pedir="dir.$(printf %04i "${pe}")" + mkdir -p "${DIAG_DIR}/${pedir}" + ${NLN} "${DIAG_DIR}/${pedir}" "${pedir}" + done + else + err_exit "lrun_subdirs must be true. lrun_subdirs=${lrun_subdirs}" + fi fi ############################################################## # Output files -${NLN} ${ATMANL} siganl -${NLN} ${ATMINC} siginc.nc -if [[ ${DOHYBVAR} == "YES" && ${l4densvar} == ".true." && ${lwrite4danl} == ".true." ]]; then - ${NLN} "${ATMA03}" siga03 - ${NLN} "${ATMI03}" sigi03.nc - ${NLN} "${ATMA04}" siga04 - ${NLN} "${ATMI04}" sigi04.nc - ${NLN} "${ATMA05}" siga05 - ${NLN} "${ATMI05}" sigi05.nc - ${NLN} "${ATMA07}" siga07 - ${NLN} "${ATMI07}" sigi07.nc - ${NLN} "${ATMA08}" siga08 - ${NLN} "${ATMI08}" sigi08.nc - ${NLN} "${ATMA09}" siga09 - ${NLN} "${ATMI09}" sigi09.nc -fi -${NLN} "${ABIAS}" satbias_out -${NLN} "${ABIASPC}" satbias_pc.out -${NLN} ${ABIASAIR} aircftbias_out - -if [[ ${DONST} == "YES" ]]; then - ${NLN} ${DTFANL} dtfanl +${NLN} "${ATMANL}" siganl +${NLN} "${ATMINC}" siginc.nc +if [[ "${DOHYBVAR}" == "YES" && "${l4densvar}" == ".true." && "${lwrite4danl}" == ".true." ]]; then + ${NLN} "${ATMA03}" siga03 + ${NLN} "${ATMI03}" sigi03.nc + ${NLN} "${ATMA04}" siga04 + ${NLN} "${ATMI04}" sigi04.nc + ${NLN} "${ATMA05}" siga05 + ${NLN} "${ATMI05}" sigi05.nc + ${NLN} "${ATMA07}" siga07 + ${NLN} "${ATMI07}" sigi07.nc + ${NLN} "${ATMA08}" siga08 + ${NLN} "${ATMI08}" sigi08.nc + ${NLN} "${ATMA09}" siga09 + ${NLN} "${ATMI09}" sigi09.nc +fi +${NLN} "${ABIAS}" satbias_out +${NLN} "${ABIASPC}" satbias_pc.out +${NLN} "${ABIASAIR}" aircftbias_out + +if [[ "${DONST}" == "YES" ]]; then + ${NLN} "${DTFANL}" dtfanl fi # If requested, link (and if tarred, de-tar obsinput.tar) into obs_input.* files -if [[ ${USE_SELECT} == "YES" ]]; then - rm -f obs_input.* - nl=$(file ${SELECT_OBS} | cut -d: -f2 | grep tar | wc -l) - if [[ ${nl} -eq 1 ]]; then - rm -f obsinput.tar - ${NLN} ${SELECT_OBS} obsinput.tar - tar -xvf obsinput.tar - rm -f obsinput.tar - else - for filetop in $(ls ${SELECT_OBS}/obs_input.*); do - fileloc=$(basename ${filetop}) - ${NLN} "${filetop}" "${fileloc}" - done - fi +if [[ "${USE_SELECT}" == "YES" ]]; then + rm -f obs_input.* + # shellcheck disable=SC2312 + nl=$(file "${SELECT_OBS}" | cut -d: -f2 | grep -c tar) + if [[ ${nl} -eq 1 ]]; then + rm -f obsinput.tar + ${NLN} "${SELECT_OBS}" obsinput.tar + tar -xvf obsinput.tar + rm -f obsinput.tar + else + for filetop in "${SELECT_OBS}/"obs_input.*; do + fileloc=$(basename "${filetop}") + ${NLN} "${filetop}" "${fileloc}" + done + fi fi ############################################################## # If requested, copy and de-tar guess radstat file if [[ "${USE_RADSTAT}" == "YES" ]]; then - if [[ "${USE_CFP}" == "YES" ]]; then - if [[ -f "${DATA}/unzip.sh" ]]; then - rm -f "${DATA}/unzip.sh" - fi - if [[ -f "${DATA}/mp_unzip.sh" ]]; then - rm -f "${DATA}/mp_unzip.sh" - fi - cat > "${DATA}/unzip.sh" << EOFunzip + if [[ -f "${DATA}/unzip.sh" ]]; then + rm -f "${DATA}/unzip.sh" + fi + if [[ -f "${DATA}/mp_unzip.sh" ]]; then + rm -f "${DATA}/mp_unzip.sh" + fi + cat > "${DATA}/unzip.sh" << EOFunzip #!/bin/sh diag_file=\$1 diag_suffix=\$2 @@ -711,59 +714,39 @@ if [[ "${USE_RADSTAT}" == "YES" ]]; then fnameges=\$(echo \$fname | sed 's/_ges//g') ${NMV} \$fname.\$fdate\$diag_suffix \$fnameges EOFunzip - chmod 755 ${DATA}/unzip.sh - fi - - listdiag=$(tar xvf radstat.gdas | cut -d' ' -f2 | grep _ges) - for type in ${listdiag}; do - diag_file=$(echo ${type} | cut -d',' -f1) - if [[ ${USE_CFP} == "YES" ]] ; then - echo "${nm} ${DATA}/unzip.sh ${diag_file} ${DIAG_SUFFIX}" | tee -a "${DATA}/mp_unzip.sh" - if [[ ${CFP_MP:-"NO"} == "YES" ]]; then - nm=$((nm+1)) - fi - else - fname=$(echo "${diag_file}" | cut -d'.' -f1) - date=$(echo "${diag_file}" | cut -d'.' -f2) - ${UNCOMPRESS} "${diag_file}" - fnameges=$(echo "${fname}"|sed 's/_ges//g') - ${NMV} "${fname}.${date}${DIAG_SUFFIX}" "${fnameges}" - fi - done - - if [[ "${USE_CFP}" == "YES" ]] ; then - chmod 755 "${DATA}/mp_unzip.sh" - ncmd=$(wc -l < "${DATA}/mp_unzip.sh") - if [[ ${ncmd} -gt 0 ]]; then - if [[ ${ncmd} -lt ${max_tasks_per_node} ]]; then - ncmd_max=${ncmd} - else - ncmd_max=${max_tasks_per_node} - fi - APRUNCFP_UNZIP=$(eval echo "${APRUNCFP}") - ${APRUNCFP_UNZIP} "${DATA}/mp_unzip.sh" - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to unzip input data files!" - fi - fi - fi + + chmod 755 "${DATA}/unzip.sh" + + #shellcheck disable=SC2312 + listdiag="$(tar xvf radstat.gdas | cut -d' ' -f2 | grep _ges)" + for type in ${listdiag}; do + diag_file=$(echo "${type}" | cut -d',' -f1) + echo "${DATA}/unzip.sh ${diag_file} ${DIAG_SUFFIX}" | tee -a "${DATA}/mp_unzip.sh" + done + chmod 755 "${DATA}/mp_unzip.sh" + "${USHgfs}/run_mpmd.sh" "${DATA}/mp_unzip.sh" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + export pgm="run_mpmd.sh" + err_exit "run_mpmd failed while unziping diagnotic files." + fi + fi # if [[ $USE_RADSTAT == "YES" ] ############################################################## # GSI Namelist options -if [[ ${DOHYBVAR} == "YES" ]]; then - HYBRID_ENSEMBLE="n_ens=${NMEM_ENS},jcap_ens=${JCAP_ENKF},nlat_ens=${NLAT_ENKF},nlon_ens=${NLON_ENKF},jcap_ens_test=${JCAP_ENKF},${HYBRID_ENSEMBLE}" - if [[ ${l4densvar} == ".true." ]]; then - SETUP="niter(1)=50,niter(2)=150,niter_no_qc(1)=25,niter_no_qc(2)=0,thin4d=.true.,ens_nstarthr=3,gmi_method=4,l4densvar=${l4densvar},lwrite4danl=${lwrite4danl},${SETUP}" - JCOPTS="ljc4tlevs=.true.,${JCOPTS}" - STRONGOPTS="tlnmc_option=3,${STRONGOPTS}" - OBSQC="c_varqc=0.04,${OBSQC}" - fi +if [[ "${DOHYBVAR}" == "YES" ]]; then + HYBRID_ENSEMBLE="n_ens=${NMEM_ENS},jcap_ens=${JCAP_ENKF},nlat_ens=${NLAT_ENKF},nlon_ens=${NLON_ENKF},jcap_ens_test=${JCAP_ENKF},${HYBRID_ENSEMBLE}" + if [[ "${l4densvar}" == ".true." ]]; then + SETUP="niter(1)=50,niter(2)=150,niter_no_qc(1)=25,niter_no_qc(2)=0,thin4d=.true.,ens_nstarthr=3,gmi_method=4,l4densvar=${l4densvar},lwrite4danl=${lwrite4danl},${SETUP}" + JCOPTS="ljc4tlevs=.true.,${JCOPTS}" + STRONGOPTS="tlnmc_option=3,${STRONGOPTS}" + OBSQC="c_varqc=0.04,${OBSQC}" + fi fi -if [[ ${DONST} == "YES" ]]; then - NST="nstinfo=${NSTINFO},fac_dtl=${FAC_DTL},fac_tsl=${FAC_TSL},zsea1=${ZSEA1},zsea2=${ZSEA2},${NST}" +if [[ "${DONST}" == "YES" ]]; then + NST="nstinfo=${NSTINFO},fac_dtl=${FAC_DTL},fac_tsl=${FAC_TSL},zsea1=${ZSEA1},zsea2=${ZSEA2},${NST}" fi OBS_INPUT_TABLE=$(cat "${OBS_INPUT}") @@ -886,34 +869,32 @@ cat gsiparm.anl export OMP_NUM_THREADS=${NTHREADS_GSI} export pgm=${GSIEXEC} -. prep_step +source prep_step cpreq "${GSIEXEC}" "${DATA}" ${APRUN_GSI} "${DATA}/$(basename "${GSIEXEC}")" 1>&1 2>&2 export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to run the GSI analysis!" + err_exit "Failed to run the GSI analysis!" fi - ############################################################## # If full analysis field written, calculate analysis increment # here before releasing FV3 forecast -if [[ ${DO_CALC_INCREMENT} == "YES" ]]; then - ${CALCINCPY} - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to calculate the analysis increment!" - fi +if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then + ${CALCINCPY} + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to calculate the analysis increment!" + fi fi - ############################################################## # For eupd if [[ -s satbias_out.int ]]; then - cpfs satbias_out.int "${ABIASe}" + cpfs satbias_out.int "${ABIASe}" else - cpfs satbias_in "${ABIASe}" + cpfs satbias_in "${ABIASe}" fi # Cat runtime output files. @@ -921,24 +902,26 @@ cat fort.2* > "${GSISTAT}" # If requested, create obsinput tarball from obs_input.* files if [[ ${RUN_SELECT} == "YES" ]]; then - echo $(date) START tar obs_input >&2 - if [[ -s obsinput.tar ]]; then - rm -f obsinput.tar - fi - ${NLN} "${SELECT_OBS}" obsinput.tar - ${CHGRP_CMD} obs_input.* - tar -cvf obsinput.tar obs_input.* - chmod 750 "${SELECT_OBS}" - ${CHGRP_CMD} "${SELECT_OBS}" - rm -f obsinput.tar - echo $(date) END tar obs_input >&2 + # shellcheck disable=SC2312 + echo "$(date) START tar obs_input" >&2 + if [[ -s obsinput.tar ]]; then + rm -f obsinput.tar + fi + ${NLN} "${SELECT_OBS}" obsinput.tar + ${CHGRP_CMD} obs_input.* + tar -cvf obsinput.tar obs_input.* + chmod 750 "${SELECT_OBS}" + ${CHGRP_CMD} "${SELECT_OBS}" + rm -f obsinput.tar + # shellcheck disable=SC2312 + echo "$(date) END tar obs_input" >&2 fi ################################################################################ # Send alerts -if [[ ${SENDDBN} == "YES" ]]; then - if [[ ${RUN} == "gfs" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL GFS_abias "${job}" "${ABIAS}" +if [[ "${SENDDBN}" == "YES" ]]; then + if [[ "${RUN}" == "gfs" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL GFS_abias "${job}" "${ABIAS}" fi fi @@ -951,9 +934,10 @@ cd "${pwd}" || exit 1 # atmopsheric analysis and updated surface RESTARTS are # available. Do not release forecast when RUN=enkf ############################################################## -if [[ ${SENDECF} == "YES" && "${RUN}" != "enkf" ]]; then - ecflow_client --event release_fcst +if [[ "${SENDECF}" == "YES" && "${RUN}" != "enkf" ]]; then + ecflow_client --event release_fcst fi +# shellcheck disable=SC2312 echo "${rCDUMP} ${PDY}${cyc} atminc done at $(date)" > "${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.done.txt" ################################################################################ diff --git a/scripts/exglobal_atmos_analysis_calc.sh b/scripts/exglobal_atmos_analysis_calc.sh index 46371403efb..17f55fd75a6 100755 --- a/scripts/exglobal_atmos_analysis_calc.sh +++ b/scripts/exglobal_atmos_analysis_calc.sh @@ -28,10 +28,9 @@ GDUMP=${GDUMP:-"gdas"} # Utilities export CHGRP_CMD=${CHGRP_CMD:-"chgrp ${group_name:-rstprod}"} -export NCLEN=${NCLEN:-${USHgfs}/getncdimlen} +export NCLEN=${NCLEN:-"${USHgfs}/getncdimlen"} COMPRESS=${COMPRESS:-gzip} UNCOMPRESS=${UNCOMPRESS:-gunzip} -APRUNCFP=${APRUNCFP:-""} # Diagnostic files options netcdf_diag=${netcdf_diag:-".true."} @@ -47,65 +46,66 @@ export APRUN_CALCINC=${APRUN_CALCINC:-${APRUN:-""}} export APRUN_CALCANL=${APRUN_CALCANL:-${APRUN:-""}} export APRUN_CHGRES=${APRUN_CALCANL:-${APRUN:-""}} -export CALCANLEXEC=${CALCANLEXEC:-${EXECgfs}/calc_analysis.x} -export CHGRESNCEXEC=${CHGRESNCEXEC:-${EXECgfs}/enkf_chgres_recenter_nc.x} -export CHGRESINCEXEC=${CHGRESINCEXEC:-${EXECgfs}/interp_inc.x} +export CALCANLEXEC=${CALCANLEXEC:-"${EXECgfs}/calc_analysis.x"} +export CHGRESNCEXEC=${CHGRESNCEXEC:-"${EXECgfs}/enkf_chgres_recenter_nc.x"} +export CHGRESINCEXEC=${CHGRESINCEXEC:-"${EXECgfs}/interp_inc.x"} export NTHREADS_CHGRES=${NTHREADS_CHGRES:-1} -CALCINCPY=${CALCINCPY:-${USHgfs}/calcinc_gfs.py} -CALCANLPY=${CALCANLPY:-${USHgfs}/calcanl_gfs.py} +CALCINCPY=${CALCINCPY:-"${USHgfs}/calcinc_gfs.py"} +CALCANLPY=${CALCANLPY:-"${USHgfs}/calcanl_gfs.py"} DOGAUSFCANL=${DOGAUSFCANL-"NO"} -GAUSFCANLSH=${GAUSFCANLSH:-${USHgfs}/gaussian_sfcanl.sh} -export GAUSFCANLEXE=${GAUSFCANLEXE:-${EXECgfs}/gaussian_sfcanl.x} +GAUSFCANLSH=${GAUSFCANLSH:-"${USHgfs}/gaussian_sfcanl.sh"} +export GAUSFCANLEXE=${GAUSFCANLEXE:-"${EXECgfs}/gaussian_sfcanl.x"} NTHREADS_GAUSFCANL=${NTHREADS_GAUSFCANL:-1} APRUN_GAUSFCANL=${APRUN_GAUSFCANL:-${APRUN:-""}} # Guess files GPREFIX=${GPREFIX:-""} -ATMG03=${ATMG03:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f003.nc} -ATMG04=${ATMG04:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f004.nc} -ATMG05=${ATMG05:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f005.nc} -ATMGES=${ATMGES:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f006.nc} -ATMG07=${ATMG07:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f007.nc} -ATMG08=${ATMG08:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f008.nc} -ATMG09=${ATMG09:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f009.nc} + +ATMG03=${ATMG03:-"${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f003.nc"} +ATMG04=${ATMG04:-"${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f004.nc"} +ATMG05=${ATMG05:-"${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f005.nc"} +ATMGES=${ATMGES:-"${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f006.nc"} +ATMG07=${ATMG07:-"${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f007.nc"} +ATMG08=${ATMG08:-"${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f008.nc"} +ATMG09=${ATMG09:-"${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atm.f009.nc"} # Analysis files export APREFIX=${APREFIX:-""} -SFCANL=${SFCANL:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.sfc.a006.nc} -DTFANL=${DTFANL:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.dtf.a006.nc} -ATMANL=${ATMANL:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a006.nc} +SFCANL=${SFCANL:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.sfc.a006.nc"} +DTFANL=${DTFANL:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.dtf.a006.nc"} +ATMANL=${ATMANL:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a006.nc"} # Increment files -ATMINC=${ATMINC:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i006.nc} +ATMINC=${ATMINC:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i006.nc"} # Set script / GSI control parameters DOHYBVAR=${DOHYBVAR:-"NO"} lrun_subdirs=${lrun_subdirs:-".true."} if [[ "${DOHYBVAR}" == "YES" ]]; then - l_hyb_ens=.true. - export l4densvar=${l4densvar:-".false."} - export lwrite4danl=${lwrite4danl:-".false."} + l_hyb_ens=.true. + export l4densvar=${l4densvar:-".false."} + export lwrite4danl=${lwrite4danl:-".false."} else - l_hyb_ens=.false. - export l4densvar=.false. - export lwrite4danl=.false. + export l_hyb_ens=.false. + export l4densvar=.false. + export lwrite4danl=.false. fi # Set 4D-EnVar specific variables if [[ "${DOHYBVAR}" == "YES" && "${l4densvar}" == ".true." && "${lwrite4danl}" == ".true." ]]; then - ATMA03=${ATMA03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a003.nc} - ATMI03=${ATMI03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i003.nc} - ATMA04=${ATMA04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a004.nc} - ATMI04=${ATMI04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i004.nc} - ATMA05=${ATMA05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a005.nc} - ATMI05=${ATMI05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i005.nc} - ATMA07=${ATMA07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a007.nc} - ATMI07=${ATMI07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i007.nc} - ATMA08=${ATMA08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a008.nc} - ATMI08=${ATMI08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i008.nc} - ATMA09=${ATMA09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a009.nc} - ATMI09=${ATMI09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i009.nc} + ATMA03=${ATMA03:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a003.nc"} + ATMI03=${ATMI03:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i003.nc"} + ATMA04=${ATMA04:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a004.nc"} + ATMI04=${ATMI04:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i004.nc"} + ATMA05=${ATMA05:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a005.nc"} + ATMI05=${ATMI05:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i005.nc"} + ATMA07=${ATMA07:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a007.nc"} + ATMI07=${ATMI07:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i007.nc"} + ATMA08=${ATMA08:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a008.nc"} + ATMI08=${ATMI08:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i008.nc"} + ATMA09=${ATMA09:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.atm.a009.nc"} + ATMI09=${ATMI09:-"${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i009.nc"} fi ################################################################################ @@ -115,72 +115,73 @@ rm -rf dir.* ############################################################## # If analysis increment is written by GSI, produce an analysis file here if [[ "${DO_CALC_ANALYSIS}" == "YES" ]]; then - # link analysis and increment files - ${NLN} "${ATMANL}" siganl - ${NLN} "${ATMINC}" siginc.nc - if [[ "${DOHYBVAR}" == "YES" && "${l4densvar}" == ".true." && "${lwrite4danl}" == ".true." ]]; then - ${NLN} "${ATMA03}" siga03 - ${NLN} "${ATMI03}" sigi03.nc - ${NLN} "${ATMA04}" siga04 - ${NLN} "${ATMI04}" sigi04.nc - ${NLN} "${ATMA05}" siga05 - ${NLN} "${ATMI05}" sigi05.nc - ${NLN} "${ATMA07}" siga07 - ${NLN} "${ATMI07}" sigi07.nc - ${NLN} "${ATMA08}" siga08 - ${NLN} "${ATMI08}" sigi08.nc - ${NLN} "${ATMA09}" siga09 - ${NLN} "${ATMI09}" sigi09.nc - fi - # link guess files - ${NLN} "${ATMG03}" sigf03 - ${NLN} "${ATMGES}" sigf06 - ${NLN} "${ATMG09}" sigf09 - - if [[ -f "${ATMG04}" ]]; then - ${NLN} "${ATMG04}" sigf04 - fi - if [[ -f "${ATMG05}" ]]; then - ${NLN} "${ATMG05}" sigf05 - fi - if [[ -f "${ATMG07}" ]]; then - ${NLN} "${ATMG07}" sigf07 - fi - if [[ -f "${ATMG08}" ]]; then - ${NLN} "${ATMG08}" sigf08 - fi - - # Link hourly backgrounds (if present) - if [[ -f "${ATMG04}" && -f "${ATMG05}" && -f "${ATMG07}" && -f "${ATMG08}" ]]; then - nhr_obsbin=1 - fi - - ${CALCANLPY} - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to run ${CALCANLPY}" - fi + # link analysis and increment files + ${NLN} "${ATMANL}" siganl + ${NLN} "${ATMINC}" siginc.nc + if [[ "${DOHYBVAR}" == "YES" && "${l4densvar}" == ".true." && "${lwrite4danl}" == ".true." ]]; then + ${NLN} "${ATMA03}" siga03 + ${NLN} "${ATMI03}" sigi03.nc + ${NLN} "${ATMA04}" siga04 + ${NLN} "${ATMI04}" sigi04.nc + ${NLN} "${ATMA05}" siga05 + ${NLN} "${ATMI05}" sigi05.nc + ${NLN} "${ATMA07}" siga07 + ${NLN} "${ATMI07}" sigi07.nc + ${NLN} "${ATMA08}" siga08 + ${NLN} "${ATMI08}" sigi08.nc + ${NLN} "${ATMA09}" siga09 + ${NLN} "${ATMI09}" sigi09.nc + fi + # link guess files + ${NLN} "${ATMG03}" sigf03 + ${NLN} "${ATMGES}" sigf06 + ${NLN} "${ATMG09}" sigf09 + + if [[ -f "${ATMG04}" ]]; then + ${NLN} "${ATMG04}" sigf04 + fi + if [[ -f "${ATMG05}" ]]; then + ${NLN} "${ATMG05}" sigf05 + fi + if [[ -f "${ATMG07}" ]]; then + ${NLN} "${ATMG07}" sigf07 + fi + if [[ -f "${ATMG08}" ]]; then + ${NLN} "${ATMG08}" sigf08 + fi + + # Link hourly backgrounds (if present) + if [[ -f "${ATMG04}" && -f "${ATMG05}" && -f "${ATMG07}" && -f "${ATMG08}" ]]; then + export nhr_obsbin=1 + fi + + ${CALCANLPY} + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to run ${CALCANLPY}" + fi else - echo "WARNING Neither increment nor analysis are generated by external utils" + echo "WARNING Neither increment nor analysis are generated by external utils" fi ############################################################## # Create gaussian grid surface analysis file at middle of window if [[ "${DOGAUSFCANL}" == "YES" ]]; then - export APRUNSFC=${APRUN_GAUSFCANL} - export OMP_NUM_THREADS_SFC=${NTHREADS_GAUSFCANL} + export APRUNSFC="${APRUN_GAUSFCANL}" + export OMP_NUM_THREADS_SFC="${NTHREADS_GAUSFCANL}" ${GAUSFCANLSH} export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Gaussian grid surface file was not generated!" + err_exit "Gaussian grid surface file was not generated!" fi fi +# shellcheck disable=SC2312 echo "${rCDUMP} ${PDY}${cyc} atmanl and sfcanl done at $(date)" > "${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.done.txt" ################################################################################ # Postprocessing -cd "${pwd}" || exit 1 +cd "${pwd}" || true exit 0 diff --git a/scripts/exglobal_atmos_chgres_gen_control.sh b/scripts/exglobal_atmos_chgres_gen_control.sh index d07460a6ad6..368c86096cf 100755 --- a/scripts/exglobal_atmos_chgres_gen_control.sh +++ b/scripts/exglobal_atmos_chgres_gen_control.sh @@ -13,16 +13,16 @@ cpreq "${SFC_FILE}" "${DATA}/sfc_input.nc" ############################################################################### # copy orography,surface, and ancillary files to DATA from the source directory for i in {1..6}; do - cpreq "${FIXgfs}/orog/${CASE}/${CASE}_grid.tile${i}.nc" "${DATA}/" - cpreq "${FIXgfs}/orog/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile${i}.nc" "${DATA}/" - cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.slope_type.tile${i}.nc" "${DATA}/" - cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.maximum_snow_albedo.tile${i}.nc" "${DATA}/" - cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.snowfree_albedo.tile${i}.nc" "${DATA}/" - cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.soil_type.tile${i}.nc" "${DATA}/" - cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_type.tile${i}.nc" "${DATA}/" - cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.substrate_temperature.tile${i}.nc" "${DATA}/" - cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_greenness.tile${i}.nc" "${DATA}/" - cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.facsf.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/${CASE}_grid.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.slope_type.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.maximum_snow_albedo.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.snowfree_albedo.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.soil_type.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_type.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.substrate_temperature.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_greenness.tile${i}.nc" "${DATA}/" + cpreq "${FIXgfs}/orog/${CASE}/sfc/${CASE}.mx${OCNRES}.facsf.tile${i}.nc" "${DATA}/" done ################################################################################ # add the namelist and run chgres @@ -80,13 +80,13 @@ EOF ${APRUN_CHGRES} "${HOMEgfs}/sorc/ufs_utils.fd/exec/chgres_cube" export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "chgres_cube failed to create cold start ICs, ABORT!" + err_exit "chgres_cube failed to create cold start ICs, ABORT!" fi ################################################################################ # copy output files to com for i in {1..6}; do - cpreq "out.atm.tile${i}.nc" "${COMOUT_ATMOS_INPUT_MEM}/gfs_data.tile${i}.nc" - cpreq "out.sfc.tile${i}.nc" "${COMOUT_ATMOS_INPUT_MEM}/sfc_data.tile${i}.nc" + cpreq "out.atm.tile${i}.nc" "${COMOUT_ATMOS_INPUT_MEM}/gfs_data.tile${i}.nc" + cpreq "out.sfc.tile${i}.nc" "${COMOUT_ATMOS_INPUT_MEM}/sfc_data.tile${i}.nc" done cpreq "gfs_ctrl.nc" "${COMOUT_ATMOS_INPUT_MEM}/" ################################################################################ diff --git a/scripts/exglobal_atmos_ensstat.sh b/scripts/exglobal_atmos_ensstat.sh index cb08714982f..e6bccaae101 100755 --- a/scripts/exglobal_atmos_ensstat.sh +++ b/scripts/exglobal_atmos_ensstat.sh @@ -2,8 +2,8 @@ fhr3=$(printf "%03d" "${FORECAST_HOUR}") -if [[ -a mpmd_script ]]; then - rm -Rf mpmd_script +if [[ -e mpmd_script ]]; then + rm -f mpmd_script fi { @@ -16,5 +16,5 @@ fi "${USHgfs}/run_mpmd.sh" mpmd_script export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "One ore more MPMD jobs failed to calculate ensemble statistics!" + err_exit "One or more MPMD jobs failed to calculate ensemble statistics!" fi diff --git a/scripts/exglobal_atmos_pmgr.sh b/scripts/exglobal_atmos_pmgr.sh index 390ab1cb71f..cc286ccf7e2 100755 --- a/scripts/exglobal_atmos_pmgr.sh +++ b/scripts/exglobal_atmos_pmgr.sh @@ -6,65 +6,42 @@ # This script monitors the progress of the gfs_fcst job # -hour=00 - -case $RUN in - gfs) - TEND=384 - TCP=385 - ;; - gdas) - TEND=9 - TCP=10 - ;; +hour=0 + +case "${RUN}" in + gfs) TEND=384 ;; + gdas) TEND=9 ;; + *) + err_exit "Run ${RUN} not supported at this time" + ;; esac -if [ -e posthours ]; then - rm -f posthours -fi - -while [ $hour -lt $TCP ]; do - hour=$(printf "%02d" $hour) - echo $hour >>posthours - if [ 10#$hour -lt 120 ]; then - let "hour=hour+1" - else - let "hour=hour+3" - fi +declare -a posthours +while [[ "${hour}" -le "${TEND}" ]]; do + posthours+=("${hour}") + if [[ ${hour} -lt 120 ]]; then + hour=$((hour + 1)) + else + hour=$((hour + 3)) + fi done -postjobs=$(cat posthours) # -# Wait for all fcst hours to finish +# Wait for all fcst hours to finish # -icnt=1 -while [ $icnt -lt 1000 ]; do - for fhr in $postjobs; do - fhr3=$(printf "%03d" $fhr) - if [ -s ${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.atm.logf${fhr3}.txt ]; then - if [ $fhr -eq 0 ]; then - #### ecflow_client --event release_${RUN}_postanl +sleep_interval=10 +max_tries=1000 +for fhr in "${posthours[@]}"; do + fhr3=$(sprintf "%03d" "${fhr}") + log_file="${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.atm.logf${fhr3}.txt" + if ! wait_for_file "${log_file}" "${sleep_interval}" "${max_tries}"; then + export err=1 + err_exit "After 2 hours of waiting for GFS FCST hour ${fhr3}." + fi + if [[ ${fhr} -eq 0 ]]; then ecflow_client --event release_postanl - fi - #### ecflow_client --event release_${RUN}_post${fhr} - ecflow_client --event release_post${fhr3} - # Remove current fhr from list - postjobs=$(echo $postjobs | sed "s/${fhr}//") fi - done - - result_check=$(echo $postjobs | wc -w) - if [ $result_check -eq 0 ]; then - break - fi - - sleep 10 - icnt=$((icnt + 1)) - if [[ ${icnt} -ge 1080 ]]; then - msg="ABORTING after 3 hours of waiting for ${RUN} FCST hours $postjobs." - err_exit $msg - fi + ecflow_client --event "release_post${fhr3}" done - exit diff --git a/scripts/exglobal_atmos_products.sh b/scripts/exglobal_atmos_products.sh index 6c0ee4fc122..f7f6bf44280 100755 --- a/scripts/exglobal_atmos_products.sh +++ b/scripts/exglobal_atmos_products.sh @@ -4,23 +4,23 @@ cd "${DATA}" || exit 1 # Set paramlist files based on FORECAST_HOUR (-1, 0, 3, 6, etc.) # Determine if supplemental products (PGBS) (1-degree and 1/2-degree) should be generated -if [[ ${FORECAST_HOUR} -le 0 ]]; then - if [[ ${FORECAST_HOUR} -lt 0 ]]; then - fhr3="analysis" - # shellcheck disable=SC2034 # paramlista is used later indirectly - paramlista="${paramlista_anl}" - FLXGF="NO" - elif [[ ${FORECAST_HOUR} == 0 ]]; then - fhr3=$(printf "f%03d" "${FORECAST_HOUR}") - # shellcheck disable=SC2034 # paramlista is used later indirectly - paramlista="${paramlista_f000}" - fi - PGBS="YES" -else - fhr3=$(printf "f%03d" "${FORECAST_HOUR}") - if (( FORECAST_HOUR%FHOUT_PGBS == 0 )); then +if [[ "${FORECAST_HOUR}" -le 0 ]]; then + if [[ "${FORECAST_HOUR}" -lt 0 ]]; then + fhr3="analysis" + # shellcheck disable=SC2034 # paramlista is used later indirectly + paramlista="${paramlista_anl}" + FLXGF="NO" + elif [[ "${FORECAST_HOUR}" -eq 0 ]]; then + fhr3=$(printf "f%03d" "${FORECAST_HOUR}") + # shellcheck disable=SC2034 # paramlista is used later indirectly + paramlista="${paramlista_f000}" + fi PGBS="YES" - fi +else + fhr3=$(printf "f%03d" "${FORECAST_HOUR}") + if ((FORECAST_HOUR % FHOUT_PGBS == 0)); then + PGBS="YES" + fi fi #----------------------------------------------------- @@ -29,10 +29,10 @@ fi # Determine grids once and save them as a string and an array for processing grid_string="0p25" if [[ "${PGBS:-}" == "YES" ]]; then - grid_string="${grid_string}:0p50:1p00" + grid_string="${grid_string}:0p50:1p00" else - echo "INFO: Supplemental product generation is disabled for fhr = ${fhr3}" - PGBS="NO" # Can't generate supplemental products if PGBS is not YES + echo "INFO: Supplemental product generation is disabled for fhr = ${fhr3}" + PGBS="NO" # Can't generate supplemental products if PGBS is not YES fi # Also transform the ${grid_string} into an array for processing IFS=':' read -ra grids <<< "${grid_string}" @@ -40,170 +40,164 @@ IFS=':' read -ra grids <<< "${grid_string}" # Files needed by ${USHgfs}/interp_atmos_master.sh MASTER_FILE="${COMIN_ATMOS_MASTER}/${PREFIX}master.${fhr3}.grib2" -nset=1 -while [[ ${nset} -le ${downset:-1} ]]; do +for ((nset = 1; nset <= downset; nset++)); do - echo "INFO: Begin processing nset = ${nset}" + echo "INFO: Begin processing nset = ${nset}" - # Each set represents a group of files - if [[ ${nset} == 1 ]]; then - grp="a" - elif [[ ${nset} == 2 ]]; then - grp="b" - fi - - # Get inventory from ${MASTER_FILE} that matches patterns from ${paramlist} - # Extract this inventory from ${MASTER_FILE} into a smaller tmpfile based on paramlist - - tmpfile="tmpfile${grp}_${fhr3}" - paramlist="paramlist${grp}" - parmfile="${!paramlist}" - - # shellcheck disable=SC2312 - ${WGRIB2} "${MASTER_FILE}" | grep -F -f "${parmfile}" | ${WGRIB2} -i -grib "${tmpfile}" "${MASTER_FILE}" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "wgrib2 failed to create intermediate grib2 file from '${MASTER_FILE}' using '${parmfile}'" - fi - - # Number of processors available to process $nset - nproc=${ntasks} - - # shellcheck disable=SC2312 - ncount=$(${WGRIB2} "${tmpfile}" | wc -l) - if [[ ${nproc} -gt ${ncount} ]]; then - echo "WARNING: Total no. of available processors '${nproc}' exceeds no. of records '${ncount}' in ${tmpfile}" - echo "WARNING: Reduce nproc to ${ncount} (or less) to not waste resources" - fi - inv=$(( ncount / nproc )) - rm -f "${DATA}/cmdfile" - - last=0 - iproc=1 - while [[ ${iproc} -le ${nproc} ]]; do - first=$((last + 1)) - last=$((last + inv)) - if [[ ${last} -gt ${ncount} ]]; then - last=${ncount} + # Each set represents a group of files + if [[ "${nset}" == 1 ]]; then + grp="a" + elif [[ "${nset}" == 2 ]]; then + grp="b" fi - # if final record of is u-component, add next record v-component - # if final record is land, add next record icec - # grep returns 1 if no match is found, so temporarily turn off exit on non-zero rc - set +e + # Get inventory from ${MASTER_FILE} that matches patterns from ${paramlist} + # Extract this inventory from ${MASTER_FILE} into a smaller tmpfile based on paramlist + + tmpfile="tmpfile${grp}_${fhr3}" + paramlist="paramlist${grp}" + parmfile="${!paramlist}" + # shellcheck disable=SC2312 - ${WGRIB2} -d "${last}" "${tmpfile}" | grep -E -i "ugrd|ustm|uflx|u-gwd|land|maxuw" - rc=$? - set_strict - if [[ ${rc} == 0 ]]; then # Matched the grep - last=$(( last + 1 )) + ${WGRIB2} "${MASTER_FILE}" | grep -F -f "${parmfile}" | ${WGRIB2} -i -grib "${tmpfile}" "${MASTER_FILE}" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "FATAL ERROR: wgrib2 failed to create intermediate grib2 file from '${MASTER_FILE}' using '${parmfile}'" fi - if [[ ${iproc} -eq ${nproc} ]]; then - last=${ncount} + + # Number of processors available to process $nset + nproc=${ntasks} + + # shellcheck disable=SC2312 + ncount=$(${WGRIB2} "${tmpfile}" | wc -l) + if [[ "${nproc}" -gt "${ncount}" ]]; then + echo "WARNING: Total no. of available processors '${nproc}' exceeds no. of records '${ncount}' in ${tmpfile}" + echo "WARNING: Reduce nproc to ${ncount} (or less) to not waste resources" fi - # Break tmpfile into processor specific chunks in preparation for MPMD - ${WGRIB2} "${tmpfile}" -for "${first}":"${last}" -grib "${tmpfile}_${iproc}" && true + inv=$((ncount / nproc)) + rm -f "${DATA}/cmdfile" + + last=0 + for ((iproc = 1; iproc <= nproc; iproc++)); do + first=$((last + 1)) + last=$((last + inv)) + if [[ ${last} -gt ${ncount} ]]; then + last=${ncount} + fi + + # if final record of is u-component, add next record v-component + # if final record is land, add next record icec + # grep returns 1 if no match is found, so temporarily turn off exit on non-zero rc + set +e + # shellcheck disable=SC2312 + ${WGRIB2} -d "${last}" "${tmpfile}" | grep -E -i "ugrd|ustm|uflx|u-gwd|land|maxuw" + rc=$? + set_strict + if [[ ${rc} == 0 ]]; then # Matched the grep + last=$((last + 1)) + fi + if [[ ${iproc} -eq ${nproc} ]]; then + last=${ncount} + fi + + # Break tmpfile into processor specific chunks in preparation for MPMD + ${WGRIB2} "${tmpfile}" -for "${first}":"${last}" -grib "${tmpfile}_${iproc}" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "wgrib2 failed to geneate an intermediate grib2 file from ${tmpfile} records ${first} to ${last}" + fi + input_file="${tmpfile}_${iproc}" + output_file_prefix="pgb2${grp}file_${fhr3}_${iproc}" + echo "${USHgfs}/interp_atmos_master.sh ${input_file} ${output_file_prefix} ${grid_string}" >> "${DATA}/cmdfile" + + # if at final record and have not reached the final processor then write echo's to + # cmdfile for remaining processors + if [[ "${last}" -eq "${ncount}" ]]; then + for ((pproc = iproc + 1; pproc < nproc; pproc++)); do + echo "/bin/echo ${pproc}" >> "${DATA}/cmdfile" + done + break + fi + done # for (( iproc = 1 ; iproc <= nproc ; iproc++ )); do + + # Run with MPMD or serial + "${USHgfs}/run_mpmd.sh" "${DATA}/cmdfile" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "wgrib2 failed to geneate an intermediate grib2 file from ${tmpfile} records ${first} to ${last}" + err_exit "FATAL ERROR: Some or all interpolations of the master grib file failed during MPMD execution!" fi - input_file="${tmpfile}_${iproc}" - output_file_prefix="pgb2${grp}file_${fhr3}_${iproc}" - echo "${USHgfs}/interp_atmos_master.sh ${input_file} ${output_file_prefix} ${grid_string}" >> "${DATA}/cmdfile" - - # if at final record and have not reached the final processor then write echo's to - # cmdfile for remaining processors - if [[ ${last} -eq ${ncount} ]]; then - for (( pproc = iproc+1 ; pproc < nproc ; pproc++ )); do - echo "/bin/echo ${pproc}" >> "${DATA}/cmdfile" - done - break - fi - iproc=$(( iproc + 1 )) - done # while [[ iproc -le nproc ]]; do - - # Run with MPMD or serial - "${USHgfs}/run_mpmd.sh" "${DATA}/cmdfile" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Some or all interpolations of the master grib file failed during MPMD execution!" - fi - - # We are in a loop over downset, save output from mpmd into nset specific output - mv mpmd.out "mpmd_${nset}.out" - - # Concatenate grib files from each processor into a single one - # and clean-up as you go - echo "INFO: Concatenating processor-specific grib2 files into a single product file" - iproc=1 - while [[ ${iproc} -le ${nproc} ]]; do - for grid in "${grids[@]}"; do - if [[ -s "pgb2${grp}file_${fhr3}_${iproc}_${grid}" ]]; then - cat "pgb2${grp}file_${fhr3}_${iproc}_${grid}" >> "pgb2${grp}file_${fhr3}_${grid}" - rm -f "pgb2${grp}file_${fhr3}_${iproc}_${grid}" - fi + + # We are in a loop over downset, save output from mpmd into nset specific output + mv mpmd.out "mpmd_${nset}.out" + + # Concatenate grib files from each processor into a single one + # and clean-up as you go + echo "INFO: Concatenating processor-specific grib2 files into a single product file" + for ((iproc = 1; iproc <= nproc; iproc++)); do + for grid in "${grids[@]}"; do + if [[ -s "pgb2${grp}file_${fhr3}_${iproc}_${grid}" ]]; then + cat "pgb2${grp}file_${fhr3}_${iproc}_${grid}" >> "pgb2${grp}file_${fhr3}_${grid}" + rm -f "pgb2${grp}file_${fhr3}_${iproc}_${grid}" + fi + done + # There is no further use of the processor specific tmpfile; delete it + rm -f "${tmpfile}_${iproc}" done - # There is no further use of the processor specific tmpfile; delete it - rm -f "${tmpfile}_${iproc}" - iproc=$(( iproc + 1 )) - done - # Move to COM and index the product grib files - for grid in "${grids[@]}"; do - ${WGRIB2} -s "pgb2${grp}file_${fhr3}_${grid}" > "pgb2${grp}file_${fhr3}_${grid}.idx" - prod_dir="COMOUT_ATMOS_GRIB_${grid}" - cpfs "pgb2${grp}file_${fhr3}_${grid}" "${!prod_dir}/${PREFIX}pres_${grp}.${grid}.${fhr3}.grib2" - cpfs "pgb2${grp}file_${fhr3}_${grid}.idx" "${!prod_dir}/${PREFIX}pres_${grp}.${grid}.${fhr3}.grib2.idx" - done + # Move to COM and index the product grib files + for grid in "${grids[@]}"; do + ${WGRIB2} -s "pgb2${grp}file_${fhr3}_${grid}" > "pgb2${grp}file_${fhr3}_${grid}.idx" + prod_dir="COMOUT_ATMOS_GRIB_${grid}" + cpfs "pgb2${grp}file_${fhr3}_${grid}" "${!prod_dir}/${PREFIX}pres_${grp}.${grid}.${fhr3}.grib2" + cpfs "pgb2${grp}file_${fhr3}_${grid}.idx" "${!prod_dir}/${PREFIX}pres_${grp}.${grid}.${fhr3}.grib2.idx" + done - echo "INFO: Finished processing nset = ${nset}" + echo "INFO: Finished processing nset = ${nset}" - nset=$(( nset + 1 )) -done # while [[ ${nset} -le ${downset} ]]; do +done # for (( nset=1 ; nset <= downset ; nset++ )) #--------------------------------------------------------------- # Create the index file for the sflux master, if it exists. FLUX_FILE="${COMIN_ATMOS_MASTER}/${PREFIX}sflux.${fhr3}.grib2" if [[ -s "${FLUX_FILE}" ]]; then - ${WGRIB2} -s "${FLUX_FILE}" > "${FLUX_FILE}.idx" + ${WGRIB2} -s "${FLUX_FILE}" > "${FLUX_FILE}.idx" fi # Section creating sflux grib2 interpolated products # Create 1-degree sflux grib2 output # move to COM and index it if [[ "${FLXGF:-}" == "YES" ]]; then + # Files needed by ${INTERP_ATMOS_SFLUXSH} + input_file="${FLUX_FILE}" + output_file_prefix="sflux_${fhr3}" + grid_string="1p00" + "${USHgfs}/interp_atmos_sflux.sh" "${input_file}" "${output_file_prefix}" "${grid_string}" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "FATAL ERROR: Unable to interpolate the surface flux grib2 files!" + fi - # Files needed by ${USHgfs}/interp_atmos_sflux.sh - input_file="${FLUX_FILE}" - output_file_prefix="sflux_${fhr3}" - grid_string="1p00" - "${USHgfs}/interp_atmos_sflux.sh" "${input_file}" "${output_file_prefix}" "${grid_string}" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Unable to interpolate the surface flux grib2 files!" - fi - - # Move to COM and index the product sflux file - IFS=':' read -ra grids <<< "${grid_string}" - for grid in "${grids[@]}"; do - ${WGRIB2} -s "sflux_${fhr3}_${grid}" > "sflux_${fhr3}_${grid}.idx" - prod_dir="COMOUT_ATMOS_GRIB_${grid}" - cpfs "sflux_${fhr3}_${grid}" "${!prod_dir}/${PREFIX}flux.${grid}.${fhr3}.grib2" - cpfs "sflux_${fhr3}_${grid}.idx" "${!prod_dir}/${PREFIX}flux.${grid}.${fhr3}.grib2.idx" - done + # Move to COM and index the product sflux file + IFS=':' read -ra grids <<< "${grid_string}" + for grid in "${grids[@]}"; do + ${WGRIB2} -s "sflux_${fhr3}_${grid}" > "sflux_${fhr3}_${grid}.idx" + prod_dir="COMOUT_ATMOS_GRIB_${grid}" + cpfs "sflux_${fhr3}_${grid}" "${!prod_dir}/${PREFIX}flux.${grid}.${fhr3}.grib2" + cpfs "sflux_${fhr3}_${grid}.idx" "${!prod_dir}/${PREFIX}flux.${grid}.${fhr3}.grib2.idx" + done fi # Section creating 0.25 degree WGNE products for nset=1, and fhr <= FHMAX_WGNE if [[ "${WGNE:-}" == "YES" ]]; then - grp="a" - if [[ ${FORECAST_HOUR} -gt 0 && ${FORECAST_HOUR} -le ${FHMAX_WGNE:-0} ]]; then - # 598 is the message number for APCP in GFSv17 (it was 597 in GFSv16) - ${WGRIB2} "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_${grp}.0p25.${fhr3}.grib2" \ - -d "${APCP_MSG:-598}" \ - -grib "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}wgne.${fhr3}.grib2" - fi + grp="a" + if [[ "${FORECAST_HOUR}" -gt 0 && "${FORECAST_HOUR}" -le ${FHMAX_WGNE:-0} ]]; then + # 598 is the message number for APCP in GFSv17 (it was 597 in GFSv16) + ${WGRIB2} "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_${grp}.0p25.${fhr3}.grib2" \ + -d "${APCP_MSG:-598}" \ + -grib "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}wgne.${fhr3}.grib2" + fi fi #--------------------------------------------------------------- @@ -211,72 +205,69 @@ fi # Start sending DBN alerts # Everything below this line is for sending files to DBN (SENDDBN=YES) if [[ "${SENDDBN:-}" == "YES" ]]; then - - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_0P25" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_a.0p25.${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_0P25_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_a.0p25.${fhr3}.grib2.idx" - if [[ "${RUN}" == "gfs" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_0P25" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_b.0p25.${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_0P25_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_b.0p25.${fhr3}.grib2.idx" - if [[ -s "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_a.0p50.${fhr3}.grib2" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_0P5" "${job}" "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_a.0p50.${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_0P5_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_a.0p50.${fhr3}.grib2.idx" - fi - if [[ -s "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_b.0p50.${fhr3}.grib2" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_0P5" "${job}" "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_b.0p50.${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_0P5_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_b.0p50.${fhr3}.grib2.idx" - fi - if [[ -s "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_1P0" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_1P0_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2.idx" - fi - if [[ -s "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_b.1p00.${fhr3}.grib2" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_1P0" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_b.1p00.${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_1P0_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_b.1p00.${fhr3}.grib2.idx" - fi - if [[ "${WGNE:-}" == "YES" ]] && [[ -s "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}wgne.${fhr3}.grib2" ]] ; then - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_WGNE" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}wgne.${fhr3}.grib2" - fi - fi - - if [[ "${fhr3}" == "analysis" ]]; then - - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_MSC_sfcanl" "${job}" "${COMIN_ATMOS_ANALYSIS}/${PREFIX}analysis.sfc.a006.nc" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SA" "${job}" "${COMIN_ATMOS_ANALYSIS}/${PREFIX}analysis.atm.a006.nc" - - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGA_GB2" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGA_GB2_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2.idx" - - else # forecast hours f000, f003, f006, etc. - - case "${RUN}" in - gdas) - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB_GB2" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB_GB2_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2.idx" - if (( FORECAST_HOUR % 3 == 0 )); then - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SF" "${job}" "${COMIN_ATMOS_HISTORY}/${PREFIX}atm.${fhr3}.nc" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_BF" "${job}" "${COMIN_ATMOS_HISTORY}/${PREFIX}sfc.${fhr3}.nc" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SGB_GB2" "${job}" "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SGB_GB2_WIDX" "${job}" "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2.idx" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_0P25" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_a.0p25.${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_0P25_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_a.0p25.${fhr3}.grib2.idx" + if [[ "${RUN}" == "gfs" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_0P25" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_b.0p25.${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_0P25_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}pres_b.0p25.${fhr3}.grib2.idx" + if [[ -s "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_a.0p50.${fhr3}.grib2" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_0P5" "${job}" "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_a.0p50.${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_0P5_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_a.0p50.${fhr3}.grib2.idx" fi - ;; - gfs) - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SF" "${job}" "${COMIN_ATMOS_HISTORY}/${PREFIX}atm.${fhr3}.nc" - if [[ ${fhr} -gt 0 && ${fhr} -le 84 || ${fhr} -eq 120 ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_BF" "${job}" "${COMIN_ATMOS_HISTORY}/${PREFIX}sfc.${fhr3}.nc" + if [[ -s "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_b.0p50.${fhr3}.grib2" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_0P5" "${job}" "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_b.0p50.${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_0P5_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_0p50}/${PREFIX}pres_b.0p50.${fhr3}.grib2.idx" fi - - if [[ -s "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SGB_GB2" "${job}" "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SGB_GB2_WIDX" "${job}" "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2.idx" + if [[ -s "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_1P0" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2_1P0_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2.idx" fi - ;; - *) - err_exit "Unsupported RUN value '${RUN}' for SENDDBN section" - ;; - esac - - fi # end if fhr3=anl + if [[ -s "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_b.1p00.${fhr3}.grib2" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_1P0" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_b.1p00.${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB2B_1P0_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_b.1p00.${fhr3}.grib2.idx" + fi + if [[ "${WGNE:-}" == "YES" ]] && [[ -s "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}wgne.${fhr3}.grib2" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_WGNE" "${job}" "${COMOUT_ATMOS_GRIB_0p25}/${PREFIX}wgne.${fhr3}.grib2" + fi + fi -fi # end if SENDDBN=YES + if [[ "${fhr3}" == "analysis" ]]; then + + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_MSC_sfcanl" "${job}" "${COMIN_ATMOS_ANALYSIS}/${PREFIX}analysis.sfc.a006.nc" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SA" "${job}" "${COMIN_ATMOS_ANALYSIS}/${PREFIX}analysis.atm.a006.nc" + + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGA_GB2" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGA_GB2_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2.idx" + + else # forecast hours f000, f003, f006, etc. + + case "${RUN}" in + gdas) + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB_GB2" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_PGB_GB2_WIDX" "${job}" "${COMOUT_ATMOS_GRIB_1p00}/${PREFIX}pres_a.1p00.${fhr3}.grib2.idx" + if ((FORECAST_HOUR % 3 == 0)); then + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SF" "${job}" "${COMIN_ATMOS_HISTORY}/${PREFIX}atm.${fhr3}.nc" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_BF" "${job}" "${COMIN_ATMOS_HISTORY}/${PREFIX}sfc.${fhr3}.nc" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SGB_GB2" "${job}" "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SGB_GB2_WIDX" "${job}" "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2.idx" + fi + ;; + gfs) + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SF" "${job}" "${COMIN_ATMOS_HISTORY}/${PREFIX}atm.${fhr3}.nc" + if [[ ${fhr} -gt 0 && ${fhr} -le 84 || ${fhr} -eq 120 ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_BF" "${job}" "${COMIN_ATMOS_HISTORY}/${PREFIX}sfc.${fhr3}.nc" + fi + + if [[ -s "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2" ]]; then + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SGB_GB2" "${job}" "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_SGB_GB2_WIDX" "${job}" "${COMIN_ATMOS_MASTER}/${PREFIX}sflux.f${fhr3}.grib2.idx" + fi + ;; + *) + err_exit "Unsupported RUN value '${RUN}' for SENDDBN section" + ;; + esac + fi +fi # end if SENDDBN=YES exit 0 diff --git a/scripts/exglobal_atmos_sfcanl.sh b/scripts/exglobal_atmos_sfcanl.sh index dd7be82cf0d..ed52df19c3d 100755 --- a/scripts/exglobal_atmos_sfcanl.sh +++ b/scripts/exglobal_atmos_sfcanl.sh @@ -22,14 +22,14 @@ # Derived base variables # Dependent Scripts and Executables -CYCLESH=${CYCLESH:-${USHgfs}/global_cycle.sh} +CYCLESH=${CYCLESH:-"${USHgfs}/global_cycle.sh"} REGRIDSH=${REGRIDSH:-"${USHgfs}/regrid_gsiSfcIncr_to_tile.sh"} -export CYCLEXEC=${CYCLEXEC:-${EXECgfs}/global_cycle} +export CYCLEXEC=${CYCLEXEC:-"${EXECgfs}/global_cycle"} NTHREADS_CYCLE=${NTHREADS_CYCLE:-24} APRUN_CYCLE=${APRUN_CYCLE:-${APRUN:-""}} # Surface cycle related parameters -export SNOW_NUDGE_COEFF=${SNOW_NUDGE_COEFF:-'-2.'} +export SNOW_NUDGE_COEFF=${SNOW_NUDGE_COEFF:--2.} export CYCLVARS=${CYCLVARS:-""} export FHOUR=${FHOUR:-0} export DELTSFC=${DELTSFC:-6} @@ -39,54 +39,53 @@ export COUPLED=${COUPLED:-".false."} # Ignore possible spelling error (nothing is misspelled) # shellcheck disable=SC2153 GPREFIX="gdas.t${GDATE:8:2}z." -OPREFIX="${RUN/enkf}.t${cyc}z." -APREFIX="${RUN/enkf}.t${cyc}z." +OPREFIX="${RUN/enkf/}.t${cyc}z." +APREFIX="${RUN/enkf/}.t${cyc}z." ntiles=6 - ############################################################## # Get dimension information based on CASE -res="${CASE:1}" -JCAP_CASE=$((res*2-2)) -LATB_CASE=$((res*2)) -LONB_CASE=$((res*4)) +res=${CASE:1} +JCAP_CASE=$((res * 2 - 2)) +LATB_CASE=$((res * 2)) +LONB_CASE=$((res * 4)) # Global cycle requires these files -export FNTSFA=${FNTSFA:-${COMIN_OBS}/${OPREFIX}rtgssthr.grb} -export FNACNA=${FNACNA:-${COMIN_OBS}/${OPREFIX}seaice.5min.blend.grb} -export FNSNOA=${FNSNOA:-${COMIN_OBS}/${OPREFIX}snogrb_t${JCAP_CASE}.${LONB_CASE}.${LATB_CASE}} +export FNTSFA=${FNTSFA:-"${COMIN_OBS}/${OPREFIX}rtgssthr.grb"} +export FNACNA=${FNACNA:-"${COMIN_OBS}/${OPREFIX}seaice.5min.blend.grb"} +export FNSNOA=${FNSNOA:-"${COMIN_OBS}/${OPREFIX}snogrb_t${JCAP_CASE}.${LONB_CASE}.${LATB_CASE}"} # Check if resolution specific FNSNOA exists, if not use t1534 version -if [[ ! -f ${FNSNOA} ]]; then - export FNSNOA="${COMIN_OBS}/${OPREFIX}snogrb_t1534.3072.1536" +if [[ ! -f "${FNSNOA}" ]]; then + export FNSNOA="${COMIN_OBS}/${OPREFIX}snogrb_t1534.3072.1536" fi -if [[ ! -f ${FNSNOA} ]]; then - echo "WARNING: Current cycle snow file ${FNSNOA} is missing. Snow coverage will not be updated." +if [[ ! -f "${FNSNOA}" ]]; then + echo "WARNING: Current cycle snow file ${FNSNOA} is missing. Snow coverage will not be updated." else - echo "INFO: Current cycle snow file is ${FNSNOA}" + echo "INFO: Current cycle snow file is ${FNSNOA}" fi -export FNSNOG=${FNSNOG:-${COMIN_OBS_PREV}/${GPREFIX}snogrb_t${JCAP_CASE}.${LONB_CASE}.${LATB_CASE}} +export FNSNOG=${FNSNOG:-"${COMIN_OBS_PREV}/${GPREFIX}snogrb_t${JCAP_CASE}.${LONB_CASE}.${LATB_CASE}"} # Check if resolution specific FNSNOG exists, if not use t1534 version -if [[ ! -f ${FNSNOG} ]]; then - export FNSNOG="${COMIN_OBS_PREV}/${GPREFIX}snogrb_t1534.3072.1536" +if [[ ! -f "${FNSNOG}" ]]; then + export FNSNOG="${COMIN_OBS_PREV}/${GPREFIX}snogrb_t1534.3072.1536" fi -if [[ ! -f ${FNSNOG} ]]; then - echo "WARNING: Previous cycle snow file ${FNSNOG} is missing. Snow coverage will not be updated." +if [[ ! -f "${FNSNOG}" ]]; then + echo "WARNING: Previous cycle snow file ${FNSNOG} is missing. Snow coverage will not be updated." else - echo "INFO: Previous cycle snow file is ${FNSNOG}" + echo "INFO: Previous cycle snow file is ${FNSNOG}" fi # If any snow files are missing, don't apply snow in the global_cycle step. -if [[ ! -f ${FNSNOA} ]] || [[ ! -f ${FNSNOG} ]]; then - export FNSNOA=" " - export CYCLVARS="FSNOL=99999.,FSNOS=99999.," +# shellcheck disable=SC2312 +if [[ ! -f "${FNSNOA}" ]] || [[ ! -f "${FNSNOG}" ]]; then + export FNSNOA=" " + export CYCLVARS=FSNOL=99999.,FSNOS=99999., # Set CYCLVARS by checking grib date of current snogrb vs that of prev cycle -elif [[ $(${WGRIB} -4yr "${FNSNOA}" 2>/dev/null | grep -i snowc | awk -F: '{print $3}' | awk -F= '{print $2}') -le \ - $(${WGRIB} -4yr "${FNSNOG}" 2>/dev/null | grep -i snowc | awk -F: '{print $3}' | awk -F= '{print $2}') ]] ; then - export FNSNOA=" " - export CYCLVARS="FSNOL=99999.,FSNOS=99999.," +elif [[ "$(${WGRIB} -4yr "${FNSNOA}" 2> /dev/null | grep -i snowc | awk -F: '{print $3}' | awk -F= '{print $2}')" -le "$(${WGRIB} -4yr "${FNSNOG}" 2> /dev/null | grep -i snowc | awk -F: '{print $3}' | awk -F= '{print $2}')" ]]; then + export FNSNOA=" " + export CYCLVARS=FSNOL=99999.,FSNOS=99999., else - export CYCLVARS="FSNOL=${SNOW_NUDGE_COEFF},${CYCLVARS}" + export CYCLVARS="FSNOL=${SNOW_NUDGE_COEFF},${CYCLVARS}" fi # determine where the input snow restart files come from @@ -99,45 +98,45 @@ else fi # global_cycle executable specific variables -export APRUNCY=${APRUN_CYCLE} -export OMP_NUM_THREADS_CY=${NTHREADS_CYCLE} -export MAX_TASKS_CY=${ntiles} +export APRUNCY="${APRUN_CYCLE}" +export OMP_NUM_THREADS_CY="${NTHREADS_CYCLE}" +export MAX_TASKS_CY="${ntiles}" # Copy fix files required by global_cycle to DATA just once -for (( nn=1; nn <= ntiles; nn++ )); do - cpreq "${FIXgfs}/orog/${CASE}/${CASE}_grid.tile${nn}.nc" "${DATA}/fngrid.00${nn}" - cpreq "${FIXgfs}/orog/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile${nn}.nc" "${DATA}/fnorog.00${nn}" +for ((nn = 1; nn <= ntiles; nn++)); do + cpreq "${FIXgfs}/orog/${CASE}/${CASE}_grid.tile${nn}.nc" "${DATA}/fngrid.00${nn}" + cpreq "${FIXgfs}/orog/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile${nn}.nc" "${DATA}/fnorog.00${nn}" done # Copy the NSST analysis file for global_cycle # There is only a single NSST analysis at the middle of the window # For now use/assume it is the same at the beginning of the window if doing IAU if [[ "${DONST}" == "YES" ]]; then - export NST_FILE=${NST_FILE:-${COMIN_ATMOS_ANALYSIS}/${APREFIX}analysis.dtf.a006.nc} - if [[ -s "${NST_FILE}" ]]; then - cpreq "${NST_FILE}" "${DATA}/dtfanl" - export NST_FILE="dtfanl" - else - export NST_FILE="NULL" - fi + export NST_FILE=${NST_FILE:-${COMIN_ATMOS_ANALYSIS}/${APREFIX}analysis.dtf.a006.nc} + if [[ -s "${NST_FILE}" ]]; then + cpreq "${NST_FILE}" "${DATA}/dtfanl" + export NST_FILE="dtfanl" + else + export NST_FILE="NULL" + fi else - export NST_FILE="NULL" + export NST_FILE="NULL" fi # Collect the dates in the window to update surface restarts gcycle_dates=("${PDY}${cyc}") # Always update surface restarts at middle of window soilinc_fhrs=("${assim_freq}") # increment file at middle of window -LFHR=${assim_freq} -if [[ "${DOIAU:-}" == "YES" ]]; then # Update surface restarts at beginning of window - half_window=$(( assim_freq / 2 )) - soilinc_fhrs+=("${half_window}") - LFHR=-1 - BDATE=$(date --utc -d "${PDY} ${cyc} - ${half_window} hours" +%Y%m%d%H) - gcycle_dates+=("${BDATE}") +LFHR="${assim_freq}" +if [[ "${DOIAU:-}" == "YES" ]]; then # Update surface restarts at beginning of window + half_window=$((assim_freq / 2)) + soilinc_fhrs+=("${half_window}") + LFHR=-1 + BDATE=$(date --utc -d "${PDY} ${cyc} - ${half_window} hours" +%Y%m%d%H) + gcycle_dates+=("${BDATE}") fi # if doing GSI soil anaysis, copy increment file and re-grid it to native model resolution -if [[ "${DO_GSISOILDA}" = "YES" ]]; then +if [[ "${DO_GSISOILDA}" == "YES" ]]; then export COMIN_SOIL_ANALYSIS_MEM="${COMIN_ATMOS_ENKF_ANALYSIS_STAT}" export COMOUT_ATMOS_ANALYSIS_MEM="${COMIN_ATMOS_ANALYSIS}" @@ -149,7 +148,7 @@ if [[ "${DO_GSISOILDA}" = "YES" ]]; then "${REGRIDSH}" export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Soil increment file was not regridded correctly!" + err_exit "Soil increment file was not regridded correctly!" fi fi @@ -157,39 +156,38 @@ fi # Loop over the dates in the window to update the surface restarts for hr in "${!gcycle_dates[@]}"; do - gcycle_date=${gcycle_dates[hr]} - FHR=${soilinc_fhrs[hr]} - echo "Updating surface restarts for ${gcycle_date} ..." + gcycle_date="${gcycle_dates[hr]}" + FHR="${soilinc_fhrs[hr]}" + echo "Updating surface restarts for ${gcycle_date} ..." - datestr="${gcycle_date:0:8}.${gcycle_date:8:2}0000" + datestr="${gcycle_date:0:8}.${gcycle_date:8:2}0000" - if [[ "${DO_GSISOILDA}" == "YES" && "${GCYCLE_DO_SOILINCR}" == ".true." ]]; then - for (( nn=1; nn <= ntiles; nn++ )); do - cpreq "${COMIN_ATMOS_ANALYSIS}/increment.sfc.i00${FHR}.tile${nn}.nc" \ - "${DATA}/soil_xainc.00${nn}" + if [[ "${DO_GSISOILDA}" == "YES" ]] && [[ "${GCYCLE_DO_SOILINCR}" == ".true." ]]; then + for ((nn = 1; nn <= ntiles; nn++)); do + cpreq "${COMIN_ATMOS_ANALYSIS}/increment.sfc.i00${FHR}.tile${nn}.nc" \ + "${DATA}/soil_xainc.00${nn}" done - fi + fi - # Copy inputs from COMIN to DATA - for (( nn=1; nn <= ntiles; nn++ )); do - cpreq "${sfcdata_dir}/${datestr}.${snow_prefix}sfc_data.tile${nn}.nc" "${DATA}/fnbgsi.00${nn}" - cpreq "${DATA}/fnbgsi.00${nn}" "${DATA}/fnbgso.00${nn}" - done + # Copy inputs from COMIN to DATA + for ((nn = 1; nn <= ntiles; nn++)); do + cpreq "${sfcdata_dir}/${datestr}.${snow_prefix}sfc_data.tile${nn}.nc" "${DATA}/fnbgsi.00${nn}" + cpreq "${DATA}/fnbgsi.00${nn}" "${DATA}/fnbgso.00${nn}" + done - "${CYCLESH}" && true - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Unable to update surface data from guess and analysis!" - fi + "${CYCLESH}" && true + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Unable to update surface data from guess and analysis!" + fi - # Copy outputs from DATA to COMOUT - for (( nn=1; nn <= ntiles; nn++ )); do - cpfs "${DATA}/fnbgso.00${nn}" "${COMOUT_ATMOS_RESTART}/${datestr}.sfcanl_data.tile${nn}.nc" - done + # Copy outputs from DATA to COMOUT + for ((nn = 1; nn <= ntiles; nn++)); do + cpfs "${DATA}/fnbgso.00${nn}" "${COMOUT_ATMOS_RESTART}/${datestr}.sfcanl_data.tile${nn}.nc" + done done - ################################################################################ exit "${err}" diff --git a/scripts/exglobal_atmos_tropcy_qc_reloc.sh b/scripts/exglobal_atmos_tropcy_qc_reloc.sh index bd99bf69547..f85bb2adc43 100755 --- a/scripts/exglobal_atmos_tropcy_qc_reloc.sh +++ b/scripts/exglobal_atmos_tropcy_qc_reloc.sh @@ -11,7 +11,7 @@ ############################################################################ # Make sure we are in the $DATA directory -cd "${DATA}" +cd "${DATA}" || exit 1 tmhr=${tmmark:2:2} cdate10=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${tmhr} hours") @@ -19,149 +19,144 @@ cdate10=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${tmhr} hours") NET_uc=${RUN^^} tmmark_uc=${tmmark^^} -iflag=0 if [[ "${RUN}" = ndas ]]; then - if [[ "${DO_RELOCATE}" = NO ]]; then - echo "CENTER PROCESSING TIME FOR NDAS TROPICAL CYCLONE QC IS ${cdate10}" - echo "Output tcvitals files will be copied forward in time to proper \ + if [[ "${DO_RELOCATE}" = NO ]]; then + echo "CENTER PROCESSING TIME FOR NDAS TROPICAL CYCLONE QC IS ${cdate10}" + echo "Output tcvitals files will be copied forward in time to proper \ output file directory path locations" - iflag=1 - else - echo "CENTER PROCESSING TIME FOR ${tmmark_uc} NDAS TROPICAL CYCLONE \ + else + echo "CENTER PROCESSING TIME FOR ${tmmark_uc} NDAS TROPICAL CYCLONE \ RELOCATION IS ${cdate10}" - fi + fi else - echo "CENTER PROCESSING TIME FOR ${tmmark_uc} ${NET_uc} TROPICAL CYCLONE QC/\ + echo "CENTER PROCESSING TIME FOR ${tmmark_uc} ${NET_uc} TROPICAL CYCLONE QC/\ RELOCATION IS ${cdate10}" fi - if [[ "${PROCESS_TROPCY}" = 'YES' ]]; then -#################################### -#################################### -# QC tcvitals for tropical cyclones -#################################### -#################################### - -#echo $PDY - - "${USHgfs}/syndat_qctropcy.sh" "${cdate10}" - errsc=$? - if [[ ${errsc} -ne 0 ]]; then - echo "syndat_qctropcy.sh failed. exit" - exit ${errsc} - fi - - - cd "${COMOUT_OBS}" || exit 1 - pwd - ls -ltr *syndata* - cd "${ARCHSYND}" - pwd;ls -ltr - cat syndat_dateck - cd "${HOMENHC}" - pwd;ls -ltr - cd "${DATA}" + #################################### + #################################### + # QC tcvitals for tropical cyclones + #################################### + #################################### + + #echo $PDY + + "${USHgfs}/syndat_qctropcy.sh" "${cdate10}" + errsc=$? + if [[ ${errsc} -ne 0 ]]; then + echo "syndat_qctropcy.sh failed. exit" + exit "${errsc}" + fi + + cd "${COMOUT_OBS}" || exit 1 + pwd + ls -ltr ./*syndata* + cd "${ARCHSYND}" || exit 1 + pwd + ls -ltr + cat syndat_dateck + cd "${HOMENHC}" || exit 1 + pwd + ls -ltr + cd "${DATA}" || exit 1 else -# Copy null files into "syndata.tcvitals" and "jtwc-fnoc.tcvitals" -# (Note: Only do so if files don't already exist - need because in NDAS this -# script is run twice, first time with DO_RELOCATE=NO, copying these -# files, and second time with PROCESS_TROPCY=NO and thus coming here - -# don't want to wipe out these files) -# + # Copy null files into "syndata.tcvitals" and "jtwc-fnoc.tcvitals" + # (Note: Only do so if files don't already exist - need because in NDAS this + # script is run twice, first time with DO_RELOCATE=NO, copying these + # files, and second time with PROCESS_TROPCY=NO and thus coming here - + # don't want to wipe out these files) + # - if [[ ! -s "${COMOUT_OBS}/${RUN}.t${cyc}z.syndata.tcvitals.${tmmark}" ]]; then - cpfs "/dev/null" "${COMOUT_OBS}/${RUN}.t${cyc}z.syndata.tcvitals.${tmmark}" - fi - if [[ ! -s "${COMOUT_OBS}/${RUN}.t${cyc}z.jtwc-fnoc.tcvitals.${tmmark}" ]]; then - cpfs "/dev/null" "${COMOUT_OBS}/${RUN}.t${cyc}z.jtwc-fnoc.tcvitals.${tmmark}" - fi + if [[ ! -s "${COMOUT_OBS}/${RUN}.t${cyc}z.syndata.tcvitals.${tmmark}" ]]; then + cpfs "/dev/null" "${COMOUT_OBS}/${RUN}.t${cyc}z.syndata.tcvitals.${tmmark}" + fi + if [[ ! -s "${COMOUT_OBS}/${RUN}.t${cyc}z.jtwc-fnoc.tcvitals.${tmmark}" ]]; then + cpfs "/dev/null" "${COMOUT_OBS}/${RUN}.t${cyc}z.jtwc-fnoc.tcvitals.${tmmark}" + fi # endif loop $PROCESS_TROPCY fi - if [[ "${DO_RELOCATE}" = 'YES' ]]; then -################################################### -################################################### -# Relocate tropical cyclones in global sigma guess -################################################### -################################################### - - export MP_LABELIO=${MP_LABELIO:-yes} - "${USHgfs}/tropcy_relocate.sh" "${cdate10}" - export err=$? - - if [[ ${err} -ne 0 ]]; then - err_exit "Failed while updating tropical cyclone data!" - fi - - -# save global sigma guess file(s) possibly updated by tropical cyclone -# relocation processing in COMSP path - qual_last=".${tmmark}" # need this because gfs and gdas don't add $tmmark - # qualifer to end of output sigma guess files - if [[ "${RUN}" == gfs || "${RUN}" == gdas || "${NET}" == cfs ]]; then - qual_last="" - fi - - if [[ ${BKGFREQ} -eq 1 ]]; then - if [[ -s sgm3prep ]]; then - cpfs "sgm3prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgm3prep${qual_last}" - fi - if [[ -s sgm2prep ]]; then - cpfs "sgm2prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgm2prep${qual_last}" - fi - if [[ -s sgm1prep ]]; then - cpfs "sgm1prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgm1prep${qual_last}" - fi - if [[ -s sgesprep ]]; then - cpfs "sgesprep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgesprep${qual_last}" - fi - if [[ -s sgp1prep ]]; then - cpfs "sgp1prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgp1prep${qual_last}" - fi - if [[ -s sgp2prep ]]; then - cpfs "sgp2prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgp2prep${qual_last}" - fi - if [[ -s sgp3prep ]]; then - cpfs "sgp3prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgp3prep${qual_last}" - fi - elif [[ ${BKGFREQ} -eq 3 ]]; then - if [[ -s sgm3prep ]]; then - cpfs "sgm3prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgm3prep${qual_last}" - fi - if [[ -s sgesprep ]]; then - cpfs "sgesprep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgesprep${qual_last}" - fi - if [[ -s sgp3prep ]]; then - cpfs "sgp3prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgp3prep${qual_last}" - fi - fi - -# The existence of ${COMOUT_OBS}/${RUN}.t${cyc}z.tropcy_relocation_status.$tmmark file will tell the -# subsequent PREP processing that RELOCATION processing occurred, if this file -# does not already exist at this point, echo "RECORDS PROCESSED" into it to -# further tell PREP processing that records were processed by relocation and -# the global sigma guess was modified by tropical cyclone relocation -# Note: If ${COMOUT_OBS}/${RUN}.t${cyc}z.tropcy_relocation_status.$tmmark already exists at this -# point it means that it contains the string "NO RECORDS to process" -# and was created by the child script tropcy_relocate.sh because records -# were not processed by relocation and the global sigma guess was NOT -# modified by tropical cyclone relocation (because no tcvitals records -# were found in the relocation step) -# ---------------------------------------------------------------------------- - - if [[ ! -s "${COMOUT_OBS}/${RUN}.t${cyc}z.tropcy_relocation_status.${tmmark}" ]]; then - echo "RECORDS PROCESSED" > "${COMOUT_OBS}/${RUN}.t${cyc}z.tropcy_relocation_status.${tmmark}" - fi + ################################################### + ################################################### + # Relocate tropical cyclones in global sigma guess + ################################################### + ################################################### + + export MP_LABELIO=${MP_LABELIO:-yes} + "${USHgfs}/tropcy_relocate.sh" "${cdate10}" + export err=$? + + if [[ ${err} -ne 0 ]]; then + err_exit "Failed while updating tropical cyclone data!" + fi + + # save global sigma guess file(s) possibly updated by tropical cyclone + # relocation processing in COMSP path + qual_last=".${tmmark}" # need this because gfs and gdas don't add $tmmark + # qualifer to end of output sigma guess files + if [[ "${RUN}" == gfs || "${RUN}" == gdas || "${NET}" == cfs ]]; then + qual_last="" + fi + + if [[ ${BKGFREQ} -eq 1 ]]; then + if [[ -s sgm3prep ]]; then + cpfs "sgm3prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgm3prep${qual_last}" + fi + if [[ -s sgm2prep ]]; then + cpfs "sgm2prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgm2prep${qual_last}" + fi + if [[ -s sgm1prep ]]; then + cpfs "sgm1prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgm1prep${qual_last}" + fi + if [[ -s sgesprep ]]; then + cpfs "sgesprep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgesprep${qual_last}" + fi + if [[ -s sgp1prep ]]; then + cpfs "sgp1prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgp1prep${qual_last}" + fi + if [[ -s sgp2prep ]]; then + cpfs "sgp2prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgp2prep${qual_last}" + fi + if [[ -s sgp3prep ]]; then + cpfs "sgp3prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgp3prep${qual_last}" + fi + elif [[ ${BKGFREQ} -eq 3 ]]; then + if [[ -s sgm3prep ]]; then + cpfs "sgm3prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgm3prep${qual_last}" + fi + if [[ -s sgesprep ]]; then + cpfs "sgesprep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgesprep${qual_last}" + fi + if [[ -s sgp3prep ]]; then + cpfs "sgp3prep" "${COMOUT_OBS}/${RUN}.t${cyc}z.sgp3prep${qual_last}" + fi + fi + + # The existence of ${COMOUT_OBS}/${RUN}.t${cyc}z.tropcy_relocation_status.$tmmark file will tell the + # subsequent PREP processing that RELOCATION processing occurred, if this file + # does not already exist at this point, echo "RECORDS PROCESSED" into it to + # further tell PREP processing that records were processed by relocation and + # the global sigma guess was modified by tropical cyclone relocation + # Note: If ${COMOUT_OBS}/${RUN}.t${cyc}z.tropcy_relocation_status.$tmmark already exists at this + # point it means that it contains the string "NO RECORDS to process" + # and was created by the child script tropcy_relocate.sh because records + # were not processed by relocation and the global sigma guess was NOT + # modified by tropical cyclone relocation (because no tcvitals records + # were found in the relocation step) + # ---------------------------------------------------------------------------- + + if [[ ! -s "${COMOUT_OBS}/${RUN}.t${cyc}z.tropcy_relocation_status.${tmmark}" ]]; then + echo "RECORDS PROCESSED" > "${COMOUT_OBS}/${RUN}.t${cyc}z.tropcy_relocation_status.${tmmark}" + fi # endif loop $DO_RELOCATE fi - ################## END OF SCRIPT ####################### diff --git a/scripts/exglobal_atmos_vminmon.sh b/scripts/exglobal_atmos_vminmon.sh index 79990001009..aa399f58a3f 100755 --- a/scripts/exglobal_atmos_vminmon.sh +++ b/scripts/exglobal_atmos_vminmon.sh @@ -19,8 +19,8 @@ if [[ ! -s "${gsistat}" ]]; then - export err=1 - err_exit "Required GSI statistics file is missing!" + export err=1 + err_exit "Required GSI statistics file is missing!" fi @@ -34,12 +34,11 @@ fi # data into ${cyc} subdirectories (elif condition). #----------------------------------------------------------------------- if [[ -s "${M_TANKverf}/gnorm_data.txt" ]]; then - cpreq "${M_TANKverf}/gnorm_data.txt" gnorm_data.txt + cpreq "${M_TANKverf}/gnorm_data.txt" gnorm_data.txt elif [[ -s "${M_TANKverfM1}/gnorm_data.txt" ]]; then - cpreq "${M_TANKverfM1}/gnorm_data.txt" gnorm_data.txt + cpreq "${M_TANKverfM1}/gnorm_data.txt" gnorm_data.txt fi - #------------------------------------------------------------------ # Run the child sccripts. #------------------------------------------------------------------ @@ -58,9 +57,9 @@ echo "rc_reduct = ${rc_reduct}" ##################################################################### # Postprocessing -err=$(( rc_costs + rc_gnorms + rc_reduct )) +err=$((rc_costs + rc_gnorms + rc_reduct)) export err=${err} if [[ ${err} -ne 0 ]]; then - err_exit "One or more minimization monitor subjobs failed!!" + err_exit "One or more minimization monitor subjobs failed!!" fi diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index c460cc8282c..ab38e4e6e9f 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -11,7 +11,7 @@ if [[ -d "${DATAfcst}" ]]; then rm -rf "${DATAfcst}"; fi rm -rf "${DATAROOT}/${RUN}efcs"*"${PDY:-}${cyc}" ############################################################### -if [[ "${CLEANUP_COM:-YES}" == NO ]] ; then +if [[ "${CLEANUP_COM:-YES}" == NO ]]; then exit 0 fi @@ -36,33 +36,33 @@ function remove_files() { find_exclude_string+="${find_exclude_string} -name ${exclude} -or" done # Chop off any trailing or - find_exclude_string="${find_exclude_string[*]/%-or}" + find_exclude_string="${find_exclude_string[*]/%-or/}" # Remove all regular files that do not match # shellcheck disable=SC2086 if [[ -n "${find_exclude_string}" ]]; then - # String is non-empty → use exclusion - find "${directory}" -type f -not \( ${find_exclude_string} \) -ignore_readdir_race -delete + # String is non-empty → use exclusion + find "${directory}" -type f -not \( ${find_exclude_string} \) -ignore_readdir_race -delete else - # String is empty → no exclusion - find "${directory}" -type f -ignore_readdir_race -delete + # String is empty → no exclusion + find "${directory}" -type f -ignore_readdir_race -delete fi # Remove all symlinks that do not match # shellcheck disable=SC2086 if [[ -n "${find_exclude_string}" ]]; then - # String is non-empty → use exclusion - find "${directory}" -type l -not \( ${find_exclude_string} \) -ignore_readdir_race -delete + # String is non-empty → use exclusion + find "${directory}" -type l -not \( ${find_exclude_string} \) -ignore_readdir_race -delete else - # String is empty → no exclusion - find "${directory}" -type l -ignore_readdir_race -delete + # String is empty → no exclusion + find "${directory}" -type l -ignore_readdir_race -delete fi # Remove any empty directories find "${directory}" -type d -empty -delete } -for (( current_date=first_date; current_date <= last_date; \ - current_date=$(date --utc +%Y%m%d%H -d "${current_date:0:8} ${current_date:8:2} +${assim_freq} hours") )); do +for ((current_date = first_date; current_date <= last_date; \ +current_date = $(date --utc +%Y%m%d%H -d "${current_date:0:8} ${current_date:8:2} +${assim_freq} hours"))); do current_PDY="${current_date:0:8}" current_cyc="${current_date:8:2}" rtofs_dir="${ROTDIR}/rtofs.${current_PDY}" @@ -77,7 +77,7 @@ for (( current_date=first_date; current_date <= last_date; \ IFS=", " read -r -a exclude_list <<< "${exclude_string:-}" remove_files "${COMOUT_TOP}" "${exclude_list[@]:-}" fi - if [[ -d "${rtofs_dir}" ]] && (( current_date < last_rtofs )); then rm -rf "${rtofs_dir}" ; fi + if [[ -d "${rtofs_dir}" ]] && ((current_date < last_rtofs)); then rm -rf "${rtofs_dir}"; fi fi fi done @@ -96,7 +96,7 @@ if [[ "${RUN}" == "gfs" ]]; then fi touch_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${FHMAX_FITS} hours") - while (( touch_date < "${PDY}${cyc}" )); do + while ((touch_date < "${PDY}${cyc}")); do touch_PDY="${touch_date:0:8}" touch_cyc="${touch_date:8:2}" touch_dir="${ROTDIR}/vrfyarch/${RUN}.${touch_PDY}/${touch_cyc}" @@ -110,7 +110,7 @@ fi # Remove $RUN.$rPDY for the older of GDATE or RDATE GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RMOLDSTD:-120} hours") RDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${FHMAX_GFS} hours") -if (( GDATE < RDATE )); then +if ((GDATE < RDATE)); then RDATE=${GDATE} fi deletion_target="${ROTDIR}/${RUN}.${RDATE:0:8}" diff --git a/scripts/exglobal_diag.sh b/scripts/exglobal_diag.sh index e5722fd3205..92ea7bdaa8f 100755 --- a/scripts/exglobal_diag.sh +++ b/scripts/exglobal_diag.sh @@ -20,7 +20,7 @@ # Set environment. # Base variables -GDUMP=${GDUMP:-"gdas"} +GDUMP="${GDUMP:-gdas}" # Utilities export CHGRP_CMD=${CHGRP_CMD:-"chgrp ${group_name:-rstprod}"} @@ -47,75 +47,65 @@ rm -f "${RADSTAT}" "${PCPSTAT}" "${CNVSTAT}" "${OZNSTAT}" # Obs diag GENDIAG=${GENDIAG:-"YES"} DIAG_SUFFIX=${DIAG_SUFFIX:-""} -if [[ "${netcdf_diag}" == ".true." ]] ; then - DIAG_SUFFIX="${DIAG_SUFFIX}.nc4" +if [[ "${netcdf_diag}" == ".true." ]]; then + DIAG_SUFFIX="${DIAG_SUFFIX}.nc4" fi DIAG_COMPRESS=${DIAG_COMPRESS:-"YES"} +COMPRESS_SUFFIX=${COMPRESS_SUFFIX:-""} +if [[ ${DIAG_COMPRESS} == "YES" ]]; then + COMPRESS_SUFFIX="${COMPRESS_SUFFIX}.gz" +fi DIAG_TARBALL=${DIAG_TARBALL:-"YES"} USE_CFP=${USE_CFP:-"NO"} CFP_MP=${CFP_MP:-"NO"} -nm="" -if [[ "${CFP_MP}" == "YES" ]]; then - nm=0 -fi DIAG_DIR=${DIAG_DIR:-${COMOUT_ATMOS_ANALYSIS}/gsidiags} REMOVE_DIAG_DIR=${REMOVE_DIAG_DIR:-"NO"} # Set script / GSI control parameters lrun_subdirs=${lrun_subdirs:-".true."} - ################################################################################ # If requested, generate diagnostic files -if [[ "${GENDIAG}" == "YES" ]] ; then - if [[ "${lrun_subdirs}" == ".true." ]] ; then - for pe in ${DIAG_DIR}/dir.*; do - pedir="$(basename -- "${pe}")" - ${NLN} "${pe}" "${DATA}/${pedir}" - done - else - err_exit "lrun_subdirs must be true. Abort job" - fi - - # Set up lists and variables for various types of diagnostic files. - ntype=3 - - diagtype[0]="conv conv_gps conv_ps conv_pw conv_q conv_sst conv_t conv_tcp conv_uv conv_spd" - diagtype[1]="pcp_ssmi_dmsp pcp_tmi_trmm" - if [[ ${USE_BUILD_GSINFO} == "YES" ]]; then - diagtype[2]=$(cat ${BUILD_GSINFO_DIR}/ozinfo/satellites) - diagtype[3]=$(cat ${BUILD_GSINFO_DIR}/satinfo/satellites) - else - diagtype[2]="sbuv2_n16 sbuv2_n17 sbuv2_n18 sbuv2_n19 gome_metop-a gome_metop-b omi_aura mls30_aura ompsnp_npp ompstc8_npp ompstc8_n20 ompsnp_n20 ompstc8_n21 ompsnp_n21 ompslp_npp gome_metop-c" - diagtype[3]="msu_n14 sndr_g08 sndr_g11 sndr_g12 sndr_g13 sndr_g08_prep sndr_g11_prep sndr_g12_prep sndr_g13_prep sndrd1_g11 sndrd2_g11 sndrd3_g11 sndrd4_g11 sndrd1_g12 sndrd2_g12 sndrd3_g12 sndrd4_g12 sndrd1_g13 sndrd2_g13 sndrd3_g13 sndrd4_g13 sndrd1_g14 sndrd2_g14 sndrd3_g14 sndrd4_g14 sndrd1_g15 sndrd2_g15 sndrd3_g15 sndrd4_g15 amsua_n15 amsua_n16 amsua_n17 amsub_n15 amsub_n16 amsub_n17 hsb_aqua airs_aqua amsua_aqua imgr_g08 imgr_g11 imgr_g12 imgr_g14 imgr_g15 ssmi_f13 ssmi_f15 amsua_n18 amsua_metop-a mhs_n18 mhs_metop-a amsre_low_aqua amsre_mid_aqua amsre_hig_aqua ssmis_f16 ssmis_f17 ssmis_f18 ssmis_f19 ssmis_f20 iasi_metop-a amsua_n19 mhs_n19 seviri_m08 seviri_m09 seviri_m10 seviri_m11 cris_npp cris-fsr_npp cris-fsr_n20 atms_npp atms_n20 amsua_metop-b mhs_metop-b iasi_metop-b avhrr_metop-b avhrr_n18 avhrr_n19 avhrr_metop-a amsr2_gcom-w1 gmi_gpm saphir_meghat ahi_himawari8 abi_g16 abi_g17 amsua_metop-c mhs_metop-c iasi_metop-c avhrr_metop-c viirs-m_npp viirs-m_j1 abi_g18 ahi_himawari9 viirs-m_j2 cris-fsr_n21 atms_n21 abi_g19" - fi - - - diaglist[0]=listcnv - diaglist[1]=listpcp - diaglist[2]=listozn - diaglist[3]=listrad - - diagfile[0]=${CNVSTAT} - diagfile[1]=${PCPSTAT} - diagfile[2]=${OZNSTAT} - diagfile[3]=${RADSTAT} - - numfile[0]=0 - numfile[1]=0 - numfile[2]=0 - numfile[3]=0 - - # Set diagnostic file prefix based on lrun_subdirs variable - if [[ "${lrun_subdirs}" == ".true." ]]; then - prefix=" dir.*/" - else - prefix="pe*" - fi - - if [[ "${USE_CFP}" == "YES" ]]; then - rm -f "${DATA}/diag.sh" "${DATA}/mp_diag.sh" - cat > "${DATA}/diag.sh" << EOFdiag +if [[ "${GENDIAG}" == "YES" ]]; then + if [[ "${lrun_subdirs}" == ".true." ]]; then + for pe in "${DIAG_DIR}/"dir.*; do + pedir="$(basename -- "${pe}")" + ${NLN} "${pe}" "${DATA}/${pedir}" + done + else + err_exit "lrun_subdirs must be true. Abort job" + fi + + # Set up lists and variables for various types of diagnostic files. + diagtype[0]="conv conv_gps conv_ps conv_pw conv_q conv_sst conv_t conv_tcp conv_uv conv_spd" + diagtype[1]="pcp_ssmi_dmsp pcp_tmi_trmm" + if [[ "${USE_BUILD_GSINFO}" == "YES" ]]; then + diagtype[2]=$(cat "${BUILD_GSINFO_DIR}/ozinfo/satellites") + diagtype[3]=$(cat "${BUILD_GSINFO_DIR}/satinfo/satellites") + else + diagtype[2]="sbuv2_n16 sbuv2_n17 sbuv2_n18 sbuv2_n19 gome_metop-a gome_metop-b omi_aura mls30_aura ompsnp_npp ompstc8_npp ompstc8_n20 ompsnp_n20 ompstc8_n21 ompsnp_n21 ompslp_npp gome_metop-c" + diagtype[3]="msu_n14 sndr_g08 sndr_g11 sndr_g12 sndr_g13 sndr_g08_prep sndr_g11_prep sndr_g12_prep sndr_g13_prep sndrd1_g11 sndrd2_g11 sndrd3_g11 sndrd4_g11 sndrd1_g12 sndrd2_g12 sndrd3_g12 sndrd4_g12 sndrd1_g13 sndrd2_g13 sndrd3_g13 sndrd4_g13 sndrd1_g14 sndrd2_g14 sndrd3_g14 sndrd4_g14 sndrd1_g15 sndrd2_g15 sndrd3_g15 sndrd4_g15 amsua_n15 amsua_n16 amsua_n17 amsub_n15 amsub_n16 amsub_n17 hsb_aqua airs_aqua amsua_aqua imgr_g08 imgr_g11 imgr_g12 imgr_g14 imgr_g15 ssmi_f13 ssmi_f15 amsua_n18 amsua_metop-a mhs_n18 mhs_metop-a amsre_low_aqua amsre_mid_aqua amsre_hig_aqua ssmis_f16 ssmis_f17 ssmis_f18 ssmis_f19 ssmis_f20 iasi_metop-a amsua_n19 mhs_n19 seviri_m08 seviri_m09 seviri_m10 seviri_m11 cris_npp cris-fsr_npp cris-fsr_n20 atms_npp atms_n20 amsua_metop-b mhs_metop-b iasi_metop-b avhrr_metop-b avhrr_n18 avhrr_n19 avhrr_metop-a amsr2_gcom-w1 gmi_gpm saphir_meghat ahi_himawari8 abi_g16 abi_g17 amsua_metop-c mhs_metop-c iasi_metop-c avhrr_metop-c viirs-m_npp viirs-m_j1 abi_g18 ahi_himawari9 viirs-m_j2 cris-fsr_n21 atms_n21 abi_g19" + fi + + diaglist[0]=listcnv + diaglist[1]=listpcp + diaglist[2]=listozn + diaglist[3]=listrad + + diagfile[0]="${CNVSTAT}" + diagfile[1]="${PCPSTAT}" + diagfile[2]="${OZNSTAT}" + diagfile[3]="${RADSTAT}" + + # Set diagnostic file prefix based on lrun_subdirs variable + if [[ "${lrun_subdirs}" == ".true." ]]; then + prefix="dir.*/" + else + prefix="pe*" + fi + + rm -f "${DATA}/diag.sh" "${DATA}/mp_diag.sh" + cat > "${DATA}/diag.sh" << EOFdiag #!/bin/sh lrun_subdirs=\$1 binary_diag=\$2 @@ -127,153 +117,127 @@ cyc=\$7 DIAG_COMPRESS=\$8 DIAG_SUFFIX=\$9 if [[ "\${lrun_subdirs}" == ".true." ]]; then - prefix=" dir.*/" + prefix="dir.*/" else - prefix="pe*" + prefix="pe*" fi -file=diag_\${type}_\${string}.\${PDY}\${cyc}\${DIAG_SUFFIX} -if [[ "\${binary_diag}" == ".true." ]]; then - cat \${prefix}\${type}_\${loop}* > \$file -else - ${CATEXEC} -o \$file \${prefix}\${type}_\${loop}* +count=\$(find -L ./ -path "./\${prefix}\${type}_\${loop}*" -type f -printf '.' | wc -c) +file="diag_\${type}_\${string}.\${PDY}\${cyc}\${DIAG_SUFFIX}" +if [[ "\${binary_diag}" == ".true." ]] || [[ "\${count}" -eq 1 ]]; then + cat \${prefix}\${type}_\${loop}* > "\${file}" +else + ${CATEXEC} -o "\${file}" \${prefix}\${type}_\${loop}* fi if [[ "\${DIAG_COMPRESS}" == "YES" ]]; then - ${COMPRESS} "\${file}" + ${COMPRESS} "\${file}" fi EOFdiag - chmod 755 "${DATA}/diag.sh" - fi - - # Collect diagnostic files as a function of loop and type. - # Loop over first and last outer loops to generate innovation - # diagnostic files for indicated observation types (groups) - # - # NOTE: Since we set miter=2 in GSI namelist SETUP, outer - # loop 03 will contain innovations with respect to - # the analysis. Creation of o-a innovation files - # is triggered by write_diag(3)=.true. The setting - # write_diag(1)=.true. turns on creation of o-g - # innovation files. - - loops="01 03" - for loop in ${loops}; do - case ${loop} in - 01) string=ges;; - 03) string=anl;; - *) string=${loop};; - esac - echo "$(date) START loop ${string}" >&2 - n=-1 - while [[ ${n} -lt ${ntype} ]] ;do - n=$(( n + 1 )) - for type in $(echo "${diagtype[n]}"); do - count=$(ls ${prefix}${type}_${loop}* 2>/dev/null | wc -l) - if [[ ${count} -gt 1 ]]; then - if [[ "${USE_CFP}" == "YES" ]]; then - echo "${nm} ${DATA}/diag.sh ${lrun_subdirs} ${binary_diag} ${type} ${loop} ${string} ${PDY} ${cyc} ${DIAG_COMPRESS} ${DIAG_SUFFIX}" | tee -a "${DATA}/mp_diag.sh" - if [[ "${CFP_MP:-"NO"}" == "YES" ]]; then - nm=$((nm+1)) - fi - else - if [[ "${binary_diag}" == ".true." ]]; then - cat ${prefix}${type}_${loop}* > "diag_${type}_${string}.${PDY}${cyc}${DIAG_SUFFIX}" - else - ${CATEXEC} -o "diag_${type}_${string}.${PDY}${cyc}${DIAG_SUFFIX}" "${prefix}${type}_${loop}"* - fi - fi - echo "diag_${type}_${string}.${PDY}${cyc}*" >> "${diaglist[n]}" - numfile[n]=$(expr ${numfile[n]} + 1) - elif [[ ${count} -eq 1 ]]; then - cat ${prefix}${type}_${loop}* > "diag_${type}_${string}.${PDY}${cyc}${DIAG_SUFFIX}" - if [[ "${DIAG_COMPRESS}" == "YES" ]]; then - ${COMPRESS} "diag_${type}_${string}.${PDY}${cyc}${DIAG_SUFFIX}" + chmod 755 "${DATA}/diag.sh" + + # Collect diagnostic files as a function of loop and type. + # Loop over first and last outer loops to generate innovation + # diagnostic files for indicated observation types (groups) + # + # NOTE: Since we set miter=2 in GSI namelist SETUP, outer + # loop 03 will contain innovations with respect to + # the analysis. Creation of o-a innovation files + # is triggered by write_diag(3)=.true. The setting + # write_diag(1)=.true. turns on creation of o-g + # innovation files. + + loops="01 03" + for loop in ${loops}; do + case ${loop} in + 01) string=ges ;; + 03) string=anl ;; + *) string=${loop} ;; + esac + # shellcheck disable=SC2312 + echo "$(date) START loop ${string}" >&2 + for ((n = 0; n < ${#diagtype[@]}; n++)); do + for type in ${diagtype[n]}; do + # shellcheck disable=SC2312 + count=$(find -L ./ -path "./${prefix}${type}_${loop}*" -type f -printf '.' | wc -c) + if [[ "${count}" -gt 0 ]]; then + echo "${DATA}/diag.sh ${lrun_subdirs} ${binary_diag} ${type} ${loop} ${string} ${PDY} ${cyc} ${DIAG_COMPRESS} ${DIAG_SUFFIX}" | tee -a "${DATA}/mp_diag.sh" + echo "diag_${type}_${string}.${PDY}${cyc}${DIAG_SUFFIX}${COMPRESS_SUFFIX}" >> "${diaglist[n]}" fi - echo "diag_${type}_${string}.${PDY}${cyc}*" >> "${diaglist[n]}" - numfile[n]=$(expr "${numfile[n]}" + 1) + done + done + # shellcheck disable=SC2312 + echo "$(date) END loop ${string}" >&2 + done + + # We should already be in $DATA, but extra cd to be sure. + cd "${DATA}" || exit 1 + + export err=0 + if [[ -s "${DATA}/mp_diag.sh" ]]; then + chmod 755 "${DATA}/mp_diag.sh" + "${USHgfs}/run_mpmd.sh" "${DATA}/mp_diag.sh" && true + # Delay err exit to avoid rstprod leakage + err=$? + fi + + # Restrict diagnostic files containing rstprod data + if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then + rlist="conv_gps conv_ps conv_pw conv_q conv_sst conv_t conv_uv saphir" + for rtype in ${rlist}; do + for rfile in *"${rtype}"*; do + if [[ -s "${rfile}" ]]; then + ${CHGRP_CMD} "${rfile}" + fi + done + done + fi + + # Now exit if compression failed + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to compress one or more observation diagnostic files!" + fi + + # If requested, create diagnostic file tarballs + if [[ "${DIAG_TARBALL}" == "YES" ]]; then + # shellcheck disable=SC2312 + echo "$(date) START tar diagnostic files" >&2 + for ((n = 0; n < ${#diagtype[@]}; n++)); do + TAROPTS="-uvf" + if [[ ! -s "${diagfile[n]}" ]]; then + TAROPTS="-cvf" fi - done - done - echo $(date) END loop "${string}" >&2 - done - - # We should already be in $DATA, but extra cd to be sure. - cd "${DATA}" || exit - - # If requested, compress diagnostic files - if [[ "${DIAG_COMPRESS}" == "YES" && "${USE_CFP}" == "NO" ]]; then - echo $(date) START "${COMPRESS}" diagnostic files >&2 - # shellcheck disable=SC2086 - for file in "diag_"*"${PDY}${cyc}${DIAG_SUFFIX}"; do - ${COMPRESS} "${file}" - done - echo "$(date) END ${COMPRESS} diagnostic files" >&2 - fi - - if [[ "${USE_CFP}" == "YES" ]] ; then - chmod 755 "${DATA}/mp_diag.sh" - ncmd=$(wc -l < "${DATA}/mp_diag.sh") - if [[ ${ncmd} -gt 0 ]]; then - if [[ ${ncmd} -lt ${max_tasks_per_node} ]]; then - ncmd_max=${ncmd} - else - ncmd_max=${max_tasks_per_node} - fi - APRUNCFP_DIAG=$(eval echo "${APRUNCFP}") - ${APRUNCFP_DIAG} "${DATA}/mp_diag.sh" - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Failed to compress one or more observation diagnostic files!" - fi - fi - fi - - # Restrict diagnostic files containing rstprod data - if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then - rlist="conv_gps conv_ps conv_pw conv_q conv_sst conv_t conv_uv saphir" - for rtype in ${rlist}; do - for rfile in *"${rtype}"*; do - if [[ -s "${rfile}" ]]; then - ${CHGRP_CMD} "${rfile}" + if [[ -s "${diaglist[n]}" ]]; then + tar "${TAROPTS}" "${diagfile[n]}" -T "${diaglist[n]}" + export err=$? + if [[ ${err} -ne 0 ]]; then + # Delay err_exit to avoid rstprod leakage + err_msg="Unable to create ${diagfile[n]}!" + break + fi fi - done - done - fi - - # If requested, create diagnostic file tarballs - if [[ ${DIAG_TARBALL} == "YES" ]]; then - echo $(date) START tar diagnostic files >&2 - n=-1 - while [[ ${n} -lt ${ntype} ]] ;do - n=$((n+1)) - TAROPTS="-uvf" - if [[ ! -s "${diagfile[n]}" ]]; then - TAROPTS="-cvf" - fi - if [[ ${numfile[n]} -gt 0 ]]; then - tar ${TAROPTS} "${diagfile[n]}" $(cat "${diaglist[n]}") - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "Unable to create ${diagfile[n]}!" + done + + # Restrict CNVSTAT + chmod 750 "${CNVSTAT}" + if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then + ${CHGRP_CMD} "${CNVSTAT}" + fi + + # Restrict RADSTAT + if [[ -s "${RADSTAT}" ]]; then + chmod 750 "${RADSTAT}" + if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then + ${CHGRP_CMD} "${RADSTAT}" fi - fi - done - - # Restrict CNVSTAT - chmod 750 "${CNVSTAT}" - if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then - ${CHGRP_CMD} "${CNVSTAT}" - fi + fi - # Restrict RADSTAT - if [[ -s "${RADSTAT}" ]]; then - chmod 750 "${RADSTAT}" - if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then - ${CHGRP_CMD} "${RADSTAT}" - fi - fi + # Now exit if there was an error + if [[ ${err} -ne 0 ]]; then + err_exit "${err_msg}" + fi - echo "$(date) END tar diagnostic files" >&2 - fi + # shellcheck disable=SC2312 + echo "$(date) END tar diagnostic files" >&2 + fi fi # End diagnostic file generation block - if [[ "${GENDIAG}" == "YES" ]] ################################################################################ diff --git a/scripts/exglobal_extractvars.sh b/scripts/exglobal_extractvars.sh index d735db6310a..952bf83f694 100755 --- a/scripts/exglobal_extractvars.sh +++ b/scripts/exglobal_extractvars.sh @@ -17,36 +17,36 @@ EXTRCTVARO="${USHgfs}/ocnice_extractvars.sh" EXTRCTVARW="${USHgfs}/wave_extractvars.sh" # Set FHMAX_HF_GFS equal to FHMAX_GFS if FHMAX_HF_GFS is greater than FHMAX_GFS -if (( FHMAX_GFS < FHMAX_HF_GFS )); then - export FHMAX_HF_GFS=${FHMAX_GFS} +if ((FHMAX_GFS < FHMAX_HF_GFS)); then + export FHMAX_HF_GFS=${FHMAX_GFS} fi # Set FHOUT_WAV_EXTRACT equal to FHOUT_WAV if FHOUT_WAV is not a factor of FHOUT_WAV_EXTRACT -if (( FHOUT_WAV_EXTRACT % FHOUT_WAV != 0 )); then - FHOUT_WAV_EXTRACT=${FHOUT_WAV} +if ((FHOUT_WAV_EXTRACT % FHOUT_WAV != 0)); then + FHOUT_WAV_EXTRACT=${FHOUT_WAV} fi # Extract variables for atmosphere if [[ "${DO_ATM}" == "YES" ]]; then - ${EXTRCTVARA} "${DATA}/atmos" + ${EXTRCTVARA} "${DATA}/atmos" fi # Extract variables for ocean if [[ "${DO_OCN}" == "YES" ]]; then - export component_name="ocn" - ${EXTRCTVARO} "${DATA}/ocn" "${varlist_ocn_netcdf}" "${ocnres}" "${compress_ocn}" "${FHOUT_OCN_GFS}" "${ARC_RFCST_PROD_OCN}" + export component_name="ocn" + ${EXTRCTVARO} "${DATA}/ocn" "${varlist_ocn_netcdf}" "${ocnres}" "${compress_ocn}" "${FHOUT_OCN_GFS}" "${ARC_RFCST_PROD_OCN}" fi # Extract variables for ice if [[ "${DO_ICE}" == "YES" ]]; then - export component_name="ice" - ${EXTRCTVARO} "${DATA}/ice" "${varlist_ice_netcdf}" "${iceres}" "${compress_ice}" "${FHOUT_ICE_GFS}" "${ARC_RFCST_PROD_ICE}" + export component_name="ice" + ${EXTRCTVARO} "${DATA}/ice" "${varlist_ice_netcdf}" "${iceres}" "${compress_ice}" "${FHOUT_ICE_GFS}" "${ARC_RFCST_PROD_ICE}" fi # Extract variables for wave if [[ "${DO_WAVE}" == "YES" ]]; then - export component_name="wav" - ${EXTRCTVARW} "${DATA}/wav" + export component_name="wav" + ${EXTRCTVARW} "${DATA}/wav" fi exit 0 diff --git a/scripts/exglobal_forecast.sh b/scripts/exglobal_forecast.sh index bbdef1aee20..6367cefdb62 100755 --- a/scripts/exglobal_forecast.sh +++ b/scripts/exglobal_forecast.sh @@ -78,12 +78,12 @@ ####################### # include all subroutines. Executions later. -source "${USHgfs}/forecast_predet.sh" # include functions for variable definition -source "${USHgfs}/forecast_det.sh" # include functions for run type determination -source "${USHgfs}/forecast_postdet.sh" # include functions for variables after run type determination -source "${USHgfs}/parsing_ufs_configure.sh" # include functions for ufs_configure processing +source "${USHgfs}/forecast_predet.sh" # include functions for variable definition +source "${USHgfs}/forecast_det.sh" # include functions for run type determination +source "${USHgfs}/forecast_postdet.sh" # include functions for variables after run type determination +source "${USHgfs}/parsing_ufs_configure.sh" # include functions for ufs_configure processing -source "${USHgfs}/atparse.bash" # include function atparse for parsing @[XYZ] templated files +source "${USHgfs}/atparse.bash" # include function atparse for parsing @[XYZ] templated files # Coupling control switches, for coupling purpose, off by default cpl=${cpl:-.false.} @@ -165,21 +165,21 @@ echo "MAIN: Name lists and model configuration written" # run the executable if [[ "${esmf_profile:-}" == ".true." ]]; then - export ESMF_RUNTIME_PROFILE=ON - export ESMF_RUNTIME_PROFILE_OUTPUT=SUMMARY + export ESMF_RUNTIME_PROFILE=ON + export ESMF_RUNTIME_PROFILE_OUTPUT=SUMMARY fi if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then - unset OMP_NUM_THREADS + unset OMP_NUM_THREADS else - export OMP_NUM_THREADS=${UFS_THREADS:-1} + export OMP_NUM_THREADS=${UFS_THREADS:-1} fi cpreq "${EXECgfs}/${FCSTEXEC}" "${DATA}/" ${APRUN_UFS} "${DATA}/${FCSTEXEC}" 1>&1 2>&2 && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "The forecast failed to run to completion!" + err_exit "The forecast failed to run to completion!" fi FV3_out diff --git a/scripts/exglobal_prep_sfc.sh b/scripts/exglobal_prep_sfc.sh index 961b09e5511..ad0fdfa92a1 100755 --- a/scripts/exglobal_prep_sfc.sh +++ b/scripts/exglobal_prep_sfc.sh @@ -106,13 +106,13 @@ export err=$? #----------------------------------------------------------------------- if [[ ${err} -ne 0 ]]; then - if [[ -s "${BLENDED_ICE_FILE_PREV}" ]]; then - echo "Copy old ice blend file to current directory" - cpfs "${BLENDED_ICE_FILE_PREV}" "${COMOUT_OBS}/${BLENDED_ICE_FILE}" - export err=0 - else - err_exit "FATAL ERROR: CURRENT ICE FILE AND 6-HR OLD ICE FILE MISSING" - fi + if [[ -s "${BLENDED_ICE_FILE_PREV}" ]]; then + echo "Copy old ice blend file to current directory" + cpfs "${BLENDED_ICE_FILE_PREV}" "${COMOUT_OBS}/${BLENDED_ICE_FILE}" + export err=0 + else + err_exit "FATAL ERROR: CURRENT ICE FILE AND 6-HR OLD ICE FILE MISSING" + fi fi #----------------------------------------------------------------------- @@ -122,8 +122,8 @@ fi export SNOW2MDLEXEC="${EXECgfs}/emcsfc_snow2mdl" -LONB_CASE=$((4*${CASE:1})) -LATB_CASE=$((2*${CASE:1})) +LONB_CASE=$((4 * ${CASE:1})) +LATB_CASE=$((2 * ${CASE:1})) export MODEL_SLMASK_FILE=${SLMASK:-${FIXgfs}/am/global_slmask.t${CASE:1}.${LONB_CASE}.${LATB_CASE}.grb} export MODEL_LATITUDE_FILE=${MDL_LATS:-${FIXgfs}/am/global_latitudes.t${CASE:1}.${LONB_CASE}.${LATB_CASE}.grb} @@ -148,14 +148,14 @@ export err=$? #----------------------------------------------------------------------- if [[ ${err} -ne 0 ]]; then - if [[ -s "${MODEL_SNOW_FILE_PREV}" ]]; then - echo "COPY OLD ${CASE} SNOW FILE TO CURRENT DIRECTORY" - cpfs "${MODEL_SNOW_FILE_PREV}" "${COMOUT_OBS}/${MODEL_SNOW_FILE}" - export err=0 - else - err_exit "CURRENT AND 6-HR OLD ${CASE} SNOW MISSING, ABORT!" - fi # check of missing 6-hr snow file -fi # return code check + if [[ -s "${MODEL_SNOW_FILE_PREV}" ]]; then + echo "COPY OLD ${CASE} SNOW FILE TO CURRENT DIRECTORY" + cpfs "${MODEL_SNOW_FILE_PREV}" "${COMOUT_OBS}/${MODEL_SNOW_FILE}" + export err=0 + else + err_exit "CURRENT AND 6-HR OLD ${CASE} SNOW MISSING, ABORT!" + fi # check of missing 6-hr snow file +fi # return code check #----------------------------------------------------------------------- # Create enkf snow file if EUPD_CYC is RUN or BOTH @@ -163,34 +163,34 @@ fi # return code check if [[ "${EUPD_CYC}" = "${RUN}" ]] || [[ "${EUPD_CYC^^}" = "BOTH" ]]; then - LONB_CASE_ENS=$((4*${CASE_ENS:1})) - LATB_CASE_ENS=$((2*${CASE_ENS:1})) - - export MODEL_SLMASK_FILE=${SLMASK_ENKF:-${FIXgfs}/am/global_slmask.t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS}.grb} - export MODEL_LATITUDE_FILE=${MDL_LATS_ENKF:-${FIXgfs}/am/global_latitudes.t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS}.grb} - export MODEL_LONGITUDE_FILE=${MDL_LONS_ENKF:-${FIXgfs}/am/global_longitudes.t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS}.grb} - export GFS_LONSPERLAT_FILE=${LONSPERLAT_ENKF:-${FIXgfs}/am/global_lonsperlat.t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS}.txt} - export MODEL_SNOW_FILE=${RUN}.t${cyc}z.snogrb_t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS} - export MODEL_SNOW_FILE_PREV=${COMINobsproc_PREV}/${RUN}.t${gcyc}z.snogrb_t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS} - - echo "Create enkf snow data." - "${USHgfs}/prep_sfc_snow.sh" - export err=$? - - #----------------------------------------------------------------------- - # Check for errors creating enkf snow. Use 6-hour old data - # as backup. If old data not available, abort. - #----------------------------------------------------------------------- - - if [[ ${err} -ne 0 ]]; then - if [[ -s "${MODEL_SNOW_FILE_PREV}" ]]; then - echo "COPY OLD ENKF SNOW FILE TO CURRENT DIRECTORY" - cpfs "${MODEL_SNOW_FILE_PREV}" "${COMOUT_OBS}/${MODEL_SNOW_FILE}" - export err=0 - else - err_exit "CURRENT AND 6-HR OLD ENKF SNOW MISSING" - fi # check of missing 6-hr snow file - fi # return code check + LONB_CASE_ENS=$((4 * ${CASE_ENS:1})) + LATB_CASE_ENS=$((2 * ${CASE_ENS:1})) + + export MODEL_SLMASK_FILE=${SLMASK_ENKF:-${FIXgfs}/am/global_slmask.t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS}.grb} + export MODEL_LATITUDE_FILE=${MDL_LATS_ENKF:-${FIXgfs}/am/global_latitudes.t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS}.grb} + export MODEL_LONGITUDE_FILE=${MDL_LONS_ENKF:-${FIXgfs}/am/global_longitudes.t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS}.grb} + export GFS_LONSPERLAT_FILE=${LONSPERLAT_ENKF:-${FIXgfs}/am/global_lonsperlat.t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS}.txt} + export MODEL_SNOW_FILE=${RUN}.t${cyc}z.snogrb_t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS} + export MODEL_SNOW_FILE_PREV=${COMINobsproc_PREV}/${RUN}.t${gcyc}z.snogrb_t${CASE_ENS:1}.${LONB_CASE_ENS}.${LATB_CASE_ENS} + + echo "Create enkf snow data." + "${USHgfs}/prep_sfc_snow.sh" + export err=$? + + #----------------------------------------------------------------------- + # Check for errors creating enkf snow. Use 6-hour old data + # as backup. If old data not available, abort. + #----------------------------------------------------------------------- + + if [[ ${err} -ne 0 ]]; then + if [[ -s "${MODEL_SNOW_FILE_PREV}" ]]; then + echo "COPY OLD ENKF SNOW FILE TO CURRENT DIRECTORY" + cpfs "${MODEL_SNOW_FILE_PREV}" "${COMOUT_OBS}/${MODEL_SNOW_FILE}" + export err=0 + else + err_exit "CURRENT AND 6-HR OLD ENKF SNOW MISSING" + fi # check of missing 6-hr snow file + fi # return code check fi # If ENKF runs for RUN diff --git a/ush/preamble.sh b/ush/preamble.sh index fab7d163a93..5572fb5e9f3 100755 --- a/ush/preamble.sh +++ b/ush/preamble.sh @@ -177,6 +177,7 @@ trap "postamble ${_calling_script} ${start_time} \$?" EXIT source "${HOMEgfs}/ush/bash_utils.sh" # Turn on our settings +shopt -s nullglob # Allow null globs instead of treating * as literal export SHELLOPTS declare -xf set_strict declare -xf set_trace From 51e848aabb564ee9657bfbf906d9097ed34de83a Mon Sep 17 00:00:00 2001 From: Cory Martin Date: Wed, 26 Nov 2025 13:38:10 -0500 Subject: [PATCH 04/27] Add support for GCAFS on MSU HPC (#3844) This adds support for GCAFS cycling on MSU HPC (that do not have access to HPSS) by allowing for the extraction of GDAS files from prestaged tarballs on disk. This includes a shell script to run on Mercury/Ursa/other machines to prepare the files that will then need to be copied to the MSU HPC disks. --- dev/ci/cases/pr/C96_gcafs_cycled.yaml | 2 - dev/ci/gitlab-ci-hosts.yml | 4 +- dev/parm/config/gcafs/config.fetch | 7 +- dev/ush/fetch_gdas_for_gcafs.sh | 66 +++++++++++++++++++ parm/fetch/gcafs_ATMA_gdas-anl_msu.yaml.j2 | 12 ++++ parm/fetch/gcafs_ATMA_gdas-dtfanl_msu.yaml.j2 | 12 ++++ ush/python/pygfs/task/fetch.py | 11 ++-- 7 files changed, 103 insertions(+), 11 deletions(-) create mode 100755 dev/ush/fetch_gdas_for_gcafs.sh create mode 100644 parm/fetch/gcafs_ATMA_gdas-anl_msu.yaml.j2 create mode 100644 parm/fetch/gcafs_ATMA_gdas-dtfanl_msu.yaml.j2 diff --git a/dev/ci/cases/pr/C96_gcafs_cycled.yaml b/dev/ci/cases/pr/C96_gcafs_cycled.yaml index 58d9c8ab5f3..a51d4277648 100644 --- a/dev/ci/cases/pr/C96_gcafs_cycled.yaml +++ b/dev/ci/cases/pr/C96_gcafs_cycled.yaml @@ -15,9 +15,7 @@ experiment: yaml: {{ HOMEgfs }}/dev/ci/cases/yamls/gcafs_cycled_defaults_ci.yaml skip_ci_on_hosts: - - orion - gaeac5 - - hercules - awsepicglobalworkflow - ursa diff --git a/dev/ci/gitlab-ci-hosts.yml b/dev/ci/gitlab-ci-hosts.yml index 97001d7cf2f..875cd7c2a32 100644 --- a/dev/ci/gitlab-ci-hosts.yml +++ b/dev/ci/gitlab-ci-hosts.yml @@ -28,10 +28,10 @@ - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48_hybatmsnowDA", "C96C48_hybatmsoilDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96_gcafs_cycled", "C96_gcafs_cycled_noDA", "C96mx100_S2S"] .orion_cases_matrix: &orion_cases - - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C96C48_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96mx100_S2S"] + - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C96C48_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96mx100_S2S", "C96_gcafs_cycled"] .hercules_cases_matrix: &hercules_cases - - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96mx100_S2S"] + - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96mx100_S2S", "C96_gcafs_cycled"] .ursa_cases_matrix: &ursa_cases - caseName: ["C48_ATM", "C48_S2SW", "C48_S2SWA_gefs", "C48mx500_3DVarAOWCDA", "C48mx500_hybAOWCDA", "C96C48_hybatmDA", "C96C48_hybatmsnowDA", "C96C48_hybatmsoilDA", "C96C48_ufsgsi_hybatmDA", "C96C48_ufs_hybatmDA", "C96C48mx500_S2SW_cyc_gfs", "C96_atm3DVar", "C96mx100_S2S"] diff --git a/dev/parm/config/gcafs/config.fetch b/dev/parm/config/gcafs/config.fetch index 7cce1d1be27..bcd65154126 100644 --- a/dev/parm/config/gcafs/config.fetch +++ b/dev/parm/config/gcafs/config.fetch @@ -17,7 +17,12 @@ if [[ "${PDY}${cyc}" -gt "${SDATE}" ]]; then gdas_version="prod" fi export gdas_version - export FETCH_YAML_TMPL_LIST="${PARMgfs}/fetch/${NET}_${APP}_gdas-anl.yaml.j2,${PARMgfs}/fetch/${NET}_${APP}_gdas-dtfanl.yaml.j2" + if [[ "${machine}" == "ORION" || "${machine}" == "HERCULES" ]]; then + FETCH_YAML_TMPL_LIST="${PARMgfs}/fetch/${NET}_${APP}_gdas-anl_msu.yaml.j2,${PARMgfs}/fetch/${NET}_${APP}_gdas-dtfanl_msu.yaml.j2" + else + FETCH_YAML_TMPL_LIST="${PARMgfs}/fetch/${NET}_${APP}_gdas-anl.yaml.j2,${PARMgfs}/fetch/${NET}_${APP}_gdas-dtfanl.yaml.j2" + fi + export FETCH_YAML_TMPL_LIST else # fetch based on first cycle # Determine start type diff --git a/dev/ush/fetch_gdas_for_gcafs.sh b/dev/ush/fetch_gdas_for_gcafs.sh new file mode 100755 index 00000000000..b8e1513493f --- /dev/null +++ b/dev/ush/fetch_gdas_for_gcafs.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# This script fetches GDAS data for GCAFS from HPSS +# and places it in a new tar file. +set -e +set -u + +# Get arguments from command line +if [[ "${#}" -ne 2 ]]; then + echo "Usage: ${0} " + exit 1 +fi +YYYYMMDDHH=${1} +OUTPUT_DIR=${2} +# Create output directory if it doesn't exist +mkdir -p "${OUTPUT_DIR}" +mkdir -p "${OUTPUT_DIR}/tmp" + +# determine GDAS version based on date +if [[ "${YYYYMMDDHH}" -ge "2022112900" ]]; then + gdas_version="v16.3" +elif [[ "${YYYYMMDDHH}" -ge "2022062700" ]]; then + gdas_version="v16.2" +else + gdas_version="prod" +fi + +# break date and time into components +cycle_Y=${YYYYMMDDHH:0:4} +cycle_M=${YYYYMMDDHH:4:2} +cycle_D=${YYYYMMDDHH:6:2} +cyc=${YYYYMMDDHH:8:2} +# cycle_YM is YYYYMM +cycle_YM="${cycle_Y}${cycle_M}" +# PDY is YYYYMMDD +PDY="${cycle_Y}${cycle_M}${cycle_D}" + +# HPSS path for the two tar files +hpss_path_root="/NCEPPROD/hpssprod/runhistory/rh${cycle_Y}/${cycle_YM}/${PDY}" +hpss_file_nc="com_gfs_${gdas_version}_gdas.${PDY}_${cyc}.gdas_nc.tar" +hpss_file_restart="com_gfs_${gdas_version}_gdas.${PDY}_${cyc}.gdas_restart.tar" + +# get the names of the files to extract +atmanl="./gdas.${PDY}/${cyc}/atmos/gdas.t${cyc}z.atmanl.nc" +dtfanl="./gdas.${PDY}/${cyc}/atmos/gdas.t${cyc}z.dtfanl.nc" + +# Fetch the tar files from HPSS +cd "${OUTPUT_DIR}/tmp" + +htar -xvf "${hpss_path_root}/${hpss_file_nc}" "${atmanl}" +htar -xvf "${hpss_path_root}/${hpss_file_restart}" "${dtfanl}" + +# create the output tar files +echo "creating output tar files" +tar cvf "${hpss_file_nc}" "${atmanl}" +tar cvf "${hpss_file_restart}" "${dtfanl}" + +# Move the tar files to the output directory +echo "moving tar files to ${OUTPUT_DIR}" +mv "${hpss_file_nc}" "${OUTPUT_DIR}/" +mv "${hpss_file_restart}" "${OUTPUT_DIR}/" + +# Clean up temporary directory +rm -rf "${OUTPUT_DIR}/tmp" +echo "GDAS data for ${YYYYMMDDHH} has been successfully fetched and stored in ${OUTPUT_DIR}." +# End of script +exit 0 diff --git a/parm/fetch/gcafs_ATMA_gdas-anl_msu.yaml.j2 b/parm/fetch/gcafs_ATMA_gdas-anl_msu.yaml.j2 new file mode 100644 index 00000000000..f7175996d14 --- /dev/null +++ b/parm/fetch/gcafs_ATMA_gdas-anl_msu.yaml.j2 @@ -0,0 +1,12 @@ +{% set cycle_YMDH = current_cycle | to_YMDH %} +{% set cycle_Y = current_cycle | strftime("%Y") %} +{% set cycle_YM = current_cycle | strftime("%Y%m") %} +{% set cycle_YMD = current_cycle | to_YMD %} +{% set cycle_HH = current_cycle | strftime("%H") %} +target: + tarball: "/work2/noaa/global/role-global/data/GCAFS_ExtData/com_gfs_{{ gdas_version }}_gdas.{{ cycle_YMD }}_{{ cycle_HH }}.gdas_nc.tar" + on_hpss: False + contents: + # Atmospheric analysis + - ./gdas.{{ cycle_YMD }}/{{ cycle_HH }}/atmos/gdas.t{{ cycle_HH }}z.atmanl.nc + destination: "{{ ROTDIR }}" diff --git a/parm/fetch/gcafs_ATMA_gdas-dtfanl_msu.yaml.j2 b/parm/fetch/gcafs_ATMA_gdas-dtfanl_msu.yaml.j2 new file mode 100644 index 00000000000..30fe9534a1d --- /dev/null +++ b/parm/fetch/gcafs_ATMA_gdas-dtfanl_msu.yaml.j2 @@ -0,0 +1,12 @@ +{% set cycle_YMDH = current_cycle | to_YMDH %} +{% set cycle_Y = current_cycle | strftime("%Y") %} +{% set cycle_YM = current_cycle | strftime("%Y%m") %} +{% set cycle_YMD = current_cycle | to_YMD %} +{% set cycle_HH = current_cycle | strftime("%H") %} +target: + tarball: "/work2/noaa/global/role-global/data/GCAFS_ExtData/com_gfs_{{ gdas_version }}_gdas.{{ cycle_YMD }}_{{ cycle_HH }}.gdas_restart.tar" + on_hpss: False + contents: + # NSST analysis + - ./gdas.{{ cycle_YMD }}/{{ cycle_HH }}/atmos/gdas.t{{ cycle_HH }}z.dtfanl.nc + destination: "{{ ROTDIR }}" diff --git a/ush/python/pygfs/task/fetch.py b/ush/python/pygfs/task/fetch.py index 5a3b0d09460..cedebc9abaa 100755 --- a/ush/python/pygfs/task/fetch.py +++ b/ush/python/pygfs/task/fetch.py @@ -3,6 +3,7 @@ import os from logging import getLogger from typing import Any, Dict +import tarfile from wxflow import (Task, htar, logit, parse_j2yaml, chdir) @@ -85,12 +86,10 @@ def execute_pull_data(self, fetchdir_set: Dict[str, Any]) -> None: if on_hpss is True: # htar all files in fnames htar_obj = htar.Htar() htar_obj.xvf(tarball, f_names) - else: # tar all files in fnames - raise NotImplementedError("The fetch job does not yet support pulling from local archives") - -# with tarfile.open(dest, "w") as tar: -# for filename in f_names: -# tar.add(filename) + else: # extract from a specified tarball + with tarfile.open(tarball, "r") as tar: + members = [m for m in tar.getmembers() if m.name in f_names] + tar.extractall(members=members) # Verify all data files were extracted missing_files = [] for f in f_names: From 76c5df56fde40fb919e258aa1683cb22f7159290 Mon Sep 17 00:00:00 2001 From: AntonMFernando-NOAA <167725623+AntonMFernando-NOAA@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:49:33 -0500 Subject: [PATCH 05/27] Refactor Stage IC: Move COM and Cycle Variables and Logic from YAML Master Templates to Python Scripts (#3984) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move Jinja logic, com, and cycle vars in stage_ic YAML into Python; simplify YAML to component includes and switches only. - This PR: 1. Implements per‑member COM path computation for gfs, gefs_offline, gefs_rt, gcafs, and enkfgdas cases 2. Move logic, member com paths and general variables to `stage_ic.py` --- dev/ci/cases/pr/C48_S2SWA_gefs_RT.yaml | 3 +- dev/parm/config/gefs/config.base.j2 | 2 +- dev/parm/config/gefs/config.stage_ic.j2 | 2 +- dev/workflow/applications/applications.py | 2 +- dev/workflow/rocoto/gefs_tasks.py | 2 +- dev/workflow/setup_expt.py | 2 +- modulefiles/gw_setup.gaeac6.lua | 2 - parm/stage/aero.yaml.j2 | 18 +- parm/stage/analysis.yaml.j2 | 142 +++--- parm/stage/atmosphere_cold.yaml.j2 | 14 +- parm/stage/atmosphere_cold_RT.yaml.j2 | 12 +- .../atmosphere_ens_perturbations.yaml.j2 | 12 +- parm/stage/atmosphere_nest.yaml.j2 | 26 +- parm/stage/atmosphere_warm.yaml.j2 | 28 +- parm/stage/atmosphere_warm_RT.yaml.j2 | 17 +- parm/stage/ice.yaml.j2 | 31 +- parm/stage/ice_RT.yaml.j2 | 10 +- parm/stage/ice_control_RT.yaml.j2 | 7 +- parm/stage/master_gcafs.yaml.j2 | 127 +---- parm/stage/master_gefs.yaml.j2 | 79 +-- parm/stage/master_gefs_RT.yaml.j2 | 58 +-- parm/stage/master_gfs.yaml.j2 | 99 ---- parm/stage/ocean.yaml.j2 | 14 +- parm/stage/ocean_RT.yaml.j2 | 15 +- parm/stage/ocean_control_RT.yaml.j2 | 13 +- parm/stage/ocean_ens_perturbations.yaml.j2 | 14 +- parm/stage/ocean_mediator.yaml.j2 | 14 +- parm/stage/ocean_rerun.yaml.j2 | 14 +- parm/stage/wave.yaml.j2 | 18 +- scripts/exglobal_stage_ic.py | 49 +- ush/python/pygfs/task/stage_ic.py | 481 +++++++++++++++++- 31 files changed, 654 insertions(+), 673 deletions(-) diff --git a/dev/ci/cases/pr/C48_S2SWA_gefs_RT.yaml b/dev/ci/cases/pr/C48_S2SWA_gefs_RT.yaml index 4bd99d07b00..ba6749b1e03 100644 --- a/dev/ci/cases/pr/C48_S2SWA_gefs_RT.yaml +++ b/dev/ci/cases/pr/C48_S2SWA_gefs_RT.yaml @@ -9,12 +9,13 @@ experiment: nens: 30 interval: 24 start: cold - gefstype: near-real-time + gefstype: gefs-real-time comroot: {{ 'RUNTESTS' | getenv }}/COMROOT expdir: {{ 'RUNTESTS' | getenv }}/EXPDIR idate: 2024112500 edate: 2024112500 yaml: {{ HOMEgfs }}/dev/ci/cases/yamls/gefs_defaults_ci.yaml + icsdir: /lfs/h2/emc/ens/noscrub/eric.sinsky/RETRO_ICS # TODO run on supported platforms once the gefs forecast and subsequent tasks can succeed with RETRO ICs # Add this to run the stage ic job 'icsdir: /lfs/h2/emc/ens/noscrub/eric.sinsky/RETRO_ICS' diff --git a/dev/parm/config/gefs/config.base.j2 b/dev/parm/config/gefs/config.base.j2 index 4e9cf02f71c..56a924fe104 100644 --- a/dev/parm/config/gefs/config.base.j2 +++ b/dev/parm/config/gefs/config.base.j2 @@ -64,7 +64,7 @@ export DO_AWIPS="{{ DO_AWIPS }}" # AWIPS products # Experiment mode (cycled or forecast-only) export MODE="{{ MODE }}" # cycled/forecast-only export DO_TEST_MODE="{{ DO_TEST_MODE }}" # option to change configuration for automated testing -export GEFSTYPE="{{ GEFSTYPE }}" # near-real-time/gefs-offline +export GEFSTYPE="{{ GEFSTYPE }}" # gefs-real-time/gefs-offline #################################################### # DO NOT ADD MACHINE DEPENDENT STUFF BELOW THIS LINE # IF YOU HAVE TO MAKE MACHINE SPECIFIC CHANGES BELOW diff --git a/dev/parm/config/gefs/config.stage_ic.j2 b/dev/parm/config/gefs/config.stage_ic.j2 index 4d6514cf9f4..8693fc170c8 100644 --- a/dev/parm/config/gefs/config.stage_ic.j2 +++ b/dev/parm/config/gefs/config.stage_ic.j2 @@ -11,7 +11,7 @@ export ICSDIR="{{ ICSDIR }}" # User provided ICSDIR; blank if not provided export BASE_IC="{{ BASE_IC }}" # Platform home for staged ICs if [[ ${RUN} == "gefs" ]] ; then - if [[ ${GEFSTYPE} = "near-real-time" ]] ; then + if [[ ${GEFSTYPE} = "gefs-real-time" ]] ; then export STAGE_IC_YAML_TMPL="${PARMgfs}/stage/master_gefs_RT.yaml.j2" elif [[ ${GEFSTYPE} = "gefs-offline" ]] ; then export STAGE_IC_YAML_TMPL="${PARMgfs}/stage/master_gefs.yaml.j2" diff --git a/dev/workflow/applications/applications.py b/dev/workflow/applications/applications.py index e49d053c1e9..3d0ebc6e36c 100644 --- a/dev/workflow/applications/applications.py +++ b/dev/workflow/applications/applications.py @@ -198,7 +198,7 @@ def _get_run_options(self, conf: Configuration) -> Dict[str, Any]: run_options[run]['use_aero_anl'] = run_base.get('USE_AERO_ANL', False) run_options[run]['do_aero_fcst'] = run_base.get('DO_AERO_FCST', False) - if run_base.get('GEFSTYPE', "") == "near-real-time": + if run_base.get('GEFSTYPE', "") == "gefs-real-time": run_options[run]['do_gefs_real_time'] = True elif run_base.get('GEFSTYPE', "") == "gefs-offline": run_options[run]['do_gefs_real_time'] = False diff --git a/dev/workflow/rocoto/gefs_tasks.py b/dev/workflow/rocoto/gefs_tasks.py index 61438252e58..3cd9be020ea 100644 --- a/dev/workflow/rocoto/gefs_tasks.py +++ b/dev/workflow/rocoto/gefs_tasks.py @@ -85,7 +85,7 @@ def fcst(self): if self.app_config.gefstype in ['gefs-offline']: dep_dict = {'type': 'task', 'name': f'{self.run}_stage_ic'} dependencies.append(rocoto.add_dependency(dep_dict)) - elif self.app_config.gefstype in ['near-real-time']: + elif self.app_config.gefstype in ['gefs-real-time']: dep_dict = {'type': 'task', 'name': f'{self.run}_gen_control_ic'} dependencies.append(rocoto.add_dependency(dep_dict)) diff --git a/dev/workflow/setup_expt.py b/dev/workflow/setup_expt.py index 1cd9ad1785c..d668ea415a5 100755 --- a/dev/workflow/setup_expt.py +++ b/dev/workflow/setup_expt.py @@ -244,7 +244,7 @@ def _common_args(parser): parser.add_argument('--interval', help='frequency of forecast (in hours); must be a multiple of 6 or 0 for no forecasts', type=_validate_interval, required=False, default=6) parser.add_argument('--icsdir', help='full path to user initial condition directory', type=str, required=False, default='') - parser.add_argument('--gefstype', help='type of the gefs experiment: near-real-time or gefs-offline', type=str, required=False, default='') + parser.add_argument('--gefstype', help='type of the gefs experiment: gefs-real-time or gefs-offline', type=str, required=False, default='') parser.add_argument('--overwrite', help='overwrite previously created experiment (if it exists)', action='store_true', required=False) return parser diff --git a/modulefiles/gw_setup.gaeac6.lua b/modulefiles/gw_setup.gaeac6.lua index 2967cd13990..942884fd109 100644 --- a/modulefiles/gw_setup.gaeac6.lua +++ b/modulefiles/gw_setup.gaeac6.lua @@ -17,8 +17,6 @@ load("py-jinja2") load("py-pyyaml") load("py-numpy") load("git-lfs") -prepend_path("MODULEPATH", "/ncrc/proj/epic/spack-stack/c6/spack-stack-1.9.2/envs/ue-intel-2023.2.0/install/modulefiles/gcc/12.3.0") -load("gh") unload("cray-libsci") diff --git a/parm/stage/aero.yaml.j2 b/parm/stage/aero.yaml.j2 index 422c67a0852..6a9aca30bbc 100644 --- a/parm/stage/aero.yaml.j2 +++ b/parm/stage/aero.yaml.j2 @@ -1,17 +1,9 @@ aero: mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_CHEM_ANALYSIS_MEM = COMOUT_CHEM_ANALYSIS_MEM_list[imem] %} - - "{{ COMOUT_CHEM_ANALYSIS_MEM }}" - {% endfor %} + - "{{ COMOUT_CHEM_ANALYSIS }}" + link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_CHEM_ANALYSIS_MEM = COMOUT_CHEM_ANALYSIS_MEM_list[imem] %} - {% for ftype in ["aero_varbc_params.tar"] %} - {% if path_exists(ICSDIR ~ "/" ~ COMOUT_CHEM_ANALYSIS_MEM | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} - - ["{{ ICSDIR }}/{{ COMOUT_CHEM_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_CHEM_ANALYSIS_MEM }}"] + {% if path_exists(ICSDIR ~ "/" ~ COMOUT_CHEM_ANALYSIS | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} + - ["{{ ICSDIR }}/{{ COMOUT_CHEM_ANALYSIS | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.aero_varbc_params.tar", + "{{ COMOUT_CHEM_ANALYSIS }}"] {% endif %} - {% endfor %} - {% endfor %} # mem loop diff --git a/parm/stage/analysis.yaml.j2 b/parm/stage/analysis.yaml.j2 index c08a1994682..6494a3a1b8a 100644 --- a/parm/stage/analysis.yaml.j2 +++ b/parm/stage/analysis.yaml.j2 @@ -1,77 +1,99 @@ -{% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS_MEM_list[0] | relpath(ROTDIR)) %} +{# ============================================================================ #} +{# Analysis Staging Configuration #} +{# ============================================================================ #} +{% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR)) %} analysis: mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_ANALYSIS_MEM = COMOUT_ATMOS_ANALYSIS_MEM_list[imem] %} - - "{{ COMOUT_ATMOS_ANALYSIS_MEM }}" - {% endfor %} - link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_ANALYSIS_MEM = COMOUT_ATMOS_ANALYSIS_MEM_list[imem] %} + - "{{ COMOUT_ATMOS_ANALYSIS }}" + link_req: + {# -------------------------------------------------------------------- #} + {# JEDI Atmospheric Variational Data Assimilation #} + {# -------------------------------------------------------------------- #} {% if DO_JEDIATMVAR %} - {% if ATMINC_GRID == "cubed_sphere_grid" %} - {% for itile in range(6) %} - {% if mem == -1 %} - {% if DOIAU %} - {% set ftypes = ["jedi_increment.atm.i003", "jedi_increment.atm.i006", "jedi_increment.atm.i009" ] %} - {% else %} - {% set ftypes = ["jedi_increment.atm.i006" ] %} - {% endif %} - {% else %} - {% if DOIAU_ENKF %} - {% set ftypes = ["recentered_jedi_increment.atm.i003", "recentered_jedi_increment.atm.i006", "recentered_jedi_increment.atm.i009" ] %} - {% else %} - {% set ftypes = ["recentered_jedi_increment.atm.i006" ] %} - {% endif %} - {% endif %} - {% for ftype in ftypes %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}.tile{{ itile+1 }}.nc", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}"] - {% endfor %} - {% endfor %} - {% else %} - {% for ftype in ["increment.atm.i006.nc", "increment.atm.i009.nc", "increment.atm.i003.nc", - "recentered_increment.atm.i006.nc", "recentered_increment.atm.i009.nc", "recentered_increment.atm.i003.nc"] %} - {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}"] - {% endif %} - {% endfor %} - {% endif %} + {# Cubed Sphere Grid Configuration #} + {% if ATMINC_GRID == "cubed_sphere_grid" %} - {% for ftype in ["abias.txt", "abias_air.txt", "abias_int.txt", "abias_pc.txt", "rad_varbc_params.tar"] %} - {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}"] - {% endif %} - {% endfor %} + {% for itile in range(ntiles) %} + + {# Deterministic Member (member == -1) #} + {% if member == -1 %} + {% if DOIAU %} + {% set ftypes = ["jedi_increment.atm.i003", "jedi_increment.atm.i006", "jedi_increment.atm.i009" ] %} + {% else %} + {% set ftypes = ["jedi_increment.atm.i006" ] %} + {% endif %} + + {# Ensemble Members (member != -1) #} + {% else %} + {% if DOIAU_ENKF %} + {% set ftypes = ["recentered_jedi_increment.atm.i003", "recentered_jedi_increment.atm.i006", "recentered_jedi_increment.atm.i009" ] %} + {% else %} + {% set ftypes = ["recentered_jedi_increment.atm.i006" ] %} + {% endif %} + {% endif %} + {% for ftype in ftypes %} + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}.tile{{ itile+1 }}.nc", "{{ COMOUT_ATMOS_ANALYSIS }}"] + {% endfor %} + + {% endfor %} + + {# Non-Cubed Sphere Grid Configuration #} + {% else %} + + {# Atmospheric Increments #} + {% for ftype in ["increment.atm.i006.nc", "increment.atm.i009.nc", "increment.atm.i003.nc", + "recentered_increment.atm.i006.nc", "recentered_increment.atm.i009.nc", "recentered_increment.atm.i003.nc"] %} + {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS }}"] + {% endif %} + {% endfor %} + + {% endif %} + + {# Bias Correction Files #} + {% for ftype in ["abias.txt", "abias_air.txt", "abias_int.txt", "abias_pc.txt", "rad_varbc_params.tar"] %} + {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS }}"] + {% endif %} + {% endfor %} + {# -------------------------------------------------------------------- #} + {# GSI Data Assimilation (Non-JEDI) #} + {# -------------------------------------------------------------------- #} {% else %} - {% for ftype in ["abias.txt", "abias_air.txt", "abias_int.txt", "abias_pc.txt", - "increment.atm.i006.nc", "increment.atm.i009.nc", "increment.atm.i003.nc", "radstat.tar", - "recentered_increment.atm.i006.nc", "recentered_increment.atm.i009.nc", "recentered_increment.atm.i003.nc", "rad_varbc_params.tar"] %} - {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}"] - {% endif %} - {% endfor %} + + {# All GSI Analysis Files #} + {% for ftype in ["abias.txt", "abias_air.txt", "abias_int.txt", "abias_pc.txt", + "increment.atm.i006.nc", "increment.atm.i009.nc", "increment.atm.i003.nc", "radstat.tar", + "recentered_increment.atm.i006.nc", "recentered_increment.atm.i009.nc", "recentered_increment.atm.i003.nc", "rad_varbc_params.tar"] %} + {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS }}"] + {% endif %} + {% endfor %} {% endif %} + {# -------------------------------------------------------------------- #} + {# GSI Soil Analysis (Land DA) #} + {# -------------------------------------------------------------------- #} {% if DO_GSISOILDA %} - {% for ftype in ["increment.sfc.i003.nc", "increment.sfc.i006.nc", "increment.sfc.i009.nc"] %} - {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}"] - {% endif %} - {% endfor %} + {# Surface Increments #} + {% for ftype in ["increment.sfc.i003.nc", "increment.sfc.i006.nc", "increment.sfc.i009.nc"] %} + {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) ~ "/" ~ RUN ~ ".t" ~ current_cycle_HH ~ "z." ~ ftype) %} + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.{{ ftype }}", "{{ COMOUT_ATMOS_ANALYSIS }}"] + {% endif %} + {% endfor %} + + {# Land IAU Increments (Tiled) #} + {% if DO_LAND_IAU %} + {% for itile in range(1,7) %} + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) }}/increment.sfc.tile{{ itile }}.nc", "{{ COMOUT_ATMOS_ANALYSIS }}"] + {% endfor %} + {% endif %} - {% if DO_LAND_IAU %} - {% for itile in range(1,7) %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/increment.sfc.tile{{ itile }}.nc", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}"] - {% endfor %} - {% endif %} {% endif %} - {% endfor %} # mem loop {% endif %} diff --git a/parm/stage/atmosphere_cold.yaml.j2 b/parm/stage/atmosphere_cold.yaml.j2 index c742b28c8d3..40acd8ee080 100644 --- a/parm/stage/atmosphere_cold.yaml.j2 +++ b/parm/stage/atmosphere_cold.yaml.j2 @@ -1,18 +1,10 @@ atmosphere_cold: mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_INPUT_MEM = COMOUT_ATMOS_INPUT_MEM_list[imem] %} - - "{{ COMOUT_ATMOS_INPUT_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_ATMOS_INPUT }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_INPUT_MEM = COMOUT_ATMOS_INPUT_MEM_list[imem] %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_INPUT_MEM | relpath(ROTDIR) }}/gfs_ctrl.nc", "{{ COMOUT_ATMOS_INPUT_MEM }}"] + - ["{{ ICSDIR }}/{{ COMIN_ATMOS_INPUT | relpath(ROTDIR) }}/gfs_ctrl.nc", "{{ COMOUT_ATMOS_INPUT }}"] {% for ftype in ["gfs_data", "sfc_data"] %} {% for ntile in range(1, ntiles + 1) %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_INPUT_MEM | relpath(ROTDIR) }}/{{ ftype }}.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_INPUT_MEM }}"] + - ["{{ ICSDIR }}/{{ COMIN_ATMOS_INPUT | relpath(ROTDIR) }}/{{ ftype }}.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_INPUT }}"] {% endfor %} # ntile {% endfor %} # ftype - {% endfor %} # mem loop diff --git a/parm/stage/atmosphere_cold_RT.yaml.j2 b/parm/stage/atmosphere_cold_RT.yaml.j2 index f6a1c0d118b..7b22285d5c2 100644 --- a/parm/stage/atmosphere_cold_RT.yaml.j2 +++ b/parm/stage/atmosphere_cold_RT.yaml.j2 @@ -1,17 +1,17 @@ atmosphere_cold_RT: mkdir: - - "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}" - - "{{ COMOUT_ATMOS_ANALYSIS_MEM }}" - - "{{ COMOUT_ATMOS_HISTORY_MEM }}" + - "{{ COMOUT_ATMOS_RESTART_PREV }}" + - "{{ COMOUT_ATMOS_ANALYSIS }}" + - "{{ COMOUT_ATMOS_HISTORY }}" link_req: {% set DIAU_cold_previous_file = ICSDIR ~ '/' ~ 'gdas.' ~ previous_cycle_YMD ~ '/' ~ previous_cycle_HH ~ '/analysis/atmos/gdas.t' ~ previous_cycle_HH ~ 'z.ensres_analysis.atm.a003.nc' %} {% set DIAU_cold_current_file = ICSDIR ~ '/' ~ 'gfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/analysis/atmos/gfs.t' ~ current_cycle_HH ~ 'z.increment.atm.i006.nc' %} {% set DIAU_current_file= ICSDIR ~ '/' ~ 'gfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/analysis/atmos/gfs.t' ~ current_cycle_HH ~ 'z.analysis.atm.a006.nc' %} {% set atm_file = ICSDIR ~ '/' ~ 'gdas.' ~ previous_cycle_YMD ~ '/' ~ previous_cycle_HH ~ '/model/atmos/history/gdas.t' ~ previous_cycle_HH ~ 'z.ensres.atm.f006.nc' %} {% set surface_file = ICSDIR ~ '/' ~ 'gdas.' ~ previous_cycle_YMD ~ '/' ~ previous_cycle_HH ~ '/model/atmos/history/gdas.t' ~ previous_cycle_HH ~ 'z.sfc.f003.nc' %} - {% set current_path = COMOUT_ATMOS_ANALYSIS_MEM %} - {% set previous_path = COMOUT_ATMOS_RESTART_PREV_MEM %} - {% set surface_atm_path = COMOUT_ATMOS_HISTORY_MEM %} + {% set current_path = COMOUT_ATMOS_ANALYSIS %} + {% set previous_path = COMOUT_ATMOS_RESTART_PREV %} + {% set surface_atm_path = COMOUT_ATMOS_HISTORY %} - ["{{ DIAU_cold_previous_file }}", "{{ previous_path}}"] - ["{{ DIAU_cold_current_file }}", "{{ current_path }}"] - ["{{ DIAU_current_file }}", "{{ current_path }}"] diff --git a/parm/stage/atmosphere_ens_perturbations.yaml.j2 b/parm/stage/atmosphere_ens_perturbations.yaml.j2 index 8f9fc857042..15496e8d53a 100644 --- a/parm/stage/atmosphere_ens_perturbations.yaml.j2 +++ b/parm/stage/atmosphere_ens_perturbations.yaml.j2 @@ -1,13 +1,5 @@ atmosphere_ens_perturbation: mkdir: - {% for mem in range(first_mem + 1, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_ANALYSIS_MEM = COMOUT_ATMOS_ANALYSIS_MEM_list[imem] %} - - "{{ COMOUT_ATMOS_ANALYSIS_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_ATMOS_ANALYSIS }}" link_req: - {% for mem in range(first_mem + 1, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_ANALYSIS_MEM = COMOUT_ATMOS_ANALYSIS_MEM_list[imem] %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.fv3_perturbation.nc", "{{ COMOUT_ATMOS_ANALYSIS_MEM }}/{{ RUN }}.t{{ current_cycle_HH }}z.increment.atm.i006.nc"] - {% endfor %} # mem loop + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ m_prefix }}.fv3_perturbation.nc", "{{ COMOUT_ATMOS_ANALYSIS }}/{{ RUN }}.t{{ current_cycle_HH }}z.increment.atm.i006.nc"] diff --git a/parm/stage/atmosphere_nest.yaml.j2 b/parm/stage/atmosphere_nest.yaml.j2 index 3ef8a7c3919..b1aeca637b6 100644 --- a/parm/stage/atmosphere_nest.yaml.j2 +++ b/parm/stage/atmosphere_nest.yaml.j2 @@ -2,35 +2,19 @@ atmosphere_nest: {% set ntile = 7 %} {% if EXP_WARM_START == True %} mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_RESTART_PREV_MEM = COMOUT_ATMOS_RESTART_PREV_MEM_list[imem] %} - - "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_ATMOS_RESTART_PREV }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_RESTART_PREV_MEM = COMOUT_ATMOS_RESTART_PREV_MEM_list[imem] %} {% for ftype in ["fv_core.res", "fv_srf_wnd.res", "fv_tracer.res", "phy_data", "sfc_data"] %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.{{ ftype }}.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}/{{ m_prefix }}.{{ ftype }}.nest0{{ ntile-5 }}.tile{{ ntile }}.nc"] + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.{{ ftype }}.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART_PREV }}/{{ m_prefix }}.{{ ftype }}.nest0{{ ntile-5 }}.tile{{ ntile }}.nc"] {% if DO_CA %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.ca_data.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}/{{ m_prefix }}.ca_data.nest0{{ ntile-5 }}.tile{{ ntile }}.nc"] + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.ca_data.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART_PREV }}/{{ m_prefix }}.ca_data.nest0{{ ntile-5 }}.tile{{ ntile }}.nc"] {% endif %} {% endfor %} - {% endfor %} # mem loop {% else %} # cold start mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_INPUT_MEM = COMOUT_ATMOS_INPUT_MEM_list[imem] %} - - "{{ COMOUT_ATMOS_INPUT_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_ATMOS_INPUT }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_INPUT_MEM = COMOUT_ATMOS_INPUT_MEM_list[imem] %} {% for ftype in ["gfs_data", "sfc_data"] %} - - ["{{ COMOUT_ATMOS_INPUT_MEM }}/{{ ftype }}.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_INPUT_MEM }}/{{ ftype }}.nest0{{ ntile-5 }}.tile{{ ntile }}.nc"] + - ["{{ COMOUT_ATMOS_INPUT }}/{{ ftype }}.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_INPUT }}/{{ ftype }}.nest0{{ ntile-5 }}.tile{{ ntile }}.nc"] {% endfor %} - {% endfor %} # mem loop {% endif %} diff --git a/parm/stage/atmosphere_warm.yaml.j2 b/parm/stage/atmosphere_warm.yaml.j2 index 501826391ce..c943fe57545 100644 --- a/parm/stage/atmosphere_warm.yaml.j2 +++ b/parm/stage/atmosphere_warm.yaml.j2 @@ -1,34 +1,24 @@ atmosphere_warm: mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_RESTART_PREV_MEM = COMOUT_ATMOS_RESTART_PREV_MEM_list[imem] %} - - "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}" - {% set COMOUT_ATMOS_RESTART_MEM = COMOUT_ATMOS_RESTART_MEM_list[imem] %} - - "{{ COMOUT_ATMOS_RESTART_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_ATMOS_RESTART_PREV }}" + - "{{ COMOUT_ATMOS_RESTART }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_RESTART_PREV_MEM = COMOUT_ATMOS_RESTART_PREV_MEM_list[imem] %} - {% set COMOUT_ATMOS_RESTART_MEM = COMOUT_ATMOS_RESTART_MEM_list[imem] %} - {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_RESTART_PREV_MEM | relpath(ROTDIR) ~ "/" ~ m_prefix ~ ".atm_stoch.res.nc") %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.atm_stoch.res.nc", "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}"] + {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_RESTART_PREV | relpath(ROTDIR) ~ "/" ~ m_prefix ~ ".atm_stoch.res.nc") %} + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.atm_stoch.res.nc", "{{ COMOUT_ATMOS_RESTART_PREV }}"] {% endif %} # path_exists {% for ftype in ["coupler.res", "fv_core.res.nc"] %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.{{ ftype }}", "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}"] + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.{{ ftype }}", "{{ COMOUT_ATMOS_RESTART_PREV }}"] {% endfor %} {% for ntile in range(1, ntiles + 1) %} {% for ftype in ["fv_core.res", "fv_srf_wnd.res", "fv_tracer.res", "phy_data", "sfc_data"] %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.{{ ftype }}.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}"] + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.{{ ftype }}.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART_PREV }}"] {% endfor %} # ftype {% if DO_CA %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.ca_data.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}"] + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.ca_data.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART_PREV }}"] {% endif %} {% endfor %} # ntile {% for ntile in range(1, ntiles + 1) %} - {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_RESTART_MEM | relpath(ROTDIR) ~ "/" ~ m_prefix ~ ".sfcanl_data.tile" ~ ntile ~ ".nc") %} - - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.sfcanl_data.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART_MEM }}"] + {% if path_exists(ICSDIR ~ "/" ~ COMOUT_ATMOS_RESTART | relpath(ROTDIR) ~ "/" ~ m_prefix ~ ".sfcanl_data.tile" ~ ntile ~ ".nc") %} + - ["{{ ICSDIR }}/{{ COMOUT_ATMOS_RESTART | relpath(ROTDIR) }}/{{ m_prefix }}.sfcanl_data.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_RESTART }}"] {% endif %} # path_exists {% endfor %} # ntile - {% endfor %} # mem loop diff --git a/parm/stage/atmosphere_warm_RT.yaml.j2 b/parm/stage/atmosphere_warm_RT.yaml.j2 index 0aee0d3a2be..afc69d1f5e6 100644 --- a/parm/stage/atmosphere_warm_RT.yaml.j2 +++ b/parm/stage/atmosphere_warm_RT.yaml.j2 @@ -1,14 +1,11 @@ atmosphere_warm_RT: mkdir: - - "{{ COMOUT_ATMOS_RESTART_PREV_MEM }}" - - "{{ COMOUT_ATMOS_ANALYSIS_MEM }}" + - "{{ COMOUT_ATMOS_RESTART_PREV }}" + - "{{ COMOUT_ATMOS_ANALYSIS }}" link_req: # select restart members files (80) specific to the cycle - {% set mid_cyc = ("%02d" | format(previous_cycle_HH | int + half_window)) ~ "0000" %} - {% set restart_mem_path = ICSDIR ~ '/' ~ 'enkfgdas.' ~ previous_cycle_YMD ~ '/' ~ previous_cycle_HH ~ '/' ~ 'mem%03d' | format(gfs_member) ~ '/model/atmos/restart/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '.' %} - {% set increment_mem_path = ICSDIR ~ '/' ~ 'enkfgfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/' ~ 'mem%03d' | format(gfs_member) ~ '/analysis/atmos/enkfgfs.t' ~ current_cycle_HH ~ 'z.' %} - {% set restart_destination_path = COMOUT_ATMOS_RESTART_PREV_MEM %} - {% set increment_destination_path = COMOUT_ATMOS_ANALYSIS_MEM %} + {% set restart_mem_path = ICSDIR ~ '/' ~ 'enkfgdas.' ~ previous_cycle_YMD ~ '/' ~ previous_cycle_HH ~ '/' ~ 'mem%03d' | format(member) ~ '/model/atmos/restart/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '0000.' %} + {% set increment_mem_path = ICSDIR ~ '/' ~ 'enkfgfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/' ~ 'mem%03d' | format(member) ~ '/analysis/atmos/enkfgfs.t' ~ current_cycle_HH ~ 'z.' %} # Include increment files {% for ftype in ["recentered_increment.atm.i003.nc", "recentered_increment.atm.i009.nc", "recentered_increment.atm.i006.nc"] %} @@ -18,15 +15,15 @@ atmosphere_warm_RT: {% if path_exists(ICSDIR) %} {% set file = restart_mem_path ~ 'coupler.res' %} - - ["{{ file }}", "{{ restart_destination_path }}"] + - ["{{ file }}", "{{ COMOUT_ATMOS_RESTART_PREV }}"] {% set file = restart_mem_path ~ 'fv_core.res.nc' %} - - ["{{ file }}", "{{ restart_destination_path }}"] + - ["{{ file }}", "{{ COMOUT_ATMOS_RESTART_PREV }}"] {% set ntiles = 6 %} {% for ftype in ["fv_core.res", "fv_srf_wnd.res", "phy_data", "sfc_data"] %} # Include restart tile files (e.g., .tile1 to .tile6) {% for tile in range(1, ntiles + 1) %} {% set file = restart_mem_path ~ ftype ~ '.tile' ~ tile ~ '.nc' %} - - ["{{ file }}", "{{ restart_destination_path }}"] + - ["{{ file }}", "{{ COMOUT_ATMOS_RESTART_PREV }}"] {% endfor %} {% endfor %} {% endif %} diff --git a/parm/stage/ice.yaml.j2 b/parm/stage/ice.yaml.j2 index 56f5e4eea33..88e8f826ff8 100644 --- a/parm/stage/ice.yaml.j2 +++ b/parm/stage/ice.yaml.j2 @@ -1,35 +1,12 @@ -{% set START_ICE_FROM_ANA = False %} -{% if DO_JEDIOCNVAR == True and RUN == 'gdas' %} - {% set START_ICE_FROM_ANA = True %} -{% endif %} -{% if DO_STARTMEM_FROM_JEDIICE == True and RUN == 'enkfgdas' %} - {% set START_ICE_FROM_ANA = True %} -{% endif %} ice: {% if START_ICE_FROM_ANA == True %} mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ICE_ANALYSIS_MEM = COMOUT_ICE_ANALYSIS_MEM_list[imem] %} - - "{{ COMOUT_ICE_ANALYSIS_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_ICE_ANALYSIS }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ICE_ANALYSIS_MEM = COMOUT_ICE_ANALYSIS_MEM_list[imem] %} - - ["{{ ICSDIR }}/{{ COMOUT_ICE_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.analysis.cice_model.res.nc", "{{ COMOUT_ICE_ANALYSIS_MEM }}"] - {% endfor %} # mem loop + - ["{{ ICSDIR }}/{{ COMOUT_ICE_ANALYSIS | relpath(ROTDIR) }}/{{ m_prefix }}.analysis.cice_model.res.nc", "{{ COMOUT_ICE_ANALYSIS }}"] {% else %} mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ICE_RESTART_PREV_MEM = COMOUT_ICE_RESTART_PREV_MEM_list[imem] %} - - "{{ COMOUT_ICE_RESTART_PREV_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_ICE_RESTART_PREV }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ICE_RESTART_PREV_MEM = COMOUT_ICE_RESTART_PREV_MEM_list[imem] %} - - ["{{ ICSDIR }}/{{ COMOUT_ICE_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.cice_model.res.nc", "{{ COMOUT_ICE_RESTART_PREV_MEM }}"] - {% endfor %} # mem loop + - ["{{ ICSDIR }}/{{ COMOUT_ICE_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.cice_model.res.nc", "{{ COMOUT_ICE_RESTART_PREV }}"] {% endif %} diff --git a/parm/stage/ice_RT.yaml.j2 b/parm/stage/ice_RT.yaml.j2 index e5ceaaea480..6699d8f9c70 100644 --- a/parm/stage/ice_RT.yaml.j2 +++ b/parm/stage/ice_RT.yaml.j2 @@ -1,12 +1,10 @@ ice_RT: mkdir: - - "{{ COMOUT_ICE_ANALYSIS_MEM }}" + - "{{ COMOUT_ICE_ANALYSIS }}" link_req: # select restart members files (80) specific to the cycle - {% set mid_cyc = ("%02d" | format(previous_cycle_HH | int + half_window)) ~ "0000" %} - {% set increment_mem_path = ICSDIR ~ '/' ~ 'enkfgfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/' ~ 'mem%03d' | format(gfs_member) ~ '/analysis/ice/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '.analysis.cice_model.res.nc' %} - {% set increment_destination_path = COMOUT_ICE_ANALYSIS_MEM %} + {% set increment_mem_path = ICSDIR ~ '/' ~ 'enkfgfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/' ~ 'mem%03d' | format(member) ~ '/analysis/ice/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '0000.analysis.cice_model.res.nc' %} + {% set increment_destination_path = COMOUT_ICE_ANALYSIS %} # Include increment files - {% set file = increment_mem_path %} - - ["{{ file }}", "{{ increment_destination_path }}"] + - ["{{ increment_mem_file }}", "{{ COMOUT_ICE_ANALYSIS }}"] diff --git a/parm/stage/ice_control_RT.yaml.j2 b/parm/stage/ice_control_RT.yaml.j2 index ab55623f341..fd335bb646e 100644 --- a/parm/stage/ice_control_RT.yaml.j2 +++ b/parm/stage/ice_control_RT.yaml.j2 @@ -1,8 +1,7 @@ ice_control_RT: mkdir: - - "{{ COMOUT_ICE_ANALYSIS_MEM }}" + - "{{ COMOUT_ICE_ANALYSIS }}" link_req: - {% set mid_cyc = ("%02d" | format(previous_cycle_HH | int + half_window)) ~ "0000" %} - {% set increment_file = ICSDIR ~ '/' ~ 'gfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/analysis/ice/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '.analysis.cice_model.res.nc' %} - {% set increment_destination_path = COMOUT_ICE_ANALYSIS_MEM %} + {% set increment_file = ICSDIR ~ '/' ~ 'gfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/analysis/ice/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '0000.analysis.cice_model.res.nc' %} + {% set increment_destination_path = COMOUT_ICE_ANALYSIS %} - ["{{ increment_file }}", "{{ increment_destination_path }}"] diff --git a/parm/stage/master_gcafs.yaml.j2 b/parm/stage/master_gcafs.yaml.j2 index 5faf462a95c..36cc43f4714 100644 --- a/parm/stage/master_gcafs.yaml.j2 +++ b/parm/stage/master_gcafs.yaml.j2 @@ -26,111 +26,14 @@ # - DO_ATM, DO_OCN, DO_ICE, etc. # For a full list see scripts/exglobal_stage_ic.py ################################################################### +# Initial condition to stage - include components based on switches +################################################################### -# Set cycle date variables -# ------------------------ -{% set half_window = assim_freq // 2 %} -{% set half_window_begin = (-half_window | string + "H") | to_timedelta %} -{% set half_window_end = (half_window | string + "H") | to_timedelta %} -{% if DOIAU and MODE == "cycled" %} - {% set model_start_date_current_cycle = current_cycle | add_to_datetime(half_window_begin) %} -{% else %} - {% set model_start_date_current_cycle = current_cycle %} -{% endif %} - -{% set current_cycle_YMD = current_cycle | to_YMD %} -{% set current_cycle_HH = current_cycle | strftime("%H") %} -{% set previous_cycle_YMD = previous_cycle | to_YMD %} -{% set previous_cycle_HH = previous_cycle | strftime("%H") %} -{% set p_prefix = previous_cycle | strftime("%Y%m%d.%H0000") %} -{% set m_prefix = model_start_date_current_cycle | strftime("%Y%m%d.%H0000") %} - -# Determine restart RUN -# --------------------- # always use GDAS for now, fix once we have staged GCDAS/GCAFS ICs +# TODO: move this to stage_ic.py +# once GCDAS/GCAFS ICs are available {% set rRUN = "gdas" %} -# Set first/last mem for loop -# --------------------------- -{% if RUN == "enkfgdas" %} # Ensemble RUN - {% set first_mem = 1 %} - {% set last_mem = NMEM_ENS %} -{% else %} # Deterministic RUN - {% set first_mem = -1 %} - {% set last_mem = -1 %} -{% endif %} - -# Declare to-be-filled lists of member COM directories -# ---------------------------------------------------- -{% set COMIN_ATMOS_INPUT_MEM_list = [] %} -{% set COMOUT_ATMOS_INPUT_MEM_list = [] %} -{% set COMOUT_ATMOS_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_ATMOS_RESTART_MEM_list = [] %} -{% set COMOUT_ATMOS_ANALYSIS_MEM_list = [] %} -{% set COMOUT_ICE_ANALYSIS_MEM_list = [] %} -{% set COMOUT_ICE_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_OCEAN_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_OCEAN_ANALYSIS_MEM_list = [] %} -{% set COMOUT_MED_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_WAVE_RESTART_PREV_MEM_list = [] %} - -# Construct member COM directory lists -# ------------------------------------ -{% for mem in range(first_mem, last_mem + 1) %} - - {% if mem >= 0 %} - {% set mem_char = 'mem%03d' | format(mem) %} - {% else %} - {% set mem_char = '' %} - {% endif %} - - {% set current_cycle_dict_in = ({ '${ROTDIR}':ROTDIR, - '${RUN}':rRUN, - '${YMD}':current_cycle_YMD, - '${HH}':current_cycle_HH, - '${MEMDIR}': mem_char }) %} - {% set current_cycle_dict = ({ '${ROTDIR}':ROTDIR, - '${RUN}':RUN, - '${YMD}':current_cycle_YMD, - '${HH}':current_cycle_HH, - '${MEMDIR}': mem_char }) %} - {% set previous_cycle_dict = ({ '${ROTDIR}':ROTDIR, - '${RUN}':rRUN, - '${YMD}':previous_cycle_YMD, - '${HH}':previous_cycle_HH, - '${MEMDIR}': mem_char }) %} - - {% set COMIN_ATMOS_INPUT_MEM = COM_ATMOS_INPUT_TMPL | replace_tmpl(current_cycle_dict_in) %} - {% set COMOUT_ATMOS_INPUT_MEM = COM_ATMOS_INPUT_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ATMOS_RESTART_PREV_MEM = COM_ATMOS_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_ATMOS_RESTART_MEM = COM_ATMOS_RESTART_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ATMOS_ANALYSIS_MEM = COM_ATMOS_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ICE_ANALYSIS_MEM = COM_ICE_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ICE_RESTART_PREV_MEM = COM_ICE_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_OCEAN_RESTART_PREV_MEM = COM_OCEAN_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_OCEAN_ANALYSIS_MEM = COM_OCEAN_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_MED_RESTART_PREV_MEM = COM_MED_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_WAVE_RESTART_PREV_MEM = COM_WAVE_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - - # Append the member COM directories - {% do COMIN_ATMOS_INPUT_MEM_list.append(COMIN_ATMOS_INPUT_MEM)%} - {% do COMOUT_ATMOS_INPUT_MEM_list.append(COMOUT_ATMOS_INPUT_MEM)%} - {% do COMOUT_ATMOS_RESTART_PREV_MEM_list.append(COMOUT_ATMOS_RESTART_PREV_MEM)%} - {% do COMOUT_ATMOS_RESTART_MEM_list.append(COMOUT_ATMOS_RESTART_MEM)%} - {% do COMOUT_ATMOS_ANALYSIS_MEM_list.append(COMOUT_ATMOS_ANALYSIS_MEM)%} - {% do COMOUT_ICE_ANALYSIS_MEM_list.append(COMOUT_ICE_ANALYSIS_MEM)%} - {% do COMOUT_ICE_RESTART_PREV_MEM_list.append(COMOUT_ICE_RESTART_PREV_MEM)%} - {% do COMOUT_OCEAN_RESTART_PREV_MEM_list.append(COMOUT_OCEAN_RESTART_PREV_MEM)%} - {% do COMOUT_OCEAN_ANALYSIS_MEM_list.append(COMOUT_OCEAN_ANALYSIS_MEM)%} - {% do COMOUT_MED_RESTART_PREV_MEM_list.append(COMOUT_MED_RESTART_PREV_MEM)%} - {% do COMOUT_WAVE_RESTART_PREV_MEM_list.append(COMOUT_WAVE_RESTART_PREV_MEM)%} - -{% endfor %} - -################################################################### -# Initial condition to stage - include components based on switches -################################################################### - {% if MODE == "cycled" %} {% filter indent(width=4) %} {% include "analysis.yaml.j2" %} @@ -142,25 +45,9 @@ {% include "atmosphere_warm.yaml.j2" %} {% endfilter %} {% else %} # cold start - atmosphere_cold: - mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_ATMOS_INPUT_MEM = COMOUT_ATMOS_INPUT_MEM_list[imem] %} - - "{{ COMOUT_ATMOS_INPUT_MEM }}" - {% endfor %} # mem loop - link: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMIN_ATMOS_INPUT_MEM = COMIN_ATMOS_INPUT_MEM_list[imem] %} - {% set COMOUT_ATMOS_INPUT_MEM = COMOUT_ATMOS_INPUT_MEM_list[imem] %} - - ["{{ ICSDIR }}/{{ COMIN_ATMOS_INPUT_MEM | relpath(ROTDIR) }}/gfs_ctrl.nc", "{{ COMOUT_ATMOS_INPUT_MEM }}"] - {% for ftype in ["gfs_data", "sfc_data"] %} - {% for ntile in range(1, ntiles + 1) %} - - ["{{ ICSDIR }}/{{ COMIN_ATMOS_INPUT_MEM | relpath(ROTDIR) }}/{{ ftype }}.tile{{ ntile }}.nc", "{{ COMOUT_ATMOS_INPUT_MEM }}"] - {% endfor %} # ntile - {% endfor %} # ftype - {% endfor %} # mem loop +{% filter indent(width=4) %} +{% include "atmosphere_cold.yaml.j2" %} +{% endfilter %} {% endif %} {% if DO_NEST %} diff --git a/parm/stage/master_gefs.yaml.j2 b/parm/stage/master_gefs.yaml.j2 index 4b848ba30aa..d778eff23dd 100644 --- a/parm/stage/master_gefs.yaml.j2 +++ b/parm/stage/master_gefs.yaml.j2 @@ -25,81 +25,6 @@ # - COMOUT_ # - DO_ATM, DO_OCN, DO_ICE, etc. # For a full list see scripts/exglobal_stage_ic.py -################################################################### - -# Set cycle variables -# ------------------------ -{% set half_window = assim_freq // 2 %} -{% set half_window_begin = (-half_window | string + "H") | to_timedelta %} -{% set half_window_end = (half_window | string + "H") | to_timedelta %} -{% if DOIAU and MODE == "cycled" %} - {% set model_start_date_current_cycle = current_cycle | add_to_datetime(half_window_begin) %} -{% else %} - {% set model_start_date_current_cycle = current_cycle %} -{% endif %} - -{% set current_cycle_YMD = current_cycle | to_YMD %} -{% set current_cycle_HH = current_cycle | strftime("%H") %} -{% set previous_cycle_YMD = previous_cycle | to_YMD %} -{% set previous_cycle_HH = previous_cycle | strftime("%H") %} -{% set p_prefix = previous_cycle | strftime("%Y%m%d.%H0000") %} -{% set m_prefix = model_start_date_current_cycle | strftime("%Y%m%d.%H0000") %} - -# Set first/last mem for loop -# --------------------------- -{% set first_mem = 0 %} -{% set last_mem = NMEM_ENS %} - -# Declare to-be-filled lists of member COM directories -# ---------------------------------------------------- -{% set COMOUT_ATMOS_INPUT_MEM_list = [] %} -{% set COMOUT_ATMOS_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_ATMOS_ANALYSIS_MEM_list = [] %} -{% set COMOUT_ICE_ANALYSIS_MEM_list = [] %} -{% set COMOUT_ICE_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_OCEAN_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_OCEAN_ANALYSIS_MEM_list = [] %} -{% set COMOUT_MED_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_WAVE_RESTART_PREV_MEM_list = [] %} - -# Construct member COM directory lists -# ------------------------------------ -{% for mem in range(first_mem, last_mem + 1) %} - - {% set current_cycle_dict = ({ '${ROTDIR}':ROTDIR, - '${RUN}':RUN, - '${YMD}':current_cycle_YMD, - '${HH}':current_cycle_HH, - '${MEMDIR}': 'mem%03d' | format(mem) }) %} - {% set previous_cycle_dict = ({ '${ROTDIR}':ROTDIR, - '${RUN}':RUN, - '${YMD}':previous_cycle_YMD, - '${HH}':previous_cycle_HH, - '${MEMDIR}': 'mem%03d' | format(mem) }) %} - - {% set COMOUT_ATMOS_INPUT_MEM = COM_ATMOS_INPUT_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ATMOS_RESTART_PREV_MEM = COM_ATMOS_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_ATMOS_ANALYSIS_MEM = COM_ATMOS_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ICE_ANALYSIS_MEM = COM_ICE_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ICE_RESTART_PREV_MEM = COM_ICE_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_OCEAN_RESTART_PREV_MEM = COM_OCEAN_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_OCEAN_ANALYSIS_MEM = COM_OCEAN_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_MED_RESTART_PREV_MEM = COM_MED_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_WAVE_RESTART_PREV_MEM = COM_WAVE_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - - # Append the member COM directories - {% do COMOUT_ATMOS_INPUT_MEM_list.append(COMOUT_ATMOS_INPUT_MEM)%} - {% do COMOUT_ATMOS_RESTART_PREV_MEM_list.append(COMOUT_ATMOS_RESTART_PREV_MEM)%} - {% do COMOUT_ATMOS_ANALYSIS_MEM_list.append(COMOUT_ATMOS_ANALYSIS_MEM)%} - {% do COMOUT_ICE_ANALYSIS_MEM_list.append(COMOUT_ICE_ANALYSIS_MEM)%} - {% do COMOUT_ICE_RESTART_PREV_MEM_list.append(COMOUT_ICE_RESTART_PREV_MEM)%} - {% do COMOUT_OCEAN_RESTART_PREV_MEM_list.append(COMOUT_OCEAN_RESTART_PREV_MEM)%} - {% do COMOUT_OCEAN_ANALYSIS_MEM_list.append(COMOUT_OCEAN_ANALYSIS_MEM)%} - {% do COMOUT_MED_RESTART_PREV_MEM_list.append(COMOUT_MED_RESTART_PREV_MEM)%} - {% do COMOUT_WAVE_RESTART_PREV_MEM_list.append(COMOUT_WAVE_RESTART_PREV_MEM)%} - -{% endfor %} - ################################################################### # Initial condition to stage - include components based on switches ################################################################### @@ -114,7 +39,7 @@ {% endfilter %} {% endif %} -{% if USE_ATM_ENS_PERTURB_FILES %} +{% if USE_ATM_ENS_PERTURB_FILES and member != 0 %} {% filter indent(width=4) %} {% include "atmosphere_ens_perturbations.yaml.j2" %} {% endfilter %} @@ -135,7 +60,7 @@ {% include "ocean_rerun.yaml.j2" %} {% endfilter %} {% endif %} -{% if USE_OCN_ENS_PERTURB_FILES %} +{% if USE_OCN_ENS_PERTURB_FILES and member != 0 %} {% filter indent(width=4) %} {% include "ocean_ens_perturbations.yaml.j2" %} {% endfilter %} diff --git a/parm/stage/master_gefs_RT.yaml.j2 b/parm/stage/master_gefs_RT.yaml.j2 index 1531422825e..ec6106e2111 100644 --- a/parm/stage/master_gefs_RT.yaml.j2 +++ b/parm/stage/master_gefs_RT.yaml.j2 @@ -25,63 +25,7 @@ # - DO_ATM, DO_OCN, DO_ICE, etc. # For a full list see scripts/exglobal_stage_ic.py ################################################################### -# Set cycle variables -# ------------------------ -{% set half_window = assim_freq // 2 %} -{% set half_window_begin = (-half_window | string + "H") | to_timedelta %} -{% set half_window_end = (half_window | string + "H") | to_timedelta %} -{% set model_start_date_current_cycle = current_cycle %} -{% set current_cycle_YMD = current_cycle | to_YMD %} -{% set current_cycle_HH = current_cycle | strftime("%H") %} -{% set previous_cycle_YMD = previous_cycle | to_YMD %} -{% set previous_cycle_HH = previous_cycle | strftime("%H") %} -{% set p_prefix = previous_cycle | strftime("%Y%m%d.%H0000") %} -{% set m_prefix = model_start_date_current_cycle | strftime("%Y%m%d.%H0000") %} - -################################################################### -# TODO -# this script should run for 30 members (+ control member) -# logic and variables in this script will move to stage_ic.py -# until then this will run only for ENSMEM = 0 (control) -{% set ENSMEM = 0 %} -################################################################### -# Construct member COM directory lists -# ------------------------------------ -{% set current_cycle_dict = ({ '${ROTDIR}':ROTDIR, - '${RUN}':RUN, - '${YMD}':current_cycle_YMD, - '${HH}':current_cycle_HH, - '${MEMDIR}': 'mem%03d' | format(ENSMEM) }) %} -{% set previous_cycle_dict = ({ '${ROTDIR}':ROTDIR, - '${RUN}':RUN, - '${YMD}':previous_cycle_YMD, - '${HH}':previous_cycle_HH, - '${MEMDIR}': 'mem%03d' | format(ENSMEM) }) %} - - -{% set COMOUT_ATMOS_INPUT_MEM = COM_ATMOS_INPUT_TMPL | replace_tmpl(current_cycle_dict) %} -{% set COMOUT_ATMOS_RESTART_PREV_MEM = COM_ATMOS_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} -{% set COMOUT_ATMOS_ANALYSIS_MEM = COM_ATMOS_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} -{% set COMOUT_ATMOS_HISTORY_MEM = COM_ATMOS_HISTORY_TMPL | replace_tmpl(previous_cycle_dict) %} -{% set COMOUT_ICE_ANALYSIS_MEM = COM_ICE_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} -{% set COMOUT_ICE_RESTART_PREV_MEM = COM_ICE_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} -{% set COMOUT_OCEAN_RESTART_PREV_MEM = COM_OCEAN_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} -{% set COMOUT_OCEAN_ANALYSIS_MEM = COM_OCEAN_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} -{% set COMOUT_MED_RESTART_PREV_MEM = COM_MED_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} -{% set COMOUT_WAVE_RESTART_PREV_MEM = COM_WAVE_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} -################################################################### -# Initial condition to stage - include components based on switches -################################################################### -{% set m_index = (current_cycle_HH | int) // 6 %} - -{% if ENSMEM != 0 %} -# GFS members (80) -{% set cyc_ranges = [(range(1, 31) | list), (range(21, 51) | list), (range(41, 71) | list), (range(61, 81) | list) + (range(1, 11) | list)] %} -# select the relevant member for each GEFS member from GFS outputs -{% set gfs_member = cyc_ranges[m_index][(ENSMEM - 1)] %} -{% endif %} - -{% if ENSMEM == 0 %} +{% if member == 0 %} {% include "atmosphere_cold_RT.yaml.j2" %} {% include "ocean_control_RT.yaml.j2" %} {% include "ice_control_RT.yaml.j2" %} diff --git a/parm/stage/master_gfs.yaml.j2 b/parm/stage/master_gfs.yaml.j2 index 35fa21cd8af..c14e6fad4ae 100644 --- a/parm/stage/master_gfs.yaml.j2 +++ b/parm/stage/master_gfs.yaml.j2 @@ -25,105 +25,6 @@ # - COMOUT_ # - DO_ATM, DO_OCN, DO_ICE, etc. # For a full list see scripts/exglobal_stage_ic.py -################################################################### - -# Set cycle date variables -# ------------------------ -{% set half_window = assim_freq // 2 %} -{% set half_window_begin = (-half_window | string + "H") | to_timedelta %} -{% set half_window_end = (half_window | string + "H") | to_timedelta %} -{% if DOIAU and MODE == "cycled" %} - {% set model_start_date_current_cycle = current_cycle | add_to_datetime(half_window_begin) %} -{% else %} - {% set model_start_date_current_cycle = current_cycle %} -{% endif %} - -{% set current_cycle_YMD = current_cycle | to_YMD %} -{% set current_cycle_HH = current_cycle | strftime("%H") %} -{% set previous_cycle_YMD = previous_cycle | to_YMD %} -{% set previous_cycle_HH = previous_cycle | strftime("%H") %} -{% set p_prefix = previous_cycle | strftime("%Y%m%d.%H0000") %} -{% set m_prefix = model_start_date_current_cycle | strftime("%Y%m%d.%H0000") %} - -# Determine restart RUN -# --------------------- -{% set rRUN = RUN %} -{% if RUN == "gfs" %} - {% set rRUN = "gdas" %} -{% endif %} - -# Set first/last mem for loop -# --------------------------- -{% if RUN == "enkfgdas" %} # Ensemble RUN - {% set first_mem = 1 %} - {% set last_mem = NMEM_ENS %} -{% else %} # Deterministic RUN - {% set first_mem = -1 %} - {% set last_mem = -1 %} -{% endif %} - -# Declare to-be-filled lists of member COM directories -# ---------------------------------------------------- -{% set COMOUT_ATMOS_INPUT_MEM_list = [] %} -{% set COMOUT_ATMOS_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_ATMOS_RESTART_MEM_list = [] %} -{% set COMOUT_ATMOS_ANALYSIS_MEM_list = [] %} -{% set COMOUT_ICE_ANALYSIS_MEM_list = [] %} -{% set COMOUT_ICE_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_OCEAN_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_OCEAN_ANALYSIS_MEM_list = [] %} -{% set COMOUT_MED_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_WAVE_RESTART_PREV_MEM_list = [] %} -{% set COMOUT_CHEM_ANALYSIS_MEM_list = [] %} - -# Construct member COM directory lists -# ------------------------------------ -{% for mem in range(first_mem, last_mem + 1) %} - - {% if mem >= 0 %} - {% set mem_char = 'mem%03d' | format(mem) %} - {% else %} - {% set mem_char = '' %} - {% endif %} - - {% set current_cycle_dict = ({ '${ROTDIR}':ROTDIR, - '${RUN}':RUN, - '${YMD}':current_cycle_YMD, - '${HH}':current_cycle_HH, - '${MEMDIR}': mem_char }) %} - {% set previous_cycle_dict = ({ '${ROTDIR}':ROTDIR, - '${RUN}':rRUN, - '${YMD}':previous_cycle_YMD, - '${HH}':previous_cycle_HH, - '${MEMDIR}': mem_char }) %} - - {% set COMOUT_ATMOS_INPUT_MEM = COM_ATMOS_INPUT_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ATMOS_RESTART_PREV_MEM = COM_ATMOS_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_ATMOS_RESTART_MEM = COM_ATMOS_RESTART_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ATMOS_ANALYSIS_MEM = COM_ATMOS_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ICE_ANALYSIS_MEM = COM_ICE_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_ICE_RESTART_PREV_MEM = COM_ICE_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_OCEAN_RESTART_PREV_MEM = COM_OCEAN_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_OCEAN_ANALYSIS_MEM = COM_OCEAN_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - {% set COMOUT_MED_RESTART_PREV_MEM = COM_MED_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_WAVE_RESTART_PREV_MEM = COM_WAVE_RESTART_TMPL | replace_tmpl(previous_cycle_dict) %} - {% set COMOUT_CHEM_ANALYSIS_MEM = COM_CHEM_ANALYSIS_TMPL | replace_tmpl(current_cycle_dict) %} - - # Append the member COM directories - {% do COMOUT_ATMOS_INPUT_MEM_list.append(COMOUT_ATMOS_INPUT_MEM)%} - {% do COMOUT_ATMOS_RESTART_PREV_MEM_list.append(COMOUT_ATMOS_RESTART_PREV_MEM)%} - {% do COMOUT_ATMOS_RESTART_MEM_list.append(COMOUT_ATMOS_RESTART_MEM)%} - {% do COMOUT_ATMOS_ANALYSIS_MEM_list.append(COMOUT_ATMOS_ANALYSIS_MEM)%} - {% do COMOUT_ICE_ANALYSIS_MEM_list.append(COMOUT_ICE_ANALYSIS_MEM)%} - {% do COMOUT_ICE_RESTART_PREV_MEM_list.append(COMOUT_ICE_RESTART_PREV_MEM)%} - {% do COMOUT_OCEAN_RESTART_PREV_MEM_list.append(COMOUT_OCEAN_RESTART_PREV_MEM)%} - {% do COMOUT_OCEAN_ANALYSIS_MEM_list.append(COMOUT_OCEAN_ANALYSIS_MEM)%} - {% do COMOUT_MED_RESTART_PREV_MEM_list.append(COMOUT_MED_RESTART_PREV_MEM)%} - {% do COMOUT_WAVE_RESTART_PREV_MEM_list.append(COMOUT_WAVE_RESTART_PREV_MEM)%} - {% do COMOUT_CHEM_ANALYSIS_MEM_list.append(COMOUT_CHEM_ANALYSIS_MEM)%} - -{% endfor %} - ################################################################### # Initial condition to stage - include components based on switches ################################################################### diff --git a/parm/stage/ocean.yaml.j2 b/parm/stage/ocean.yaml.j2 index 135d5056bc4..5916e69aff7 100644 --- a/parm/stage/ocean.yaml.j2 +++ b/parm/stage/ocean.yaml.j2 @@ -1,18 +1,10 @@ ocean: mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_OCEAN_RESTART_PREV_MEM = COMOUT_OCEAN_RESTART_PREV_MEM_list[imem] %} - - "{{ COMOUT_OCEAN_RESTART_PREV_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_OCEAN_RESTART_PREV }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_OCEAN_RESTART_PREV_MEM = COMOUT_OCEAN_RESTART_PREV_MEM_list[imem] %} - - ["{{ ICSDIR }}/{{ COMOUT_OCEAN_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.MOM.res.nc", "{{ COMOUT_OCEAN_RESTART_PREV_MEM }}"] + - ["{{ ICSDIR }}/{{ COMOUT_OCEAN_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.MOM.res.nc", "{{ COMOUT_OCEAN_RESTART_PREV }}"] {% if OCNRES == "025" %} {% for nn in range(1, 4) %} - - ["{{ ICSDIR }}/{{ COMOUT_OCEAN_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.MOM.res_{{ nn }}.nc", "{{ COMOUT_OCEAN_RESTART_PREV_MEM }}"] + - ["{{ ICSDIR }}/{{ COMOUT_OCEAN_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.MOM.res_{{ nn }}.nc", "{{ COMOUT_OCEAN_RESTART_PREV }}"] {% endfor %} {% endif %} - {% endfor %} # mem loop diff --git a/parm/stage/ocean_RT.yaml.j2 b/parm/stage/ocean_RT.yaml.j2 index 3957388eba4..810f533d20a 100644 --- a/parm/stage/ocean_RT.yaml.j2 +++ b/parm/stage/ocean_RT.yaml.j2 @@ -1,23 +1,20 @@ ocean_RT: mkdir: - - "{{ COMOUT_OCEAN_RESTART_PREV_MEM }}" - - "{{ COMOUT_OCEAN_ANALYSIS_MEM }}" + - "{{ COMOUT_OCEAN_RESTART_PREV }}" + - "{{ COMOUT_OCEAN_ANALYSIS }}" link_req: # select restart members files (80) specific to the cycle - {% set mid_cyc = ("%02d" | format(previous_cycle_HH | int + half_window)) ~ "0000" %} - {% set restart_mem_path = ICSDIR ~ '/' ~ 'enkfgdas.' ~ previous_cycle_YMD ~ '/' ~ previous_cycle_HH ~ '/' ~ 'mem%03d' | format(gfs_member) ~ '/model/ocean/restart/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '.' %} - {% set increment_mem_path = ICSDIR ~ '/' ~ 'enkfgfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/' ~ 'mem%03d' | format(gfs_member) ~ '/analysis/ocean/enkfgfs.t' ~ current_cycle_HH ~ 'z.ocninc.nc' %} - {% set restart_destination_path = COMOUT_OCEAN_RESTART_PREV_MEM %} - {% set increment_destination_path = COMOUT_OCEAN_ANALYSIS_MEM %} + {% set restart_mem_path = ICSDIR ~ '/' ~ 'enkfgdas.' ~ previous_cycle_YMD ~ '/' ~ previous_cycle_HH ~ '/' ~ 'mem%03d' | format(member) ~ '/model/ocean/restart/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '0000.' %} + {% set increment_mem_path = ICSDIR ~ '/' ~ 'enkfgfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/' ~ 'mem%03d' | format(member) ~ '/analysis/ocean/enkfgfs.t' ~ current_cycle_HH ~ 'z.ocninc.nc' %} # Include increment files {% set file = increment_mem_path %} - - ["{{ file }}", "{{ increment_destination_path }}"] + - ["{{ file }}", "{{ COMOUT_OCEAN_ANALYSIS }}"] {% if path_exists(ICSDIR) %} {% for ftype in ["MOM.res.nc", "MOM.res_1.nc", "MOM.res_2.nc", "MOM.res_3.nc"] %} # Include base file for restart files {% set file = restart_mem_path ~ ftype %} - - ["{{ file }}", "{{ restart_destination_path }}"] + - ["{{ file }}", "{{ COMOUT_OCEAN_RESTART_PREV }}"] {% endfor %} {% endif %} diff --git a/parm/stage/ocean_control_RT.yaml.j2 b/parm/stage/ocean_control_RT.yaml.j2 index 249c8940650..6e5f654459d 100644 --- a/parm/stage/ocean_control_RT.yaml.j2 +++ b/parm/stage/ocean_control_RT.yaml.j2 @@ -1,18 +1,15 @@ ocean_control_RT: mkdir: - - "{{ COMOUT_OCEAN_RESTART_PREV_MEM }}" - - "{{ COMOUT_OCEAN_ANALYSIS_MEM }}" + - "{{ COMOUT_OCEAN_RESTART_PREV }}" + - "{{ COMOUT_OCEAN_ANALYSIS }}" link_req: - {% set mid_cyc = ("%02d" | format(previous_cycle_HH | int + half_window)) ~ "0000" %} - {% set restart_path = ICSDIR ~ '/' ~ 'gdas.' ~ previous_cycle_YMD ~ '/' ~ previous_cycle_HH ~ '/model/ocean/restart/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '.' %} + {% set restart_path = ICSDIR ~ '/' ~ 'gdas.' ~ previous_cycle_YMD ~ '/' ~ previous_cycle_HH ~ '/model/ocean/restart/' ~ previous_cycle_YMD ~ '.' ~ mid_cyc ~ '0000.' %} {% set increment_file = ICSDIR ~ '/' ~ 'gfs.' ~ current_cycle_YMD ~ '/' ~ current_cycle_HH ~ '/analysis/ocean/gfs.t' ~ current_cycle_HH ~ 'z.ocninc.nc' %} - {% set restart_destination_path = COMOUT_OCEAN_RESTART_PREV_MEM %} - {% set increment_destination_path = COMOUT_OCEAN_ANALYSIS_MEM %} # Restart increment files {% for ftype in ["MOM.res.nc", "MOM.res_1.nc", "MOM.res_2.nc", "MOM.res_3.nc"] %} {% set file = restart_path ~ ftype %} - - ["{{ file }}", "{{ restart_destination_path }}"] + - ["{{ file }}", "{{ COMOUT_OCEAN_RESTART_PREV }}"] {% endfor %} # Include increment files - - ["{{ increment_file }}", "{{ increment_destination_path }}"] + - ["{{ increment_file }}", "{{ COMOUT_OCEAN_ANALYSIS }}"] diff --git a/parm/stage/ocean_ens_perturbations.yaml.j2 b/parm/stage/ocean_ens_perturbations.yaml.j2 index d551d89694f..000dab1aa0c 100644 --- a/parm/stage/ocean_ens_perturbations.yaml.j2 +++ b/parm/stage/ocean_ens_perturbations.yaml.j2 @@ -1,14 +1,6 @@ ocean_ens_perturbation: mkdir: - {% for mem in range(first_mem + 1, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_OCEAN_ANALYSIS_MEM = COMOUT_OCEAN_ANALYSIS_MEM_list[imem] %} - - "{{ COMOUT_OCEAN_ANALYSIS_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_OCEAN_ANALYSIS }}" link_req: - {% for mem in range(first_mem + 1, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_OCEAN_ANALYSIS_MEM = COMOUT_OCEAN_ANALYSIS_MEM_list[imem] %} - - ["{{ ICSDIR }}/{{ COMOUT_OCEAN_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.mom6_perturbation.nc", - "{{ COMOUT_OCEAN_ANALYSIS_MEM }}/{{ RUN }}.t{{ current_cycle_HH }}z.mom6_increment.i006.nc"] - {% endfor %} # mem loop + - ["{{ ICSDIR }}/{{ COMOUT_OCEAN_ANALYSIS | relpath(ROTDIR) }}/{{ m_prefix }}.mom6_perturbation.nc", + "{{ COMOUT_OCEAN_ANALYSIS }}/{{ RUN }}.t{{ current_cycle_HH }}z.mom6_increment.i006.nc"] diff --git a/parm/stage/ocean_mediator.yaml.j2 b/parm/stage/ocean_mediator.yaml.j2 index e72f973ac54..6a60a933df4 100644 --- a/parm/stage/ocean_mediator.yaml.j2 +++ b/parm/stage/ocean_mediator.yaml.j2 @@ -1,15 +1,7 @@ -{% if path_exists(ICSDIR ~ "/" ~ COMOUT_MED_RESTART_PREV_MEM_list[0] | relpath(ROTDIR) ~ "/" ~ m_prefix ~ ".ufs.cpld.cpl.r.nc") %} +{% if path_exists(ICSDIR ~ "/" ~ COMOUT_MED_RESTART_PREV | relpath(ROTDIR) ~ "/" ~ m_prefix ~ ".ufs.cpld.cpl.r.nc") %} ocean_mediator: mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_MED_RESTART_PREV_MEM = COMOUT_MED_RESTART_PREV_MEM_list[imem] %} - - "{{ COMOUT_MED_RESTART_PREV_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_MED_RESTART_PREV }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_MED_RESTART_PREV_MEM = COMOUT_MED_RESTART_PREV_MEM_list[imem] %} - - ["{{ ICSDIR }}/{{ COMOUT_MED_RESTART_PREV_MEM | relpath(ROTDIR) }}/{{ m_prefix }}.ufs.cpld.cpl.r.nc", "{{ COMOUT_MED_RESTART_PREV_MEM }}"] - {% endfor %} # mem loop + - ["{{ ICSDIR }}/{{ COMOUT_MED_RESTART_PREV | relpath(ROTDIR) }}/{{ m_prefix }}.ufs.cpld.cpl.r.nc", "{{ COMOUT_MED_RESTART_PREV }}"] {% endif %} # path exists diff --git a/parm/stage/ocean_rerun.yaml.j2 b/parm/stage/ocean_rerun.yaml.j2 index c64fe82be4c..9ef484b40f7 100644 --- a/parm/stage/ocean_rerun.yaml.j2 +++ b/parm/stage/ocean_rerun.yaml.j2 @@ -1,14 +1,6 @@ ocean_rerun: mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_OCEAN_ANALYSIS_MEM = COMOUT_OCEAN_ANALYSIS_MEM_list[imem] %} - - "{{ COMOUT_OCEAN_ANALYSIS_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_OCEAN_ANALYSIS }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_OCEAN_ANALYSIS_MEM = COMOUT_OCEAN_ANALYSIS_MEM_list[imem] %} - - ["{{ ICSDIR }}/{{ COMOUT_OCEAN_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.mom6_increment.i006.nc", - "{{ COMOUT_OCEAN_ANALYSIS_MEM }}/"] - {% endfor %} # mem loop + - ["{{ ICSDIR }}/{{ COMOUT_OCEAN_ANALYSIS | relpath(ROTDIR) }}/{{ RUN }}.t{{ current_cycle_HH }}z.mom6_increment.i006.nc", {{ COMOUT_OCEAN_ANALYSIS }}] + diff --git a/parm/stage/wave.yaml.j2 b/parm/stage/wave.yaml.j2 index f7d42a9a9cf..ecb3ff50781 100644 --- a/parm/stage/wave.yaml.j2 +++ b/parm/stage/wave.yaml.j2 @@ -1,20 +1,12 @@ wave: mkdir: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_WAVE_RESTART_PREV_MEM = COMOUT_WAVE_RESTART_PREV_MEM_list[imem] %} - - "{{ COMOUT_WAVE_RESTART_PREV_MEM }}" - {% endfor %} # mem loop + - "{{ COMOUT_WAVE_RESTART_PREV }}" link_req: - {% for mem in range(first_mem, last_mem + 1) %} - {% set imem = mem - first_mem %} - {% set COMOUT_WAVE_RESTART_PREV_MEM = COMOUT_WAVE_RESTART_PREV_MEM_list[imem] %} - {% set ww3_file = ICSDIR ~ "/" ~ COMOUT_WAVE_RESTART_PREV_MEM | relpath(ROTDIR) ~ "/" ~ m_prefix ~ ".restart.ww3" %} - {% if path_exists(ww3_file ~ ".nc") %} - - ["{{ ww3_file }}.nc" , "{{ COMOUT_WAVE_RESTART_PREV_MEM }}/{{ m_prefix }}.restart.ww3.nc"] + {% set ww3_file = ICSDIR ~ "/" ~ COMOUT_WAVE_RESTART_PREV | relpath(ROTDIR) ~ "/" ~ m_prefix ~ ".restart.ww3" %} + {% if path_exists(ww3_file ~ ".nc") %} + - ["{{ ww3_file }}.nc" , "{{ COMOUT_WAVE_RESTART_PREV }}/{{ m_prefix }}.restart.ww3.nc"] {% else %} {% if path_exists(ww3_file) %} - - ["{{ ww3_file }}" , "{{ COMOUT_WAVE_RESTART_PREV_MEM }}/{{ m_prefix }}.restart.ww3"] + - ["{{ ww3_file }}" , "{{ COMOUT_WAVE_RESTART_PREV }}/{{ m_prefix }}.restart.ww3"] {% endif %} {% endif %} - {% endfor %} # mem loop diff --git a/scripts/exglobal_stage_ic.py b/scripts/exglobal_stage_ic.py index 3c8fc230c40..9504faebed2 100755 --- a/scripts/exglobal_stage_ic.py +++ b/scripts/exglobal_stage_ic.py @@ -3,7 +3,7 @@ import os from pygfs.task.stage_ic import Stage -from wxflow import AttrDict, Logger, cast_strdict_as_dtypedict, logit +from wxflow import Logger, cast_strdict_as_dtypedict, logit # Initialize root logger logger = Logger(level=os.environ.get("LOGGING_LEVEL", "DEBUG"), colored_log=True) @@ -13,7 +13,6 @@ def main(): config = cast_strdict_as_dtypedict(os.environ) - # Set a default value for ATMINC_GRID if it is not in the environment # This MUST be done *before* config is passed to the Stage constructor. config.setdefault('ATMINC_GRID', '') @@ -21,35 +20,23 @@ def main(): # Instantiate the Stage object stage = Stage(config) - # Pull out all the configuration keys needed to run stage job - keys = ['RUN', 'MODE', 'EXP_WARM_START', 'NMEM_ENS', - 'assim_freq', 'current_cycle', 'previous_cycle', - 'ROTDIR', 'ICSDIR', 'STAGE_IC_YAML_TMPL', 'DO_JEDIATMVAR', 'ATMINC_GRID', - 'OCNRES', 'waveGRD', 'ntiles', 'DOIAU', - 'DO_JEDIOCNVAR', 'DO_STARTMEM_FROM_JEDIICE', - 'DO_WAVE', 'DO_OCN', 'DO_ICE', 'DO_NEST', 'DO_CA', 'DO_AERO_ANL', - 'USE_ATM_ENS_PERTURB_FILES', 'USE_OCN_ENS_PERTURB_FILES', 'DO_GSISOILDA', 'DO_LAND_IAU'] - - # Only pull the DOIAU_ENKF key if this is a gfs staging job - if stage.task_config['NET'] == 'gfs': - keys.append('DOIAU_ENKF') - - stage_dict = AttrDict() - for key in keys: - # Make sure OCNRES is three digits - if key == "OCNRES": - stage.task_config.OCNRES = f"{stage.task_config.OCNRES :03d}" - stage_dict[key] = stage.task_config[key] - - # Also import all COM* directory and template variables - for key in stage.task_config.keys(): - if key.startswith("COM"): - stage_dict[key] = stage.task_config[key] - if "ENSMEM" in stage.task_config: - stage_dict["ENSMEM"] = stage.task_config["ENSMEM"] - - # Stage ICs - stage.execute_stage(stage_dict) + # Create staging dictionary with all necessary variables + stage_dict = stage.create_stage_dict() + + # Loop through members and stage ICs for each + for member in stage_dict.member_list: + logger.info(f"Staging initial conditions for member: {member}") + + # Get member-specific COM paths + member_com_paths = stage.get_member_com_paths(stage_dict, member) + + # Create member-specific staging dict to avoid modifying base stage_dict + stage_mem_dict = stage_dict.deepcopy() + stage_mem_dict.update(member_com_paths) + stage_mem_dict.update({'member': member}) + + # Execute staging + stage.execute_stage(stage_mem_dict) if __name__ == '__main__': diff --git a/ush/python/pygfs/task/stage_ic.py b/ush/python/pygfs/task/stage_ic.py index d1e95b8d120..cbec76c78f0 100644 --- a/ush/python/pygfs/task/stage_ic.py +++ b/ush/python/pygfs/task/stage_ic.py @@ -1,58 +1,499 @@ #!/usr/bin/env python3 +""" +Stage Initial Conditions (IC) Task +Overview +-------- +This module constructs cycle and member-specific COM directory path variables +required for initial conditions for the Stage IC task. +""" import os from logging import getLogger -from typing import Any, Dict - -from wxflow import FileHandler, Task, logit, parse_j2yaml +from typing import Any, Dict, Tuple, Optional +from wxflow import FileHandler, Task, logit, parse_j2yaml, AttrDict, to_YMD, to_fv3time, add_to_datetime, to_timedelta logger = getLogger(__name__.split('.')[-1]) class Stage(Task): - """Task to stage initial conditions - """ + """Task to stage initial conditions""" @logit(logger, name="Stage") def __init__(self, config: Dict[str, Any]) -> None: """Constructor for the Stage task - The constructor is responsible for collecting necessary settings based on - the runtime options and RUN. Parameters ---------- config : Dict[str, Any] Incoming configuration for the task from the environment + """ + super().__init__(config) + + @logit(logger) + def _copy_base_config(self) -> Dict[str, Any]: + """Copy essential base configuration from task_config Returns ------- - None + Dict[str, Any] + Dictionary with base configuration values """ - super().__init__(config) + base_keys = [ + 'RUN', 'MODE', 'EXP_WARM_START', 'NMEM_ENS', + 'assim_freq', 'current_cycle', 'previous_cycle', + 'ROTDIR', 'ICSDIR', 'STAGE_IC_YAML_TMPL', 'DO_JEDIATMVAR', + 'OCNRES', 'waveGRD', 'ntiles', 'DOIAU', 'ATMINC_GRID', + 'DO_JEDIOCNVAR', 'DO_STARTMEM_FROM_JEDIICE', + 'DO_WAVE', 'DO_OCN', 'DO_ICE', 'DO_NEST', 'DO_CA', 'DO_AERO_ANL', + 'USE_ATM_ENS_PERTURB_FILES', 'USE_OCN_ENS_PERTURB_FILES', 'DO_GSISOILDA', 'DO_LAND_IAU' + ] + + if self.task_config.get('NET') == 'gfs': + base_keys.append('DOIAU_ENKF') + + return {key: self.task_config[key] for key in base_keys if key in self.task_config} @logit(logger) - def execute_stage(self, stage_dict: Dict[str, Any]) -> None: - """Perform local staging of initial condition files. + def _get_config_vars(self) -> Dict[str, Any]: + """Calculate derived configuration variables + + Returns + ------- + Dict[str, Any] + Dictionary with derived configuration values (rRUN, OCNRES, START_ICE_FROM_ANA) + """ + config_vars = {} + + # Determine rRUN + # For GFS/GCAFS/GCDAS, always use 'gdas' for initial conditions from previous cycles + # TODO: Update when GCDAS/GCAFS-specific ICs become available + config_vars['rRUN'] = "gdas" if self.task_config.RUN in ['gfs', 'gcafs', 'gcdas'] else self.task_config.RUN + + # OCNRES formatting + if "OCNRES" in self.task_config: + config_vars['OCNRES'] = f"{int(self.task_config.OCNRES):03d}" + + # START_ICE_FROM_ANA logic + if self.task_config.get("DO_ICE", False): + config_vars['START_ICE_FROM_ANA'] = False + if self.task_config.get("DO_JEDIOCNVAR", False) and self.task_config.RUN == "gdas": + config_vars['START_ICE_FROM_ANA'] = True + if self.task_config.get("DO_STARTMEM_FROM_JEDIICE", False) and self.task_config.RUN == "enkfgdas": + config_vars['START_ICE_FROM_ANA'] = True + + return config_vars + + @logit(logger) + def _get_cycle_vars(self) -> Dict[str, Any]: + """Calculate current and previous cycle variables + + Returns + ------- + Dict[str, Any] + Dictionary with current and previous cycle variables including half_window + """ + cycle_vars = {} + half_window = self.task_config.assim_freq // 2 + cycle_vars['half_window'] = half_window + + # Current cycle variables + cycle_vars['current_cycle_HH'] = self.task_config.current_cycle.strftime("%H") + cycle_vars['current_cycle_YMD'] = to_YMD(self.task_config.current_cycle) + + if self.task_config.DOIAU and self.task_config.MODE == "cycled": + cycle_vars['model_start_date_current_cycle'] = add_to_datetime(self.task_config.current_cycle, to_timedelta(f"-{half_window}H")) + else: + if self.task_config.get('REPLAY_ICS', False): + cycle_vars['model_start_date_current_cycle'] = add_to_datetime(self.task_config.current_cycle, to_timedelta(f"{half_window}H")) + else: + cycle_vars['model_start_date_current_cycle'] = self.task_config.current_cycle + + cycle_vars['m_prefix'] = to_fv3time(cycle_vars['model_start_date_current_cycle']) + + # Previous cycle variables + previous_cycle_HH = self.task_config.previous_cycle.strftime("%H") + cycle_vars['m_index'] = self.task_config.current_cycle.hour // self.task_config.assim_freq + cycle_vars['p_prefix'] = to_fv3time(self.task_config.previous_cycle) + cycle_vars['previous_cycle_HH'] = previous_cycle_HH + cycle_vars['previous_cycle_YMD'] = to_YMD(self.task_config.previous_cycle) + cycle_vars['mid_cyc'] = int(previous_cycle_HH) + int(half_window) + + return cycle_vars + + @logit(logger) + def _create_cycle_dicts(self, rotdir: str, run: str) -> Dict[str, Dict[str, str]]: + """Create cycle directories for template substitution Parameters ---------- - stage_dict : Dict[str, Any] - Configuration dictionary + rotdir : str + ROTDIR path + run : str + RUN type Returns ------- - None + Dict[str, Dict[str, str]] + Dictionary containing current_cycle_dict and previous_cycle_dict """ + return { + 'current_cycle_dict': { + "${ROTDIR}": rotdir, + "${RUN}": run, + "${YMD}": to_YMD(self.task_config.current_cycle), + "${HH}": self.task_config.current_cycle.strftime("%H"), + }, + 'previous_cycle_dict': { + "${ROTDIR}": rotdir, + "${RUN}": run, + "${YMD}": to_YMD(self.task_config.previous_cycle), + "${HH}": self.task_config.previous_cycle.strftime("%H"), + } + } - if not os.path.isdir(stage_dict.ROTDIR): - raise FileNotFoundError(f"FATAL ERROR: The ROTDIR ({stage_dict.ROTDIR}) does not exist!") + @logit(logger) + def _copy_com_templates(self) -> Dict[str, str]: + """Copy COM templates from task_config + + Returns + ------- + Dict[str, str] + Dictionary with COM template paths + """ + return {key: self.task_config[key] for key in self.task_config.keys() + if key.startswith('COM_') and key.endswith('_TMPL')} + + @logit(logger) + def create_stage_dict(self) -> AttrDict: + """Create staging dictionary with all necessary variables for YAML templates + + Returns + ------- + AttrDict + Dictionary containing all variables needed for staging YAML templates + """ + stage_dict = AttrDict() - # Add the os.path.exists function to the dict for yaml parsing + # Copy essential base configuration + stage_dict.update(self._copy_base_config()) + + # Calculate derived configuration + stage_dict.update(self._get_config_vars()) + + # Calculate current and previous cycle variables + stage_dict.update(self._get_cycle_vars()) + + # Create cycle directories for template substitution + stage_dict.update(self._create_cycle_dicts(stage_dict.ROTDIR, stage_dict.RUN)) + + # Copy COM templates + stage_dict.update(self._copy_com_templates()) + + # Add GEFSTYPE if available (for GEFS runs) + if 'GEFSTYPE' in self.task_config: + stage_dict['GEFSTYPE'] = self.task_config.GEFSTYPE + + # Calculate member list based on RUN type + stage_dict['member_list'] = self.get_member_list( + stage_dict.RUN, + stage_dict.NMEM_ENS, + m_index=stage_dict.get('m_index', 0), + gefstype=stage_dict.get('GEFSTYPE', None) + ) + + # Add os.path.exists function for template use stage_dict['path_exists'] = os.path.exists - # Parse staging yaml to get list of files to stage - stage_set = parse_j2yaml(self.task_config.STAGE_IC_YAML_TMPL, stage_dict, allow_missing=False) + return stage_dict + + @logit(logger) + def execute_stage(self, stage_dict: AttrDict) -> None: + """Perform local staging of initial condition files + + Parameters + ---------- + stage_dict : AttrDict + Configuration dictionary with all necessary staging variables + """ + if not os.path.isdir(stage_dict.ROTDIR): + raise FileNotFoundError(f"FATAL ERROR: The ROTDIR ({stage_dict.ROTDIR}) does not exist!") + + stage_set = parse_j2yaml(stage_dict.STAGE_IC_YAML_TMPL, stage_dict, allow_missing=False) - # stage files to ROTDIR for key in stage_set.keys(): FileHandler(stage_set[key]).sync() + + @staticmethod + @logit(logger) + def get_member_com_paths(stage_dict: AttrDict, member: int) -> Dict[str, Any]: + """Get member-specific COM paths based on RUN type + + Parameters + ---------- + stage_dict : AttrDict + Staging configuration dictionary + member : int + Member directory number + + Returns + ------- + Dict[str, Any] + Dictionary of member-specific COM paths + + Raises + ------ + ValueError + If RUN type is unknown or GEFSTYPE is invalid for GEFS runs + """ + + if stage_dict.RUN == 'gefs': + gefstype = stage_dict.get('GEFSTYPE', None) + if gefstype == 'gefs-real-time': + com_path = Stage._get_member_com_paths_gefs_rt(stage_dict, member) + elif gefstype == 'gefs-offline': + com_path = Stage._get_member_com_paths_gefs_offline(stage_dict, member) + else: + raise ValueError(f"Invalid GEFSTYPE '{gefstype}' for RUN 'gefs'.") + elif stage_dict.RUN == 'sfs': + com_path = Stage._get_member_com_paths_gefs_offline(stage_dict, member) + elif stage_dict.RUN in ('gcafs', 'enkfgdas', 'gcdas', 'gdas'): + com_path = Stage._get_member_com_paths_gcafs(stage_dict, member) + elif stage_dict.RUN == 'gfs': + com_path = Stage._get_member_com_paths_gfs(stage_dict, member) + else: + raise ValueError(f"Unknown RUN type: {stage_dict.RUN}") + + return Stage._paths_from_templates(stage_dict, com_path) + + @staticmethod + @logit(logger) + def get_member_list(run: str, nmem_ens: int, m_index: int = 0, gefstype: Optional[str] = None) -> list[int]: + """Get list of member indices based on RUN type + + Parameters + ---------- + run : str + RUN type (e.g., 'gfs', 'gefs', 'enkfgdas', 'gdas', 'gcafs') + nmem_ens : int + Total number of ensemble members + m_index : int, optional + Cycle index for GEFS real-time mapping (default: 0) + gefstype : Optional[str], optional + GEFS type ('gefs-real-time' or 'gefs-offline') + + Returns + ------- + list[int] + List of member indices to process + """ + if run in ['enkfgdas']: + return list(range(1, nmem_ens + 1)) + if run in ['sfs']: + return list(range(0, nmem_ens + 1)) + elif run in ['gefs']: + if gefstype == 'gefs-real-time': + # Map GEFS members to GFS member numbers + # Cycle ranges determine which 30-member range to use based on cycle index + cyc_ranges = {'00': list(range(1, 31)), + '06': list(range(21, 51)), + '12': list(range(41, 71)), + '18': list(range(61, 81)) + list(range(1, 11))} + member_list = [0] + cyc_ranges[f'{m_index:02}'] + return member_list + else: + # GEFS offline uses sequential member numbering + return list(range(0, nmem_ens + 1)) + else: + # Deterministic runs (GFS, GDAS, GCAFS, GCDAS) + # Only member -1 is processed (empty string for MEMDIR) + return [-1] + + @staticmethod + @logit(logger) + def _paths_from_templates(stage_dict: AttrDict, com_path_tuples: Tuple[Tuple[str, str, Dict[str, Any]], ...]) -> Dict[str, str]: + """Generate COM paths from template configurations + + Parameters + ---------- + stage_dict : AttrDict + Staging configuration dictionary + com_path_tuples : Tuple[Tuple[str, str, Dict[str, Any]], ...] + Tuple of tuples containing path key, template key, and substitution dict + + Returns + ------- + Dict[str, str] + Dictionary mapping COM path keys to resolved file paths + """ + def _replace_template_vars(template: str, var_dict: Dict[str, Any]) -> str: + """Replace template variables in string with actual values + + Parameters + ---------- + template : str + Template string with variables to replace + var_dict : Dict[str, Any] + Dictionary of variable names and values + + Returns + ------- + str + String with variables replaced + """ + replaced_com = template + for var, value in var_dict.items(): + replaced_com = replaced_com.replace(var, value) + return replaced_com + + path_dict = {} + for com_key, template_key, substitution_dict in com_path_tuples: + template_str = stage_dict.get(template_key, '') + if not template_str: + logger.warning("Template key '%s' not found for COM key '%s'", template_key, com_key) + path_dict[com_key] = '' + else: + path_dict[com_key] = _replace_template_vars(template_str, substitution_dict) + return path_dict + + @staticmethod + @logit(logger) + def _get_member_com_paths_gfs(stage_dict: AttrDict, member: int) -> Tuple[Tuple[str, str, Dict[str, Any]], ...]: + """Get member COM paths for GFS + + Parameters + ---------- + stage_dict : AttrDict + Staging configuration dictionary + member : int + The member directory number + + Returns + ------- + Tuple[Tuple[str, str, Dict[str, Any]], ...] + Tuple of tuples containing path key, template key, and substitution dict + """ + member_str = f"mem{member:03d}" if member >= 0 else '' + current_cycle_mem_dict = {**stage_dict.current_cycle_dict, "${MEMDIR}": member_str} + previous_cycle_mem_dict = {**stage_dict.previous_cycle_dict, "${MEMDIR}": member_str, "${RUN}": stage_dict.rRUN} + + return ( + ('COMIN_ATMOS_INPUT', 'COM_ATMOS_INPUT_TMPL', current_cycle_mem_dict), + ('COMOUT_ATMOS_INPUT', 'COM_ATMOS_INPUT_TMPL', current_cycle_mem_dict), + ('COMOUT_ATMOS_RESTART_PREV', 'COM_ATMOS_RESTART_TMPL', previous_cycle_mem_dict), + ('COMOUT_ATMOS_RESTART', 'COM_ATMOS_RESTART_TMPL', current_cycle_mem_dict), + ('COMOUT_ATMOS_ANALYSIS', 'COM_ATMOS_ANALYSIS_TMPL', current_cycle_mem_dict), + ('COMOUT_ICE_ANALYSIS', 'COM_ICE_ANALYSIS_TMPL', current_cycle_mem_dict), + ('COMOUT_ICE_RESTART_PREV', 'COM_ICE_RESTART_TMPL', previous_cycle_mem_dict), + ('COMOUT_OCEAN_RESTART_PREV', 'COM_OCEAN_RESTART_TMPL', previous_cycle_mem_dict), + ('COMOUT_OCEAN_ANALYSIS', 'COM_OCEAN_ANALYSIS_TMPL', current_cycle_mem_dict), + ('COMOUT_MED_RESTART_PREV', 'COM_MED_RESTART_TMPL', previous_cycle_mem_dict), + ('COMOUT_CHEM_ANALYSIS', 'COM_CHEM_ANALYSIS_TMPL', current_cycle_mem_dict), + ('COMOUT_WAVE_RESTART_PREV', 'COM_WAVE_RESTART_TMPL', previous_cycle_mem_dict), + ) + + @staticmethod + @logit(logger) + def _get_member_com_paths_gefs_offline(stage_dict: AttrDict, member: int) -> Tuple[Tuple[str, str, Dict[str, Any]], ...]: + """Get member COM paths for GEFS offline + + Parameters + ---------- + stage_dict : AttrDict + Staging configuration dictionary + member : int + The member directory number + + Returns + ------- + Tuple[Tuple[str, str, Dict[str, Any]], ...] + Tuple of tuples containing path key, template key, and substitution dict + """ + member_str = f"mem{member:03d}" if member >= 0 else '' + current_cycle = {**stage_dict.current_cycle_dict, "${MEMDIR}": member_str} + previous_cycle = {**stage_dict.previous_cycle_dict, "${MEMDIR}": member_str} + + return ( + ('COMIN_ATMOS_INPUT', 'COM_ATMOS_INPUT_TMPL', current_cycle), + ('COMOUT_ATMOS_INPUT', 'COM_ATMOS_INPUT_TMPL', current_cycle), + ('COMOUT_ATMOS_RESTART_PREV', 'COM_ATMOS_RESTART_TMPL', previous_cycle), + ('COMOUT_ATMOS_RESTART', 'COM_ATMOS_RESTART_TMPL', current_cycle), + ('COMOUT_ATMOS_ANALYSIS', 'COM_ATMOS_ANALYSIS_TMPL', current_cycle), + ('COMOUT_ATMOS_HISTORY', 'COM_ATMOS_HISTORY_TMPL', previous_cycle), + ('COMOUT_ICE_ANALYSIS', 'COM_ICE_ANALYSIS_TMPL', current_cycle), + ('COMOUT_ICE_RESTART_PREV', 'COM_ICE_RESTART_TMPL', previous_cycle), + ('COMOUT_OCEAN_RESTART_PREV', 'COM_OCEAN_RESTART_TMPL', previous_cycle), + ('COMOUT_OCEAN_ANALYSIS', 'COM_OCEAN_ANALYSIS_TMPL', current_cycle), + ('COMOUT_MED_RESTART_PREV', 'COM_MED_RESTART_TMPL', previous_cycle), + ('COMOUT_WAVE_RESTART_PREV', 'COM_WAVE_RESTART_TMPL', previous_cycle), + ) + + @staticmethod + @logit(logger) + def _get_member_com_paths_gefs_rt(stage_dict: AttrDict, member: int) -> Tuple[Tuple[str, str, Dict[str, Any]], ...]: + """Get member COM paths for GEFS real-time + + Parameters + ---------- + stage_dict : AttrDict + Staging configuration dictionary + member : int + The GFS member directory number (already mapped from GEFS) + + Returns + ------- + Tuple[Tuple[str, str, Dict[str, Any]], ...] + Tuple of tuples containing path key, template key, and substitution dict + """ + member_str = f"mem{member:03d}" if member >= 0 else '' + current_cycle = {**stage_dict.current_cycle_dict, "${MEMDIR}": member_str} + previous_cycle = {**stage_dict.previous_cycle_dict, "${MEMDIR}": member_str} + + return ( + ('COMIN_ATMOS_INPUT', 'COM_ATMOS_INPUT_TMPL', current_cycle), + ('COMOUT_ATMOS_INPUT', 'COM_ATMOS_INPUT_TMPL', current_cycle), + ('COMOUT_ATMOS_RESTART_PREV', 'COM_ATMOS_RESTART_TMPL', previous_cycle), + ('COMOUT_ATMOS_ANALYSIS', 'COM_ATMOS_ANALYSIS_TMPL', current_cycle), + ('COMOUT_ATMOS_HISTORY', 'COM_ATMOS_HISTORY_TMPL', previous_cycle), + ('COMOUT_ICE_ANALYSIS', 'COM_ICE_ANALYSIS_TMPL', current_cycle), + ('COMOUT_ICE_RESTART_PREV', 'COM_ICE_RESTART_TMPL', previous_cycle), + ('COMOUT_OCEAN_RESTART_PREV', 'COM_OCEAN_RESTART_TMPL', previous_cycle), + ('COMOUT_OCEAN_ANALYSIS', 'COM_OCEAN_ANALYSIS_TMPL', current_cycle), + ('COMOUT_MED_RESTART_PREV', 'COM_MED_RESTART_TMPL', previous_cycle), + ('COMOUT_WAVE_RESTART_PREV', 'COM_WAVE_RESTART_TMPL', previous_cycle), + ) + + @staticmethod + @logit(logger) + def _get_member_com_paths_gcafs(stage_dict: AttrDict, member: int) -> Tuple[Tuple[str, str, Dict[str, Any]], ...]: + """Get member COM paths for GCAFS + + Parameters + ---------- + stage_dict : AttrDict + Staging configuration dictionary + member : int + The member directory number + + Returns + ------- + Tuple[Tuple[str, str, Dict[str, Any]], ...] + Tuple of tuples containing path key, template key, and substitution dict + """ + member_str = f"mem{member:03d}" if member >= 0 else '' + current_cycle_in = {**stage_dict.current_cycle_dict, "${MEMDIR}": member_str, "${RUN}": stage_dict.rRUN} + current_cycle = {**current_cycle_in, "${RUN}": stage_dict.RUN} + previous_cycle = {**stage_dict.previous_cycle_dict, "${MEMDIR}": member_str, "${RUN}": stage_dict.rRUN} + + return ( + ('COMIN_ATMOS_INPUT', 'COM_ATMOS_INPUT_TMPL', current_cycle_in), + ('COMOUT_ATMOS_INPUT', 'COM_ATMOS_INPUT_TMPL', current_cycle), + ('COMOUT_ATMOS_RESTART_PREV', 'COM_ATMOS_RESTART_TMPL', previous_cycle), + ('COMOUT_ATMOS_RESTART', 'COM_ATMOS_RESTART_TMPL', current_cycle), + ('COMOUT_ATMOS_ANALYSIS', 'COM_ATMOS_ANALYSIS_TMPL', current_cycle), + ('COMOUT_ICE_ANALYSIS', 'COM_ICE_ANALYSIS_TMPL', current_cycle), + ('COMOUT_ICE_RESTART_PREV', 'COM_ICE_RESTART_TMPL', previous_cycle), + ('COMOUT_OCEAN_RESTART_PREV', 'COM_OCEAN_RESTART_TMPL', previous_cycle), + ('COMOUT_OCEAN_ANALYSIS', 'COM_OCEAN_ANALYSIS_TMPL', current_cycle), + ('COMOUT_MED_RESTART_PREV', 'COM_MED_RESTART_TMPL', previous_cycle), + ('COMOUT_WAVE_RESTART_PREV', 'COM_WAVE_RESTART_TMPL', previous_cycle), + ) From da19eb699413ed4ba06a9b4dfd33fcf69bd4d882 Mon Sep 17 00:00:00 2001 From: Walter Kolczynski Date: Tue, 2 Dec 2025 08:01:09 -0500 Subject: [PATCH 06/27] Update shell script analysis GH action (#4280) Updates the GitHub action for static shell code analysis. The shellcheck is switched over to the reviewdog ecosystem and now checks all files in directories that have been made compliant, rather than just checking changes. A second pass on just changes is temporarily included (also using reviewdog, as that mode is supported) to ensure any new changes are compliant until the entire workflow is brough up to spec. There is also a new check against `shfmt`. The reviewdog version does not allow for path restrictions for shfmt, so for now this is being done manually on compliant directories. The reviewdog version is included to be uncommented when the entire repo is compliant. Additionally, the bash and python GH workflows are renamed to better represent their contents and updated to have the same set of triggers. The push trigger is restricted to develop to avoid double-testing of PRs, and a workflow dispatch trigger is added. Finally, a couple scripts that became non-compliant due to a lack of a shfmt check have been corrected. Refs: #397 Resolves #4239 --- .github/workflows/bash_code_analysis.yaml | 100 ++++++++++++++++++ .github/workflows/linters.yaml | 64 ----------- ...pynorms.yaml => python_code_analysis.yaml} | 10 +- dev/jobs/prep.sh | 8 +- dev/jobs/upp.sh | 2 +- 5 files changed, 112 insertions(+), 72 deletions(-) create mode 100644 .github/workflows/bash_code_analysis.yaml delete mode 100644 .github/workflows/linters.yaml rename .github/workflows/{pynorms.yaml => python_code_analysis.yaml} (81%) diff --git a/.github/workflows/bash_code_analysis.yaml b/.github/workflows/bash_code_analysis.yaml new file mode 100644 index 00000000000..c555c7506c7 --- /dev/null +++ b/.github/workflows/bash_code_analysis.yaml @@ -0,0 +1,100 @@ +name: bash_code_analysis +on: + push: + branches: + - develop + pull_request: + + workflow_dispatch: + +permissions: + contents: read + +jobs: + + shfmt: + runs-on: ubuntu-22.04 + + permissions: + contents: read # for actions/checkout to fetch code + pull-requests: read # to get PR metadata + security-events: write + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + # Switch to this action once whole repo is shfmt compliant + # - name: shfmt scan + # uses: reviewdog/action-shfmt@v1 + # with: + # filter_mode: nofilter + # level: warning + + - name: Install shfmt + uses: mfinelli/setup-shfmt@v4 + - name: shfmt scan + run: shfmt -d dev/jobs jobs scripts + + shellcheck: + runs-on: ubuntu-22.04 + + permissions: + contents: read # for actions/checkout to fetch code + pull-requests: read # to get PR metadata + security-events: write + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + submodules: false + + - name: Shellcheck Scan + uses: reviewdog/action-shellcheck@v1 + with: + filter_mode: nofilter + level: warning + path: | + dev/jobs + jobs + scripts + pattern: | + config.* + J* + *.env + *.sh + *.bash + + differential_shellcheck: + # Run again on just changes until whole repo is compliant + runs-on: ubuntu-22.04 + + permissions: + contents: read # for actions/checkout to fetch code + pull-requests: read # to get PR metadata + security-events: write + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + submodules: false + + - name: Shellcheck Scan + uses: reviewdog/action-shellcheck@v1 + with: + filter_mode: added + level: warning + check_all_files_with_shebangs: true + pattern: | + config.* + J* + *.env + *.sh + *.bash + + + diff --git a/.github/workflows/linters.yaml b/.github/workflows/linters.yaml deleted file mode 100644 index 4987c8caf01..00000000000 --- a/.github/workflows/linters.yaml +++ /dev/null @@ -1,64 +0,0 @@ -# -name: shellnorms -on: - pull_request: - -permissions: - contents: read - -defaults: - run: - shell: bash -o pipefail {0} - -jobs: - lint-shell: - runs-on: ubuntu-22.04 - - permissions: - security-events: write - - steps: - - name: Checkout code - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - id: ShellCheck - name: Lint shell scripts - uses: redhat-plumbers-in-action/differential-shellcheck@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - - if: ${{ always() }} - name: Upload artifact with ShellCheck defects in SARIF format - uses: actions/upload-artifact@v4 - with: - name: Differential ShellCheck SARIF - path: ${{ steps.ShellCheck.outputs.sarif }} - - # lint-python: - # runs-on: ubuntu-latest - - # permissions: - # security-events: write - - # steps: - # - name: Checkout code - # uses: actions/checkout@v3 - - # - id: VCS_Diff_Lint - # name: Lint python scripts - # uses: fedora-copr/vcs-diff-lint-action@v1 - - # - if: ${{ always() }} - # name: Upload artifact with detected defects in SARIF format - # uses: actions/upload-artifact@v3 - # with: - # name: VCS Diff Lint SARIF - # path: ${{ steps.VCS_Diff_Lint.outputs.sarif }} - - # - if: ${{ failure() }} - # name: Upload SARIF to GitHub using github/codeql-action/upload-sarif - # uses: github/codeql-action/upload-sarif@v2 - # with: - # sarif_file: ${{ steps.VCS_Diff_Lint.outputs.sarif }} diff --git a/.github/workflows/pynorms.yaml b/.github/workflows/python_code_analysis.yaml similarity index 81% rename from .github/workflows/pynorms.yaml rename to .github/workflows/python_code_analysis.yaml index 87915190ef2..bc4b49f4532 100644 --- a/.github/workflows/pynorms.yaml +++ b/.github/workflows/python_code_analysis.yaml @@ -1,5 +1,11 @@ -name: pynorms -on: [push, pull_request] +name: python_code_analysis +on: + push: + branches: + - develop + pull_request: + + workflow_dispatch: jobs: check_norms: diff --git a/dev/jobs/prep.sh b/dev/jobs/prep.sh index e47b055dc24..6b662967cba 100755 --- a/dev/jobs/prep.sh +++ b/dev/jobs/prep.sh @@ -112,7 +112,6 @@ else cpfs "${COMINobsproc}/${RUN_local}.t${cyc}z.syndata.tcvitals.tm00" "${COMOUT_OBS}/" fi - ############################################################### # If requested, copy bias correction files from source or stait to analysis directories # TODO: remove this when JEDI ATM can cycle bias correction coefficents @@ -133,7 +132,6 @@ if [[ ${RUN} == "gdas" && ${COPY_BIASCOR_STATIC:-"NO"} == "YES" ]]; then done fi - ############################################################### # Generate prepbufr files from dumps and prior gdas guess rm -f "${COMOUT_OBS}/${OPREFIX}prepbufr" @@ -199,7 +197,7 @@ if [[ ${err} -ne 0 ]]; then err_exit "Failed to obtain/create ${files}, ABORT!" fi -################################################################################ +################################################################################ # If requested, create radiance bias correction files for JEDI if [[ ${RUN} == "gdas" && ${CONVERT_BIASCOR:-"NO"} == "YES" ]]; then cd "${DATAROOT}" || true @@ -208,12 +206,12 @@ if [[ ${RUN} == "gdas" && ${CONVERT_BIASCOR:-"NO"} == "YES" ]]; then if [[ ${err} -ne 0 ]]; then err_exit "gsi_satbias2ioda failed, ABORT!" fi - + # Remove temporary working directory cd "${DATAROOT}" || true if [[ "${KEEPDATA}" == "NO" ]]; then rm -rf "${DATA}" - fi + fi fi ################################################################################ diff --git a/dev/jobs/upp.sh b/dev/jobs/upp.sh index 7dbce24453f..923a92d46f3 100755 --- a/dev/jobs/upp.sh +++ b/dev/jobs/upp.sh @@ -17,7 +17,7 @@ source "${HOMEgfs}/ush/detect_machine.sh" source "${HOMEgfs}/dev/ush/load_modules.sh" upp status=$? if [[ ${status} -ne 0 ]]; then - exit "${status}"; + exit "${status}" fi export job="upp" From c76804b46d4383c57d03a99f0df4bd21203a438d Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Thu, 4 Dec 2025 09:57:13 -0500 Subject: [PATCH 07/27] Fix eobs diags being left on the floor and a number of EE2 related updates (#4267) - Tar up the gsidiags into a gsidiag.tar instead of the GSI writing out to COM via symlinks. The tarred GSI diags are then untarred where they are needed. - provides a number of EE2 related updates (replacing link with copy), `COMIN/COMOUT`, etc. During the course of this , it was noticed that the EnKF was not assimilating any satellite obs. This hotfix was issued by @CatherineThomas-NOAA in a different PR already. Several variables in the analysis-related scripts are unnecessary and seem to come from earlier copy/paste versions. They can lead to confusion. This PR tries to eliminate some, though more work is recommended before code hand-off to expedite code acceptance into ops. There are also several deprecated "options" that are either no longer functional or not used. --- dev/parm/config/gfs/config.resources | 23 +- env/GAEAC6.env | 5 +- env/HERA.env | 4 + env/HERCULES.env | 5 +- env/ORION.env | 6 +- env/URSA.env | 4 + env/WCOSS2.env | 4 + jobs/JGDAS_ATMOS_ANALYSIS_DIAG | 21 +- jobs/JGDAS_ENKF_DIAG | 99 ++++---- jobs/JGDAS_ENKF_SELECT_OBS | 10 +- jobs/JGDAS_ENKF_UPDATE | 13 +- jobs/JGLOBAL_ATMOS_ANALYSIS_CALC | 1 + parm/archive/enkf.yaml.j2 | 10 +- parm/archive/gcafs_arcdir.yaml.j2 | 2 +- parm/archive/gdas_restarta.yaml.j2 | 2 +- parm/archive/gfs_arcdir.yaml.j2 | 2 +- scripts/exgdas_enkf_update.sh | 130 +++------- scripts/exglobal_atmos_analysis.sh | 104 +++----- scripts/exglobal_diag.sh | 347 +++++++++++++-------------- sorc/build_gdas.sh | 2 - sorc/build_gsi_enkf.sh | 3 - sorc/build_gsi_monitor.sh | 2 - sorc/build_ufs_utils.sh | 3 - sorc/build_ww3prepost.sh | 2 - ush/gaussian_sfcanl.sh | 136 ++++------- ush/python/pygfs/task/stage_ic.py | 10 + ush/regrid_gsiSfcIncr_to_tile.sh | 265 ++++++++++---------- 27 files changed, 542 insertions(+), 673 deletions(-) diff --git a/dev/parm/config/gfs/config.resources b/dev/parm/config/gfs/config.resources index 1c8ca9d24a1..f6bd3ab387f 100644 --- a/dev/parm/config/gfs/config.resources +++ b/dev/parm/config/gfs/config.resources @@ -758,12 +758,19 @@ case ${step} in fi ;; - "analdiag") + "analdiag" | "ediag") walltime="00:15:00" ntasks=96 # Should be at least twice ediag's tasks + memory="48GB" + #if [[ "${step}" == "ediag" ]]; then + # ntasks=48 + #fi threads_per_task=1 + if [[ ${ntasks} -gt ${max_tasks_per_node} ]]; then + ntasks=${max_tasks_per_node} + export is_exclusive=True + fi tasks_per_node=$(( max_tasks_per_node / threads_per_task )) - memory="48GB" ;; "anlstat") @@ -853,7 +860,7 @@ case ${step} in MEDTHREADS=${nthreads_mediator:-1} MEDPETS=${MEDPETS:-${FV3PETS}} (( MEDPETS = FV3PETS )) - (( MEDTHREADS = FV3THREADS )) + (( MEDTHREADS = FV3THREADS )) (( "${MEDPETS}" > 4800 )) && MEDPETS=4800 export MEDPETS MEDTHREADS echo "MEDIATOR using (threads, PETS) = (${MEDTHREADS}, ${MEDPETS})" @@ -979,7 +986,7 @@ case ${step} in ;; "upp") - #ntasks cannot be greater than $CASE_HIST + #ntasks cannot be greater than $CASE_HIST #define resources based on $CASE_HIST for upp case "${CASE_HIST}" in "C48" | "C96") @@ -1255,14 +1262,6 @@ case ${step} in fi ;; - "ediag") - walltime="00:15:00" - ntasks=48 - threads_per_task=1 - tasks_per_node=$(( max_tasks_per_node / threads_per_task )) - memory="30GB" - ;; - "eupd") walltime="00:45:00" case "${CASE}" in diff --git a/env/GAEAC6.env b/env/GAEAC6.env index 77e7bdd05d3..5ab863acb16 100755 --- a/env/GAEAC6.env +++ b/env/GAEAC6.env @@ -199,7 +199,10 @@ case ${step} in ntasks_gausfcanl=${ntasks_gausfcanl:-1} export APRUN_GAUSFCANL="${launcher} -n ${ntasks_gausfcanl} --cpus-per-task=${NTHREADS_GAUSFCANL}" ;; - "offlineanl") + "analdiag" | "ediag") + export USE_CFP="YES" + ;; + "offlineanl") export NTHREADS_CHGRES=${threads_per_task_chgres:-12} if [[ ${NTHREADS_CHGRES} -gt ${max_tasks_per_node} ]]; then diff --git a/env/HERA.env b/env/HERA.env index 8d6619e0da1..76af27e6748 100755 --- a/env/HERA.env +++ b/env/HERA.env @@ -203,6 +203,10 @@ elif [[ "${step}" = "anal" ]] || [[ "${step}" = "analcalc" ]]; then ntasks_gausfcanl=${ntasks_gausfcanl:-1} export APRUN_GAUSFCANL="${launcher} -n ${ntasks_gausfcanl} --cpus-per-task=${NTHREADS_GAUSFCANL}" +elif [[ "${step}" = "analdiag" ]] || [[ "${step}" = "ediag" ]]; then + + export USE_CFP="YES" + elif [[ "${step}" = "offlineanl" ]]; then export NTHREADS_CHGRES=${threads_per_task_chgres:-12} diff --git a/env/HERCULES.env b/env/HERCULES.env index 9aa6feb9ed8..493e23db4a3 100755 --- a/env/HERCULES.env +++ b/env/HERCULES.env @@ -158,7 +158,7 @@ case ${step} in "anlstat") export NTHREADS_ANLSTAT=${NTHREADSmax} - export APRUN_ANLSTAT="${APRUN_default} --cpus-per-task=${NTHREADS_ANLSTAT}" + export APRUN_ANLSTAT="${APRUN_default} --cpus-per-task=${NTHREADS_ANLSTAT}" ;; "ecen_fv3jedi") @@ -218,6 +218,9 @@ case ${step} in # REGRID requires 6 tasks for reproducibility ntasks_regrid=6 export APRUN_REGRID="${launcher} -n ${ntasks_regrid} " + ;; + "analdiag" | "ediag") + export USE_CFP="YES" ;; "offlineanl") diff --git a/env/ORION.env b/env/ORION.env index ca1d9334dc5..6634fda665f 100755 --- a/env/ORION.env +++ b/env/ORION.env @@ -157,7 +157,7 @@ elif [[ "${step}" = "marineanlletkf" ]]; then elif [[ "${step}" = "anlstat" ]]; then export NTHREADS_ANLSTAT=${NTHREADSmax} - export APRUN_ANLSTAT="${APRUN_default} --cpus-per-task=${NTHREADS_ANLSTAT}" + export APRUN_ANLSTAT="${APRUN_default} --cpus-per-task=${NTHREADS_ANLSTAT}" elif [[ "${step}" = "ecen_fv3jedi" ]]; then @@ -216,6 +216,10 @@ elif [[ "${step}" = "sfcanl" ]]; then ntasks_regrid=6 export APRUN_REGRID="${launcher} -n ${ntasks_regrid} " +elif [[ "${step}" = "analdiag" ]] || [[ "${step}" = "ediag" ]]; then + + export USE_CFP="YES" + elif [[ "${step}" = "offlineanl" ]]; then export NTHREADS_CHGRES=${threads_per_task:-12} diff --git a/env/URSA.env b/env/URSA.env index 4ee5a07b7e5..80711ea2b3b 100644 --- a/env/URSA.env +++ b/env/URSA.env @@ -192,6 +192,10 @@ elif [[ "${step}" = "anal" ]] || [[ "${step}" = "analcalc" ]]; then ntasks_gausfcanl=${ntasks_gausfcanl:-1} export APRUN_GAUSFCANL="${launcher} -n ${ntasks_gausfcanl} --cpus-per-task=${NTHREADS_GAUSFCANL}" +elif [[ "${step}" = "analdiag" ]] || [[ "${step}" = "ediag" ]]; then + + export USE_CFP="YES" + elif [[ "${step}" = "offlineanl" ]]; then export NTHREADS_CHGRES=${threads_per_task_chgres:-12} diff --git a/env/WCOSS2.env b/env/WCOSS2.env index 5d89728674c..867c0a4eab2 100755 --- a/env/WCOSS2.env +++ b/env/WCOSS2.env @@ -205,6 +205,10 @@ elif [[ "${step}" = "sfcanl" ]]; then ntasks_regrid=6 export APRUN_REGRID="${launcher} -n ${ntasks_regrid} " +elif [[ "${step}" = "analdiag" ]] || [[ "${step}" = "ediag" ]]; then + + export USE_CFP="YES" + elif [[ "${step}" = "offlineanl" ]]; then export NTHREADS_CHGRES=${threads_per_task_chgres:-14} diff --git a/jobs/JGDAS_ATMOS_ANALYSIS_DIAG b/jobs/JGDAS_ATMOS_ANALYSIS_DIAG index ad83614bff8..553a58e1160 100755 --- a/jobs/JGDAS_ATMOS_ANALYSIS_DIAG +++ b/jobs/JGDAS_ATMOS_ANALYSIS_DIAG @@ -1,27 +1,28 @@ #! /usr/bin/env bash -source "${HOMEgfs}/ush/jjob_header.sh" -e "anal" -c "base anal analdiag" +source "${HOMEgfs}/ush/jjob_header.sh" -e "analdiag" -c "base anal analdiag" ############################################## # Set variables used in the script ############################################## -export DO_CALC_ANALYSIS=${DO_CALC_ANALYSIS:-"YES"} +#export DO_CALC_ANALYSIS=${DO_CALC_ANALYSIS:-"YES"} ############################################## # Begin JOB SPECIFIC work ############################################## # shellcheck disable=SC2153 -GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") -export gPDY=${GDATE:0:8} -export gcyc=${GDATE:8:2} -export GDUMP="gdas" -export GDUMP_ENS="enkf${GDUMP}" +#GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") +#export gPDY=${GDATE:0:8} +#export gcyc=${GDATE:8:2} +#export GDUMP="gdas" +#export GDUMP_ENS="enkf${GDUMP}" -export OPREFIX="${RUN/enkf/}.t${cyc}z." -export GPREFIX="${GDUMP}.t${gcyc}z." -export APREFIX="${RUN}.t${cyc}z." +#export OPREFIX="${RUN/enkf/}.t${cyc}z." +#export GPREFIX="${GDUMP}.t${gcyc}z." +#export APREFIX="${RUN}.t${cyc}z." YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMIN_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \ COMOUT_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL mkdir -m 775 -p "${COMOUT_ATMOS_ANALYSIS}" diff --git a/jobs/JGDAS_ENKF_DIAG b/jobs/JGDAS_ENKF_DIAG index 70567283f2f..fa494dfb847 100755 --- a/jobs/JGDAS_ENKF_DIAG +++ b/jobs/JGDAS_ENKF_DIAG @@ -1,6 +1,6 @@ #! /usr/bin/env bash -source "${HOMEgfs}/ush/jjob_header.sh" -e "eobs" -c "base anal eobs analdiag ediag" +source "${HOMEgfs}/ush/jjob_header.sh" -e "ediag" -c "base anal eobs analdiag ediag" ############################################## # Set variables used in the script @@ -10,83 +10,76 @@ source "${HOMEgfs}/ush/jjob_header.sh" -e "eobs" -c "base anal eobs analdiag edi # Begin JOB SPECIFIC work ############################################## # shellcheck disable=SC2153 -GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") -export gPDY=${GDATE:0:8} -export gcyc=${GDATE:8:2} -export GDUMP="gdas" -export GDUMP_ENS="enkf${GDUMP}" +#GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") +#export gPDY=${GDATE:0:8} +#export gcyc=${GDATE:8:2} +#export GDUMP="gdas" +#export GDUMP_ENS="enkf${GDUMP}" export CASE=${CASE_ENS} -export OPREFIX="${RUN/enkf/}.t${cyc}z." +#export OPREFIX="${RUN/enkf/}.t${cyc}z." export APREFIX="${RUN}.t${cyc}z." -export GPREFIX="${GDUMP_ENS}.t${gcyc}z." -GPREFIX_DET="${GDUMP}.t${gcyc}z." +#export GPREFIX="${GDUMP_ENS}.t${gcyc}z." +#GPREFIX_DET="${GDUMP}.t${gcyc}z." -RUN=${RUN/enkf/} YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ - COMIN_OBS:COM_OBS_TMPL +#RUN=${RUN/enkf/} YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ +# COMIN_OBS:COM_OBS_TMPL MEMDIR="ensstat" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMIN_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \ COMOUT_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL -RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ - COMIN_OBS_PREV:COM_OBS_TMPL \ - COMIN_ATMOS_ANALYSIS_DET_PREV:COM_ATMOS_ANALYSIS_TMPL +#RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ +# COMIN_OBS_PREV:COM_OBS_TMPL \ +# COMIN_ATMOS_ANALYSIS_DET_PREV:COM_ATMOS_ANALYSIS_TMPL -MEMDIR="ensstat" RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ - COMIN_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL +#MEMDIR="ensstat" RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ +# COMIN_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL -export ATMGES_ENSMEAN="${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}ensmean.atm.f006.nc" -if [[ ! -f "${ATMGES_ENSMEAN}" ]]; then - export err=1 - err_exit "FILE MISSING: ATMGES_ENSMEAN == ${ATMGES_ENSMEAN}" -fi +#export ATMGES_ENSMEAN="${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}ensmean.atm.f006.nc" +#if [[ ! -f "${ATMGES_ENSMEAN}" ]]; then +# export err=1 +# err_exit "FILE MISSING: ATMGES_ENSMEAN == ${ATMGES_ENSMEAN}" +#fi # Link observational data -export PREPQC="${COMIN_OBS}/${OPREFIX}prepbufr" -if [[ ! -f ${PREPQC} ]]; then - echo "WARNING: Global PREPBUFR FILE ${PREPQC} MISSING" -fi -export TCVITL="${COMIN_OBS}/${OPREFIX}syndata.tcvitals.tm00" -if [[ ${DONST} == "YES" ]]; then - export NSSTBF="${COMIN_OBS}/${OPREFIX}nsstbufr" -fi -export PREPQCPF="${COMIN_OBS}/${OPREFIX}prepbufr.acft_profiles" +#export PREPQC="${COMIN_OBS}/${OPREFIX}prepbufr" +#if [[ ! -f ${PREPQC} ]]; then +# echo "WARNING: Global PREPBUFR FILE ${PREPQC} MISSING" +#fi +#export TCVITL="${COMIN_OBS}/${OPREFIX}syndata.tcvitals.tm00" +#if [[ ${DONST} == "YES" ]]; then +# export NSSTBF="${COMIN_OBS}/${OPREFIX}nsstbufr" +#fi +#export PREPQCPF="${COMIN_OBS}/${OPREFIX}prepbufr.acft_profiles" # Guess Bias correction coefficients related to control -export GBIAS=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias.txt -export GBIASPC=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias_pc.txt -export GBIASAIR=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias_air.txt -export GRADSTAT=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}radstat.tar +#export GBIAS=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias.txt +#export GBIASPC=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias_pc.txt +#export GBIASAIR=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias_air.txt +#export GRADSTAT=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}radstat.tar # Bias correction coefficients related to ensemble mean -export ABIAS="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias.txt" -export ABIASPC="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_pc.txt" -export ABIASAIR="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_air.txt" -export ABIASe="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_int.txt" +#export ABIAS="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias.txt" +#export ABIASPC="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_pc.txt" +#export ABIASAIR="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_air.txt" +#export ABIASe="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_int.txt" # Diagnostics related to ensemble mean -export GSISTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}gsistat.ensmean.tar" -export CNVSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}cnvstat.ensmean.tar" -export OZNSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}oznstat.ensmean.tar" -export RADSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}radstat.ensmean.tar" +export CNVSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}cnvstat_ensmean.tar" +export OZNSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}oznstat_ensmean.tar" +export RADSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}radstat_ensmean.tar" # Select observations based on ensemble mean -export RUN_SELECT="YES" -export USE_SELECT="NO" -export SELECT_OBS="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}obsinput.ensmean" +#export RUN_SELECT="YES" +#export USE_SELECT="NO" +#export SELECT_OBS="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}obsinput.ensmean" export DIAG_SUFFIX="_ensmean" export DIAG_COMPRESS="NO" # GSI namelist options specific to eobs -export SETUP_INVOBS="passive_bc=.false.,${SETUP_INVOBS}" - -# Ensure clean stat tarballs for ensemble mean -for fstat in ${CNVSTAT} ${OZNSTAT} ${RADSTAT}; do - if [[ -f "${fstat}" ]]; then - rm -f "${fstat}" - fi -done +#export SETUP_INVOBS="passive_bc=.false.,${SETUP_INVOBS}" ############################################################### # Run relevant script diff --git a/jobs/JGDAS_ENKF_SELECT_OBS b/jobs/JGDAS_ENKF_SELECT_OBS index 3417f6f6e77..f5fe813ef9d 100755 --- a/jobs/JGDAS_ENKF_SELECT_OBS +++ b/jobs/JGDAS_ENKF_SELECT_OBS @@ -84,15 +84,15 @@ export ABIASAIR="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_air.txt" export ABIASe="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_int.txt" # Diagnostics related to ensemble mean -export GSISTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}gsistat.ensmean.txt" -export CNVSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}cnvstat.ensmean.tar" -export OZNSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}oznstat.ensmean.tar" -export RADSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}radstat.ensmean.tar" +export GSISTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}gsistat_ensmean.txt" +export CNVSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}cnvstat_ensmean.tar" +export OZNSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}oznstat_ensmean.tar" +export RADSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}radstat_ensmean.tar" # Select observations based on ensemble mean export RUN_SELECT="YES" export USE_SELECT="NO" -export SELECT_OBS="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}obsinput.ensmean" +export SELECT_OBS="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}obsinput_ensmean.tar" export DIAG_SUFFIX="_ensmean" diff --git a/jobs/JGDAS_ENKF_UPDATE b/jobs/JGDAS_ENKF_UPDATE index 3b0d829591b..43d39b21735 100755 --- a/jobs/JGDAS_ENKF_UPDATE +++ b/jobs/JGDAS_ENKF_UPDATE @@ -9,15 +9,12 @@ source "${HOMEgfs}/ush/jjob_header.sh" -e "eupd" -c "base anal eupd" ############################################## # Begin JOB SPECIFIC work ############################################## -# shellcheck disable=SC2153 -GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") -export gPDY=${GDATE:0:8} -export gcyc=${GDATE:8:2} -export GDUMP="gdas" -export GDUMP_ENS="enkf${GDUMP}" +# shellcheck disable=SC2155 +export GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") +export GDUMP="enkfgdas" # EnKF ensemble always uses RUN=enkfgdas for prior members export APREFIX="${RUN}.t${cyc}z." -export GPREFIX="${GDUMP_ENS}.t${gcyc}z." +export GPREFIX="${GDUMP}.t${GDATE:8:2}z." MEMDIR="ensstat" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ COMIN_ATMOS_ANALYSIS_STAT:COM_ATMOS_ANALYSIS_TMPL @@ -25,7 +22,7 @@ MEMDIR="ensstat" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ MEMDIR="ensstat" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ COMOUT_ATMOS_ANALYSIS_STAT:COM_ATMOS_ANALYSIS_TMPL -MEMDIR="ensstat" RUN="enkfgdas" YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ +MEMDIR="ensstat" RUN="enkfgdas" YMD=${GDATE:0:8} HH=${GDATE:8:2} declare_from_tmpl -rx \ COMIN_ATMOS_HISTORY_STAT_PREV:COM_ATMOS_HISTORY_TMPL ############################################################### diff --git a/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC b/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC index cf59158117a..bfb5c74a3ad 100755 --- a/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC +++ b/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC @@ -28,6 +28,7 @@ RUN=${rCDUMP} YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ COMOUT_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \ + COMIN_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \ COMIN_ATMOS_RESTART:COM_ATMOS_RESTART_TMPL RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ diff --git a/parm/archive/enkf.yaml.j2 b/parm/archive/enkf.yaml.j2 index c19781a1c3e..73c92aeb806 100644 --- a/parm/archive/enkf.yaml.j2 +++ b/parm/archive/enkf.yaml.j2 @@ -69,10 +69,10 @@ enkf: # Ensemble mean state {% if not DO_JEDIATMENS %} {% set da_stat_files = ["enkfstat.txt", - "gsistat.ensmean.txt", - "cnvstat.ensmean.tar", - "oznstat.ensmean.tar", - "radstat.ensmean.tar"] %} + "gsistat_ensmean.txt", + "cnvstat_ensmean.tar", + "oznstat_ensmean.tar", + "radstat_ensmean.tar"] %} {% set da_conf_files = [] %} {% else %} {% if lobsdiag_forenkf %} @@ -109,7 +109,7 @@ enkf: # soil DA increments {% if DO_GSISOILDA %} {% for fhr in IAUFHRS %} - - "{{ COMIN_ATMOS_ANALYSIS_ENSSTAT | relpath(ROTDIR) }}/{{ head }}increment.sfc.i{{ '%03d' % fhr }}.nc" + - "{{ COMIN_ATMOS_ANALYSIS_ENSSTAT | relpath(ROTDIR) }}/{{ head }}ensmean_increment.sfc.i{{ '%03d' % fhr }}.nc" {% endfor %} {% endif %} diff --git a/parm/archive/gcafs_arcdir.yaml.j2 b/parm/archive/gcafs_arcdir.yaml.j2 index c4a548c4e94..325ffba80e6 100644 --- a/parm/archive/gcafs_arcdir.yaml.j2 +++ b/parm/archive/gcafs_arcdir.yaml.j2 @@ -83,7 +83,7 @@ {% else %} {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "enkfstat.txt", ARCDIR ~ "/enkfstat." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "gsistat.ensmean.txt", + {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "gsistat_ensmean.txt", ARCDIR ~ "/gsistat." ~ RUN ~ "." ~ cycle_YMDH ~ ".ensmean"]) %} {% endif %} diff --git a/parm/archive/gdas_restarta.yaml.j2 b/parm/archive/gdas_restarta.yaml.j2 index 60615e0c7ad..94074d2239b 100644 --- a/parm/archive/gdas_restarta.yaml.j2 +++ b/parm/archive/gdas_restarta.yaml.j2 @@ -46,7 +46,7 @@ gdas_restarta: - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}cnvstat.tar" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}abias_int.txt" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.dtf.a006.nc" - - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}increment.done.txt" + - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}analysis.done.txt" {% else %} - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}rad_varbc_params.tar" {% endif %} diff --git a/parm/archive/gfs_arcdir.yaml.j2 b/parm/archive/gfs_arcdir.yaml.j2 index 877691ff5f9..ed873b21c8b 100644 --- a/parm/archive/gfs_arcdir.yaml.j2 +++ b/parm/archive/gfs_arcdir.yaml.j2 @@ -140,7 +140,7 @@ {% else %} {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "enkfstat.txt", ARCDIR ~ "/enkfstat." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "gsistat.ensmean.txt", + {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "gsistat_ensmean.txt", ARCDIR ~ "/gsistat." ~ RUN ~ "." ~ cycle_YMDH ~ ".ensmean"]) %} {% endif %} diff --git a/scripts/exgdas_enkf_update.sh b/scripts/exgdas_enkf_update.sh index df981d16973..c44ba3e2bb9 100755 --- a/scripts/exgdas_enkf_update.sh +++ b/scripts/exgdas_enkf_update.sh @@ -18,56 +18,32 @@ ################################################################################ # Directories. -pwd=$(pwd) +cd "${DATA}" || exit 1 # Utilities NCLEN=${NCLEN:-${USHgfs}/getncdimlen} -USE_CFP=${USE_CFP:-"NO"} -CFP_MP=${CFP_MP:-"NO"} -APRUNCFP=${APRUNCFP:-""} APRUN_ENKF=${APRUN_ENKF:-${APRUN:-""}} NTHREADS_ENKF=${NTHREADS_ENKF:-${NTHREADS:-1}} # Executables ENKFEXEC=${ENKFEXEC:-${EXECgfs}/enkf.x} -# Filenames. -GPREFIX=${GPREFIX:-""} -APREFIX=${APREFIX:-""} +APREFIX=${APREFIX:-${RUN}.t${cyc}z.} +GPREFIX=${GPREFIX:-${RUN}.t${GDATE:8:2}z.} -SMOOTH_ENKF=${SMOOTH_ENKF:-"YES"} - -GBIASe=${GBIASe:-${APREFIX}abias_int.ensmean.txt} -CNVSTAT=${CNVSTAT:-${APREFIX}cnvstat.tar} -OZNSTAT=${OZNSTAT:-${APREFIX}oznstat.tar} -RADSTAT=${RADSTAT:-${APREFIX}radstat.tar} -ENKFSTAT=${ENKFSTAT:-${APREFIX}enkfstat.txt} +# GBIASe=${GBIASe:-${APREFIX}abias_int.ensmean.txt} # TODO: remove (see comment and TODO below) Also, this is not a "G"BIAS (See the name, it has APREFIX in its name) +CNVSTAT="${APREFIX}cnvstat_ensmean.tar" +OZNSTAT="${APREFIX}oznstat_ensmean.tar" +RADSTAT="${APREFIX}radstat_ensmean.tar" # Namelist parameters -USE_CORRELATED_OBERRS=${USE_CORRELATED_OBERRS:-"NO"} -NAM_ENKF=${NAM_ENKF:-""} -SATOBS_ENKF=${SATOBS_ENKF:-""} -OZOBS_ENKF=${OZOBS_ENKF:-""} -use_correlated_oberrs=${use_correlated_oberrs:-".false."} -if [[ "${USE_CORRELATED_OBERRS}" == "YES" ]]; then +if [[ "${USE_CORRELATED_OBERRS:-}" == "YES" ]]; then use_correlated_oberrs=".true." fi -imp_physics=${imp_physics:-"99"} -lupp=${lupp:-".true."} corrlength=${corrlength:-1250} lnsigcutoff=${lnsigcutoff:-2.5} analpertwt=${analpertwt:-0.85} -readin_localization_enkf=${readin_localization_enkf:-".true."} -reducedgrid=${reducedgrid:-".false."} -letkf_flag=${letkf_flag:-".false."} -getkf=${getkf:-".false."} -denkf=${denkf:-".false."} -nobsl_max=${nobsl_max:-10000} -write_spread_diag=${write_spread_diag:-".false."} cnvw_option=${cnvw_option:-".false."} -netcdf_diag=${netcdf_diag:-".true."} -modelspace_vloc=${modelspace_vloc:-".false."} # if true, 'vlocal_eig.dat' is needed -taperanalperts=${taperanalperts:-".false."} IAUFHRS_ENKF=${IAUFHRS_ENKF:-"6,"} NMEM_ENS_MAX=${NMEM_ENS:-80} if [[ "${RUN}" == "enkfgfs" ]]; then @@ -90,9 +66,6 @@ ATMGES_ENSMEAN="${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX}ensmean.atm.f006.nc" LONB_ENKF=${LONB_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" grid_xt)} # get LONB_ENKF LATB_ENKF=${LATB_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" grid_yt)} # get LATB_ENFK LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} "${ATMGES_ENSMEAN}" pfull)} # get LEVS_ENFK -use_gfs_ncio=".true." -use_gfs_nemsio=".false." -paranc=${paranc:-".true."} WRITE_INCR_ZERO="incvars_to_zero= ${INCREMENTS_TO_ZERO}," if [[ "${DO_CALC_INCREMENT}" == "YES" ]]; then write_fv3_incr=".false." @@ -110,71 +83,55 @@ HYBENSINFO=${HYBENSINFO:-${FIXgfs}/gsi/global_hybens_info.l${LEVS_ENKF}.txt} ANAVINFO=${ANAVINFO:-${FIXgfs}/gsi/global_anavinfo.l${LEVS_ENKF}.txt} VLOCALEIG=${VLOCALEIG:-${FIXgfs}/gsi/vlocal_eig_l${LEVS_ENKF}.dat} ENKF_SUFFIX="s" -if [[ "${SMOOTH_ENKF}" == "NO" ]]; then +if [[ "${SMOOTH_ENKF:-YES}" == "NO" ]]; then ENKF_SUFFIX="" fi ################################################################################ # Fixed files +cpreq "${SATANGL}" satbias_angle +cpreq "${SCANINFO}" scaninfo +cpreq "${HYBENSINFO}" hybens_info +cpreq "${ANAVINFO}" anavinfo +cpreq "${VLOCALEIG}" vlocal_eig.dat if [[ "${SATINFO}" == "generate" ]]; then "${USHgfs}/create_gsi_info.sh" sat "${PDY}${cyc}" "${DATA}" else - ${NLN} "${SATINFO}" satinfo + cpreq "${SATINFO}" satinfo fi if [[ "${CONVINFO}" == "generate" ]]; then "${USHgfs}/create_gsi_info.sh" conv "${PDY}${cyc}" "${DATA}" "${USE_2M_OBS}" else - ${NLN} "${CONVINFO}" convinfo + cpreq "${CONVINFO}" convinfo fi if [[ "${OZINFO}" == "generate" ]]; then "${USHgfs}/create_gsi_info.sh" oz "${PDY}${cyc}" "${DATA}" else - ${NLN} "${OZINFO}" ozinfo + cpreq "${OZINFO}" ozinfo fi -${NLN} "${SATANGL}" satbias_angle -${NLN} "${SCANINFO}" scaninfo -${NLN} "${HYBENSINFO}" hybens_info -${NLN} "${ANAVINFO}" anavinfo -${NLN} "${VLOCALEIG}" vlocal_eig.dat # Bias correction coefficients based on the ensemble mean -${NLN} "${COMIN_ATMOS_ANALYSIS_STAT}/${GBIASe}" "satbias_in" +#${NLN} "${COMIN_ATMOS_ANALYSIS_STAT}/${GBIASe}" "satbias_in" # This file does not exist when test was run # TODO: remove ################################################################################ +# Ensemble guess, observational data and analyses/increments -if [[ "${USE_CFP}" == "YES" ]]; then - rm -f "${DATA}/untar.sh" "${DATA}/mp_untar.sh" - cat > "${DATA}/untar.sh" << EOFuntar -#!/bin/sh -memchar=\$1 -COMOUT_ATMOS_ANALYSIS=\$2 flist="${CNVSTAT} ${OZNSTAT} ${RADSTAT}" -for ftype in \$flist; do - if [[ "\${memchar}" == "ensmean" ]]; then - fname=\${COMOUT_ATMOS_ANALYSIS}/\${ftype%.tar}.ensmean.tar - else - fname=\${COMOUT_ATMOS_ANALYSIS}/\${ftype} - fi - tar -xvf \$fname +for ftype in ${flist}; do + fname="${COMIN_ATMOS_ANALYSIS_STAT}/${ftype}" + tar -xvf "${fname}" done -EOFuntar - chmod 755 "${DATA}/untar.sh" -fi - -################################################################################ -# Ensemble guess, observational data and analyses/increments -echo "${DATA}/untar.sh ensmean ${COMIN_ATMOS_ANALYSIS_STAT}" | tee -a "${DATA}/mp_untar.sh" nfhrs="${IAUFHRS_ENKF//,/ }" for imem in $(seq 1 "${NMEM_ENS}"); do smem=$((imem + mem_offset)) - if ((smem > NMEM_ENS_MAX)); then + if [[ ${smem} -gt ${NMEM_ENS_MAX} ]]; then smem=$((smem - NMEM_ENS_MAX)) fi gmemchar="mem"$(printf "%03i" "${smem}") memchar="mem"$(printf "%03i" "${imem}") - MEMDIR=${gmemchar} RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -x \ + MEMDIR=${gmemchar} RUN=${GDUMP} YMD=${GDATE:0:8} HH=${GDATE:8:2} declare_from_tmpl -x \ COMIN_ATMOS_HISTORY_MEM_PREV:COM_ATMOS_HISTORY_TMPL MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl -x \ @@ -220,18 +177,11 @@ for FHR in ${nfhrs}; do if [[ "${DO_GSISOILDA}" == "YES" ]]; then ${NLN} "${COMIN_ATMOS_HISTORY_STAT_PREV}/${GPREFIX}ensmean.sfc.f00${FHR}.nc" \ "bfg_${PDY}${cyc}_fhr0${FHR}_ensmean" - ${NLN} "${COMIN_ATMOS_ANALYSIS_STAT}/${APREFIX}increment.sfc.i00${FHR}.nc" \ + ${NLN} "${COMIN_ATMOS_ANALYSIS_STAT}/${APREFIX}ensmean_increment.sfc.i00${FHR}.nc" \ "sfcincr_${PDY}${cyc}_fhr0${FHR}_ensmean" fi done -# Run with MPMD or serial -"${USHgfs}/run_mpmd.sh" "${DATA}/mp_untar.sh" && true -export err=$? -if [[ ${err} -ne 0 ]]; then - err_exit "Failed to untar input data!" -fi - ################################################################################ # Create global_enkf namelist cat > enkf.nml << EOFnml @@ -248,19 +198,19 @@ cat > enkf.nml << EOFnml sprd_tol=1.e30,paoverpb_thresh=0.98, nlons=${LONA_ENKF},nlats=${LATA_ENKF},nlevs=${LEVS_ENKF},nanals=${NMEM_ENS}, deterministic=.true.,sortinc=.true.,lupd_satbiasc=.false., - reducedgrid=${reducedgrid},readin_localization=${readin_localization_enkf}., - use_gfs_nemsio=${use_gfs_nemsio},use_gfs_ncio=${use_gfs_ncio},imp_physics=${imp_physics},lupp=${lupp}, + reducedgrid=${reducedgrid:-.false.},readin_localization=${readin_localization_enkf:-.true.}, + use_gfs_nemsio=.false.,use_gfs_ncio=.true.,imp_physics=${imp_physics:-99},lupp=${lupp:-.true.}, univaroz=.false.,adp_anglebc=.true.,angord=4,use_edges=.false.,emiss_bc=.true., - letkf_flag=${letkf_flag},nobsl_max=${nobsl_max},denkf=${denkf},getkf=${getkf}., + letkf_flag=${letkf_flag:-.false.},nobsl_max=${nobsl_max:-10000},denkf=${denkf:-.false.},getkf=${getkf:-.false.}, nhr_anal=${IAUFHRS_ENKF},nhr_state=${IAUFHRS_ENKF}, - lobsdiag_forenkf=.true.,taperanalperts=${taperanalperts}, - write_spread_diag=${write_spread_diag}, - modelspace_vloc=${modelspace_vloc}, - use_correlated_oberrs=${use_correlated_oberrs}, - netcdf_diag=${netcdf_diag},cnvw_option=${cnvw_option}, - paranc=${paranc},write_fv3_incr=${write_fv3_incr}, + lobsdiag_forenkf=.true.,taperanalperts=${taperanalperts:-.false.}, + write_spread_diag=${write_spread_diag:-".false."}, + modelspace_vloc=${modelspace_vloc:-.false.}, + use_correlated_oberrs=${use_correlated_oberrs:-.false.}, + netcdf_diag=.true.,cnvw_option=${cnvw_option}, + paranc=${paranc:-.true.},write_fv3_incr=${write_fv3_incr}, ${WRITE_INCR_ZERO} - ${NAM_ENKF} + ${NAM_ENKF:-} / &satobs_enkf sattypes_rad(1) = 'amsua_n15', dsis(1) = 'amsua_n15', @@ -343,7 +293,7 @@ cat > enkf.nml << EOFnml sattypes_rad(78)= 'atms_n21', dsis(78)= 'atms_n21', sattypes_rad(79)= 'cris-fsr_n21', dsis(79)= 'cris-fsr_n21', sattypes_rad(80)= 'abi_g19', dsis(80)= 'abi_g19', - ${SATOBS_ENKF} + ${SATOBS_ENKF:-} / &ozobs_enkf sattypes_oz(1) = 'sbuv2_n16', @@ -362,7 +312,7 @@ cat > enkf.nml << EOFnml sattypes_oz(14) = 'ompstc8_n21', sattypes_oz(15) = 'ompsnp_n21', sattypes_oz(16) = 'gome_metop-c', - ${OZOBS_ENKF} + ${OZOBS_ENKF:-} / EOFnml @@ -381,10 +331,10 @@ if [[ ${err} -ne 0 ]]; then fi # Cat runtime output files. -cat stdout stderr > "${COMOUT_ATMOS_ANALYSIS_STAT}/${ENKFSTAT}" +cat stdout stderr > enkfstat.txt +cpfs enkfstat.txt "${COMOUT_ATMOS_ANALYSIS_STAT}/${APREFIX}enkfstat.txt" ################################################################################ # Postprocessing -cd "${pwd}" || exit 1 -exit "${err}" +exit 0 diff --git a/scripts/exglobal_atmos_analysis.sh b/scripts/exglobal_atmos_analysis.sh index 604350dcf45..6eb8804a59d 100755 --- a/scripts/exglobal_atmos_analysis.sh +++ b/scripts/exglobal_atmos_analysis.sh @@ -20,8 +20,7 @@ # Set environment. # Directories. -pwd=$(pwd) - +cd "${DATA}" || exit 1 # Base variables rCDUMP=${rCDUMP:-"gdas"} GDUMP=${GDUMP:-"gdas"} @@ -39,7 +38,6 @@ export CHGRP_CMD=${CHGRP_CMD:-"chgrp ${group_name:-rstprod}"} export NCLEN=${NCLEN:-${USHgfs}/getncdimlen} COMPRESS=${COMPRESS:-gzip} UNCOMPRESS=${UNCOMPRESS:-gunzip} -APRUNCFP=${APRUNCFP:-""} APRUN_GSI=${APRUN_GSI:-${APRUN:-""}} NTHREADS_GSI=${NTHREADS_GSI:-${NTHREADS:-1}} @@ -57,8 +55,6 @@ IASI_CADS=${IASI_CADS:-".false."} CRIS_CADS=${CRIS_CADS:-".false."} # Diagnostic files options -netcdf_diag=${netcdf_diag:-".true."} -binary_diag=${binary_diag:-".false."} lobsdiag_forenkf=${lobsdiag_forenkf:-".false."} # IAU @@ -186,11 +182,7 @@ ABIAS=${ABIAS:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias.txt} ABIASPC=${ABIASPC:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_pc.txt} ABIASAIR=${ABIASAIR:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_air.txt} ABIASe=${ABIASe:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_int.txt} -RADSTAT=${RADSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}radstat.tar} GSISTAT=${GSISTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}gsistat.txt} -PCPSTAT=${PCPSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}pcpstat} -CNVSTAT=${CNVSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}cnvstat.tar} -OZNSTAT=${OZNSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}oznstat.tar} # Increment files ATMINC=${ATMINC:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i006.nc} @@ -199,17 +191,8 @@ ATMINC=${ATMINC:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.atm.i006.nc} RUN_SELECT=${RUN_SELECT:-"NO"} USE_SELECT=${USE_SELECT:-"NO"} USE_RADSTAT=${USE_RADSTAT:-"YES"} -SELECT_OBS=${SELECT_OBS:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}obsinput} +SELECT_OBS=${SELECT_OBS:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}obsinput.tar} GENDIAG=${GENDIAG:-"YES"} -DIAG_SUFFIX=${DIAG_SUFFIX:-""} -if [[ "${netcdf_diag}" == ".true." ]]; then - DIAG_SUFFIX="${DIAG_SUFFIX}.nc4" -fi -DIAG_COMPRESS=${DIAG_COMPRESS:-"YES"} -DIAG_TARBALL=${DIAG_TARBALL:-"YES"} -USE_CFP=${USE_CFP:-"NO"} -CFP_MP=${CFP_MP:-"NO"} -DIAG_DIR=${DIAG_DIR:-${COMOUT_ATMOS_ANALYSIS}/gsidiags} # Set script / GSI control parameters DOHYBVAR=${DOHYBVAR:-"NO"} @@ -332,8 +315,7 @@ RAPIDREFRESH_CLDSURF=${RAPIDREFRESH_CLDSURF:-""} CHEM=${CHEM:-""} NST=${NST:-""} -#uGSI Namelist parameters -lrun_subdirs=${lrun_subdirs:-".true."} +# GSI Namelist parameters if [[ "${DOHYBVAR}" == "YES" ]]; then l_hyb_ens=.true. export l4densvar=${l4densvar:-".false."} @@ -632,25 +614,6 @@ if [[ "${JCAP}" -ne "${JCAP_A}" ]]; then fi fi -############################################################## -# Diagnostic files -# if requested, link GSI diagnostic file directories for use later -if [[ "${GENDIAG}" == "YES" ]]; then - if [[ "${lrun_subdirs}" == ".true." ]]; then - if [[ -d "${DIAG_DIR}" ]]; then - rm -rf "${DIAG_DIR}" - fi - ntasks_m1="$((ntasks - 1))" - for pe in $(seq 0 "${ntasks_m1}"); do - pedir="dir.$(printf %04i "${pe}")" - mkdir -p "${DIAG_DIR}/${pedir}" - ${NLN} "${DIAG_DIR}/${pedir}" "${pedir}" - done - else - err_exit "lrun_subdirs must be true. lrun_subdirs=${lrun_subdirs}" - fi -fi - ############################################################## # Output files ${NLN} "${ATMANL}" siganl @@ -698,39 +661,32 @@ fi ############################################################## # If requested, copy and de-tar guess radstat file if [[ "${USE_RADSTAT}" == "YES" ]]; then - if [[ -f "${DATA}/unzip.sh" ]]; then - rm -f "${DATA}/unzip.sh" - fi - if [[ -f "${DATA}/mp_unzip.sh" ]]; then - rm -f "${DATA}/mp_unzip.sh" - fi - cat > "${DATA}/unzip.sh" << EOFunzip -#!/bin/sh - diag_file=\$1 - diag_suffix=\$2 - fname=\$(echo \$diag_file | cut -d'.' -f1) - fdate=\$(echo \$diag_file | cut -d'.' -f2) - ${UNCOMPRESS} \$diag_file - fnameges=\$(echo \$fname | sed 's/_ges//g') - ${NMV} \$fname.\$fdate\$diag_suffix \$fnameges -EOFunzip - - chmod 755 "${DATA}/unzip.sh" + rm -f "${DATA}/unzip_radstat.sh" + cat > "${DATA}/unzip_radstat.sh" << EOF +#!/bin/bash +diag_file=\$1 +diag_suffix=\$2 +fname=\$(echo \$diag_file | cut -d'.' -f1) +fdate=\$(echo \$diag_file | cut -d'.' -f2) +${UNCOMPRESS} \$diag_file +fnameges=\$(echo \$fname | sed 's/_ges//g') +${NMV} \$fname.\$fdate\$diag_suffix \$fnameges +EOF + chmod 755 "${DATA}/unzip_radstat.sh" + rm -f "${DATA}/cmdfile" #shellcheck disable=SC2312 - listdiag="$(tar xvf radstat.gdas | cut -d' ' -f2 | grep _ges)" + listdiag=$(tar -xvf radstat.gdas | cut -d' ' -f2 | grep _ges) for type in ${listdiag}; do diag_file=$(echo "${type}" | cut -d',' -f1) - echo "${DATA}/unzip.sh ${diag_file} ${DIAG_SUFFIX}" | tee -a "${DATA}/mp_unzip.sh" + echo "${DATA}/unzip_radstat.sh ${diag_file} ${DIAG_SUFFIX:-}.nc4" >> "${DATA}/cmdfile" done - chmod 755 "${DATA}/mp_unzip.sh" - "${USHgfs}/run_mpmd.sh" "${DATA}/mp_unzip.sh" && true + + "${USHgfs}/run_mpmd.sh" "${DATA}/cmdfile" && true export err=$? if [[ ${err} -ne 0 ]]; then - export pgm="run_mpmd.sh" - err_exit "run_mpmd failed while unziping diagnotic files." + err_exit "Failed to unzip radstat.gdas file!" fi - fi # if [[ $USE_RADSTAT == "YES" ] ############################################################## @@ -768,12 +724,12 @@ cat > gsiparm.anl << EOF use_pbl=.false.,use_compress=.true.,nsig_ext=45,gpstop=50.,commgpstop=45.,commgpserrinf=1.0, use_gfs_nemsio=.false.,use_gfs_ncio=.true.,sfcnst_comb=.true., use_readin_anl_sfcmask=${USE_READIN_ANL_SFCMASK}, - lrun_subdirs=${lrun_subdirs}, + lrun_subdirs=.true., crtm_coeffs_path='./crtm_coeffs/', newpc4pred=.true.,adp_anglebc=.true.,angord=4,passive_bc=.true.,use_edges=.false., diag_precon=.true.,step_start=1.e-3,emiss_bc=.true.,nhr_obsbin=${nhr_obsbin:-3}, cwoption=3,imp_physics=${imp_physics},lupp=${lupp},cnvw_option=${cnvw_option},cao_check=${cao_check}, - netcdf_diag=${netcdf_diag},binary_diag=${binary_diag}, + netcdf_diag=.true.,binary_diag=.false., lobsdiag_forenkf=${lobsdiag_forenkf}, write_fv3_incr=${write_fv3_increment}, nhr_anal=${IAUFHRS}, @@ -927,7 +883,7 @@ fi ################################################################################ # Postprocessing -cd "${pwd}" || exit 1 +cd "${DATA}" || exit 1 ############################################################## # Add this statement to release the forecast job once the @@ -937,6 +893,18 @@ cd "${pwd}" || exit 1 if [[ "${SENDECF}" == "YES" && "${RUN}" != "enkf" ]]; then ecflow_client --event release_fcst fi + +# Diagnostic files +# if requested, GSI diagnostic file directories for use later +if [[ "${GENDIAG}" == "YES" ]]; then + tar -cvf gsidiags.tar dir.???? + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Failed to tar GSI diagnostic directories!" + fi + cpfs gsidiags.tar "${COMOUT_ATMOS_ANALYSIS}/${APREFIX}gsidiags${DIAG_SUFFIX:-}.tar" +fi + # shellcheck disable=SC2312 echo "${rCDUMP} ${PDY}${cyc} atminc done at $(date)" > "${COMOUT_ATMOS_ANALYSIS}/${APREFIX}increment.done.txt" diff --git a/scripts/exglobal_diag.sh b/scripts/exglobal_diag.sh index 92ea7bdaa8f..68231b6fb72 100755 --- a/scripts/exglobal_diag.sh +++ b/scripts/exglobal_diag.sh @@ -18,233 +18,218 @@ ################################################################################ # Set environment. +cd "${DATA}" || exit 8 # Base variables -GDUMP="${GDUMP:-gdas}" # Utilities -export CHGRP_CMD=${CHGRP_CMD:-"chgrp ${group_name:-rstprod}"} -export NCLEN=${NCLEN:-${USHgfs}/getncdimlen} -export CATEXEC=${CATEXEC:-${ncdiag_ROOT:-${gsi_ncdiag_ROOT}}/bin/ncdiag_cat_serial.x} +CHGRP_CMD=${CHGRP_CMD:-"chgrp ${group_name:-rstprod}"} +CATEXEC=${CATEXEC:-${ncdiag_ROOT:-${gsi_ncdiag_ROOT}}/bin/ncdiag_cat_serial.x} COMPRESS=${COMPRESS:-gzip} -UNCOMPRESS=${UNCOMPRESS:-gunzip} -APRUNCFP=${APRUNCFP:-""} - -# Diagnostic files options -netcdf_diag=${netcdf_diag:-".true."} -binary_diag=${binary_diag:-".false."} # Analysis files -export APREFIX=${APREFIX:-""} -RADSTAT=${RADSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}radstat.tar} -PCPSTAT=${PCPSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}pcpstat} +APREFIX=${APREFIX:-"${RUN}.t${cyc}z."} CNVSTAT=${CNVSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}cnvstat.tar} +PCPSTAT=${PCPSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}pcpstat} OZNSTAT=${OZNSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}oznstat.tar} +RADSTAT=${RADSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}radstat.tar} # Remove stat file if file already exists rm -f "${RADSTAT}" "${PCPSTAT}" "${CNVSTAT}" "${OZNSTAT}" # Obs diag GENDIAG=${GENDIAG:-"YES"} -DIAG_SUFFIX=${DIAG_SUFFIX:-""} -if [[ "${netcdf_diag}" == ".true." ]]; then - DIAG_SUFFIX="${DIAG_SUFFIX}.nc4" -fi +GSIDIAG=${GSIDIAG:-"${COMIN_ATMOS_ANALYSIS}/${APREFIX}gsidiags${DIAG_SUFFIX:-}.tar"} +USE_BUILD_GSINFO=${USE_BUILD_GSINFO:-"NO"} DIAG_COMPRESS=${DIAG_COMPRESS:-"YES"} -COMPRESS_SUFFIX=${COMPRESS_SUFFIX:-""} -if [[ ${DIAG_COMPRESS} == "YES" ]]; then - COMPRESS_SUFFIX="${COMPRESS_SUFFIX}.gz" +if [[ "${DIAG_COMPRESS:-}" == "YES" ]]; then + COMPRESS_SUFFIX=".gz" fi DIAG_TARBALL=${DIAG_TARBALL:-"YES"} -USE_CFP=${USE_CFP:-"NO"} -CFP_MP=${CFP_MP:-"NO"} -DIAG_DIR=${DIAG_DIR:-${COMOUT_ATMOS_ANALYSIS}/gsidiags} -REMOVE_DIAG_DIR=${REMOVE_DIAG_DIR:-"NO"} # Set script / GSI control parameters -lrun_subdirs=${lrun_subdirs:-".true."} ################################################################################ -# If requested, generate diagnostic files -if [[ "${GENDIAG}" == "YES" ]]; then - if [[ "${lrun_subdirs}" == ".true." ]]; then - for pe in "${DIAG_DIR}/"dir.*; do - pedir="$(basename -- "${pe}")" - ${NLN} "${pe}" "${DATA}/${pedir}" - done - else - err_exit "lrun_subdirs must be true. Abort job" - fi +if [[ "${GENDIAG}" != "YES" ]]; then + echo "INFO: GENDIAG set to NO. Skipping diagnostic file generation." + exit 0 +fi - # Set up lists and variables for various types of diagnostic files. - diagtype[0]="conv conv_gps conv_ps conv_pw conv_q conv_sst conv_t conv_tcp conv_uv conv_spd" - diagtype[1]="pcp_ssmi_dmsp pcp_tmi_trmm" - if [[ "${USE_BUILD_GSINFO}" == "YES" ]]; then - diagtype[2]=$(cat "${BUILD_GSINFO_DIR}/ozinfo/satellites") - diagtype[3]=$(cat "${BUILD_GSINFO_DIR}/satinfo/satellites") - else - diagtype[2]="sbuv2_n16 sbuv2_n17 sbuv2_n18 sbuv2_n19 gome_metop-a gome_metop-b omi_aura mls30_aura ompsnp_npp ompstc8_npp ompstc8_n20 ompsnp_n20 ompstc8_n21 ompsnp_n21 ompslp_npp gome_metop-c" - diagtype[3]="msu_n14 sndr_g08 sndr_g11 sndr_g12 sndr_g13 sndr_g08_prep sndr_g11_prep sndr_g12_prep sndr_g13_prep sndrd1_g11 sndrd2_g11 sndrd3_g11 sndrd4_g11 sndrd1_g12 sndrd2_g12 sndrd3_g12 sndrd4_g12 sndrd1_g13 sndrd2_g13 sndrd3_g13 sndrd4_g13 sndrd1_g14 sndrd2_g14 sndrd3_g14 sndrd4_g14 sndrd1_g15 sndrd2_g15 sndrd3_g15 sndrd4_g15 amsua_n15 amsua_n16 amsua_n17 amsub_n15 amsub_n16 amsub_n17 hsb_aqua airs_aqua amsua_aqua imgr_g08 imgr_g11 imgr_g12 imgr_g14 imgr_g15 ssmi_f13 ssmi_f15 amsua_n18 amsua_metop-a mhs_n18 mhs_metop-a amsre_low_aqua amsre_mid_aqua amsre_hig_aqua ssmis_f16 ssmis_f17 ssmis_f18 ssmis_f19 ssmis_f20 iasi_metop-a amsua_n19 mhs_n19 seviri_m08 seviri_m09 seviri_m10 seviri_m11 cris_npp cris-fsr_npp cris-fsr_n20 atms_npp atms_n20 amsua_metop-b mhs_metop-b iasi_metop-b avhrr_metop-b avhrr_n18 avhrr_n19 avhrr_metop-a amsr2_gcom-w1 gmi_gpm saphir_meghat ahi_himawari8 abi_g16 abi_g17 amsua_metop-c mhs_metop-c iasi_metop-c avhrr_metop-c viirs-m_npp viirs-m_j1 abi_g18 ahi_himawari9 viirs-m_j2 cris-fsr_n21 atms_n21 abi_g19" - fi +################################################################################ +# Copy gsidiags.tar file from COMIN to DATA and untar +cpreq "${GSIDIAG}" ./gsidiags.tar +tar -xvf gsidiags.tar +export err=$? +if [[ ${err} -ne 0 ]]; then + err_exit "Unable to unpack gsidiags.tar file!" +fi - diaglist[0]=listcnv - diaglist[1]=listpcp - diaglist[2]=listozn - diaglist[3]=listrad - - diagfile[0]="${CNVSTAT}" - diagfile[1]="${PCPSTAT}" - diagfile[2]="${OZNSTAT}" - diagfile[3]="${RADSTAT}" - - # Set diagnostic file prefix based on lrun_subdirs variable - if [[ "${lrun_subdirs}" == ".true." ]]; then - prefix="dir.*/" - else - prefix="pe*" - fi +# Set up lists and variables for various types of diagnostic files. +ntype=3 - rm -f "${DATA}/diag.sh" "${DATA}/mp_diag.sh" - cat > "${DATA}/diag.sh" << EOFdiag -#!/bin/sh -lrun_subdirs=\$1 -binary_diag=\$2 -type=\$3 -loop=\$4 -string=\$5 -PDY=\$6 -cyc=\$7 -DIAG_COMPRESS=\$8 -DIAG_SUFFIX=\$9 -if [[ "\${lrun_subdirs}" == ".true." ]]; then - prefix="dir.*/" +diagtype[0]="conv conv_gps conv_ps conv_pw conv_q conv_sst conv_t conv_tcp conv_uv conv_spd" +diagtype[1]="pcp_ssmi_dmsp pcp_tmi_trmm" +if [[ ${USE_BUILD_GSINFO} == "YES" ]]; then + diagtype[2]=$(cat "${BUILD_GSINFO_DIR}/ozinfo/satellites") + diagtype[3]=$(cat "${BUILD_GSINFO_DIR}/satinfo/satellites") else - prefix="pe*" -fi -count=\$(find -L ./ -path "./\${prefix}\${type}_\${loop}*" -type f -printf '.' | wc -c) -file="diag_\${type}_\${string}.\${PDY}\${cyc}\${DIAG_SUFFIX}" -if [[ "\${binary_diag}" == ".true." ]] || [[ "\${count}" -eq 1 ]]; then - cat \${prefix}\${type}_\${loop}* > "\${file}" -else - ${CATEXEC} -o "\${file}" \${prefix}\${type}_\${loop}* + diagtype[2]="sbuv2_n16 sbuv2_n17 sbuv2_n18 sbuv2_n19 gome_metop-a gome_metop-b omi_aura mls30_aura ompsnp_npp ompstc8_npp ompstc8_n20 ompsnp_n20 ompstc8_n21 ompsnp_n21 ompslp_npp gome_metop-c" + diagtype[3]="msu_n14 sndr_g08 sndr_g11 sndr_g12 sndr_g13 sndr_g08_prep sndr_g11_prep sndr_g12_prep sndr_g13_prep sndrd1_g11 sndrd2_g11 sndrd3_g11 sndrd4_g11 sndrd1_g12 sndrd2_g12 sndrd3_g12 sndrd4_g12 sndrd1_g13 sndrd2_g13 sndrd3_g13 sndrd4_g13 sndrd1_g14 sndrd2_g14 sndrd3_g14 sndrd4_g14 sndrd1_g15 sndrd2_g15 sndrd3_g15 sndrd4_g15 amsua_n15 amsua_n16 amsua_n17 amsub_n15 amsub_n16 amsub_n17 hsb_aqua airs_aqua amsua_aqua imgr_g08 imgr_g11 imgr_g12 imgr_g14 imgr_g15 ssmi_f13 ssmi_f15 amsua_n18 amsua_metop-a mhs_n18 mhs_metop-a amsre_low_aqua amsre_mid_aqua amsre_hig_aqua ssmis_f16 ssmis_f17 ssmis_f18 ssmis_f19 ssmis_f20 iasi_metop-a amsua_n19 mhs_n19 seviri_m08 seviri_m09 seviri_m10 seviri_m11 cris_npp cris-fsr_npp cris-fsr_n20 atms_npp atms_n20 amsua_metop-b mhs_metop-b iasi_metop-b avhrr_metop-b avhrr_n18 avhrr_n19 avhrr_metop-a amsr2_gcom-w1 gmi_gpm saphir_meghat ahi_himawari8 abi_g16 abi_g17 amsua_metop-c mhs_metop-c iasi_metop-c avhrr_metop-c viirs-m_npp viirs-m_j1 abi_g18 ahi_himawari9 viirs-m_j2 cris-fsr_n21 atms_n21 abi_g19" fi -if [[ "\${DIAG_COMPRESS}" == "YES" ]]; then - ${COMPRESS} "\${file}" + +diaglist[0]=listcnv +diaglist[1]=listpcp +diaglist[2]=listozn +diaglist[3]=listrad + +diagfile[0]="${CNVSTAT}" +diagfile[1]="${PCPSTAT}" +diagfile[2]="${OZNSTAT}" +diagfile[3]="${RADSTAT}" + +numfile[0]=0 +numfile[1]=0 +numfile[2]=0 +numfile[3]=0 + +rm -f "${DATA}/diag.sh" +cat > "${DATA}/diag.sh" << EOF +#!/bin/bash +set -x + +type=\$1 +loop=\$2 +string=\$3 +count=\$4 +suffix=\$5 + +# Match files with this prefix +diag_files=dir.*/\${type}_\${loop} + +# Name of combined diagnostic file from matched files +out_diag_file=diag_\${type}_\${string}.${PDY}${cyc}\${suffix} + +# Combine diagnostic files +if [[ \${count} -gt 1 ]]; then + ${CATEXEC} -o \${out_diag_file} \${diag_files}* +else + cat \${diag_files}* > "\${out_diag_file}" fi -EOFdiag - chmod 755 "${DATA}/diag.sh" - - # Collect diagnostic files as a function of loop and type. - # Loop over first and last outer loops to generate innovation - # diagnostic files for indicated observation types (groups) - # - # NOTE: Since we set miter=2 in GSI namelist SETUP, outer - # loop 03 will contain innovations with respect to - # the analysis. Creation of o-a innovation files - # is triggered by write_diag(3)=.true. The setting - # write_diag(1)=.true. turns on creation of o-g - # innovation files. - - loops="01 03" - for loop in ${loops}; do - case ${loop} in - 01) string=ges ;; - 03) string=anl ;; - *) string=${loop} ;; - esac - # shellcheck disable=SC2312 - echo "$(date) START loop ${string}" >&2 - for ((n = 0; n < ${#diagtype[@]}; n++)); do - for type in ${diagtype[n]}; do - # shellcheck disable=SC2312 - count=$(find -L ./ -path "./${prefix}${type}_${loop}*" -type f -printf '.' | wc -c) - if [[ "${count}" -gt 0 ]]; then - echo "${DATA}/diag.sh ${lrun_subdirs} ${binary_diag} ${type} ${loop} ${string} ${PDY} ${cyc} ${DIAG_COMPRESS} ${DIAG_SUFFIX}" | tee -a "${DATA}/mp_diag.sh" - echo "diag_${type}_${string}.${PDY}${cyc}${DIAG_SUFFIX}${COMPRESS_SUFFIX}" >> "${diaglist[n]}" - fi - done - done - # shellcheck disable=SC2312 - echo "$(date) END loop ${string}" >&2 - done - # We should already be in $DATA, but extra cd to be sure. - cd "${DATA}" || exit 1 +# Compress diagnostic file if requested +if [[ "${DIAG_COMPRESS:-}" == "YES" ]]; then + ${COMPRESS} "\${out_diag_file}" +fi - export err=0 - if [[ -s "${DATA}/mp_diag.sh" ]]; then - chmod 755 "${DATA}/mp_diag.sh" - "${USHgfs}/run_mpmd.sh" "${DATA}/mp_diag.sh" && true - # Delay err exit to avoid rstprod leakage - err=$? - fi +exit 0 +EOF +chmod 755 "${DATA}/diag.sh" - # Restrict diagnostic files containing rstprod data - if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then - rlist="conv_gps conv_ps conv_pw conv_q conv_sst conv_t conv_uv saphir" - for rtype in ${rlist}; do - for rfile in *"${rtype}"*; do - if [[ -s "${rfile}" ]]; then - ${CHGRP_CMD} "${rfile}" - fi - done +# Collect diagnostic files as a function of loop and type. +# Loop over first and last outer loops to generate innovation +# diagnostic files for indicated observation types (groups) +# +# NOTE: Since we set miter=2 in GSI namelist SETUP, outer +# loop 03 will contain innovations with respect to +# the analysis. Creation of o-a innovation files +# is triggered by write_diag(3)=.true. The setting +# write_diag(1)=.true. turns on creation of o-g +# innovation files. + +rm -f cmdfile +touch cmdfile +loops="01 03" +for loop in ${loops}; do + case ${loop} in + 01) string=ges ;; + 03) string=anl ;; + *) string=${loop} ;; + esac + echo "START loop ${string}" + n=-1 + while [[ ${n} -lt ${ntype} ]]; do + n=$((n + 1)) + for type in ${diagtype[n]}; do + #shellcheck disable=SC2012,SC2312 + count=$(ls dir.*/"${type}_${loop}"* 2> /dev/null | wc -l) + if [[ ${count} -eq 0 ]]; then + continue + fi + echo "${DATA}/diag.sh ${type} ${loop} ${string} ${count} ${DIAG_SUFFIX:-}.nc4" >> cmdfile + echo "diag_${type}_${string}.${PDY}${cyc}${DIAG_SUFFIX:-}.nc4${COMPRESS_SUFFIX:-}" >> "${diaglist[n]}" + numfile[n]=$((numfile[n] + 1)) done - fi + done + echo "END loop ${string}" +done - # Now exit if compression failed +ncmd=$(wc -l < cmdfile) +if [[ ${ncmd} -eq 0 ]]; then + echo "WARNING: No diagnostic files found to process!" + exit 0 +fi + +# MPMD can only be executed on a single node, +# so break up cmdfile into parts of tasks_per_node size files +# and run them sequentially +split -l "${tasks_per_node}" ./cmdfile cmdfile_part_ +cmdfile_parts=$(ls cmdfile_part_*) +for partfile in ${cmdfile_parts}; do + "${USHgfs}/run_mpmd.sh" "${partfile}" && true + export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "Failed to compress one or more observation diagnostic files!" + err_exit "Failed to create one or more observation diagnostic files for ${partfile}!" fi - - # If requested, create diagnostic file tarballs - if [[ "${DIAG_TARBALL}" == "YES" ]]; then - # shellcheck disable=SC2312 - echo "$(date) START tar diagnostic files" >&2 - for ((n = 0; n < ${#diagtype[@]}; n++)); do - TAROPTS="-uvf" - if [[ ! -s "${diagfile[n]}" ]]; then - TAROPTS="-cvf" - fi - if [[ -s "${diaglist[n]}" ]]; then - tar "${TAROPTS}" "${diagfile[n]}" -T "${diaglist[n]}" - export err=$? - if [[ ${err} -ne 0 ]]; then - # Delay err_exit to avoid rstprod leakage - err_msg="Unable to create ${diagfile[n]}!" - break - fi +done + +# Restrict diagnostic files containing rstprod data +if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then + rlist="conv_gps conv_ps conv_pw conv_q conv_sst conv_t conv_uv saphir" + for rtype in ${rlist}; do + for rfile in *"${rtype}"*; do + if [[ -s "${rfile}" ]]; then + ${CHGRP_CMD} "${rfile}" fi done + done +fi - # Restrict CNVSTAT - chmod 750 "${CNVSTAT}" - if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then - ${CHGRP_CMD} "${CNVSTAT}" +# If requested, create diagnostic file tarballs +if [[ "${DIAG_TARBALL}" == "YES" ]]; then + echo "START tar diagnostic files" + n=-1 + while [[ ${n} -lt ${ntype} ]]; do + n=$((n + 1)) + TAROPTS="-uvf" + if [[ ! -s "${diagfile[n]}" ]]; then + TAROPTS="-cvf" fi - - # Restrict RADSTAT - if [[ -s "${RADSTAT}" ]]; then - chmod 750 "${RADSTAT}" - if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then - ${CHGRP_CMD} "${RADSTAT}" + if [[ ${numfile[n]} -gt 0 ]]; then + tar "${TAROPTS}" "${diagfile[n]}" -T "${diaglist[n]}" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "Unable to create ${diagfile[n]}!" fi fi + done + echo "END tar diagnostic files" - # Now exit if there was an error - if [[ ${err} -ne 0 ]]; then - err_exit "${err_msg}" - fi + # Restrict CNVSTAT + chmod 750 "${CNVSTAT}" + if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then + ${CHGRP_CMD} "${CNVSTAT}" + fi - # shellcheck disable=SC2312 - echo "$(date) END tar diagnostic files" >&2 + # Restrict RADSTAT + if [[ -s "${RADSTAT}" ]]; then + chmod 750 "${RADSTAT}" + if [[ "${CHGRP_RSTPROD}" == "YES" ]]; then + ${CHGRP_CMD} "${RADSTAT}" + fi fi -fi # End diagnostic file generation block - if [[ "${GENDIAG}" == "YES" ]] +fi ################################################################################ # Postprocessing -# Remove $DIAG_DIR -if [[ "${REMOVE_DIAG_DIR}" == "YES" ]]; then - rm -rf "${DIAG_DIR}" -fi exit 0 diff --git a/sorc/build_gdas.sh b/sorc/build_gdas.sh index 32213153423..e49cc00429c 100755 --- a/sorc/build_gdas.sh +++ b/sorc/build_gdas.sh @@ -13,11 +13,9 @@ while getopts ":j:dv" option; do v) _opts+="-v ";; :) echo "[${BASH_SOURCE[0]}]: ${option} requires an argument" - usage ;; *) echo "[${BASH_SOURCE[0]}]: Unrecognized option: ${option}" - usage ;; esac done diff --git a/sorc/build_gsi_enkf.sh b/sorc/build_gsi_enkf.sh index 09cf250acf2..badba6c332d 100755 --- a/sorc/build_gsi_enkf.sh +++ b/sorc/build_gsi_enkf.sh @@ -9,11 +9,9 @@ while getopts ":j:dv" option; do v) BUILD_VERBOSE="YES";; :) echo "[${BASH_SOURCE[0]}]: ${option} requires an argument" - usage ;; *) echo "[${BASH_SOURCE[0]}]: Unrecognized option: ${option}" - usage ;; esac done @@ -33,4 +31,3 @@ REGRESSION_TESTS=NO \ "${HOMEgfs_}/sorc/gsi_enkf.fd/ush/build.sh" exit - diff --git a/sorc/build_gsi_monitor.sh b/sorc/build_gsi_monitor.sh index d355067f127..e982f14f703 100755 --- a/sorc/build_gsi_monitor.sh +++ b/sorc/build_gsi_monitor.sh @@ -12,11 +12,9 @@ while getopts ":j:dv" option; do v) BUILD_VERBOSE="YES";; :) echo "[${BASH_SOURCE[0]}]: ${option} requires an argument" - usage ;; *) echo "[${BASH_SOURCE[0]}]: Unrecognized option: ${option}" - usage ;; esac done diff --git a/sorc/build_ufs_utils.sh b/sorc/build_ufs_utils.sh index 2284b151343..e6698bb5008 100755 --- a/sorc/build_ufs_utils.sh +++ b/sorc/build_ufs_utils.sh @@ -12,11 +12,9 @@ while getopts ":j:dv" option; do v) BUILD_VERBOSE="YES";; :) echo "[${BASH_SOURCE[0]}]: ${option} requires an argument" - usage ;; *) echo "[${BASH_SOURCE[0]}]: Unrecognized option: ${option}" - usage ;; esac done @@ -31,4 +29,3 @@ BUILD_VERBOSE=${BUILD_VERBOSE:-} \ "${HOMEgfs_}/sorc/ufs_utils.fd/build_all.sh" exit - diff --git a/sorc/build_ww3prepost.sh b/sorc/build_ww3prepost.sh index 19133b12972..5408a5c390c 100755 --- a/sorc/build_ww3prepost.sh +++ b/sorc/build_ww3prepost.sh @@ -16,11 +16,9 @@ while getopts ":j:a:dvw" option; do w) PDLIB="OFF" ;; :) echo "[${BASH_SOURCE[0]}]: ${option} requires an argument" - usage ;; *) echo "[${BASH_SOURCE[0]}]: Unrecognized option: ${option}" - usage ;; esac done diff --git a/ush/gaussian_sfcanl.sh b/ush/gaussian_sfcanl.sh index 70780e63a8a..0652c0117c5 100755 --- a/ush/gaussian_sfcanl.sh +++ b/ush/gaussian_sfcanl.sh @@ -23,35 +23,12 @@ # CASE Forecast model and restart resolution. Defaults to C768. # CASE_HIST History file output resolution. Defaults to $CASE. # DONST Process NST fields when 'yes'. Default is 'no'. -# OUTPUT_FILE Output gaussian analysis file format. Default is "nemsio" -# Set to "netcdf" for netcdf output file -# Otherwise, output in nemsio. # FIXWGTS Weight file to use for interpolation -# DATA Working directory -# (if nonexistent will be made, used and deleted) -# Defaults to current working directory # COMOUT Output directory # (if nonexistent will be made) # defaults to current working directory -# XC Suffix to add to executables. Defaults to none. # GAUSFCANLEXE Program executable. # Defaults to $EXECgfs/gaussian_sfcanl.x -# INISCRIPT Preprocessing script. Defaults to none. -# LOGSCRIPT Log posting script. Defaults to none. -# ENDSCRIPT Postprocessing script -# defaults to none -# PGMOUT Executable standard output -# defaults to $pgmout, then to '&1' -# PGMERR Executable standard error -# defaults to $pgmerr, then to '&1' -# pgmout Executable standard output default -# pgmerr Executable standard error default -# REDOUT standard output redirect ('1>' or '1>>') -# defaults to '1>', or to '1>>' to append if $PGMOUT is a file -# REDERR standard error redirect ('2>' or '2>>') -# defaults to '2>', or to '2>>' to append if $PGMERR is a file -# VERBOSE Verbose flag (YES or NO) -# defaults to NO # gfs_ver Version number of gfs directory. Default is # v15.0.0. # OMP_NUM_ @@ -60,15 +37,11 @@ # Default is none. # # Exported Shell Variables: -# PGM Current program name # pgm -# ERR Last return code # err # # Modules and files referenced: -# scripts : $INISCRIPT -# $LOGSCRIPT -# $ENDSCRIPT +# scripts : # # programs : $GAUSFCANLEXE # @@ -77,10 +50,9 @@ # ${FIXgfs}/am/global_hyblev.l65.txt # # input data : ${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile*.nc +# ${COMIN_ATMOS_ANALYSIS}/increment.sfc.i006.tile${i}.nc" # -# output data: $PGMOUT -# $PGMERR -# $COMOUT/${APREFIX}analysis.sfc.a006.nc +# output data: $COMOUT/${APREFIX}analysis.sfc.a006.nc # # Remarks: # @@ -95,7 +67,6 @@ # # Attributes: # Language: POSIX shell -# Machine: IBM SP # ################################################################################ @@ -104,94 +75,69 @@ CASE_HIST=${CASE_HIST:-${CASE}} resh=${CASE_HIST:1} LONB_CASE=$((resh*4)) LATB_CASE=$((resh*2)) -LONB_SFC=${LONB_SFC:-$LONB_CASE} -LATB_SFC=${LATB_SFC:-$LATB_CASE} +LONB_SFC=${LONB_SFC:-${LONB_CASE}} +LATB_SFC=${LATB_SFC:-${LATB_CASE}} DONST=${DONST:-"NO"} LEVS=${LEVS:-64} -LEVSP1=$(($LEVS+1)) +LEVSP1=$(( LEVS + 1 )) FIXWGTS=${FIXWGTS:-${FIXorog}/${CASE}/fv3_SCRIP_${CASE}_GRIDSPEC_lon${LONB_SFC}_lat${LATB_SFC}.gaussian.neareststod.nc} # Filenames. -XC=${XC:-} -GAUSFCANLEXE=${GAUSFCANLEXE:-$EXECgfs/gaussian_sfcanl.x} +GAUSFCANLEXE=${GAUSFCANLEXE:-${EXECgfs}/gaussian_sfcanl.x} SIGLEVEL=${SIGLEVEL:-${FIXgfs}/am/global_hyblev.l${LEVSP1}.txt} # Other variables. -export PGMOUT=${PGMOUT:-${pgmout:-'&1'}} -export PGMERR=${PGMERR:-${pgmerr:-'&2'}} -export REDOUT=${REDOUT:-'1>'} -export REDERR=${REDERR:-'2>'} # Set defaults ################################################################################ # Preprocessing -${INISCRIPT:-} -pwd=$(pwd) -if [[ ! -d "${COMOUT_ATMOS_ANALYSIS}" ]]; then - mkdir -p "${COMOUT_ATMOS_ANALYSIS}" -fi ################################################################################ # Make surface analysis -export PGM=$GAUSFCANLEXE -export pgm=$PGM -$LOGSCRIPT - -iy=${PDY:0:4} -im=${PDY:4:2} -id=${PDY:6:2} -ih=${cyc} - -export OMP_NUM_THREADS=${OMP_NUM_THREADS_SFC:-1} - # input interpolation weights -${NLN} "${FIXWGTS}" "./weights.nc" +cpreq "${FIXWGTS}" "./weights.nc" # input analysis tiles (with nst records) -${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile1.nc" "./anal.tile1.nc" -${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile2.nc" "./anal.tile2.nc" -${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile3.nc" "./anal.tile3.nc" -${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile4.nc" "./anal.tile4.nc" -${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile5.nc" "./anal.tile5.nc" -${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile6.nc" "./anal.tile6.nc" +cpreq "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile1.nc" "./anal.tile1.nc" +cpreq "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile2.nc" "./anal.tile2.nc" +cpreq "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile3.nc" "./anal.tile3.nc" +cpreq "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile4.nc" "./anal.tile4.nc" +cpreq "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile5.nc" "./anal.tile5.nc" +cpreq "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile6.nc" "./anal.tile6.nc" # input orography tiles -${NLN} "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile1.nc" "./orog.tile1.nc" -${NLN} "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile2.nc" "./orog.tile2.nc" -${NLN} "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile3.nc" "./orog.tile3.nc" -${NLN} "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile4.nc" "./orog.tile4.nc" -${NLN} "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile5.nc" "./orog.tile5.nc" -${NLN} "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile6.nc" "./orog.tile6.nc" - -${NLN} "${SIGLEVEL}" "./vcoord.txt" +cpreq "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile1.nc" "./orog.tile1.nc" +cpreq "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile2.nc" "./orog.tile2.nc" +cpreq "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile3.nc" "./orog.tile3.nc" +cpreq "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile4.nc" "./orog.tile4.nc" +cpreq "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile5.nc" "./orog.tile5.nc" +cpreq "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile6.nc" "./orog.tile6.nc" -# output gaussian global surface analysis files -${NLN} "${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.sfc.a006.nc" "./sfc.gaussian.analysis.file" +cpreq "${SIGLEVEL}" "./vcoord.txt" # Namelist uses booleans now -if [[ ${DONST} == "YES" ]]; then do_nst='.true.'; else do_nst='.false.'; fi +if [[ "${DONST}" == "YES" ]]; then + do_nst=".true." +else + do_nst=".false." +fi -#Add soil increments to gdas gaussian sfcanal if they are not added by gcycle (i.e., when landiau=true) +# Add soil increments to gdas gaussian sfcanal if they are not added by gcycle (i.e., when landiau=true) LSOIL_INCR=${LSOIL_INCR:-2} -if [[ "${DO_LAND_IAU:-.false.}" == ".true." ]]; then +if [[ "${DO_LAND_IAU:-.false.}" == ".true." ]]; then for i in $(seq 1 6); do - sfc_inc="${COMOUT_ATMOS_ANALYSIS}/increment.sfc.i006.tile${i}.nc" - if [[ ! -f "${sfc_inc}" ]]; then - echo "Error! gaussian sfc analysis missing increment file ${sfc_inc}" - exit 1 - else - ${NLN} "${sfc_inc}" "./sfc_inc.tile${i}.nc" - fi + sfc_inc="${COMIN_ATMOS_ANALYSIS}/increment.sfc.i006.tile${i}.nc" + cpreq "${sfc_inc}" "./sfc_inc.tile${i}.nc" done fi # Executable namelist cat < fort.41 - &setup - yy=${iy}, - mm=${im}, - dd=${id}, - hh=${ih}, +&setup + yy=${PDY:0:4}, + mm=${PDY:4:2}, + dd=${PDY:6:2}, + hh=${cyc}, igaus=${LONB_SFC}, jgaus=${LATB_SFC}, donst=${do_nst}, @@ -200,19 +146,25 @@ cat < fort.41 add_soil_inc=${DO_LAND_IAU}, lsoil_incr=${LSOIL_INCR}, sfc_inc_file="./sfc_inc", - / +/ EOF +cat fort.41 +export pgm="${GAUSFCANLEXE}" +export OMP_NUM_THREADS=${OMP_NUM_THREADS_SFC:-1} ${APRUNSFC} "${GAUSFCANLEXE}" - export err=$? if [[ ${err} -ne 0 ]]; then echo "FATAL ERROR: ${GAUSFCANLEXE} returned non-zero exit status!" exit "${err}" fi +# output gaussian global surface analysis files +if [[ -f "sfc.gaussian.analysis.file" ]]; then + cpfs "./sfc.gaussian.analysis.file" "${COMOUT_ATMOS_ANALYSIS}/${APREFIX}analysis.sfc.a006.nc" +fi + ################################################################################ # Postprocessing -cd "${pwd}" exit 0 diff --git a/ush/python/pygfs/task/stage_ic.py b/ush/python/pygfs/task/stage_ic.py index cbec76c78f0..873d4346593 100644 --- a/ush/python/pygfs/task/stage_ic.py +++ b/ush/python/pygfs/task/stage_ic.py @@ -220,6 +220,16 @@ def execute_stage(self, stage_dict: AttrDict) -> None: stage_set = parse_j2yaml(stage_dict.STAGE_IC_YAML_TMPL, stage_dict, allow_missing=False) + # Parse staging yaml to get list of files to stage + stage_set = parse_j2yaml(self.task_config.STAGE_IC_YAML_TMPL, stage_dict, allow_missing=False) + logger.info(stage_set) + + # Write stage_set to a file in DATA for debugging + stage_yaml = f"./stage{stage_dict.member:03}.yaml" + stage_set.save(stage_yaml) + logger.debug(f"Staging yaml written to '{stage_yaml}' for debugging purposes.") + + # stage files to ROTDIR for key in stage_set.keys(): FileHandler(stage_set[key]).sync() diff --git a/ush/regrid_gsiSfcIncr_to_tile.sh b/ush/regrid_gsiSfcIncr_to_tile.sh index aa922229f6c..5e2fe1cf59f 100755 --- a/ush/regrid_gsiSfcIncr_to_tile.sh +++ b/ush/regrid_gsiSfcIncr_to_tile.sh @@ -9,12 +9,6 @@ source "${HOMEgfs}/ush/atparse.bash" # David New, Nov 2025 (parallelization updates) #------------------------------------------------------------------------------------------------- -export PGMOUT=${PGMOUT:-${pgmout:-'&1'}} -export PGMERR=${PGMERR:-${pgmerr:-'&2'}} - -export PGM=${REGRID_EXEC} -export pgm=${PGM} - NMEM_REGRID=${NMEM_REGRID:-1} CASE_IN=${CASE_IN:-${CASE_ENS}} LFHR=${LFHR:-6} @@ -31,13 +25,9 @@ LSOIL_INCR=${LSOIL_INCR:-2} export n_vars=$(( LSOIL_INCR*2 )) -soil_incr_vars="" -for vi in $( seq 1 "${LSOIL_INCR}" ); do - soil_incr_vars=${soil_incr_vars}'"soilt'${vi}'_inc"', -done -for vi in $( seq 1 "${LSOIL_INCR}" ); do - soil_incr_vars=${soil_incr_vars}'"slc'${vi}'_inc"', -done +soilt_incr_vars=$(seq -s ',' -f '"soilt%g_inc"' 1 "${LSOIL_INCR}") +slc_incr_vars=$(seq -s ',' -f '"slc%g_inc"' 1 "${LSOIL_INCR}") +export soil_incr_vars="${soilt_incr_vars},${slc_incr_vars}" if [[ "${DO_LAND_IAU}" = ".true." ]]; then IFS=',' read -ra landifhrs <<< "${IAUFHRS}" @@ -52,9 +42,9 @@ export jres=${LATB_CASE_IN} export ireso=${CASE_OUT:1} export jreso=${CASE_OUT:1} -regrid_nml_tmpl="${PARMgfs}/regrid_sfc/regrid.nml_tmpl" +regrid_nml_tmpl="${PARMgfs}/regrid_sfc/regrid.nml_tmpl" -if (( LFHR >= 0 )); then +if [[ "${LFHR}" -ge 0 ]]; then soilinc_fhrs=("${LFHR}") else # construct restart times for deterministic member soilinc_fhrs=("${assim_freq}") # increment file at middle of window @@ -64,14 +54,14 @@ else # construct restart times for deterministic member fi fi -# # Stage input files -# + +cd "${DATA}" || exit 1 # Create MDMD command file for fixed files -rm -f cmdfile.0 -touch cmdfile.0 -chmod 755 cmdfile.0 +rm -f cmdfile_in.0 +touch cmdfile_in.0 +chmod 755 cmdfile_in.0 # Append fixed files command file to master command file { @@ -91,80 +81,148 @@ for n in $(seq 1 "${ntiles}"); do echo "cpreq ${FIXorog}/${CASE_OUT}/${CASE_OUT}_grid.tile${n}.nc \ ${DATA}/${CASE_OUT}_grid.tile${n}.nc" done -} > cmdfile.0 +} >> cmdfile_in.0 + +if [[ "${NMEM_REGRID}" -gt 1 ]]; then + + echo "INFO: Preparing to regrid surface increments for ${NMEM_REGRID} ensemble members." + for imem in $(seq 1 "${NMEM_REGRID}"); do + + memdir=$(printf "mem%03i" "${imem}") + + MEMDIR=${memdir} YMD=${PDY} HH=${cyc} declare_from_tmpl \ + COMIN_SOIL_ANALYSIS_MEM:COM_ATMOS_ANALYSIS_TMPL \ + COMOUT_ATMOS_ANALYSIS_MEM:COM_ATMOS_ANALYSIS_TMPL + + # Create MPMD command file for this member + rm -f "cmdfile_in.${imem}" "cmdfile_out.${imem}" + touch "cmdfile_in.${imem}" "cmdfile_out.${imem}" + chmod 755 "cmdfile_in.${imem}" "cmdfile_out.${imem}" -for imem in $(seq 1 "${NMEM_REGRID}"); do - cmem=$(printf %03i "${imem}") - memchar="mem${cmem}" + # Create commands to stage input files + { + echo "#!/bin/bash" - # If deterministic job, COMOUT_ATMOS_ANALYSIS_MEM is just COMOUT_ATMOS_ANALYSIS - if (( NMEM_REGRID > 1 )); then - MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl \ - COMIN_SOIL_ANALYSIS_MEM:COM_ATMOS_ANALYSIS_TMPL + echo "mkdir -p ${DATA}/${memdir}" - memdir="${DATA}/${memchar}" - mkdir -p "${memdir}" + for FHR in "${soilinc_fhrs[@]}"; do + echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}increment.sfc.i00${FHR}.nc \ + ${DATA}/${memdir}/sfci00${FHR}.nc" + done - if [[ "${imem}" -gt 1 ]]; then - in_dir+=", " + if [[ "${DO_LAND_IAU}" = ".true." ]]; then + for FHI in "${landifhrs[@]}"; do + echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}increment.sfc.i00${FHI}.nc \ + ${DATA}/${memdir}/sfci00${FHI}.nc" + done + fi + } >> "cmdfile_in.${imem}" + + # Create commands to copy output files + { + echo "#!/bin/bash" + + if [[ "${DO_LAND_IAU}" = ".false." || "${RUN}" == "gdas" || "${RUN}" == "gfs" ]]; then + for FHR in "${soilinc_fhrs[@]}"; do + for n in $(seq 1 "${ntiles}"); do + echo "cpfs ${DATA}/${memdir}/sfci00${FHR}.mem${imem}.tile${n}.nc \ + ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.i00${FHR}.tile${n}.nc" + done + done fi - in_dir+="\"./${memchar}/\"" - else - # If deterministic job, memdir is just DATA - memdir="${DATA}" - in_dir="'./'" - fi + if [[ "${DO_LAND_IAU}" = ".true." ]]; then + for n in $(seq 1 "${ntiles}"); do + echo "cpfs ${DATA}/${memdir}/sfci.mem${imem}.tile${n}.nc \ + ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.tile${n}.nc" + done + fi + } >> "cmdfile_out.${imem}" - # Create MPMD command file for this member - rm -f "cmdfile.${imem}" - touch "cmdfile.${imem}" - chmod 755 "cmdfile.${imem}" + done # for imem in $(seq 1 "${NMEM_REGRID}"); do + in_dir=$(seq -s ", " -f "'./mem%03g/'" 1 "${NMEM_REGRID}") - # Create commands to stage input files - { - echo "#!/bin/bash" +else # deterministic member only (NMEM_REGRID=1) + echo "INFO: Preparing to regrid surface increments for deterministic member." + + # Create commands to stage input files and append to the cmdfile.0 + { for FHR in "${soilinc_fhrs[@]}"; do - echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}increment.sfc.i00${FHR}.nc \ - ${memdir}/sfci00${FHR}.nc" - done + echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}ensmean_increment.sfc.i00${FHR}.nc \ + ${DATA}/sfci00${FHR}.nc" + done - if [[ "${DO_LAND_IAU}" = ".true." ]]; then + if [[ "${DO_LAND_IAU}" = ".true." ]]; then for FHI in "${landifhrs[@]}"; do - echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}increment.sfc.i00${FHI}.nc \ - ${memdir}/sfci00${FHI}.nc" + echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}ensmean_increment.sfc.i00${FHI}.nc \ + ${DATA}/sfci00${FHI}.nc" done fi - } > "cmdfile.${imem}" -done + } >> "cmdfile_in.0" + in_dir="'./'" -# Create master MPMD command file -rm -f cmdfile -touch cmdfile -chmod 755 cmdfile + # Create commands to copy output files + rm -f cmdfile_out.0 + touch cmdfile_out.0 + chmod 755 cmdfile_out.0 + { + echo "#!/bin/bash" + + if [[ "${DO_LAND_IAU}" = ".false." || "${RUN}" == "gdas" || "${RUN}" == "gfs" ]]; then + for FHR in "${soilinc_fhrs[@]}"; do + for n in $(seq 1 "${ntiles}"); do + echo "cpfs ${DATA}/sfci00${FHR}.mem1.tile${n}.nc \ + ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.i00${FHR}.tile${n}.nc" + done + done + fi + + if [[ "${DO_LAND_IAU}" = ".true." ]]; then + for n in $(seq 1 "${ntiles}"); do + echo "cpfs ${DATA}/sfci.mem1.tile${n}.nc \ + ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.tile${n}.nc" + done + fi + } >> "cmdfile_out.0" + + +fi + +# Create master MPMD command files for input and output +rm -f cmdfile_in cmdfile_out +touch cmdfile_in cmdfile_out # Append all members' command files to master command file -{ -echo "${DATA}/cmdfile.0" # fixed files -for imem in $(seq 1 "${NMEM_REGRID}"); do - echo "${DATA}/cmdfile.${imem}" -done -} >> cmdfile +if [[ -f cmdfile_in.0 ]]; then + echo "${DATA}/cmdfile_in.0" >> cmdfile_in +fi +if [[ -f cmdfile_out.0 ]]; then + echo "${DATA}/cmdfile_out.0" >> cmdfile_out +fi +if [[ "${NMEM_REGRID}" -gt 1 ]]; then + for imem in $(seq 1 "${NMEM_REGRID}"); do + if [[ -f "cmdfile_in.${imem}" ]]; then + echo "${DATA}/cmdfile_in.${imem}" >> cmdfile_in + fi + if [[ -f "cmdfile_out.${imem}" ]]; then + echo "${DATA}/cmdfile_out.${imem}" >> cmdfile_out + fi + done +fi # Run MPMD to stage input files -"${USHgfs}/run_mpmd.sh" "cmdfile" && true +"${USHgfs}/run_mpmd.sh" "cmdfile_in" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "run_mpmd.sh failed!" + err_exit "run_mpmd.sh failed to copy input and fix data!" fi +mv mpmd.out mpmd_in.out # Finish defining input/output directory list export out_dir="${in_dir}" -# -# Regrid soil increments and save to COMOUT -# +# Regrid soil increments # Increments for offline analysis # If land IAU --> deterministic only. If no land IAU --> both deterministic and ensemble @@ -180,10 +238,11 @@ if [[ "${DO_LAND_IAU}" = ".false." || "${RUN}" == "gdas" || "${RUN}" == "gfs" ]] atparse < "${regrid_nml_tmpl}" >> "regrid.nml" # Run regrid executable - ${APRUN_REGRID} "${REGRID_EXEC}" 1>"${PGMOUT}" 2>"${PGMERR}" + export pgm="${REGRID_EXEC}" + ${APRUN_REGRID} "${REGRID_EXEC}" export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "${REGRID_EXEC} failed, ABORT!" + err_exit "${REGRID_EXEC} failed to regrid soil increments (without LANDIAU), ABORT!" fi done fi @@ -202,75 +261,19 @@ if [[ "${DO_LAND_IAU}" = ".true." ]]; then # Run regrid executable export pgm="${REGRID_EXEC}" - ${APRUN_REGRID} "${REGRID_EXEC}" 1>"${PGMOUT}" 2>"${PGMERR}" + ${APRUN_REGRID} "${REGRID_EXEC}" export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "${pgm} failed, ABORT!" + err_exit "${pgm} failed to regrid soil increments (with LANDIAU), ABORT!" fi fi -# -# Save regridded files to COMOUT -# - -for imem in $(seq 1 "${NMEM_REGRID}"); do - cmem=$(printf %03i "${imem}") - memchar="mem${cmem}" - - # If deterministic job, COMOUT_ATMOS_ANALYSIS_MEM is just COMOUT_ATMOS_ANALYSIS - if (( NMEM_REGRID > 1 )); then - MEMDIR=${memchar} YMD=${PDY} HH=${cyc} declare_from_tmpl \ - COMOUT_ATMOS_ANALYSIS_MEM:COM_ATMOS_ANALYSIS_TMPL - - memdir="${DATA}/${memchar}" - else - # If deterministic job, memdir is just DATA - memdir="${DATA}" - fi - - # Create MPMD command file for this member - rm -f "cmdfile.${imem}" - touch "cmdfile.${imem}" - chmod 755 "cmdfile.${imem}" - - { - echo "#!/bin/bash" - - if [[ "${DO_LAND_IAU}" = ".false." || "${RUN}" == "gdas" || "${RUN}" == "gfs" ]]; then - for FHR in "${soilinc_fhrs[@]}"; do - for n in $(seq 1 "${ntiles}"); do - echo "cpfs ${memdir}/sfci00${FHR}.mem${imem}.tile${n}.nc \ - ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.i00${FHR}.tile${n}.nc" - done - done - fi - - if [[ "${DO_LAND_IAU}" = ".true." ]]; then - for n in $(seq 1 "${ntiles}"); do - echo "cpfs ${memdir}/sfci.mem${imem}.tile${n}.nc \ - ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.tile${n}.nc" - done - fi - } > "cmdfile.${imem}" -done - -# Create master MPMD command file -rm -f cmdfile -touch cmdfile -chmod 755 cmdfile - -# Append all members' command files to master command file -{ -for imem in $(seq 1 "${NMEM_REGRID}"); do - echo "${DATA}/cmdfile.${imem}" -done -} >> cmdfile - # Run MPMD to save output files -"${USHgfs}/run_mpmd.sh" "cmdfile" && true +"${USHgfs}/run_mpmd.sh" "cmdfile_out" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "run_mpmd.sh failed!" + err_exit "run_mpmd.sh failed to copy output files to COMOUT, ABORT!" fi +mv mpmd.out mpmd_out.out exit 0 From 4ff8e191673014610822024ceaba9ed51c0e67ee Mon Sep 17 00:00:00 2001 From: Neil Barton <103681022+NeilBarton-NOAA@users.noreply.github.com> Date: Thu, 4 Dec 2025 15:16:06 -0500 Subject: [PATCH 08/27] Reduction in Ocean and Sea Ice Output (#4200) Reducing the I/O burden by reducing the number of variables, layers, and adding compression. Also adds archiving for native subsets --- .../gefs/{config.nsst => config.nsst.j2} | 2 +- dev/parm/config/gefs/config.oceanice_products | 3 +- dev/parm/config/gefs/config.ufs | 6 +- dev/parm/config/gefs/yaml/defaults.yaml | 2 + dev/parm/config/gfs/config.oceanice_products | 2 + dev/parm/config/gfs/config.ufs | 6 +- dev/parm/config/sfs/config.base.j2 | 19 +----- dev/parm/config/sfs/config.nsst | 1 - dev/parm/config/sfs/config.nsst.j2 | 32 ++++++++++ dev/parm/config/sfs/yaml/defaults.yaml | 2 + dev/workflow/applications/sfs.py | 9 ++- dev/workflow/rocoto/gfs_tasks.py | 4 +- dev/workflow/rocoto/sfs_tasks.py | 31 ++++++++++ jobs/JGLOBAL_ARCHIVE_TARS | 1 + parm/archive/ice_native.yaml.j2 | 7 +++ parm/archive/ocean_native.yaml.j2 | 7 +++ parm/post/oceanice_products_gefs.yaml | 48 +++++++++++---- parm/post/oceanice_products_gfs.yaml | 58 ++++++++++++++----- parm/post/oceanice_products_sfs.yaml | 46 ++++++++++++--- parm/ufs/fv3/diag_table | 4 +- ush/python/pygfs/task/oceanice_products.py | 41 +++++++++---- versions/fix.ver | 2 +- 22 files changed, 257 insertions(+), 76 deletions(-) rename dev/parm/config/gefs/{config.nsst => config.nsst.j2} (96%) delete mode 120000 dev/parm/config/sfs/config.nsst create mode 100644 dev/parm/config/sfs/config.nsst.j2 create mode 100644 parm/archive/ice_native.yaml.j2 create mode 100644 parm/archive/ocean_native.yaml.j2 diff --git a/dev/parm/config/gefs/config.nsst b/dev/parm/config/gefs/config.nsst.j2 similarity index 96% rename from dev/parm/config/gefs/config.nsst rename to dev/parm/config/gefs/config.nsst.j2 index f9a29d44d3a..04abadc91dc 100644 --- a/dev/parm/config/gefs/config.nsst +++ b/dev/parm/config/gefs/config.nsst.j2 @@ -11,7 +11,7 @@ echo "BEGIN: config.nsst" export NST_MODEL=2 # nstf_name(2) : NST_SPINUP : 0 = OFF, 1 = ON, -export NST_SPINUP=0 +export NST_SPINUP="{{ NST_SPINUP }}" # nstf_name(3) : NST_RESV (Reserved, NSST Analysis) : 0 = OFF, 1 = ON export NST_RESV=0 diff --git a/dev/parm/config/gefs/config.oceanice_products b/dev/parm/config/gefs/config.oceanice_products index 48483613f43..7b30de84bc5 100644 --- a/dev/parm/config/gefs/config.oceanice_products +++ b/dev/parm/config/gefs/config.oceanice_products @@ -7,9 +7,10 @@ echo "BEGIN: config.oceanice_products" # Get task specific resources source "${EXPDIR}/config.resources" oceanice_products +export write_grib2=False +export write_netcdf=False export OCEANICEPRODUCTS_CONFIG="${PARMgfs}/post/oceanice_products_${NET}.yaml" # Maximum number of rocoto tasks per member export MAX_TASKS=25 - echo "END: config.oceanice_products" diff --git a/dev/parm/config/gefs/config.ufs b/dev/parm/config/gefs/config.ufs index 04924ab1283..33c06d70d0a 100644 --- a/dev/parm/config/gefs/config.ufs +++ b/dev/parm/config/gefs/config.ufs @@ -311,7 +311,7 @@ if [[ "${skip_mom6}" == "false" ]]; then TOPOEDITS="ufs.topo_edits_011818.nc" case ${RUN} in gfs|gefs|sfs) - MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_40L.nc" + MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_30L.nc" MOM6_DIAG_MISVAL="-1e34" ;; gdas|enkfgdas|enkfgfs) @@ -339,7 +339,7 @@ if [[ "${skip_mom6}" == "false" ]]; then eps_imesh="1.0e-1" case ${RUN} in gfs|gefs|sfs) - MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_40L.nc" + MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_30L.nc" MOM6_DIAG_MISVAL="-1e34" ;; gdas|enkfgdas|enkfgfs) @@ -368,7 +368,7 @@ if [[ "${skip_mom6}" == "false" ]]; then eps_imesh="1.0e-1" case ${RUN} in gfs|gefs|sfs) - MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_40L.nc" + MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_30L.nc" MOM6_DIAG_MISVAL="-1e34" ;; gdas|enkfgdas|enkfgfs) diff --git a/dev/parm/config/gefs/yaml/defaults.yaml b/dev/parm/config/gefs/yaml/defaults.yaml index e20890d5582..b302a8bf30b 100644 --- a/dev/parm/config/gefs/yaml/defaults.yaml +++ b/dev/parm/config/gefs/yaml/defaults.yaml @@ -29,6 +29,8 @@ fcst: MONO: "non-mono" ocn: MOM6_INTERP_ICS: "NO" +nsst: + NST_SPINUP: 0 # config.aero has just a system-specific path to add. # This is handled by the setup_expt.py, but it has to be told to write to it. aero: {} diff --git a/dev/parm/config/gfs/config.oceanice_products b/dev/parm/config/gfs/config.oceanice_products index 6cce26997ce..7f1d94bf0b9 100644 --- a/dev/parm/config/gfs/config.oceanice_products +++ b/dev/parm/config/gfs/config.oceanice_products @@ -10,6 +10,8 @@ source "${EXPDIR}/config.resources" oceanice_products # Maximum number of rocoto tasks per member export MAX_TASKS=25 +export write_grib2=False +export write_netcdf=False export OCEANICEPRODUCTS_CONFIG="${PARMgfs}/post/oceanice_products_gfs.yaml" # No. of forecast hours to process in a single job diff --git a/dev/parm/config/gfs/config.ufs b/dev/parm/config/gfs/config.ufs index 6c883d66bf7..411b0461b46 100644 --- a/dev/parm/config/gfs/config.ufs +++ b/dev/parm/config/gfs/config.ufs @@ -451,7 +451,7 @@ if [[ "${skip_mom6}" == "false" ]]; then TOPOEDITS="ufs.topo_edits_011818.nc" case ${RUN} in gfs|gefs|sfs|gcafs) - MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_40L.nc" + MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_30L.nc" MOM6_DIAG_MISVAL="-1e34" ;; gdas|enkfgdas|enkfgfs) @@ -479,7 +479,7 @@ if [[ "${skip_mom6}" == "false" ]]; then eps_imesh="1.0e-1" case ${RUN} in gfs|gefs|sfs|gcafs) - MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_40L.nc" + MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_30L.nc" MOM6_DIAG_MISVAL="-1e34" ;; gdas|enkfgdas|enkfgfs) @@ -516,7 +516,7 @@ if [[ "${skip_mom6}" == "false" ]]; then eps_imesh="1.0e-1" case ${RUN} in gfs|gefs|sfs|gcafs) - MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_40L.nc" + MOM6_DIAG_COORD_DEF_Z_FILE="interpolate_zgrid_30L.nc" MOM6_DIAG_MISVAL="-1e34" ;; gdas|enkfgdas|enkfgfs) diff --git a/dev/parm/config/sfs/config.base.j2 b/dev/parm/config/sfs/config.base.j2 index 32a26ab5f8a..bff4c3be6ce 100644 --- a/dev/parm/config/sfs/config.base.j2 +++ b/dev/parm/config/sfs/config.base.j2 @@ -318,23 +318,8 @@ export DO_METP="NO" # Run METPLUS jobs - set METPLUS settings in config. export DO_FIT2OBS="NO" # Run fit to observations package # Archiving options -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_ARCHCOM="YES" -else - export DO_ARCHCOM="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 -export ARCH_FCSTICFREQ=1 # Archive frequency in days for gdas and gfs forecast-only capability -export ARCH_EXPDIR='YES' # Archive the EXPDIR configs, XML, and database -export ARCH_EXPDIR_FREQ=0 # How often to archive the EXPDIR in hours or 0 for first and last cycle only -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 DO_ARCHCOM="NO" # Tar and archive the COM directories +export ARCHCOM_TO="{{ ARCHCOM_TO }}" # Valid options are hpss, globus_hpss, and local # Number of regional collectives to create soundings for export NUM_SND_COLLECTIVES=${NUM_SND_COLLECTIVES:-9} diff --git a/dev/parm/config/sfs/config.nsst b/dev/parm/config/sfs/config.nsst deleted file mode 120000 index 3a015c1d65f..00000000000 --- a/dev/parm/config/sfs/config.nsst +++ /dev/null @@ -1 +0,0 @@ -../gefs/config.nsst \ No newline at end of file diff --git a/dev/parm/config/sfs/config.nsst.j2 b/dev/parm/config/sfs/config.nsst.j2 new file mode 100644 index 00000000000..137e785eb65 --- /dev/null +++ b/dev/parm/config/sfs/config.nsst.j2 @@ -0,0 +1,32 @@ +#! /usr/bin/env bash + +########## config.nsst ########## +# NSST specific + +echo "BEGIN: config.nsst" + +# NSST parameters contained within nstf_name + +# nstf_name(1) : NST_MODEL (NSST Model) : 0 = OFF, 1 = ON but uncoupled, 2 = ON and coupled +export NST_MODEL=2 + +# nstf_name(2) : NST_SPINUP : 0 = OFF, 1 = ON, +export NST_SPINUP="{{ NST_SPINUP }}" + +# nstf_name(3) : NST_RESV (Reserved, NSST Analysis) : 0 = OFF, 1 = ON +export NST_RESV=0 + +# nstf_name(4,5) : ZSEA1, ZSEA2 the two depths to apply vertical average (bias correction) +export ZSEA1=0 +export ZSEA2=0 + +export NST_GSI=3 # default 0: No NST info at all; + # 1: Input NST info but not used in GSI; + # 2: Input NST info, used in CRTM simulation, no Tr analysis + # 3: Input NST info, used in both CRTM simulation and Tr analysis +export NSTINFO=0 # number of elements added in obs. data array (default = 0) +if [[ ${NST_GSI} -gt 0 ]]; then + export NSTINFO=4 +fi + +echo "END: config.nsst" diff --git a/dev/parm/config/sfs/yaml/defaults.yaml b/dev/parm/config/sfs/yaml/defaults.yaml index c322c9a0142..305183fdf88 100644 --- a/dev/parm/config/sfs/yaml/defaults.yaml +++ b/dev/parm/config/sfs/yaml/defaults.yaml @@ -29,6 +29,8 @@ fcst: MONO: "mono" ocn: MOM6_INTERP_ICS: "NO" +nsst: + NST_SPINUP: 0 # config.aero has just a system-specific path to add. # This is handled by the setup_expt.py, but it has to be told to write to it. aero: {} diff --git a/dev/workflow/applications/sfs.py b/dev/workflow/applications/sfs.py index d08e028fdcc..89c6f4e9788 100644 --- a/dev/workflow/applications/sfs.py +++ b/dev/workflow/applications/sfs.py @@ -93,6 +93,8 @@ def _get_app_configs(self, run): if options['do_archcom']: configs += ['arch_tars'] + if options['do_globusarch']: + configs += ['globus'] configs += ['arch_vrfy', 'cleanup'] @@ -164,7 +166,12 @@ def get_task_names(self): if options['do_extractvars']: tasks += ['extractvars'] - # TODO: Add archive + # TODO add archiving for SFS + # if options['do_archcom']: + # tasks += ['arch_tars'] + # if options['do_globusarch']: + # tasks += ['globus'] + tasks += ['cleanup'] return {f"{self.run}": tasks} diff --git a/dev/workflow/rocoto/gfs_tasks.py b/dev/workflow/rocoto/gfs_tasks.py index df2467a85fd..cc0ac3c80a3 100644 --- a/dev/workflow/rocoto/gfs_tasks.py +++ b/dev/workflow/rocoto/gfs_tasks.py @@ -2228,12 +2228,12 @@ def arch_tars(self): tarball_types.append('chem') if self.options['do_ocean']: - tarball_types.extend(['ocean_6hravg', 'ocean_grib2', 'gfs_flux_1p00']) + tarball_types.extend(['ocean_6hravg', 'ocean_native', 'gfs_flux_1p00']) if self.options.get('do_jediocnvar', False) and self.app_config.mode == 'cycled': tarball_types.append('gfsocean_analysis') if self.options['do_ice']: - tarball_types.extend(['ice_6hravg', 'ice_grib2']) + tarball_types.extend(['ice_6hravg', 'ice_native']) if self.options['do_bufrsnd']: tarball_types.append('gfs_downstream') diff --git a/dev/workflow/rocoto/sfs_tasks.py b/dev/workflow/rocoto/sfs_tasks.py index 9113a5d9bb4..2a8906e073e 100644 --- a/dev/workflow/rocoto/sfs_tasks.py +++ b/dev/workflow/rocoto/sfs_tasks.py @@ -612,6 +612,30 @@ def arch_tars(self): return task + # Globus transfer for HPSS archiving + def globus(self): + deps = [] + dep_dict = {'type': 'task', 'name': f'{self.run}_arch_tars'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep=deps) + + resources = self.get_resource('globus') + task_name = f'{self.run}_globus_arch' + task_dict = {'task_name': task_name, + 'resources': resources, + 'dependency': dependencies, + 'envars': self.envars, + 'cycledef': self.run, + 'command': f'{self.HOMEgfs}/dev/jobs/globus_arch.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 cleanup(self): deps = [] dep_dict = {'type': 'metatask', 'name': f'{self.run}_atmos_prod'} @@ -637,6 +661,13 @@ def cleanup(self): if self.options['do_extractvars']: dep_dict = {'type': 'metatask', 'name': f'{self.run}_extractvars'} deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_archcom']: + if self.options['do_globusarch']: + dep_dict = {'type': 'task', 'name': f'{self.run}_globus_arch'} + else: + dep_dict = {'type': 'task', 'name': f'{self.run}_arch_tars'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep=deps) dependencies = rocoto.create_dependency(dep=deps, dep_condition='and') resources = self.get_resource('cleanup') task_name = f'{self.run}_cleanup' diff --git a/jobs/JGLOBAL_ARCHIVE_TARS b/jobs/JGLOBAL_ARCHIVE_TARS index 9614ecb18e2..67b45b993ab 100755 --- a/jobs/JGLOBAL_ARCHIVE_TARS +++ b/jobs/JGLOBAL_ARCHIVE_TARS @@ -32,6 +32,7 @@ YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ COMIN_ICE_INPUT:COM_ICE_INPUT_TMPL \ COMIN_ICE_RESTART:COM_ICE_RESTART_TMPL \ COMIN_ICE_GRIB:COM_ICE_GRIB_TMPL \ + COMIN_ICE_NETCDF:COM_ICE_NETCDF_TMPL \ COMIN_OBS:COM_OBS_TMPL \ COMIN_TOP:COM_TOP_TMPL \ COMIN_OCEAN_HISTORY:COM_OCEAN_HISTORY_TMPL \ diff --git a/parm/archive/ice_native.yaml.j2 b/parm/archive/ice_native.yaml.j2 new file mode 100644 index 00000000000..546650a0225 --- /dev/null +++ b/parm/archive/ice_native.yaml.j2 @@ -0,0 +1,7 @@ +ice_native: + name: "ICE_NATIVE" + target: "{{ ATARDIR }}/{{ cycle_YMDH }}/ice_native_subset.tar" + required: + {% for fhr in range(FHOUT_ICE_GFS, FHMAX_GFS + FHOUT_ICE_GFS, FHOUT_ICE_GFS) %} + - "{{ COMIN_ICE_NETCDF | relpath(ROTDIR) }}/native/{{ RUN }}.t{{ cycle_HH }}z.native.f{{ '%03d' % fhr }}.nc" + {% endfor %} diff --git a/parm/archive/ocean_native.yaml.j2 b/parm/archive/ocean_native.yaml.j2 new file mode 100644 index 00000000000..51c039c06bb --- /dev/null +++ b/parm/archive/ocean_native.yaml.j2 @@ -0,0 +1,7 @@ +ocean_native: + name: "OCEAN_NATIVE" + target: "{{ ATARDIR }}/{{ cycle_YMDH }}/ocean_native_subset.tar" + required: + {% for fhr in range(FHOUT_OCN_GFS, FHMAX_GFS + FHOUT_OCN_GFS, FHOUT_OCN_GFS) %} + - "{{ COMIN_OCEAN_NETCDF | relpath(ROTDIR) }}/native/{{ RUN }}.t{{ cycle_HH }}z.native.f{{ '%03d' % fhr }}.nc" + {% endfor %} diff --git a/parm/post/oceanice_products_gefs.yaml b/parm/post/oceanice_products_gefs.yaml index b2651fdc331..a797efa6364 100644 --- a/parm/post/oceanice_products_gefs.yaml +++ b/parm/post/oceanice_products_gefs.yaml @@ -1,16 +1,17 @@ ocnicepost: executable: "ocnicepost.x" namelist: - write_grib2: True - write_netcdf: False + write_grib2: {{ write_grib2 }} + write_netcdf: {{ write_netcdf }} debug: False fix_data: mkdir: - "{{ DATA }}" copy: - - ["{{ EXECgfs }}/ocnicepost.x", "{{ DATA }}/"] - ["{{ PARMgfs }}/post/ocnicepost.nml.jinja2", "{{ DATA }}/"] - - ["{{ PARMgfs }}/post/{{ component }}_gefs.csv", "{{ DATA }}/{{ component }}.csv"] + {% if write_grib2 or write_netcdf %} + - ["{{ PARMgfs }}/post/{{ component }}_{{ RUN }}.csv", "{{ DATA }}/{{ component }}.csv"] + - ["{{ EXECgfs }}/ocnicepost.x", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Bu.to.Ct.bilinear.nc", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Cu.to.Ct.bilinear.nc", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Cv.to.Ct.bilinear.nc", "{{ DATA }}/"] @@ -19,6 +20,7 @@ ocnicepost: - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Ct.to.rect.{{ grid }}.conserve.nc", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/template.global.{{ grid }}.gb2", "{{ DATA }}/"] {% endfor %} + {% endif %} ocean: namelist: @@ -28,11 +30,15 @@ ocean: cosvar: "cos_rot" angvar: "" {% if model_grid == 'mx025' or model_grid == 'mx050' or model_grid == 'mx100' %} - ocean_levels: [5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 226, 241, 267, 309, 374, 467, 594, 757, 960, 1204, 1490, 1817, 2184, 2587, 3024, 3489, 3977, 4481] + ocean_levels: [1, 3, 5, 10, 20, 30, 50, 100, 200, 500, 1000] {% elif model_grid == 'mx500' %} - ocean_levels: [5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 226, 241, 267] + ocean_levels: [2.5, 7.5, 12.5, 17.5, 116] {% endif %} - subset: ['SSH', 'SST', 'SSS', 'speed', 'MLD_003', 'latent', 'sensible', 'SW', 'LW', 'LwLatSens', 'Heat_PmE', 'SSU', 'SSV', 'taux', 'tauy', 'temp', 'tob', 'so', 'uo', 'vo'] + subset: + variables: ['SSH', 'SST', 'SSS', 'speed', 'MLD_003', 'latent', 'sensible', 'SW', 'LW', 'LwLatSens', 'Heat_PmE', 'SSU', 'SSV', 'taux', 'tauy', 'temp', 'tob', 'so', 'uo', 'vo'] + compress_with: 'zlib' + compress: True + compress_level: 9 data_in: copy: - ["{{ COMIN_OCEAN_HISTORY }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ interval }}hr_avg.f{{ '%03d' % forecast_hour }}.nc", "{{ DATA }}/ocean.nc"] @@ -40,14 +46,23 @@ ocean: mkdir: - "{{ COMOUT_OCEAN_NETCDF }}/native" {% for grid in product_grids %} + {% if write_netcdf %} - "{{ COMOUT_OCEAN_NETCDF }}/{{ grid }}" + {% endif %} + {% if write_grib2 %} - "{{ COMOUT_OCEAN_GRIB }}/{{ grid }}" + {% endif %} {% endfor %} copy: - - ["{{ DATA }}/ocean_subset.nc", "{{ COMOUT_OCEAN_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.tripolar.f{{ '%03d' % forecast_hour }}.nc"] + - ["{{ DATA }}/ocean_subset.nc", "{{ COMOUT_OCEAN_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.native.f{{ '%03d' % forecast_hour }}.nc"] {% for grid in product_grids %} + {% if write_netcdf %} + - ["{{ DATA }}/ocean.{{ grid }}.nc", "{{ COMOUT_OCEAN_NETCDF }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.nc"] + {% endif %} + {% if write_grib2 %} - ["{{ DATA }}/ocean.{{ grid }}.grib2", "{{ COMOUT_OCEAN_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2"] - ["{{ DATA }}/ocean.{{ grid }}.grib2.idx", "{{ COMOUT_OCEAN_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2.idx"] + {% endif %} {% endfor %} ice: @@ -57,7 +72,11 @@ ice: sinvar: "" cosvar: "" angvar: "ANGLET" - subset: ['hi_1', 'hs_1', 'aice_1', 'Tsfc_1', 'uvel_1', 'vvel_1', 'frzmlt_1', 'albsni_1'] + subset: + variables: ['hi_1', 'hs_1', 'aice_1', 'Tsfc_1', 'uvel_1', 'vvel_1', 'frzmlt_1', 'albsni_1', 'tmask', 'tarea'] + compress_with: 'zlib' + compress: True + compress_level: 9 data_in: copy: - ["{{ COMIN_ICE_HISTORY }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ interval }}hr_avg.f{{ '%03d' % forecast_hour }}.nc", "{{ DATA }}/ice.nc"] @@ -65,12 +84,21 @@ ice: mkdir: - "{{ COMOUT_ICE_NETCDF }}/native" {% for grid in product_grids %} + {% if write_netcdf %} - "{{ COMOUT_ICE_NETCDF }}/{{ grid }}" + {% endif %} + {% if write_grib2 %} - "{{ COMOUT_ICE_GRIB }}/{{ grid }}" + {% endif %} {% endfor %} copy: - - ["{{ DATA }}/ice_subset.nc", "{{ COMOUT_ICE_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.tripolar.f{{ '%03d' % forecast_hour }}.nc"] + - ["{{ DATA }}/ice_subset.nc", "{{ COMOUT_ICE_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.native.f{{ '%03d' % forecast_hour }}.nc"] {% for grid in product_grids %} + {% if write_netcdf %} + - ["{{ DATA }}/ice.{{ grid }}.nc", "{{ COMOUT_ICE_NETCDF }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.nc"] + {% endif %} + {% if write_grib2 %} - ["{{ DATA }}/ice.{{ grid }}.grib2", "{{ COMOUT_ICE_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2"] - ["{{ DATA }}/ice.{{ grid }}.grib2.idx", "{{ COMOUT_ICE_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2.idx"] + {% endif %} {% endfor %} diff --git a/parm/post/oceanice_products_gfs.yaml b/parm/post/oceanice_products_gfs.yaml index 9604b71560e..6d8355fb491 100644 --- a/parm/post/oceanice_products_gfs.yaml +++ b/parm/post/oceanice_products_gfs.yaml @@ -1,16 +1,17 @@ ocnicepost: executable: "ocnicepost.x" namelist: - write_grib2: True - write_netcdf: False + write_grib2: {{ write_grib2 }} + write_netcdf: {{ write_netcdf }} debug: False fix_data: mkdir: - "{{ DATA }}" copy: - - ["{{ EXECgfs }}/ocnicepost.x", "{{ DATA }}/"] - ["{{ PARMgfs }}/post/ocnicepost.nml.jinja2", "{{ DATA }}/"] - - ["{{ PARMgfs }}/post/{{ component }}_gfs.csv", "{{ DATA }}/{{ component }}.csv"] + {% if write_grib2 or write_netcdf %} + - ["{{ PARMgfs }}/post/{{ component }}_{{ RUN }}.csv", "{{ DATA }}/{{ component }}.csv"] + - ["{{ EXECgfs }}/ocnicepost.x", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Bu.to.Ct.bilinear.nc", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Cu.to.Ct.bilinear.nc", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Cv.to.Ct.bilinear.nc", "{{ DATA }}/"] @@ -19,6 +20,7 @@ ocnicepost: - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Ct.to.rect.{{ grid }}.conserve.nc", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/template.global.{{ grid }}.gb2", "{{ DATA }}/"] {% endfor %} + {% endif %} ocean: namelist: @@ -28,25 +30,39 @@ ocean: cosvar: "cos_rot" angvar: "" {% if model_grid == 'mx025' or model_grid == 'mx050' or model_grid == 'mx100' %} - ocean_levels: [5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 226, 241, 267, 309, 374, 467, 594, 757, 960, 1204, 1490, 1817, 2184, 2587, 3024, 3489, 3977, 4481] + ocean_levels: [1, 3, 5, 10, 20, 30, 50, 100, 200, 500, 1000] {% elif model_grid == 'mx500' %} - ocean_levels: [5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 226, 241, 267] + ocean_levels: [2.5, 7.5, 12.5, 17.5, 116] {% endif %} - subset: ['SSH', 'SST', 'SSS', 'speed', 'MLD_003', 'latent', 'sensible', 'SW', 'LW', 'LwLatSens', 'Heat_PmE', 'SSU', 'SSV', 'taux', 'tauy', 'temp', 'so', 'uo', 'vo'] + subset: + variables: ['SSH', 'MLD_003', 'SST', 'SSS', 'temp', 'tob', 'so', 'uo', 'vo'] + compress_with: 'zlib' + compress: True + compress_level: 9 data_in: copy: - - ["{{ COMIN_OCEAN_HISTORY }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.6hr_avg.f{{ '%03d' % forecast_hour }}.nc", "{{ DATA }}/ocean.nc"] + - ["{{ COMIN_OCEAN_HISTORY }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ interval }}hr_avg.f{{ '%03d' % forecast_hour }}.nc", "{{ DATA }}/ocean.nc"] data_out: mkdir: - - "{{ COMOUT_OCEAN_NETCDF }}" + - "{{ COMOUT_OCEAN_NETCDF }}/native" {% for grid in product_grids %} + {% if write_netcdf %} + - "{{ COMOUT_OCEAN_NETCDF }}/{{ grid }}" + {% endif %} + {% if write_grib2 %} - "{{ COMOUT_OCEAN_GRIB }}/{{ grid }}" + {% endif %} {% endfor %} copy: - - ["{{ DATA }}/ocean_subset.nc", "{{ COMOUT_OCEAN_NETCDF }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.tripolar.f{{ '%03d' % forecast_hour }}.nc"] + - ["{{ DATA }}/ocean_subset.nc", "{{ COMOUT_OCEAN_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.native.f{{ '%03d' % forecast_hour }}.nc"] {% for grid in product_grids %} + {% if write_netcdf %} + - ["{{ DATA }}/ocean.{{ grid }}.nc", "{{ COMOUT_OCEAN_NETCDF }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.nc"] + {% endif %} + {% if write_grib2 %} - ["{{ DATA }}/ocean.{{ grid }}.grib2", "{{ COMOUT_OCEAN_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2"] - ["{{ DATA }}/ocean.{{ grid }}.grib2.idx", "{{ COMOUT_OCEAN_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2.idx"] + {% endif %} {% endfor %} ice: @@ -56,19 +72,33 @@ ice: sinvar: "" cosvar: "" angvar: "ANGLET" - subset: ['hi_h', 'hs_h', 'aice_h', 'Tsfc_h', 'uvel_h', 'vvel_h', 'frzmlt_h', 'albsni_h'] + subset: + variables: ['hi_h', 'hs_h', 'aice_h', 'Tsfc_h', 'uvel_h', 'vvel_h', 'albsni_h', 'tarea', 'tmask'] + compress_with: 'zlib' + compress: True + compress_level: 9 data_in: copy: - - ["{{ COMIN_ICE_HISTORY }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.6hr_avg.f{{ '%03d' % forecast_hour }}.nc", "{{ DATA }}/ice.nc"] + - ["{{ COMIN_ICE_HISTORY }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ interval }}hr_avg.f{{ '%03d' % forecast_hour }}.nc", "{{ DATA }}/ice.nc"] data_out: mkdir: - - "{{ COMOUT_ICE_NETCDF }}" + - "{{ COMOUT_ICE_NETCDF }}/native" {% for grid in product_grids %} + {% if write_netcdf %} + - "{{ COMOUT_ICE_NETCDF }}/{{ grid }}" + {% endif %} + {% if write_grib2 %} - "{{ COMOUT_ICE_GRIB }}/{{ grid }}" + {% endif %} {% endfor %} copy: - - ["{{ DATA }}/ice_subset.nc", "{{ COMOUT_ICE_NETCDF }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.tripolar.f{{ '%03d' % forecast_hour }}.nc"] + - ["{{ DATA }}/ice_subset.nc", "{{ COMOUT_ICE_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.native.f{{ '%03d' % forecast_hour }}.nc"] {% for grid in product_grids %} + {% if write_netcdf %} + - ["{{ DATA }}/ice.{{ grid }}.nc", "{{ COMOUT_ICE_NETCDF }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.nc"] + {% endif %} + {% if write_grib2 %} - ["{{ DATA }}/ice.{{ grid }}.grib2", "{{ COMOUT_ICE_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2"] - ["{{ DATA }}/ice.{{ grid }}.grib2.idx", "{{ COMOUT_ICE_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2.idx"] + {% endif %} {% endfor %} diff --git a/parm/post/oceanice_products_sfs.yaml b/parm/post/oceanice_products_sfs.yaml index e38e545dce3..086af354844 100644 --- a/parm/post/oceanice_products_sfs.yaml +++ b/parm/post/oceanice_products_sfs.yaml @@ -1,16 +1,17 @@ ocnicepost: executable: "ocnicepost.x" namelist: - write_grib2: True - write_netcdf: False + write_grib2: {{ write_grib2 }} + write_netcdf: {{ write_netcdf }} debug: False fix_data: mkdir: - "{{ DATA }}" copy: - - ["{{ EXECgfs }}/ocnicepost.x", "{{ DATA }}/"] - ["{{ PARMgfs }}/post/ocnicepost.nml.jinja2", "{{ DATA }}/"] - - ["{{ PARMgfs }}/post/{{ component }}_gfs.csv", "{{ DATA }}/{{ component }}.csv"] + {% if write_grib2 or write_netcdf %} + - ["{{ PARMgfs }}/post/{{ component }}_{{ RUN }}.csv", "{{ DATA }}/{{ component }}.csv"] + - ["{{ EXECgfs }}/ocnicepost.x", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Bu.to.Ct.bilinear.nc", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Cu.to.Ct.bilinear.nc", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Cv.to.Ct.bilinear.nc", "{{ DATA }}/"] @@ -19,6 +20,7 @@ ocnicepost: - ["{{ FIXgfs }}/mom6/post/{{ model_grid }}/tripole.{{ model_grid }}.Ct.to.rect.{{ grid }}.conserve.nc", "{{ DATA }}/"] - ["{{ FIXgfs }}/mom6/post/template.global.{{ grid }}.gb2", "{{ DATA }}/"] {% endfor %} + {% endif %} ocean: namelist: @@ -28,11 +30,15 @@ ocean: cosvar: "cos_rot" angvar: "" {% if model_grid == 'mx025' or model_grid == 'mx050' or model_grid == 'mx100' %} - ocean_levels: [5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 226, 241, 267, 309, 374, 467, 594, 757, 960, 1204, 1490, 1817, 2184, 2587, 3024, 3489, 3977, 4481] + ocean_levels: [1, 3, 5, 10, 20, 30, 50, 100, 200, 500, 1000] {% elif model_grid == 'mx500' %} ocean_levels: [5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 226, 241, 267] {% endif %} - subset: ['SSH', 'SST', 'SSS', 'speed', 'MLD_003', 'latent', 'sensible', 'SW', 'LW', 'LwLatSens', 'Heat_PmE', 'SSU', 'SSV', 'taux', 'tauy', 'temp', 'tob', 'so', 'uo', 'vo'] + subset: + variables: ['SSH', 'MLD_003', 'temp', 'tob', 'so', 'uo', 'vo'] + compress_with: 'zlib' + compress: True + compress_level: 9 data_in: copy: - ["{{ COMIN_OCEAN_HISTORY }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ interval }}hr_avg.f{{ '%03d' % forecast_hour }}.nc", "{{ DATA }}/ocean.nc"] @@ -40,14 +46,23 @@ ocean: mkdir: - "{{ COMOUT_OCEAN_NETCDF }}/native" {% for grid in product_grids %} + {% if write_netcdf %} - "{{ COMOUT_OCEAN_NETCDF }}/{{ grid }}" + {% endif %} + {% if write_grib2 %} - "{{ COMOUT_OCEAN_GRIB }}/{{ grid }}" + {% endif %} {% endfor %} copy: - - ["{{ DATA }}/ocean_subset.nc", "{{ COMOUT_OCEAN_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.tripolar.f{{ '%03d' % forecast_hour }}.nc"] + - ["{{ DATA }}/ocean_subset.nc", "{{ COMOUT_OCEAN_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.native.f{{ '%03d' % forecast_hour }}.nc"] {% for grid in product_grids %} + {% if write_netcdf %} + - ["{{ DATA }}/ocean.{{ grid }}.nc", "{{ COMOUT_OCEAN_NETCDF }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.nc"] + {% endif %} + {% if write_grib2 %} - ["{{ DATA }}/ocean.{{ grid }}.grib2", "{{ COMOUT_OCEAN_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2"] - ["{{ DATA }}/ocean.{{ grid }}.grib2.idx", "{{ COMOUT_OCEAN_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2.idx"] + {% endif %} {% endfor %} ice: @@ -57,7 +72,11 @@ ice: sinvar: "" cosvar: "" angvar: "ANGLET" - subset: ['hi_h', 'hs_h', 'aice_h', 'Tsfc_h', 'uvel_h', 'vvel_h', 'frzmlt_h', 'albsni_h'] + subset: + variables: ['hi_h', 'hs_h', 'aice_h', 'Tsfc_h', 'uvel_h', 'vvel_h', 'albsni_h', 'tmask', 'tarea'] + compress_with: 'zlib' + compress: True + compress_level: 9 data_in: copy: - ["{{ COMIN_ICE_HISTORY }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ interval }}hr_avg.f{{ '%03d' % forecast_hour }}.nc", "{{ DATA }}/ice.nc"] @@ -65,12 +84,21 @@ ice: mkdir: - "{{ COMOUT_ICE_NETCDF }}/native" {% for grid in product_grids %} + {% if write_netcdf %} - "{{ COMOUT_ICE_NETCDF }}/{{ grid }}" + {% endif %} + {% if write_grib2 %} - "{{ COMOUT_ICE_GRIB }}/{{ grid }}" + {% endif %} {% endfor %} copy: - - ["{{ DATA }}/ice_subset.nc", "{{ COMOUT_ICE_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.tripolar.f{{ '%03d' % forecast_hour }}.nc"] + - ["{{ DATA }}/ice_subset.nc", "{{ COMOUT_ICE_NETCDF }}/native/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.native.f{{ '%03d' % forecast_hour }}.nc"] {% for grid in product_grids %} + {% if write_netcdf %} + - ["{{ DATA }}/ice.{{ grid }}.nc", "{{ COMOUT_ICE_NETCDF }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.nc"] + {% endif %} + {% if write_grib2 %} - ["{{ DATA }}/ice.{{ grid }}.grib2", "{{ COMOUT_ICE_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2"] - ["{{ DATA }}/ice.{{ grid }}.grib2.idx", "{{ COMOUT_ICE_GRIB }}/{{ grid }}/{{ RUN }}.t{{ current_cycle | strftime('%H') }}z.{{ grid }}.f{{ '%03d' % forecast_hour }}.grib2.idx"] + {% endif %} {% endfor %} diff --git a/parm/ufs/fv3/diag_table b/parm/ufs/fv3/diag_table index ba4f9c793d5..ffc60816b83 100644 --- a/parm/ufs/fv3/diag_table +++ b/parm/ufs/fv3/diag_table @@ -49,10 +49,10 @@ "ocean_model", "SW", "SW", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 "ocean_model", "LW", "LW", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 "ocean_model", "evap", "evap", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 -"ocean_model", "lprec", "lprec", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 +#"ocean_model", "lprec", "lprec", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 "ocean_model", "lrunoff", "lrunoff", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 #"ocean_model", "frunoff", "frunoff", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 -"ocean_model", "fprec", "fprec", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 +#"ocean_model", "fprec", "fprec", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 "ocean_model", "LwLatSens", "LwLatSens", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 "ocean_model", "Heat_PmE", "Heat_PmE", "@[MOM6_OUTPUT_DIR]/ocn%4yr%2mo%2dy%2hr","all",.true.,"none",2 diff --git a/ush/python/pygfs/task/oceanice_products.py b/ush/python/pygfs/task/oceanice_products.py index d319608ad14..775d13e07f9 100644 --- a/ush/python/pygfs/task/oceanice_products.py +++ b/ush/python/pygfs/task/oceanice_products.py @@ -170,11 +170,13 @@ def execute(config: Dict, product_grid: str) -> None: None """ - # Run the ocnicepost.x executable - OceanIceProducts.interp(config.DATA, config.APRUN_OCNICEPOST, exec_name="ocnicepost.x") + # Run the ocnicepost.x executable if interpolated variables are wanted + if config.oceanice_yaml.ocnicepost.namelist.write_netcdf or config.oceanice_yaml.ocnicepost.namelist.write_grib2: + OceanIceProducts.interp(config.DATA, config.APRUN_OCNICEPOST, exec_name="ocnicepost.x") - # Index the interpolated grib2 file - OceanIceProducts.index(config, product_grid) + if config.oceanice_yaml.ocnicepost.namelist.write_grib2: + # Index the interpolated grib2 file + OceanIceProducts.index(config, product_grid) @staticmethod @logit(logger) @@ -274,22 +276,40 @@ def subset(config: Dict) -> None: input_file = f"{config.component}.nc" output_file = f"{config.component}_subset.nc" - varlist = config.oceanice_yaml[config.component].subset + + varlist = config.oceanice_yaml[config.component].subset.variables logger.info(f"Subsetting {varlist} from {input_file} to {output_file}") try: # open the netcdf file ds = xr.open_dataset(input_file) - - # subset the variables - ds_subset = ds[varlist] + if config.component == 'ice': + # subset the variables + ds_subset = ds[varlist] + # remove coords that were carried from original file but not used + ds_subset = ds_subset.drop_vars('ELON', errors='ignore') + ds_subset = ds_subset.drop_vars('ELAT', errors='ignore') + ds_subset = ds_subset.drop_vars('NLON', errors='ignore') + ds_subset = ds_subset.drop_vars('NLAT', errors='ignore') + + if config.component == 'ocean': + # subset ocean variables for z_levels in products + levels = config.oceanice_yaml.ocean.namelist.ocean_levels + ds_subset = ds[varlist].sel(z_l=levels) # save global attributes from the old netcdf file into new netcdf file ds_subset.attrs = ds.attrs - # save subsetted variables to a new netcdf file - ds_subset.to_netcdf(output_file) + # save subsetted variables to a new netcdf file and compress + if config.oceanice_yaml[config.component].subset.compress: + compress_with = config.oceanice_yaml[config.component].subset.compress_with + compress_level = config.oceanice_yaml[config.component].subset.compress_level + default_compression = {compress_with: True, "complevel": int(compress_level)} + compress_encoding = {var_name: default_compression for var_name in ds_subset.data_vars} + ds_subset.to_netcdf(output_file, encoding=compress_encoding) + else: + ds_subset.to_netcdf(output_file) except FileNotFoundError: logger.exception(f"FATAL ERROR: Input file not found: {input_file}") @@ -326,6 +346,5 @@ def finalize(config: Dict) -> None: # Copy "component" specific generated data to COM/ directory data_out = config.oceanice_yaml[config.component].data_out - logger.info(f"Copy processed data to COM/ directory") FileHandler(data_out).sync() diff --git a/versions/fix.ver b/versions/fix.ver index fa2b4311fad..d48482e93ae 100644 --- a/versions/fix.ver +++ b/versions/fix.ver @@ -17,7 +17,7 @@ export gdas_snow_ver=20241210 export glwu_ver=20220805 export gsi_ver=20251105 export lut_ver=20220805 -export mom6_ver=20240416 +export mom6_ver=20250128 export orog_ver=20240917 export reg2grb2_ver=20220805 export sfc_climo_ver=20220805 From 8ae8674ec4b9bdf1d93de4f80375d7ef1bd20cea Mon Sep 17 00:00:00 2001 From: David Huber <69919478+DavidHuber-NOAA@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:42:24 +0000 Subject: [PATCH 09/27] Update PR template for expected changes (#4278) This updates the PR template to include checklist items for expected changes. --- .github/pull_request_template.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9e9c9eccfec..41d02f0af95 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -41,6 +41,11 @@ # Change characteristics +- Is this change expected to change outputs (e.g. value changes to existing outputs, new files stored in COM, files removed from COM, filename changes, additions/subtractions to archives)? YES/NO (If YES, please indicate to which system(s)) + - [ ] GFS + - [ ] GEFS + - [ ] SFS + - [ ] GCAFS - Is this a breaking change (a change in existing functionality)? YES/NO - Does this change require a documentation update? YES/NO - Does this change require an update to any of the following submodules? YES/NO (If YES, please add a link to any PRs that are pending.) From b6604d06d7d9e72bffa15f947fc47e7e680dad9a Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Fri, 5 Dec 2025 09:53:45 -0500 Subject: [PATCH 10/27] Rename a bunch of jgdas/exgdas to jglobal/exglobal (#4293) --- dev/jobs/analdiag.sh | 2 +- dev/jobs/earc_tars.sh | 2 +- dev/jobs/earc_vrfy.sh | 2 +- dev/jobs/ecen.sh | 2 +- dev/jobs/ecen_fv3jedi.sh | 2 +- dev/jobs/ediag.sh | 2 +- dev/jobs/eobs.sh | 2 +- dev/jobs/esfc.sh | 2 +- dev/jobs/eupd.sh | 2 +- jobs/{JGDAS_ATMOS_ANALYSIS_DIAG => JGLOBAL_ATMOS_ANALYSIS_DIAG} | 0 jobs/{JGLOBAL_ENS_ARCHIVE_TARS => JGLOBAL_ENKF_ARCHIVE_TARS} | 2 +- jobs/{JGLOBAL_ENS_ARCHIVE_VRFY => JGLOBAL_ENKF_ARCHIVE_VRFY} | 2 +- jobs/{JGDAS_ENKF_DIAG => JGLOBAL_ENKF_DIAG} | 0 jobs/{JGDAS_ENKF_ECEN => JGLOBAL_ENKF_ECEN} | 2 +- jobs/{JGDAS_ENKF_ECEN_FV3JEDI => JGLOBAL_ENKF_ECEN_FV3JEDI} | 2 +- jobs/{JGDAS_ENKF_SELECT_OBS => JGLOBAL_ENKF_SELECT_OBS} | 2 +- jobs/{JGDAS_ENKF_SFC => JGLOBAL_ENKF_SFC} | 2 +- jobs/{JGDAS_ENKF_UPDATE => JGLOBAL_ENKF_UPDATE} | 2 +- scripts/exglobal_atmos_analysis.sh | 2 ++ .../{exgdas_enkf_earc_tars.py => exglobal_enkf_earc_tars.py} | 0 .../{exgdas_enkf_earc_vrfy.py => exglobal_enkf_earc_vrfy.py} | 0 scripts/{exgdas_enkf_ecen.sh => exglobal_enkf_ecen.sh} | 0 ...xgdas_enkf_ecen_fv3jedi.py => exglobal_enkf_ecen_fv3jedi.py} | 0 .../{exgdas_enkf_select_obs.sh => exglobal_enkf_select_obs.sh} | 0 scripts/{exgdas_enkf_sfc.sh => exglobal_enkf_sfc.sh} | 0 scripts/{exgdas_enkf_update.sh => exglobal_enkf_update.sh} | 0 26 files changed, 18 insertions(+), 16 deletions(-) rename jobs/{JGDAS_ATMOS_ANALYSIS_DIAG => JGLOBAL_ATMOS_ANALYSIS_DIAG} (100%) rename jobs/{JGLOBAL_ENS_ARCHIVE_TARS => JGLOBAL_ENKF_ARCHIVE_TARS} (97%) rename jobs/{JGLOBAL_ENS_ARCHIVE_VRFY => JGLOBAL_ENKF_ARCHIVE_VRFY} (97%) rename jobs/{JGDAS_ENKF_DIAG => JGLOBAL_ENKF_DIAG} (100%) rename jobs/{JGDAS_ENKF_ECEN => JGLOBAL_ENKF_ECEN} (96%) rename jobs/{JGDAS_ENKF_ECEN_FV3JEDI => JGLOBAL_ENKF_ECEN_FV3JEDI} (96%) rename jobs/{JGDAS_ENKF_SELECT_OBS => JGLOBAL_ENKF_SELECT_OBS} (98%) rename jobs/{JGDAS_ENKF_SFC => JGLOBAL_ENKF_SFC} (97%) rename jobs/{JGDAS_ENKF_UPDATE => JGLOBAL_ENKF_UPDATE} (97%) rename scripts/{exgdas_enkf_earc_tars.py => exglobal_enkf_earc_tars.py} (100%) rename scripts/{exgdas_enkf_earc_vrfy.py => exglobal_enkf_earc_vrfy.py} (100%) rename scripts/{exgdas_enkf_ecen.sh => exglobal_enkf_ecen.sh} (100%) rename scripts/{exgdas_enkf_ecen_fv3jedi.py => exglobal_enkf_ecen_fv3jedi.py} (100%) rename scripts/{exgdas_enkf_select_obs.sh => exglobal_enkf_select_obs.sh} (100%) rename scripts/{exgdas_enkf_sfc.sh => exglobal_enkf_sfc.sh} (100%) rename scripts/{exgdas_enkf_update.sh => exglobal_enkf_update.sh} (100%) diff --git a/dev/jobs/analdiag.sh b/dev/jobs/analdiag.sh index 2849a41d7e6..7b4badebb88 100755 --- a/dev/jobs/analdiag.sh +++ b/dev/jobs/analdiag.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_ATMOS_ANALYSIS_DIAG" +"${HOMEgfs}/jobs/JGLOBAL_ATMOS_ANALYSIS_DIAG" status=$? exit "${status}" diff --git a/dev/jobs/earc_tars.sh b/dev/jobs/earc_tars.sh index 16508f162dc..15b7ad421a1 100755 --- a/dev/jobs/earc_tars.sh +++ b/dev/jobs/earc_tars.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ENS_ARCHIVE_TARS" +"${HOMEgfs}/jobs/JGLOBAL_ENKF_ARCHIVE_TARS" status=$? exit "${status}" diff --git a/dev/jobs/earc_vrfy.sh b/dev/jobs/earc_vrfy.sh index 1f6b437046c..6556a35304a 100755 --- a/dev/jobs/earc_vrfy.sh +++ b/dev/jobs/earc_vrfy.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ENS_ARCHIVE_VRFY" +"${HOMEgfs}/jobs/JGLOBAL_ENKF_ARCHIVE_VRFY" status=$? exit "${status}" diff --git a/dev/jobs/ecen.sh b/dev/jobs/ecen.sh index b202fdd291e..5d4168be54d 100755 --- a/dev/jobs/ecen.sh +++ b/dev/jobs/ecen.sh @@ -22,7 +22,7 @@ for fhr in ${fhrlst}; do export job=ecen export jobid="${job}.$$" - "${HOMEgfs}/jobs/JGDAS_ENKF_ECEN" + "${HOMEgfs}/jobs/JGLOBAL_ENKF_ECEN" status=$? if [[ ${status} -ne 0 ]]; then exit "${status}" diff --git a/dev/jobs/ecen_fv3jedi.sh b/dev/jobs/ecen_fv3jedi.sh index 0d3f13c6c57..5c4cc21f780 100755 --- a/dev/jobs/ecen_fv3jedi.sh +++ b/dev/jobs/ecen_fv3jedi.sh @@ -13,6 +13,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGDAS_ENKF_ECEN_FV3JEDI +"${HOMEgfs}"/jobs/JGLOBAL_ENKF_ECEN_FV3JEDI status=$? exit "${status}" diff --git a/dev/jobs/ediag.sh b/dev/jobs/ediag.sh index df628a147c6..44808e42094 100755 --- a/dev/jobs/ediag.sh +++ b/dev/jobs/ediag.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_ENKF_DIAG" +"${HOMEgfs}/jobs/JGLOBAL_ENKF_DIAG" status=$? exit "${status}" diff --git a/dev/jobs/eobs.sh b/dev/jobs/eobs.sh index 5821bf0f186..1c5e7fd1458 100755 --- a/dev/jobs/eobs.sh +++ b/dev/jobs/eobs.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_ENKF_SELECT_OBS" +"${HOMEgfs}/jobs/JGLOBAL_ENKF_SELECT_OBS" status=$? exit "${status}" diff --git a/dev/jobs/esfc.sh b/dev/jobs/esfc.sh index 756134fb153..ecac9e02e86 100755 --- a/dev/jobs/esfc.sh +++ b/dev/jobs/esfc.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_ENKF_SFC" +"${HOMEgfs}/jobs/JGLOBAL_ENKF_SFC" status=$? exit "${status}" diff --git a/dev/jobs/eupd.sh b/dev/jobs/eupd.sh index a9a992dd529..8a3fd4112e1 100755 --- a/dev/jobs/eupd.sh +++ b/dev/jobs/eupd.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_ENKF_UPDATE" +"${HOMEgfs}/jobs/JGLOBAL_ENKF_UPDATE" status=$? exit "${status}" diff --git a/jobs/JGDAS_ATMOS_ANALYSIS_DIAG b/jobs/JGLOBAL_ATMOS_ANALYSIS_DIAG similarity index 100% rename from jobs/JGDAS_ATMOS_ANALYSIS_DIAG rename to jobs/JGLOBAL_ATMOS_ANALYSIS_DIAG diff --git a/jobs/JGLOBAL_ENS_ARCHIVE_TARS b/jobs/JGLOBAL_ENKF_ARCHIVE_TARS similarity index 97% rename from jobs/JGLOBAL_ENS_ARCHIVE_TARS rename to jobs/JGLOBAL_ENKF_ARCHIVE_TARS index 093877876d4..2e22ada681b 100755 --- a/jobs/JGLOBAL_ENS_ARCHIVE_TARS +++ b/jobs/JGLOBAL_ENKF_ARCHIVE_TARS @@ -25,7 +25,7 @@ mkdir -p "${COMIN_CONF}" # Calls an external bash command; do not fail on unassigned/error set +eu export -n SHELLOPTS -"${SCRgfs}/exgdas_enkf_earc_tars.py" +"${SCRgfs}/exglobal_enkf_earc_tars.py" export err=$? set +x if [[ ${err} -ne 0 ]]; then diff --git a/jobs/JGLOBAL_ENS_ARCHIVE_VRFY b/jobs/JGLOBAL_ENKF_ARCHIVE_VRFY similarity index 97% rename from jobs/JGLOBAL_ENS_ARCHIVE_VRFY rename to jobs/JGLOBAL_ENKF_ARCHIVE_VRFY index 832ff9a0277..77c3d1973fc 100755 --- a/jobs/JGLOBAL_ENS_ARCHIVE_VRFY +++ b/jobs/JGLOBAL_ENKF_ARCHIVE_VRFY @@ -14,7 +14,7 @@ MEMDIR="ensstat" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ # Run archive script ############################################################### -"${SCRgfs}/exgdas_enkf_earc_vrfy.py" +"${SCRgfs}/exglobal_enkf_earc_vrfy.py" err=$? if [[ ${err} -ne 0 ]]; then exit "${err}" diff --git a/jobs/JGDAS_ENKF_DIAG b/jobs/JGLOBAL_ENKF_DIAG similarity index 100% rename from jobs/JGDAS_ENKF_DIAG rename to jobs/JGLOBAL_ENKF_DIAG diff --git a/jobs/JGDAS_ENKF_ECEN b/jobs/JGLOBAL_ENKF_ECEN similarity index 96% rename from jobs/JGDAS_ENKF_ECEN rename to jobs/JGLOBAL_ENKF_ECEN index e3024ceb43b..0d8a67fc324 100755 --- a/jobs/JGDAS_ENKF_ECEN +++ b/jobs/JGLOBAL_ENKF_ECEN @@ -36,7 +36,7 @@ MEMDIR="ensstat" RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ ############################################################### # Run relevant script -${ENKFRECENSH:-${SCRgfs}/exgdas_enkf_ecen.sh} && true +${ENKFRECENSH:-${SCRgfs}/exglobal_enkf_ecen.sh} && true export err=$? if [[ ${err} -ne 0 ]]; then err_exit diff --git a/jobs/JGDAS_ENKF_ECEN_FV3JEDI b/jobs/JGLOBAL_ENKF_ECEN_FV3JEDI similarity index 96% rename from jobs/JGDAS_ENKF_ECEN_FV3JEDI rename to jobs/JGLOBAL_ENKF_ECEN_FV3JEDI index 3d2ff374a4f..12fe96146db 100755 --- a/jobs/JGDAS_ENKF_ECEN_FV3JEDI +++ b/jobs/JGLOBAL_ENKF_ECEN_FV3JEDI @@ -36,7 +36,7 @@ mkdir -m 755 -p "${COMOUT_CONF}" # Run relevant script ############################################## -EXSCRIPT=${GDASATMRUNPY:-${SCRgfs}/exgdas_enkf_ecen_fv3jedi.py} +EXSCRIPT=${GDASATMRUNPY:-${SCRgfs}/exglobal_enkf_ecen_fv3jedi.py} ${EXSCRIPT} && true export err=$? if [[ ${err} -ne 0 ]]; then diff --git a/jobs/JGDAS_ENKF_SELECT_OBS b/jobs/JGLOBAL_ENKF_SELECT_OBS similarity index 98% rename from jobs/JGDAS_ENKF_SELECT_OBS rename to jobs/JGLOBAL_ENKF_SELECT_OBS index f5fe813ef9d..f038f524b5f 100755 --- a/jobs/JGDAS_ENKF_SELECT_OBS +++ b/jobs/JGLOBAL_ENKF_SELECT_OBS @@ -109,7 +109,7 @@ done ############################################################### # Run relevant script -${INVOBSSH:-${SCRgfs}/exgdas_enkf_select_obs.sh} && true +${INVOBSSH:-${SCRgfs}/exglobal_enkf_select_obs.sh} && true export err=$? if [[ ${err} -ne 0 ]]; then err_exit diff --git a/jobs/JGDAS_ENKF_SFC b/jobs/JGLOBAL_ENKF_SFC similarity index 97% rename from jobs/JGDAS_ENKF_SFC rename to jobs/JGLOBAL_ENKF_SFC index c2bfc6f33e4..0e33d9e4dac 100755 --- a/jobs/JGDAS_ENKF_SFC +++ b/jobs/JGLOBAL_ENKF_SFC @@ -42,7 +42,7 @@ export USE_CFP=YES ############################################################### # Run relevant script -${ENKFRESFCSH:-${SCRgfs}/exgdas_enkf_sfc.sh} && true +${ENKFRESFCSH:-${SCRgfs}/exglobal_enkf_sfc.sh} && true export err=$? if [[ ${err} -ne 0 ]]; then err_exit diff --git a/jobs/JGDAS_ENKF_UPDATE b/jobs/JGLOBAL_ENKF_UPDATE similarity index 97% rename from jobs/JGDAS_ENKF_UPDATE rename to jobs/JGLOBAL_ENKF_UPDATE index 43d39b21735..47d2fb0640b 100755 --- a/jobs/JGDAS_ENKF_UPDATE +++ b/jobs/JGLOBAL_ENKF_UPDATE @@ -28,7 +28,7 @@ MEMDIR="ensstat" RUN="enkfgdas" YMD=${GDATE:0:8} HH=${GDATE:8:2} declare_from_tm ############################################################### # Run relevant script -${ENKFUPDSH:-${SCRgfs}/exgdas_enkf_update.sh} && true +${ENKFUPDSH:-${SCRgfs}/exglobal_enkf_update.sh} && true export err=$? if [[ ${err} -ne 0 ]]; then err_exit diff --git a/scripts/exglobal_atmos_analysis.sh b/scripts/exglobal_atmos_analysis.sh index 6eb8804a59d..a53153d97e8 100755 --- a/scripts/exglobal_atmos_analysis.sh +++ b/scripts/exglobal_atmos_analysis.sh @@ -20,7 +20,9 @@ # Set environment. # Directories. +# shellcheck disable=SC2153 cd "${DATA}" || exit 1 + # Base variables rCDUMP=${rCDUMP:-"gdas"} GDUMP=${GDUMP:-"gdas"} diff --git a/scripts/exgdas_enkf_earc_tars.py b/scripts/exglobal_enkf_earc_tars.py similarity index 100% rename from scripts/exgdas_enkf_earc_tars.py rename to scripts/exglobal_enkf_earc_tars.py diff --git a/scripts/exgdas_enkf_earc_vrfy.py b/scripts/exglobal_enkf_earc_vrfy.py similarity index 100% rename from scripts/exgdas_enkf_earc_vrfy.py rename to scripts/exglobal_enkf_earc_vrfy.py diff --git a/scripts/exgdas_enkf_ecen.sh b/scripts/exglobal_enkf_ecen.sh similarity index 100% rename from scripts/exgdas_enkf_ecen.sh rename to scripts/exglobal_enkf_ecen.sh diff --git a/scripts/exgdas_enkf_ecen_fv3jedi.py b/scripts/exglobal_enkf_ecen_fv3jedi.py similarity index 100% rename from scripts/exgdas_enkf_ecen_fv3jedi.py rename to scripts/exglobal_enkf_ecen_fv3jedi.py diff --git a/scripts/exgdas_enkf_select_obs.sh b/scripts/exglobal_enkf_select_obs.sh similarity index 100% rename from scripts/exgdas_enkf_select_obs.sh rename to scripts/exglobal_enkf_select_obs.sh diff --git a/scripts/exgdas_enkf_sfc.sh b/scripts/exglobal_enkf_sfc.sh similarity index 100% rename from scripts/exgdas_enkf_sfc.sh rename to scripts/exglobal_enkf_sfc.sh diff --git a/scripts/exgdas_enkf_update.sh b/scripts/exglobal_enkf_update.sh similarity index 100% rename from scripts/exgdas_enkf_update.sh rename to scripts/exglobal_enkf_update.sh From a9123819ef7c9f56b332de9b9a3c9b92e4d9bfdc Mon Sep 17 00:00:00 2001 From: JohnSteffen-NOAA <77806417+JohnSteffen-NOAA@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:54:42 -0500 Subject: [PATCH 11/27] Specify marine yamls for gfs ocean analysis archiving (#4286) Explicitly list the marine yamls to archive during the gfsocean_analysis archiving task. This replaces the * wildcard which was grabbing all of the available yamls in the conf directory, including yaml files that do not need to be archived. --- parm/archive/gfsocean_analysis.yaml.j2 | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/parm/archive/gfsocean_analysis.yaml.j2 b/parm/archive/gfsocean_analysis.yaml.j2 index dd94b3e8019..d8a84c07c4a 100644 --- a/parm/archive/gfsocean_analysis.yaml.j2 +++ b/parm/archive/gfsocean_analysis.yaml.j2 @@ -23,7 +23,16 @@ gfsocean_analysis: - '{{ COMIN_ICE_BMATRIX | relpath(ROTDIR) }}/{{ head }}bkgerr_parametric_stddev.nc' # runtime configs - - '{{ COMIN_CONF | relpath(ROTDIR) }}/*.yaml' + - '{{ COMIN_CONF | relpath(ROTDIR) }}/{{ head }}soca_setcorscales.yaml' + - '{{ COMIN_CONF | relpath(ROTDIR) }}/{{ head }}soca_chgres.yaml' + - '{{ COMIN_CONF | relpath(ROTDIR) }}/{{ head }}soca_diagb.yaml' + - '{{ COMIN_CONF | relpath(ROTDIR) }}/{{ head }}gridgen.yaml' + - '{{ COMIN_CONF | relpath(ROTDIR) }}/{{ head }}soca_vtscales.yaml' + - '{{ COMIN_CONF | relpath(ROTDIR) }}/{{ head }}bmat_fields_metadata.yaml' + - '{{ COMIN_CONF | relpath(ROTDIR) }}/var.yaml' + # soca_parameters_diffusion_vt, and soca_parameters_diffusion_hz when present + - '{{ COMIN_CONF | relpath(ROTDIR) }}/{{ head }}soca_parameters_diffusion_??.yaml' + - '{{ COMIN_CONF | relpath(ROTDIR) }}/soca_incpostproc.yaml' optional: # obs space diags - '{{ COMIN_OCEAN_ANALYSIS | relpath(ROTDIR) }}/diags/{{ head }}ocn.*.stats.csv' From 390f243cf984b97816b6274f305012868737dfca Mon Sep 17 00:00:00 2001 From: Cory Martin Date: Mon, 8 Dec 2025 10:39:01 -0500 Subject: [PATCH 12/27] Move j-jobs and ex-scripts into dev subdirectory (#4259) This moves `jobs/` to `dev/jobs`, `dev/jobs` to `dev/job_cards/rocoto` and `scripts` to `dev/scripts` (but symlinks the latter to the original location for now. This is in anticipation for T2O where we will only want to put in `jobs/` and `scripts/` the files needed for each application from the total global-workflow develop set. --- .editorconfig | 2 +- .github/workflows/bash_code_analysis.yaml | 2 +- dev/ctests/README.md | 2 +- .../rocoto}/aeroanlfinal.sh | 2 +- dev/{jobs => job_cards/rocoto}/aeroanlgenb.sh | 2 +- dev/{jobs => job_cards/rocoto}/aeroanlinit.sh | 2 +- dev/{jobs => job_cards/rocoto}/aeroanlvar.sh | 2 +- .../rocoto}/aerosol_init.sh | 0 dev/{jobs => job_cards/rocoto}/anal.sh | 2 +- dev/{jobs => job_cards/rocoto}/analcalc.sh | 2 +- .../rocoto}/analcalc_fv3jedi.sh | 2 +- dev/{jobs => job_cards/rocoto}/analdiag.sh | 2 +- dev/{jobs => job_cards/rocoto}/anlstat.sh | 2 +- dev/{jobs => job_cards/rocoto}/arch_tars.sh | 2 +- dev/{jobs => job_cards/rocoto}/arch_vrfy.sh | 2 +- dev/{jobs => job_cards/rocoto}/atmanlfinal.sh | 2 +- .../rocoto}/atmanlfv3inc.sh | 2 +- dev/{jobs => job_cards/rocoto}/atmanlinit.sh | 2 +- dev/{jobs => job_cards/rocoto}/atmanlvar.sh | 2 +- .../rocoto}/atmensanlfinal.sh | 2 +- .../rocoto}/atmensanlfv3inc.sh | 2 +- .../rocoto}/atmensanlinit.sh | 2 +- .../rocoto}/atmensanlletkf.sh | 2 +- .../rocoto}/atmensanlobs.sh | 2 +- .../rocoto}/atmensanlsol.sh | 2 +- .../rocoto}/atmos_ensstat.sh | 2 +- .../rocoto}/atmos_products.sh | 2 +- dev/{jobs => job_cards/rocoto}/awips.sh | 2 +- .../rocoto}/awips_20km_1p0deg.sh | 4 +- dev/{jobs => job_cards/rocoto}/cleanup.sh | 2 +- dev/{jobs => job_cards/rocoto}/earc_tars.sh | 2 +- dev/{jobs => job_cards/rocoto}/earc_vrfy.sh | 2 +- dev/{jobs => job_cards/rocoto}/ecen.sh | 2 +- .../rocoto}/ecen_fv3jedi.sh | 2 +- dev/{jobs => job_cards/rocoto}/echgres.sh | 2 +- dev/{jobs => job_cards/rocoto}/ediag.sh | 2 +- dev/{jobs => job_cards/rocoto}/eobs.sh | 2 +- dev/{jobs => job_cards/rocoto}/epos.sh | 2 +- dev/{jobs => job_cards/rocoto}/esfc.sh | 2 +- dev/{jobs => job_cards/rocoto}/esnowanl.sh | 2 +- dev/{jobs => job_cards/rocoto}/eupd.sh | 2 +- dev/{jobs => job_cards/rocoto}/extractvars.sh | 2 +- dev/{jobs => job_cards/rocoto}/fbwind.sh | 2 +- dev/{jobs => job_cards/rocoto}/fcst.sh | 2 +- dev/{jobs => job_cards/rocoto}/fetch.sh | 2 +- dev/{jobs => job_cards/rocoto}/fit2obs.sh | 2 +- dev/{jobs => job_cards/rocoto}/gempak.sh | 2 +- .../rocoto}/gempakgrb2spec.sh | 2 +- dev/{jobs => job_cards/rocoto}/gempakmeta.sh | 2 +- .../rocoto}/gempakmetancdc.sh | 2 +- .../rocoto}/gempakncdcupapgif.sh | 2 +- .../rocoto}/gen_control_ic.sh | 2 +- dev/{jobs => job_cards/rocoto}/genesis.sh | 2 +- dev/{jobs => job_cards/rocoto}/genesis_fsu.sh | 2 +- dev/{jobs => job_cards/rocoto}/globus_arch.sh | 2 +- dev/{jobs => job_cards/rocoto}/globus_earc.sh | 2 +- .../rocoto}/marineanlchkpt.sh | 2 +- .../rocoto}/marineanlecen.sh | 2 +- .../rocoto}/marineanlfinal.sh | 2 +- .../rocoto}/marineanlinit.sh | 2 +- .../rocoto}/marineanlletkf.sh | 2 +- .../rocoto}/marineanlvar.sh | 2 +- dev/{jobs => job_cards/rocoto}/marinebmat.sh | 2 +- .../rocoto}/marinebmatinit.sh | 2 +- dev/{jobs => job_cards/rocoto}/metp.sh | 2 +- dev/{jobs => job_cards/rocoto}/npoess.sh | 2 +- .../rocoto}/oceanice_products.sh | 2 +- dev/{jobs => job_cards/rocoto}/offlineanl.sh | 2 +- dev/{jobs => job_cards/rocoto}/postsnd.sh | 2 +- dev/{jobs => job_cards/rocoto}/prep.sh | 2 +- .../rocoto}/prep_emissions.sh | 2 +- dev/{jobs => job_cards/rocoto}/prep_sfc.sh | 2 +- .../rocoto}/prepoceanobs.sh | 2 +- dev/{jobs => job_cards/rocoto}/sfcanl.sh | 2 +- dev/{jobs => job_cards/rocoto}/snowanl.sh | 2 +- dev/{jobs => job_cards/rocoto}/stage_ic.sh | 2 +- dev/{jobs => job_cards/rocoto}/tracker.sh | 2 +- dev/{jobs => job_cards/rocoto}/upp.sh | 2 +- dev/{jobs => job_cards/rocoto}/verfozn.sh | 2 +- dev/{jobs => job_cards/rocoto}/verfrad.sh | 2 +- dev/{jobs => job_cards/rocoto}/vminmon.sh | 2 +- dev/{jobs => job_cards/rocoto}/wave_stat.sh | 2 +- .../rocoto}/wave_stat_pnt.sh | 2 +- .../rocoto}/waveawipsbulls.sh | 2 +- .../rocoto}/waveawipsgridded.sh | 2 +- dev/{jobs => job_cards/rocoto}/wavegempak.sh | 2 +- dev/{jobs => job_cards/rocoto}/waveinit.sh | 2 +- .../rocoto}/wavepostbndpnt.sh | 2 +- .../rocoto}/wavepostbndpntbll.sh | 2 +- dev/{jobs => job_cards/rocoto}/wavepostpnt.sh | 2 +- dev/{jobs => job_cards/rocoto}/wavepostsbs.sh | 2 +- dev/{jobs => job_cards/rocoto}/waveprep.sh | 2 +- .../JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX | 0 {jobs => dev/jobs}/JGDAS_ATMOS_CHGRES_FORENKF | 0 {jobs => dev/jobs}/JGDAS_ATMOS_GEMPAK | 0 .../jobs}/JGDAS_ATMOS_GEMPAK_META_NCDC | 0 {jobs => dev/jobs}/JGDAS_ATMOS_VERFOZN | 0 {jobs => dev/jobs}/JGDAS_ATMOS_VERFRAD | 0 {jobs => dev/jobs}/JGDAS_ENKF_POST | 0 {jobs => dev/jobs}/JGDAS_FIT2OBS | 0 {jobs => dev/jobs}/JGEFS_WAVE_STAT | 0 {jobs => dev/jobs}/JGEFS_WAVE_STAT_PNT | 0 .../jobs}/JGFS_ATMOS_AWIPS_20KM_1P0DEG | 0 {jobs => dev/jobs}/JGFS_ATMOS_CYCLONE_GENESIS | 0 {jobs => dev/jobs}/JGFS_ATMOS_CYCLONE_TRACKER | 0 {jobs => dev/jobs}/JGFS_ATMOS_FBWIND | 0 {jobs => dev/jobs}/JGFS_ATMOS_FSU_GENESIS | 0 {jobs => dev/jobs}/JGFS_ATMOS_GEMPAK | 0 {jobs => dev/jobs}/JGFS_ATMOS_GEMPAK_META | 0 .../jobs}/JGFS_ATMOS_GEMPAK_NCDC_UPAPGIF | 0 .../jobs}/JGFS_ATMOS_GEMPAK_PGRB2_SPEC | 0 .../jobs}/JGFS_ATMOS_PGRB2_SPEC_NPOESS | 0 {jobs => dev/jobs}/JGFS_ATMOS_POSTSND | 0 {jobs => dev/jobs}/JGFS_ATMOS_VERIFICATION | 0 .../jobs}/JGLOBAL_AERO_ANALYSIS_FINALIZE | 0 .../jobs}/JGLOBAL_AERO_ANALYSIS_INITIALIZE | 0 .../jobs}/JGLOBAL_AERO_ANALYSIS_VARIATIONAL | 0 {jobs => dev/jobs}/JGLOBAL_ANALYSIS_STATS | 0 {jobs => dev/jobs}/JGLOBAL_ARCHIVE_TARS | 0 {jobs => dev/jobs}/JGLOBAL_ARCHIVE_VRFY | 0 .../jobs}/JGLOBAL_ATMENS_ANALYSIS_FINALIZE | 0 .../JGLOBAL_ATMENS_ANALYSIS_FV3_INCREMENT | 0 .../jobs}/JGLOBAL_ATMENS_ANALYSIS_INITIALIZE | 0 .../jobs}/JGLOBAL_ATMENS_ANALYSIS_LETKF | 0 .../jobs}/JGLOBAL_ATMENS_ANALYSIS_OBS | 0 .../jobs}/JGLOBAL_ATMENS_ANALYSIS_SOL | 0 {jobs => dev/jobs}/JGLOBAL_ATMOS_ANALYSIS | 0 .../jobs}/JGLOBAL_ATMOS_ANALYSIS_CALC | 0 .../jobs}/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI | 0 .../jobs}/JGLOBAL_ATMOS_ANALYSIS_DIAG | 0 .../jobs}/JGLOBAL_ATMOS_CHGRES_GEN_CONTROL | 0 {jobs => dev/jobs}/JGLOBAL_ATMOS_ENSSTAT | 0 {jobs => dev/jobs}/JGLOBAL_ATMOS_POST_MANAGER | 0 {jobs => dev/jobs}/JGLOBAL_ATMOS_PREP_SFC | 0 {jobs => dev/jobs}/JGLOBAL_ATMOS_PRODUCTS | 0 {jobs => dev/jobs}/JGLOBAL_ATMOS_SFCANL | 0 .../jobs}/JGLOBAL_ATMOS_TROPCY_QC_RELOC | 0 {jobs => dev/jobs}/JGLOBAL_ATMOS_UPP | 0 {jobs => dev/jobs}/JGLOBAL_ATMOS_VMINMON | 0 .../jobs}/JGLOBAL_ATM_ANALYSIS_FINALIZE | 0 .../jobs}/JGLOBAL_ATM_ANALYSIS_FV3_INCREMENT | 0 .../jobs}/JGLOBAL_ATM_ANALYSIS_INITIALIZE | 0 .../jobs}/JGLOBAL_ATM_ANALYSIS_VARIATIONAL | 0 {jobs => dev/jobs}/JGLOBAL_CLEANUP | 0 {jobs => dev/jobs}/JGLOBAL_ENKF_ARCHIVE_TARS | 0 {jobs => dev/jobs}/JGLOBAL_ENKF_ARCHIVE_VRFY | 0 {jobs => dev/jobs}/JGLOBAL_ENKF_DIAG | 0 {jobs => dev/jobs}/JGLOBAL_ENKF_ECEN | 0 {jobs => dev/jobs}/JGLOBAL_ENKF_ECEN_FV3JEDI | 0 {jobs => dev/jobs}/JGLOBAL_ENKF_SELECT_OBS | 0 {jobs => dev/jobs}/JGLOBAL_ENKF_SFC | 0 {jobs => dev/jobs}/JGLOBAL_ENKF_UPDATE | 0 {jobs => dev/jobs}/JGLOBAL_ENS_GLOBUS_ARCH | 0 {jobs => dev/jobs}/JGLOBAL_EXTRACTVARS | 0 {jobs => dev/jobs}/JGLOBAL_FETCH | 0 {jobs => dev/jobs}/JGLOBAL_FORECAST | 0 {jobs => dev/jobs}/JGLOBAL_GLOBUS_ARCH | 0 .../jobs}/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT | 0 .../jobs}/JGLOBAL_MARINE_ANALYSIS_ECEN | 0 .../jobs}/JGLOBAL_MARINE_ANALYSIS_FINALIZE | 0 .../jobs}/JGLOBAL_MARINE_ANALYSIS_INITIALIZE | 0 .../jobs}/JGLOBAL_MARINE_ANALYSIS_LETKF | 0 .../jobs}/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL | 0 {jobs => dev/jobs}/JGLOBAL_MARINE_BMAT | 0 .../jobs}/JGLOBAL_MARINE_BMAT_INITIALIZE | 0 {jobs => dev/jobs}/JGLOBAL_OCEANICE_PRODUCTS | 0 .../jobs}/JGLOBAL_OFFLINE_ATMOS_ANALYSIS | 0 {jobs => dev/jobs}/JGLOBAL_PREP_EMISSIONS | 0 {jobs => dev/jobs}/JGLOBAL_PREP_OCEAN_OBS | 0 {jobs => dev/jobs}/JGLOBAL_SNOWENS_ANALYSIS | 0 {jobs => dev/jobs}/JGLOBAL_SNOW_ANALYSIS | 0 {jobs => dev/jobs}/JGLOBAL_STAGE_IC | 0 {jobs => dev/jobs}/JGLOBAL_WAVE_GEMPAK | 0 {jobs => dev/jobs}/JGLOBAL_WAVE_INIT | 0 {jobs => dev/jobs}/JGLOBAL_WAVE_POST_BNDPNT | 0 .../jobs}/JGLOBAL_WAVE_POST_BNDPNTBLL | 0 {jobs => dev/jobs}/JGLOBAL_WAVE_POST_PNT | 0 {jobs => dev/jobs}/JGLOBAL_WAVE_POST_SBS | 0 {jobs => dev/jobs}/JGLOBAL_WAVE_PRDGEN_BULLS | 0 .../jobs}/JGLOBAL_WAVE_PRDGEN_GRIDDED | 0 {jobs => dev/jobs}/JGLOBAL_WAVE_PREP | 0 .../exgdas_aero_analysis_generate_bmatrix.py | 0 .../scripts}/exgdas_atmos_chgres_forenkf.sh | 0 .../scripts}/exgdas_atmos_gempak_gif_ncdc.sh | 0 .../scripts}/exgdas_atmos_nawips.sh | 0 .../scripts}/exgdas_atmos_verfozn.sh | 0 .../scripts}/exgdas_atmos_verfrad.sh | 0 {scripts => dev/scripts}/exgdas_enkf_post.sh | 0 .../scripts}/exgfs_aero_init_aerosol.py | 0 .../scripts}/exgfs_atmos_awips_20km_1p0deg.sh | 0 .../scripts}/exgfs_atmos_fbwind.sh | 0 .../exgfs_atmos_gempak_gif_ncdc_skew_t.sh | 0 .../scripts}/exgfs_atmos_gempak_meta.sh | 0 .../scripts}/exgfs_atmos_goes_nawips.sh | 0 .../exgfs_atmos_grib2_special_npoess.sh | 0 .../scripts}/exgfs_atmos_nawips.sh | 0 .../scripts}/exgfs_atmos_postsnd.sh | 0 {scripts => dev/scripts}/exgfs_pmgr.sh | 0 .../scripts}/exgfs_prdgen_manager.sh | 0 {scripts => dev/scripts}/exgfs_wave_init.sh | 0 {scripts => dev/scripts}/exgfs_wave_nawips.sh | 0 .../scripts}/exgfs_wave_post_gridded_sbs.sh | 0 .../scripts}/exgfs_wave_post_pnt.sh | 0 .../scripts}/exgfs_wave_prdgen_bulls.sh | 0 .../scripts}/exgfs_wave_prdgen_gridded.sh | 0 {scripts => dev/scripts}/exgfs_wave_prep.sh | 0 .../exglobal_aero_analysis_finalize.py | 0 .../exglobal_aero_analysis_initialize.py | 0 .../exglobal_aero_analysis_variational.py | 0 .../scripts}/exglobal_analysis_stats.py | 0 .../scripts}/exglobal_archive_tars.py | 0 .../scripts}/exglobal_archive_vrfy.py | 0 .../exglobal_atm_analysis_finalize.py | 0 .../exglobal_atm_analysis_fv3_increment.py | 0 .../exglobal_atm_analysis_initialize.py | 0 .../exglobal_atm_analysis_variational.py | 0 .../exglobal_atmens_analysis_finalize.py | 0 .../exglobal_atmens_analysis_fv3_increment.py | 0 .../exglobal_atmens_analysis_initialize.py | 0 .../exglobal_atmens_analysis_letkf.py | 0 .../scripts}/exglobal_atmens_analysis_obs.py | 0 .../scripts}/exglobal_atmens_analysis_sol.py | 0 .../scripts}/exglobal_atmos_analysis.sh | 0 .../scripts}/exglobal_atmos_analysis_calc.sh | 0 .../exglobal_atmos_analysis_calc_fv3jedi.py | 0 .../exglobal_atmos_chgres_gen_control.sh | 0 .../scripts}/exglobal_atmos_ensstat.sh | 0 .../scripts}/exglobal_atmos_pmgr.sh | 0 .../scripts}/exglobal_atmos_products.sh | 0 .../scripts}/exglobal_atmos_sfcanl.sh | 0 .../exglobal_atmos_tropcy_qc_reloc.sh | 0 .../scripts}/exglobal_atmos_upp.py | 0 .../scripts}/exglobal_atmos_vminmon.sh | 0 {scripts => dev/scripts}/exglobal_cleanup.sh | 0 {scripts => dev/scripts}/exglobal_diag.sh | 0 .../scripts}/exglobal_enkf_earc_tars.py | 0 .../scripts}/exglobal_enkf_earc_vrfy.py | 0 .../scripts}/exglobal_enkf_ecen.sh | 0 .../scripts}/exglobal_enkf_ecen_fv3jedi.py | 0 .../scripts}/exglobal_enkf_select_obs.sh | 0 {scripts => dev/scripts}/exglobal_enkf_sfc.sh | 0 .../scripts}/exglobal_enkf_update.sh | 0 .../scripts}/exglobal_extractvars.sh | 0 {scripts => dev/scripts}/exglobal_fetch.py | 0 {scripts => dev/scripts}/exglobal_forecast.py | 0 {scripts => dev/scripts}/exglobal_forecast.sh | 0 .../scripts}/exglobal_globus_arch.py | 0 .../scripts}/exglobal_globus_earc.py | 0 .../exglobal_marine_analysis_checkpoint.py | 0 .../scripts}/exglobal_marine_analysis_ecen.py | 0 .../exglobal_marine_analysis_finalize.py | 0 .../exglobal_marine_analysis_initialize.py | 0 .../exglobal_marine_analysis_letkf.py | 0 .../exglobal_marine_analysis_variational.py | 0 .../scripts}/exglobal_marinebmat.py | 0 .../exglobal_marinebmat_initialize.py | 0 .../scripts}/exglobal_oceanice_products.py | 0 .../exglobal_offline_atmos_analysis.py | 0 .../scripts}/exglobal_prep_emissions.py | 0 {scripts => dev/scripts}/exglobal_prep_sfc.sh | 0 .../scripts}/exglobal_snow_analysis.py | 0 .../scripts}/exglobal_snowens_analysis.py | 0 {scripts => dev/scripts}/exglobal_stage_ic.py | 0 dev/workflow/rocoto/gcafs_tasks.py | 60 +++---- dev/workflow/rocoto/gefs_tasks.py | 38 ++-- dev/workflow/rocoto/gfs_tasks.py | 166 +++++++++--------- dev/workflow/rocoto/sfs_tasks.py | 30 ++-- scripts | 1 + 268 files changed, 240 insertions(+), 239 deletions(-) rename dev/{jobs => job_cards/rocoto}/aeroanlfinal.sh (88%) rename dev/{jobs => job_cards/rocoto}/aeroanlgenb.sh (87%) rename dev/{jobs => job_cards/rocoto}/aeroanlinit.sh (87%) rename dev/{jobs => job_cards/rocoto}/aeroanlvar.sh (87%) rename dev/{jobs => job_cards/rocoto}/aerosol_init.sh (100%) rename dev/{jobs => job_cards/rocoto}/anal.sh (89%) rename dev/{jobs => job_cards/rocoto}/analcalc.sh (88%) rename dev/{jobs => job_cards/rocoto}/analcalc_fv3jedi.sh (87%) rename dev/{jobs => job_cards/rocoto}/analdiag.sh (88%) rename dev/{jobs => job_cards/rocoto}/anlstat.sh (90%) rename dev/{jobs => job_cards/rocoto}/arch_tars.sh (90%) rename dev/{jobs => job_cards/rocoto}/arch_vrfy.sh (90%) rename dev/{jobs => job_cards/rocoto}/atmanlfinal.sh (88%) rename dev/{jobs => job_cards/rocoto}/atmanlfv3inc.sh (87%) rename dev/{jobs => job_cards/rocoto}/atmanlinit.sh (88%) rename dev/{jobs => job_cards/rocoto}/atmanlvar.sh (87%) rename dev/{jobs => job_cards/rocoto}/atmensanlfinal.sh (88%) rename dev/{jobs => job_cards/rocoto}/atmensanlfv3inc.sh (87%) rename dev/{jobs => job_cards/rocoto}/atmensanlinit.sh (87%) rename dev/{jobs => job_cards/rocoto}/atmensanlletkf.sh (88%) rename dev/{jobs => job_cards/rocoto}/atmensanlobs.sh (88%) rename dev/{jobs => job_cards/rocoto}/atmensanlsol.sh (88%) rename dev/{jobs => job_cards/rocoto}/atmos_ensstat.sh (94%) rename dev/{jobs => job_cards/rocoto}/atmos_products.sh (94%) rename dev/{jobs => job_cards/rocoto}/awips.sh (92%) rename dev/{jobs => job_cards/rocoto}/awips_20km_1p0deg.sh (91%) rename dev/{jobs => job_cards/rocoto}/cleanup.sh (91%) rename dev/{jobs => job_cards/rocoto}/earc_tars.sh (89%) rename dev/{jobs => job_cards/rocoto}/earc_vrfy.sh (89%) rename dev/{jobs => job_cards/rocoto}/ecen.sh (94%) rename dev/{jobs => job_cards/rocoto}/ecen_fv3jedi.sh (89%) rename dev/{jobs => job_cards/rocoto}/echgres.sh (89%) rename dev/{jobs => job_cards/rocoto}/ediag.sh (90%) rename dev/{jobs => job_cards/rocoto}/eobs.sh (89%) rename dev/{jobs => job_cards/rocoto}/epos.sh (94%) rename dev/{jobs => job_cards/rocoto}/esfc.sh (90%) rename dev/{jobs => job_cards/rocoto}/esnowanl.sh (89%) rename dev/{jobs => job_cards/rocoto}/eupd.sh (90%) rename dev/{jobs => job_cards/rocoto}/extractvars.sh (93%) rename dev/{jobs => job_cards/rocoto}/fbwind.sh (87%) rename dev/{jobs => job_cards/rocoto}/fcst.sh (93%) rename dev/{jobs => job_cards/rocoto}/fetch.sh (88%) rename dev/{jobs => job_cards/rocoto}/fit2obs.sh (93%) rename dev/{jobs => job_cards/rocoto}/gempak.sh (92%) rename dev/{jobs => job_cards/rocoto}/gempakgrb2spec.sh (82%) rename dev/{jobs => job_cards/rocoto}/gempakmeta.sh (86%) rename dev/{jobs => job_cards/rocoto}/gempakmetancdc.sh (85%) rename dev/{jobs => job_cards/rocoto}/gempakncdcupapgif.sh (85%) rename dev/{jobs => job_cards/rocoto}/gen_control_ic.sh (84%) rename dev/{jobs => job_cards/rocoto}/genesis.sh (88%) rename dev/{jobs => job_cards/rocoto}/genesis_fsu.sh (89%) rename dev/{jobs => job_cards/rocoto}/globus_arch.sh (90%) rename dev/{jobs => job_cards/rocoto}/globus_earc.sh (89%) rename dev/{jobs => job_cards/rocoto}/marineanlchkpt.sh (87%) rename dev/{jobs => job_cards/rocoto}/marineanlecen.sh (92%) rename dev/{jobs => job_cards/rocoto}/marineanlfinal.sh (88%) rename dev/{jobs => job_cards/rocoto}/marineanlinit.sh (88%) rename dev/{jobs => job_cards/rocoto}/marineanlletkf.sh (88%) rename dev/{jobs => job_cards/rocoto}/marineanlvar.sh (87%) rename dev/{jobs => job_cards/rocoto}/marinebmat.sh (90%) rename dev/{jobs => job_cards/rocoto}/marinebmatinit.sh (88%) rename dev/{jobs => job_cards/rocoto}/metp.sh (85%) rename dev/{jobs => job_cards/rocoto}/npoess.sh (85%) rename dev/{jobs => job_cards/rocoto}/oceanice_products.sh (94%) rename dev/{jobs => job_cards/rocoto}/offlineanl.sh (88%) rename dev/{jobs => job_cards/rocoto}/postsnd.sh (87%) rename dev/{jobs => job_cards/rocoto}/prep.sh (99%) rename dev/{jobs => job_cards/rocoto}/prep_emissions.sh (89%) rename dev/{jobs => job_cards/rocoto}/prep_sfc.sh (89%) rename dev/{jobs => job_cards/rocoto}/prepoceanobs.sh (90%) rename dev/{jobs => job_cards/rocoto}/sfcanl.sh (90%) rename dev/{jobs => job_cards/rocoto}/snowanl.sh (89%) rename dev/{jobs => job_cards/rocoto}/stage_ic.sh (87%) rename dev/{jobs => job_cards/rocoto}/tracker.sh (88%) rename dev/{jobs => job_cards/rocoto}/upp.sh (95%) rename dev/{jobs => job_cards/rocoto}/verfozn.sh (91%) rename dev/{jobs => job_cards/rocoto}/verfrad.sh (91%) rename dev/{jobs => job_cards/rocoto}/vminmon.sh (91%) rename dev/{jobs => job_cards/rocoto}/wave_stat.sh (94%) rename dev/{jobs => job_cards/rocoto}/wave_stat_pnt.sh (91%) rename dev/{jobs => job_cards/rocoto}/waveawipsbulls.sh (89%) rename dev/{jobs => job_cards/rocoto}/waveawipsgridded.sh (89%) rename dev/{jobs => job_cards/rocoto}/wavegempak.sh (93%) rename dev/{jobs => job_cards/rocoto}/waveinit.sh (91%) rename dev/{jobs => job_cards/rocoto}/wavepostbndpnt.sh (92%) rename dev/{jobs => job_cards/rocoto}/wavepostbndpntbll.sh (92%) rename dev/{jobs => job_cards/rocoto}/wavepostpnt.sh (93%) rename dev/{jobs => job_cards/rocoto}/wavepostsbs.sh (93%) rename dev/{jobs => job_cards/rocoto}/waveprep.sh (92%) rename {jobs => dev/jobs}/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX (100%) rename {jobs => dev/jobs}/JGDAS_ATMOS_CHGRES_FORENKF (100%) rename {jobs => dev/jobs}/JGDAS_ATMOS_GEMPAK (100%) rename {jobs => dev/jobs}/JGDAS_ATMOS_GEMPAK_META_NCDC (100%) rename {jobs => dev/jobs}/JGDAS_ATMOS_VERFOZN (100%) rename {jobs => dev/jobs}/JGDAS_ATMOS_VERFRAD (100%) rename {jobs => dev/jobs}/JGDAS_ENKF_POST (100%) rename {jobs => dev/jobs}/JGDAS_FIT2OBS (100%) rename {jobs => dev/jobs}/JGEFS_WAVE_STAT (100%) rename {jobs => dev/jobs}/JGEFS_WAVE_STAT_PNT (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_AWIPS_20KM_1P0DEG (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_CYCLONE_GENESIS (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_CYCLONE_TRACKER (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_FBWIND (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_FSU_GENESIS (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_GEMPAK (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_GEMPAK_META (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_GEMPAK_NCDC_UPAPGIF (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_GEMPAK_PGRB2_SPEC (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_PGRB2_SPEC_NPOESS (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_POSTSND (100%) rename {jobs => dev/jobs}/JGFS_ATMOS_VERIFICATION (100%) rename {jobs => dev/jobs}/JGLOBAL_AERO_ANALYSIS_FINALIZE (100%) rename {jobs => dev/jobs}/JGLOBAL_AERO_ANALYSIS_INITIALIZE (100%) rename {jobs => dev/jobs}/JGLOBAL_AERO_ANALYSIS_VARIATIONAL (100%) rename {jobs => dev/jobs}/JGLOBAL_ANALYSIS_STATS (100%) rename {jobs => dev/jobs}/JGLOBAL_ARCHIVE_TARS (100%) rename {jobs => dev/jobs}/JGLOBAL_ARCHIVE_VRFY (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMENS_ANALYSIS_FINALIZE (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMENS_ANALYSIS_FV3_INCREMENT (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMENS_ANALYSIS_INITIALIZE (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMENS_ANALYSIS_LETKF (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMENS_ANALYSIS_OBS (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMENS_ANALYSIS_SOL (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_ANALYSIS (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_ANALYSIS_CALC (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_ANALYSIS_DIAG (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_CHGRES_GEN_CONTROL (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_ENSSTAT (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_POST_MANAGER (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_PREP_SFC (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_PRODUCTS (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_SFCANL (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_TROPCY_QC_RELOC (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_UPP (100%) rename {jobs => dev/jobs}/JGLOBAL_ATMOS_VMINMON (100%) rename {jobs => dev/jobs}/JGLOBAL_ATM_ANALYSIS_FINALIZE (100%) rename {jobs => dev/jobs}/JGLOBAL_ATM_ANALYSIS_FV3_INCREMENT (100%) rename {jobs => dev/jobs}/JGLOBAL_ATM_ANALYSIS_INITIALIZE (100%) rename {jobs => dev/jobs}/JGLOBAL_ATM_ANALYSIS_VARIATIONAL (100%) rename {jobs => dev/jobs}/JGLOBAL_CLEANUP (100%) rename {jobs => dev/jobs}/JGLOBAL_ENKF_ARCHIVE_TARS (100%) rename {jobs => dev/jobs}/JGLOBAL_ENKF_ARCHIVE_VRFY (100%) rename {jobs => dev/jobs}/JGLOBAL_ENKF_DIAG (100%) rename {jobs => dev/jobs}/JGLOBAL_ENKF_ECEN (100%) rename {jobs => dev/jobs}/JGLOBAL_ENKF_ECEN_FV3JEDI (100%) rename {jobs => dev/jobs}/JGLOBAL_ENKF_SELECT_OBS (100%) rename {jobs => dev/jobs}/JGLOBAL_ENKF_SFC (100%) rename {jobs => dev/jobs}/JGLOBAL_ENKF_UPDATE (100%) rename {jobs => dev/jobs}/JGLOBAL_ENS_GLOBUS_ARCH (100%) rename {jobs => dev/jobs}/JGLOBAL_EXTRACTVARS (100%) rename {jobs => dev/jobs}/JGLOBAL_FETCH (100%) rename {jobs => dev/jobs}/JGLOBAL_FORECAST (100%) rename {jobs => dev/jobs}/JGLOBAL_GLOBUS_ARCH (100%) rename {jobs => dev/jobs}/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT (100%) rename {jobs => dev/jobs}/JGLOBAL_MARINE_ANALYSIS_ECEN (100%) rename {jobs => dev/jobs}/JGLOBAL_MARINE_ANALYSIS_FINALIZE (100%) rename {jobs => dev/jobs}/JGLOBAL_MARINE_ANALYSIS_INITIALIZE (100%) rename {jobs => dev/jobs}/JGLOBAL_MARINE_ANALYSIS_LETKF (100%) rename {jobs => dev/jobs}/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL (100%) rename {jobs => dev/jobs}/JGLOBAL_MARINE_BMAT (100%) rename {jobs => dev/jobs}/JGLOBAL_MARINE_BMAT_INITIALIZE (100%) rename {jobs => dev/jobs}/JGLOBAL_OCEANICE_PRODUCTS (100%) rename {jobs => dev/jobs}/JGLOBAL_OFFLINE_ATMOS_ANALYSIS (100%) rename {jobs => dev/jobs}/JGLOBAL_PREP_EMISSIONS (100%) rename {jobs => dev/jobs}/JGLOBAL_PREP_OCEAN_OBS (100%) rename {jobs => dev/jobs}/JGLOBAL_SNOWENS_ANALYSIS (100%) rename {jobs => dev/jobs}/JGLOBAL_SNOW_ANALYSIS (100%) rename {jobs => dev/jobs}/JGLOBAL_STAGE_IC (100%) rename {jobs => dev/jobs}/JGLOBAL_WAVE_GEMPAK (100%) rename {jobs => dev/jobs}/JGLOBAL_WAVE_INIT (100%) rename {jobs => dev/jobs}/JGLOBAL_WAVE_POST_BNDPNT (100%) rename {jobs => dev/jobs}/JGLOBAL_WAVE_POST_BNDPNTBLL (100%) rename {jobs => dev/jobs}/JGLOBAL_WAVE_POST_PNT (100%) rename {jobs => dev/jobs}/JGLOBAL_WAVE_POST_SBS (100%) rename {jobs => dev/jobs}/JGLOBAL_WAVE_PRDGEN_BULLS (100%) rename {jobs => dev/jobs}/JGLOBAL_WAVE_PRDGEN_GRIDDED (100%) rename {jobs => dev/jobs}/JGLOBAL_WAVE_PREP (100%) rename {scripts => dev/scripts}/exgdas_aero_analysis_generate_bmatrix.py (100%) rename {scripts => dev/scripts}/exgdas_atmos_chgres_forenkf.sh (100%) rename {scripts => dev/scripts}/exgdas_atmos_gempak_gif_ncdc.sh (100%) rename {scripts => dev/scripts}/exgdas_atmos_nawips.sh (100%) rename {scripts => dev/scripts}/exgdas_atmos_verfozn.sh (100%) rename {scripts => dev/scripts}/exgdas_atmos_verfrad.sh (100%) rename {scripts => dev/scripts}/exgdas_enkf_post.sh (100%) rename {scripts => dev/scripts}/exgfs_aero_init_aerosol.py (100%) rename {scripts => dev/scripts}/exgfs_atmos_awips_20km_1p0deg.sh (100%) rename {scripts => dev/scripts}/exgfs_atmos_fbwind.sh (100%) rename {scripts => dev/scripts}/exgfs_atmos_gempak_gif_ncdc_skew_t.sh (100%) rename {scripts => dev/scripts}/exgfs_atmos_gempak_meta.sh (100%) rename {scripts => dev/scripts}/exgfs_atmos_goes_nawips.sh (100%) rename {scripts => dev/scripts}/exgfs_atmos_grib2_special_npoess.sh (100%) rename {scripts => dev/scripts}/exgfs_atmos_nawips.sh (100%) rename {scripts => dev/scripts}/exgfs_atmos_postsnd.sh (100%) rename {scripts => dev/scripts}/exgfs_pmgr.sh (100%) rename {scripts => dev/scripts}/exgfs_prdgen_manager.sh (100%) rename {scripts => dev/scripts}/exgfs_wave_init.sh (100%) rename {scripts => dev/scripts}/exgfs_wave_nawips.sh (100%) rename {scripts => dev/scripts}/exgfs_wave_post_gridded_sbs.sh (100%) rename {scripts => dev/scripts}/exgfs_wave_post_pnt.sh (100%) rename {scripts => dev/scripts}/exgfs_wave_prdgen_bulls.sh (100%) rename {scripts => dev/scripts}/exgfs_wave_prdgen_gridded.sh (100%) rename {scripts => dev/scripts}/exgfs_wave_prep.sh (100%) rename {scripts => dev/scripts}/exglobal_aero_analysis_finalize.py (100%) rename {scripts => dev/scripts}/exglobal_aero_analysis_initialize.py (100%) rename {scripts => dev/scripts}/exglobal_aero_analysis_variational.py (100%) rename {scripts => dev/scripts}/exglobal_analysis_stats.py (100%) rename {scripts => dev/scripts}/exglobal_archive_tars.py (100%) rename {scripts => dev/scripts}/exglobal_archive_vrfy.py (100%) rename {scripts => dev/scripts}/exglobal_atm_analysis_finalize.py (100%) rename {scripts => dev/scripts}/exglobal_atm_analysis_fv3_increment.py (100%) rename {scripts => dev/scripts}/exglobal_atm_analysis_initialize.py (100%) rename {scripts => dev/scripts}/exglobal_atm_analysis_variational.py (100%) rename {scripts => dev/scripts}/exglobal_atmens_analysis_finalize.py (100%) rename {scripts => dev/scripts}/exglobal_atmens_analysis_fv3_increment.py (100%) rename {scripts => dev/scripts}/exglobal_atmens_analysis_initialize.py (100%) rename {scripts => dev/scripts}/exglobal_atmens_analysis_letkf.py (100%) rename {scripts => dev/scripts}/exglobal_atmens_analysis_obs.py (100%) rename {scripts => dev/scripts}/exglobal_atmens_analysis_sol.py (100%) rename {scripts => dev/scripts}/exglobal_atmos_analysis.sh (100%) rename {scripts => dev/scripts}/exglobal_atmos_analysis_calc.sh (100%) rename {scripts => dev/scripts}/exglobal_atmos_analysis_calc_fv3jedi.py (100%) rename {scripts => dev/scripts}/exglobal_atmos_chgres_gen_control.sh (100%) rename {scripts => dev/scripts}/exglobal_atmos_ensstat.sh (100%) rename {scripts => dev/scripts}/exglobal_atmos_pmgr.sh (100%) rename {scripts => dev/scripts}/exglobal_atmos_products.sh (100%) rename {scripts => dev/scripts}/exglobal_atmos_sfcanl.sh (100%) rename {scripts => dev/scripts}/exglobal_atmos_tropcy_qc_reloc.sh (100%) rename {scripts => dev/scripts}/exglobal_atmos_upp.py (100%) rename {scripts => dev/scripts}/exglobal_atmos_vminmon.sh (100%) rename {scripts => dev/scripts}/exglobal_cleanup.sh (100%) rename {scripts => dev/scripts}/exglobal_diag.sh (100%) rename {scripts => dev/scripts}/exglobal_enkf_earc_tars.py (100%) rename {scripts => dev/scripts}/exglobal_enkf_earc_vrfy.py (100%) rename {scripts => dev/scripts}/exglobal_enkf_ecen.sh (100%) rename {scripts => dev/scripts}/exglobal_enkf_ecen_fv3jedi.py (100%) rename {scripts => dev/scripts}/exglobal_enkf_select_obs.sh (100%) rename {scripts => dev/scripts}/exglobal_enkf_sfc.sh (100%) rename {scripts => dev/scripts}/exglobal_enkf_update.sh (100%) rename {scripts => dev/scripts}/exglobal_extractvars.sh (100%) rename {scripts => dev/scripts}/exglobal_fetch.py (100%) rename {scripts => dev/scripts}/exglobal_forecast.py (100%) rename {scripts => dev/scripts}/exglobal_forecast.sh (100%) rename {scripts => dev/scripts}/exglobal_globus_arch.py (100%) rename {scripts => dev/scripts}/exglobal_globus_earc.py (100%) rename {scripts => dev/scripts}/exglobal_marine_analysis_checkpoint.py (100%) rename {scripts => dev/scripts}/exglobal_marine_analysis_ecen.py (100%) rename {scripts => dev/scripts}/exglobal_marine_analysis_finalize.py (100%) rename {scripts => dev/scripts}/exglobal_marine_analysis_initialize.py (100%) rename {scripts => dev/scripts}/exglobal_marine_analysis_letkf.py (100%) rename {scripts => dev/scripts}/exglobal_marine_analysis_variational.py (100%) rename {scripts => dev/scripts}/exglobal_marinebmat.py (100%) rename {scripts => dev/scripts}/exglobal_marinebmat_initialize.py (100%) rename {scripts => dev/scripts}/exglobal_oceanice_products.py (100%) rename {scripts => dev/scripts}/exglobal_offline_atmos_analysis.py (100%) rename {scripts => dev/scripts}/exglobal_prep_emissions.py (100%) rename {scripts => dev/scripts}/exglobal_prep_sfc.sh (100%) rename {scripts => dev/scripts}/exglobal_snow_analysis.py (100%) rename {scripts => dev/scripts}/exglobal_snowens_analysis.py (100%) rename {scripts => dev/scripts}/exglobal_stage_ic.py (100%) create mode 120000 scripts diff --git a/.editorconfig b/.editorconfig index 5ad9da1a41d..047fcbf85da 100644 --- a/.editorconfig +++ b/.editorconfig @@ -22,7 +22,7 @@ indent_style = tab indent_size = 4 max_line_length = 79 -[jobs/*] +[dev/jobs/*] indent_style = space indent_size = 4 shell_variant = bash diff --git a/.github/workflows/bash_code_analysis.yaml b/.github/workflows/bash_code_analysis.yaml index c555c7506c7..27be4c76b6c 100644 --- a/.github/workflows/bash_code_analysis.yaml +++ b/.github/workflows/bash_code_analysis.yaml @@ -36,7 +36,7 @@ jobs: - name: Install shfmt uses: mfinelli/setup-shfmt@v4 - name: shfmt scan - run: shfmt -d dev/jobs jobs scripts + run: shfmt -d dev/jobs dev/job_cards dev/scripts shellcheck: runs-on: ubuntu-22.04 diff --git a/dev/ctests/README.md b/dev/ctests/README.md index 95e8ae13872..f25ad3a1d1a 100644 --- a/dev/ctests/README.md +++ b/dev/ctests/README.md @@ -251,7 +251,7 @@ source $HOMEgfs/dev/ci/platforms/config.$MACHINE_ID - **Complete Documentation**: `docs/source/testing.rst` - **Test Case Examples**: `cases/*.yaml` - **CI/CD Pipeline**: `../ci/gitlab-ci-hosts.yml` -- **Job Scripts**: `../../jobs/JGLOBAL_*` +- **Job Scripts**: `../jobs/JGLOBAL_*` - **Platform Configuration**: `../ci/platforms/config.*` --- diff --git a/dev/jobs/aeroanlfinal.sh b/dev/job_cards/rocoto/aeroanlfinal.sh similarity index 88% rename from dev/jobs/aeroanlfinal.sh rename to dev/job_cards/rocoto/aeroanlfinal.sh index e5e0c3736eb..a002c5c1940 100755 --- a/dev/jobs/aeroanlfinal.sh +++ b/dev/job_cards/rocoto/aeroanlfinal.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_AERO_ANALYSIS_FINALIZE" +"${HOMEgfs}/dev/jobs/JGLOBAL_AERO_ANALYSIS_FINALIZE" status=$? exit "${status}" diff --git a/dev/jobs/aeroanlgenb.sh b/dev/job_cards/rocoto/aeroanlgenb.sh similarity index 87% rename from dev/jobs/aeroanlgenb.sh rename to dev/job_cards/rocoto/aeroanlgenb.sh index be57aae5857..af72ffe6b8b 100755 --- a/dev/jobs/aeroanlgenb.sh +++ b/dev/job_cards/rocoto/aeroanlgenb.sh @@ -16,6 +16,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX" +"${HOMEgfs}/dev/jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX" status=$? exit "${status}" diff --git a/dev/jobs/aeroanlinit.sh b/dev/job_cards/rocoto/aeroanlinit.sh similarity index 87% rename from dev/jobs/aeroanlinit.sh rename to dev/job_cards/rocoto/aeroanlinit.sh index eb540376c70..e1df69aabdf 100755 --- a/dev/jobs/aeroanlinit.sh +++ b/dev/job_cards/rocoto/aeroanlinit.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_AERO_ANALYSIS_INITIALIZE" +"${HOMEgfs}/dev/jobs/JGLOBAL_AERO_ANALYSIS_INITIALIZE" status=$? exit "${status}" diff --git a/dev/jobs/aeroanlvar.sh b/dev/job_cards/rocoto/aeroanlvar.sh similarity index 87% rename from dev/jobs/aeroanlvar.sh rename to dev/job_cards/rocoto/aeroanlvar.sh index 8e17bf41f8e..681d30c9428 100755 --- a/dev/jobs/aeroanlvar.sh +++ b/dev/job_cards/rocoto/aeroanlvar.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_AERO_ANALYSIS_VARIATIONAL" +"${HOMEgfs}/dev/jobs/JGLOBAL_AERO_ANALYSIS_VARIATIONAL" status=$? exit "${status}" diff --git a/dev/jobs/aerosol_init.sh b/dev/job_cards/rocoto/aerosol_init.sh similarity index 100% rename from dev/jobs/aerosol_init.sh rename to dev/job_cards/rocoto/aerosol_init.sh diff --git a/dev/jobs/anal.sh b/dev/job_cards/rocoto/anal.sh similarity index 89% rename from dev/jobs/anal.sh rename to dev/job_cards/rocoto/anal.sh index d854d86fe31..a2178f92334 100755 --- a/dev/jobs/anal.sh +++ b/dev/job_cards/rocoto/anal.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMOS_ANALYSIS" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_ANALYSIS" status=$? exit "${status}" diff --git a/dev/jobs/analcalc.sh b/dev/job_cards/rocoto/analcalc.sh similarity index 88% rename from dev/jobs/analcalc.sh rename to dev/job_cards/rocoto/analcalc.sh index 7e5549b8395..77e5f5d27a5 100755 --- a/dev/jobs/analcalc.sh +++ b/dev/job_cards/rocoto/analcalc.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC" status=$? exit "${status}" diff --git a/dev/jobs/analcalc_fv3jedi.sh b/dev/job_cards/rocoto/analcalc_fv3jedi.sh similarity index 87% rename from dev/jobs/analcalc_fv3jedi.sh rename to dev/job_cards/rocoto/analcalc_fv3jedi.sh index 52bbdf42804..4984ab0eab7 100755 --- a/dev/jobs/analcalc_fv3jedi.sh +++ b/dev/job_cards/rocoto/analcalc_fv3jedi.sh @@ -13,6 +13,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI +"${HOMEgfs}"/dev/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI status=$? exit "${status}" diff --git a/dev/jobs/analdiag.sh b/dev/job_cards/rocoto/analdiag.sh similarity index 88% rename from dev/jobs/analdiag.sh rename to dev/job_cards/rocoto/analdiag.sh index 7b4badebb88..005e49471a8 100755 --- a/dev/jobs/analdiag.sh +++ b/dev/job_cards/rocoto/analdiag.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMOS_ANALYSIS_DIAG" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_ANALYSIS_DIAG" status=$? exit "${status}" diff --git a/dev/jobs/anlstat.sh b/dev/job_cards/rocoto/anlstat.sh similarity index 90% rename from dev/jobs/anlstat.sh rename to dev/job_cards/rocoto/anlstat.sh index 8b73be1026b..55a4c00a293 100755 --- a/dev/jobs/anlstat.sh +++ b/dev/job_cards/rocoto/anlstat.sh @@ -16,5 +16,5 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ANALYSIS_STATS" +"${HOMEgfs}/dev/jobs/JGLOBAL_ANALYSIS_STATS" exit $? diff --git a/dev/jobs/arch_tars.sh b/dev/job_cards/rocoto/arch_tars.sh similarity index 90% rename from dev/jobs/arch_tars.sh rename to dev/job_cards/rocoto/arch_tars.sh index fb8dbdc170a..24f0ab9c688 100755 --- a/dev/jobs/arch_tars.sh +++ b/dev/job_cards/rocoto/arch_tars.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ARCHIVE_TARS" +"${HOMEgfs}/dev/jobs/JGLOBAL_ARCHIVE_TARS" status=$? exit "${status}" diff --git a/dev/jobs/arch_vrfy.sh b/dev/job_cards/rocoto/arch_vrfy.sh similarity index 90% rename from dev/jobs/arch_vrfy.sh rename to dev/job_cards/rocoto/arch_vrfy.sh index 50cb330281b..f289ea5ecf4 100755 --- a/dev/jobs/arch_vrfy.sh +++ b/dev/job_cards/rocoto/arch_vrfy.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ARCHIVE_VRFY" +"${HOMEgfs}/dev/jobs/JGLOBAL_ARCHIVE_VRFY" status=$? exit "${status}" diff --git a/dev/jobs/atmanlfinal.sh b/dev/job_cards/rocoto/atmanlfinal.sh similarity index 88% rename from dev/jobs/atmanlfinal.sh rename to dev/job_cards/rocoto/atmanlfinal.sh index 05202ea5ccf..2dc364af25e 100755 --- a/dev/jobs/atmanlfinal.sh +++ b/dev/job_cards/rocoto/atmanlfinal.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATM_ANALYSIS_FINALIZE" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATM_ANALYSIS_FINALIZE" status=$? exit "${status}" diff --git a/dev/jobs/atmanlfv3inc.sh b/dev/job_cards/rocoto/atmanlfv3inc.sh similarity index 87% rename from dev/jobs/atmanlfv3inc.sh rename to dev/job_cards/rocoto/atmanlfv3inc.sh index 9d9fac34c55..5e6c9d4cbbb 100755 --- a/dev/jobs/atmanlfv3inc.sh +++ b/dev/job_cards/rocoto/atmanlfv3inc.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATM_ANALYSIS_FV3_INCREMENT" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATM_ANALYSIS_FV3_INCREMENT" status=$? exit "${status}" diff --git a/dev/jobs/atmanlinit.sh b/dev/job_cards/rocoto/atmanlinit.sh similarity index 88% rename from dev/jobs/atmanlinit.sh rename to dev/job_cards/rocoto/atmanlinit.sh index 1fe059958e0..8ec82291a7f 100755 --- a/dev/jobs/atmanlinit.sh +++ b/dev/job_cards/rocoto/atmanlinit.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATM_ANALYSIS_INITIALIZE" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATM_ANALYSIS_INITIALIZE" status=$? exit "${status}" diff --git a/dev/jobs/atmanlvar.sh b/dev/job_cards/rocoto/atmanlvar.sh similarity index 87% rename from dev/jobs/atmanlvar.sh rename to dev/job_cards/rocoto/atmanlvar.sh index 4e6156af443..98b1063c985 100755 --- a/dev/jobs/atmanlvar.sh +++ b/dev/job_cards/rocoto/atmanlvar.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATM_ANALYSIS_VARIATIONAL" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATM_ANALYSIS_VARIATIONAL" status=$? exit "${status}" diff --git a/dev/jobs/atmensanlfinal.sh b/dev/job_cards/rocoto/atmensanlfinal.sh similarity index 88% rename from dev/jobs/atmensanlfinal.sh rename to dev/job_cards/rocoto/atmensanlfinal.sh index a127724b24a..42b51412ced 100755 --- a/dev/jobs/atmensanlfinal.sh +++ b/dev/job_cards/rocoto/atmensanlfinal.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMENS_ANALYSIS_FINALIZE" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_FINALIZE" status=$? exit "${status}" diff --git a/dev/jobs/atmensanlfv3inc.sh b/dev/job_cards/rocoto/atmensanlfv3inc.sh similarity index 87% rename from dev/jobs/atmensanlfv3inc.sh rename to dev/job_cards/rocoto/atmensanlfv3inc.sh index 9e2cbc7a82e..43cb11cc7a5 100755 --- a/dev/jobs/atmensanlfv3inc.sh +++ b/dev/job_cards/rocoto/atmensanlfv3inc.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMENS_ANALYSIS_FV3_INCREMENT" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_FV3_INCREMENT" status=$? exit "${status}" diff --git a/dev/jobs/atmensanlinit.sh b/dev/job_cards/rocoto/atmensanlinit.sh similarity index 87% rename from dev/jobs/atmensanlinit.sh rename to dev/job_cards/rocoto/atmensanlinit.sh index e30e96fce31..08786874a4a 100755 --- a/dev/jobs/atmensanlinit.sh +++ b/dev/job_cards/rocoto/atmensanlinit.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMENS_ANALYSIS_INITIALIZE" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_INITIALIZE" status=$? exit "${status}" diff --git a/dev/jobs/atmensanlletkf.sh b/dev/job_cards/rocoto/atmensanlletkf.sh similarity index 88% rename from dev/jobs/atmensanlletkf.sh rename to dev/job_cards/rocoto/atmensanlletkf.sh index 53b296235f3..e33f2d03206 100755 --- a/dev/jobs/atmensanlletkf.sh +++ b/dev/job_cards/rocoto/atmensanlletkf.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMENS_ANALYSIS_LETKF" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_LETKF" status=$? exit "${status}" diff --git a/dev/jobs/atmensanlobs.sh b/dev/job_cards/rocoto/atmensanlobs.sh similarity index 88% rename from dev/jobs/atmensanlobs.sh rename to dev/job_cards/rocoto/atmensanlobs.sh index fa47622c6db..fbf45a07b3d 100755 --- a/dev/jobs/atmensanlobs.sh +++ b/dev/job_cards/rocoto/atmensanlobs.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMENS_ANALYSIS_OBS" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_OBS" status=$? exit "${status}" diff --git a/dev/jobs/atmensanlsol.sh b/dev/job_cards/rocoto/atmensanlsol.sh similarity index 88% rename from dev/jobs/atmensanlsol.sh rename to dev/job_cards/rocoto/atmensanlsol.sh index 0318e2ccdc4..81bf908c068 100755 --- a/dev/jobs/atmensanlsol.sh +++ b/dev/job_cards/rocoto/atmensanlsol.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMENS_ANALYSIS_SOL" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_SOL" status=$? exit "${status}" diff --git a/dev/jobs/atmos_ensstat.sh b/dev/job_cards/rocoto/atmos_ensstat.sh similarity index 94% rename from dev/jobs/atmos_ensstat.sh rename to dev/job_cards/rocoto/atmos_ensstat.sh index 47c355ba497..ed64b5f79c3 100755 --- a/dev/jobs/atmos_ensstat.sh +++ b/dev/job_cards/rocoto/atmos_ensstat.sh @@ -24,7 +24,7 @@ for FORECAST_HOUR in "${fhr_list[@]}"; do ############################################################### # Execute the JJOB ############################################################### - "${HOMEgfs}/jobs/JGLOBAL_ATMOS_ENSSTAT" + "${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_ENSSTAT" status=$? [[ ${status} -ne 0 ]] && exit "${status}" done diff --git a/dev/jobs/atmos_products.sh b/dev/job_cards/rocoto/atmos_products.sh similarity index 94% rename from dev/jobs/atmos_products.sh rename to dev/job_cards/rocoto/atmos_products.sh index 145f4c7dead..ab2952c5977 100755 --- a/dev/jobs/atmos_products.sh +++ b/dev/job_cards/rocoto/atmos_products.sh @@ -24,7 +24,7 @@ for FORECAST_HOUR in "${fhr_list[@]}"; do ############################################################### # Execute the JJOB ############################################################### - "${HOMEgfs}/jobs/JGLOBAL_ATMOS_PRODUCTS" + "${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_PRODUCTS" status=$? [[ ${status} -ne 0 ]] && exit "${status}" done diff --git a/dev/jobs/awips.sh b/dev/job_cards/rocoto/awips.sh similarity index 92% rename from dev/jobs/awips.sh rename to dev/job_cards/rocoto/awips.sh index 9f9aca44589..158407387ed 100755 --- a/dev/jobs/awips.sh +++ b/dev/job_cards/rocoto/awips.sh @@ -19,7 +19,7 @@ for fhr in "${fhr_list[@]}"; do ############################################################### # Execute the JJOB # TODO ############################################################### - # "${HOMEgfs}/jobs/J${RUN^^}_ATMOS_AWIPS" + # "${HOMEgfs}/dev/jobs/J${RUN^^}_ATMOS_AWIPS" err=$? if [[ ${err} -ne 0 ]]; then exit "${err}" diff --git a/dev/jobs/awips_20km_1p0deg.sh b/dev/job_cards/rocoto/awips_20km_1p0deg.sh similarity index 91% rename from dev/jobs/awips_20km_1p0deg.sh rename to dev/job_cards/rocoto/awips_20km_1p0deg.sh index c8010b3eb9f..233e2f02b01 100755 --- a/dev/jobs/awips_20km_1p0deg.sh +++ b/dev/job_cards/rocoto/awips_20km_1p0deg.sh @@ -38,14 +38,14 @@ for fhr3 in ${fhrlst}; do if ((fhr % 3 == 0)); then export fcsthr="${fhr3}" export DATA="${DATAROOT}/${jobid}.${fcsthr}" - "${HOMEgfs}/jobs/JGFS_ATMOS_AWIPS_20KM_1P0DEG" + "${HOMEgfs}/dev/jobs/JGFS_ATMOS_AWIPS_20KM_1P0DEG" fi # Process every 6 hrs from hour 90 up to hour 240 elif [[ ${fhr} -ge 90 ]] && [[ ${fhr} -le 240 ]]; then if ((fhr % 6 == 0)); then export fcsthr="${fhr3}" export DATA="${DATAROOT}/${jobid}.${fcsthr}" - "${HOMEgfs}/jobs/JGFS_ATMOS_AWIPS_20KM_1P0DEG" + "${HOMEgfs}/dev/jobs/JGFS_ATMOS_AWIPS_20KM_1P0DEG" fi fi done diff --git a/dev/jobs/cleanup.sh b/dev/job_cards/rocoto/cleanup.sh similarity index 91% rename from dev/jobs/cleanup.sh rename to dev/job_cards/rocoto/cleanup.sh index 0cb259555f6..7af2d3eb942 100755 --- a/dev/jobs/cleanup.sh +++ b/dev/job_cards/rocoto/cleanup.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_CLEANUP" +"${HOMEgfs}/dev/jobs/JGLOBAL_CLEANUP" status=$? exit "${status}" diff --git a/dev/jobs/earc_tars.sh b/dev/job_cards/rocoto/earc_tars.sh similarity index 89% rename from dev/jobs/earc_tars.sh rename to dev/job_cards/rocoto/earc_tars.sh index 15b7ad421a1..e0cecadf1c5 100755 --- a/dev/jobs/earc_tars.sh +++ b/dev/job_cards/rocoto/earc_tars.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ENKF_ARCHIVE_TARS" +"${HOMEgfs}/dev/jobs/JGLOBAL_ENKF_ARCHIVE_TARS" status=$? exit "${status}" diff --git a/dev/jobs/earc_vrfy.sh b/dev/job_cards/rocoto/earc_vrfy.sh similarity index 89% rename from dev/jobs/earc_vrfy.sh rename to dev/job_cards/rocoto/earc_vrfy.sh index 6556a35304a..25e0d31ad41 100755 --- a/dev/jobs/earc_vrfy.sh +++ b/dev/job_cards/rocoto/earc_vrfy.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ENKF_ARCHIVE_VRFY" +"${HOMEgfs}/dev/jobs/JGLOBAL_ENKF_ARCHIVE_VRFY" status=$? exit "${status}" diff --git a/dev/jobs/ecen.sh b/dev/job_cards/rocoto/ecen.sh similarity index 94% rename from dev/jobs/ecen.sh rename to dev/job_cards/rocoto/ecen.sh index 5d4168be54d..7e267ca0ed2 100755 --- a/dev/jobs/ecen.sh +++ b/dev/job_cards/rocoto/ecen.sh @@ -22,7 +22,7 @@ for fhr in ${fhrlst}; do export job=ecen export jobid="${job}.$$" - "${HOMEgfs}/jobs/JGLOBAL_ENKF_ECEN" + "${HOMEgfs}/dev/jobs/JGLOBAL_ENKF_ECEN" status=$? if [[ ${status} -ne 0 ]]; then exit "${status}" diff --git a/dev/jobs/ecen_fv3jedi.sh b/dev/job_cards/rocoto/ecen_fv3jedi.sh similarity index 89% rename from dev/jobs/ecen_fv3jedi.sh rename to dev/job_cards/rocoto/ecen_fv3jedi.sh index 5c4cc21f780..9e84069279c 100755 --- a/dev/jobs/ecen_fv3jedi.sh +++ b/dev/job_cards/rocoto/ecen_fv3jedi.sh @@ -13,6 +13,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_ENKF_ECEN_FV3JEDI +"${HOMEgfs}"/dev/jobs/JGLOBAL_ENKF_ECEN_FV3JEDI status=$? exit "${status}" diff --git a/dev/jobs/echgres.sh b/dev/job_cards/rocoto/echgres.sh similarity index 89% rename from dev/jobs/echgres.sh rename to dev/job_cards/rocoto/echgres.sh index f8532306da7..0b14cf7f311 100755 --- a/dev/jobs/echgres.sh +++ b/dev/job_cards/rocoto/echgres.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_ATMOS_CHGRES_FORENKF" +"${HOMEgfs}/dev/jobs/JGDAS_ATMOS_CHGRES_FORENKF" status=$? exit "${status}" diff --git a/dev/jobs/ediag.sh b/dev/job_cards/rocoto/ediag.sh similarity index 90% rename from dev/jobs/ediag.sh rename to dev/job_cards/rocoto/ediag.sh index 44808e42094..c0710d0acdb 100755 --- a/dev/jobs/ediag.sh +++ b/dev/job_cards/rocoto/ediag.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ENKF_DIAG" +"${HOMEgfs}/dev/jobs/JGLOBAL_ENKF_DIAG" status=$? exit "${status}" diff --git a/dev/jobs/eobs.sh b/dev/job_cards/rocoto/eobs.sh similarity index 89% rename from dev/jobs/eobs.sh rename to dev/job_cards/rocoto/eobs.sh index 1c5e7fd1458..517a6a64402 100755 --- a/dev/jobs/eobs.sh +++ b/dev/job_cards/rocoto/eobs.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ENKF_SELECT_OBS" +"${HOMEgfs}/dev/jobs/JGLOBAL_ENKF_SELECT_OBS" status=$? exit "${status}" diff --git a/dev/jobs/epos.sh b/dev/job_cards/rocoto/epos.sh similarity index 94% rename from dev/jobs/epos.sh rename to dev/job_cards/rocoto/epos.sh index c8a37b858fb..6e2dfa0b6ef 100755 --- a/dev/jobs/epos.sh +++ b/dev/job_cards/rocoto/epos.sh @@ -23,7 +23,7 @@ for fhr in ${fhrlst}; do export FHMIN_EPOS=${fhr} export FHMAX_EPOS=${fhr} export FHOUT_EPOS=${fhr} - "${HOMEgfs}/jobs/JGDAS_ENKF_POST" + "${HOMEgfs}/dev/jobs/JGDAS_ENKF_POST" status=$? if [[ ${status} -ne 0 ]]; then exit "${status}" diff --git a/dev/jobs/esfc.sh b/dev/job_cards/rocoto/esfc.sh similarity index 90% rename from dev/jobs/esfc.sh rename to dev/job_cards/rocoto/esfc.sh index ecac9e02e86..b052431d296 100755 --- a/dev/jobs/esfc.sh +++ b/dev/job_cards/rocoto/esfc.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ENKF_SFC" +"${HOMEgfs}/dev/jobs/JGLOBAL_ENKF_SFC" status=$? exit "${status}" diff --git a/dev/jobs/esnowanl.sh b/dev/job_cards/rocoto/esnowanl.sh similarity index 89% rename from dev/jobs/esnowanl.sh rename to dev/job_cards/rocoto/esnowanl.sh index 7ee1d0f6079..d1112b26c7e 100755 --- a/dev/jobs/esnowanl.sh +++ b/dev/job_cards/rocoto/esnowanl.sh @@ -13,6 +13,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_SNOWENS_ANALYSIS" +"${HOMEgfs}/dev/jobs/JGLOBAL_SNOWENS_ANALYSIS" status=$? exit "${status}" diff --git a/dev/jobs/eupd.sh b/dev/job_cards/rocoto/eupd.sh similarity index 90% rename from dev/jobs/eupd.sh rename to dev/job_cards/rocoto/eupd.sh index 8a3fd4112e1..58bc59c1c28 100755 --- a/dev/jobs/eupd.sh +++ b/dev/job_cards/rocoto/eupd.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ENKF_UPDATE" +"${HOMEgfs}/dev/jobs/JGLOBAL_ENKF_UPDATE" status=$? exit "${status}" diff --git a/dev/jobs/extractvars.sh b/dev/job_cards/rocoto/extractvars.sh similarity index 93% rename from dev/jobs/extractvars.sh rename to dev/job_cards/rocoto/extractvars.sh index da9194dc152..125ff8394f5 100755 --- a/dev/jobs/extractvars.sh +++ b/dev/job_cards/rocoto/extractvars.sh @@ -18,7 +18,7 @@ export jobid="${job}.$$" echo echo "=============== START TO RUN EXTRACTVARS ===============" # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_EXTRACTVARS" +"${HOMEgfs}/dev/jobs/JGLOBAL_EXTRACTVARS" status=$? if [[ "${status}" -ne 0 ]]; then exit "${status}" diff --git a/dev/jobs/fbwind.sh b/dev/job_cards/rocoto/fbwind.sh similarity index 87% rename from dev/jobs/fbwind.sh rename to dev/job_cards/rocoto/fbwind.sh index 2c298b74f51..e2a253cb0ee 100755 --- a/dev/jobs/fbwind.sh +++ b/dev/job_cards/rocoto/fbwind.sh @@ -11,7 +11,7 @@ export job="fbwind" export jobid="${job}.$$" # Execute the JJOB -"${HOMEgfs}/jobs/JGFS_ATMOS_FBWIND" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_FBWIND" status=$? exit "${status}" diff --git a/dev/jobs/fcst.sh b/dev/job_cards/rocoto/fcst.sh similarity index 93% rename from dev/jobs/fcst.sh rename to dev/job_cards/rocoto/fcst.sh index 11de0bd6b68..57cd65bd798 100755 --- a/dev/jobs/fcst.sh +++ b/dev/job_cards/rocoto/fcst.sh @@ -20,7 +20,7 @@ export job="fcst" export jobid="${job}.$$" # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_FORECAST" +"${HOMEgfs}/dev/jobs/JGLOBAL_FORECAST" status=$? exit "${status}" diff --git a/dev/jobs/fetch.sh b/dev/job_cards/rocoto/fetch.sh similarity index 88% rename from dev/jobs/fetch.sh rename to dev/job_cards/rocoto/fetch.sh index 55a87a01c0d..4c55258de75 100755 --- a/dev/jobs/fetch.sh +++ b/dev/job_cards/rocoto/fetch.sh @@ -13,7 +13,7 @@ export job="fetch" export jobid="${job}.$$" # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_FETCH" +"${HOMEgfs}/dev/jobs/JGLOBAL_FETCH" status=$? exit "${status}" diff --git a/dev/jobs/fit2obs.sh b/dev/job_cards/rocoto/fit2obs.sh similarity index 93% rename from dev/jobs/fit2obs.sh rename to dev/job_cards/rocoto/fit2obs.sh index f4471a73069..77fd9731fce 100755 --- a/dev/jobs/fit2obs.sh +++ b/dev/job_cards/rocoto/fit2obs.sh @@ -18,7 +18,7 @@ export jobid="${job}.$$" echo echo "=============== START TO RUN FIT2OBS ===============" # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_FIT2OBS" +"${HOMEgfs}/dev/jobs/JGDAS_FIT2OBS" status=$? if [[ ${status} -ne 0 ]]; then exit "${status}" diff --git a/dev/jobs/gempak.sh b/dev/job_cards/rocoto/gempak.sh similarity index 92% rename from dev/jobs/gempak.sh rename to dev/job_cards/rocoto/gempak.sh index e58b76ba030..c20b3a121f7 100755 --- a/dev/jobs/gempak.sh +++ b/dev/job_cards/rocoto/gempak.sh @@ -17,7 +17,7 @@ for fhr in "${fhr_list[@]}"; do ############################################################### # Execute the JJOB ############################################################### - "${HOMEgfs}/jobs/J${RUN^^}_ATMOS_GEMPAK" + "${HOMEgfs}/dev/jobs/J${RUN^^}_ATMOS_GEMPAK" err=$? [[ ${err} -ne 0 ]] && exit "${err}" done diff --git a/dev/jobs/gempakgrb2spec.sh b/dev/job_cards/rocoto/gempakgrb2spec.sh similarity index 82% rename from dev/jobs/gempakgrb2spec.sh rename to dev/job_cards/rocoto/gempakgrb2spec.sh index 6fad75c1d72..e0594ec8bde 100755 --- a/dev/jobs/gempakgrb2spec.sh +++ b/dev/job_cards/rocoto/gempakgrb2spec.sh @@ -9,7 +9,7 @@ export job="gempakpgrb2spec" export jobid="${job}.$$" # Execute the JJOB -"${HOMEgfs}/jobs/JGFS_ATMOS_GEMPAK_PGRB2_SPEC" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_GEMPAK_PGRB2_SPEC" status=$? exit "${status}" diff --git a/dev/jobs/gempakmeta.sh b/dev/job_cards/rocoto/gempakmeta.sh similarity index 86% rename from dev/jobs/gempakmeta.sh rename to dev/job_cards/rocoto/gempakmeta.sh index 0619ea02228..d980d9e8bdd 100755 --- a/dev/jobs/gempakmeta.sh +++ b/dev/job_cards/rocoto/gempakmeta.sh @@ -11,7 +11,7 @@ export job="gempakmeta" export jobid="${job}.$$" # Execute the JJOB -"${HOMEgfs}/jobs/JGFS_ATMOS_GEMPAK_META" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_GEMPAK_META" status=$? exit "${status}" diff --git a/dev/jobs/gempakmetancdc.sh b/dev/job_cards/rocoto/gempakmetancdc.sh similarity index 85% rename from dev/jobs/gempakmetancdc.sh rename to dev/job_cards/rocoto/gempakmetancdc.sh index 7d447bce25d..423e48e7c24 100755 --- a/dev/jobs/gempakmetancdc.sh +++ b/dev/job_cards/rocoto/gempakmetancdc.sh @@ -11,7 +11,7 @@ export job="gempakmetancdc" export jobid="${job}.$$" # Execute the JJOB -"${HOMEgfs}/jobs/JGDAS_ATMOS_GEMPAK_META_NCDC" +"${HOMEgfs}/dev/jobs/JGDAS_ATMOS_GEMPAK_META_NCDC" status=$? exit "${status}" diff --git a/dev/jobs/gempakncdcupapgif.sh b/dev/job_cards/rocoto/gempakncdcupapgif.sh similarity index 85% rename from dev/jobs/gempakncdcupapgif.sh rename to dev/job_cards/rocoto/gempakncdcupapgif.sh index 7f3988ca0bc..8e95860300a 100755 --- a/dev/jobs/gempakncdcupapgif.sh +++ b/dev/job_cards/rocoto/gempakncdcupapgif.sh @@ -11,7 +11,7 @@ export job="gempakncdcupapgif" export jobid="${job}.$$" # Execute the JJOB -"${HOMEgfs}/jobs/JGFS_ATMOS_GEMPAK_NCDC_UPAPGIF" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_GEMPAK_NCDC_UPAPGIF" status=$? exit "${status}" diff --git a/dev/jobs/gen_control_ic.sh b/dev/job_cards/rocoto/gen_control_ic.sh similarity index 84% rename from dev/jobs/gen_control_ic.sh rename to dev/job_cards/rocoto/gen_control_ic.sh index 0d4bddbc600..cfe6299501e 100755 --- a/dev/jobs/gen_control_ic.sh +++ b/dev/job_cards/rocoto/gen_control_ic.sh @@ -10,7 +10,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMOS_CHGRES_GEN_CONTROL" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_CHGRES_GEN_CONTROL" status=$? exit "${status}" diff --git a/dev/jobs/genesis.sh b/dev/job_cards/rocoto/genesis.sh similarity index 88% rename from dev/jobs/genesis.sh rename to dev/job_cards/rocoto/genesis.sh index 0e954ffd897..0f3102faa1c 100755 --- a/dev/jobs/genesis.sh +++ b/dev/job_cards/rocoto/genesis.sh @@ -14,7 +14,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGFS_ATMOS_CYCLONE_GENESIS" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_CYCLONE_GENESIS" status=$? exit "${status}" diff --git a/dev/jobs/genesis_fsu.sh b/dev/job_cards/rocoto/genesis_fsu.sh similarity index 89% rename from dev/jobs/genesis_fsu.sh rename to dev/job_cards/rocoto/genesis_fsu.sh index b39eff9d88b..0290ef1659b 100755 --- a/dev/jobs/genesis_fsu.sh +++ b/dev/job_cards/rocoto/genesis_fsu.sh @@ -14,7 +14,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGFS_ATMOS_FSU_GENESIS" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_FSU_GENESIS" status=$? exit "${status}" diff --git a/dev/jobs/globus_arch.sh b/dev/job_cards/rocoto/globus_arch.sh similarity index 90% rename from dev/jobs/globus_arch.sh rename to dev/job_cards/rocoto/globus_arch.sh index 9bd32136e45..2d33c047678 100755 --- a/dev/jobs/globus_arch.sh +++ b/dev/job_cards/rocoto/globus_arch.sh @@ -13,7 +13,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_GLOBUS_ARCH" +"${HOMEgfs}/dev/jobs/JGLOBAL_GLOBUS_ARCH" status=$? exit "${status}" diff --git a/dev/jobs/globus_earc.sh b/dev/job_cards/rocoto/globus_earc.sh similarity index 89% rename from dev/jobs/globus_earc.sh rename to dev/job_cards/rocoto/globus_earc.sh index 0bb421b41f7..61f7d5f6f49 100755 --- a/dev/jobs/globus_earc.sh +++ b/dev/job_cards/rocoto/globus_earc.sh @@ -13,7 +13,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ENS_GLOBUS_ARCH" +"${HOMEgfs}/dev/jobs/JGLOBAL_ENS_GLOBUS_ARCH" status=$? exit "${status}" diff --git a/dev/jobs/marineanlchkpt.sh b/dev/job_cards/rocoto/marineanlchkpt.sh similarity index 87% rename from dev/jobs/marineanlchkpt.sh rename to dev/job_cards/rocoto/marineanlchkpt.sh index 3c1de075cae..7734d330de4 100755 --- a/dev/jobs/marineanlchkpt.sh +++ b/dev/job_cards/rocoto/marineanlchkpt.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT +"${HOMEgfs}"/dev/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT status=$? exit "${status}" diff --git a/dev/jobs/marineanlecen.sh b/dev/job_cards/rocoto/marineanlecen.sh similarity index 92% rename from dev/jobs/marineanlecen.sh rename to dev/job_cards/rocoto/marineanlecen.sh index 9d1678c9122..8c1f633b97a 100755 --- a/dev/jobs/marineanlecen.sh +++ b/dev/job_cards/rocoto/marineanlecen.sh @@ -20,6 +20,6 @@ export PYTHONPATH ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_MARINE_ANALYSIS_ECEN +"${HOMEgfs}"/dev/jobs/JGLOBAL_MARINE_ANALYSIS_ECEN status=$? exit "${status}" diff --git a/dev/jobs/marineanlfinal.sh b/dev/job_cards/rocoto/marineanlfinal.sh similarity index 88% rename from dev/jobs/marineanlfinal.sh rename to dev/job_cards/rocoto/marineanlfinal.sh index 127f74693fd..991cd7cda49 100755 --- a/dev/jobs/marineanlfinal.sh +++ b/dev/job_cards/rocoto/marineanlfinal.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE +"${HOMEgfs}"/dev/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE status=$? exit "${status}" diff --git a/dev/jobs/marineanlinit.sh b/dev/job_cards/rocoto/marineanlinit.sh similarity index 88% rename from dev/jobs/marineanlinit.sh rename to dev/job_cards/rocoto/marineanlinit.sh index 4a5e75db985..5357a8f24c3 100755 --- a/dev/jobs/marineanlinit.sh +++ b/dev/job_cards/rocoto/marineanlinit.sh @@ -16,6 +16,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE +"${HOMEgfs}"/dev/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE status=$? exit "${status}" diff --git a/dev/jobs/marineanlletkf.sh b/dev/job_cards/rocoto/marineanlletkf.sh similarity index 88% rename from dev/jobs/marineanlletkf.sh rename to dev/job_cards/rocoto/marineanlletkf.sh index 51a342d58f0..70add214186 100755 --- a/dev/jobs/marineanlletkf.sh +++ b/dev/job_cards/rocoto/marineanlletkf.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_MARINE_ANALYSIS_LETKF" +"${HOMEgfs}/dev/jobs/JGLOBAL_MARINE_ANALYSIS_LETKF" status=$? exit "${status}" diff --git a/dev/jobs/marineanlvar.sh b/dev/job_cards/rocoto/marineanlvar.sh similarity index 87% rename from dev/jobs/marineanlvar.sh rename to dev/job_cards/rocoto/marineanlvar.sh index ac8d06a4a0c..facad6c38ad 100755 --- a/dev/jobs/marineanlvar.sh +++ b/dev/job_cards/rocoto/marineanlvar.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL" +"${HOMEgfs}/dev/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL" status=$? exit "${status}" diff --git a/dev/jobs/marinebmat.sh b/dev/job_cards/rocoto/marinebmat.sh similarity index 90% rename from dev/jobs/marinebmat.sh rename to dev/job_cards/rocoto/marinebmat.sh index 94d3dd3e9f2..d2b898ce4ad 100755 --- a/dev/jobs/marinebmat.sh +++ b/dev/job_cards/rocoto/marinebmat.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_MARINE_BMAT +"${HOMEgfs}"/dev/jobs/JGLOBAL_MARINE_BMAT status=$? exit "${status}" diff --git a/dev/jobs/marinebmatinit.sh b/dev/job_cards/rocoto/marinebmatinit.sh similarity index 88% rename from dev/jobs/marinebmatinit.sh rename to dev/job_cards/rocoto/marinebmatinit.sh index 4cbaff95a8d..db9685d6c04 100755 --- a/dev/jobs/marinebmatinit.sh +++ b/dev/job_cards/rocoto/marinebmatinit.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_MARINE_BMAT_INITIALIZE +"${HOMEgfs}"/dev/jobs/JGLOBAL_MARINE_BMAT_INITIALIZE status=$? exit "${status}" diff --git a/dev/jobs/metp.sh b/dev/job_cards/rocoto/metp.sh similarity index 85% rename from dev/jobs/metp.sh rename to dev/job_cards/rocoto/metp.sh index d31310ef20c..38fd4272d45 100755 --- a/dev/jobs/metp.sh +++ b/dev/job_cards/rocoto/metp.sh @@ -10,6 +10,6 @@ if ((status != 0)); then exit "${status}"; fi export job="metp${METPCASE}" export jobid="${job}.$$" -"${HOMEgfs}/jobs/JGFS_ATMOS_VERIFICATION" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_VERIFICATION" exit $? diff --git a/dev/jobs/npoess.sh b/dev/job_cards/rocoto/npoess.sh similarity index 85% rename from dev/jobs/npoess.sh rename to dev/job_cards/rocoto/npoess.sh index e992dc73a7b..7c5d59b8abb 100755 --- a/dev/jobs/npoess.sh +++ b/dev/job_cards/rocoto/npoess.sh @@ -11,7 +11,7 @@ export job="npoess_pgrb2_0p5deg" export jobid="${job}.$$" # Execute the JJOB -"${HOMEgfs}/jobs/JGFS_ATMOS_PGRB2_SPEC_NPOESS" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_PGRB2_SPEC_NPOESS" status=$? exit "${status}" diff --git a/dev/jobs/oceanice_products.sh b/dev/job_cards/rocoto/oceanice_products.sh similarity index 94% rename from dev/jobs/oceanice_products.sh rename to dev/job_cards/rocoto/oceanice_products.sh index a23c70f5113..b8564ec4f4c 100755 --- a/dev/jobs/oceanice_products.sh +++ b/dev/job_cards/rocoto/oceanice_products.sh @@ -24,7 +24,7 @@ for FORECAST_HOUR in "${fhr_list[@]}"; do ############################################################### # Execute the JJOB ############################################################### - "${HOMEgfs}/jobs/JGLOBAL_OCEANICE_PRODUCTS" + "${HOMEgfs}/dev/jobs/JGLOBAL_OCEANICE_PRODUCTS" status=$? [[ ${status} -ne 0 ]] && exit "${status}" done diff --git a/dev/jobs/offlineanl.sh b/dev/job_cards/rocoto/offlineanl.sh similarity index 88% rename from dev/jobs/offlineanl.sh rename to dev/job_cards/rocoto/offlineanl.sh index 26f5576c58d..74a8da33182 100755 --- a/dev/jobs/offlineanl.sh +++ b/dev/job_cards/rocoto/offlineanl.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_OFFLINE_ATMOS_ANALYSIS" +"${HOMEgfs}/dev/jobs/JGLOBAL_OFFLINE_ATMOS_ANALYSIS" status=$? exit "${status}" diff --git a/dev/jobs/postsnd.sh b/dev/job_cards/rocoto/postsnd.sh similarity index 87% rename from dev/jobs/postsnd.sh rename to dev/job_cards/rocoto/postsnd.sh index a7da693a5a7..f8d5e15e65a 100755 --- a/dev/jobs/postsnd.sh +++ b/dev/job_cards/rocoto/postsnd.sh @@ -13,6 +13,6 @@ export jobid="${job}.$$" ################################################################ # Execute the JJOB -"${HOMEgfs}/jobs/JGFS_ATMOS_POSTSND" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_POSTSND" err=$? exit "${err}" diff --git a/dev/jobs/prep.sh b/dev/job_cards/rocoto/prep.sh similarity index 99% rename from dev/jobs/prep.sh rename to dev/job_cards/rocoto/prep.sh index 6b662967cba..59df45e563e 100755 --- a/dev/jobs/prep.sh +++ b/dev/job_cards/rocoto/prep.sh @@ -102,7 +102,7 @@ if [[ ${PROCESS_TROPCY} == "YES" ]]; then rm -f "${COMOUT_OBS}/${RUN_local}.t${cyc}z.syndata.tcvitals.tm00" - "${HOMEgfs}/jobs/JGLOBAL_ATMOS_TROPCY_QC_RELOC" + "${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_TROPCY_QC_RELOC" status=$? if [[ ${status} -ne 0 ]]; then exit "${status}" diff --git a/dev/jobs/prep_emissions.sh b/dev/job_cards/rocoto/prep_emissions.sh similarity index 89% rename from dev/jobs/prep_emissions.sh rename to dev/job_cards/rocoto/prep_emissions.sh index 11bd0799307..c764660bb74 100755 --- a/dev/jobs/prep_emissions.sh +++ b/dev/job_cards/rocoto/prep_emissions.sh @@ -13,6 +13,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_PREP_EMISSIONS" +"${HOMEgfs}/dev/jobs/JGLOBAL_PREP_EMISSIONS" status=$? exit "${status}" diff --git a/dev/jobs/prep_sfc.sh b/dev/job_cards/rocoto/prep_sfc.sh similarity index 89% rename from dev/jobs/prep_sfc.sh rename to dev/job_cards/rocoto/prep_sfc.sh index 4d4164ca7ad..fd524f04fc5 100755 --- a/dev/jobs/prep_sfc.sh +++ b/dev/job_cards/rocoto/prep_sfc.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMOS_PREP_SFC" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_PREP_SFC" status=$? exit "${status}" diff --git a/dev/jobs/prepoceanobs.sh b/dev/job_cards/rocoto/prepoceanobs.sh similarity index 90% rename from dev/jobs/prepoceanobs.sh rename to dev/job_cards/rocoto/prepoceanobs.sh index 38f71e3ee39..ee68a3464c6 100755 --- a/dev/jobs/prepoceanobs.sh +++ b/dev/job_cards/rocoto/prepoceanobs.sh @@ -15,6 +15,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGLOBAL_PREP_OCEAN_OBS +"${HOMEgfs}"/dev/jobs/JGLOBAL_PREP_OCEAN_OBS status=$? exit "${status}" diff --git a/dev/jobs/sfcanl.sh b/dev/job_cards/rocoto/sfcanl.sh similarity index 90% rename from dev/jobs/sfcanl.sh rename to dev/job_cards/rocoto/sfcanl.sh index 0d029f943d2..d6738fe3a11 100755 --- a/dev/jobs/sfcanl.sh +++ b/dev/job_cards/rocoto/sfcanl.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_ATMOS_SFCANL" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_SFCANL" status=$? exit "${status}" diff --git a/dev/jobs/snowanl.sh b/dev/job_cards/rocoto/snowanl.sh similarity index 89% rename from dev/jobs/snowanl.sh rename to dev/job_cards/rocoto/snowanl.sh index 84b401f7750..eb4c7a92f98 100755 --- a/dev/jobs/snowanl.sh +++ b/dev/job_cards/rocoto/snowanl.sh @@ -13,6 +13,6 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_SNOW_ANALYSIS" +"${HOMEgfs}/dev/jobs/JGLOBAL_SNOW_ANALYSIS" status=$? exit "${status}" diff --git a/dev/jobs/stage_ic.sh b/dev/job_cards/rocoto/stage_ic.sh similarity index 87% rename from dev/jobs/stage_ic.sh rename to dev/job_cards/rocoto/stage_ic.sh index e104d785f9c..cb5c215f438 100755 --- a/dev/jobs/stage_ic.sh +++ b/dev/job_cards/rocoto/stage_ic.sh @@ -13,7 +13,7 @@ export job="stage_ic" export jobid="${job}.$$" # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_STAGE_IC" +"${HOMEgfs}/dev/jobs/JGLOBAL_STAGE_IC" status=$? exit "${status}" diff --git a/dev/jobs/tracker.sh b/dev/job_cards/rocoto/tracker.sh similarity index 88% rename from dev/jobs/tracker.sh rename to dev/job_cards/rocoto/tracker.sh index 6062e6086dd..c13de1848fe 100755 --- a/dev/jobs/tracker.sh +++ b/dev/job_cards/rocoto/tracker.sh @@ -14,7 +14,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGFS_ATMOS_CYCLONE_TRACKER" +"${HOMEgfs}/dev/jobs/JGFS_ATMOS_CYCLONE_TRACKER" status=$? exit "${status}" diff --git a/dev/jobs/upp.sh b/dev/job_cards/rocoto/upp.sh similarity index 95% rename from dev/jobs/upp.sh rename to dev/job_cards/rocoto/upp.sh index 923a92d46f3..ca6dd65a23c 100755 --- a/dev/jobs/upp.sh +++ b/dev/job_cards/rocoto/upp.sh @@ -28,6 +28,6 @@ export FORECAST_HOUR=$((10#${FHR3})) ############################################################### # Execute the JJOB ############################################################### -"${HOMEgfs}/jobs/JGLOBAL_ATMOS_UPP" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_UPP" exit $? diff --git a/dev/jobs/verfozn.sh b/dev/job_cards/rocoto/verfozn.sh similarity index 91% rename from dev/jobs/verfozn.sh rename to dev/job_cards/rocoto/verfozn.sh index 4ae7c594fc2..018be19a002 100755 --- a/dev/jobs/verfozn.sh +++ b/dev/job_cards/rocoto/verfozn.sh @@ -18,7 +18,7 @@ export jobid="${job}.$$" echo echo "=============== START TO RUN OZMON DATA EXTRACTION ===============" -"${HOMEgfs}/jobs/JGDAS_ATMOS_VERFOZN" +"${HOMEgfs}/dev/jobs/JGDAS_ATMOS_VERFOZN" status=$? exit "${status}" diff --git a/dev/jobs/verfrad.sh b/dev/job_cards/rocoto/verfrad.sh similarity index 91% rename from dev/jobs/verfrad.sh rename to dev/job_cards/rocoto/verfrad.sh index 815983deb80..6e8b13049f0 100755 --- a/dev/jobs/verfrad.sh +++ b/dev/job_cards/rocoto/verfrad.sh @@ -18,7 +18,7 @@ export jobid="${job}.$$" echo echo "=============== START TO RUN RADMON DATA EXTRACTION ===============" -"${HOMEgfs}/jobs/JGDAS_ATMOS_VERFRAD" +"${HOMEgfs}/dev/jobs/JGDAS_ATMOS_VERFRAD" status=$? exit "${status}" diff --git a/dev/jobs/vminmon.sh b/dev/job_cards/rocoto/vminmon.sh similarity index 91% rename from dev/jobs/vminmon.sh rename to dev/job_cards/rocoto/vminmon.sh index 20c4d5dad6b..b05c2963859 100755 --- a/dev/jobs/vminmon.sh +++ b/dev/job_cards/rocoto/vminmon.sh @@ -18,7 +18,7 @@ export jobid="${job}.$$" echo echo "=============== START TO RUN MINMON ===============" -"${HOMEgfs}/jobs/JGLOBAL_ATMOS_VMINMON" +"${HOMEgfs}/dev/jobs/JGLOBAL_ATMOS_VMINMON" status=$? exit "${status}" diff --git a/dev/jobs/wave_stat.sh b/dev/job_cards/rocoto/wave_stat.sh similarity index 94% rename from dev/jobs/wave_stat.sh rename to dev/job_cards/rocoto/wave_stat.sh index abe1ef0a04c..a2b8260d5f5 100755 --- a/dev/jobs/wave_stat.sh +++ b/dev/job_cards/rocoto/wave_stat.sh @@ -22,7 +22,7 @@ for FORECAST_HOUR in "${fhr_list[@]}"; do FHR3=$(printf '%03d' "${FORECAST_HOUR}") jobid="${job}_f${FHR3}.$$" # Execute the JJOB - "${HOMEgfs}/jobs/JGEFS_WAVE_STAT" + "${HOMEgfs}/dev/jobs/JGEFS_WAVE_STAT" err=$? if [[ "${err}" -ne 0 ]]; then exit "${err}" diff --git a/dev/jobs/wave_stat_pnt.sh b/dev/job_cards/rocoto/wave_stat_pnt.sh similarity index 91% rename from dev/jobs/wave_stat_pnt.sh rename to dev/job_cards/rocoto/wave_stat_pnt.sh index beabf3cd573..71c3fbab146 100755 --- a/dev/jobs/wave_stat_pnt.sh +++ b/dev/job_cards/rocoto/wave_stat_pnt.sh @@ -14,7 +14,7 @@ export jobid="${job}.$$" echo echo "=============== START TO RUN WAVESTAT PNT ===============" # Execute the JJOB -"${HOMEgfs}/jobs/JGEFS_WAVE_STAT_PNT" +"${HOMEgfs}/dev/jobs/JGEFS_WAVE_STAT_PNT" err=$? if [[ "${err}" -ne 0 ]]; then exit "${err}" diff --git a/dev/jobs/waveawipsbulls.sh b/dev/job_cards/rocoto/waveawipsbulls.sh similarity index 89% rename from dev/jobs/waveawipsbulls.sh rename to dev/job_cards/rocoto/waveawipsbulls.sh index fb28736b965..68304158c0c 100755 --- a/dev/jobs/waveawipsbulls.sh +++ b/dev/job_cards/rocoto/waveawipsbulls.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_WAVE_PRDGEN_BULLS" +"${HOMEgfs}/dev/jobs/JGLOBAL_WAVE_PRDGEN_BULLS" status=$? exit "${status}" diff --git a/dev/jobs/waveawipsgridded.sh b/dev/job_cards/rocoto/waveawipsgridded.sh similarity index 89% rename from dev/jobs/waveawipsgridded.sh rename to dev/job_cards/rocoto/waveawipsgridded.sh index 9fbfd40a7f4..100bf545d31 100755 --- a/dev/jobs/waveawipsgridded.sh +++ b/dev/job_cards/rocoto/waveawipsgridded.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_WAVE_PRDGEN_GRIDDED" +"${HOMEgfs}/dev/jobs/JGLOBAL_WAVE_PRDGEN_GRIDDED" status=$? exit "${status}" diff --git a/dev/jobs/wavegempak.sh b/dev/job_cards/rocoto/wavegempak.sh similarity index 93% rename from dev/jobs/wavegempak.sh rename to dev/job_cards/rocoto/wavegempak.sh index e9dc4bf7bcd..60a66e749eb 100755 --- a/dev/jobs/wavegempak.sh +++ b/dev/job_cards/rocoto/wavegempak.sh @@ -21,7 +21,7 @@ for FORECAST_HOUR in "${fhr_list[@]}"; do fhr3=$(printf '%03d' "${FORECAST_HOUR}") jobid="${job}_f${fhr3}.$$" # Execute the JJOB - "${HOMEgfs}/jobs/JGLOBAL_WAVE_GEMPAK" + "${HOMEgfs}/dev/jobs/JGLOBAL_WAVE_GEMPAK" err=$? if [[ "${err}" -ne 0 ]]; then exit "${err}" diff --git a/dev/jobs/waveinit.sh b/dev/job_cards/rocoto/waveinit.sh similarity index 91% rename from dev/jobs/waveinit.sh rename to dev/job_cards/rocoto/waveinit.sh index c04a50298ec..4770c56356a 100755 --- a/dev/jobs/waveinit.sh +++ b/dev/job_cards/rocoto/waveinit.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_WAVE_INIT" +"${HOMEgfs}/dev/jobs/JGLOBAL_WAVE_INIT" status=$? exit "${status}" diff --git a/dev/jobs/wavepostbndpnt.sh b/dev/job_cards/rocoto/wavepostbndpnt.sh similarity index 92% rename from dev/jobs/wavepostbndpnt.sh rename to dev/job_cards/rocoto/wavepostbndpnt.sh index cc30ce0f268..8bd2969a178 100755 --- a/dev/jobs/wavepostbndpnt.sh +++ b/dev/job_cards/rocoto/wavepostbndpnt.sh @@ -19,7 +19,7 @@ export jobid="${job}.$$" echo echo "=============== START TO RUN WAVE_POST_BNDPNT ===============" # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_WAVE_POST_BNDPNT" +"${HOMEgfs}/dev/jobs/JGLOBAL_WAVE_POST_BNDPNT" err=$? if [[ "${err}" -ne 0 ]]; then exit "${err}" diff --git a/dev/jobs/wavepostbndpntbll.sh b/dev/job_cards/rocoto/wavepostbndpntbll.sh similarity index 92% rename from dev/jobs/wavepostbndpntbll.sh rename to dev/job_cards/rocoto/wavepostbndpntbll.sh index ec9d66c993e..91e34d691b3 100755 --- a/dev/jobs/wavepostbndpntbll.sh +++ b/dev/job_cards/rocoto/wavepostbndpntbll.sh @@ -19,7 +19,7 @@ export jobid="${job}.$$" echo echo "=============== START TO RUN WAVE_POST_BNDPNT ===============" # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_WAVE_POST_BNDPNTBLL" +"${HOMEgfs}/dev/jobs/JGLOBAL_WAVE_POST_BNDPNTBLL" err=$? if [[ "${err}" -ne 0 ]]; then exit "${err}" diff --git a/dev/jobs/wavepostpnt.sh b/dev/job_cards/rocoto/wavepostpnt.sh similarity index 93% rename from dev/jobs/wavepostpnt.sh rename to dev/job_cards/rocoto/wavepostpnt.sh index 612b39ef959..ad18783810d 100755 --- a/dev/jobs/wavepostpnt.sh +++ b/dev/job_cards/rocoto/wavepostpnt.sh @@ -17,7 +17,7 @@ export jobid="${job}.$$" echo echo "=============== START TO RUN WAVE_POST_PNT ===============" # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_WAVE_POST_PNT" +"${HOMEgfs}/dev/jobs/JGLOBAL_WAVE_POST_PNT" err=$? if [[ "${err}" -ne 0 ]]; then exit "${err}" diff --git a/dev/jobs/wavepostsbs.sh b/dev/job_cards/rocoto/wavepostsbs.sh similarity index 93% rename from dev/jobs/wavepostsbs.sh rename to dev/job_cards/rocoto/wavepostsbs.sh index 678f201b26d..4acfe335914 100755 --- a/dev/jobs/wavepostsbs.sh +++ b/dev/job_cards/rocoto/wavepostsbs.sh @@ -22,7 +22,7 @@ for FORECAST_HOUR in "${fhr_list[@]}"; do fhr3=$(printf '%03d' "${FORECAST_HOUR}") jobid="${job}_f${fhr3}.$$" # Execute the JJOB - "${HOMEgfs}/jobs/JGLOBAL_WAVE_POST_SBS" + "${HOMEgfs}/dev/jobs/JGLOBAL_WAVE_POST_SBS" err=$? if [[ "${err}" -ne 0 ]]; then exit "${err}" diff --git a/dev/jobs/waveprep.sh b/dev/job_cards/rocoto/waveprep.sh similarity index 92% rename from dev/jobs/waveprep.sh rename to dev/job_cards/rocoto/waveprep.sh index ac2bbbc022a..d24086f93a4 100755 --- a/dev/jobs/waveprep.sh +++ b/dev/job_cards/rocoto/waveprep.sh @@ -15,7 +15,7 @@ export jobid="${job}.$$" ############################################################### # Execute the JJOB -"${HOMEgfs}/jobs/JGLOBAL_WAVE_PREP" +"${HOMEgfs}/dev/jobs/JGLOBAL_WAVE_PREP" status=$? if [[ ${status} -ne 0 ]]; then exit "${status}" diff --git a/jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX b/dev/jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX similarity index 100% rename from jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX rename to dev/jobs/JGDAS_AERO_ANALYSIS_GENERATE_BMATRIX diff --git a/jobs/JGDAS_ATMOS_CHGRES_FORENKF b/dev/jobs/JGDAS_ATMOS_CHGRES_FORENKF similarity index 100% rename from jobs/JGDAS_ATMOS_CHGRES_FORENKF rename to dev/jobs/JGDAS_ATMOS_CHGRES_FORENKF diff --git a/jobs/JGDAS_ATMOS_GEMPAK b/dev/jobs/JGDAS_ATMOS_GEMPAK similarity index 100% rename from jobs/JGDAS_ATMOS_GEMPAK rename to dev/jobs/JGDAS_ATMOS_GEMPAK diff --git a/jobs/JGDAS_ATMOS_GEMPAK_META_NCDC b/dev/jobs/JGDAS_ATMOS_GEMPAK_META_NCDC similarity index 100% rename from jobs/JGDAS_ATMOS_GEMPAK_META_NCDC rename to dev/jobs/JGDAS_ATMOS_GEMPAK_META_NCDC diff --git a/jobs/JGDAS_ATMOS_VERFOZN b/dev/jobs/JGDAS_ATMOS_VERFOZN similarity index 100% rename from jobs/JGDAS_ATMOS_VERFOZN rename to dev/jobs/JGDAS_ATMOS_VERFOZN diff --git a/jobs/JGDAS_ATMOS_VERFRAD b/dev/jobs/JGDAS_ATMOS_VERFRAD similarity index 100% rename from jobs/JGDAS_ATMOS_VERFRAD rename to dev/jobs/JGDAS_ATMOS_VERFRAD diff --git a/jobs/JGDAS_ENKF_POST b/dev/jobs/JGDAS_ENKF_POST similarity index 100% rename from jobs/JGDAS_ENKF_POST rename to dev/jobs/JGDAS_ENKF_POST diff --git a/jobs/JGDAS_FIT2OBS b/dev/jobs/JGDAS_FIT2OBS similarity index 100% rename from jobs/JGDAS_FIT2OBS rename to dev/jobs/JGDAS_FIT2OBS diff --git a/jobs/JGEFS_WAVE_STAT b/dev/jobs/JGEFS_WAVE_STAT similarity index 100% rename from jobs/JGEFS_WAVE_STAT rename to dev/jobs/JGEFS_WAVE_STAT diff --git a/jobs/JGEFS_WAVE_STAT_PNT b/dev/jobs/JGEFS_WAVE_STAT_PNT similarity index 100% rename from jobs/JGEFS_WAVE_STAT_PNT rename to dev/jobs/JGEFS_WAVE_STAT_PNT diff --git a/jobs/JGFS_ATMOS_AWIPS_20KM_1P0DEG b/dev/jobs/JGFS_ATMOS_AWIPS_20KM_1P0DEG similarity index 100% rename from jobs/JGFS_ATMOS_AWIPS_20KM_1P0DEG rename to dev/jobs/JGFS_ATMOS_AWIPS_20KM_1P0DEG diff --git a/jobs/JGFS_ATMOS_CYCLONE_GENESIS b/dev/jobs/JGFS_ATMOS_CYCLONE_GENESIS similarity index 100% rename from jobs/JGFS_ATMOS_CYCLONE_GENESIS rename to dev/jobs/JGFS_ATMOS_CYCLONE_GENESIS diff --git a/jobs/JGFS_ATMOS_CYCLONE_TRACKER b/dev/jobs/JGFS_ATMOS_CYCLONE_TRACKER similarity index 100% rename from jobs/JGFS_ATMOS_CYCLONE_TRACKER rename to dev/jobs/JGFS_ATMOS_CYCLONE_TRACKER diff --git a/jobs/JGFS_ATMOS_FBWIND b/dev/jobs/JGFS_ATMOS_FBWIND similarity index 100% rename from jobs/JGFS_ATMOS_FBWIND rename to dev/jobs/JGFS_ATMOS_FBWIND diff --git a/jobs/JGFS_ATMOS_FSU_GENESIS b/dev/jobs/JGFS_ATMOS_FSU_GENESIS similarity index 100% rename from jobs/JGFS_ATMOS_FSU_GENESIS rename to dev/jobs/JGFS_ATMOS_FSU_GENESIS diff --git a/jobs/JGFS_ATMOS_GEMPAK b/dev/jobs/JGFS_ATMOS_GEMPAK similarity index 100% rename from jobs/JGFS_ATMOS_GEMPAK rename to dev/jobs/JGFS_ATMOS_GEMPAK diff --git a/jobs/JGFS_ATMOS_GEMPAK_META b/dev/jobs/JGFS_ATMOS_GEMPAK_META similarity index 100% rename from jobs/JGFS_ATMOS_GEMPAK_META rename to dev/jobs/JGFS_ATMOS_GEMPAK_META diff --git a/jobs/JGFS_ATMOS_GEMPAK_NCDC_UPAPGIF b/dev/jobs/JGFS_ATMOS_GEMPAK_NCDC_UPAPGIF similarity index 100% rename from jobs/JGFS_ATMOS_GEMPAK_NCDC_UPAPGIF rename to dev/jobs/JGFS_ATMOS_GEMPAK_NCDC_UPAPGIF diff --git a/jobs/JGFS_ATMOS_GEMPAK_PGRB2_SPEC b/dev/jobs/JGFS_ATMOS_GEMPAK_PGRB2_SPEC similarity index 100% rename from jobs/JGFS_ATMOS_GEMPAK_PGRB2_SPEC rename to dev/jobs/JGFS_ATMOS_GEMPAK_PGRB2_SPEC diff --git a/jobs/JGFS_ATMOS_PGRB2_SPEC_NPOESS b/dev/jobs/JGFS_ATMOS_PGRB2_SPEC_NPOESS similarity index 100% rename from jobs/JGFS_ATMOS_PGRB2_SPEC_NPOESS rename to dev/jobs/JGFS_ATMOS_PGRB2_SPEC_NPOESS diff --git a/jobs/JGFS_ATMOS_POSTSND b/dev/jobs/JGFS_ATMOS_POSTSND similarity index 100% rename from jobs/JGFS_ATMOS_POSTSND rename to dev/jobs/JGFS_ATMOS_POSTSND diff --git a/jobs/JGFS_ATMOS_VERIFICATION b/dev/jobs/JGFS_ATMOS_VERIFICATION similarity index 100% rename from jobs/JGFS_ATMOS_VERIFICATION rename to dev/jobs/JGFS_ATMOS_VERIFICATION diff --git a/jobs/JGLOBAL_AERO_ANALYSIS_FINALIZE b/dev/jobs/JGLOBAL_AERO_ANALYSIS_FINALIZE similarity index 100% rename from jobs/JGLOBAL_AERO_ANALYSIS_FINALIZE rename to dev/jobs/JGLOBAL_AERO_ANALYSIS_FINALIZE diff --git a/jobs/JGLOBAL_AERO_ANALYSIS_INITIALIZE b/dev/jobs/JGLOBAL_AERO_ANALYSIS_INITIALIZE similarity index 100% rename from jobs/JGLOBAL_AERO_ANALYSIS_INITIALIZE rename to dev/jobs/JGLOBAL_AERO_ANALYSIS_INITIALIZE diff --git a/jobs/JGLOBAL_AERO_ANALYSIS_VARIATIONAL b/dev/jobs/JGLOBAL_AERO_ANALYSIS_VARIATIONAL similarity index 100% rename from jobs/JGLOBAL_AERO_ANALYSIS_VARIATIONAL rename to dev/jobs/JGLOBAL_AERO_ANALYSIS_VARIATIONAL diff --git a/jobs/JGLOBAL_ANALYSIS_STATS b/dev/jobs/JGLOBAL_ANALYSIS_STATS similarity index 100% rename from jobs/JGLOBAL_ANALYSIS_STATS rename to dev/jobs/JGLOBAL_ANALYSIS_STATS diff --git a/jobs/JGLOBAL_ARCHIVE_TARS b/dev/jobs/JGLOBAL_ARCHIVE_TARS similarity index 100% rename from jobs/JGLOBAL_ARCHIVE_TARS rename to dev/jobs/JGLOBAL_ARCHIVE_TARS diff --git a/jobs/JGLOBAL_ARCHIVE_VRFY b/dev/jobs/JGLOBAL_ARCHIVE_VRFY similarity index 100% rename from jobs/JGLOBAL_ARCHIVE_VRFY rename to dev/jobs/JGLOBAL_ARCHIVE_VRFY diff --git a/jobs/JGLOBAL_ATMENS_ANALYSIS_FINALIZE b/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_FINALIZE similarity index 100% rename from jobs/JGLOBAL_ATMENS_ANALYSIS_FINALIZE rename to dev/jobs/JGLOBAL_ATMENS_ANALYSIS_FINALIZE diff --git a/jobs/JGLOBAL_ATMENS_ANALYSIS_FV3_INCREMENT b/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_FV3_INCREMENT similarity index 100% rename from jobs/JGLOBAL_ATMENS_ANALYSIS_FV3_INCREMENT rename to dev/jobs/JGLOBAL_ATMENS_ANALYSIS_FV3_INCREMENT diff --git a/jobs/JGLOBAL_ATMENS_ANALYSIS_INITIALIZE b/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_INITIALIZE similarity index 100% rename from jobs/JGLOBAL_ATMENS_ANALYSIS_INITIALIZE rename to dev/jobs/JGLOBAL_ATMENS_ANALYSIS_INITIALIZE diff --git a/jobs/JGLOBAL_ATMENS_ANALYSIS_LETKF b/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_LETKF similarity index 100% rename from jobs/JGLOBAL_ATMENS_ANALYSIS_LETKF rename to dev/jobs/JGLOBAL_ATMENS_ANALYSIS_LETKF diff --git a/jobs/JGLOBAL_ATMENS_ANALYSIS_OBS b/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_OBS similarity index 100% rename from jobs/JGLOBAL_ATMENS_ANALYSIS_OBS rename to dev/jobs/JGLOBAL_ATMENS_ANALYSIS_OBS diff --git a/jobs/JGLOBAL_ATMENS_ANALYSIS_SOL b/dev/jobs/JGLOBAL_ATMENS_ANALYSIS_SOL similarity index 100% rename from jobs/JGLOBAL_ATMENS_ANALYSIS_SOL rename to dev/jobs/JGLOBAL_ATMENS_ANALYSIS_SOL diff --git a/jobs/JGLOBAL_ATMOS_ANALYSIS b/dev/jobs/JGLOBAL_ATMOS_ANALYSIS similarity index 100% rename from jobs/JGLOBAL_ATMOS_ANALYSIS rename to dev/jobs/JGLOBAL_ATMOS_ANALYSIS diff --git a/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC b/dev/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC similarity index 100% rename from jobs/JGLOBAL_ATMOS_ANALYSIS_CALC rename to dev/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC diff --git a/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI b/dev/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI similarity index 100% rename from jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI rename to dev/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC_FV3JEDI diff --git a/jobs/JGLOBAL_ATMOS_ANALYSIS_DIAG b/dev/jobs/JGLOBAL_ATMOS_ANALYSIS_DIAG similarity index 100% rename from jobs/JGLOBAL_ATMOS_ANALYSIS_DIAG rename to dev/jobs/JGLOBAL_ATMOS_ANALYSIS_DIAG diff --git a/jobs/JGLOBAL_ATMOS_CHGRES_GEN_CONTROL b/dev/jobs/JGLOBAL_ATMOS_CHGRES_GEN_CONTROL similarity index 100% rename from jobs/JGLOBAL_ATMOS_CHGRES_GEN_CONTROL rename to dev/jobs/JGLOBAL_ATMOS_CHGRES_GEN_CONTROL diff --git a/jobs/JGLOBAL_ATMOS_ENSSTAT b/dev/jobs/JGLOBAL_ATMOS_ENSSTAT similarity index 100% rename from jobs/JGLOBAL_ATMOS_ENSSTAT rename to dev/jobs/JGLOBAL_ATMOS_ENSSTAT diff --git a/jobs/JGLOBAL_ATMOS_POST_MANAGER b/dev/jobs/JGLOBAL_ATMOS_POST_MANAGER similarity index 100% rename from jobs/JGLOBAL_ATMOS_POST_MANAGER rename to dev/jobs/JGLOBAL_ATMOS_POST_MANAGER diff --git a/jobs/JGLOBAL_ATMOS_PREP_SFC b/dev/jobs/JGLOBAL_ATMOS_PREP_SFC similarity index 100% rename from jobs/JGLOBAL_ATMOS_PREP_SFC rename to dev/jobs/JGLOBAL_ATMOS_PREP_SFC diff --git a/jobs/JGLOBAL_ATMOS_PRODUCTS b/dev/jobs/JGLOBAL_ATMOS_PRODUCTS similarity index 100% rename from jobs/JGLOBAL_ATMOS_PRODUCTS rename to dev/jobs/JGLOBAL_ATMOS_PRODUCTS diff --git a/jobs/JGLOBAL_ATMOS_SFCANL b/dev/jobs/JGLOBAL_ATMOS_SFCANL similarity index 100% rename from jobs/JGLOBAL_ATMOS_SFCANL rename to dev/jobs/JGLOBAL_ATMOS_SFCANL diff --git a/jobs/JGLOBAL_ATMOS_TROPCY_QC_RELOC b/dev/jobs/JGLOBAL_ATMOS_TROPCY_QC_RELOC similarity index 100% rename from jobs/JGLOBAL_ATMOS_TROPCY_QC_RELOC rename to dev/jobs/JGLOBAL_ATMOS_TROPCY_QC_RELOC diff --git a/jobs/JGLOBAL_ATMOS_UPP b/dev/jobs/JGLOBAL_ATMOS_UPP similarity index 100% rename from jobs/JGLOBAL_ATMOS_UPP rename to dev/jobs/JGLOBAL_ATMOS_UPP diff --git a/jobs/JGLOBAL_ATMOS_VMINMON b/dev/jobs/JGLOBAL_ATMOS_VMINMON similarity index 100% rename from jobs/JGLOBAL_ATMOS_VMINMON rename to dev/jobs/JGLOBAL_ATMOS_VMINMON diff --git a/jobs/JGLOBAL_ATM_ANALYSIS_FINALIZE b/dev/jobs/JGLOBAL_ATM_ANALYSIS_FINALIZE similarity index 100% rename from jobs/JGLOBAL_ATM_ANALYSIS_FINALIZE rename to dev/jobs/JGLOBAL_ATM_ANALYSIS_FINALIZE diff --git a/jobs/JGLOBAL_ATM_ANALYSIS_FV3_INCREMENT b/dev/jobs/JGLOBAL_ATM_ANALYSIS_FV3_INCREMENT similarity index 100% rename from jobs/JGLOBAL_ATM_ANALYSIS_FV3_INCREMENT rename to dev/jobs/JGLOBAL_ATM_ANALYSIS_FV3_INCREMENT diff --git a/jobs/JGLOBAL_ATM_ANALYSIS_INITIALIZE b/dev/jobs/JGLOBAL_ATM_ANALYSIS_INITIALIZE similarity index 100% rename from jobs/JGLOBAL_ATM_ANALYSIS_INITIALIZE rename to dev/jobs/JGLOBAL_ATM_ANALYSIS_INITIALIZE diff --git a/jobs/JGLOBAL_ATM_ANALYSIS_VARIATIONAL b/dev/jobs/JGLOBAL_ATM_ANALYSIS_VARIATIONAL similarity index 100% rename from jobs/JGLOBAL_ATM_ANALYSIS_VARIATIONAL rename to dev/jobs/JGLOBAL_ATM_ANALYSIS_VARIATIONAL diff --git a/jobs/JGLOBAL_CLEANUP b/dev/jobs/JGLOBAL_CLEANUP similarity index 100% rename from jobs/JGLOBAL_CLEANUP rename to dev/jobs/JGLOBAL_CLEANUP diff --git a/jobs/JGLOBAL_ENKF_ARCHIVE_TARS b/dev/jobs/JGLOBAL_ENKF_ARCHIVE_TARS similarity index 100% rename from jobs/JGLOBAL_ENKF_ARCHIVE_TARS rename to dev/jobs/JGLOBAL_ENKF_ARCHIVE_TARS diff --git a/jobs/JGLOBAL_ENKF_ARCHIVE_VRFY b/dev/jobs/JGLOBAL_ENKF_ARCHIVE_VRFY similarity index 100% rename from jobs/JGLOBAL_ENKF_ARCHIVE_VRFY rename to dev/jobs/JGLOBAL_ENKF_ARCHIVE_VRFY diff --git a/jobs/JGLOBAL_ENKF_DIAG b/dev/jobs/JGLOBAL_ENKF_DIAG similarity index 100% rename from jobs/JGLOBAL_ENKF_DIAG rename to dev/jobs/JGLOBAL_ENKF_DIAG diff --git a/jobs/JGLOBAL_ENKF_ECEN b/dev/jobs/JGLOBAL_ENKF_ECEN similarity index 100% rename from jobs/JGLOBAL_ENKF_ECEN rename to dev/jobs/JGLOBAL_ENKF_ECEN diff --git a/jobs/JGLOBAL_ENKF_ECEN_FV3JEDI b/dev/jobs/JGLOBAL_ENKF_ECEN_FV3JEDI similarity index 100% rename from jobs/JGLOBAL_ENKF_ECEN_FV3JEDI rename to dev/jobs/JGLOBAL_ENKF_ECEN_FV3JEDI diff --git a/jobs/JGLOBAL_ENKF_SELECT_OBS b/dev/jobs/JGLOBAL_ENKF_SELECT_OBS similarity index 100% rename from jobs/JGLOBAL_ENKF_SELECT_OBS rename to dev/jobs/JGLOBAL_ENKF_SELECT_OBS diff --git a/jobs/JGLOBAL_ENKF_SFC b/dev/jobs/JGLOBAL_ENKF_SFC similarity index 100% rename from jobs/JGLOBAL_ENKF_SFC rename to dev/jobs/JGLOBAL_ENKF_SFC diff --git a/jobs/JGLOBAL_ENKF_UPDATE b/dev/jobs/JGLOBAL_ENKF_UPDATE similarity index 100% rename from jobs/JGLOBAL_ENKF_UPDATE rename to dev/jobs/JGLOBAL_ENKF_UPDATE diff --git a/jobs/JGLOBAL_ENS_GLOBUS_ARCH b/dev/jobs/JGLOBAL_ENS_GLOBUS_ARCH similarity index 100% rename from jobs/JGLOBAL_ENS_GLOBUS_ARCH rename to dev/jobs/JGLOBAL_ENS_GLOBUS_ARCH diff --git a/jobs/JGLOBAL_EXTRACTVARS b/dev/jobs/JGLOBAL_EXTRACTVARS similarity index 100% rename from jobs/JGLOBAL_EXTRACTVARS rename to dev/jobs/JGLOBAL_EXTRACTVARS diff --git a/jobs/JGLOBAL_FETCH b/dev/jobs/JGLOBAL_FETCH similarity index 100% rename from jobs/JGLOBAL_FETCH rename to dev/jobs/JGLOBAL_FETCH diff --git a/jobs/JGLOBAL_FORECAST b/dev/jobs/JGLOBAL_FORECAST similarity index 100% rename from jobs/JGLOBAL_FORECAST rename to dev/jobs/JGLOBAL_FORECAST diff --git a/jobs/JGLOBAL_GLOBUS_ARCH b/dev/jobs/JGLOBAL_GLOBUS_ARCH similarity index 100% rename from jobs/JGLOBAL_GLOBUS_ARCH rename to dev/jobs/JGLOBAL_GLOBUS_ARCH diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT b/dev/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT similarity index 100% rename from jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT rename to dev/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_ECEN b/dev/jobs/JGLOBAL_MARINE_ANALYSIS_ECEN similarity index 100% rename from jobs/JGLOBAL_MARINE_ANALYSIS_ECEN rename to dev/jobs/JGLOBAL_MARINE_ANALYSIS_ECEN diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE b/dev/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE similarity index 100% rename from jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE rename to dev/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE b/dev/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE similarity index 100% rename from jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE rename to dev/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_LETKF b/dev/jobs/JGLOBAL_MARINE_ANALYSIS_LETKF similarity index 100% rename from jobs/JGLOBAL_MARINE_ANALYSIS_LETKF rename to dev/jobs/JGLOBAL_MARINE_ANALYSIS_LETKF diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL b/dev/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL similarity index 100% rename from jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL rename to dev/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL diff --git a/jobs/JGLOBAL_MARINE_BMAT b/dev/jobs/JGLOBAL_MARINE_BMAT similarity index 100% rename from jobs/JGLOBAL_MARINE_BMAT rename to dev/jobs/JGLOBAL_MARINE_BMAT diff --git a/jobs/JGLOBAL_MARINE_BMAT_INITIALIZE b/dev/jobs/JGLOBAL_MARINE_BMAT_INITIALIZE similarity index 100% rename from jobs/JGLOBAL_MARINE_BMAT_INITIALIZE rename to dev/jobs/JGLOBAL_MARINE_BMAT_INITIALIZE diff --git a/jobs/JGLOBAL_OCEANICE_PRODUCTS b/dev/jobs/JGLOBAL_OCEANICE_PRODUCTS similarity index 100% rename from jobs/JGLOBAL_OCEANICE_PRODUCTS rename to dev/jobs/JGLOBAL_OCEANICE_PRODUCTS diff --git a/jobs/JGLOBAL_OFFLINE_ATMOS_ANALYSIS b/dev/jobs/JGLOBAL_OFFLINE_ATMOS_ANALYSIS similarity index 100% rename from jobs/JGLOBAL_OFFLINE_ATMOS_ANALYSIS rename to dev/jobs/JGLOBAL_OFFLINE_ATMOS_ANALYSIS diff --git a/jobs/JGLOBAL_PREP_EMISSIONS b/dev/jobs/JGLOBAL_PREP_EMISSIONS similarity index 100% rename from jobs/JGLOBAL_PREP_EMISSIONS rename to dev/jobs/JGLOBAL_PREP_EMISSIONS diff --git a/jobs/JGLOBAL_PREP_OCEAN_OBS b/dev/jobs/JGLOBAL_PREP_OCEAN_OBS similarity index 100% rename from jobs/JGLOBAL_PREP_OCEAN_OBS rename to dev/jobs/JGLOBAL_PREP_OCEAN_OBS diff --git a/jobs/JGLOBAL_SNOWENS_ANALYSIS b/dev/jobs/JGLOBAL_SNOWENS_ANALYSIS similarity index 100% rename from jobs/JGLOBAL_SNOWENS_ANALYSIS rename to dev/jobs/JGLOBAL_SNOWENS_ANALYSIS diff --git a/jobs/JGLOBAL_SNOW_ANALYSIS b/dev/jobs/JGLOBAL_SNOW_ANALYSIS similarity index 100% rename from jobs/JGLOBAL_SNOW_ANALYSIS rename to dev/jobs/JGLOBAL_SNOW_ANALYSIS diff --git a/jobs/JGLOBAL_STAGE_IC b/dev/jobs/JGLOBAL_STAGE_IC similarity index 100% rename from jobs/JGLOBAL_STAGE_IC rename to dev/jobs/JGLOBAL_STAGE_IC diff --git a/jobs/JGLOBAL_WAVE_GEMPAK b/dev/jobs/JGLOBAL_WAVE_GEMPAK similarity index 100% rename from jobs/JGLOBAL_WAVE_GEMPAK rename to dev/jobs/JGLOBAL_WAVE_GEMPAK diff --git a/jobs/JGLOBAL_WAVE_INIT b/dev/jobs/JGLOBAL_WAVE_INIT similarity index 100% rename from jobs/JGLOBAL_WAVE_INIT rename to dev/jobs/JGLOBAL_WAVE_INIT diff --git a/jobs/JGLOBAL_WAVE_POST_BNDPNT b/dev/jobs/JGLOBAL_WAVE_POST_BNDPNT similarity index 100% rename from jobs/JGLOBAL_WAVE_POST_BNDPNT rename to dev/jobs/JGLOBAL_WAVE_POST_BNDPNT diff --git a/jobs/JGLOBAL_WAVE_POST_BNDPNTBLL b/dev/jobs/JGLOBAL_WAVE_POST_BNDPNTBLL similarity index 100% rename from jobs/JGLOBAL_WAVE_POST_BNDPNTBLL rename to dev/jobs/JGLOBAL_WAVE_POST_BNDPNTBLL diff --git a/jobs/JGLOBAL_WAVE_POST_PNT b/dev/jobs/JGLOBAL_WAVE_POST_PNT similarity index 100% rename from jobs/JGLOBAL_WAVE_POST_PNT rename to dev/jobs/JGLOBAL_WAVE_POST_PNT diff --git a/jobs/JGLOBAL_WAVE_POST_SBS b/dev/jobs/JGLOBAL_WAVE_POST_SBS similarity index 100% rename from jobs/JGLOBAL_WAVE_POST_SBS rename to dev/jobs/JGLOBAL_WAVE_POST_SBS diff --git a/jobs/JGLOBAL_WAVE_PRDGEN_BULLS b/dev/jobs/JGLOBAL_WAVE_PRDGEN_BULLS similarity index 100% rename from jobs/JGLOBAL_WAVE_PRDGEN_BULLS rename to dev/jobs/JGLOBAL_WAVE_PRDGEN_BULLS diff --git a/jobs/JGLOBAL_WAVE_PRDGEN_GRIDDED b/dev/jobs/JGLOBAL_WAVE_PRDGEN_GRIDDED similarity index 100% rename from jobs/JGLOBAL_WAVE_PRDGEN_GRIDDED rename to dev/jobs/JGLOBAL_WAVE_PRDGEN_GRIDDED diff --git a/jobs/JGLOBAL_WAVE_PREP b/dev/jobs/JGLOBAL_WAVE_PREP similarity index 100% rename from jobs/JGLOBAL_WAVE_PREP rename to dev/jobs/JGLOBAL_WAVE_PREP diff --git a/scripts/exgdas_aero_analysis_generate_bmatrix.py b/dev/scripts/exgdas_aero_analysis_generate_bmatrix.py similarity index 100% rename from scripts/exgdas_aero_analysis_generate_bmatrix.py rename to dev/scripts/exgdas_aero_analysis_generate_bmatrix.py diff --git a/scripts/exgdas_atmos_chgres_forenkf.sh b/dev/scripts/exgdas_atmos_chgres_forenkf.sh similarity index 100% rename from scripts/exgdas_atmos_chgres_forenkf.sh rename to dev/scripts/exgdas_atmos_chgres_forenkf.sh diff --git a/scripts/exgdas_atmos_gempak_gif_ncdc.sh b/dev/scripts/exgdas_atmos_gempak_gif_ncdc.sh similarity index 100% rename from scripts/exgdas_atmos_gempak_gif_ncdc.sh rename to dev/scripts/exgdas_atmos_gempak_gif_ncdc.sh diff --git a/scripts/exgdas_atmos_nawips.sh b/dev/scripts/exgdas_atmos_nawips.sh similarity index 100% rename from scripts/exgdas_atmos_nawips.sh rename to dev/scripts/exgdas_atmos_nawips.sh diff --git a/scripts/exgdas_atmos_verfozn.sh b/dev/scripts/exgdas_atmos_verfozn.sh similarity index 100% rename from scripts/exgdas_atmos_verfozn.sh rename to dev/scripts/exgdas_atmos_verfozn.sh diff --git a/scripts/exgdas_atmos_verfrad.sh b/dev/scripts/exgdas_atmos_verfrad.sh similarity index 100% rename from scripts/exgdas_atmos_verfrad.sh rename to dev/scripts/exgdas_atmos_verfrad.sh diff --git a/scripts/exgdas_enkf_post.sh b/dev/scripts/exgdas_enkf_post.sh similarity index 100% rename from scripts/exgdas_enkf_post.sh rename to dev/scripts/exgdas_enkf_post.sh diff --git a/scripts/exgfs_aero_init_aerosol.py b/dev/scripts/exgfs_aero_init_aerosol.py similarity index 100% rename from scripts/exgfs_aero_init_aerosol.py rename to dev/scripts/exgfs_aero_init_aerosol.py diff --git a/scripts/exgfs_atmos_awips_20km_1p0deg.sh b/dev/scripts/exgfs_atmos_awips_20km_1p0deg.sh similarity index 100% rename from scripts/exgfs_atmos_awips_20km_1p0deg.sh rename to dev/scripts/exgfs_atmos_awips_20km_1p0deg.sh diff --git a/scripts/exgfs_atmos_fbwind.sh b/dev/scripts/exgfs_atmos_fbwind.sh similarity index 100% rename from scripts/exgfs_atmos_fbwind.sh rename to dev/scripts/exgfs_atmos_fbwind.sh diff --git a/scripts/exgfs_atmos_gempak_gif_ncdc_skew_t.sh b/dev/scripts/exgfs_atmos_gempak_gif_ncdc_skew_t.sh similarity index 100% rename from scripts/exgfs_atmos_gempak_gif_ncdc_skew_t.sh rename to dev/scripts/exgfs_atmos_gempak_gif_ncdc_skew_t.sh diff --git a/scripts/exgfs_atmos_gempak_meta.sh b/dev/scripts/exgfs_atmos_gempak_meta.sh similarity index 100% rename from scripts/exgfs_atmos_gempak_meta.sh rename to dev/scripts/exgfs_atmos_gempak_meta.sh diff --git a/scripts/exgfs_atmos_goes_nawips.sh b/dev/scripts/exgfs_atmos_goes_nawips.sh similarity index 100% rename from scripts/exgfs_atmos_goes_nawips.sh rename to dev/scripts/exgfs_atmos_goes_nawips.sh diff --git a/scripts/exgfs_atmos_grib2_special_npoess.sh b/dev/scripts/exgfs_atmos_grib2_special_npoess.sh similarity index 100% rename from scripts/exgfs_atmos_grib2_special_npoess.sh rename to dev/scripts/exgfs_atmos_grib2_special_npoess.sh diff --git a/scripts/exgfs_atmos_nawips.sh b/dev/scripts/exgfs_atmos_nawips.sh similarity index 100% rename from scripts/exgfs_atmos_nawips.sh rename to dev/scripts/exgfs_atmos_nawips.sh diff --git a/scripts/exgfs_atmos_postsnd.sh b/dev/scripts/exgfs_atmos_postsnd.sh similarity index 100% rename from scripts/exgfs_atmos_postsnd.sh rename to dev/scripts/exgfs_atmos_postsnd.sh diff --git a/scripts/exgfs_pmgr.sh b/dev/scripts/exgfs_pmgr.sh similarity index 100% rename from scripts/exgfs_pmgr.sh rename to dev/scripts/exgfs_pmgr.sh diff --git a/scripts/exgfs_prdgen_manager.sh b/dev/scripts/exgfs_prdgen_manager.sh similarity index 100% rename from scripts/exgfs_prdgen_manager.sh rename to dev/scripts/exgfs_prdgen_manager.sh diff --git a/scripts/exgfs_wave_init.sh b/dev/scripts/exgfs_wave_init.sh similarity index 100% rename from scripts/exgfs_wave_init.sh rename to dev/scripts/exgfs_wave_init.sh diff --git a/scripts/exgfs_wave_nawips.sh b/dev/scripts/exgfs_wave_nawips.sh similarity index 100% rename from scripts/exgfs_wave_nawips.sh rename to dev/scripts/exgfs_wave_nawips.sh diff --git a/scripts/exgfs_wave_post_gridded_sbs.sh b/dev/scripts/exgfs_wave_post_gridded_sbs.sh similarity index 100% rename from scripts/exgfs_wave_post_gridded_sbs.sh rename to dev/scripts/exgfs_wave_post_gridded_sbs.sh diff --git a/scripts/exgfs_wave_post_pnt.sh b/dev/scripts/exgfs_wave_post_pnt.sh similarity index 100% rename from scripts/exgfs_wave_post_pnt.sh rename to dev/scripts/exgfs_wave_post_pnt.sh diff --git a/scripts/exgfs_wave_prdgen_bulls.sh b/dev/scripts/exgfs_wave_prdgen_bulls.sh similarity index 100% rename from scripts/exgfs_wave_prdgen_bulls.sh rename to dev/scripts/exgfs_wave_prdgen_bulls.sh diff --git a/scripts/exgfs_wave_prdgen_gridded.sh b/dev/scripts/exgfs_wave_prdgen_gridded.sh similarity index 100% rename from scripts/exgfs_wave_prdgen_gridded.sh rename to dev/scripts/exgfs_wave_prdgen_gridded.sh diff --git a/scripts/exgfs_wave_prep.sh b/dev/scripts/exgfs_wave_prep.sh similarity index 100% rename from scripts/exgfs_wave_prep.sh rename to dev/scripts/exgfs_wave_prep.sh diff --git a/scripts/exglobal_aero_analysis_finalize.py b/dev/scripts/exglobal_aero_analysis_finalize.py similarity index 100% rename from scripts/exglobal_aero_analysis_finalize.py rename to dev/scripts/exglobal_aero_analysis_finalize.py diff --git a/scripts/exglobal_aero_analysis_initialize.py b/dev/scripts/exglobal_aero_analysis_initialize.py similarity index 100% rename from scripts/exglobal_aero_analysis_initialize.py rename to dev/scripts/exglobal_aero_analysis_initialize.py diff --git a/scripts/exglobal_aero_analysis_variational.py b/dev/scripts/exglobal_aero_analysis_variational.py similarity index 100% rename from scripts/exglobal_aero_analysis_variational.py rename to dev/scripts/exglobal_aero_analysis_variational.py diff --git a/scripts/exglobal_analysis_stats.py b/dev/scripts/exglobal_analysis_stats.py similarity index 100% rename from scripts/exglobal_analysis_stats.py rename to dev/scripts/exglobal_analysis_stats.py diff --git a/scripts/exglobal_archive_tars.py b/dev/scripts/exglobal_archive_tars.py similarity index 100% rename from scripts/exglobal_archive_tars.py rename to dev/scripts/exglobal_archive_tars.py diff --git a/scripts/exglobal_archive_vrfy.py b/dev/scripts/exglobal_archive_vrfy.py similarity index 100% rename from scripts/exglobal_archive_vrfy.py rename to dev/scripts/exglobal_archive_vrfy.py diff --git a/scripts/exglobal_atm_analysis_finalize.py b/dev/scripts/exglobal_atm_analysis_finalize.py similarity index 100% rename from scripts/exglobal_atm_analysis_finalize.py rename to dev/scripts/exglobal_atm_analysis_finalize.py diff --git a/scripts/exglobal_atm_analysis_fv3_increment.py b/dev/scripts/exglobal_atm_analysis_fv3_increment.py similarity index 100% rename from scripts/exglobal_atm_analysis_fv3_increment.py rename to dev/scripts/exglobal_atm_analysis_fv3_increment.py diff --git a/scripts/exglobal_atm_analysis_initialize.py b/dev/scripts/exglobal_atm_analysis_initialize.py similarity index 100% rename from scripts/exglobal_atm_analysis_initialize.py rename to dev/scripts/exglobal_atm_analysis_initialize.py diff --git a/scripts/exglobal_atm_analysis_variational.py b/dev/scripts/exglobal_atm_analysis_variational.py similarity index 100% rename from scripts/exglobal_atm_analysis_variational.py rename to dev/scripts/exglobal_atm_analysis_variational.py diff --git a/scripts/exglobal_atmens_analysis_finalize.py b/dev/scripts/exglobal_atmens_analysis_finalize.py similarity index 100% rename from scripts/exglobal_atmens_analysis_finalize.py rename to dev/scripts/exglobal_atmens_analysis_finalize.py diff --git a/scripts/exglobal_atmens_analysis_fv3_increment.py b/dev/scripts/exglobal_atmens_analysis_fv3_increment.py similarity index 100% rename from scripts/exglobal_atmens_analysis_fv3_increment.py rename to dev/scripts/exglobal_atmens_analysis_fv3_increment.py diff --git a/scripts/exglobal_atmens_analysis_initialize.py b/dev/scripts/exglobal_atmens_analysis_initialize.py similarity index 100% rename from scripts/exglobal_atmens_analysis_initialize.py rename to dev/scripts/exglobal_atmens_analysis_initialize.py diff --git a/scripts/exglobal_atmens_analysis_letkf.py b/dev/scripts/exglobal_atmens_analysis_letkf.py similarity index 100% rename from scripts/exglobal_atmens_analysis_letkf.py rename to dev/scripts/exglobal_atmens_analysis_letkf.py diff --git a/scripts/exglobal_atmens_analysis_obs.py b/dev/scripts/exglobal_atmens_analysis_obs.py similarity index 100% rename from scripts/exglobal_atmens_analysis_obs.py rename to dev/scripts/exglobal_atmens_analysis_obs.py diff --git a/scripts/exglobal_atmens_analysis_sol.py b/dev/scripts/exglobal_atmens_analysis_sol.py similarity index 100% rename from scripts/exglobal_atmens_analysis_sol.py rename to dev/scripts/exglobal_atmens_analysis_sol.py diff --git a/scripts/exglobal_atmos_analysis.sh b/dev/scripts/exglobal_atmos_analysis.sh similarity index 100% rename from scripts/exglobal_atmos_analysis.sh rename to dev/scripts/exglobal_atmos_analysis.sh diff --git a/scripts/exglobal_atmos_analysis_calc.sh b/dev/scripts/exglobal_atmos_analysis_calc.sh similarity index 100% rename from scripts/exglobal_atmos_analysis_calc.sh rename to dev/scripts/exglobal_atmos_analysis_calc.sh diff --git a/scripts/exglobal_atmos_analysis_calc_fv3jedi.py b/dev/scripts/exglobal_atmos_analysis_calc_fv3jedi.py similarity index 100% rename from scripts/exglobal_atmos_analysis_calc_fv3jedi.py rename to dev/scripts/exglobal_atmos_analysis_calc_fv3jedi.py diff --git a/scripts/exglobal_atmos_chgres_gen_control.sh b/dev/scripts/exglobal_atmos_chgres_gen_control.sh similarity index 100% rename from scripts/exglobal_atmos_chgres_gen_control.sh rename to dev/scripts/exglobal_atmos_chgres_gen_control.sh diff --git a/scripts/exglobal_atmos_ensstat.sh b/dev/scripts/exglobal_atmos_ensstat.sh similarity index 100% rename from scripts/exglobal_atmos_ensstat.sh rename to dev/scripts/exglobal_atmos_ensstat.sh diff --git a/scripts/exglobal_atmos_pmgr.sh b/dev/scripts/exglobal_atmos_pmgr.sh similarity index 100% rename from scripts/exglobal_atmos_pmgr.sh rename to dev/scripts/exglobal_atmos_pmgr.sh diff --git a/scripts/exglobal_atmos_products.sh b/dev/scripts/exglobal_atmos_products.sh similarity index 100% rename from scripts/exglobal_atmos_products.sh rename to dev/scripts/exglobal_atmos_products.sh diff --git a/scripts/exglobal_atmos_sfcanl.sh b/dev/scripts/exglobal_atmos_sfcanl.sh similarity index 100% rename from scripts/exglobal_atmos_sfcanl.sh rename to dev/scripts/exglobal_atmos_sfcanl.sh diff --git a/scripts/exglobal_atmos_tropcy_qc_reloc.sh b/dev/scripts/exglobal_atmos_tropcy_qc_reloc.sh similarity index 100% rename from scripts/exglobal_atmos_tropcy_qc_reloc.sh rename to dev/scripts/exglobal_atmos_tropcy_qc_reloc.sh diff --git a/scripts/exglobal_atmos_upp.py b/dev/scripts/exglobal_atmos_upp.py similarity index 100% rename from scripts/exglobal_atmos_upp.py rename to dev/scripts/exglobal_atmos_upp.py diff --git a/scripts/exglobal_atmos_vminmon.sh b/dev/scripts/exglobal_atmos_vminmon.sh similarity index 100% rename from scripts/exglobal_atmos_vminmon.sh rename to dev/scripts/exglobal_atmos_vminmon.sh diff --git a/scripts/exglobal_cleanup.sh b/dev/scripts/exglobal_cleanup.sh similarity index 100% rename from scripts/exglobal_cleanup.sh rename to dev/scripts/exglobal_cleanup.sh diff --git a/scripts/exglobal_diag.sh b/dev/scripts/exglobal_diag.sh similarity index 100% rename from scripts/exglobal_diag.sh rename to dev/scripts/exglobal_diag.sh diff --git a/scripts/exglobal_enkf_earc_tars.py b/dev/scripts/exglobal_enkf_earc_tars.py similarity index 100% rename from scripts/exglobal_enkf_earc_tars.py rename to dev/scripts/exglobal_enkf_earc_tars.py diff --git a/scripts/exglobal_enkf_earc_vrfy.py b/dev/scripts/exglobal_enkf_earc_vrfy.py similarity index 100% rename from scripts/exglobal_enkf_earc_vrfy.py rename to dev/scripts/exglobal_enkf_earc_vrfy.py diff --git a/scripts/exglobal_enkf_ecen.sh b/dev/scripts/exglobal_enkf_ecen.sh similarity index 100% rename from scripts/exglobal_enkf_ecen.sh rename to dev/scripts/exglobal_enkf_ecen.sh diff --git a/scripts/exglobal_enkf_ecen_fv3jedi.py b/dev/scripts/exglobal_enkf_ecen_fv3jedi.py similarity index 100% rename from scripts/exglobal_enkf_ecen_fv3jedi.py rename to dev/scripts/exglobal_enkf_ecen_fv3jedi.py diff --git a/scripts/exglobal_enkf_select_obs.sh b/dev/scripts/exglobal_enkf_select_obs.sh similarity index 100% rename from scripts/exglobal_enkf_select_obs.sh rename to dev/scripts/exglobal_enkf_select_obs.sh diff --git a/scripts/exglobal_enkf_sfc.sh b/dev/scripts/exglobal_enkf_sfc.sh similarity index 100% rename from scripts/exglobal_enkf_sfc.sh rename to dev/scripts/exglobal_enkf_sfc.sh diff --git a/scripts/exglobal_enkf_update.sh b/dev/scripts/exglobal_enkf_update.sh similarity index 100% rename from scripts/exglobal_enkf_update.sh rename to dev/scripts/exglobal_enkf_update.sh diff --git a/scripts/exglobal_extractvars.sh b/dev/scripts/exglobal_extractvars.sh similarity index 100% rename from scripts/exglobal_extractvars.sh rename to dev/scripts/exglobal_extractvars.sh diff --git a/scripts/exglobal_fetch.py b/dev/scripts/exglobal_fetch.py similarity index 100% rename from scripts/exglobal_fetch.py rename to dev/scripts/exglobal_fetch.py diff --git a/scripts/exglobal_forecast.py b/dev/scripts/exglobal_forecast.py similarity index 100% rename from scripts/exglobal_forecast.py rename to dev/scripts/exglobal_forecast.py diff --git a/scripts/exglobal_forecast.sh b/dev/scripts/exglobal_forecast.sh similarity index 100% rename from scripts/exglobal_forecast.sh rename to dev/scripts/exglobal_forecast.sh diff --git a/scripts/exglobal_globus_arch.py b/dev/scripts/exglobal_globus_arch.py similarity index 100% rename from scripts/exglobal_globus_arch.py rename to dev/scripts/exglobal_globus_arch.py diff --git a/scripts/exglobal_globus_earc.py b/dev/scripts/exglobal_globus_earc.py similarity index 100% rename from scripts/exglobal_globus_earc.py rename to dev/scripts/exglobal_globus_earc.py diff --git a/scripts/exglobal_marine_analysis_checkpoint.py b/dev/scripts/exglobal_marine_analysis_checkpoint.py similarity index 100% rename from scripts/exglobal_marine_analysis_checkpoint.py rename to dev/scripts/exglobal_marine_analysis_checkpoint.py diff --git a/scripts/exglobal_marine_analysis_ecen.py b/dev/scripts/exglobal_marine_analysis_ecen.py similarity index 100% rename from scripts/exglobal_marine_analysis_ecen.py rename to dev/scripts/exglobal_marine_analysis_ecen.py diff --git a/scripts/exglobal_marine_analysis_finalize.py b/dev/scripts/exglobal_marine_analysis_finalize.py similarity index 100% rename from scripts/exglobal_marine_analysis_finalize.py rename to dev/scripts/exglobal_marine_analysis_finalize.py diff --git a/scripts/exglobal_marine_analysis_initialize.py b/dev/scripts/exglobal_marine_analysis_initialize.py similarity index 100% rename from scripts/exglobal_marine_analysis_initialize.py rename to dev/scripts/exglobal_marine_analysis_initialize.py diff --git a/scripts/exglobal_marine_analysis_letkf.py b/dev/scripts/exglobal_marine_analysis_letkf.py similarity index 100% rename from scripts/exglobal_marine_analysis_letkf.py rename to dev/scripts/exglobal_marine_analysis_letkf.py diff --git a/scripts/exglobal_marine_analysis_variational.py b/dev/scripts/exglobal_marine_analysis_variational.py similarity index 100% rename from scripts/exglobal_marine_analysis_variational.py rename to dev/scripts/exglobal_marine_analysis_variational.py diff --git a/scripts/exglobal_marinebmat.py b/dev/scripts/exglobal_marinebmat.py similarity index 100% rename from scripts/exglobal_marinebmat.py rename to dev/scripts/exglobal_marinebmat.py diff --git a/scripts/exglobal_marinebmat_initialize.py b/dev/scripts/exglobal_marinebmat_initialize.py similarity index 100% rename from scripts/exglobal_marinebmat_initialize.py rename to dev/scripts/exglobal_marinebmat_initialize.py diff --git a/scripts/exglobal_oceanice_products.py b/dev/scripts/exglobal_oceanice_products.py similarity index 100% rename from scripts/exglobal_oceanice_products.py rename to dev/scripts/exglobal_oceanice_products.py diff --git a/scripts/exglobal_offline_atmos_analysis.py b/dev/scripts/exglobal_offline_atmos_analysis.py similarity index 100% rename from scripts/exglobal_offline_atmos_analysis.py rename to dev/scripts/exglobal_offline_atmos_analysis.py diff --git a/scripts/exglobal_prep_emissions.py b/dev/scripts/exglobal_prep_emissions.py similarity index 100% rename from scripts/exglobal_prep_emissions.py rename to dev/scripts/exglobal_prep_emissions.py diff --git a/scripts/exglobal_prep_sfc.sh b/dev/scripts/exglobal_prep_sfc.sh similarity index 100% rename from scripts/exglobal_prep_sfc.sh rename to dev/scripts/exglobal_prep_sfc.sh diff --git a/scripts/exglobal_snow_analysis.py b/dev/scripts/exglobal_snow_analysis.py similarity index 100% rename from scripts/exglobal_snow_analysis.py rename to dev/scripts/exglobal_snow_analysis.py diff --git a/scripts/exglobal_snowens_analysis.py b/dev/scripts/exglobal_snowens_analysis.py similarity index 100% rename from scripts/exglobal_snowens_analysis.py rename to dev/scripts/exglobal_snowens_analysis.py diff --git a/scripts/exglobal_stage_ic.py b/dev/scripts/exglobal_stage_ic.py similarity index 100% rename from scripts/exglobal_stage_ic.py rename to dev/scripts/exglobal_stage_ic.py diff --git a/dev/workflow/rocoto/gcafs_tasks.py b/dev/workflow/rocoto/gcafs_tasks.py index 4bd63a69f18..c6687399697 100644 --- a/dev/workflow/rocoto/gcafs_tasks.py +++ b/dev/workflow/rocoto/gcafs_tasks.py @@ -61,7 +61,7 @@ def fetch(self): 'resources': resources, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/fetch.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fetch.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -101,7 +101,7 @@ def stage_ic(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/stage_ic.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/stage_ic.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -144,7 +144,7 @@ def prep(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/prep.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/prep.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -172,7 +172,7 @@ def prep_emissions(self): 'resources': resources, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/prep_emissions.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/prep_emissions.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -208,7 +208,7 @@ def offlineanl(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': 'gcdas', - 'command': f'{self.HOMEgfs}/dev/jobs/offlineanl.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/offlineanl.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -234,7 +234,7 @@ def sfcanl(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': 'gcdas', - 'command': f'{self.HOMEgfs}/dev/jobs/sfcanl.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/sfcanl.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -270,7 +270,7 @@ def atmanlinit(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/atmanlinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmanlinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -294,7 +294,7 @@ def atmanlvar(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmanlvar.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmanlvar.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -318,7 +318,7 @@ def atmanlfv3inc(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmanlfv3inc.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmanlfv3inc.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -342,7 +342,7 @@ def atmanlfinal(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmanlfinal.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmanlfinal.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -366,7 +366,7 @@ def aeroanlgenb(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': 'gcdas_half,gcdas', - 'command': f'{self.HOMEgfs}/dev/jobs/aeroanlgenb.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aeroanlgenb.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -392,7 +392,7 @@ def aeroanlinit(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/aeroanlinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aeroanlinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -418,7 +418,7 @@ def aeroanlvar(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/aeroanlvar.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aeroanlvar.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -442,7 +442,7 @@ def aeroanlfinal(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/aeroanlfinal.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aeroanlfinal.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -504,7 +504,7 @@ def aerosol_init(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/aerosol_init.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aerosol_init.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -581,7 +581,7 @@ def _fcst_forecast_only(self): 'dependency': dependencies, 'envars': fcst_vars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -639,7 +639,7 @@ def _fcst_cycled(self): 'dependency': dependencies, 'envars': fcst_vars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -708,7 +708,7 @@ def efcs(self): 'dependency': dependencies, 'envars': efcsenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -764,7 +764,7 @@ def atmanlupp(self): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/upp.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/upp.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -793,7 +793,7 @@ def atmanlprod(self): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmos_products.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmos_products.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -842,7 +842,7 @@ def _upptask(self, upp_run="forecast", task_id="atmupp"): 'dependency': dependencies, 'envars': postenvars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/upp.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/upp.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -938,7 +938,7 @@ def _atmosoceaniceprod(self, component: str): 'dependency': dependencies, 'envars': postenvars, 'cycledef': cycledef, - 'command': f"{self.HOMEgfs}/dev/jobs/{config}.sh", + 'command': f"{self.HOMEgfs}/dev/job_cards/rocoto/{config}.sh", 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -994,7 +994,7 @@ def atmos_ensstat(self): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/atmos_ensstat.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmos_ensstat.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;'} @@ -1048,7 +1048,7 @@ def metp(self): 'dependency': dependencies, 'envars': metpenvars, 'cycledef': 'metp,last_gfs', - 'command': f'{self.HOMEgfs}/dev/jobs/metp.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/metp.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1079,7 +1079,7 @@ def anlstat(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/anlstat.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/anlstat.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1128,7 +1128,7 @@ def extractvars(self): 'dependency': dependencies, 'envars': extractvars_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/extractvars.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/extractvars.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1189,7 +1189,7 @@ def arch_vrfy(self): 'envars': self.envars, 'cycledef': self.run, 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/arch_vrfy.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' @@ -1242,7 +1242,7 @@ def arch_tars(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/arch_tars.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' @@ -1275,7 +1275,7 @@ def globus(self): 'envars': self.envars, 'cycledef': 'gefs', 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/globus_arch.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/globus_arch.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1318,7 +1318,7 @@ def cleanup(self): 'envars': self.envars, 'cycledef': self.run, 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/cleanup.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/cleanup.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' diff --git a/dev/workflow/rocoto/gefs_tasks.py b/dev/workflow/rocoto/gefs_tasks.py index 3cd9be020ea..6689675e998 100644 --- a/dev/workflow/rocoto/gefs_tasks.py +++ b/dev/workflow/rocoto/gefs_tasks.py @@ -16,7 +16,7 @@ def stage_ic(self): 'resources': resources, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/stage_ic.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/stage_ic.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -37,7 +37,7 @@ def gen_control_ic(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/gen_control_ic.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/gen_control_ic.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -54,7 +54,7 @@ def waveinit(self): 'resources': resources, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/waveinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/waveinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -71,7 +71,7 @@ def prep_emissions(self): 'resources': resources, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/prep_emissions.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/prep_emissions.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -112,7 +112,7 @@ def fcst(self): 'dependency': dependencies, 'envars': fcst_vars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -167,7 +167,7 @@ def efcs(self): 'dependency': dependencies, 'envars': efcsenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -263,7 +263,7 @@ def _atmosoceaniceprod(self, component: str): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/{config}.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/{config}.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;'} @@ -305,7 +305,7 @@ def postsnd(self): 'dependency': dependencies, 'envars': postsnd_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/postsnd.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/postsnd.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -355,7 +355,7 @@ def gempak(self): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/gempak.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/gempak.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -407,7 +407,7 @@ def atmos_ensstat(self): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/atmos_ensstat.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmos_ensstat.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;'} @@ -449,7 +449,7 @@ def awips(self): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/awips.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/awips.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;'} @@ -498,7 +498,7 @@ def wavepostsbs(self): 'dependency': dependencies, 'envars': wave_post_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/wavepostsbs.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wavepostsbs.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -556,7 +556,7 @@ def wave_stat(self): 'dependency': dependencies, 'envars': wave_stat_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/wave_stat.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wave_stat.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -585,7 +585,7 @@ def wave_stat_pnt(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/wave_stat_pnt.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wave_stat_pnt.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -624,7 +624,7 @@ def extractvars(self): 'dependency': dependencies, 'envars': extractvars_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/extractvars.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/extractvars.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -669,7 +669,7 @@ def arch_vrfy(self): 'envars': self.envars, 'cycledef': self.run, 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/arch_vrfy.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' @@ -708,7 +708,7 @@ def arch_tars(self): 'envars': self.envars, 'cycledef': self.run, 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/arch_tars.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' @@ -731,7 +731,7 @@ def globus(self): 'envars': self.envars, 'cycledef': self.run, 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/globus_arch.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/globus_arch.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -762,7 +762,7 @@ def cleanup(self): 'envars': self.envars, 'cycledef': self.run, 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/cleanup.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/cleanup.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' diff --git a/dev/workflow/rocoto/gfs_tasks.py b/dev/workflow/rocoto/gfs_tasks.py index cc0ac3c80a3..4f2c52bc4f1 100644 --- a/dev/workflow/rocoto/gfs_tasks.py +++ b/dev/workflow/rocoto/gfs_tasks.py @@ -26,7 +26,7 @@ def fetch(self): 'resources': resources, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/fetch.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fetch.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -55,7 +55,7 @@ def stage_ic(self): 'resources': resources, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/stage_ic.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/stage_ic.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;', @@ -84,7 +84,7 @@ def prep_sfc(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/prep_sfc.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/prep_sfc.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -148,7 +148,7 @@ def prep(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/prep.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/prep.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -178,7 +178,7 @@ def waveinit(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/waveinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/waveinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -202,7 +202,7 @@ def waveprep(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/waveprep.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/waveprep.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -254,7 +254,7 @@ def aerosol_init(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/aerosol_init.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aerosol_init.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -282,7 +282,7 @@ def anal(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/anal.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/anal.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -318,7 +318,7 @@ def sfcanl(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/sfcanl.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/sfcanl.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -350,7 +350,7 @@ def analcalc(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/analcalc.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/analcalc.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -374,7 +374,7 @@ def analdiag(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/analdiag.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/analdiag.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -410,7 +410,7 @@ def atmanlinit(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/atmanlinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmanlinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -434,7 +434,7 @@ def atmanlvar(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmanlvar.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmanlvar.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -458,7 +458,7 @@ def atmanlfv3inc(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmanlfv3inc.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmanlfv3inc.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -482,7 +482,7 @@ def atmanlfinal(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmanlfinal.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmanlfinal.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -506,7 +506,7 @@ def aeroanlgenb(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': 'gdas_half,gdas', - 'command': f'{self.HOMEgfs}/dev/jobs/aeroanlgenb.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aeroanlgenb.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -533,7 +533,7 @@ def aeroanlinit(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/aeroanlinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aeroanlinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -564,7 +564,7 @@ def aeroanlvar(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/aeroanlvar.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aeroanlvar.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -588,7 +588,7 @@ def aeroanlfinal(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/aeroanlfinal.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/aeroanlfinal.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -612,7 +612,7 @@ def snowanl(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/snowanl.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/snowanl.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -637,7 +637,7 @@ def esnowanl(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/esnowanl.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/esnowanl.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -670,7 +670,7 @@ def prepoceanobs(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/prepoceanobs.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/prepoceanobs.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -696,7 +696,7 @@ def marineanlletkf(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/marineanlletkf.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/marineanlletkf.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -726,7 +726,7 @@ def marinebmatinit(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/marinebmatinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/marinebmatinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -750,7 +750,7 @@ def marinebmat(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/marinebmat.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/marinebmat.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -778,7 +778,7 @@ def marineanlinit(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/marineanlinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/marineanlinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -802,7 +802,7 @@ def marineanlvar(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/marineanlvar.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/marineanlvar.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -827,7 +827,7 @@ def marineanlecen(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/marineanlecen.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/marineanlecen.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -862,7 +862,7 @@ def marineanlchkpt(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/marineanlchkpt.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/marineanlchkpt.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -886,7 +886,7 @@ def marineanlfinal(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/marineanlfinal.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/marineanlfinal.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -955,7 +955,7 @@ def _fcst_forecast_only(self): 'dependency': dependencies, 'envars': fcst_vars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1035,7 +1035,7 @@ def _fcst_cycled(self): 'dependency': dependencies, 'envars': fcst_vars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1084,7 +1084,7 @@ def atmanlupp(self): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/upp.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/upp.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1113,7 +1113,7 @@ def atmanlprod(self): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmos_products.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmos_products.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1162,7 +1162,7 @@ def _upptask(self, upp_run="forecast", task_id="atmupp"): 'dependency': dependencies, 'envars': postenvars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/upp.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/upp.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1250,7 +1250,7 @@ def _atmosoceaniceprod(self, component: str): 'dependency': dependencies, 'envars': postenvars, 'cycledef': cycledef, - 'command': f"{self.HOMEgfs}/dev/jobs/{config}.sh", + 'command': f"{self.HOMEgfs}/dev/job_cards/rocoto/{config}.sh", 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1295,7 +1295,7 @@ def wavepostsbs(self): 'dependency': dependencies, 'envars': wave_post_envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/wavepostsbs.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wavepostsbs.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1334,7 +1334,7 @@ def _wavepostbndpnt(self, name_in): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/{name_in}.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/{name_in}.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1357,7 +1357,7 @@ def wavepostpnt(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/wavepostpnt.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wavepostpnt.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1407,7 +1407,7 @@ def wavegempak(self): 'dependency': dependencies, 'envars': wave_post_envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/wavegempak.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wavegempak.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1436,7 +1436,7 @@ def waveawipsbulls(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/waveawipsbulls.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/waveawipsbulls.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1459,7 +1459,7 @@ def waveawipsgridded(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/waveawipsgridded.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/waveawipsgridded.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1482,7 +1482,7 @@ def postsnd(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/postsnd.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/postsnd.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1519,7 +1519,7 @@ def fbwind(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/fbwind.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fbwind.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1591,7 +1591,7 @@ def awips_20km_1p0deg(self): 'dependency': dependencies, 'envars': awipsenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/awips_20km_1p0deg.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/awips_20km_1p0deg.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1646,7 +1646,7 @@ def gempak(self): 'dependency': dependencies, 'envars': gempak_vars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/gempak.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/gempak.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1673,7 +1673,7 @@ def gempakmeta(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/gempakmeta.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/gempakmeta.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1696,7 +1696,7 @@ def gempakmetancdc(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/gempakmetancdc.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/gempakmetancdc.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1719,7 +1719,7 @@ def gempakncdcupapgif(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/gempakncdcupapgif.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/gempakncdcupapgif.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1747,7 +1747,7 @@ def gempakpgrb2spec(self): 'dependency': dependencies, 'envars': gempak_vars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/gempakgrb2spec.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/gempakgrb2spec.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1789,7 +1789,7 @@ def npoess_pgrb2_0p5deg(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/npoess.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/npoess.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1812,7 +1812,7 @@ def verfozn(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/verfozn.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/verfozn.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1835,7 +1835,7 @@ def verfrad(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/verfrad.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/verfrad.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1858,7 +1858,7 @@ def vminmon(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/vminmon.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/vminmon.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1895,7 +1895,7 @@ def anlstat(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/anlstat.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/anlstat.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1918,7 +1918,7 @@ def tracker(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/tracker.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/tracker.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1941,7 +1941,7 @@ def genesis(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/genesis.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/genesis.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1964,7 +1964,7 @@ def genesis_fsu(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/genesis_fsu.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/genesis_fsu.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -1987,7 +1987,7 @@ def fit2obs(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/fit2obs.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fit2obs.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2041,7 +2041,7 @@ def metp(self): 'dependency': dependencies, 'envars': metpenvars, 'cycledef': 'metp,last_gfs', - 'command': f'{self.HOMEgfs}/dev/jobs/metp.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/metp.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2109,7 +2109,7 @@ def arch_vrfy(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/arch_vrfy.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' @@ -2282,7 +2282,7 @@ def arch_tars(self): 'dependency': dependencies, 'envars': archenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/arch_tars.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' @@ -2311,7 +2311,7 @@ def globus_arch(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/globus_arch.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/globus_arch.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2344,7 +2344,7 @@ def globus_earc(self): 'dependency': dependencies, 'envars': earcenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/globus_earc.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/globus_earc.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2497,7 +2497,7 @@ def cleanup(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/cleanup.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/cleanup.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2523,7 +2523,7 @@ def eobs(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/eobs.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/eobs.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2546,7 +2546,7 @@ def ediag(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/ediag.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/ediag.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2569,7 +2569,7 @@ def eupd(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/eupd.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/eupd.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2595,7 +2595,7 @@ def atmensanlinit(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/atmensanlinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmensanlinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2621,7 +2621,7 @@ def atmensanlobs(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmensanlobs.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmensanlobs.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2647,7 +2647,7 @@ def atmensanlsol(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmensanlsol.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmensanlsol.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2673,7 +2673,7 @@ def atmensanlletkf(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmensanlletkf.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmensanlletkf.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2702,7 +2702,7 @@ def atmensanlfv3inc(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmensanlfv3inc.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmensanlfv3inc.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2726,7 +2726,7 @@ def atmensanlfinal(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/atmensanlfinal.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmensanlfinal.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2786,7 +2786,7 @@ def _get_ecengroups(): 'dependency': dependencies, 'envars': ecenenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/ecen.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/ecen.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2816,7 +2816,7 @@ def ecen_fv3jedi(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/ecen_fv3jedi.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/ecen_fv3jedi.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2846,7 +2846,7 @@ def analcalc_fv3jedi(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/analcalc_fv3jedi.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/analcalc_fv3jedi.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2879,7 +2879,7 @@ def esfc(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/esfc.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/esfc.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2924,7 +2924,7 @@ def efcs(self): 'dependency': dependencies, 'envars': efcsenvars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -2960,7 +2960,7 @@ def echgres(self): 'dependency': dependencies, 'envars': self.envars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/echgres.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/echgres.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -3019,7 +3019,7 @@ def _get_eposgroups(epos): 'dependency': dependencies, 'envars': eposenvars, 'cycledef': cycledef, - 'command': f'{self.HOMEgfs}/dev/jobs/epos.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/epos.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -3059,7 +3059,7 @@ def earc_vrfy(self): 'dependency': dependencies, 'envars': earcenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/earc_vrfy.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' @@ -3114,7 +3114,7 @@ def earc_tars(self): 'dependency': dependencies, 'envars': earcenvars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/earc_tars.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' diff --git a/dev/workflow/rocoto/sfs_tasks.py b/dev/workflow/rocoto/sfs_tasks.py index 2a8906e073e..42b25617f13 100644 --- a/dev/workflow/rocoto/sfs_tasks.py +++ b/dev/workflow/rocoto/sfs_tasks.py @@ -16,7 +16,7 @@ def stage_ic(self): 'resources': resources, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/stage_ic.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/stage_ic.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -33,7 +33,7 @@ def waveinit(self): 'resources': resources, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/waveinit.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/waveinit.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -50,7 +50,7 @@ def prep_emissions(self): 'resources': resources, 'envars': self.envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/prep_emissions.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/prep_emissions.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -88,7 +88,7 @@ def fcst(self): 'dependency': dependencies, 'envars': fcst_vars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -145,7 +145,7 @@ def efcs(self): 'dependency': dependencies, 'envars': efcsenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/fcst.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/fcst.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -241,7 +241,7 @@ def _atmosoceaniceprod(self, component: str): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/{config}.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/{config}.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;'} @@ -291,7 +291,7 @@ def atmos_ensstat(self): 'dependency': dependencies, 'envars': postenvars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/atmos_ensstat.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/atmos_ensstat.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;'} @@ -340,7 +340,7 @@ def wavepostsbs(self): 'dependency': dependencies, 'envars': wave_post_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/wavepostsbs.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wavepostsbs.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -379,7 +379,7 @@ def wavepostbndpnt(self): 'dependency': dependencies, 'envars': wave_post_bndpnt_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/wavepostbndpnt.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wavepostbndpnt.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -424,7 +424,7 @@ def wavepostbndpntbll(self): 'dependency': dependencies, 'envars': wave_post_bndpnt_bull_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/wavepostbndpntbll.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wavepostbndpntbll.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -463,7 +463,7 @@ def wavepostpnt(self): 'dependency': dependencies, 'envars': wave_post_pnt_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/wavepostpnt.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/wavepostpnt.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -508,7 +508,7 @@ def extractvars(self): 'dependency': dependencies, 'envars': extractvars_envars, 'cycledef': self.run, - 'command': f'{self.HOMEgfs}/dev/jobs/extractvars.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/extractvars.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -558,7 +558,7 @@ def arch_vrfy(self): 'envars': self.envars, 'cycledef': self.run, 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/arch_vrfy.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' @@ -602,7 +602,7 @@ def arch_tars(self): 'envars': self.envars, 'cycledef': self.run, 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/arch_tars.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/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;' @@ -676,7 +676,7 @@ def cleanup(self): 'envars': self.envars, 'cycledef': self.run, 'dependency': dependencies, - 'command': f'{self.HOMEgfs}/dev/jobs/cleanup.sh', + 'command': f'{self.HOMEgfs}/dev/job_cards/rocoto/cleanup.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' diff --git a/scripts b/scripts new file mode 120000 index 00000000000..f3685b2bf23 --- /dev/null +++ b/scripts @@ -0,0 +1 @@ +dev/scripts/ \ No newline at end of file From 9e1ae040ec18d72fe6b586a2537c179ffd364752 Mon Sep 17 00:00:00 2001 From: Taylor Roper Date: Mon, 8 Dec 2025 11:01:38 -0700 Subject: [PATCH 13/27] Generalize AWS config.resources for compute parition; add mem_node_max (#4303) # Description This PR generalizes the AWS GFS `config.resources.AWSPW` file for the default compute partition and specifies `mem_node_max` for this partition in the AWS machine block for GFS `config.resources`. Resolves #4213 --- dev/parm/config/gfs/config.resources | 3 +-- dev/parm/config/gfs/config.resources.AWSPW | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/dev/parm/config/gfs/config.resources b/dev/parm/config/gfs/config.resources index f6bd3ab387f..0a63608e6f1 100644 --- a/dev/parm/config/gfs/config.resources +++ b/dev/parm/config/gfs/config.resources @@ -69,8 +69,7 @@ case ${machine} in export PARTITION_BATCH="compute" npe_node_max=48 max_tasks_per_node=48 - # TODO Supply a max mem/node value for AWS - mem_node_max="" + mem_node_max="192GB" ;; "AZUREPW") export PARTITION_BATCH="compute" diff --git a/dev/parm/config/gfs/config.resources.AWSPW b/dev/parm/config/gfs/config.resources.AWSPW index c76f50bf0ce..45b19dd296f 100644 --- a/dev/parm/config/gfs/config.resources.AWSPW +++ b/dev/parm/config/gfs/config.resources.AWSPW @@ -68,7 +68,7 @@ case ${step} in "esfc") export is_exclusive="True" - export tasks_per_node=40 + export tasks_per_node=${max_tasks_per_node} ;; "upp") From cf7039af99298333368ad6f33bb94b0e699d9f66 Mon Sep 17 00:00:00 2001 From: David Huber <69919478+DavidHuber-NOAA@users.noreply.github.com> Date: Tue, 9 Dec 2025 16:47:05 +0000 Subject: [PATCH 14/27] Fix METplus dependency matrix (#4297) # Description This fixes the METplus dependencies by checking backwards for up to (`GFS_INTERVAL / assim_freq`) cycles for completed `gfs_arch_vrfy` jobs. It also does a separate check for the last cycle. Resolves #4281 # Type of change - [x] Bug fix (fixes something broken) - [ ] New feature (adds functionality) - [ ] Maintenance (code refactor, clean-up, new CI test, etc.) # Change characteristics - Is this a breaking change (a change in existing functionality)? NO - Does this change require a documentation update? NO - Does this change require an update to any of the following submodules? NO # How has this been tested? Generated XMLs for several different cases. # Checklist - [x] Any dependent changes have been merged and published - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] My changes generate no new warnings - [ ] New and existing tests pass with my changes - [ ] This change is covered by an existing CI test or a new one has been added --- .gitignore | 2 +- dev/workflow/rocoto/gfs_cycled_xml.py | 1 - dev/workflow/rocoto/gfs_tasks.py | 54 +++++++++++++++++++-------- dev/workflow/rocoto/tasks.py | 2 +- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index ac94c46ff30..f83211291ef 100644 --- a/.gitignore +++ b/.gitignore @@ -150,7 +150,7 @@ sorc/ocnicepost.fd #------------------------------ # jobs symlinks # scripts symlinks -scripts/exglobal_prep_ocean_obs.py +dev/scripts/exglobal_prep_ocean_obs.py # ush symlinks ush/bufr2ioda_insitu_profile_argo.py ush/bufr2ioda_insitu_profile_bathy.py diff --git a/dev/workflow/rocoto/gfs_cycled_xml.py b/dev/workflow/rocoto/gfs_cycled_xml.py index 6b4542251de..f3792ad43eb 100644 --- a/dev/workflow/rocoto/gfs_cycled_xml.py +++ b/dev/workflow/rocoto/gfs_cycled_xml.py @@ -100,7 +100,6 @@ def get_cycledefs(self): interval_metp_str = interval_gfs_str strings.append(f'\t{sdate_metp_str} {edate_metp_str} {interval_metp_str}') - strings.append(f'\t{edate_gfs_str} {edate_gfs_str} 24:00:00') strings.append('') strings.append('') diff --git a/dev/workflow/rocoto/gfs_tasks.py b/dev/workflow/rocoto/gfs_tasks.py index 4f2c52bc4f1..f3e7c3d3e69 100644 --- a/dev/workflow/rocoto/gfs_tasks.py +++ b/dev/workflow/rocoto/gfs_tasks.py @@ -2001,24 +2001,48 @@ def metp(self): deps = [] 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 = [] + interval_gfs = self._base.get('interval_gfs') + assim_freq = self._base['assim_freq'] + + if interval_gfs < to_timedelta("24H"): + n_lookback = int(interval_gfs // to_timedelta(f"{assim_freq}H")) - 1 + # Check if the previous up to `n_lookback` arch_vrfy tasks have completed + # For interval=6, there are no lookbacks + # For interval=12, check lookback=1 + # For interval=18, check lookback=1,2 + # Only lookback if arch_vrfy is not valid for this cycle + if n_lookback > 0: dep_dict = {'type': 'taskvalid', 'name': f'{self.run}_arch_vrfy', 'condition': 'not'} + deps2 = [] deps2.append(rocoto.add_dependency(dep_dict)) - for lookback2 in range(1, lookback): - offset = timedelta_to_HMS(-to_timedelta(f'{6 * lookback2}H')) - dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': offset} - deps2.append(rocoto.add_dependency(dep_dict)) - - edate_gfs = self._base['EDATE'] - edate_metp = edate_gfs.replace(hour=18) - edate_metp_diff = edate_metp - edate_gfs - offset = timedelta_to_HMS(-to_timedelta(f'{edate_metp_diff}H')) - dep_dict = {'type': 'task', 'name': f'{self.run}_arch_vrfy', 'offset': offset} + deps3 = [] + for lookback in range(n_lookback): + offset = timedelta_to_HMS(-to_timedelta(f'{assim_freq * (lookback+1)}H')) + dep_dict = {'type': 'task', 'name': f'{self.run}_arch_vrfy', 'offset': offset} + deps3.append(rocoto.add_dependency(dep_dict)) + + deps2.append(rocoto.create_dependency(dep=deps3, dep_condition='or')) + deps.append(rocoto.create_dependency(dep=deps2, dep_condition='and')) + + # Lastly, check that the last arch_vrfy job is done + # This only happens if the metp cycle is not aligned with the last_gfs cycle + sdate_gfs = self._base.get('SDATE_GFS') + edate = self._base.get('EDATE') + edate_metp = self._base.get('EDATE').replace(hour=(24 - assim_freq)) + n_intervals = int((edate - sdate_gfs) // interval_gfs) + edate_gfs = sdate_gfs + n_intervals * interval_gfs + metp_gfs_offset = edate_metp - edate_gfs + if metp_gfs_offset > to_timedelta("0H") and metp_gfs_offset < to_timedelta("24H"): + deps2 = [] + dep_dict = {'type': 'taskvalid', 'name': f'{self.run}_arch_vrfy', 'condition': 'not'} + deps2.append(rocoto.add_dependency(dep_dict)) + dep_dict = {'type': 'task', 'name': f'{self.run}_arch_vrfy', 'offset': timedelta_to_HMS(-metp_gfs_offset)} + deps2.append(rocoto.add_dependency(dep_dict)) + for i in range(1, int((metp_gfs_offset.seconds / 3600) // assim_freq)): + dep_dict = {'type': 'cycleexist', 'offset': timedelta_to_HMS(-to_timedelta(f'{assim_freq * i}H')), 'condition': 'not'} deps2.append(rocoto.add_dependency(dep_dict)) - deps.append(rocoto.create_dependency(dep_condition='and', dep=deps2)) + + deps.append(rocoto.create_dependency(dep=deps2, dep_condition='and')) dependencies = rocoto.create_dependency(dep_condition='or', dep=deps) diff --git a/dev/workflow/rocoto/tasks.py b/dev/workflow/rocoto/tasks.py index 5a892af4d21..b5d48e994bb 100644 --- a/dev/workflow/rocoto/tasks.py +++ b/dev/workflow/rocoto/tasks.py @@ -415,7 +415,7 @@ def get_resource(self, task_name): service_task = task_name in Tasks.SERVICE_TASKS if task_name not in Tasks.VALID_TASKS: - raise KeyError(f"ERROR {task_name} is not a valid tasks!") + raise KeyError(f"ERROR {task_name} is not a valid task!") # Combine the task configuration with the system configuration if service_task: From ebb5bae9b36b6b4ff134b9ab61780eff6fbe9877 Mon Sep 17 00:00:00 2001 From: Jessica Meixner Date: Tue, 9 Dec 2025 18:40:18 +0000 Subject: [PATCH 15/27] point to release/gfs.v17 for gdas app --- sorc/gdas.cd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorc/gdas.cd b/sorc/gdas.cd index 58da1e3bcc8..887b7efb9aa 160000 --- a/sorc/gdas.cd +++ b/sorc/gdas.cd @@ -1 +1 @@ -Subproject commit 58da1e3bcc863fddaf32319efe6b409565dd568b +Subproject commit 887b7efb9aaaa26cf4ad0eead0b4b73306df64b3 From b66a420ba07f72d10acd83f809d625c57cf958d3 Mon Sep 17 00:00:00 2001 From: David Huber <69919478+DavidHuber-NOAA@users.noreply.github.com> Date: Wed, 10 Dec 2025 12:58:43 +0000 Subject: [PATCH 16/27] Reduce HPSS jobs' memory to 3GB on WCOSS2 (#4307) # Description This reduces the memory request for WCOSS2 HPSS jobs to 3GB to (hopefully) speed up queue time. Resolves #4288 # Type of change - [ ] Bug fix (fixes something broken) - [ ] New feature (adds functionality) - [x] Maintenance (code refactor, clean-up, new CI test, etc.) # Change characteristics - Is this change expected to change outputs (e.g. value changes to existing outputs, new files stored in COM, files removed from COM, filename changes, additions/subtractions to archives)? NO - Is this a breaking change (a change in existing functionality)? NO - Does this change require a documentation update? NO - Does this change require an update to any of the following submodules? NO # How has this been tested? Full suite of tests on WCOSS2 has started. # Checklist - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings - [ ] New and existing tests pass with my changes - [x] This change is covered by an existing CI test or a new one has been added --- dev/parm/config/gfs/config.resources.WCOSS2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/parm/config/gfs/config.resources.WCOSS2 b/dev/parm/config/gfs/config.resources.WCOSS2 index 2c7161e8d87..042317ac3bc 100644 --- a/dev/parm/config/gfs/config.resources.WCOSS2 +++ b/dev/parm/config/gfs/config.resources.WCOSS2 @@ -35,7 +35,7 @@ case ${step} in ;; "arch_vrfy" | "arch_tars" | "earc_vrfy" | "earc_tars" | "getic") - declare -x "memory"="10GB" + declare -x "memory"="3GB" ;; "eupd") From f5f96dc7381b12707364c16d73d51517b448c908 Mon Sep 17 00:00:00 2001 From: David Huber <69919478+DavidHuber-NOAA@users.noreply.github.com> Date: Wed, 10 Dec 2025 13:07:56 +0000 Subject: [PATCH 17/27] Refactor cleanup task and add checks for gempak files (#4258) This adds more specific checks for gempak files and makes an attempt at making the cleanup job less disk-intensive by running a single `find -f` command. --- dev/ci/cases/pr/C48_S2SW.yaml | 3 + dev/ci/cases/yamls/gfs_extended_ci.yaml | 1 + dev/jobs/JGFS_ATMOS_POSTSND | 1 + dev/parm/config/gfs/config.cleanup | 36 ++++++--- dev/parm/config/gfs/config.resources | 2 +- dev/scripts/exgfs_atmos_postsnd.sh | 17 ++-- dev/scripts/exglobal_cleanup.sh | 101 ++++++++++++++++++------ dev/workflow/rocoto/gefs_tasks.py | 2 +- dev/workflow/rocoto/sfs_tasks.py | 2 +- modulefiles/gw_setup.hera.lua | 1 - modulefiles/gw_setup.hercules.lua | 1 - modulefiles/gw_setup.orion.lua | 1 - modulefiles/gw_setup.ursa.lua | 1 - parm/archive/gfs_downstream.yaml.j2 | 2 +- ush/gfs_bfr2gpk.sh | 19 +++-- ush/gfs_sndp.sh | 11 ++- ush/preamble.sh | 5 +- 17 files changed, 139 insertions(+), 67 deletions(-) diff --git a/dev/ci/cases/pr/C48_S2SW.yaml b/dev/ci/cases/pr/C48_S2SW.yaml index 59148444792..cd7e5875903 100644 --- a/dev/ci/cases/pr/C48_S2SW.yaml +++ b/dev/ci/cases/pr/C48_S2SW.yaml @@ -11,6 +11,9 @@ experiment: edate: 2021032312 yaml: {{ HOMEgfs }}/dev/ci/cases/yamls/gfs_defaults_ci.yaml +skip_ci_on_hosts: + - wcoss2 + workflow: engine: rocoto rocoto: diff --git a/dev/ci/cases/yamls/gfs_extended_ci.yaml b/dev/ci/cases/yamls/gfs_extended_ci.yaml index bbf8155ac3f..b45ac7d935a 100644 --- a/dev/ci/cases/yamls/gfs_extended_ci.yaml +++ b/dev/ci/cases/yamls/gfs_extended_ci.yaml @@ -13,3 +13,4 @@ base: FHMAX_GFS: 384 FHMAX_HF_GFS: 120 DO_TEST_MODE: "NO" + DO_ARCHCOM: "YES" diff --git a/dev/jobs/JGFS_ATMOS_POSTSND b/dev/jobs/JGFS_ATMOS_POSTSND index d2d7491f9fb..10f6248081e 100755 --- a/dev/jobs/JGFS_ATMOS_POSTSND +++ b/dev/jobs/JGFS_ATMOS_POSTSND @@ -12,6 +12,7 @@ source "${HOMEgfs}/ush/jjob_header.sh" -e "postsnd" -c "base postsnd" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL \ + COMIN_ATMOS_BUFR:COM_ATMOS_BUFR_TMPL \ COMOUT_ATMOS_BUFR:COM_ATMOS_BUFR_TMPL \ COMOUT_ATMOS_WMO:COM_ATMOS_WMO_TMPL \ COMOUT_ATMOS_GEMPAK:COM_ATMOS_GEMPAK_TMPL diff --git a/dev/parm/config/gfs/config.cleanup b/dev/parm/config/gfs/config.cleanup index 543d624caf2..a4af66b493d 100644 --- a/dev/parm/config/gfs/config.cleanup +++ b/dev/parm/config/gfs/config.cleanup @@ -9,22 +9,40 @@ source "${EXPDIR}/config.resources" cleanup export CLEANUP_COM="YES" # NO=retain ROTDIR. YES default in cleanup.sh #--starting and ending hours of previous cycles to be removed from rotating directory -export RMOLDSTD=144 -export RMOLDEND=24 +# RUN-based cleanup variables +# Keep all files newer than SELECTIVE_CLEANUP_MIN hours +# Selectively remove files between SELECTIVE_CLEANUP_MAX and SELECTIVE_CLEANUP_MIN hours old, based on exclude_string +# Remove all GEMPAK files older than GEMPAK_CLEANUP hours if DO_GEMPAK is set to YES and only for RUN==gfs +# Remove **all** files and directories older than max(SELECTIVE_CLEANUP_MAX, GEMPAK_CLEANUP, RTOFS_CLEANUP) -if [[ "${DO_GEMPAK}" == "YES" && "${RUN}" == "gfs" ]]; then - export RMOLDSTD=346 - export RMOLDEND=222 +# RTOFS-specific variables (runs every RUN) +# Remove all RTOFS files older than RTOFS_CLEANUP hours + +export SELECTIVE_CLEANUP_MAX=144 +export SELECTIVE_CLEANUP_MIN=24 +export GEMPAK_CLEANUP=240 +export RTOFS_CLEANUP=24 +if [[ ${SELECTIVE_CLEANUP_MIN} -gt ${SELECTIVE_CLEANUP_MAX} ]]; then + echo "FATAL ERROR: Invalid selective cleanup times: " + echo " SELECTIVE_CLEANUP_MIN=${SELECTIVE_CLEANUP_MIN} > SELECTIVE_CLEANUP_MAX=${SELECTIVE_CLEANUP_MAX}" + exit 1 +fi + +# GEMPAK_CLEANUP must not be less than SELECTIVE_CLEANUP_MIN, which acts as the starting point for cleanup +if [[ "${DO_GEMPAK}" == "YES" && ${GEMPAK_CLEANUP} -lt ${SELECTIVE_CLEANUP_MIN} ]]; then + echo "FATAL ERROR: Invalid GEMPAK cleanup time: " + echo " GEMPAK_CLEANUP=${GEMPAK_CLEANUP} < SELECTIVE_CLEANUP_MIN=${SELECTIVE_CLEANUP_MIN}" + exit 2 fi # Specify the list of files to exclude from the first stage of cleanup # Because arrays cannot be exported, list is a single string of comma- # separated values. This string is split to form an array at runtime. +export selective_exclude_string="" case ${RUN} in - gdas | gfs) exclude_string="*prepbufr*, *cnvstat.tar*, *analysis.atm.a*.nc" ;; - enkf*) exclude_string="*f006.ens*" ;; - *) exclude_string="" ;; + gdas | gfs) selective_exclude_string+="*prepbufr*, *cnvstat.tar*, *analysis.atm.a*.nc" ;; + enkf*) selective_exclude_string+="*f006.ens*" ;; + *) selective_exclude_string="" ;; esac -export exclude_string echo "END: config.cleanup" diff --git a/dev/parm/config/gfs/config.resources b/dev/parm/config/gfs/config.resources index 0a63608e6f1..f2eb37465d0 100644 --- a/dev/parm/config/gfs/config.resources +++ b/dev/parm/config/gfs/config.resources @@ -1378,7 +1378,7 @@ case ${step} in elif [[ "${RUN}" = *gfs ]]; then ntasks=28 tasks_per_node=28 - memory="4GB" + memory="6GB" fi ;; diff --git a/dev/scripts/exgfs_atmos_postsnd.sh b/dev/scripts/exgfs_atmos_postsnd.sh index 53b84caa68c..725acf5548b 100755 --- a/dev/scripts/exgfs_atmos_postsnd.sh +++ b/dev/scripts/exgfs_atmos_postsnd.sh @@ -149,20 +149,21 @@ else fi ${runscript} "${fhr}" "${fhr_p}" "${FINT}" "${F00FLAG}" "${DATA}" -############################################################## -# Tar and gzip the individual bufr files and send them to /com -############################################################## -cd "${COMOUT_ATMOS_BUFR}" || exit 2 -# shellcheck disable=SC2312 -tar -cf - . | /usr/bin/gzip > "${RUN}.${cycle}.bufrsnd.tar.gz" -cd "${DATA}" || exit 2 +############################################ +# Tar and gzip the bufr files created so far +############################################ +find "${COMIN_ATMOS_BUFR}" -maxdepth 1 -type f -name "bufr.*" -printf '%f\n' > "${DATA}/all_bufr_files.txt" + +tar -czf "${RUN}.${cycle}.soundings.tar.gz" -C "${COMIN_ATMOS_BUFR}" -T "${DATA}/all_bufr_files.txt" + +cpfs "${RUN}.${cycle}.soundings.tar.gz" "${COMOUT_ATMOS_BUFR}/" ######################################## # Send the single tar file to OSO ######################################## if [[ "${SENDDBN}" == "YES" ]]; then "${DBNROOT}/bin/dbn_alert" MODEL GFS_BUFRSND_TAR "${job}" \ - "${COMOUT_ATMOS_BUFR}/${RUN}.${cycle}.bufrsnd.tar.gz" + "${COMOUT_ATMOS_BUFR}/${RUN}.${cycle}.soundings.tar.gz" fi ######################################## diff --git a/dev/scripts/exglobal_cleanup.sh b/dev/scripts/exglobal_cleanup.sh index ab38e4e6e9f..1e5d51f8c78 100755 --- a/dev/scripts/exglobal_cleanup.sh +++ b/dev/scripts/exglobal_cleanup.sh @@ -6,7 +6,9 @@ echo "Begin Cleanup ${DATAROOT}!" # Remove DATAoutput from the forecast model run # TODO: Handle this better DATAfcst="${DATAROOT}/${RUN}fcst.${PDY:-}${cyc}" -if [[ -d "${DATAfcst}" ]]; then rm -rf "${DATAfcst}"; fi +if [[ -d "${DATAfcst}" ]]; then + rm -rf "${DATAfcst}" +fi #DATAefcs="${DATAROOT}/${RUN}efcs???${PDY:-}${cyc}" rm -rf "${DATAROOT}/${RUN}efcs"*"${PDY:-}${cyc}" ############################################################### @@ -15,15 +17,48 @@ if [[ "${CLEANUP_COM:-YES}" == NO ]]; then exit 0 fi +SELECTIVE_CLEANUP_MIN=${SELECTIVE_CLEANUP_MIN:-24} +SELECTIVE_CLEANUP_MAX=${SELECTIVE_CLEANUP_MAX:-120} +RTOFS_CLEANUP=${RTOFS_CLEANUP:-24} +GEMPAK_CLEANUP=${GEMPAK_CLEANUP:-240} ############################################################### # Clean up previous cycles; various depths # Step back every assim_freq hours and remove old rotating directories # for successful cycles (defaults from 24h to 120h). # Retain files needed by Fit2Obs -last_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RMOLDEND:-24} hours") -first_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RMOLDSTD:-120} hours") -last_rtofs=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RMOLDRTOFS:-48} hours") +first_selective_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${SELECTIVE_CLEANUP_MAX} hours") +last_selective_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${SELECTIVE_CLEANUP_MIN} hours") +gempak_cutoff_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${GEMPAK_CLEANUP} hours") +# Selective exclude list +selective_exclude_string="${selective_exclude_string:-}" +# Gempak exclude list +gempak_exclude_string+=", gfs_1p00_*" + +# RTOFS is cleaned separately (for all RUNs) +rtofs_cutoff_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RTOFS_CLEANUP} hours") + +# Find the first and last date among all cleanup targets +max_cleanup_max="${SELECTIVE_CLEANUP_MAX:-120}" +max_list="${SELECTIVE_CLEANUP_MAX}" +if [[ "${RUN}" == "gfs" && "${DO_GEMPAK}" == "YES" ]]; then + max_list+=" ${GEMPAK_CLEANUP}" +fi + +for cleanup_max in ${max_list}; do + if [[ ${cleanup_max} -gt ${max_cleanup_max} ]]; then + max_cleanup_max=${cleanup_max} + fi +done + +# Start 4 cycles before the earliest exclusion target so we actually remove older files +max_cleanup_max=$((max_cleanup_max + 4 * assim_freq)) +first_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${max_cleanup_max} hours") + +# Cleanup starts on SELECTIVE_CLEANUP_MIN +last_date=${last_selective_date} + +# Declare remove_files(), which will be called in a loop to selectively remove files function remove_files() { local directory=$1 shift @@ -33,51 +68,62 @@ function remove_files() { fi local find_exclude_string="" for exclude in "$@"; do - find_exclude_string+="${find_exclude_string} -name ${exclude} -or" + if [[ -n "${exclude}" ]]; then + find_exclude_string+=" -name ${exclude} -or" + fi done # Chop off any trailing or find_exclude_string="${find_exclude_string[*]/%-or/}" - # Remove all regular files that do not match - # shellcheck disable=SC2086 - if [[ -n "${find_exclude_string}" ]]; then - # String is non-empty → use exclusion - find "${directory}" -type f -not \( ${find_exclude_string} \) -ignore_readdir_race -delete - else - # String is empty → no exclusion - find "${directory}" -type f -ignore_readdir_race -delete - fi - - # Remove all symlinks that do not match + # Remove all regular files and symlinks that do not match # shellcheck disable=SC2086 if [[ -n "${find_exclude_string}" ]]; then # String is non-empty → use exclusion - find "${directory}" -type l -not \( ${find_exclude_string} \) -ignore_readdir_race -delete + find "${directory}" \( -type f -o -type l \) -not \( ${find_exclude_string} \) -ignore_readdir_race -delete else # String is empty → no exclusion - find "${directory}" -type l -ignore_readdir_race -delete + find "${directory}" \( -type f -o -type l \) -ignore_readdir_race -delete fi # Remove any empty directories find "${directory}" -type d -empty -delete } +# Now start removing old COM files/directories for ((current_date = first_date; current_date <= last_date; \ current_date = $(date --utc +%Y%m%d%H -d "${current_date:0:8} ${current_date:8:2} +${assim_freq} hours"))); do current_PDY="${current_date:0:8}" current_cyc="${current_date:8:2}" - rtofs_dir="${ROTDIR}/rtofs.${current_PDY}" rocotolog="${EXPDIR}/logs/${current_date}.log" + + # Build the exclude list based on the 'current_date' + exclude_string="" + if [[ ${current_date} -ge ${first_selective_date} && ${current_date} -le ${last_selective_date} ]]; then + exclude_string+="${selective_exclude_string}" + fi + + # Extend the exclude list for gempak files if needed + if [[ "${RUN}" == "gfs" && ${current_date} -ge ${gempak_cutoff_date} && "${DO_GEMPAK}" == "YES" ]]; then + # Provide the gempak exclude pattern(s) + exclude_string+="${gempak_exclude_string}" + fi + + # Check if the cycle completed successfully by looking at the rocoto log if [[ -f "${rocotolog}" ]]; then # TODO: This needs to be revamped to not look at the rocoto log. - # shellcheck disable=SC2312 - if [[ $(tail -n 1 "${rocotolog}") =~ "This cycle is complete: Success" ]]; then + tail_log=$(tail -n 1 "${rocotolog}") || true + # Test if the last line of rocotolog indicates success + if [[ ${tail_log} =~ "This cycle is complete: Success" ]]; then YMD="${current_PDY}" HH="${current_cyc}" declare_from_tmpl \ COMOUT_TOP:COM_TOP_TMPL if [[ -d "${COMOUT_TOP}" ]]; then - IFS=", " read -r -a exclude_list <<< "${exclude_string:-}" + IFS=", " read -r -a exclude_list <<< "${exclude_string}" remove_files "${COMOUT_TOP}" "${exclude_list[@]:-}" fi - if [[ -d "${rtofs_dir}" ]] && ((current_date < last_rtofs)); then rm -rf "${rtofs_dir}"; fi + # Remove all rtofs directories in each RUN older than last_rtofs_date + rtofs_dir="${ROTDIR}/rtofs.${current_PDY}" + if [[ -d "${rtofs_dir}" && ${current_date} -lt ${rtofs_cutoff_date} ]]; then + rm -rf "${rtofs_dir}" + fi fi fi done @@ -107,14 +153,17 @@ if [[ "${RUN}" == "gfs" ]]; then done fi -# Remove $RUN.$rPDY for the older of GDATE or RDATE -GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RMOLDSTD:-120} hours") +# Remove $RUN.$rPDY for the older of GDATE or RDATE if it is empty +GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${max_cleanup_max} hours") RDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${FHMAX_GFS} hours") if ((GDATE < RDATE)); then RDATE=${GDATE} fi + deletion_target="${ROTDIR}/${RUN}.${RDATE:0:8}" -if [[ -d ${deletion_target} ]]; then rm -rf "${deletion_target}"; fi +if [[ -d "${deletion_target}" ]]; then + find "${deletion_target}" -maxdepth 0 -type d -empty -delete +fi # sync and wait to avoid filesystem synchronization issues sync && sleep 1 diff --git a/dev/workflow/rocoto/gefs_tasks.py b/dev/workflow/rocoto/gefs_tasks.py index 6689675e998..dcede32b627 100644 --- a/dev/workflow/rocoto/gefs_tasks.py +++ b/dev/workflow/rocoto/gefs_tasks.py @@ -212,7 +212,7 @@ def _atmosoceaniceprod(self, component: str): fhout_ice_gfs = self._configs['base']['FHOUT_ICE_GFS'] products_dict = {'atmos': {'config': 'atmos_products', 'history_path_tmpl': 'COM_ATMOS_MASTER_TMPL', - 'history_file_tmpl': f'{self.run}.t@Hz.master.grb2f#fhr3_last#'}, + 'history_file_tmpl': f'{self.run}.t@Hz.master.f#fhr3_last#.grib2'}, 'ocean': {'config': 'oceanice_products', 'history_path_tmpl': 'COM_OCEAN_HISTORY_TMPL', 'history_file_tmpl': f'{self.run}.ocean.t@Hz.{fhout_ocn_gfs}hr_avg.f#fhr3_next#.nc'}, diff --git a/dev/workflow/rocoto/sfs_tasks.py b/dev/workflow/rocoto/sfs_tasks.py index 42b25617f13..0d29390e945 100644 --- a/dev/workflow/rocoto/sfs_tasks.py +++ b/dev/workflow/rocoto/sfs_tasks.py @@ -190,7 +190,7 @@ def _atmosoceaniceprod(self, component: str): fhout_ice_gfs = self._configs['base']['FHOUT_ICE_GFS'] products_dict = {'atmos': {'config': 'atmos_products', 'history_path_tmpl': 'COM_ATMOS_MASTER_TMPL', - 'history_file_tmpl': f'{self.run}.t@Hz.master.grb2f#fhr3_last#'}, + 'history_file_tmpl': f'{self.run}.t@Hz.master.f#fhr3_last#.grib2'}, 'ocean': {'config': 'oceanice_products', 'history_path_tmpl': 'COM_OCEAN_HISTORY_TMPL', 'history_file_tmpl': f'{self.run}.ocean.t@Hz.{fhout_ocn_gfs}hr_avg.f#fhr3_next#.nc'}, diff --git a/modulefiles/gw_setup.hera.lua b/modulefiles/gw_setup.hera.lua index 7e7debc259a..56f8c50e665 100644 --- a/modulefiles/gw_setup.hera.lua +++ b/modulefiles/gw_setup.hera.lua @@ -16,6 +16,5 @@ load(pathJoin("python", python_ver)) load("py-jinja2") load("py-pyyaml") load("py-numpy") -load("gh") whatis("Description: GFS run setup environment") diff --git a/modulefiles/gw_setup.hercules.lua b/modulefiles/gw_setup.hercules.lua index 8e9870f5b0a..fdc3a02c9d5 100644 --- a/modulefiles/gw_setup.hercules.lua +++ b/modulefiles/gw_setup.hercules.lua @@ -17,6 +17,5 @@ load("py-jinja2") load("py-pyyaml") load("py-numpy") try_load("globus-cli") -load("gh") whatis("Description: GFS run setup environment") diff --git a/modulefiles/gw_setup.orion.lua b/modulefiles/gw_setup.orion.lua index c387a366f0f..1580cc57369 100644 --- a/modulefiles/gw_setup.orion.lua +++ b/modulefiles/gw_setup.orion.lua @@ -19,6 +19,5 @@ load("py-pyyaml") load("py-numpy") load(pathJoin("cmake", cmake_ver)) try_load("globus-cli") -load("gh") whatis("Description: GFS run setup environment") diff --git a/modulefiles/gw_setup.ursa.lua b/modulefiles/gw_setup.ursa.lua index a38c5f53e77..c7706764ff7 100644 --- a/modulefiles/gw_setup.ursa.lua +++ b/modulefiles/gw_setup.ursa.lua @@ -16,6 +16,5 @@ load(pathJoin("cmake", cmake_ver)) load("py-jinja2") load("py-pyyaml") load("py-numpy") -load("gh") whatis("Description: GFS run setup environment") diff --git a/parm/archive/gfs_downstream.yaml.j2 b/parm/archive/gfs_downstream.yaml.j2 index 040292b7dd8..6bc663cb5b4 100644 --- a/parm/archive/gfs_downstream.yaml.j2 +++ b/parm/archive/gfs_downstream.yaml.j2 @@ -3,7 +3,7 @@ gfs_downstream: name: "GFS_DOWNSTREAM" target: "{{ ATARDIR }}/{{ cycle_YMDH }}/gfs_downstream.tar" required: - {% if DO_GEMPAK %} + {% if DO_GEMPAK and DO_BUFRSND %} - "{{ COMIN_ATMOS_GEMPAK | relpath(ROTDIR) }}/gfs_{{ cycle_YMDH }}.sfc.bufr" - "{{ COMIN_ATMOS_GEMPAK | relpath(ROTDIR) }}/gfs_{{ cycle_YMDH }}.soundings.bufr" {% endif %} diff --git a/ush/gfs_bfr2gpk.sh b/ush/gfs_bfr2gpk.sh index 0ff2a400539..1e0ea9224aa 100755 --- a/ush/gfs_bfr2gpk.sh +++ b/ush/gfs_bfr2gpk.sh @@ -30,10 +30,13 @@ date cat "${COMOUT_ATMOS_BUFR}/bufr."*".${PDY}${cyc}" > bufr.combined date +snd=${outfilbase}.snd +sfc=${outfilbase}.sfc + namsnd << EOF > /dev/null SNBUFR = bufr.combined -SNOUTF = ${outfilbase}.snd -SFOUTF = ${outfilbase}.sfc +SNOUTF = ${snd} +SFOUTF = ${sfc} SNPRMF = sngfs.prm SFPRMF = sfgfs.prm TIMSTN = 170/2150 @@ -46,13 +49,13 @@ date /bin/rm ./*.nts -snd=${outfilbase}.snd -sfc=${outfilbase}.sfc -cpfs "${snd}" "${COMOUT_ATMOS_GEMPAK}/${snd}" -cpfs "${sfc}" "${COMOUT_ATMOS_GEMPAK}/${sfc}" +snd_out=${outfilbase}.soundings.bufr +sfc_out=${outfilbase}.sfc.bufr +cpfs "${snd}" "${COMOUT_ATMOS_GEMPAK}/${snd_out}" +cpfs "${sfc}" "${COMOUT_ATMOS_GEMPAK}/${sfc_out}" if [[ ${SENDDBN} == "YES" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL GFS_PTYP_SFC "${job}" "${COMOUT_ATMOS_GEMPAK}/${sfc}" - "${DBNROOT}/bin/dbn_alert" MODEL GFS_PTYP_SND "${job}" "${COMOUT_ATMOS_GEMPAK}/${snd}" + "${DBNROOT}/bin/dbn_alert" MODEL GFS_PTYP_SFC "${job}" "${COMOUT_ATMOS_GEMPAK}/${sfc_out}" + "${DBNROOT}/bin/dbn_alert" MODEL GFS_PTYP_SND "${job}" "${COMOUT_ATMOS_GEMPAK}/${snd_out}" fi echo "done" > "${DATA}/gembufr.done" diff --git a/ush/gfs_sndp.sh b/ush/gfs_sndp.sh index 3d1cd01401c..af09e175dd7 100755 --- a/ush/gfs_sndp.sh +++ b/ush/gfs_sndp.sh @@ -10,7 +10,7 @@ # Create "collectives" consisting of groupings of the soundings # into files designated by geographical region. Each input # file gfs_collective*.list (1-9) contains the list of stations to - # put in a particular collective output file. + # put in a particular collective output file. export m=$1 mkdir $DATA/$m cd $DATA/$m @@ -19,18 +19,18 @@ cd $DATA/$m file_list=gfs_collective${m}.list if [ $m -le 2 ] - then + then WMOHEAD=JUSA4$m elif [ $m -le 6 ] - then + then WMOHEAD=JUSB4$m - else + else WMOHEAD=JUSX4$m fi for stn in $(cat $file_list) do - cpreq "${COMOUT_ATMOS_BUFR}/bufr.${stn}.${PDY}${cyc}" "${DATA}/${m}/bufrin" + cpreq "${COMIN_ATMOS_BUFR}/bufr.${stn}.${PDY}${cyc}" "${DATA}/${m}/bufrin" export pgm=tocsbufr.x #. prep_step export FORT11=$DATA/${m}/bufrin @@ -59,4 +59,3 @@ EOF "${COMOUT_ATMOS_WMO}/gfs_collective${m}.postsnd_${cyc}" fi cpfs "${DATA}/${m}/gfs_collective${m}.fil" "${COMOUT_ATMOS_BUFR}/." - diff --git a/ush/preamble.sh b/ush/preamble.sh index 5572fb5e9f3..aac23c4b39b 100755 --- a/ush/preamble.sh +++ b/ush/preamble.sh @@ -33,8 +33,9 @@ declare -x PS4='+ $(basename ${BASH_SOURCE[0]:-${FUNCNAME[0]:-"Unknown"}})[${LIN set_strict() { if [[ ${STRICT:-"YES"} == "YES" ]]; then - # Exit on error and undefined variable - set -eu + # Exit on error or undefined variable + # TODO: Also error in a pipeline (e.g. if and command in "cmd | cmd2" fails) + set -eu # -o pipefail fi } From 16241307e2f74028d2ba9e749148f0365768b275 Mon Sep 17 00:00:00 2001 From: Jeff Whitaker Date: Wed, 10 Dec 2025 06:28:24 -0700 Subject: [PATCH 18/27] update gsi hash to include ABI G19 in build_gsinfo (issue #4287) (#4304) This updates the GSI hash to include an updated version of build_gsinfo which turns on abi_g19 assimilaton. --- sorc/gsi_enkf.fd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorc/gsi_enkf.fd b/sorc/gsi_enkf.fd index 7da30e79df0..6f500cd5802 160000 --- a/sorc/gsi_enkf.fd +++ b/sorc/gsi_enkf.fd @@ -1 +1 @@ -Subproject commit 7da30e79df0c986712c92b30de8136d7caa00adc +Subproject commit 6f500cd580239fb173377c12f1f4628db1ec9666 From 70083a8c3f441cfc92ebaa01079cc63edabfcda0 Mon Sep 17 00:00:00 2001 From: "jessica.meixner" Date: Wed, 10 Dec 2025 11:21:45 -0500 Subject: [PATCH 19/27] updates for ice in --- ush/parsing_namelists_CICE.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ush/parsing_namelists_CICE.sh b/ush/parsing_namelists_CICE.sh index b2b0a97aca3..ecc0e2bd3f6 100755 --- a/ush/parsing_namelists_CICE.sh +++ b/ush/parsing_namelists_CICE.sh @@ -67,6 +67,7 @@ local CICE_RESTART_ROOT=-99 local CICE_RESTART_REARR="box" local CICE_RESTART_IOTASKS=-99 local CICE_RESTART_FORMAT="pnetcdf2" +local CICE_RESTART_MOD='none' local CICE_DUMPFREQ="y" # "h","d","m" or "y" for restarts at intervals of "hours", "days", "months" or "years" local CICE_DUMPFREQ_N=10000 # Set this to a really large value, as cice, mom6 and cmeps restart interval is controlled by ufs.configure local CICE_DIAGFREQ=$(( 86400 / DT_CICE )) # frequency of diagnostic output in timesteps, recommended for 1x per day From 447464758d273f59e4936e8fefb55071602bdcf0 Mon Sep 17 00:00:00 2001 From: "jessica.meixner" Date: Wed, 10 Dec 2025 17:09:18 -0500 Subject: [PATCH 20/27] update model --- sorc/ufs_model.fd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorc/ufs_model.fd b/sorc/ufs_model.fd index 2a33f2c8ee2..6f22f57403d 160000 --- a/sorc/ufs_model.fd +++ b/sorc/ufs_model.fd @@ -1 +1 @@ -Subproject commit 2a33f2c8ee265e75d5df18b652a23bf674528899 +Subproject commit 6f22f57403db693dee3b6979a4e6f58ade633e86 From f2a34bf0a7541147627141f47245d1c55c3f47a3 Mon Sep 17 00:00:00 2001 From: Walter Kolczynski Date: Thu, 11 Dec 2025 06:38:38 -0500 Subject: [PATCH 21/27] Update ush scripts to comply with bash static code checkers (#4292) Updates the ush scripts (including dev/ush) to be compliant with the static bash code analysis checkers. Also updates the reporter for the GH action so that it should be able to post recommendations on PRs. --- .github/workflows/bash_code_analysis.yaml | 17 +- dev/ush/get_warm_s2sw_restart_tarballs.sh | 8 +- dev/ush/gw_setup.sh | 20 +- dev/ush/load_modules.sh | 328 +-- dev/ush/make_ee2_links.sh | 221 +- ush/atmos_ensstat.sh | 13 +- ush/atmos_extractvars.sh | 166 +- ush/bash_utils.sh | 6 +- ush/create_gsi_info.sh | 175 +- ush/detect_machine.sh | 124 +- ush/extractvars_tools.sh | 94 +- ush/forecast_det.sh | 268 +- ush/forecast_postdet.sh | 1812 +++++++------ ush/forecast_predet.sh | 1374 +++++----- ush/fv3gfs_remap_weights.sh | 98 +- ush/gaussian_sfcanl.sh | 13 +- ush/getdump.sh | 14 +- ush/getges.sh | 2854 +++++++++++---------- ush/getioda.sh | 22 +- ush/gfs_bfr2gpk.sh | 6 +- ush/gfs_bufr.sh | 41 +- ush/gfs_bufr_netcdf.sh | 103 - ush/gfs_sndp.sh | 79 +- ush/gfs_truncate_enkf.sh | 52 - ush/global_cycle.sh | 15 +- ush/global_savefits.sh | 68 +- ush/interp_atmos_master.sh | 52 +- ush/interp_atmos_sflux.sh | 26 +- ush/jjob_header.sh | 18 +- ush/link_crtm_fix.sh | 32 +- ush/make_tif.sh | 18 +- ush/module-setup.sh | 37 +- ush/month_name.sh | 129 +- ush/ocnice_extractvars.sh | 112 +- ush/ozn_xtrct.sh | 221 +- ush/parsing_model_configure_FV3.sh | 134 +- ush/parsing_namelists_CICE.sh | 274 +- ush/parsing_namelists_FV3.sh | 980 +++---- ush/parsing_namelists_FV3_nest.sh | 413 ++- ush/parsing_namelists_GOCART.sh | 86 +- ush/parsing_namelists_MOM6.sh | 164 +- ush/parsing_namelists_WW3.sh | 122 +- ush/parsing_ufs_configure.sh | 238 +- ush/preamble.sh | 34 +- ush/prep_sfc_ice_blend.sh | 37 +- ush/prep_sfc_snow.sh | 66 +- ush/product_functions.sh | 54 +- ush/radmon_diag_ck.sh | 263 +- ush/radmon_err_rpt.sh | 209 +- ush/radmon_verf_angle.sh | 135 +- ush/radmon_verf_bcoef.sh | 148 +- ush/radmon_verf_bcor.sh | 137 +- ush/radmon_verf_time.sh | 581 +++-- ush/regrid_gsiSfcIncr_to_tile.sh | 155 +- ush/rstprod.sh | 6 +- ush/run_mpmd.sh | 96 +- ush/syndat_getjtbul.sh | 158 +- ush/syndat_qctropcy.sh | 321 ++- ush/tropcy_relocate.sh | 687 +++-- ush/tropcy_relocate_extrkr.sh | 1973 +++++++------- ush/wave_domain_grid.sh | 161 +- ush/wave_extractvars.sh | 38 +- ush/wave_grib2_sbs.sh | 87 +- ush/wave_grid_interp_sbs.sh | 38 +- ush/wave_grid_moddef.sh | 39 +- ush/wave_outp_cat.sh | 72 +- ush/wave_outp_spec.sh | 108 +- ush/wave_prnc_cur.sh | 48 +- ush/wave_prnc_ice.sh | 114 +- ush/wave_tar.sh | 196 +- 70 files changed, 8516 insertions(+), 8492 deletions(-) delete mode 100755 ush/gfs_bufr_netcdf.sh delete mode 100755 ush/gfs_truncate_enkf.sh diff --git a/.github/workflows/bash_code_analysis.yaml b/.github/workflows/bash_code_analysis.yaml index 27be4c76b6c..ca6160175a7 100644 --- a/.github/workflows/bash_code_analysis.yaml +++ b/.github/workflows/bash_code_analysis.yaml @@ -1,8 +1,8 @@ name: bash_code_analysis on: - push: - branches: - - develop + # push: + # branches: + # - develop pull_request: workflow_dispatch: @@ -32,11 +32,12 @@ jobs: # with: # filter_mode: nofilter # level: warning + # reporter: github-pr-review - name: Install shfmt uses: mfinelli/setup-shfmt@v4 - name: shfmt scan - run: shfmt -d dev/jobs dev/job_cards dev/scripts + run: shfmt -d dev/jobs dev/job_cards dev/scripts dev/ush ush shellcheck: runs-on: ubuntu-22.04 @@ -57,10 +58,13 @@ jobs: with: filter_mode: nofilter level: warning + reporter: github-pr-review path: | dev/jobs - jobs - scripts + dev/job_cards + dev/scripts + dev/ush + ush pattern: | config.* J* @@ -88,6 +92,7 @@ jobs: with: filter_mode: added level: warning + reporter: github-pr-review check_all_files_with_shebangs: true pattern: | config.* diff --git a/dev/ush/get_warm_s2sw_restart_tarballs.sh b/dev/ush/get_warm_s2sw_restart_tarballs.sh index 6adba89a21c..44a968b08f3 100755 --- a/dev/ush/get_warm_s2sw_restart_tarballs.sh +++ b/dev/ush/get_warm_s2sw_restart_tarballs.sh @@ -33,9 +33,9 @@ fi cd "${untar_dir}" -ptargets=( "enkfgdas_restartb_grp1.tar" "enkfgdas_restartb_grp2.tar" "enkfgdas_restartb_grp3.tar" "enkfgdas_restartb_grp4.tar" "enkfgdas_restartb_grp5.tar" "enkfgdas_restartb_grp6.tar" "enkfgdas_restartb_grp7.tar" "enkfgdas_restartb_grp8.tar" "gdas_restartb.tar" "gdasocean_restart.tar" "gdaswave_restart.tar" ) +ptargets=("enkfgdas_restartb_grp1.tar" "enkfgdas_restartb_grp2.tar" "enkfgdas_restartb_grp3.tar" "enkfgdas_restartb_grp4.tar" "enkfgdas_restartb_grp5.tar" "enkfgdas_restartb_grp6.tar" "enkfgdas_restartb_grp7.tar" "enkfgdas_restartb_grp8.tar" "gdas_restartb.tar" "gdasocean_restart.tar" "gdaswave_restart.tar") -targets=( "enkfgdas_restarta_grp1.tar" "enkfgdas_restarta_grp2.tar" "enkfgdas_restarta_grp3.tar" "enkfgdas_restarta_grp4.tar" "enkfgdas_restarta_grp5.tar" "enkfgdas_restarta_grp6.tar" "enkfgdas_restarta_grp7.tar" "enkfgdas_restarta_grp8.tar" "gdas_restarta.tar" "gdasocean_analysis.tar") +targets=("enkfgdas_restarta_grp1.tar" "enkfgdas_restarta_grp2.tar" "enkfgdas_restarta_grp3.tar" "enkfgdas_restarta_grp4.tar" "enkfgdas_restarta_grp5.tar" "enkfgdas_restarta_grp6.tar" "enkfgdas_restarta_grp7.tar" "enkfgdas_restarta_grp8.tar" "gdas_restarta.tar" "gdasocean_analysis.tar") # This is all specific to Gaea C6 clusters="es" @@ -48,7 +48,7 @@ tasks=1 # Construct a wrapper script in a loop to submit to the sbatch system for tarball in "${targets[@]}"; do - sbatch << EOF + sbatch << EOF #!/bin/bash #SBATCH --job-name=get_retro_${tarball} #SBATCH --output=get_retro_${tarball}.out @@ -81,7 +81,7 @@ done # Now do the same for the previous cycle tarballs for tarball in "${ptargets[@]}"; do - sbatch << EOF + sbatch << EOF #!/bin/bash #SBATCH --job-name=get_retro_${tarball} #SBATCH --output=get_retro_${tarball}.out diff --git a/dev/ush/gw_setup.sh b/dev/ush/gw_setup.sh index 5b70b9b4fce..04d9433f819 100755 --- a/dev/ush/gw_setup.sh +++ b/dev/ush/gw_setup.sh @@ -11,10 +11,10 @@ # Determine if HOMEgfs is already set unset_homegfs=NO if [[ -z "${HOMEgfs+x}" ]]; then - script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )" - HOMEgfs=$(cd "${script_dir}" && git rev-parse --show-toplevel) - export HOMEgfs - unset_homegfs=YES + script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" + HOMEgfs=$(cd "${script_dir}" && git rev-parse --show-toplevel) + export HOMEgfs + unset_homegfs=YES fi source "${HOMEgfs}/ush/detect_machine.sh" source "${HOMEgfs}/ush/module-setup.sh" @@ -23,18 +23,16 @@ module use "${HOMEgfs}/modulefiles" module load "gw_setup.${MACHINE_ID}" err=$? if [[ "${err}" -ne 0 ]]; then - echo "FATAL ERROR: Failed to load module_gwsetup.${MACHINE_ID}" - exit 1 + echo "FATAL ERROR: Failed to load module_gwsetup.${MACHINE_ID}" + exit 1 fi # Set up the PYTHONPATH to include wxflow from HOMEgfs if [[ -d "${HOMEgfs}/sorc/wxflow/src" ]]; then - PYTHONPATH="${HOMEgfs}/sorc/wxflow/src${PYTHONPATH:+:${PYTHONPATH}}" - export PYTHONPATH + PYTHONPATH="${HOMEgfs}/sorc/wxflow/src${PYTHONPATH:+:${PYTHONPATH}}" + export PYTHONPATH fi - if [[ ${unset_homegfs} == "YES" ]]; then - unset HOMEgfs + unset HOMEgfs fi - diff --git a/dev/ush/load_modules.sh b/dev/ush/load_modules.sh index d049bcf92ce..263549f9f6c 100755 --- a/dev/ush/load_modules.sh +++ b/dev/ush/load_modules.sh @@ -8,14 +8,14 @@ ############################################################### if [[ "$-" == *x* ]]; then - set_x=YES + set_x=YES else - set_x=NO + set_x=NO fi if [[ "${DEBUG_WORKFLOW:-NO}" == "NO" ]]; then - echo "Loading modules quietly..." - set +x + echo "Loading modules quietly..." + set +x fi # Parse module type argument @@ -24,11 +24,11 @@ MODULE_TYPE="${1:-run}" # For backwards compatibility, handle ufsda options UFSDA_MODS="GDAS" if [[ "${MODULE_TYPE}" == "--eva" ]]; then - MODULE_TYPE="ufsda" - UFSDA_MODS="EVA" + MODULE_TYPE="ufsda" + UFSDA_MODS="EVA" elif [[ "${MODULE_TYPE}" == "--gdas" ]]; then - MODULE_TYPE="ufsda" - UFSDA_MODS="GDAS" + MODULE_TYPE="ufsda" + UFSDA_MODS="GDAS" fi # Setup runtime environment by loading modules @@ -37,25 +37,25 @@ ulimit_s=$(ulimit -S -s) # Test if HOMEgfs is defined. If not, then try to determine it with git rev-parse _unset_homegfs="NO" if [[ -z ${HOMEgfs+x} ]]; then - echo "INFO: HOMEgfs is not defined. Attempting to find the global-workflow root directory" - # HOMEgfs will be removed from the environment at the end of this script - _unset_homegfs="YES" - - script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) - HOMEgfs=$(cd "${script_dir}" && git rev-parse --show-toplevel) - export HOMEgfs - err=$? - if [[ ${err} -ne 0 ]]; then - is_git_dir=$(cd -- "${script_dir}" &> /dev/null && git rev-parse --is-inside-work-tree) - git_stat=$? - if [[ ${git_stat} -ne 0 || ${is_git_dir} != "true" ]]; then - echo "FATAL ERROR: unable to determine the root because it is not a git repository." - else - echo "FATAL ERROR: unable to determine the root because git rev-parse --show-toplevel failed for an unknown reason" + echo "INFO: HOMEgfs is not defined. Attempting to find the global-workflow root directory" + # HOMEgfs will be removed from the environment at the end of this script + _unset_homegfs="YES" + + script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) + HOMEgfs=$(cd "${script_dir}" && git rev-parse --show-toplevel) + export HOMEgfs + err=$? + if [[ ${err} -ne 0 ]]; then + is_git_dir=$(cd -- "${script_dir}" &> /dev/null && git rev-parse --is-inside-work-tree) + git_stat=$? + if [[ ${git_stat} -ne 0 || ${is_git_dir} != "true" ]]; then + echo "FATAL ERROR: unable to determine the root because it is not a git repository." + else + echo "FATAL ERROR: unable to determine the root because git rev-parse --show-toplevel failed for an unknown reason" + fi + echo "FATAL ERROR: Unable to load modules. Exiting" + exit 1 fi - echo "FATAL ERROR: Unable to load modules. Exiting" - exit 1 - fi fi # Find module command and purge: @@ -64,162 +64,162 @@ source "${HOMEgfs}/ush/module-setup.sh" # Handle different module types case "${MODULE_TYPE}" in - "ufswm") - # UFS Weather Model modules - special handling - module use "${HOMEgfs}/sorc/ufs_model.fd/modulefiles" - module load "ufs_${MACHINE_ID}.intel" - export err=$? - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: Failed to load ufs_${MACHINE_ID}.intel" - exit 1 - fi - module load prod_util - if [[ "${MACHINE_ID}" = "wcoss2" ]]; then - module load cray-pals - module load cfp - module load libjpeg - module load craype-network-ucx - module load cray-mpich-ucx - module load python/3.8.6 - module load wgrib2 - else - export UTILROOT=${prod_util_ROOT} - source "${HOMEgfs}/versions/run.ver" - module load "wgrib2/${wgrib2_ver}" - fi - export WGRIB2=wgrib2 - - module list - unset MACHINE_ID - ;; - - "ufsda") - # UFSDA modules - special handling - module use "${HOMEgfs}/sorc/gdas.cd/modulefiles" - - case "${MACHINE_ID}" in - ("hera" | "orion" | "hercules" | "wcoss2" | "gaeac5" | "gaeac6" | "ursa" | "noaacloud") - #TODO: Remove LMOD_TMOD_FIND_FIRST line when spack-stack on WCOSS2 - if [[ "${MACHINE_ID}" == "wcoss2" ]]; then - export LMOD_TMOD_FIND_FIRST=yes - # TODO: Add path to GDASApp libraries and cray-mpich as temporary patches - export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${HOMEgfs}/sorc/gdas.cd/build/lib" - # TODO: Remove LD_LIBRARY_PATH line as soon as permanent solution is available - export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/cray/pe/mpich/8.1.29/ofi/intel/2022.1/lib" - fi - module load "${UFSDA_MODS}/${MACHINE_ID}" + "ufswm") + # UFS Weather Model modules - special handling + module use "${HOMEgfs}/sorc/ufs_model.fd/modulefiles" + module load "ufs_${MACHINE_ID}.intel" export err=$? if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: Failed to load ${UFSDA_MODS}/${MACHINE_ID}" - exit 1 + echo "FATAL ERROR: Failed to load ufs_${MACHINE_ID}.intel" + exit 1 fi - ncdump=$(command -v ncdump) - NETCDF=$(echo "${ncdump}" | cut -d " " -f 3) - export NETCDF - ;; - ("acorn") - echo WARNING: UFSDA NOT SUPPORTED ON 'acorn' - ;; - *) - echo "WARNING: UNKNOWN PLATFORM" + module load prod_util + if [[ "${MACHINE_ID}" == "wcoss2" ]]; then + module load cray-pals + module load cfp + module load libjpeg + module load craype-network-ucx + module load cray-mpich-ucx + module load python/3.8.6 + module load wgrib2 + else + export UTILROOT=${prod_util_ROOT} + source "${HOMEgfs}/versions/run.ver" + module load "wgrib2/${wgrib2_ver}" + fi + export WGRIB2=wgrib2 + + module list + unset MACHINE_ID ;; - esac - module list + "ufsda") + # UFSDA modules - special handling + module use "${HOMEgfs}/sorc/gdas.cd/modulefiles" + + case "${MACHINE_ID}" in + "hera" | "orion" | "hercules" | "wcoss2" | "gaeac5" | "gaeac6" | "ursa" | "noaacloud") + #TODO: Remove LMOD_TMOD_FIND_FIRST line when spack-stack on WCOSS2 + if [[ "${MACHINE_ID}" == "wcoss2" ]]; then + export LMOD_TMOD_FIND_FIRST=yes + # TODO: Add path to GDASApp libraries and cray-mpich as temporary patches + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${HOMEgfs}/sorc/gdas.cd/build/lib" + # TODO: Remove LD_LIBRARY_PATH line as soon as permanent solution is available + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/cray/pe/mpich/8.1.29/ofi/intel/2022.1/lib" + fi + module load "${UFSDA_MODS}/${MACHINE_ID}" + export err=$? + if [[ ${err} -ne 0 ]]; then + echo "FATAL ERROR: Failed to load ${UFSDA_MODS}/${MACHINE_ID}" + exit 1 + fi + ncdump=$(command -v ncdump) + NETCDF=$(echo "${ncdump}" | cut -d " " -f 3) + export NETCDF + ;; + "acorn") + echo WARNING: UFSDA NOT SUPPORTED ON 'acorn' + ;; + *) + echo "WARNING: UNKNOWN PLATFORM" + ;; + esac + + module list + + ftype=$(type -t set_trace || echo "") + if [[ "${ftype}" == "function" ]]; then + set_trace + elif [[ "${set_x}" == "YES" ]]; then + set -x + fi - ftype=$(type -t set_trace || echo "") - if [[ "${ftype}" == "function" ]]; then - set_trace - elif [[ "${set_x}" == "YES" ]]; then - set -x - fi + pip list - pip list + # Detect the Python major.minor version + _regex="[0-9]+\.[0-9]+" + # shellcheck disable=SC2312 + if [[ $(python --version) =~ ${_regex} ]]; then + export PYTHON_VERSION="${BASH_REMATCH[0]}" + else + echo "FATAL ERROR: Could not detect the python version" + exit 1 + fi - # Detect the Python major.minor version - _regex="[0-9]+\.[0-9]+" - # shellcheck disable=SC2312 - if [[ $(python --version) =~ ${_regex} ]]; then - export PYTHON_VERSION="${BASH_REMATCH[0]}" - else - echo "FATAL ERROR: Could not detect the python version" - exit 1 - fi + ############################################################### + # setup python path for ioda utilities + # TODO: a better solution should be created for setting paths to package python scripts + # shellcheck disable=SC2311 + pyiodaPATH="${HOMEgfs}/sorc/gdas.cd/build/lib/python${PYTHON_VERSION}/" + pybufrPATH="${HOMEgfs}/sorc/gdas.cd/build/lib/python${PYTHON_VERSION}/site-packages/" + PYTHONPATH="${pyiodaPATH}:${pybufrPATH}${PYTHONPATH:+:${PYTHONPATH}}" + export PYTHONPATH + ;; - ############################################################### - # setup python path for ioda utilities - # TODO: a better solution should be created for setting paths to package python scripts - # shellcheck disable=SC2311 - pyiodaPATH="${HOMEgfs}/sorc/gdas.cd/build/lib/python${PYTHON_VERSION}/" - pybufrPATH="${HOMEgfs}/sorc/gdas.cd/build/lib/python${PYTHON_VERSION}/site-packages/" - PYTHONPATH="${pyiodaPATH}:${pybufrPATH}${PYTHONPATH:+:${PYTHONPATH}}" - export PYTHONPATH - ;; - - "run" | "gsi" | "verif" | "setup" | "upp") - - # Test that the version file exists - if [[ ! -f "${HOMEgfs}/versions/run.ver" ]]; then - echo "FATAL ERROR: ${HOMEgfs}/versions/run.ver does not exist!" - echo "HINT: Run link_workflow.sh first." - exit 1 - fi + "run" | "gsi" | "verif" | "setup" | "upp") - # Load our modules: - module use "${HOMEgfs}/modulefiles" - - # Determine target module based on type and machine - target_module="gw_${MODULE_TYPE}.${MACHINE_ID}" - - # Check if the target module file exists, fall back to gw_run if not - if ! module is-avail "${target_module}" 2>/dev/null; then - if [[ "${MODULE_TYPE}" != "run" ]]; then - echo "INFO: ${target_module} module not available, falling back to gw_run.${MACHINE_ID}" - mod_type="run" - fi - target_module="gw_run.${MACHINE_ID}" - else - mod_type="${MODULE_TYPE}" - fi + # Test that the version file exists + if [[ ! -f "${HOMEgfs}/versions/run.ver" ]]; then + echo "FATAL ERROR: ${HOMEgfs}/versions/run.ver does not exist!" + echo "HINT: Run link_workflow.sh first." + exit 1 + fi - # Source versions file (except for upp) - if [[ "${mod_type}" != "upp" ]]; then - source "${HOMEgfs}/versions/run.ver" - fi + # Load our modules: + module use "${HOMEgfs}/modulefiles" + + # Determine target module based on type and machine + target_module="gw_${MODULE_TYPE}.${MACHINE_ID}" + + # Check if the target module file exists, fall back to gw_run if not + if ! module is-avail "${target_module}" 2> /dev/null; then + if [[ "${MODULE_TYPE}" != "run" ]]; then + echo "INFO: ${target_module} module not available, falling back to gw_run.${MACHINE_ID}" + mod_type="run" + fi + target_module="gw_run.${MACHINE_ID}" + else + mod_type="${MODULE_TYPE}" + fi - if [[ -n "${target_module}" ]]; then - module load "${target_module}" - export err=$? - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: Failed to load ${target_module}" - exit 1 - fi - else - echo "FATAL ERROR: Could not determine target module for MODULE_TYPE='${MODULE_TYPE}' and MACHINE_ID='${MACHINE_ID}'" - exit 1 - fi + # Source versions file (except for upp) + if [[ "${mod_type}" != "upp" ]]; then + source "${HOMEgfs}/versions/run.ver" + fi - module list + if [[ -n "${target_module}" ]]; then + module load "${target_module}" + export err=$? + if [[ ${err} -ne 0 ]]; then + echo "FATAL ERROR: Failed to load ${target_module}" + exit 1 + fi + else + echo "FATAL ERROR: Could not determine target module for MODULE_TYPE='${MODULE_TYPE}' and MACHINE_ID='${MACHINE_ID}'" + exit 1 + fi - # If this function exists in the environment, run it; else set -x if it was set on entering this script - ftype=$(type -t set_trace || echo "") - if [[ "${ftype}" == "function" ]]; then - set_trace - elif [[ "${set_x}" == "YES" ]]; then - set -x - fi - ;; + module list + + # If this function exists in the environment, run it; else set -x if it was set on entering this script + ftype=$(type -t set_trace || echo "") + if [[ "${ftype}" == "function" ]]; then + set_trace + elif [[ "${set_x}" == "YES" ]]; then + set -x + fi + ;; + + *) + echo "FATAL ERROR: Unknown module type '${MODULE_TYPE}'" + echo "Valid types: run, gsi, verif, ufsda, ufswm, setup" + ;; - *) - echo "FATAL ERROR: Unknown module type '${MODULE_TYPE}'" - echo "Valid types: run, gsi, verif, ufsda, ufswm, setup" - exit 1 - ;; esac # Set up the PYTHONPATH to include wxflow from HOMEgfs if [[ -d "${HOMEgfs}/sorc/wxflow/src" ]]; then - PYTHONPATH="${HOMEgfs}/sorc/wxflow/src${PYTHONPATH:+:${PYTHONPATH}}" + PYTHONPATH="${HOMEgfs}/sorc/wxflow/src${PYTHONPATH:+:${PYTHONPATH}}" fi # Add HOMEgfs/ush/python to PYTHONPATH @@ -232,5 +232,5 @@ unset ulimit_s # Unset HOMEgfs if it was not set at the beginning of this script if [[ ${_unset_homegfs} == "YES" ]]; then - unset HOMEgfs + unset HOMEgfs fi diff --git a/dev/ush/make_ee2_links.sh b/dev/ush/make_ee2_links.sh index 674e83a5013..9704dc553bd 100755 --- a/dev/ush/make_ee2_links.sh +++ b/dev/ush/make_ee2_links.sh @@ -14,7 +14,6 @@ set -eux # WARNING: This script does not create all links needed for EE2 compatibility. It only creates links needed to # restart an existing experiment. - if [[ $# -ne 1 ]]; then echo "Usage: $0 " exit 1 @@ -43,18 +42,18 @@ link_file() { return 0 } -gdas_list=($(ls -d gdas.* || true )) -gfs_list=($(ls -d gfs.* || true )) -gcdas_list=($(ls -d gcdas.* || true )) -gcafs_list=($(ls -d gcafs.* || true )) -enkfgdas_list=($(ls -d enkfgdas.* || true )) -enkfgfs_list=($(ls -d enkfgfs.* || true )) -enkfgcdas_list=($(ls -d enkfgcdas.* || true )) +gdas_list=($(ls -d gdas.* || true)) +gfs_list=($(ls -d gfs.* || true)) +gcdas_list=($(ls -d gcdas.* || true)) +gcafs_list=($(ls -d gcafs.* || true)) +enkfgdas_list=($(ls -d enkfgdas.* || true)) +enkfgfs_list=($(ls -d enkfgfs.* || true)) +enkfgcdas_list=($(ls -d enkfgcdas.* || true)) # If the length of all of the arrays is zero, exit with a message if [[ ${#gdas_list[@]} -eq 0 && ${#gfs_list[@]} -eq 0 && ${#gcdas_list[@]} -eq 0 && - ${#gcafs_list[@]} -eq 0 && ${#enkfgdas_list[@]} -eq 0 && - ${#enkfgfs_list[@]} -eq 0 && ${#enkfgcdas_list[@]} -eq 0 ]]; then + ${#gcafs_list[@]} -eq 0 && ${#enkfgdas_list[@]} -eq 0 && + ${#enkfgfs_list[@]} -eq 0 && ${#enkfgcdas_list[@]} -eq 0 ]]; then echo "No gdas, gfs, gcdas, gcafs, enkfgdas, enkfgfs, or enkfgcdas directories found. Exiting." exit 0 fi @@ -70,10 +69,13 @@ for dir in "${gdas_list[@]}" "${gfs_list[@]}" "${gcdas_list[@]}" "${gcafs_list[@ gfs.*) system_prefix="gfs" ;; gcdas.*) system_prefix="gcdas" ;; gcafs.*) system_prefix="gcafs" ;; - *) echo "Unknown directory prefix: ${dir}"; exit 1 ;; + *) + echo "Unknown directory prefix: ${dir}" + exit 1 + ;; esac - cycle_list=($(ls -d -- ?? || true )) + cycle_list=($(ls -d -- ?? || true)) for cyc in "${cycle_list[@]}"; do if [[ -d "${cwd}/${dir}/${cyc}/analysis/atmos" ]]; then cd "${cwd}/${dir}/${cyc}/analysis/atmos" @@ -82,93 +84,93 @@ for dir in "${gdas_list[@]}" "${gfs_list[@]}" "${gcdas_list[@]}" "${gcafs_list[@ link_file "${system_prefix}.t${cyc}z.${abias_type}" "${system_prefix}.t${cyc}z.${abias_type}.txt" fi done - if [[ -f "${system_prefix}.t${cyc}z.radstat" ]]; then - link_file "${system_prefix}.t${cyc}z.radstat" "${system_prefix}.t${cyc}z.radstat.tar" - fi - if [[ -f "${system_prefix}.t${cyc}z.atmi003.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.atmi003.nc" "${system_prefix}.t${cyc}z.increment.atm.i003.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.atminc.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.atminc.nc" "${system_prefix}.t${cyc}z.increment.atm.i006.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.atmi009.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.atmi009.nc" "${system_prefix}.t${cyc}z.increment.atm.i009.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.atma003.ensres.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.atma003.ensres.nc" "${system_prefix}.t${cyc}z.ensres_analysis.atm.a003.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.atmanl.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.atmanl.nc" "${system_prefix}.t${cyc}z.analysis.atm.a006.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.atmanl.ensres.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.atmanl.ensres.nc" "${system_prefix}.t${cyc}z.ensres_analysis.atm.a006.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.atma009.ensres.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.atma009.ensres.nc" "${system_prefix}.t${cyc}z.ensres_analysis.atm.a009.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.cnvstat" ]]; then - link_file "${system_prefix}.t${cyc}z.cnvstat" "${system_prefix}.t${cyc}z.cnvstat.tar" - fi - if [[ -f "${system_prefix}.t${cyc}z.dtfanl.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.dtfanl.nc" "${system_prefix}.t${cyc}z.analysis.dtf.a006.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.gsistat" ]]; then - link_file "${system_prefix}.t${cyc}z.gsistat" "${system_prefix}.t${cyc}z.gsistat.txt" - fi - if [[ -f "${system_prefix}.t${cyc}z.oznstat" ]]; then - link_file "${system_prefix}.t${cyc}z.oznstat" "${system_prefix}.t${cyc}z.oznstat.tar" - fi - if [[ -f "${system_prefix}.t${cyc}z.loginc.txt" ]]; then - link_file "${system_prefix}.t${cyc}z.loginc.txt" "${system_prefix}.t${cyc}z.increment.done.txt" - fi - if [[ -f "${system_prefix}.t${cyc}z.loganl.txt" ]]; then - link_file "${system_prefix}.t${cyc}z.loganl.txt" "${system_prefix}.t${cyc}z.analysis.done.txt" - fi - if [[ -f "${system_prefix}.t${cyc}z.sfci003.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.sfci003.nc" "${system_prefix}.t${cyc}z.increment.sfc.i003.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.sfci006.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.sfci006.nc" "${system_prefix}.t${cyc}z.increment.sfc.i006.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.sfci009.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.sfci009.nc" "${system_prefix}.t${cyc}z.increment.sfc.i009.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.sfcanl.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.sfcanl.nc" "${system_prefix}.t${cyc}z.analysis.sfc.a006.nc" - fi - if [[ -f "${system_prefix}.t${cyc}z.sfcinc.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.sfcinc.nc" "${system_prefix}.t${cyc}z.increment.sfc.i006.nc" - fi - if [[ -f "sfc_inc.tile1.nc" ]]; then - for tile in {1..6}; do - link_file "sfc_inc.tile${tile}.nc" "increment.sfc.tile${tile}.nc" - done - fi - if [[ -f "${system_prefix}.t${cyc}z.cubed_sphere_grid_atminc.tile1.nc" ]]; then - for tile in {1..6}; do - link_file "${system_prefix}.t${cyc}z.cubed_sphere_grid_atminc.tile${tile}.nc" "${system_prefix}.t${cyc}z.jedi_increment.atm.i006.tile${tile}.nc" - done - fi - fi - cd "${cwd}" - if [[ -d "${cwd}/${dir}/${cyc}/analysis/ocean" ]]; then - cd "${cwd}/${dir}/${cyc}/analysis/ocean" - if [[ -f "${system_prefix}.t${cyc}z.ocninc.nc" ]]; then - link_file "${system_prefix}.t${cyc}z.ocninc.nc" "${system_prefix}.t${cyc}z.mom6_increment.i006.nc" - fi - fi - cd "${cwd}" - if [[ -d "${cwd}/${dir}/${cyc}/analysis/ice" ]]; then - cd "${cwd}/${dir}/${cyc}/analysis/ice" - for ice_file in *.cice_model_anl.res.nc; do - if [[ -f "${ice_file}" ]]; then - # This gets the first two fields of the filename separated by dots - prefix=$(echo "${ice_file}" | cut -d. -f1-2) - link_file "${ice_file}" "${prefix}.analysis.cice_model.res.nc" - fi - done - fi - cd "${cwd}" + if [[ -f "${system_prefix}.t${cyc}z.radstat" ]]; then + link_file "${system_prefix}.t${cyc}z.radstat" "${system_prefix}.t${cyc}z.radstat.tar" + fi + if [[ -f "${system_prefix}.t${cyc}z.atmi003.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.atmi003.nc" "${system_prefix}.t${cyc}z.increment.atm.i003.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.atminc.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.atminc.nc" "${system_prefix}.t${cyc}z.increment.atm.i006.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.atmi009.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.atmi009.nc" "${system_prefix}.t${cyc}z.increment.atm.i009.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.atma003.ensres.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.atma003.ensres.nc" "${system_prefix}.t${cyc}z.ensres_analysis.atm.a003.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.atmanl.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.atmanl.nc" "${system_prefix}.t${cyc}z.analysis.atm.a006.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.atmanl.ensres.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.atmanl.ensres.nc" "${system_prefix}.t${cyc}z.ensres_analysis.atm.a006.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.atma009.ensres.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.atma009.ensres.nc" "${system_prefix}.t${cyc}z.ensres_analysis.atm.a009.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.cnvstat" ]]; then + link_file "${system_prefix}.t${cyc}z.cnvstat" "${system_prefix}.t${cyc}z.cnvstat.tar" + fi + if [[ -f "${system_prefix}.t${cyc}z.dtfanl.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.dtfanl.nc" "${system_prefix}.t${cyc}z.analysis.dtf.a006.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.gsistat" ]]; then + link_file "${system_prefix}.t${cyc}z.gsistat" "${system_prefix}.t${cyc}z.gsistat.txt" + fi + if [[ -f "${system_prefix}.t${cyc}z.oznstat" ]]; then + link_file "${system_prefix}.t${cyc}z.oznstat" "${system_prefix}.t${cyc}z.oznstat.tar" + fi + if [[ -f "${system_prefix}.t${cyc}z.loginc.txt" ]]; then + link_file "${system_prefix}.t${cyc}z.loginc.txt" "${system_prefix}.t${cyc}z.increment.done.txt" + fi + if [[ -f "${system_prefix}.t${cyc}z.loganl.txt" ]]; then + link_file "${system_prefix}.t${cyc}z.loganl.txt" "${system_prefix}.t${cyc}z.analysis.done.txt" + fi + if [[ -f "${system_prefix}.t${cyc}z.sfci003.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.sfci003.nc" "${system_prefix}.t${cyc}z.increment.sfc.i003.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.sfci006.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.sfci006.nc" "${system_prefix}.t${cyc}z.increment.sfc.i006.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.sfci009.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.sfci009.nc" "${system_prefix}.t${cyc}z.increment.sfc.i009.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.sfcanl.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.sfcanl.nc" "${system_prefix}.t${cyc}z.analysis.sfc.a006.nc" + fi + if [[ -f "${system_prefix}.t${cyc}z.sfcinc.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.sfcinc.nc" "${system_prefix}.t${cyc}z.increment.sfc.i006.nc" + fi + if [[ -f "sfc_inc.tile1.nc" ]]; then + for tile in {1..6}; do + link_file "sfc_inc.tile${tile}.nc" "increment.sfc.tile${tile}.nc" + done + fi + if [[ -f "${system_prefix}.t${cyc}z.cubed_sphere_grid_atminc.tile1.nc" ]]; then + for tile in {1..6}; do + link_file "${system_prefix}.t${cyc}z.cubed_sphere_grid_atminc.tile${tile}.nc" "${system_prefix}.t${cyc}z.jedi_increment.atm.i006.tile${tile}.nc" + done + fi + fi + cd "${cwd}" + if [[ -d "${cwd}/${dir}/${cyc}/analysis/ocean" ]]; then + cd "${cwd}/${dir}/${cyc}/analysis/ocean" + if [[ -f "${system_prefix}.t${cyc}z.ocninc.nc" ]]; then + link_file "${system_prefix}.t${cyc}z.ocninc.nc" "${system_prefix}.t${cyc}z.mom6_increment.i006.nc" + fi + fi + cd "${cwd}" + if [[ -d "${cwd}/${dir}/${cyc}/analysis/ice" ]]; then + cd "${cwd}/${dir}/${cyc}/analysis/ice" + for ice_file in *.cice_model_anl.res.nc; do + if [[ -f "${ice_file}" ]]; then + # This gets the first two fields of the filename separated by dots + prefix=$(echo "${ice_file}" | cut -d. -f1-2) + link_file "${ice_file}" "${prefix}.analysis.cice_model.res.nc" + fi + done + fi + cd "${cwd}" if [[ -d "${cwd}/${dir}/${cyc}/analysis/snow" ]]; then cd "${cwd}/${dir}/${cyc}/analysis/snow" for snow_file in snowinc*.sfc_data.tile1.nc; do @@ -189,18 +191,21 @@ done for dir in "${enkfgdas_list[@]}" "${enkfgfs_list[@]}"; do cd "${dir}" - cycle_list=($(ls -d -- ?? || true )) + cycle_list=($(ls -d -- ?? || true)) # Determine the system prefix system_prefix="" case "${dir}" in enkfgdas.*) system_prefix="enkfgdas" ;; enkfgfs.*) system_prefix="enkfgfs" ;; enkfgcdas.*) system_prefix="enkfgcdas" ;; - *) echo "Unknown directory prefix: ${dir}"; exit 1 ;; + *) + echo "Unknown directory prefix: ${dir}" + exit 1 + ;; esac for cyc in "${cycle_list[@]}"; do cd "${cwd}/${dir}/${cyc}" - mem_list=($(ls -d mem* || true )) + mem_list=($(ls -d mem* || true)) for mem in "${mem_list[@]}"; do # atmos if [[ -d "${cwd}/${dir}/${cyc}/${mem}/analysis/atmos" ]]; then @@ -280,12 +285,12 @@ for dir in "${enkfgdas_list[@]}" "${enkfgfs_list[@]}"; do cd "${cwd}/${dir}/${cyc}/${mem}/analysis/snow" # The old snow analysis files start with YYYYMMDD.HHMMSS, which we want to keep for snow_file in ????????.??????.sfc_data.tile1.nc; do - if [[ -f "${snow_file}" ]]; then - prefix=$(echo "${snow_file}" | cut -d. -f1-2) - for tile in {1..6}; do - link_file "${prefix}.sfc_data.tile${tile}.nc" "${prefix}.snow_analysis.sfc_data.tile${tile}.nc" - done - fi + if [[ -f "${snow_file}" ]]; then + prefix=$(echo "${snow_file}" | cut -d. -f1-2) + for tile in {1..6}; do + link_file "${prefix}.sfc_data.tile${tile}.nc" "${prefix}.snow_analysis.sfc_data.tile${tile}.nc" + done + fi done fi cd "${cwd}" diff --git a/ush/atmos_ensstat.sh b/ush/atmos_ensstat.sh index 36218731627..4be0a96d56b 100755 --- a/ush/atmos_ensstat.sh +++ b/ush/atmos_ensstat.sh @@ -24,8 +24,8 @@ for ((mem_num = 0; mem_num <= "${NMEM_ENS:-0}"; mem_num++)); do done num_found=${#input_files[@]} -if (( num_found != NMEM_ENS + 1 )); then - echo "FATAL ERROR: Only ${num_found} grib files found out of $(( NMEM_ENS + 1 )) expected members." +if ((num_found != NMEM_ENS + 1)); then + echo "FATAL ERROR: Only ${num_found} grib files found out of $((NMEM_ENS + 1)) expected members." exit 10 fi @@ -47,8 +47,8 @@ cat << EOF > input.nml cfopg2="${spr_out}" $( - for (( filenum = 1; filenum <= num_found; filenum++ )); do - echo " cfipg(${filenum})=\"${input_files[$((filenum-1))]}\"," + for ((filenum = 1; filenum <= num_found; filenum++)); do + echo " cfipg(${filenum})=\"${input_files[$((filenum - 1))]}\"," echo " iskip(${filenum})=0," done ) @@ -61,7 +61,7 @@ cat input.nml "${EXECgfs}/ensstat.x" < input.nml export err=$? -if (( err != 0 )) ; then +if [[ "${err}" -ne 0 ]]; then echo "FATAL ERROR: ensstat returned error code ${err}" exit "${err}" fi @@ -78,7 +78,7 @@ for outfile in ${mean_out} ${spr_out}; do ${WGRIB2} -s "${outfile}" > "${outfile}.idx" err=$? - if (( err != 0 )); then + if [[ "${err}" -ne 0 ]]; then echo "FATAL ERROR: Failed to create inventory file, wgrib2 returned ${err}" exit "${err}" fi @@ -94,4 +94,3 @@ for outfile in ${mean_out} ${spr_out}; do fi done - diff --git a/ush/atmos_extractvars.sh b/ush/atmos_extractvars.sh index 2033fd8c849..31cd61087bd 100755 --- a/ush/atmos_extractvars.sh +++ b/ush/atmos_extractvars.sh @@ -14,101 +14,101 @@ dcnt=1 # lead day subdata=${1} if [[ ! -d "${subdata}" ]]; then - mkdir -p "${subdata}" + mkdir -p "${subdata}" fi for outtype in "f2d" "f3d"; do - if [[ "${outtype}" == "f2d" ]]; then - varlist=${varlist_2d} - ARC_RFCST_PROD_ATMOS="${ARC_RFCST_PROD_ATMOS_F2D}" - elif [[ "${outtype}" == "f3d" ]]; then - varlist=${varlist_3d} - varlist_d=${varlist_3d_d} - ARC_RFCST_PROD_ATMOS="${ARC_RFCST_PROD_ATMOS_F3D}" - fi - - outdirpre="${subdata}/${outtype}" - if [[ ! -d "${outdirpre}" ]]; then - mkdir -p "${outdirpre}" - fi - - nh=${FHMIN} - - while (( nh <= FHMAX_GFS )); do - fnh=$(printf "%3.3d" "${nh}") - if [[ "${outtype}" == "f2d" ]]; then - if (( nh < FHMAX_HF_GFS )); then - outres="0p25" - else - outres="0p50" - fi + varlist=${varlist_2d} + ARC_RFCST_PROD_ATMOS="${ARC_RFCST_PROD_ATMOS_F2D}" elif [[ "${outtype}" == "f3d" ]]; then - outres="1p00" + varlist=${varlist_3d} + varlist_d=${varlist_3d_d} + ARC_RFCST_PROD_ATMOS="${ARC_RFCST_PROD_ATMOS_F3D}" fi - if [[ "${outtype}" == "f2d" ]]; then - if (( nh < FHMAX_HF_GFS )); then - outfreq=${FHOUT_HF_GFS} - else - outfreq=${FHOUT_GFS} - fi - elif [[ "${outtype}" == "f3d" ]]; then - outfreq=${FHOUT_GFS} + outdirpre="${subdata}/${outtype}" + if [[ ! -d "${outdirpre}" ]]; then + mkdir -p "${outdirpre}" fi - com_var="COMIN_ATMOS_GRIB_${outres}" - infile1="${!com_var}/${RUN}.t${cyc}z.pres_a.${outres}.f${fnh}.grib2" - infile2="${!com_var}/${RUN}.t${cyc}z.pres_b.${outres}.f${fnh}.grib2" - outfile="${outdirpre}/${RUN}.t${cyc}z.pres_a.${outres}.f${fnh}.grib2" - rm -f "${outfile}" #remove outfile if it already exists before extraction - - for infile in "${infile1}" "${infile2}"; do - if [[ -f "${infile}" ]]; then # check if input file exists before extraction - new_infile="${outdirpre}/$(basename "${infile}")_ext" - if ! cpfs "${infile}" "${new_infile}"; then - echo "FATAL ERROR: Failed to copy ${infile} to ${new_infile}." - exit 1 + nh=${FHMIN} + + while ((nh <= FHMAX_GFS)); do + fnh=$(printf "%3.3d" "${nh}") + + if [[ "${outtype}" == "f2d" ]]; then + if ((nh < FHMAX_HF_GFS)); then + outres="0p25" + else + outres="0p50" + fi + elif [[ "${outtype}" == "f3d" ]]; then + outres="1p00" fi - # shellcheck disable=SC2312 - ${WGRIB2} "${new_infile}" | grep -F -f "${varlist}" | ${WGRIB2} -i "${new_infile}" -append -grib "${outfile}" - else - echo "WARNING: ${infile} does not exist in ${com_dir}." - fi - done - - check_atmos "${infile1}" "${infile2}" "${varlist}" "${fnh}" - copy_to_comout "${outfile}" "${ARC_RFCST_PROD_ATMOS}" - - # Compute daily average for a subset of variables - if (( nh % 6 == 0 )) && (( nh != 0 )) && [[ "${outtype}" == "f3d" ]]; then - outfile=${subdata}/vartmp_raw_vari_ldy${dcnt}.grib2 - for infile in "${infile1}" "${infile2}"; do - if [[ -f "${infile}" ]]; then # check if input file exists before extraction - new_infile="${outdirpre}/$(basename "${infile}")_ext" - if ! cpfs "${infile}" "${new_infile}"; then - echo "FATAL ERROR: Failed to copy ${infile} to ${new_infile}." - exit 1 - fi - # shellcheck disable=SC2312 - ${WGRIB2} "${new_infile}" | grep -F -f "${varlist_d}" | ${WGRIB2} -i "${new_infile}" -append -grib "${outfile}" - else - echo "WARNING: ${infile} does not exist in ${com_dir}." + + if [[ "${outtype}" == "f2d" ]]; then + if ((nh < FHMAX_HF_GFS)); then + outfreq=${FHOUT_HF_GFS} + else + outfreq=${FHOUT_GFS} + fi + elif [[ "${outtype}" == "f3d" ]]; then + outfreq=${FHOUT_GFS} fi - done - if [[ ${fcnt} -eq 4 ]]; then - daily_avg_atmos "${outfile}" "${dcnt}" "${outres}" - copy_to_comout "${davg_file}" "${ARC_RFCST_PROD_ATMOS}" - fcnt=1 - dcnt=$(( dcnt + 1 )) - else - fcnt=$(( fcnt + 1 )) - fi # If at final lead hour of a given day - fi # if lead hour is divisible by 6 and outtype is f3d - - nh=$(( nh + outfreq )) - done # nh + + com_var="COMIN_ATMOS_GRIB_${outres}" + infile1="${!com_var}/${RUN}.t${cyc}z.pres_a.${outres}.f${fnh}.grib2" + infile2="${!com_var}/${RUN}.t${cyc}z.pres_b.${outres}.f${fnh}.grib2" + outfile="${outdirpre}/${RUN}.t${cyc}z.pres_a.${outres}.f${fnh}.grib2" + rm -f "${outfile}" #remove outfile if it already exists before extraction + + for infile in "${infile1}" "${infile2}"; do + if [[ -f "${infile}" ]]; then # check if input file exists before extraction + new_infile="${outdirpre}/$(basename "${infile}")_ext" + if ! cpfs "${infile}" "${new_infile}"; then + echo "FATAL ERROR: Failed to copy ${infile} to ${new_infile}." + exit 1 + fi + # shellcheck disable=SC2312 + ${WGRIB2} "${new_infile}" | grep -F -f "${varlist}" | ${WGRIB2} -i "${new_infile}" -append -grib "${outfile}" + else + echo "WARNING: ${infile} does not exist in ${com_dir}." + fi + done + + check_atmos "${infile1}" "${infile2}" "${varlist}" "${fnh}" + copy_to_comout "${outfile}" "${ARC_RFCST_PROD_ATMOS}" + + # Compute daily average for a subset of variables + if ((nh % 6 == 0)) && ((nh != 0)) && [[ "${outtype}" == "f3d" ]]; then + outfile=${subdata}/vartmp_raw_vari_ldy${dcnt}.grib2 + for infile in "${infile1}" "${infile2}"; do + if [[ -f "${infile}" ]]; then # check if input file exists before extraction + new_infile="${outdirpre}/$(basename "${infile}")_ext" + if ! cpfs "${infile}" "${new_infile}"; then + echo "FATAL ERROR: Failed to copy ${infile} to ${new_infile}." + exit 1 + fi + # shellcheck disable=SC2312 + ${WGRIB2} "${new_infile}" | grep -F -f "${varlist_d}" | ${WGRIB2} -i "${new_infile}" -append -grib "${outfile}" + else + echo "WARNING: ${infile} does not exist in ${com_dir}." + fi + done + if [[ ${fcnt} -eq 4 ]]; then + daily_avg_atmos "${outfile}" "${dcnt}" "${outres}" + copy_to_comout "${davg_file}" "${ARC_RFCST_PROD_ATMOS}" + fcnt=1 + dcnt=$((dcnt + 1)) + else + fcnt=$((fcnt + 1)) + fi # If at final lead hour of a given day + fi # if lead hour is divisible by 6 and outtype is f3d + + nh=$((nh + outfreq)) + done # nh done # f2d,f3d diff --git a/ush/bash_utils.sh b/ush/bash_utils.sh index fc69a79131a..48007623351 100755 --- a/ush/bash_utils.sh +++ b/ush/bash_utils.sh @@ -42,14 +42,14 @@ function declare_from_tmpl() { while getopts "rx" option; do opts="${opts}${option}" done - shift $((OPTIND-1)) + shift $((OPTIND - 1)) for input in "$@"; do IFS=':' read -ra args <<< "${input}" local com_var="${args[0]}" local template local value - if (( ${#args[@]} > 1 )); then + if ((${#args[@]} > 1)); then template="${args[1]}" else template="${com_var}_TMPL" @@ -99,7 +99,7 @@ function wait_for_file() { local sleep_interval=${2:-60} local max_tries=${3:-100} - for (( iter=0; iter [use2mobs]" - echo " : conv, oz, or sat" - echo " : date string to match" - echo " : where to write the new GSI info files into" - echo " [use2mobs]: (optional, only for conv, whether to use 2m observations) YES or NO" - exit 1 + echo "Usage: ${0} [use2mobs]" + echo " : conv, oz, or sat" + echo " : date string to match" + echo " : where to write the new GSI info files into" + echo " [use2mobs]: (optional, only for conv, whether to use 2m observations) YES or NO" + exit 1 fi # Function to get the most recent data available for the target obs. # If an empty string is returned, this represents an error. # Assumes the variable date_in is set. get_usedate() { - usedate="" - # Loop over files matching date pattern. - for datex in [1-2][0-9][0-9][0-9]*; do - # Skip for loop if there are no matches. - if [[ ! -e "${datex}" ]]; then - continue - fi - - if [[ ${date_in} -ge ${datex} ]]; then - usedate=${datex} - fi - done - - echo "${usedate}" + usedate="" + # Loop over files matching date pattern. + for datex in [1-2][0-9][0-9][0-9]*; do + # Skip for loop if there are no matches. + if [[ ! -e "${datex}" ]]; then + continue + fi + + if [[ ${date_in} -ge ${datex} ]]; then + usedate=${datex} + fi + done + + echo "${usedate}" } # Get the starting directory @@ -52,88 +52,87 @@ cd "${build_dir}" || exit 1 # Get the list of satellites available if [[ "${type_in}" != "conv" ]]; then - if [[ ! -f satellites ]]; then - echo "FATAL ERROR: Satellite list file 'satellites' not found in ${build_dir}!" - exit 1 - fi + if [[ ! -f satellites ]]; then + echo "FATAL ERROR: Satellite list file 'satellites' not found in ${build_dir}!" + exit 1 + fi - satellite_list=$(grep -Ev '^ *#|readme' satellites) + satellite_list=$(grep -Ev '^ *#|readme' satellites) - if [[ -z "${satellite_list}" ]]; then - echo "FATAL ERROR: No satellites found in the satellite file list!" - exit 1 - fi + if [[ -z "${satellite_list}" ]]; then + echo "FATAL ERROR: No satellites found in the satellite file list!" + exit 1 + fi fi # Filename to write the info to info_file="${write_dir}/${type_in}info" if [[ -f "${info_file}" ]]; then - rm -f "${info_file}" + rm -f "${info_file}" fi # Function to cycle through the list of satellites (oz or sat) and build the info file. build_info_file() { - while IFS= read -r sat - do - usedate="" - # Check that the satellite directory exists - if [[ ! -d "${sat}" ]]; then - echo "FATAL ERROR: Directory ${sat} does not exist!" - exit 1 - fi - - cd "${sat}" || exit 1 - - usedate=$(get_usedate) - - cd "${build_dir}" || exit 1 - - if [[ ${usedate} != "" ]]; then - cat "${sat}/${usedate}" >> "${info_file}" - else - echo "FATAL ERROR: No valid satellite info was found for satellite target '${sat}'!" - exit 1 - fi - done <<< "${satellite_list}" + while IFS= read -r sat; do + usedate="" + # Check that the satellite directory exists + if [[ ! -d "${sat}" ]]; then + echo "FATAL ERROR: Directory ${sat} does not exist!" + exit 1 + fi + + cd "${sat}" || exit 1 + + usedate=$(get_usedate) + + cd "${build_dir}" || exit 1 + + if [[ ${usedate} != "" ]]; then + cat "${sat}/${usedate}" >> "${info_file}" + else + echo "FATAL ERROR: No valid satellite info was found for satellite target '${sat}'!" + exit 1 + fi + done <<< "${satellite_list}" } case "${type_in}" in - conv) - usedate=$(get_usedate) - if [[ ${usedate} != "" ]]; then - if [[ ${use2mobs} == "YES" ]]; then - # Turn on 2m t,q obs over land - sed -e "s/t 181 0 -1/t 181 0 1/g" \ - -e "s/t 187 0 -1/t 187 0 1/g" \ - -e "s/q 181 0 -1/q 181 0 1/g" \ - -e "s/q 187 0 -1/q 187 0 1/g" "${usedate}" >> "${info_file}" - else - cat "${usedate}" >> "${info_file}" - fi - else - echo "FATAL ERROR: No valid conventional info was found!" - exit 1 - fi - ;; - oz) - # Header lines - { - echo '! For mls data, pressure and obs errors are pulled from bufr, so not listed here' - echo '! sens/instr/sat lev use pressure gross obs b_oz pg_oz' - echo '! error error variational qc' - } >> "${info_file}" - build_info_file - ;; - - sat) - # Header line - echo '!sensor/instr/sat chan iuse error error_cld ermax var_b var_pg icld_det icloud iaerosol' >> "${info_file}" - build_info_file - ;; - *) - echo "FATAL ERROR: Unknown info file type: '${type_in}'. Must be one of: conv, oz, sat" - exit 2 - ;; + conv) + usedate=$(get_usedate) + if [[ ${usedate} != "" ]]; then + if [[ ${use2mobs} == "YES" ]]; then + # Turn on 2m t,q obs over land + sed -e "s/t 181 0 -1/t 181 0 1/g" \ + -e "s/t 187 0 -1/t 187 0 1/g" \ + -e "s/q 181 0 -1/q 181 0 1/g" \ + -e "s/q 187 0 -1/q 187 0 1/g" "${usedate}" >> "${info_file}" + else + cat "${usedate}" >> "${info_file}" + fi + else + echo "FATAL ERROR: No valid conventional info was found!" + exit 1 + fi + ;; + oz) + # Header lines + { + echo '! For mls data, pressure and obs errors are pulled from bufr, so not listed here' + echo '! sens/instr/sat lev use pressure gross obs b_oz pg_oz' + echo '! error error variational qc' + } >> "${info_file}" + build_info_file + ;; + + sat) + # Header line + echo '!sensor/instr/sat chan iuse error error_cld ermax var_b var_pg icld_det icloud iaerosol' >> "${info_file}" + build_info_file + ;; + *) + echo "FATAL ERROR: Unknown info file type: '${type_in}'. Must be one of: conv, oz, sat" + exit 2 + ;; esac # Return to starting directory diff --git a/ush/detect_machine.sh b/ush/detect_machine.sh index ee6c2c2c79b..070904eb683 100755 --- a/ush/detect_machine.sh +++ b/ush/detect_machine.sh @@ -16,49 +16,49 @@ fi # First detect w/ hostname case $(hostname -f) in - adecflow0[12].acorn.wcoss2.ncep.noaa.gov) MACHINE_ID=acorn ;; ### acorn - alogin0[12].acorn.wcoss2.ncep.noaa.gov) MACHINE_ID=acorn ;; ### acorn - clogin0[1-9].cactus.wcoss2.ncep.noaa.gov) MACHINE_ID=wcoss2 ;; ### cactus01-9 - clogin10.cactus.wcoss2.ncep.noaa.gov) MACHINE_ID=wcoss2 ;; ### cactus10 - dlogin0[1-9].dogwood.wcoss2.ncep.noaa.gov) MACHINE_ID=wcoss2 ;; ### dogwood01-9 - dlogin10.dogwood.wcoss2.ncep.noaa.gov) MACHINE_ID=wcoss2 ;; ### dogwood10 + adecflow0[12].acorn.wcoss2.ncep.noaa.gov) MACHINE_ID=acorn ;; ### acorn + alogin0[12].acorn.wcoss2.ncep.noaa.gov) MACHINE_ID=acorn ;; ### acorn + clogin0[1-9].cactus.wcoss2.ncep.noaa.gov) MACHINE_ID=wcoss2 ;; ### cactus01-9 + clogin10.cactus.wcoss2.ncep.noaa.gov) MACHINE_ID=wcoss2 ;; ### cactus10 + dlogin0[1-9].dogwood.wcoss2.ncep.noaa.gov) MACHINE_ID=wcoss2 ;; ### dogwood01-9 + dlogin10.dogwood.wcoss2.ncep.noaa.gov) MACHINE_ID=wcoss2 ;; ### dogwood10 - gaea5[1-8]) MACHINE_ID=gaeac5 ;; ### gaea51-58 - gaea5[1-8].ncrc.gov) MACHINE_ID=gaeac5 ;; ### gaea51-58 + gaea5[1-8]) MACHINE_ID=gaeac5 ;; ### gaea51-58 + gaea5[1-8].ncrc.gov) MACHINE_ID=gaeac5 ;; ### gaea51-58 - gaea6[1-8]) MACHINE_ID=gaeac6 ;; ### gaea61-68 - gaea6[1-8].ncrc.gov) MACHINE_ID=gaeac6 ;; ### gaea61-68 + gaea6[1-8]) MACHINE_ID=gaeac6 ;; ### gaea61-68 + gaea6[1-8].ncrc.gov) MACHINE_ID=gaeac6 ;; ### gaea61-68 - hfe0[1-9]) MACHINE_ID=hera ;; ### hera01-09 - hfe1[0-2]) MACHINE_ID=hera ;; ### hera10-12 - hecflow01) MACHINE_ID=hera ;; ### heraecflow01 + hfe0[1-9]) MACHINE_ID=hera ;; ### hera01-09 + hfe1[0-2]) MACHINE_ID=hera ;; ### hera10-12 + hecflow01) MACHINE_ID=hera ;; ### heraecflow01 - ufe0[1-9]) MACHINE_ID=ursa ;; ### ursa01-09 - ufe1[0-6]) MACHINE_ID=ursa ;; ### ursa10-16 - uecflow01) MACHINE_ID=ursa ;; ### ursaecflow01 + ufe0[1-9]) MACHINE_ID=ursa ;; ### ursa01-09 + ufe1[0-6]) MACHINE_ID=ursa ;; ### ursa10-16 + uecflow01) MACHINE_ID=ursa ;; ### ursaecflow01 - s4-submit.ssec.wisc.edu) MACHINE_ID=s4 ;; ### s4 + s4-submit.ssec.wisc.edu) MACHINE_ID=s4 ;; ### s4 - fe[1-8]) MACHINE_ID=jet ;; ### jet01-8 - tfe[12]) MACHINE_ID=jet ;; ### tjet1-2 + fe[1-8]) MACHINE_ID=jet ;; ### jet01-8 + tfe[12]) MACHINE_ID=jet ;; ### tjet1-2 - Orion-login-[1-4].HPC.MsState.Edu) MACHINE_ID=orion ;; ### orion1-4 + Orion-login-[1-4].HPC.MsState.Edu) MACHINE_ID=orion ;; ### orion1-4 - [Hh]ercules-login-[1-4].[Hh][Pp][Cc].[Mm]s[Ss]tate.[Ee]du) MACHINE_ID=hercules ;; ### hercules1-4 + [Hh]ercules-login-[1-4].[Hh][Pp][Cc].[Mm]s[Ss]tate.[Ee]du) MACHINE_ID=hercules ;; ### hercules1-4 - login[1-4].stampede2.tacc.utexas.edu) MACHINE_ID=stampede ;; ### stampede1-4 + login[1-4].stampede2.tacc.utexas.edu) MACHINE_ID=stampede ;; ### stampede1-4 - login0[1-2].expanse.sdsc.edu) MACHINE_ID=expanse ;; ### expanse1-2 + login0[1-2].expanse.sdsc.edu) MACHINE_ID=expanse ;; ### expanse1-2 - discover3[1-5].prv.cube) MACHINE_ID=discover ;; ### discover31-35 - *) MACHINE_ID=UNKNOWN ;; # Unknown platform + discover3[1-5].prv.cube) MACHINE_ID=discover ;; ### discover31-35 + *) MACHINE_ID=UNKNOWN ;; # Unknown platform esac if [[ ${MACHINE_ID} == "UNKNOWN" ]]; then - case ${PW_CSP:-} in - "aws" | "google" | "azure") MACHINE_ID=noaacloud ;; - *) PW_CSP="UNKNOWN" - esac + case ${PW_CSP:-} in + "aws" | "google" | "azure") MACHINE_ID=noaacloud ;; + *) PW_CSP="UNKNOWN" ;; + esac fi # Overwrite auto-detect with MACHINE if set @@ -66,50 +66,50 @@ MACHINE_ID=${MACHINE:-${MACHINE_ID}} # If MACHINE_ID is no longer UNKNNOWN, return it if [[ "${MACHINE_ID}" != "UNKNOWN" ]]; then - # TODO: make this read-only when UPP#1308 is addressed. - declare -x MACHINE_ID # Should be -rx, but the UPP system needs Gaea C6 to be ID'd as "gaea" - return + # TODO: make this read-only when UPP#1308 is addressed. + declare -x MACHINE_ID # Should be -rx, but the UPP system needs Gaea C6 to be ID'd as "gaea" + return fi # Try searching based on paths since hostname may not match on compute nodes if [[ -d /lfs/h3 ]]; then - # We are on NOAA Cactus or Dogwood - MACHINE_ID=wcoss2 + # We are on NOAA Cactus or Dogwood + MACHINE_ID=wcoss2 elif [[ -d /lfs/h1 && ! -d /lfs/h3 ]]; then - # We are on NOAA TDS Acorn - MACHINE_ID=acorn + # We are on NOAA TDS Acorn + MACHINE_ID=acorn elif [[ -d /mnt/lfs5 ]]; then - # We are on NOAA Jet - MACHINE_ID=jet + # We are on NOAA Jet + MACHINE_ID=jet elif [[ -d /scratch3 ]]; then - # We are on NOAA Hera or Ursa - mount=$(findmnt -n -o SOURCE /apps) || true # /home doesn't exist on the GitHub runners - if [[ ${mount} =~ "ursa" ]]; then - MACHINE_ID=ursa - elif [[ ${mount} =~ "hera" ]]; then - MACHINE_ID=hera - else # Assume we are on the GitHub runners, which mock Hera - MACHINE_ID=hera - fi + # We are on NOAA Hera or Ursa + mount=$(findmnt -n -o SOURCE /apps) || true # /home doesn't exist on the GitHub runners + if [[ ${mount} =~ "ursa" ]]; then + MACHINE_ID=ursa + elif [[ ${mount} =~ "hera" ]]; then + MACHINE_ID=hera + else # Assume we are on the GitHub runners, which mock Hera + MACHINE_ID=hera + fi elif [[ -d /work ]]; then - # We are on MSU Orion or Hercules - mount=$(findmnt -n -o SOURCE /home) - if [[ -n "${mount+0}" && ${mount} =~ "hercules" ]]; then - MACHINE_ID=hercules - else - MACHINE_ID=orion - fi + # We are on MSU Orion or Hercules + mount=$(findmnt -n -o SOURCE /home) + if [[ -n "${mount+0}" && ${mount} =~ "hercules" ]]; then + MACHINE_ID=hercules + else + MACHINE_ID=orion + fi elif [[ -d /gpfs/f5 ]]; then - # We are on GAEAC5. - MACHINE_ID=gaeac5 + # We are on GAEAC5. + MACHINE_ID=gaeac5 elif [[ -d /gpfs/f6 ]]; then - # We are on GAEAC6. - MACHINE_ID=gaeac6 + # We are on GAEAC6. + MACHINE_ID=gaeac6 elif [[ -d /data/prod ]]; then - # We are on SSEC's S4 - MACHINE_ID=s4 + # We are on SSEC's S4 + MACHINE_ID=s4 else - echo WARNING: UNKNOWN PLATFORM 1>&2 + echo WARNING: UNKNOWN PLATFORM 1>&2 fi # TODO: Make this read-only when UPP#1308 is addressed. -declare -x MACHINE_ID # Should be -rx, but the UPP system needs Gaea C6 to be ID'd as "gaea" +declare -x MACHINE_ID # Should be -rx, but the UPP system needs Gaea C6 to be ID'd as "gaea" diff --git a/ush/extractvars_tools.sh b/ush/extractvars_tools.sh index f351441fa53..fe7a4d34a43 100644 --- a/ush/extractvars_tools.sh +++ b/ush/extractvars_tools.sh @@ -1,59 +1,59 @@ #! /usr/bin/env bash check_atmos() { - # Function to check if there are any missing parm variables in any of the input product grib2 files - # A warning will be displayed if there is a parm variable that cannot be found in any of the given input product grib2 files - infile1p=$1 - infile2p=$2 - varlistl=$3 - fnhl=$4 - requestedvar_in_allgrb2file="${subdata}/parmvarsingribfil.txt" - rm -f "${requestedvar_in_allgrb2file}" - touch "${requestedvar_in_allgrb2file}" - for infilep in "${infile1p}" "${infile2p}"; do - # It is permitted for an empty string to return if no parmlist vars are in infilep, therefore do not return exit 1 error - # shellcheck disable=SC2312 - ${WGRIB2} "${infilep}" | grep -F -f "${varlist}" >> "${requestedvar_in_allgrb2file}" || true - done - mapfile -t requestedvar_in_allgrb2file_arr < "${requestedvar_in_allgrb2file}" - while read -r vari; do - # shellcheck disable=SC2076 - if [[ ! ${requestedvar_in_allgrb2file_arr[*]} =~ "${vari}" ]] ;then - echo "WARNING: PARM VARIABLE (${vari}) is not available in pgrb and pgrb2b for f${fnhl}." - fi - done <"${varlistl}" + # Function to check if there are any missing parm variables in any of the input product grib2 files + # A warning will be displayed if there is a parm variable that cannot be found in any of the given input product grib2 files + infile1p=$1 + infile2p=$2 + varlistl=$3 + fnhl=$4 + requestedvar_in_allgrb2file="${subdata}/parmvarsingribfil.txt" + rm -f "${requestedvar_in_allgrb2file}" + touch "${requestedvar_in_allgrb2file}" + for infilep in "${infile1p}" "${infile2p}"; do + # It is permitted for an empty string to return if no parmlist vars are in infilep, therefore do not return exit 1 error + # shellcheck disable=SC2312 + ${WGRIB2} "${infilep}" | grep -F -f "${varlist}" >> "${requestedvar_in_allgrb2file}" || true + done + mapfile -t requestedvar_in_allgrb2file_arr < "${requestedvar_in_allgrb2file}" + while read -r vari; do + # shellcheck disable=SC2076 + if [[ ! ${requestedvar_in_allgrb2file_arr[*]} =~ "${vari}" ]]; then + echo "WARNING: PARM VARIABLE (${vari}) is not available in pgrb and pgrb2b for f${fnhl}." + fi + done < "${varlistl}" } daily_avg_atmos() { - # Function to calculate the 24-hr average of a grib2 file with atmospheric fields - # The input grib2 file must contain all the time records to be averaged (e.g. 6hr, 12hr, 18hr and 24hr record in one grib2 file) - outfile_p=$1 - dcnt_p=$2 - outres_p=$3 - fnd=$(printf "%2.2d" "${dcnt_p}") - davg_file=${outdirpre}/${RUN}.t${cyc}z.pgrb2.${outres_p}.24hr_avg.ldy${fnd} - vcnt=1 #count variables in varlist_d - while read -r vari; do - davgtmp=${subdata}/atmos_tmp.ldy${fnd}.${vcnt} - # shellcheck disable=SC2312 - ${WGRIB2} "${outfile_p}" | grep "${vari}" | ${WGRIB2} -i "${outfile_p}" -fcst_ave 6hr "${davgtmp}" - # shellcheck disable=SC2312 - ${WGRIB2} "${davgtmp}" | ${WGRIB2} -i "${davgtmp}" -append -grib "${davg_file}" - rm -f "${davgtmp}" - vcnt=$(( vcnt + 1 )) - done <"${varlist_d}" # variable + # Function to calculate the 24-hr average of a grib2 file with atmospheric fields + # The input grib2 file must contain all the time records to be averaged (e.g. 6hr, 12hr, 18hr and 24hr record in one grib2 file) + outfile_p=$1 + dcnt_p=$2 + outres_p=$3 + fnd=$(printf "%2.2d" "${dcnt_p}") + davg_file=${outdirpre}/${RUN}.t${cyc}z.pgrb2.${outres_p}.24hr_avg.ldy${fnd} + vcnt=1 #count variables in varlist_d + while read -r vari; do + davgtmp=${subdata}/atmos_tmp.ldy${fnd}.${vcnt} + # shellcheck disable=SC2312 + ${WGRIB2} "${outfile_p}" | grep "${vari}" | ${WGRIB2} -i "${outfile_p}" -fcst_ave 6hr "${davgtmp}" + # shellcheck disable=SC2312 + ${WGRIB2} "${davgtmp}" | ${WGRIB2} -i "${davgtmp}" -append -grib "${davg_file}" + rm -f "${davgtmp}" + vcnt=$((vcnt + 1)) + done < "${varlist_d}" # variable } copy_to_comout() { - # Function to copy the output file with the extracted product variables to a user-defined destination directory - rundir_outfile=$1 # output data file generated in RUNDIR - comout_dir=$2 # destination directory to which to copy the data file - if [[ -f "${rundir_outfile}" ]]; then - cpfs "${rundir_outfile}" "${comout_dir}" - else - export err=1 - err_exit "Output file (${rundir_outfile}) does not exist." - fi + # Function to copy the output file with the extracted product variables to a user-defined destination directory + rundir_outfile=$1 # output data file generated in RUNDIR + comout_dir=$2 # destination directory to which to copy the data file + if [[ -f "${rundir_outfile}" ]]; then + cpfs "${rundir_outfile}" "${comout_dir}" + else + export err=1 + err_exit "Output file (${rundir_outfile}) does not exist." + fi } declare -xf check_atmos diff --git a/ush/forecast_det.sh b/ush/forecast_det.sh index cb7a3eac601..602e7d473fb 100755 --- a/ush/forecast_det.sh +++ b/ush/forecast_det.sh @@ -2,149 +2,149 @@ # Disable variable not used warnings # shellcheck disable=SC2034 -UFS_det(){ - echo "SUB ${FUNCNAME[0]}: Run type determination for UFS" - - # Determine if the current cycle is a warm start (based on the availability of restarts) - if [[ -f "${COMIN_ATMOS_RESTART_PREV}/${model_start_date_current_cycle:0:8}.${model_start_date_current_cycle:8:2}0000.coupler.res" ]]; then - warm_start=".true." - fi - - # If restarts were not available, this is likely a cold start - if [[ "${warm_start}" == ".false." ]]; then - - # Since restarts are not available from the previous cycle, this is likely a cold start - # Ensure cold start ICs are present when warm start is not set - # TODO: add checks for other cold start ICs as well - if [[ ! -f "${COMIN_ATMOS_INPUT}/gfs_ctrl.nc" ]]; then - echo "FATAL ERROR: Cold start ICs are missing from '${COMIN_ATMOS_INPUT}'" - exit 1 - fi +UFS_det() { + echo "SUB ${FUNCNAME[0]}: Run type determination for UFS" - # Since warm start is false, we cannot do IAU - DOIAU="NO" - IAU_OFFSET=0 - model_start_date_current_cycle=${current_cycle} - - DO_LAND_IAU=".false." - - # It is still possible that a restart is available from a previous forecast attempt - # So we have to continue checking for restarts - fi - - # Lets assume this is was not run before and hence this is not a RERUN - RERUN="NO" - - # RERUN is only available for RUN=gfs|gefs. It is not available for RUN=gdas|enkfgdas|enkfgfs - if [[ "${RUN}" =~ "gdas" ]] || [[ "${RUN}" == "enkfgfs" ]]; then - echo "RERUN is not available for RUN='${RUN}'" - return 0 - fi - - # However, if this was run before, a DATArestart/FV3_RESTART must exist with data in it. - local file_array nrestarts - # shellcheck disable=SC2312 - mapfile -t file_array < <(find "${DATArestart}/FV3_RESTART" -name "????????.??0000.coupler.res" | sort) - nrestarts=${#file_array[@]} - if [[ ${nrestarts} -eq 0 ]]; then - echo "No restarts found in '${DATArestart}/FV3_RESTART', RERUN='${RERUN}'" - return 0 - else - echo "Found ${nrestarts} restarts in '${DATArestart}/FV3_RESTART' to check for RERUN" - ls -1 "${DATArestart}/FV3_RESTART/"????????.??0000.coupler.res - fi - - # Look in reverse order of file_array to determine available restart times - local ii filepath filename - local rdate seconds - local fv3_rst_ok cmeps_rst_ok mom6_rst_ok cice6_rst_ok ww3_rst_ok - local hdate hdatep1 fhout_ocn_by_2 - for (( ii=nrestarts-1; ii>=0; ii-- )); do - - filepath="${file_array[ii]}" - filename=$(basename "${filepath}") # Strip path from YYYYMMDD.HH0000.coupler.res - rdate="${filename:0:8}${filename:9:2}" # match YYYYMMDD and HH of YYYYMMDD.HH0000.coupler.res - - # Assume all is well; all restarts are available - fv3_rst_ok="YES" - cmeps_rst_ok="YES" - mom6_rst_ok="YES" - cice6_rst_ok="YES" - ww3_rst_ok="YES" - - # Check for FV3 restart availability - if [[ ! -f "${DATArestart}/FV3_RESTART/${rdate:0:8}.${rdate:8:2}0000.coupler.res" ]]; then - # TODO: add checks for other FV3 restarts as well - fv3_rst_ok="NO" + # Determine if the current cycle is a warm start (based on the availability of restarts) + if [[ -f "${COMIN_ATMOS_RESTART_PREV}/${model_start_date_current_cycle:0:8}.${model_start_date_current_cycle:8:2}0000.coupler.res" ]]; then + warm_start=".true." fi - # Check for CMEPS and MOM6 restart availability - if [[ "${cplflx}" == ".true." ]]; then - seconds=$(to_seconds "${rdate:8:2}0000") - if [[ ! -f "${DATArestart}/CMEPS_RESTART/ufs.cpld.cpl.r.${rdate:0:4}-${rdate:4:2}-${rdate:6:2}-${seconds}.nc" ]]; then - cmeps_rst_ok="NO" - fi - # TODO: add checks for other MOM6 restarts as well - if [[ ! -f "${DATArestart}/MOM6_RESTART/${rdate:0:8}.${rdate:8:2}0000.MOM.res.nc" ]]; then - mom6_rst_ok="NO" - else - # Also check for MOM6 history file availability - # TODO: SFS runs with 24-hr averaging of ocean output, which causes issues with restart checks, - # TODO: so we will skip them for now, and revisit this logic later - if [[ ${FHOUT_OCN} -le 6 ]]; then - fhout_ocn_by_2=$((FHOUT_OCN / 2)) - hdate=$(date -u -d "${rdate:0:8} ${rdate:8:2} + ${fhout_ocn_by_2} hours" +"%Y%m%d%H") - if [[ ! -f "${DATAoutput}/MOM6_OUTPUT/ocn_${hdate:0:4}_${hdate:4:2}_${hdate:6:2}_${hdate:8:2}.nc" ]]; then - mom6_rst_ok="NO" - else - # Also check for the next MOM6 history file (hdate + FHOUT_OCN hours) - hdatep1=$(date -u -d "${hdate:0:8} ${hdate:8:2} + ${FHOUT_OCN} hours" +"%Y%m%d%H") - if [[ ! -f "${DATAoutput}/MOM6_OUTPUT/ocn_${hdatep1:0:4}_${hdatep1:4:2}_${hdatep1:6:2}_${hdatep1:8:2}.nc" ]]; then - mom6_rst_ok="NO" - fi - fi + # If restarts were not available, this is likely a cold start + if [[ "${warm_start}" == ".false." ]]; then + + # Since restarts are not available from the previous cycle, this is likely a cold start + # Ensure cold start ICs are present when warm start is not set + # TODO: add checks for other cold start ICs as well + if [[ ! -f "${COMIN_ATMOS_INPUT}/gfs_ctrl.nc" ]]; then + echo "FATAL ERROR: Cold start ICs are missing from '${COMIN_ATMOS_INPUT}'" + exit 1 fi - fi - MOM6_RESTART_SETTING='r' - MOM6_INIT_FROM_Z=True - MOM6_WARMSTART_FILE="none" - MOM6_INIT_UV="zero" - ODA_INCUPD="False" - fi - # Check for CICE6 restart availability - if [[ "${cplice}" == ".true." ]]; then - if [[ ! -f "${DATArestart}/CICE_RESTART/cice_model.res.${rdate:0:4}-${rdate:4:2}-${rdate:6:2}-${seconds}.nc" ]]; then - cice6_rst_ok="NO" - fi + # Since warm start is false, we cannot do IAU + DOIAU="NO" + IAU_OFFSET=0 + model_start_date_current_cycle=${current_cycle} + + DO_LAND_IAU=".false." + + # It is still possible that a restart is available from a previous forecast attempt + # So we have to continue checking for restarts fi - # Check for WW3 restart availability - if [[ "${cplwav}" == ".true." ]]; then - if [[ ! -f "${DATArestart}/WW3_RESTART/${rdate:0:8}.${rdate:8:2}0000.restart.ww3.nc" ]]; then - ww3_rst_ok="NO" - fi + # Lets assume this is was not run before and hence this is not a RERUN + RERUN="NO" + + # RERUN is only available for RUN=gfs|gefs. It is not available for RUN=gdas|enkfgdas|enkfgfs + if [[ "${RUN}" =~ "gdas" ]] || [[ "${RUN}" == "enkfgfs" ]]; then + echo "RERUN is not available for RUN='${RUN}'" + return 0 fi - # Collective check - if [[ "${fv3_rst_ok}" == "YES" ]] \ - && [[ "${cmeps_rst_ok}" == "YES" ]] \ - && [[ "${mom6_rst_ok}" == "YES" ]] \ - && [[ "${cice6_rst_ok}" == "YES" ]] \ - && [[ "${ww3_rst_ok}" == "YES" ]]; then - RERUN="YES" - RERUN_DATE="${rdate}" - - # Check if RERUN_DATE is at/after model end time; if so, this will cause the model to crash - if [[ ${RERUN_DATE} -ge ${forecast_end_cycle} ]]; then - echo "FATAL ERROR Warm start detected, but restart date (${RERUN_DATE}) is at/after model end date (${forecast_end_cycle})" - exit 1 - fi - - warm_start=".true." - echo "All restarts found for '${RERUN_DATE}', RERUN='${RERUN}', warm_start='${warm_start}'" - break + # However, if this was run before, a DATArestart/FV3_RESTART must exist with data in it. + local file_array nrestarts + # shellcheck disable=SC2312 + mapfile -t file_array < <(find "${DATArestart}/FV3_RESTART" -name "????????.??0000.coupler.res" | sort) + nrestarts=${#file_array[@]} + if [[ ${nrestarts} -eq 0 ]]; then + echo "No restarts found in '${DATArestart}/FV3_RESTART', RERUN='${RERUN}'" + return 0 + else + echo "Found ${nrestarts} restarts in '${DATArestart}/FV3_RESTART' to check for RERUN" + ls -1 "${DATArestart}/FV3_RESTART/"????????.??0000.coupler.res fi - done # loop over nrestarts + # Look in reverse order of file_array to determine available restart times + local ii filepath filename + local rdate seconds + local fv3_rst_ok cmeps_rst_ok mom6_rst_ok cice6_rst_ok ww3_rst_ok + local hdate hdatep1 fhout_ocn_by_2 + for ((ii = nrestarts - 1; ii >= 0; ii--)); do + + filepath="${file_array[ii]}" + filename=$(basename "${filepath}") # Strip path from YYYYMMDD.HH0000.coupler.res + rdate="${filename:0:8}${filename:9:2}" # match YYYYMMDD and HH of YYYYMMDD.HH0000.coupler.res + + # Assume all is well; all restarts are available + fv3_rst_ok="YES" + cmeps_rst_ok="YES" + mom6_rst_ok="YES" + cice6_rst_ok="YES" + ww3_rst_ok="YES" + + # Check for FV3 restart availability + if [[ ! -f "${DATArestart}/FV3_RESTART/${rdate:0:8}.${rdate:8:2}0000.coupler.res" ]]; then + # TODO: add checks for other FV3 restarts as well + fv3_rst_ok="NO" + fi + + # Check for CMEPS and MOM6 restart availability + if [[ "${cplflx}" == ".true." ]]; then + seconds=$(to_seconds "${rdate:8:2}0000") + if [[ ! -f "${DATArestart}/CMEPS_RESTART/ufs.cpld.cpl.r.${rdate:0:4}-${rdate:4:2}-${rdate:6:2}-${seconds}.nc" ]]; then + cmeps_rst_ok="NO" + fi + # TODO: add checks for other MOM6 restarts as well + if [[ ! -f "${DATArestart}/MOM6_RESTART/${rdate:0:8}.${rdate:8:2}0000.MOM.res.nc" ]]; then + mom6_rst_ok="NO" + else + # Also check for MOM6 history file availability + # TODO: SFS runs with 24-hr averaging of ocean output, which causes issues with restart checks, + # TODO: so we will skip them for now, and revisit this logic later + if [[ "${FHOUT_OCN}" -le 6 ]]; then + fhout_ocn_by_2=$((FHOUT_OCN / 2)) + hdate=$(date -u -d "${rdate:0:8} ${rdate:8:2} + ${fhout_ocn_by_2} hours" +"%Y%m%d%H") + if [[ ! -f "${DATAoutput}/MOM6_OUTPUT/ocn_${hdate:0:4}_${hdate:4:2}_${hdate:6:2}_${hdate:8:2}.nc" ]]; then + mom6_rst_ok="NO" + else + # Also check for the next MOM6 history file (hdate + FHOUT_OCN hours) + hdatep1=$(date -u -d "${hdate:0:8} ${hdate:8:2} + ${FHOUT_OCN} hours" +"%Y%m%d%H") + if [[ ! -f "${DATAoutput}/MOM6_OUTPUT/ocn_${hdatep1:0:4}_${hdatep1:4:2}_${hdatep1:6:2}_${hdatep1:8:2}.nc" ]]; then + mom6_rst_ok="NO" + fi + fi + fi + fi + MOM6_RESTART_SETTING='r' + MOM6_INIT_FROM_Z=True + MOM6_WARMSTART_FILE="none" + MOM6_INIT_UV="zero" + ODA_INCUPD="False" + fi + + # Check for CICE6 restart availability + if [[ "${cplice}" == ".true." ]]; then + if [[ ! -f "${DATArestart}/CICE_RESTART/cice_model.res.${rdate:0:4}-${rdate:4:2}-${rdate:6:2}-${seconds}.nc" ]]; then + cice6_rst_ok="NO" + fi + fi + + # Check for WW3 restart availability + if [[ "${cplwav}" == ".true." ]]; then + if [[ ! -f "${DATArestart}/WW3_RESTART/${rdate:0:8}.${rdate:8:2}0000.restart.ww3.nc" ]]; then + ww3_rst_ok="NO" + fi + fi + + # Collective check + if [[ "${fv3_rst_ok}" == "YES" ]] && + [[ "${cmeps_rst_ok}" == "YES" ]] && + [[ "${mom6_rst_ok}" == "YES" ]] && + [[ "${cice6_rst_ok}" == "YES" ]] && + [[ "${ww3_rst_ok}" == "YES" ]]; then + RERUN="YES" + RERUN_DATE="${rdate}" + + # Check if RERUN_DATE is at/after model end time; if so, this will cause the model to crash + if [[ "${RERUN_DATE}" -ge "${forecast_end_cycle}" ]]; then + echo "FATAL ERROR Warm start detected, but restart date (${RERUN_DATE}) is at/after model end date (${forecast_end_cycle})" + exit 1 + fi + + warm_start=".true." + echo "All restarts found for '${RERUN_DATE}', RERUN='${RERUN}', warm_start='${warm_start}'" + break + fi + + done # loop over nrestarts } diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index f4b9b9f47c6..aee9fe9bced 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -4,1025 +4,1021 @@ # shellcheck disable=SC2034 # shellcheck disable=SC2178 FV3_postdet() { - echo "SUB ${FUNCNAME[0]}: Entering for RUN = ${RUN}" - - echo "warm_start = ${warm_start}" - echo "RERUN = ${RERUN}" - - - #============================================================================ - # First copy initial conditions - # cold start case - if [[ "${warm_start}" == ".false." ]]; then - - # Get list of FV3 cold start files - local file_list - file_list=$(FV3_coldstarts) - echo "Copying FV3 cold start files for 'RUN=${RUN}' at '${current_cycle}' from '${COMIN_ATMOS_INPUT}'" - local fv3_file - for fv3_file in ${file_list}; do - cpreq "${COMIN_ATMOS_INPUT}/${fv3_file}" "${DATA}/INPUT/${fv3_file}" - done - - # warm start case - elif [[ "${warm_start}" == ".true." ]]; then - - # Determine restart date and directory containing restarts - local restart_date restart_dir - if [[ "${RERUN}" == "YES" ]]; then - restart_date="${RERUN_DATE}" - restart_dir="${DATArestart}/FV3_RESTART" - else # "${RERUN}" == "NO" - restart_date="${model_start_date_current_cycle}" - restart_dir="${COMIN_ATMOS_RESTART_PREV}" - fi + echo "SUB ${FUNCNAME[0]}: Entering for RUN = ${RUN}" + + echo "warm_start = ${warm_start}" + echo "RERUN = ${RERUN}" + + #============================================================================ + # First copy initial conditions + # cold start case + if [[ "${warm_start}" == ".false." ]]; then + + # Get list of FV3 cold start files + local file_list + file_list=$(FV3_coldstarts) + echo "Copying FV3 cold start files for 'RUN=${RUN}' at '${current_cycle}' from '${COMIN_ATMOS_INPUT}'" + local fv3_file + for fv3_file in ${file_list}; do + cpreq "${COMIN_ATMOS_INPUT}/${fv3_file}" "${DATA}/INPUT/${fv3_file}" + done - # Get list of FV3 restart files - local file_list - file_list=$(FV3_restarts) - echo "Copying FV3 restarts for 'RUN=${RUN}' at '${restart_date}' from '${restart_dir}'" - local fv3_file restart_file - for fv3_file in ${file_list}; do - restart_file="${restart_date:0:8}.${restart_date:8:2}0000.${fv3_file}" - cpreq "${restart_dir}/${restart_file}" "${DATA}/INPUT/${fv3_file}" - done + # warm start case + elif [[ "${warm_start}" == ".true." ]]; then + + # Determine restart date and directory containing restarts + local restart_date restart_dir + if [[ "${RERUN}" == "YES" ]]; then + restart_date="${RERUN_DATE}" + restart_dir="${DATArestart}/FV3_RESTART" + else # "${RERUN}" == "NO" + restart_date="${model_start_date_current_cycle}" + restart_dir="${COMIN_ATMOS_RESTART_PREV}" + fi - if [[ "${RERUN}" == "YES" ]]; then - if [[ "${DO_SPPT:-}" == "YES" || "${DO_SKEB:-}" == "YES" || \ - "${DO_SHUM:-}" == "YES" || "${DO_LAND_PERT:-}" == "YES" ]]; then - stochini=".true." - file_list=$(stoch_restarts) - echo "Copying stochastic restarts for 'RUN=${RUN}' at '${restart_date}' from '${restart_dir}'" - for stoch_file in $(stoch_restarts); do - restart_file="${restart_date:0:8}.${restart_date:8:2}0000.${stoch_file}" - cpreq "${restart_dir}/${restart_file}" "${DATA}/INPUT/${stoch_file}" + # Get list of FV3 restart files + local file_list + file_list=$(FV3_restarts) + echo "Copying FV3 restarts for 'RUN=${RUN}' at '${restart_date}' from '${restart_dir}'" + local fv3_file restart_file + for fv3_file in ${file_list}; do + restart_file="${restart_date:0:8}.${restart_date:8:2}0000.${fv3_file}" + cpreq "${restart_dir}/${restart_file}" "${DATA}/INPUT/${fv3_file}" done - fi - else - # Replace sfc_data with sfcanl_data restart files from current cycle (if found) - local nn - for (( nn = 1; nn <= ntiles; nn++ )); do - if [[ -f "${COMIN_ATMOS_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.sfcanl_data.tile${nn}.nc" ]]; then - rm -f "${DATA}/INPUT/sfc_data.tile${nn}.nc" - cpreq "${COMIN_ATMOS_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.sfcanl_data.tile${nn}.nc" \ - "${DATA}/INPUT/sfc_data.tile${nn}.nc" - # GCAFS does not run the sfcanl, only GCDAS - elif [[ ${DO_AERO_FCST} == "YES" && -f "${COMIN_TRACER_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.sfcanl_data.tile${nn}.nc" ]]; then - rm -f "${DATA}/INPUT/sfc_data.tile${nn}.nc" - cpreq "${COMIN_TRACER_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.sfcanl_data.tile${nn}.nc" \ - "${DATA}/INPUT/sfc_data.tile${nn}.nc" + + if [[ "${RERUN}" == "YES" ]]; then + if [[ "${DO_SPPT:-}" == "YES" || "${DO_SKEB:-}" == "YES" || + "${DO_SHUM:-}" == "YES" || "${DO_LAND_PERT:-}" == "YES" ]]; then + stochini=".true." + file_list=$(stoch_restarts) + echo "Copying stochastic restarts for 'RUN=${RUN}' at '${restart_date}' from '${restart_dir}'" + for stoch_file in $(stoch_restarts); do + restart_file="${restart_date:0:8}.${restart_date:8:2}0000.${stoch_file}" + cpreq "${restart_dir}/${restart_file}" "${DATA}/INPUT/${stoch_file}" + done + fi else - echo "'sfcanl_data.tile1.nc' not found in '${COMIN_ATMOS_RESTART}', using 'sfc_data.tile1.nc'" - break + # Replace sfc_data with sfcanl_data restart files from current cycle (if found) + local nn + for ((nn = 1; nn <= ntiles; nn++)); do + if [[ -f "${COMIN_ATMOS_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.sfcanl_data.tile${nn}.nc" ]]; then + rm -f "${DATA}/INPUT/sfc_data.tile${nn}.nc" + cpreq "${COMIN_ATMOS_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.sfcanl_data.tile${nn}.nc" \ + "${DATA}/INPUT/sfc_data.tile${nn}.nc" + # GCAFS does not run the sfcanl, only GCDAS + elif [[ ${DO_AERO_FCST} == "YES" && -f "${COMIN_TRACER_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.sfcanl_data.tile${nn}.nc" ]]; then + rm -f "${DATA}/INPUT/sfc_data.tile${nn}.nc" + cpreq "${COMIN_TRACER_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.sfcanl_data.tile${nn}.nc" \ + "${DATA}/INPUT/sfc_data.tile${nn}.nc" + else + echo "'sfcanl_data.tile1.nc' not found in '${COMIN_ATMOS_RESTART}', using 'sfc_data.tile1.nc'" + break + fi + done + + # If aerosol analysis is to be done, replace fv_tracer with aeroanl_fv_tracer + # restart files from current cycle (if found) + if [[ "${DO_AERO_FCST}" == "YES" ]]; then + local nn + local use_anl_aero="YES" + for ((nn = 1; nn <= ntiles; nn++)); do + test_tracer_file="${COMIN_TRACER_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.aeroanl_fv_tracer.res.tile${nn}.nc" + if [[ ! -f "${test_tracer_file}" ]]; then + use_anl_aero="NO" + echo "WARNING: File ${test_tracer_file} does not exist, will not replace any files from the aerosol analysis" + break + fi + done + if [[ "${use_anl_aero}" == "YES" ]]; then + for ((nn = 1; nn <= ntiles; nn++)); do + rm -f "${DATA}/INPUT/fv_tracer.res.tile${nn}.nc" + cpreq "${COMIN_TRACER_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.aeroanl_fv_tracer.res.tile${nn}.nc" \ + "${DATA}/INPUT/fv_tracer.res.tile${nn}.nc" + done + fi # if [[ ${use_anl_aero} == "YES" ]]; then + + fi # [[ ${DO_AERO_FCST} == "YES" ]]; then + + fi # if [[ "${RERUN}" == "YES" ]]; then + + fi # if [[ "${warm_start}" == ".true." ]]; then + + # Regardless of warm_start or not, the sfc_data and orography files should be consistent + # Check for consistency + # TODO: the checker has a --fatal option, which is not used here. This needs to be decided how to handle. + if [[ "${CHECK_LAND_RESTART_OROG:-NO}" == "YES" ]]; then + "${USHgfs}/check_land_input_orography.py" \ + --input_dir "${DATA}/INPUT" --orog_dir "${DATA}/INPUT" + err=$? + if [[ ${err} -ne 0 ]]; then + echo "FATAL ERROR: check_land_input_orography.py returned error code ${err}, ABORT!" + exit "${err}" fi - done - - # If aerosol analysis is to be done, replace fv_tracer with aeroanl_fv_tracer - # restart files from current cycle (if found) - if [[ "${DO_AERO_FCST}" == "YES" ]]; then - local nn - local use_anl_aero="YES" - for (( nn = 1; nn <= ntiles; nn++ )); do - test_tracer_file="${COMIN_TRACER_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.aeroanl_fv_tracer.res.tile${nn}.nc" - if [[ ! -f "${test_tracer_file}" ]]; then - use_anl_aero="NO" - echo "WARNING: File ${test_tracer_file} does not exist, will not replace any files from the aerosol analysis" - break - fi - done - if [[ "${use_anl_aero}" == "YES" ]]; then - for (( nn = 1; nn <= ntiles; nn++ )); do - rm -f "${DATA}/INPUT/fv_tracer.res.tile${nn}.nc" - cpreq "${COMIN_TRACER_RESTART}/${restart_date:0:8}.${restart_date:8:2}0000.aeroanl_fv_tracer.res.tile${nn}.nc" \ - "${DATA}/INPUT/fv_tracer.res.tile${nn}.nc" - done - fi # if [[ ${use_anl_aero} == "YES" ]]; then - - fi # [[ ${DO_AERO_FCST} == "YES" ]]; then - - fi # if [[ "${RERUN}" == "YES" ]]; then - - fi # if [[ "${warm_start}" == ".true." ]]; then - - # Regardless of warm_start or not, the sfc_data and orography files should be consistent - # Check for consistency - # TODO: the checker has a --fatal option, which is not used here. This needs to be decided how to handle. - if [[ "${CHECK_LAND_RESTART_OROG:-NO}" == "YES" ]]; then - "${USHgfs}/check_land_input_orography.py" \ - --input_dir "${DATA}/INPUT" --orog_dir "${DATA}/INPUT" - err=$? - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: check_land_input_orography.py returned error code ${err}, ABORT!" - exit "${err}" - fi - fi - - #============================================================================ - # Determine increment files when doing cold start - if [[ "${warm_start}" == ".false." ]]; then - - if [[ "${USE_ATM_ENS_PERTURB_FILES:-NO}" == "YES" ]]; then - if (( MEMBER == 0 )); then - inc_files=() - else - inc_files=("increment.atm.i006.nc") - read_increment=".true." - res_latlon_dynamics="increment.atm.i006.nc" - fi - increment_file_on_native_grid=".false." - local increment_file - for inc_file in "${inc_files[@]}"; do - increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${inc_file}" - cpreq "${increment_file}" "${DATA}/INPUT/${inc_file}" - done fi - # Determine IAU and increment files when doing warm start - elif [[ "${warm_start}" == ".true." ]]; then + #============================================================================ + # Determine increment files when doing cold start + if [[ "${warm_start}" == ".false." ]]; then - #-------------------------------------------------------------------------- - if [[ "${RERUN}" == "YES" ]]; then + if [[ "${USE_ATM_ENS_PERTURB_FILES:-NO}" == "YES" ]]; then + if ((MEMBER == 0)); then + inc_files=() + else + inc_files=("increment.atm.i006.nc") + read_increment=".true." + res_latlon_dynamics="increment.atm.i006.nc" + fi + increment_file_on_native_grid=".false." + local increment_file + for inc_file in "${inc_files[@]}"; do + increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${inc_file}" + cpreq "${increment_file}" "${DATA}/INPUT/${inc_file}" + done + fi - local restart_fhr - restart_fhr=$(nhour "${RERUN_DATE}" "${current_cycle}") - IAU_FHROT=$((IAU_OFFSET + restart_fhr)) - if [[ "${DOIAU}" == "YES" ]]; then - IAUFHRS=-1 - IAU_DELTHRS=0 - IAU_INC_FILES="''" - fi - DO_LAND_IAU=".false." - #-------------------------------------------------------------------------- - else # "${RERUN}" == "NO" - - # Need a coupler.res that is consistent with the model start time - if [[ "${DOIAU:-NO}" == "YES" ]]; then - local model_start_time="${previous_cycle}" - else - local model_start_time="${current_cycle}" - fi - local model_current_time="${model_start_date_current_cycle}" - rm -f "${DATA}/INPUT/coupler.res" - cat >> "${DATA}/INPUT/coupler.res" << EOF + # Determine IAU and increment files when doing warm start + elif [[ "${warm_start}" == ".true." ]]; then + + #-------------------------------------------------------------------------- + if [[ "${RERUN}" == "YES" ]]; then + + local restart_fhr + restart_fhr=$(nhour "${RERUN_DATE}" "${current_cycle}") + IAU_FHROT=$((IAU_OFFSET + restart_fhr)) + if [[ "${DOIAU}" == "YES" ]]; then + IAUFHRS=-1 + IAU_DELTHRS=0 + IAU_INC_FILES="''" + fi + DO_LAND_IAU=".false." + #-------------------------------------------------------------------------- + else # "${RERUN}" == "NO" + + # Need a coupler.res that is consistent with the model start time + if [[ "${DOIAU:-NO}" == "YES" ]]; then + local model_start_time="${previous_cycle}" + else + local model_start_time="${current_cycle}" + fi + local model_current_time="${model_start_date_current_cycle}" + rm -f "${DATA}/INPUT/coupler.res" + cat >> "${DATA}/INPUT/coupler.res" << EOF 3 (Calendar: no_calendar=0, thirty_day_months=1, julian=2, gregorian=3, noleap=4) ${model_start_time:0:4} ${model_start_time:4:2} ${model_start_time:6:2} ${model_start_time:8:2} 0 0 Model start time: year, month, day, hour, minute, second ${model_current_time:0:4} ${model_current_time:4:2} ${model_current_time:6:2} ${model_current_time:8:2} 0 0 Current model time: year, month, day, hour, minute, second EOF - # Create a array of increment files - local inc_files inc_file iaufhrs iaufhr - if [[ "${DOIAU}" == "YES" ]]; then - # create an array of inc_files for each IAU hour - IFS=',' read -ra iaufhrs <<< "${IAUFHRS}" - inc_files=() - delimiter="" - IAU_INC_FILES="" - for iaufhr in "${iaufhrs[@]}"; do - if [[ "${DO_JEDIATMVAR:-NO}" == "YES" ]]; then - for tile in {1..6}; do - inc_file="jedi_increment.atm.i$(printf %03i "${iaufhr}").tile${tile}.nc" - inc_files+=("${inc_file}") - IAU_INC_FILES="${IAU_INC_FILES}${delimiter}'${inc_file}'" + # Create a array of increment files + local inc_files inc_file iaufhrs iaufhr + if [[ "${DOIAU}" == "YES" ]]; then + # create an array of inc_files for each IAU hour + IFS=',' read -ra iaufhrs <<< "${IAUFHRS}" + inc_files=() + delimiter="" + IAU_INC_FILES="" + for iaufhr in "${iaufhrs[@]}"; do + if [[ "${DO_JEDIATMVAR:-NO}" == "YES" ]]; then + for tile in {1..6}; do + inc_file="jedi_increment.atm.i$(printf %03i "${iaufhr}").tile${tile}.nc" + inc_files+=("${inc_file}") + IAU_INC_FILES="${IAU_INC_FILES}${delimiter}'${inc_file}'" + done + else + inc_file="increment.atm.i$(printf %03i "${iaufhr}").nc" + inc_files+=("${inc_file}") + IAU_INC_FILES="${IAU_INC_FILES}${delimiter}'${inc_file}'" + fi + + delimiter="," + done + else # "${DOIAU}" == "NO" + read_increment=".true." + + if [[ "${DO_JEDIATMVAR:-NO}" == "YES" ]]; then + inc_files=("jedi_increment.atm.i006.tile1.nc" "jedi_increment.atm.i006.tile2.nc" "jedi_increment.atm.i006.tile3.nc" "jedi_increment.atm.i006.tile4.nc" "jedi_increment.atm.i006.tile5.nc" "jedi_increment.atm.i006.tile6.nc") + increment_file_on_native_grid=".true." + res_latlon_dynamics="jedi_increment.atm.i006" + if [[ "${DO_JEDIATMENS:-NO}" == "NO" ]]; then + inc_files=("increment.atm.i006.nc") + res_latlon_dynamics="increment.atm.i006.nc" + increment_file_on_native_grid=".false." + fi + else + inc_files=("increment.atm.i006.nc") + res_latlon_dynamics="increment.atm.i006.nc" + increment_file_on_native_grid=".false." + fi + if [[ "${USE_ATM_ENS_PERTURB_FILES:-NO}" == "YES" ]]; then + # Control member has no perturbation + if ((MEMBER == 0)); then + inc_files=() + read_increment=".false." + res_latlon_dynamics='""' + fi + fi + fi + + if [[ "${RUN}" == "enkfgfs" ]] || [[ "${RUN}" == "enkfgdas" ]]; then + prefix_atminc="recentered_" + else + prefix_atminc="" + fi + + local increment_file + for inc_file in "${inc_files[@]}"; do + if [[ "${DO_JEDIATMVAR:-NO}" == "YES" ]]; then + increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${prefix_atminc}${inc_file}" + if [[ "${DO_JEDIATMENS:-NO}" == "NO" ]]; then + increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${prefix_atminc}${inc_file}" + fi + else + if [[ "${RUN}" == "gcafs" ]]; then + increment_file="${COMIN_ATMOS_ANALYSIS}/gcdas.t${cyc}z.${prefix_atminc}${inc_file}" + else + increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${prefix_atminc}${inc_file}" + fi + fi + cpreq "${increment_file}" "${DATA}/INPUT/${inc_file}" done - else - inc_file="increment.atm.i$(printf %03i "${iaufhr}").nc" - inc_files+=("${inc_file}") - IAU_INC_FILES="${IAU_INC_FILES}${delimiter}'${inc_file}'" - fi - delimiter="," - done - else # "${DOIAU}" == "NO" - read_increment=".true." - - if [[ "${DO_JEDIATMVAR:-NO}" == "YES" ]]; then - inc_files=("jedi_increment.atm.i006.tile1.nc" "jedi_increment.atm.i006.tile2.nc" "jedi_increment.atm.i006.tile3.nc" "jedi_increment.atm.i006.tile4.nc" "jedi_increment.atm.i006.tile5.nc" "jedi_increment.atm.i006.tile6.nc") - increment_file_on_native_grid=".true." - res_latlon_dynamics="jedi_increment.atm.i006" - if [[ "${DO_JEDIATMENS:-NO}" == "NO" ]]; then - inc_files=("increment.atm.i006.nc") - res_latlon_dynamics="increment.atm.i006.nc" - increment_file_on_native_grid=".false." - fi - else - inc_files=("increment.atm.i006.nc") - res_latlon_dynamics="increment.atm.i006.nc" - increment_file_on_native_grid=".false." - fi - if [[ "${USE_ATM_ENS_PERTURB_FILES:-NO}" == "YES" ]]; then - # Control member has no perturbation - if (( MEMBER == 0 )); then - inc_files=() - read_increment=".false." - res_latlon_dynamics='""' - fi - fi - fi - - if [[ "${RUN}" = "enkfgfs" ]] || [[ "${RUN}" = "enkfgdas" ]]; then - prefix_atminc="recentered_" - else - prefix_atminc="" - fi - - local increment_file - for inc_file in "${inc_files[@]}"; do - if [[ "${DO_JEDIATMVAR:-NO}" == "YES" ]]; then - increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${prefix_atminc}${inc_file}" - if [[ "${DO_JEDIATMENS:-NO}" == "NO" ]]; then - increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${prefix_atminc}${inc_file}" - fi - else - if [[ "${RUN}" == "gcafs" ]]; then - increment_file="${COMIN_ATMOS_ANALYSIS}/gcdas.t${cyc}z.${prefix_atminc}${inc_file}" - else - increment_file="${COMIN_ATMOS_ANALYSIS}/${RUN}.t${cyc}z.${prefix_atminc}${inc_file}" - fi + # Land IAU increments: sfc_inc in FV3 grid, all timesteps in one file per tile + if [[ ${DO_LAND_IAU} == ".true." ]]; then + local TN sfc_increment_file + for TN in $(seq 1 "${ntiles}"); do + sfc_increment_file="${COMIN_ATMOS_ANALYSIS}/increment.sfc.tile${TN}.nc" + if [[ ! -f "${sfc_increment_file}" ]]; then + export err=1 + err_exit "FATAL ERROR: DO_LAND_IAU=${DO_LAND_IAU}, but missing increment file ${sfc_increment_file}, ABORT!" + else + cpreq "${sfc_increment_file}" "${DATA}/INPUT/sfc_inc.tile${TN}.nc" + fi + done + fi + fi # if [[ "${RERUN}" == "YES" ]]; then + #-------------------------------------------------------------------------- + fi # if [[ "${warm_start}" == ".true." ]]; then + #============================================================================ + + #============================================================================ + # If doing IAU, change forecast hours + if [[ "${DOIAU:-NO}" == "YES" ]]; then + FHMAX=$((FHMAX + 6)) + if [[ ${FHMAX_HF} -gt 0 ]]; then + FHMAX_HF=$((FHMAX_HF + 6)) fi - cpreq "${increment_file}" "${DATA}/INPUT/${inc_file}" - done - - # Land IAU increments: sfc_inc in FV3 grid, all timesteps in one file per tile - if [[ ${DO_LAND_IAU} = ".true." ]]; then - local TN sfc_increment_file - for TN in $(seq 1 "${ntiles}"); do - sfc_increment_file="${COMIN_ATMOS_ANALYSIS}/increment.sfc.tile${TN}.nc" - if [[ ! -f "${sfc_increment_file}" ]]; then - echo "FATAL ERROR: DO_LAND_IAU=${DO_LAND_IAU}, but missing increment file ${sfc_increment_file}, ABORT!" - exit 1 - else - cpreq "${sfc_increment_file}" "${DATA}/INPUT/sfc_inc.tile${TN}.nc" - fi - done + fi + #============================================================================ - fi + #============================================================================ + # If warm starting from restart files, set the following flags + if [[ "${warm_start}" == ".true." ]]; then - fi # if [[ "${RERUN}" == "YES" ]]; then - #-------------------------------------------------------------------------- + # start from restart file + nggps_ic=".false." + ncep_ic=".false." + external_ic=".false." + mountain=".true." - fi # if [[ "${warm_start}" == ".true." ]]; then - #============================================================================ + # restarts contain non-hydrostatic state + if [[ "${TYPE}" == "nh" ]]; then + make_nh=".false." + fi - #============================================================================ - # If doing IAU, change forecast hours - if [[ "${DOIAU:-NO}" == "YES" ]]; then - FHMAX=$((FHMAX + 6)) - if (( FHMAX_HF > 0 )); then - FHMAX_HF=$((FHMAX_HF + 6)) - fi - fi - #============================================================================ - - #============================================================================ - # If warm starting from restart files, set the following flags - if [[ "${warm_start}" == ".true." ]]; then - - # start from restart file - nggps_ic=".false." - ncep_ic=".false." - external_ic=".false." - mountain=".true." - - # restarts contain non-hydrostatic state - if [[ "${TYPE}" == "nh" ]]; then - make_nh=".false." + # do not pre-condition the solution + na_init=0 + + fi # warm_start == .true. + #============================================================================ + + #============================================================================ + if [[ "${QUILTING}" == ".true." ]] && [[ "${OUTPUT_GRID}" == "gaussian_grid" ]]; then + local FH2 FH3 + for fhr in ${FV3_OUTPUT_FH}; do + FH3=$(printf %03i "${fhr}") + FH2=$(printf %02i "${fhr}") + ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.atm.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/atmf${FH3}.nc" + ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.sfc.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/sfcf${FH3}.nc" + ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.log.f${FH3}.txt" "${DATAoutput}/FV3ATM_OUTPUT/log.atm.f${FH3}" + if [[ "${DO_JEDIATMVAR:-}" == "YES" || "${DO_HISTORY_FILE_ON_NATIVE_GRID:-"NO"}" == "YES" ]]; then + ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.csg_atm.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/cubed_sphere_grid_atmf${FH3}.nc" + ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.csg_sfc.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/cubed_sphere_grid_sfcf${FH3}.nc" + fi + if [[ "${WRITE_DOPOST}" == ".true." ]]; then + ${NLN} "${COMOUT_ATMOS_MASTER}/${RUN}.t${cyc}z.master.f${FH3}.grib2" "${DATAoutput}/FV3ATM_OUTPUT/GFSPRS.GrbF${FH2}" + ${NLN} "${COMOUT_ATMOS_MASTER}/${RUN}.t${cyc}z.sflux.f${FH3}.grib2" "${DATAoutput}/FV3ATM_OUTPUT/GFSFLX.GrbF${FH2}" + if [[ "${DO_NEST:-NO}" == "YES" ]]; then + ${NLN} "${COMOUT_ATMOS_MASTER}/${RUN}.t${cyc}z.master.nest.f${FH3}.grib2" "${DATAoutput}/FV3ATM_OUTPUT/GFSPRS.GrbF${FH2}.nest02" + ${NLN} "${COMOUT_ATMOS_MASTER}/${RUN}.t${cyc}z.sflux.nest.f${FH3}.grib2" "${DATAoutput}/FV3ATM_OUTPUT/GFSFLX.GrbF${FH2}.nest02" + fi + fi + done fi - - # do not pre-condition the solution - na_init=0 - - fi # warm_start == .true. - #============================================================================ - - #============================================================================ - if [[ "${QUILTING}" = ".true." ]] && [[ "${OUTPUT_GRID}" = "gaussian_grid" ]]; then - local FH2 FH3 - for fhr in ${FV3_OUTPUT_FH}; do - FH3=$(printf %03i "${fhr}") - FH2=$(printf %02i "${fhr}") - ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.atm.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/atmf${FH3}.nc" - ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.sfc.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/sfcf${FH3}.nc" - ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.log.f${FH3}.txt" "${DATAoutput}/FV3ATM_OUTPUT/log.atm.f${FH3}" - if [[ "${DO_JEDIATMVAR:-}" == "YES" || "${DO_HISTORY_FILE_ON_NATIVE_GRID:-"NO"}" == "YES" ]]; then - ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.csg_atm.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/cubed_sphere_grid_atmf${FH3}.nc" - ${NLN} "${COMOUT_ATMOS_HISTORY}/${RUN}.t${cyc}z.csg_sfc.f${FH3}.nc" "${DATAoutput}/FV3ATM_OUTPUT/cubed_sphere_grid_sfcf${FH3}.nc" - fi - if [[ "${WRITE_DOPOST}" == ".true." ]]; then - ${NLN} "${COMOUT_ATMOS_MASTER}/${RUN}.t${cyc}z.master.f${FH3}.grib2" "${DATAoutput}/FV3ATM_OUTPUT/GFSPRS.GrbF${FH2}" - ${NLN} "${COMOUT_ATMOS_MASTER}/${RUN}.t${cyc}z.sflux.f${FH3}.grib2" "${DATAoutput}/FV3ATM_OUTPUT/GFSFLX.GrbF${FH2}" - if [[ "${DO_NEST:-NO}" == "YES" ]]; then - ${NLN} "${COMOUT_ATMOS_MASTER}/${RUN}.t${cyc}z.master.nest.f${FH3}.grib2" "${DATAoutput}/FV3ATM_OUTPUT/GFSPRS.GrbF${FH2}.nest02" - ${NLN} "${COMOUT_ATMOS_MASTER}/${RUN}.t${cyc}z.sflux.nest.f${FH3}.grib2" "${DATAoutput}/FV3ATM_OUTPUT/GFSFLX.GrbF${FH2}.nest02" + #============================================================================ + restart_interval=${restart_interval:-${FHMAX}} + # restart_interval = 0 implies write restart at the END of the forecast i.e. at FHMAX + # Convert restart interval into an explicit list for CMEPS/CICE/MOM6/WW3 + # Note, this must be computed after determination IAU in forecast_det and fhrot. + if [[ ${restart_interval} -eq 0 ]]; then + if [[ "${DOIAU:-NO}" == "YES" ]]; then + FV3_RESTART_FH=$((FHMAX + assim_freq)) + else + FV3_RESTART_FH=("${FHMAX}") fi - fi - done - fi - #============================================================================ - restart_interval=${restart_interval:-${FHMAX}} - # restart_interval = 0 implies write restart at the END of the forecast i.e. at FHMAX - # Convert restart interval into an explicit list for CMEPS/CICE/MOM6/WW3 - # Note, this must be computed after determination IAU in forecast_det and fhrot. - if (( restart_interval == 0 )); then - if [[ "${DOIAU:-NO}" == "YES" ]]; then - FV3_RESTART_FH=$(( FHMAX + assim_freq )) - else - FV3_RESTART_FH=("${FHMAX}") - fi - else - if [[ "${DOIAU:-NO}" == "YES" ]]; then - if [[ "${MODE}" = "cycled" && "${SDATE}" = "${PDY}${cyc}" && ${EXP_WARM_START} = ".false." ]]; then - local restart_interval_start=${restart_interval} - local restart_interval_end=${FHMAX} - else - local restart_interval_start=$(( restart_interval + assim_freq )) - local restart_interval_end=$(( FHMAX + assim_freq )) - fi else - local restart_interval_start=${restart_interval} - local restart_interval_end=${FHMAX} + if [[ "${DOIAU:-NO}" == "YES" ]]; then + if [[ "${MODE}" = "cycled" && "${SDATE}" = "${PDY}${cyc}" && ${EXP_WARM_START} = ".false." ]]; then + local restart_interval_start=${restart_interval} + local restart_interval_end=${FHMAX} + else + local restart_interval_start=$((restart_interval + assim_freq)) + local restart_interval_end=$((FHMAX + assim_freq)) + fi + else + local restart_interval_start=${restart_interval} + local restart_interval_end=${FHMAX} + fi + FV3_RESTART_FH="$(seq -s ' ' "${restart_interval_start}" "${restart_interval}" "${restart_interval_end}")" fi - FV3_RESTART_FH="$(seq -s ' ' "${restart_interval_start}" "${restart_interval}" "${restart_interval_end}")" - fi - export FV3_RESTART_FH - #============================================================================ + export FV3_RESTART_FH + #============================================================================ } FV3_nml() { - # namelist output for a certain component - echo "SUB ${FUNCNAME[0]}: Creating name lists and model configure file for FV3" - - source "${USHgfs}/parsing_namelists_FV3.sh" - source "${USHgfs}/parsing_model_configure_FV3.sh" - - # Call the appropriate namelist functions - if [[ "${DO_NEST:-NO}" == "YES" ]] ; then - source "${USHgfs}/parsing_namelists_FV3_nest.sh" - FV3_namelists_nest global - FV3_namelists_nest nest - else - FV3_namelists - fi - FV3_model_configure - - echo "SUB ${FUNCNAME[0]}: FV3 name lists and model configure file created" + # namelist output for a certain component + echo "SUB ${FUNCNAME[0]}: Creating name lists and model configure file for FV3" + + source "${USHgfs}/parsing_namelists_FV3.sh" + source "${USHgfs}/parsing_model_configure_FV3.sh" + + # Call the appropriate namelist functions + if [[ "${DO_NEST:-NO}" == "YES" ]]; then + source "${USHgfs}/parsing_namelists_FV3_nest.sh" + FV3_namelists_nest global + FV3_namelists_nest nest + else + FV3_namelists + fi + FV3_model_configure + + echo "SUB ${FUNCNAME[0]}: FV3 name lists and model configure file created" } FV3_out() { - echo "SUB ${FUNCNAME[0]}: copying output data for FV3" - - # Copy configuration files - cpfs "${DATA}/input.nml" "${COMOUT_CONF}/ufs.input.nml" - cpfs "${DATA}/model_configure" "${COMOUT_CONF}/ufs.model_configure" - cpfs "${DATA}/ufs.configure" "${COMOUT_CONF}/ufs.ufs.configure" - cpfs "${DATA}/diag_table" "${COMOUT_CONF}/ufs.diag_table" - - - # Determine the dates for restart files to be copied to COM - local restart_date restart_dates - restart_dates=() - - case ${RUN} in - gdas|enkfgdas|enkfgfs|enkfgcafs|gcdas) # Copy restarts in the assimilation window for RUN=gdas|enkfgdas|enkfgfs - restart_date="${model_start_date_next_cycle}" - while (( restart_date <= forecast_end_cycle )); do - restart_dates+=("${restart_date:0:8}.${restart_date:8:2}0000") - restart_date=$(date --utc -d "${restart_date:0:8} ${restart_date:8:2} + ${restart_interval} hours" +%Y%m%d%H) - done - ;; - gfs|gefs|sfs|gcafs) # Copy restarts at the end of the forecast segment for RUN=gfs|gefs|sfs|gcafs - if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then - restart_dates+=("${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000") - fi - ;; - *) - echo "FATAL ERROR: Not sure how to copy restart files for RUN ${RUN}" - exit 25 - ;; - esac - - ### Check that there are restart files to copy - if [[ ${#restart_dates[@]} -gt 0 ]]; then - # Get list of FV3 restart files - local file_list fv3_file - file_list=$(FV3_restarts) - - # Copy restarts for the dates collected above to COM - for restart_date in "${restart_dates[@]}"; do - echo "Copying FV3 restarts for 'RUN=${RUN}' at ${restart_date}" - for fv3_file in ${file_list}; do - cpfs "${DATArestart}/FV3_RESTART/${restart_date}.${fv3_file}" \ - "${COMOUT_ATMOS_RESTART}/${restart_date}.${fv3_file}" - done - done + echo "SUB ${FUNCNAME[0]}: copying output data for FV3" + + # Copy configuration files + cpfs "${DATA}/input.nml" "${COMOUT_CONF}/ufs.input.nml" + cpfs "${DATA}/model_configure" "${COMOUT_CONF}/ufs.model_configure" + cpfs "${DATA}/ufs.configure" "${COMOUT_CONF}/ufs.ufs.configure" + cpfs "${DATA}/diag_table" "${COMOUT_CONF}/ufs.diag_table" + + # Determine the dates for restart files to be copied to COM + local restart_date restart_dates + restart_dates=() + + case ${RUN} in + gdas | enkfgdas | enkfgfs | enkfgcafs | gcdas) # Copy restarts in the assimilation window for RUN=gdas|enkfgdas|enkfgfs + restart_date="${model_start_date_next_cycle}" + while ((restart_date <= forecast_end_cycle)); do + restart_dates+=("${restart_date:0:8}.${restart_date:8:2}0000") + restart_date=$(date --utc -d "${restart_date:0:8} ${restart_date:8:2} + ${restart_interval} hours" +%Y%m%d%H) + done + ;; + gfs | gefs | sfs | gcafs) # Copy restarts at the end of the forecast segment for RUN=gfs|gefs|sfs|gcafs + if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then + restart_dates+=("${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000") + fi + ;; + *) + echo "FATAL ERROR: Not sure how to copy restart files for RUN ${RUN}" + exit 25 + ;; + esac + + ### Check that there are restart files to copy + if [[ ${#restart_dates[@]} -gt 0 ]]; then + # Get list of FV3 restart files + local file_list fv3_file + file_list=$(FV3_restarts) + + # Copy restarts for the dates collected above to COM + for restart_date in "${restart_dates[@]}"; do + echo "Copying FV3 restarts for 'RUN=${RUN}' at ${restart_date}" + for fv3_file in ${file_list}; do + cpfs "${DATArestart}/FV3_RESTART/${restart_date}.${fv3_file}" \ + "${COMOUT_ATMOS_RESTART}/${restart_date}.${fv3_file}" + done + done - echo "SUB ${FUNCNAME[0]}: Output data for FV3 copied" - fi + echo "SUB ${FUNCNAME[0]}: Output data for FV3 copied" + fi } # Disable variable not used warnings # shellcheck disable=SC2034 WW3_postdet() { - echo "SUB ${FUNCNAME[0]}: Linking input data for WW3" - # Copy initial condition files: - local restart_date restart_dir - if [[ "${RERUN}" == "YES" ]]; then - restart_date="${RERUN_DATE}" - restart_dir="${DATArestart}/WW3_RESTART" - else - restart_date="${model_start_date_current_cycle}" - restart_dir="${COMIN_WAVE_RESTART_PREV}" - fi - - echo "Copying WW3 restarts for 'RUN=${RUN}' at '${restart_date}' from '${restart_dir}'" - - local ww3_restart_file ww3_restart_dest_file seconds - seconds=$(to_seconds "${restart_date:8:2}0000") # convert HHMMSS to seconds - ww3_restart_file="${restart_dir}/${restart_date:0:8}.${restart_date:8:2}0000.restart.ww3" - ww3_restart_dest_file="ufs.cpld.ww3.r.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}" - if [[ -s "${ww3_restart_file}.nc" ]]; then # First check to see if netcdf restart exists: - export WW3_restart_from_binary=false - cpreq "${ww3_restart_file}.nc" "${DATA}/${ww3_restart_dest_file}.nc" - elif [[ -s "${ww3_restart_file}" ]]; then # If not, check to see if binary restart exists: - export WW3_restart_from_binary=true - cpreq "${ww3_restart_file}" "${DATA}/${ww3_restart_dest_file}" - else - if [[ "${RERUN}" == "YES" ]] || [[ -f "${DATA}/ufs.cpld.cpl.r.nc" ]]; then # The || part requires CMEPS_postdet to be called before WW3_postdet - # In the case of a RERUN, the WW3 restart file is required - # In the case of runtype=continue, if no wave restart when using PIO, the model will fail - echo "FATAL ERROR: WW3 binary | netcdf restart file '${ww3_restart_file}' | '${ww3_restart_file}.nc' not found for RERUN='${RERUN}' or runtype=continue, ABORT!" - exit 1 + echo "SUB ${FUNCNAME[0]}: Linking input data for WW3" + # Copy initial condition files: + local restart_date restart_dir + if [[ "${RERUN}" == "YES" ]]; then + restart_date="${RERUN_DATE}" + restart_dir="${DATArestart}/WW3_RESTART" else - export WW3_restart_from_binary=false - echo "WARNING: WW3 binary | netcdf restart file '${ww3_restart_file}' | '${ww3_restart_file}.nc' not found for warm_start='${warm_start}', will start from rest!" + restart_date="${model_start_date_current_cycle}" + restart_dir="${COMIN_WAVE_RESTART_PREV}" fi - fi - - local first_ww3_restart_out - first_ww3_restart_out=$(date --utc -d "${restart_date:0:8} ${restart_date:8:2} + ${restart_interval} hours" +%Y%m%d%H) - if [[ "${DOIAU:-NO}" == "YES" ]]; then - first_ww3_restart_out=$(date --utc -d "${first_ww3_restart_out:0:8} ${first_ww3_restart_out:8:2} + ${half_window} hours" +%Y%m%d%H) - fi - - # Link restart files to their expected names in DATArestart/WW3_RESTART - # TODO: Have the UFSWM write out the WW3 restart files in the expected format of 'YYYYMMDD.HHmmSS.restart.ww3.nc' - local cwd vdate ww3_ufs_restart_file ww3_netcdf_restart_file - cwd="${PWD}" - cd "${DATArestart}/WW3_RESTART" || exit 1 - for (( vdate = first_ww3_restart_out; vdate <= forecast_end_cycle; - vdate = $(date --utc -d "${vdate:0:8} ${vdate:8:2} + ${restart_interval} hours" +%Y%m%d%H) )); do - seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds - ww3_ufs_restart_file="ufs.cpld.ww3.r.${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${seconds}.nc" # UFS restart file name - ww3_netcdf_restart_file="${vdate:0:8}.${vdate:8:2}0000.restart.ww3.nc" # WW3 restart file name in COM - ${NLN} "${ww3_netcdf_restart_file}" "${ww3_ufs_restart_file}" - done - - # TODO: link GEFS restart for next cycle IC - #if [[ "${RUN}" == "gefs" ]]; then - # vdate=${model_start_date_next_cycle} - # seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds - # ww3_ufs_restart_file="ufs.cpld.ww3.r.${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${seconds}.nc" - # ww3_netcdf_restart_file="${vdate:0:8}.${vdate:8:2}0000.restart.ww3.nc" - # ${NLN} "${ww3_netcdf_restart_file}" "${ww3_ufs_restart_file}" - #fi - cd "${cwd}" || exit 1 - - # Link output files - ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.${waveGRD}.${PDY}${cyc}.log" "log.ww3" - - # Loop for gridded output (uses FHINC) - local fhr fhr3 FHINC - fhr=${FHMIN_WAV} - if [[ ${FHMAX_HF_WAV} -gt 0 && ${FHOUT_HF_WAV} -gt 0 && ${fhr} -lt ${FHMAX_HF_WAV} ]]; then - fhinc=${FHOUT_HF_WAV} - else - fhinc=${FHOUT_WAV} - fi - while [[ ${fhr} -le ${FHMAX_WAV} ]]; do - fhr3=$(printf '%03d' "${fhr}") - vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d.%H0000) - ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.${waveGRD}.f${fhr3}.bin" "${DATAoutput}/WW3_OUTPUT/${vdate}.out_grd.ww3" - ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.${waveGRD}.f${fhr3}.log" "${DATAoutput}/WW3_OUTPUT/log.${vdate}.out_grd.ww3.txt" - - if [[ ${fhr} -ge ${FHMAX_HF_WAV} ]]; then - fhinc=${FHOUT_WAV} + + echo "Copying WW3 restarts for 'RUN=${RUN}' at '${restart_date}' from '${restart_dir}'" + + local ww3_restart_file ww3_restart_dest_file seconds + seconds=$(to_seconds "${restart_date:8:2}0000") # convert HHMMSS to seconds + ww3_restart_file="${restart_dir}/${restart_date:0:8}.${restart_date:8:2}0000.restart.ww3" + ww3_restart_dest_file="ufs.cpld.ww3.r.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}" + if [[ -s "${ww3_restart_file}.nc" ]]; then # First check to see if netcdf restart exists: + export WW3_restart_from_binary=false + cpreq "${ww3_restart_file}.nc" "${DATA}/${ww3_restart_dest_file}.nc" + elif [[ -s "${ww3_restart_file}" ]]; then # If not, check to see if binary restart exists: + export WW3_restart_from_binary=true + cpreq "${ww3_restart_file}" "${DATA}/${ww3_restart_dest_file}" + else + if [[ "${RERUN}" == "YES" ]] || [[ -f "${DATA}/ufs.cpld.cpl.r.nc" ]]; then # The || part requires CMEPS_postdet to be called before WW3_postdet + # In the case of a RERUN, the WW3 restart file is required + # In the case of runtype=continue, if no wave restart when using PIO, the model will fail + echo "FATAL ERROR: WW3 binary | netcdf restart file '${ww3_restart_file}' | '${ww3_restart_file}.nc' not found for RERUN='${RERUN}' or runtype=continue, ABORT!" + exit 1 + else + export WW3_restart_from_binary=false + echo "WARNING: WW3 binary | netcdf restart file '${ww3_restart_file}' | '${ww3_restart_file}.nc' not found for warm_start='${warm_start}', will start from rest!" + fi + fi + + local first_ww3_restart_out + first_ww3_restart_out=$(date --utc -d "${restart_date:0:8} ${restart_date:8:2} + ${restart_interval} hours" +%Y%m%d%H) + if [[ "${DOIAU:-NO}" == "YES" ]]; then + first_ww3_restart_out=$(date --utc -d "${first_ww3_restart_out:0:8} ${first_ww3_restart_out:8:2} + ${half_window} hours" +%Y%m%d%H) + fi + + # Link restart files to their expected names in DATArestart/WW3_RESTART + # TODO: Have the UFSWM write out the WW3 restart files in the expected format of 'YYYYMMDD.HHmmSS.restart.ww3.nc' + local cwd vdate ww3_ufs_restart_file ww3_netcdf_restart_file + cwd="${PWD}" + cd "${DATArestart}/WW3_RESTART" || exit 1 + for ((vdate = first_ww3_restart_out; vdate <= forecast_end_cycle; \ + vdate = $(date --utc -d "${vdate:0:8} ${vdate:8:2} + ${restart_interval} hours" +%Y%m%d%H))); do + seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds + ww3_ufs_restart_file="ufs.cpld.ww3.r.${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${seconds}.nc" # UFS restart file name + ww3_netcdf_restart_file="${vdate:0:8}.${vdate:8:2}0000.restart.ww3.nc" # WW3 restart file name in COM + ${NLN} "${ww3_netcdf_restart_file}" "${ww3_ufs_restart_file}" + done + + # TODO: link GEFS restart for next cycle IC + #if [[ "${RUN}" == "gefs" ]]; then + # vdate=${model_start_date_next_cycle} + # seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds + # ww3_ufs_restart_file="ufs.cpld.ww3.r.${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${seconds}.nc" + # ww3_netcdf_restart_file="${vdate:0:8}.${vdate:8:2}0000.restart.ww3.nc" + # ${NLN} "${ww3_netcdf_restart_file}" "${ww3_ufs_restart_file}" + #fi + cd "${cwd}" || exit 1 + + # Link output files + ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.${waveGRD}.${PDY}${cyc}.log" "log.ww3" + + # Loop for gridded output (uses FHINC) + local fhr fhr3 FHINC + # shellcheck disable=SC2153 + fhr="${FHMIN_WAV}" + if [[ ${FHMAX_HF_WAV} -gt 0 && ${FHOUT_HF_WAV} -gt 0 && ${fhr} -lt ${FHMAX_HF_WAV} ]]; then + fhinc=${FHOUT_HF_WAV} + else + fhinc=${FHOUT_WAV} fi - fhr=$((fhr + fhinc)) - done - - # Loop for point output (uses DTPNT) - fhr=${FHMIN_WAV} - fhinc=${FHINCP_WAV} - while [[ ${fhr} -le ${FHMAX_WAV} ]]; do - fhr3=$(printf '%03d' "${fhr}") - vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d.%H0000) - ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.points.f${fhr3}.nc" "${DATAoutput}/WW3_OUTPUT/${vdate}.out_pnt.ww3.nc" - ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.points.f${fhr3}.log" "${DATAoutput}/WW3_OUTPUT/log.${vdate}.out_pnt.ww3.txt" - - fhr=$((fhr + fhinc)) - done + while [[ ${fhr} -le ${FHMAX_WAV} ]]; do + fhr3=$(printf '%03d' "${fhr}") + vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d.%H0000) + ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.${waveGRD}.f${fhr3}.bin" "${DATAoutput}/WW3_OUTPUT/${vdate}.out_grd.ww3" + ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.${waveGRD}.f${fhr3}.log" "${DATAoutput}/WW3_OUTPUT/log.${vdate}.out_grd.ww3.txt" + + if [[ ${fhr} -ge ${FHMAX_HF_WAV} ]]; then + fhinc=${FHOUT_WAV} + fi + fhr=$((fhr + fhinc)) + done + + # Loop for point output (uses DTPNT) + fhr=${FHMIN_WAV} + fhinc=${FHINCP_WAV} + while [[ ${fhr} -le ${FHMAX_WAV} ]]; do + fhr3=$(printf '%03d' "${fhr}") + vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d.%H0000) + ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.points.f${fhr3}.nc" "${DATAoutput}/WW3_OUTPUT/${vdate}.out_pnt.ww3.nc" + ${NLN} "${COMOUT_WAVE_HISTORY}/${RUN}.t${cyc}z.points.f${fhr3}.log" "${DATAoutput}/WW3_OUTPUT/log.${vdate}.out_pnt.ww3.txt" + + fhr=$((fhr + fhinc)) + done } WW3_nml() { - echo "SUB ${FUNCNAME[0]}: Copying input files for WW3" - source "${USHgfs}/parsing_namelists_WW3.sh" - WW3_namelists + echo "SUB ${FUNCNAME[0]}: Copying input files for WW3" + source "${USHgfs}/parsing_namelists_WW3.sh" + WW3_namelists } WW3_out() { - echo "SUB ${FUNCNAME[0]}: Copying output data for WW3" - - # Copy wave namelist from DATA to COMOUT_CONF after the forecast is run (and successfull) - cpfs "${DATA}/ww3_shel.nml" "${COMOUT_CONF}/ufs.ww3_shel.nml" - - # Copy WW3 restarts at the end of the forecast segment to COM for RUN=gfs|gefs - if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then - local restart_file - if [[ "${RUN}" == "gfs" || "${RUN}" == "gefs" || "${RUN}" == "gcafs" ]]; then - echo "Copying WW3 restarts for 'RUN=${RUN}' at ${forecast_end_cycle}" - restart_file="${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000.restart.ww3.nc" - cpfs "${DATArestart}/WW3_RESTART/${restart_file}" \ - "${COMOUT_WAVE_RESTART}/${restart_file}" + echo "SUB ${FUNCNAME[0]}: Copying output data for WW3" + + # Copy wave namelist from DATA to COMOUT_CONF after the forecast is run (and successfull) + cpfs "${DATA}/ww3_shel.nml" "${COMOUT_CONF}/ufs.ww3_shel.nml" + + # Copy WW3 restarts at the end of the forecast segment to COM for RUN=gfs|gefs + if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then + local restart_file + if [[ "${RUN}" == "gfs" || "${RUN}" == "gefs" || "${RUN}" == "gcafs" ]]; then + echo "Copying WW3 restarts for 'RUN=${RUN}' at ${forecast_end_cycle}" + restart_file="${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000.restart.ww3.nc" + cpfs "${DATArestart}/WW3_RESTART/${restart_file}" \ + "${COMOUT_WAVE_RESTART}/${restart_file}" + fi fi - fi - - # Copy restarts for next cycle for RUN=gdas|gefs - # TODO: GEFS needs to be added here - if [[ "${RUN}" == "gdas" ]]; then - local restart_date restart_file - restart_date="${model_start_date_next_cycle}" - echo "Copying WW3 restarts for 'RUN=${RUN}' at ${restart_date}" - restart_file="${restart_date:0:8}.${restart_date:8:2}0000.restart.ww3.nc" - cpfs "${DATArestart}/WW3_RESTART/${restart_file}" \ - "${COMOUT_WAVE_RESTART}/${restart_file}" - fi - - # Copy restarts for downstream usage in HAFS - if [[ "${RUN}" == "gdas" ]]; then - local restart_date restart_file - restart_date="${next_cycle}" - echo "Copying WW3 restarts for 'RUN=${RUN}' at ${restart_date}" - restart_file="${restart_date:0:8}.${restart_date:8:2}0000.restart.ww3.nc" - cpfs "${DATArestart}/WW3_RESTART/${restart_file}" \ - "${COMOUT_WAVE_RESTART}/${restart_file}" - fi -} + # Copy restarts for next cycle for RUN=gdas|gefs + # TODO: GEFS needs to be added here + if [[ "${RUN}" == "gdas" ]]; then + local restart_date restart_file + restart_date="${model_start_date_next_cycle}" + echo "Copying WW3 restarts for 'RUN=${RUN}' at ${restart_date}" + restart_file="${restart_date:0:8}.${restart_date:8:2}0000.restart.ww3.nc" + cpfs "${DATArestart}/WW3_RESTART/${restart_file}" \ + "${COMOUT_WAVE_RESTART}/${restart_file}" + fi + # Copy restarts for downstream usage in HAFS + if [[ "${RUN}" == "gdas" ]]; then + local restart_date restart_file + restart_date="${next_cycle}" + echo "Copying WW3 restarts for 'RUN=${RUN}' at ${restart_date}" + restart_file="${restart_date:0:8}.${restart_date:8:2}0000.restart.ww3.nc" + cpfs "${DATArestart}/WW3_RESTART/${restart_file}" \ + "${COMOUT_WAVE_RESTART}/${restart_file}" + fi -CPL_out() { - echo "SUB ${FUNCNAME[0]}: Copying output data for general cpl fields" - if [[ "${esmf_profile:-.false.}" == ".true." ]]; then - cpfs "${DATA}/ESMF_Profile.summary" "${COMOUT_ATMOS_HISTORY}/ESMF_Profile.summary" - fi } -MOM6_postdet() { - echo "SUB ${FUNCNAME[0]}: MOM6 after run type determination" - - local restart_dir restart_date - if [[ "${RERUN}" == "YES" ]]; then - restart_dir="${DATArestart}/MOM6_RESTART" - restart_date="${RERUN_DATE}" - else # "${RERUN}" == "NO" - restart_dir="${COMIN_OCEAN_RESTART_PREV}" - restart_date="${model_start_date_current_cycle}" - fi - - # Copy MOM6 ICs - cpreq "${restart_dir}/${restart_date:0:8}.${restart_date:8:2}0000.MOM.res.nc" "${DATA}/INPUT/MOM.res.nc" - case ${OCNRES} in - "025") - local nn - for (( nn = 1; nn <= 4; nn++ )); do - if [[ -f "${restart_dir}/${restart_date:0:8}.${restart_date:8:2}0000.MOM.res_${nn}.nc" ]]; then - cpreq "${restart_dir}/${restart_date:0:8}.${restart_date:8:2}0000.MOM.res_${nn}.nc" "${DATA}/INPUT/MOM.res_${nn}.nc" - fi - done - ;; - *) ;; - esac - - # Copy increment (only when RERUN=NO) - if [[ "${RERUN}" == "NO" ]]; then - if [[ "${DO_JEDIOCNVAR:-NO}" == "YES" ]] || [[ ${MEMBER} -gt 0 && "${ODA_INCUPD:-False}" == "True" ]]; then - cpreq "${COMIN_OCEAN_ANALYSIS}/${RUN}.t${cyc}z.mom6_increment.i006.nc" "${DATA}/INPUT/mom6_increment.nc" +CPL_out() { + echo "SUB ${FUNCNAME[0]}: Copying output data for general cpl fields" + if [[ "${esmf_profile:-.false.}" == ".true." ]]; then + cpfs "${DATA}/ESMF_Profile.summary" "${COMOUT_ATMOS_HISTORY}/ESMF_Profile.summary" fi - fi # if [[ "${RERUN}" == "NO" ]]; then - - # Link output files - case ${RUN} in - gfs|enkfgfs|gefs|sfs|gcafs) # Link output files for RUN=gfs|enkfgfs|gefs|sfs - # Looping over MOM6 output hours - local fhr fhr3 last_fhr interval midpoint vdate vdate_mid source_file dest_file - for fhr in ${MOM6_OUTPUT_FH}; do - fhr3=$(printf %03i "${fhr}") +} - if [[ -z ${last_fhr:-} ]]; then - last_fhr=${fhr} - continue - fi +MOM6_postdet() { + echo "SUB ${FUNCNAME[0]}: MOM6 after run type determination" - (( interval = fhr - last_fhr )) - (( midpoint = last_fhr + interval/2 )) + local restart_dir restart_date + if [[ "${RERUN}" == "YES" ]]; then + restart_dir="${DATArestart}/MOM6_RESTART" + restart_date="${RERUN_DATE}" + else # "${RERUN}" == "NO" + restart_dir="${COMIN_OCEAN_RESTART_PREV}" + restart_date="${model_start_date_current_cycle}" + fi - vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) - #If OFFSET_START_HOUR is greater than 0, OFFSET_START_HOUR should be added to the midpoint for first lead time - if (( OFFSET_START_HOUR > 0 )) && (( fhr == FHOUT_OCN ));then - vdate_mid=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + $(( midpoint + OFFSET_START_HOUR )) hours" +%Y%m%d%H) - else - vdate_mid=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${midpoint} hours" +%Y%m%d%H) - fi + # Copy MOM6 ICs + cpreq "${restart_dir}/${restart_date:0:8}.${restart_date:8:2}0000.MOM.res.nc" "${DATA}/INPUT/MOM.res.nc" + case ${OCNRES} in + "025") + local nn + for ((nn = 1; nn <= 4; nn++)); do + if [[ -f "${restart_dir}/${restart_date:0:8}.${restart_date:8:2}0000.MOM.res_${nn}.nc" ]]; then + cpreq "${restart_dir}/${restart_date:0:8}.${restart_date:8:2}0000.MOM.res_${nn}.nc" "${DATA}/INPUT/MOM.res_${nn}.nc" + fi + done + ;; + *) ;; + esac - # Native model output uses window midpoint in the filename, but we are mapping that to the end of the period for COM - if (( OFFSET_START_HOUR > 0 )) && (( fhr == FHOUT_OCN ));then - source_file="ocn_lead1_${vdate_mid:0:4}_${vdate_mid:4:2}_${vdate_mid:6:2}_${vdate_mid:8:2}.nc" - else - source_file="ocn_${vdate_mid:0:4}_${vdate_mid:4:2}_${vdate_mid:6:2}_${vdate_mid:8:2}.nc" + # Copy increment (only when RERUN=NO) + if [[ "${RERUN}" == "NO" ]]; then + if [[ "${DO_JEDIOCNVAR:-NO}" == "YES" ]] || [[ ${MEMBER} -gt 0 && "${ODA_INCUPD:-False}" == "True" ]]; then + cpreq "${COMIN_OCEAN_ANALYSIS}/${RUN}.t${cyc}z.mom6_increment.i006.nc" "${DATA}/INPUT/mom6_increment.nc" fi - dest_file="${RUN}.t${cyc}z.${interval}hr_avg.f${fhr3}.nc" - ${NLN} "${COMOUT_OCEAN_HISTORY}/${dest_file}" "${DATAoutput}/MOM6_OUTPUT/${source_file}" + fi # if [[ "${RERUN}" == "NO" ]]; then + + # Link output files + case ${RUN} in + gfs | enkfgfs | gefs | sfs | gcafs) # Link output files for RUN=gfs|enkfgfs|gefs|sfs + # Looping over MOM6 output hours + local fhr fhr3 last_fhr interval midpoint vdate vdate_mid source_file dest_file + for fhr in ${MOM6_OUTPUT_FH}; do + fhr3=$(printf %03i "${fhr}") + + if [[ -z ${last_fhr:-} ]]; then + last_fhr=${fhr} + continue + fi + + ((interval = fhr - last_fhr)) + ((midpoint = last_fhr + interval / 2)) + + vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + #If OFFSET_START_HOUR is greater than 0, OFFSET_START_HOUR should be added to the midpoint for first lead time + if ((OFFSET_START_HOUR > 0)) && ((fhr == FHOUT_OCN)); then + vdate_mid=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + $((midpoint + OFFSET_START_HOUR)) hours" +%Y%m%d%H) + else + vdate_mid=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${midpoint} hours" +%Y%m%d%H) + fi + + # Native model output uses window midpoint in the filename, but we are mapping that to the end of the period for COM + if ((OFFSET_START_HOUR > 0)) && ((fhr == FHOUT_OCN)); then + source_file="ocn_lead1_${vdate_mid:0:4}_${vdate_mid:4:2}_${vdate_mid:6:2}_${vdate_mid:8:2}.nc" + else + source_file="ocn_${vdate_mid:0:4}_${vdate_mid:4:2}_${vdate_mid:6:2}_${vdate_mid:8:2}.nc" + fi + dest_file="${RUN}.t${cyc}z.${interval}hr_avg.f${fhr3}.nc" + ${NLN} "${COMOUT_OCEAN_HISTORY}/${dest_file}" "${DATAoutput}/MOM6_OUTPUT/${source_file}" + + last_fhr=${fhr} - last_fhr=${fhr} - - done - ;; + done + ;; + + gdas | enkfgdas) # Link output files for RUN=gdas|enkfgdas + # Save (instantaneous) MOM6 backgrounds + local fhr3 vdatestr + for fhr in ${MOM6_OUTPUT_FH}; do + fhr3=$(printf %03i "${fhr}") + vdatestr=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y_%m_%d_%H) + ${NLN} "${COMOUT_OCEAN_HISTORY}/${RUN}.t${cyc}z.inst.f${fhr3}.nc" "${DATAoutput}/MOM6_OUTPUT/ocn_da_${vdatestr}.nc" + done + ;; + *) + echo "FATAL ERROR: Don't know how to copy MOM output files for RUN ${RUN}" + exit 25 + ;; + esac - gdas|enkfgdas) # Link output files for RUN=gdas|enkfgdas - # Save (instantaneous) MOM6 backgrounds - local fhr3 vdatestr - for fhr in ${MOM6_OUTPUT_FH}; do - fhr3=$(printf %03i "${fhr}") - vdatestr=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y_%m_%d_%H) - ${NLN} "${COMOUT_OCEAN_HISTORY}/${RUN}.t${cyc}z.inst.f${fhr3}.nc" "${DATAoutput}/MOM6_OUTPUT/ocn_da_${vdatestr}.nc" - done - ;; - *) - echo "FATAL ERROR: Don't know how to copy MOM output files for RUN ${RUN}" - exit 25 - ;; - esac - - echo "SUB ${FUNCNAME[0]}: MOM6 input data linked/copied" + echo "SUB ${FUNCNAME[0]}: MOM6 input data linked/copied" } MOM6_nml() { - echo "SUB ${FUNCNAME[0]}: Creating name list for MOM6" - source "${USHgfs}/parsing_namelists_MOM6.sh" - MOM6_namelists + echo "SUB ${FUNCNAME[0]}: Creating name list for MOM6" + source "${USHgfs}/parsing_namelists_MOM6.sh" + MOM6_namelists } MOM6_out() { - echo "SUB ${FUNCNAME[0]}: Copying output data for MOM6" - - # Copy MOM_input from DATA to COMOUT_CONF after the forecast is run (and successfull) - cpfs "${DATA}/INPUT/MOM_input" "${COMOUT_CONF}/ufs.MOM_input" - # Copy runtime configuration of MOM: MOM_parameter_doc.all that was used in the forecast - if [[ -f "${DATA}/MOM6_OUTPUT/MOM_parameter_doc.all" ]]; then - cpfs "${DATA}/MOM6_OUTPUT/MOM_parameter_doc.all" "${COMOUT_CONF}/MOM_parameter_doc.all" - fi - - # Create a list of MOM6 restart files - # Coarser than 1/2 degree has a single MOM restart - local mom6_restart_files mom6_restart_file restart_file - mom6_restart_files=(MOM.res.nc) - # 1/4 degree resolution has 3 additional restarts - case "${OCNRES}" in - "025") - local nn - for (( nn = 1; nn <= 3; nn++ )); do - mom6_restart_files+=("MOM.res_${nn}.nc") - done - ;; - *) ;; - esac - - case ${RUN} in - gdas|enkfgdas|enkfgfs) # Copy restarts for the next cycle for RUN=gdas|enkfgdas|enkfgfs - local restart_date - restart_date="${model_start_date_next_cycle}" - echo "Copying MOM6 restarts for 'RUN=${RUN}' at ${restart_date}" - for mom6_restart_file in "${mom6_restart_files[@]}"; do - restart_file="${restart_date:0:8}.${restart_date:8:2}0000.${mom6_restart_file}" - cpfs "${DATArestart}/MOM6_RESTART/${restart_file}" \ - "${COMOUT_OCEAN_RESTART}/${restart_file}" - done - ;; - gfs|gefs|sfs|gcafs) # Copy MOM6 restarts at the end of the forecast segment to COM for RUN=gfs|gefs|sfs - if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then - local restart_file - echo "Copying MOM6 restarts for 'RUN=${RUN}' at ${forecast_end_cycle}" - for mom6_restart_file in "${mom6_restart_files[@]}"; do - restart_file="${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000.${mom6_restart_file}" - cpfs "${DATArestart}/MOM6_RESTART/${restart_file}" \ - "${COMOUT_OCEAN_RESTART}/${restart_file}" - done - fi - ;; - *) - echo "FATAL ERROR: Not sure how to copy restart files for RUN ${RUN}" - exit 25 - ;; - esac + echo "SUB ${FUNCNAME[0]}: Copying output data for MOM6" + + # Copy MOM_input from DATA to COMOUT_CONF after the forecast is run (and successfull) + cpfs "${DATA}/INPUT/MOM_input" "${COMOUT_CONF}/ufs.MOM_input" + # Copy runtime configuration of MOM: MOM_parameter_doc.all that was used in the forecast + if [[ -f "${DATA}/MOM6_OUTPUT/MOM_parameter_doc.all" ]]; then + cpfs "${DATA}/MOM6_OUTPUT/MOM_parameter_doc.all" "${COMOUT_CONF}/MOM_parameter_doc.all" + fi + + # Create a list of MOM6 restart files + # Coarser than 1/2 degree has a single MOM restart + local mom6_restart_files mom6_restart_file restart_file + mom6_restart_files=(MOM.res.nc) + # 1/4 degree resolution has 3 additional restarts + case "${OCNRES}" in + "025") + local nn + for ((nn = 1; nn <= 3; nn++)); do + mom6_restart_files+=("MOM.res_${nn}.nc") + done + ;; + *) ;; + esac + + case ${RUN} in + gdas | enkfgdas | enkfgfs) # Copy restarts for the next cycle for RUN=gdas|enkfgdas|enkfgfs + local restart_date + restart_date="${model_start_date_next_cycle}" + echo "Copying MOM6 restarts for 'RUN=${RUN}' at ${restart_date}" + for mom6_restart_file in "${mom6_restart_files[@]}"; do + restart_file="${restart_date:0:8}.${restart_date:8:2}0000.${mom6_restart_file}" + cpfs "${DATArestart}/MOM6_RESTART/${restart_file}" \ + "${COMOUT_OCEAN_RESTART}/${restart_file}" + done + ;; + gfs | gefs | sfs | gcafs) # Copy MOM6 restarts at the end of the forecast segment to COM for RUN=gfs|gefs|sfs + if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then + local restart_file + echo "Copying MOM6 restarts for 'RUN=${RUN}' at ${forecast_end_cycle}" + for mom6_restart_file in "${mom6_restart_files[@]}"; do + restart_file="${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000.${mom6_restart_file}" + cpfs "${DATArestart}/MOM6_RESTART/${restart_file}" \ + "${COMOUT_OCEAN_RESTART}/${restart_file}" + done + fi + ;; + *) + echo "FATAL ERROR: Not sure how to copy restart files for RUN ${RUN}" + exit 25 + ;; + esac } CICE_postdet() { - echo "SUB ${FUNCNAME[0]}: CICE after run type determination" - - local restart_date cice_restart_file - if [[ "${RERUN}" == "YES" ]]; then - restart_date="${RERUN_DATE}" - local seconds - seconds=$(to_seconds "${restart_date:8:2}0000") # convert HHMMSS to seconds - cice_restart_file="${DATArestart}/CICE_RESTART/cice_model.res.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}.nc" - else # "${RERUN}" == "NO" - restart_date="${model_start_date_current_cycle}" - cice_restart_file="${COMIN_ICE_RESTART_PREV}/${restart_date:0:8}.${restart_date:8:2}0000.cice_model.res.nc" - if [[ "${DO_JEDIOCNVAR:-NO}" == "YES" ]]; then - if [[ ${MEMBER} -eq 0 ]]; then - # Start the deterministic from the JEDI/SOCA analysis if the Marine DA in ON - cice_restart_file="${COMIN_ICE_ANALYSIS}/${restart_date:0:8}.${restart_date:8:2}0000.analysis.cice_model.res.nc" - elif [[ ${MEMBER} -gt 0 && "${DO_STARTMEM_FROM_JEDIICE:-NO}" == "YES" ]]; then - # Ignore the JEDI/SOCA ensemble analysis for the ensemble members if DO_START_FROM_JEDIICE is OFF - cice_restart_file="${COMIN_ICE_ANALYSIS}/${restart_date:0:8}.${restart_date:8:2}0000.analysis.cice_model.res.nc" - fi + echo "SUB ${FUNCNAME[0]}: CICE after run type determination" + + local restart_date cice_restart_file + if [[ "${RERUN}" == "YES" ]]; then + restart_date="${RERUN_DATE}" + local seconds + seconds=$(to_seconds "${restart_date:8:2}0000") # convert HHMMSS to seconds + cice_restart_file="${DATArestart}/CICE_RESTART/cice_model.res.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}.nc" + else # "${RERUN}" == "NO" + restart_date="${model_start_date_current_cycle}" + cice_restart_file="${COMIN_ICE_RESTART_PREV}/${restart_date:0:8}.${restart_date:8:2}0000.cice_model.res.nc" + if [[ "${DO_JEDIOCNVAR:-NO}" == "YES" ]]; then + if [[ "${MEMBER}" -eq 0 ]]; then + # Start the deterministic from the JEDI/SOCA analysis if the Marine DA in ON + cice_restart_file="${COMIN_ICE_ANALYSIS}/${restart_date:0:8}.${restart_date:8:2}0000.analysis.cice_model.res.nc" + elif [[ "${MEMBER}" -gt 0 ]] && [[ "${DO_STARTMEM_FROM_JEDIICE:-NO}" == "YES" ]]; then + # Ignore the JEDI/SOCA ensemble analysis for the ensemble members if DO_START_FROM_JEDIICE is OFF + cice_restart_file="${COMIN_ICE_ANALYSIS}/${restart_date:0:8}.${restart_date:8:2}0000.analysis.cice_model.res.nc" + fi + fi fi - fi - # Copy CICE ICs - cpreq "${cice_restart_file}" "${DATA}/cice_model.res.nc" + # Copy CICE ICs + cpreq "${cice_restart_file}" "${DATA}/cice_model.res.nc" - # Link iceh_ic file to COM. This is the initial condition file from CICE (f000) - # TODO: Is this file needed in COM? Is this going to be used for generating any products? - local vdate seconds vdatestr fhr fhr3 interval last_fhr - seconds=$(to_seconds "${model_start_date_current_cycle:8:2}0000") # convert HHMMSS to seconds - vdatestr="${model_start_date_current_cycle:0:4}-${model_start_date_current_cycle:4:2}-${model_start_date_current_cycle:6:2}-${seconds}" - ${NLN} "${COMOUT_ICE_HISTORY}/${RUN}.t${cyc}z.ic.nc" "${DATAoutput}/CICE_OUTPUT/iceh_ic.${vdatestr}.nc" + # Link iceh_ic file to COM. This is the initial condition file from CICE (f000) + # TODO: Is this file needed in COM? Is this going to be used for generating any products? + local vdate seconds vdatestr fhr fhr3 interval last_fhr + seconds=$(to_seconds "${model_start_date_current_cycle:8:2}0000") # convert HHMMSS to seconds + vdatestr="${model_start_date_current_cycle:0:4}-${model_start_date_current_cycle:4:2}-${model_start_date_current_cycle:6:2}-${seconds}" + ${NLN} "${COMOUT_ICE_HISTORY}/${RUN}.t${cyc}z.ic.nc" "${DATAoutput}/CICE_OUTPUT/iceh_ic.${vdatestr}.nc" - # Link CICE forecast output files from DATAoutput/CICE_OUTPUT to COM - local source_file dest_file - for fhr in "${CICE_OUTPUT_FH[@]}"; do + # Link CICE forecast output files from DATAoutput/CICE_OUTPUT to COM + local source_file dest_file + for fhr in "${CICE_OUTPUT_FH[@]}"; do - if [[ -z ${last_fhr:-} ]]; then - last_fhr=${fhr} - continue - fi + if [[ -z ${last_fhr:-} ]]; then + last_fhr=${fhr} + continue + fi - fhr3=$(printf %03i "${fhr}") - (( interval = fhr - last_fhr )) - - vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) - seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds - vdatestr="${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${seconds}" - - case "${RUN}" in - gdas|enkfgdas) - source_file="iceh_inst.${vdatestr}.nc" - dest_file="${RUN}.t${cyc}z.inst.f${fhr3}.nc" - ;; - gfs|enkfgfs|sfs|gcafs) - source_file="iceh_$(printf "%0.2d" "${FHOUT_ICE}")h.${vdatestr}.nc" - dest_file="${RUN}.t${cyc}z.${interval}hr_avg.f${fhr3}.nc" - ;; - gefs) - source_file="iceh.${vdatestr}.nc" - dest_file="${RUN}.t${cyc}z.${interval}hr_avg.f${fhr3}.nc" - ;; - *) - echo "FATAL ERROR: Unsupported RUN ${RUN} in CICE postdet" - exit 10 - esac + fhr3=$(printf %03i "${fhr}") + ((interval = fhr - last_fhr)) - ${NLN} "${COMOUT_ICE_HISTORY}/${dest_file}" "${DATAoutput}/CICE_OUTPUT/${source_file}" + vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds + vdatestr="${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${seconds}" + + case "${RUN}" in + gdas | enkfgdas) + source_file="iceh_inst.${vdatestr}.nc" + dest_file="${RUN}.t${cyc}z.inst.f${fhr3}.nc" + ;; + gfs | enkfgfs | sfs | gcafs) + source_file="iceh_$(printf "%0.2d" "${FHOUT_ICE}")h.${vdatestr}.nc" + dest_file="${RUN}.t${cyc}z.${interval}hr_avg.f${fhr3}.nc" + ;; + gefs) + source_file="iceh.${vdatestr}.nc" + dest_file="${RUN}.t${cyc}z.${interval}hr_avg.f${fhr3}.nc" + ;; + *) + echo "FATAL ERROR: Unsupported RUN ${RUN} in CICE postdet" + exit 10 + ;; + esac + + ${NLN} "${COMOUT_ICE_HISTORY}/${dest_file}" "${DATAoutput}/CICE_OUTPUT/${source_file}" - last_fhr=${fhr} - done + last_fhr=${fhr} + done } CICE_nml() { - echo "SUB ${FUNCNAME[0]}: Creating name list for CICE" - source "${USHgfs}/parsing_namelists_CICE.sh" - CICE_namelists + echo "SUB ${FUNCNAME[0]}: Creating name list for CICE" + source "${USHgfs}/parsing_namelists_CICE.sh" + CICE_namelists } CICE_out() { - echo "SUB ${FUNCNAME[0]}: Copying output data for CICE" - - # Copy ice_in namelist from DATA to COMOUT_CONF after the forecast is run (and successfull) - cpfs "${DATA}/ice_in" "${COMOUT_CONF}/ufs.ice_in" - - case ${RUN} in - gdas|enkfgdas|enkfgfs) # Copy restarts for next cycle for RUN=gdas|enkfgdas|enkfgfs - local restart_date - restart_date="${model_start_date_next_cycle}" - echo "Copying CICE restarts for 'RUN=${RUN}' at ${restart_date}" - seconds=$(to_seconds "${restart_date:8:2}0000") # convert HHMMSS to seconds - source_file="cice_model.res.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}.nc" - target_file="${restart_date:0:8}.${restart_date:8:2}0000.cice_model.res.nc" - cpfs "${DATArestart}/CICE_RESTART/${source_file}" \ - "${COMOUT_ICE_RESTART}/${target_file}" - ;; - gfs|gefs|sfs|gcafs) # Copy CICE restarts at the end of the forecast segment to COM for RUN=gfs|gefs|sfs|gcafs - if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then - local seconds source_file target_file - echo "Copying CICE restarts for 'RUN=${RUN}' at ${forecast_end_cycle}" - seconds=$(to_seconds "${forecast_end_cycle:8:2}0000") # convert HHMMSS to seconds - source_file="cice_model.res.${forecast_end_cycle:0:4}-${forecast_end_cycle:4:2}-${forecast_end_cycle:6:2}-${seconds}.nc" - target_file="${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000.cice_model.res.nc" - cpfs "${DATArestart}/CICE_RESTART/${source_file}" \ - "${COMOUT_ICE_RESTART}/${target_file}" - fi - ;; - *) - echo "FATAL ERROR: Not sure how to copy restart files for RUN ${RUN}" - exit 25 - ;; - esac + echo "SUB ${FUNCNAME[0]}: Copying output data for CICE" + + # Copy ice_in namelist from DATA to COMOUT_CONF after the forecast is run (and successfull) + cpfs "${DATA}/ice_in" "${COMOUT_CONF}/ufs.ice_in" + + case ${RUN} in + gdas | enkfgdas | enkfgfs) # Copy restarts for next cycle for RUN=gdas|enkfgdas|enkfgfs + local restart_date + restart_date="${model_start_date_next_cycle}" + echo "Copying CICE restarts for 'RUN=${RUN}' at ${restart_date}" + seconds=$(to_seconds "${restart_date:8:2}0000") # convert HHMMSS to seconds + source_file="cice_model.res.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}.nc" + target_file="${restart_date:0:8}.${restart_date:8:2}0000.cice_model.res.nc" + cpfs "${DATArestart}/CICE_RESTART/${source_file}" \ + "${COMOUT_ICE_RESTART}/${target_file}" + ;; + gfs | gefs | sfs | gcafs) # Copy CICE restarts at the end of the forecast segment to COM for RUN=gfs|gefs|sfs|gcafs + if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then + local seconds source_file target_file + echo "Copying CICE restarts for 'RUN=${RUN}' at ${forecast_end_cycle}" + seconds=$(to_seconds "${forecast_end_cycle:8:2}0000") # convert HHMMSS to seconds + source_file="cice_model.res.${forecast_end_cycle:0:4}-${forecast_end_cycle:4:2}-${forecast_end_cycle:6:2}-${seconds}.nc" + target_file="${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000.cice_model.res.nc" + cpfs "${DATArestart}/CICE_RESTART/${source_file}" \ + "${COMOUT_ICE_RESTART}/${target_file}" + fi + ;; + *) + echo "FATAL ERROR: Not sure how to copy restart files for RUN ${RUN}" + exit 25 + ;; + esac } GOCART_rc() { - echo "SUB ${FUNCNAME[0]}: Linking input data and copying config files for GOCART" - # set input directory containing GOCART input data and configuration files - # this variable is platform-dependent and should be set via a YAML file - - # link directory containing GOCART input dataset, if provided - if [[ -n "${AERO_INPUTS_DIR}" ]]; then - ${NLN} "${AERO_INPUTS_DIR}" "${DATA}/ExtData" - status=$? - if [[ ${status} -ne 0 ]]; then - exit "${status}" + echo "SUB ${FUNCNAME[0]}: Linking input data and copying config files for GOCART" + # set input directory containing GOCART input data and configuration files + # this variable is platform-dependent and should be set via a YAML file + + # link directory containing GOCART input dataset, if provided + if [[ -n "${AERO_INPUTS_DIR}" ]]; then + ${NLN} "${AERO_INPUTS_DIR}" "${DATA}/ExtData" + status=$? + if [[ ${status} -ne 0 ]]; then + exit "${status}" + fi fi - fi - source "${USHgfs}/parsing_namelists_GOCART.sh" - GOCART_namelists + source "${USHgfs}/parsing_namelists_GOCART.sh" + GOCART_namelists } GOCART_postdet() { - echo "SUB ${FUNCNAME[0]}: Linking output data for GOCART" - - local vdate - for fhr in $(GOCART_output_fh); do - vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) - - # Temporarily delete existing files due to noclobber in GOCART - local file_types=("inst_aod" "inst_du_ss" "inst_ca" "inst_ni" "inst_su" \ - "inst_du_bin" "inst_ss_bin" "inst_ca_bin" "inst_ni_bin" "inst_su_bin" \ - "inst_2d" "inst_3d" "tavg_du_ss" "tavg_du_bin" "tavg_2d_rad" "tavg_3d_rad") - for file_type in "${file_types[@]}"; do - if [[ -e "${COMOUT_CHEM_HISTORY}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" ]]; then - rm -f "${COMOUT_CHEM_HISTORY}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" - fi - done + echo "SUB ${FUNCNAME[0]}: Linking output data for GOCART" - #TODO: Temporarily removing this as this will crash gocart, adding copy statement at the end - #${NLN} "${COMOUT_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" \ - # "${DATA}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" - done + local vdate + for fhr in $(GOCART_output_fh); do + vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + + # Temporarily delete existing files due to noclobber in GOCART + local file_types=("inst_aod" "inst_du_ss" "inst_ca" "inst_ni" "inst_su" + "inst_du_bin" "inst_ss_bin" "inst_ca_bin" "inst_ni_bin" "inst_su_bin" + "inst_2d" "inst_3d" "tavg_du_ss" "tavg_du_bin" "tavg_2d_rad" "tavg_3d_rad") + for file_type in "${file_types[@]}"; do + if [[ -e "${COMOUT_CHEM_HISTORY}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" ]]; then + rm -f "${COMOUT_CHEM_HISTORY}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" + fi + done + + #TODO: Temporarily removing this as this will crash gocart, adding copy statement at the end + #${NLN} "${COMOUT_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" \ + # "${DATA}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" + done } GOCART_output_fh() { - # This has to be called during postdet after FHROT has been set - local aero_min - local gocart_output_fh - # GOCART produces no AOD files at the initial forecast time, so start the time - # after the forecast start (accounting for FHROT) - aero_min=$(( ${IAU_FHROT:-0} > FHMIN ? IAU_FHROT + FHOUT_AERO : FHMIN + FHOUT_AERO )) - gocart_output_fh=$(seq -s ' ' "$(( aero_min ))" "${FHOUT_AERO}" "${GOCART_MAX}") - - echo "${gocart_output_fh}" + # This has to be called during postdet after FHROT has been set + local aero_min + local gocart_output_fh + # GOCART produces no AOD files at the initial forecast time, so start the time + # after the forecast start (accounting for FHROT) + aero_min=$((${IAU_FHROT:-0} > FHMIN ? IAU_FHROT + FHOUT_AERO : FHMIN + FHOUT_AERO)) + gocart_output_fh=$(seq -s ' ' "$((aero_min))" "${FHOUT_AERO}" "${GOCART_MAX}") + + echo "${gocart_output_fh}" } GOCART_out() { - echo "SUB ${FUNCNAME[0]}: Copying output data for GOCART" - - # Copy gocart.inst_aod after the forecast is run (and successfull) - # TODO: this should be linked but there are issues where gocart crashing if it is linked - local fhr - local vdate - - local file_types=("inst_aod" "inst_du_ss" "inst_ca" "inst_ni" "inst_su" \ - "inst_du_bin" "inst_ss_bin" "inst_ca_bin" "inst_ni_bin" "inst_su_bin" \ - "inst_2d" "inst_3d" "tavg_du_ss" "tavg_du_bin" "tavg_2d_rad" "tavg_3d_rad") - - for fhr in $(GOCART_output_fh); do - vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) - for file_type in "${file_types[@]}"; do - if [[ -e "${DATA}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" ]]; then - cpfs "${DATA}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" \ - "${COMOUT_CHEM_HISTORY}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" - fi + echo "SUB ${FUNCNAME[0]}: Copying output data for GOCART" + + # Copy gocart.inst_aod after the forecast is run (and successfull) + # TODO: this should be linked but there are issues where gocart crashing if it is linked + local fhr + local vdate + + local file_types=("inst_aod" "inst_du_ss" "inst_ca" "inst_ni" "inst_su" + "inst_du_bin" "inst_ss_bin" "inst_ca_bin" "inst_ni_bin" "inst_su_bin" + "inst_2d" "inst_3d" "tavg_du_ss" "tavg_du_bin" "tavg_2d_rad" "tavg_3d_rad") + + for fhr in $(GOCART_output_fh); do + vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + for file_type in "${file_types[@]}"; do + if [[ -e "${DATA}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" ]]; then + cpfs "${DATA}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" \ + "${COMOUT_CHEM_HISTORY}/gocart.${file_type}.${vdate:0:8}_${vdate:8:2}00z.nc4" + fi + done done - done } # shellcheck disable=SC2178 CMEPS_postdet() { - echo "SUB ${FUNCNAME[0]}: Linking output data for CMEPS mediator" - - if [[ "${warm_start}" == ".true." ]]; then - - # Determine the appropriate restart file - local restart_date cmeps_restart_file - if [[ "${RERUN}" == "YES" ]]; then - restart_date="${RERUN_DATE}" - local seconds - seconds=$(to_seconds "${restart_date:8:2}0000") # convert HHMMSS to seconds - cmeps_restart_file="${DATArestart}/CMEPS_RESTART/ufs.cpld.cpl.r.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}.nc" - else # "${RERUN}" == "NO" - restart_date="${model_start_date_current_cycle}" - cmeps_restart_file="${COMIN_MED_RESTART_PREV}/${restart_date:0:8}.${restart_date:8:2}0000.ufs.cpld.cpl.r.nc" - fi - - # Copy CMEPS restarts - if [[ -f "${cmeps_restart_file}" ]]; then - cpreq "${cmeps_restart_file}" "${DATA}/ufs.cpld.cpl.r.nc" - rm -f "${DATA}/rpointer.cpl" - touch "${DATA}/rpointer.cpl" - echo "ufs.cpld.cpl.r.nc" >> "${DATA}/rpointer.cpl" - else - # We have a choice to make here. - # Either we can FATAL ERROR out, or we can let the coupling fields initialize from zero - # cmeps_run_type is determined based on the availability of the CMEPS restart file - echo "WARNING: CMEPS restart file '${cmeps_restart_file}' not found for warm_start='${warm_start}', will initialize!" - if [[ "${RERUN}" == "YES" ]]; then - # In the case of a RERUN, the CMEPS restart file is required - echo "FATAL ERROR: CMEPS restart file '${cmeps_restart_file}' not found for RERUN='${RERUN}', ABORT!" - exit 1 - fi - fi + echo "SUB ${FUNCNAME[0]}: Linking output data for CMEPS mediator" + + if [[ "${warm_start}" == ".true." ]]; then + + # Determine the appropriate restart file + local restart_date cmeps_restart_file + if [[ "${RERUN}" == "YES" ]]; then + restart_date="${RERUN_DATE}" + local seconds + seconds=$(to_seconds "${restart_date:8:2}0000") # convert HHMMSS to seconds + cmeps_restart_file="${DATArestart}/CMEPS_RESTART/ufs.cpld.cpl.r.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}.nc" + else # "${RERUN}" == "NO" + restart_date="${model_start_date_current_cycle}" + cmeps_restart_file="${COMIN_MED_RESTART_PREV}/${restart_date:0:8}.${restart_date:8:2}0000.ufs.cpld.cpl.r.nc" + fi - fi # [[ "${warm_start}" == ".true." ]]; + # Copy CMEPS restarts + if [[ -f "${cmeps_restart_file}" ]]; then + cpreq "${cmeps_restart_file}" "${DATA}/ufs.cpld.cpl.r.nc" + rm -f "${DATA}/rpointer.cpl" + touch "${DATA}/rpointer.cpl" + echo "ufs.cpld.cpl.r.nc" >> "${DATA}/rpointer.cpl" + else + # We have a choice to make here. + # Either we can FATAL ERROR out, or we can let the coupling fields initialize from zero + # cmeps_run_type is determined based on the availability of the CMEPS restart file + echo "WARNING: CMEPS restart file '${cmeps_restart_file}' not found for warm_start='${warm_start}', will initialize!" + if [[ "${RERUN}" == "YES" ]]; then + # In the case of a RERUN, the CMEPS restart file is required + echo "FATAL ERROR: CMEPS restart file '${cmeps_restart_file}' not found for RERUN='${RERUN}', ABORT!" + exit 1 + fi + fi - # For CMEPS, CICE, MOM6 and WW3 determine restart writes - # Note FV3 has its own restart intervals - cmeps_restart_interval=${restart_interval:-${FHMAX}} - # restart_interval = 0 implies write restart at the END of the forecast i.e. at FHMAX - # Convert restart interval into an explicit list for CMEPS/CICE/MOM6/WW3 - # Note, this must be computed after determination IAU in forecast_det and fhrot. - if (( cmeps_restart_interval == 0 )); then - if [[ "${DOIAU:-NO}" == "YES" ]]; then - CMEPS_RESTART_FH=$(( FHMAX + half_window )) - else - CMEPS_RESTART_FH=("${FHMAX}") - fi - else - if [[ "${DOIAU:-NO}" == "YES" ]]; then - if [[ "${MODE}" = "cycled" && "${SDATE}" = "${PDY}${cyc}" && ${EXP_WARM_START} = ".false." ]]; then - local restart_interval_start=${cmeps_restart_interval} - local restart_interval_end=${FHMAX} - else - local restart_interval_start=$(( cmeps_restart_interval + half_window )) - local restart_interval_end=$(( FHMAX + half_window )) - fi + fi # [[ "${warm_start}" == ".true." ]]; + + # For CMEPS, CICE, MOM6 and WW3 determine restart writes + # Note FV3 has its own restart intervals + cmeps_restart_interval=${restart_interval:-${FHMAX}} + # restart_interval = 0 implies write restart at the END of the forecast i.e. at FHMAX + # Convert restart interval into an explicit list for CMEPS/CICE/MOM6/WW3 + # Note, this must be computed after determination IAU in forecast_det and fhrot. + if ((cmeps_restart_interval == 0)); then + if [[ "${DOIAU:-NO}" == "YES" ]]; then + CMEPS_RESTART_FH=$((FHMAX + half_window)) + else + CMEPS_RESTART_FH=("${FHMAX}") + fi else - local restart_interval_start=${cmeps_restart_interval} - local restart_interval_end=${FHMAX} + if [[ "${DOIAU:-NO}" == "YES" ]]; then + if [[ "${MODE}" = "cycled" && "${SDATE}" = "${PDY}${cyc}" && ${EXP_WARM_START} = ".false." ]]; then + local restart_interval_start=${cmeps_restart_interval} + local restart_interval_end=${FHMAX} + else + local restart_interval_start=$((cmeps_restart_interval + half_window)) + local restart_interval_end=$((FHMAX + half_window)) + fi + else + local restart_interval_start=${cmeps_restart_interval} + local restart_interval_end=${FHMAX} + fi + CMEPS_RESTART_FH="$(seq -s ' ' "${restart_interval_start}" "${cmeps_restart_interval}" "${restart_interval_end}")" fi - CMEPS_RESTART_FH="$(seq -s ' ' "${restart_interval_start}" "${cmeps_restart_interval}" "${restart_interval_end}")" - fi - export CMEPS_RESTART_FH - # TODO: For GEFS, once cycling waves "self-cycles" and therefore needs to have a restart at 6 hour + export CMEPS_RESTART_FH + # TODO: For GEFS, once cycling waves "self-cycles" and therefore needs to have a restart at 6 hour } CMEPS_out() { - echo "SUB ${FUNCNAME[0]}: Copying output data for CMEPS mediator" - - case ${RUN} in - gdas|enkfgdas|enkfgfs) # Copy restarts for the next cycle to COM - local restart_date - restart_date="${model_start_date_next_cycle}" - echo "Copying mediator restarts for 'RUN=${RUN}' at ${restart_date}" - seconds=$(to_seconds "${restart_date:8:2}"0000) - source_file="ufs.cpld.cpl.r.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}.nc" - target_file="${restart_date:0:8}.${restart_date:8:2}0000.ufs.cpld.cpl.r.nc" - if [[ -f "${DATArestart}/CMEPS_RESTART/${source_file}" ]]; then - cpfs "${DATArestart}/CMEPS_RESTART/${source_file}" \ - "${COMOUT_MED_RESTART}/${target_file}" - else - echo "Mediator restart '${DATArestart}/CMEPS_RESTART/${source_file}' not found." - fi - ;; - gfs|gefs|sfs|gcafs) # Copy mediator restarts at the end of the forecast segment - if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then - echo "Copying mediator restarts for 'RUN=${RUN}' at ${forecast_end_cycle}" - local seconds source_file target_file - seconds=$(to_seconds "${forecast_end_cycle:8:2}"0000) - source_file="ufs.cpld.cpl.r.${forecast_end_cycle:0:4}-${forecast_end_cycle:4:2}-${forecast_end_cycle:6:2}-${seconds}.nc" - target_file="${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000.ufs.cpld.cpl.r.nc" - if [[ -f "${DATArestart}/CMEPS_RESTART/${source_file}" ]]; then - cpfs "${DATArestart}/CMEPS_RESTART/${source_file}" \ - "${COMOUT_MED_RESTART}/${target_file}" - else - echo "Mediator restart '${DATArestart}/CMEPS_RESTART/${source_file}' not found." - fi - fi - ;; - *) - echo "FATAL ERROR: Not sure how to copy restart files for RUN ${RUN}" - exit 25 - ;; - esac + echo "SUB ${FUNCNAME[0]}: Copying output data for CMEPS mediator" + + case ${RUN} in + gdas | enkfgdas | enkfgfs) # Copy restarts for the next cycle to COM + local restart_date + restart_date="${model_start_date_next_cycle}" + echo "Copying mediator restarts for 'RUN=${RUN}' at ${restart_date}" + seconds=$(to_seconds "${restart_date:8:2}"0000) + source_file="ufs.cpld.cpl.r.${restart_date:0:4}-${restart_date:4:2}-${restart_date:6:2}-${seconds}.nc" + target_file="${restart_date:0:8}.${restart_date:8:2}0000.ufs.cpld.cpl.r.nc" + if [[ -f "${DATArestart}/CMEPS_RESTART/${source_file}" ]]; then + cpfs "${DATArestart}/CMEPS_RESTART/${source_file}" \ + "${COMOUT_MED_RESTART}/${target_file}" + else + echo "Mediator restart '${DATArestart}/CMEPS_RESTART/${source_file}' not found." + fi + ;; + gfs | gefs | sfs | gcafs) # Copy mediator restarts at the end of the forecast segment + if [[ "${COPY_FINAL_RESTARTS}" == "YES" ]]; then + echo "Copying mediator restarts for 'RUN=${RUN}' at ${forecast_end_cycle}" + local seconds source_file target_file + seconds=$(to_seconds "${forecast_end_cycle:8:2}"0000) + source_file="ufs.cpld.cpl.r.${forecast_end_cycle:0:4}-${forecast_end_cycle:4:2}-${forecast_end_cycle:6:2}-${seconds}.nc" + target_file="${forecast_end_cycle:0:8}.${forecast_end_cycle:8:2}0000.ufs.cpld.cpl.r.nc" + if [[ -f "${DATArestart}/CMEPS_RESTART/${source_file}" ]]; then + cpfs "${DATArestart}/CMEPS_RESTART/${source_file}" \ + "${COMOUT_MED_RESTART}/${target_file}" + else + echo "Mediator restart '${DATArestart}/CMEPS_RESTART/${source_file}' not found." + fi + fi + ;; + *) + echo "FATAL ERROR: Not sure how to copy restart files for RUN ${RUN}" + exit 25 + ;; + esac } diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index 905ae85b351..3a59f8b7889 100755 --- a/ush/forecast_predet.sh +++ b/ush/forecast_predet.sh @@ -1,757 +1,755 @@ #! /usr/bin/env bash to_seconds() { - # Function to convert HHMMSS to seconds since 00Z - local hhmmss hh mm ss seconds padded_seconds - hhmmss=${1:?} - hh=${hhmmss:0:2} - mm=${hhmmss:2:2} - ss=${hhmmss:4:2} - seconds=$((10#${hh}*3600+10#${mm}*60+10#${ss})) - padded_seconds=$(printf "%05d" "${seconds}") - echo "${padded_seconds}" + # Function to convert HHMMSS to seconds since 00Z + local hhmmss hh mm ss seconds padded_seconds + hhmmss=${1:?} + hh=${hhmmss:0:2} + mm=${hhmmss:2:2} + ss=${hhmmss:4:2} + seconds=$((10#${hh} * 3600 + 10#${mm} * 60 + 10#${ss})) + padded_seconds=$(printf "%05d" "${seconds}") + echo "${padded_seconds}" } -middle_date(){ - # Function to calculate mid-point date in YYYYMMDDHH between two dates also in YYYYMMDDHH - local date1 date2 date1s date2s dtsecsby2 mid_date - date1=${1:?} - date2=${2:?} - date1s=$(date --utc -d "${date1:0:8} ${date1:8:2}:00:00" +%s) - date2s=$(date --utc -d "${date2:0:8} ${date2:8:2}:00:00" +%s) - dtsecsby2=$(( $((date2s - date1s)) / 2 )) - mid_date=$(date --utc -d "${date1:0:8} ${date1:8:2} + ${dtsecsby2} seconds" +%Y%m%d%H%M%S) - echo "${mid_date:0:10}" +middle_date() { + # Function to calculate mid-point date in YYYYMMDDHH between two dates also in YYYYMMDDHH + local date1 date2 date1s date2s dtsecsby2 mid_date + date1=${1:?} + date2=${2:?} + date1s=$(date --utc -d "${date1:0:8} ${date1:8:2}:00:00" +%s) + date2s=$(date --utc -d "${date2:0:8} ${date2:8:2}:00:00" +%s) + dtsecsby2=$(($((date2s - date1s)) / 2)) + mid_date=$(date --utc -d "${date1:0:8} ${date1:8:2} + ${dtsecsby2} seconds" +%Y%m%d%H%M%S) + echo "${mid_date:0:10}" } -nhour(){ - # Function to calculate hours between two dates (This replicates prod-util NHOUR) - local date1 date2 seconds1 seconds2 hours - date1=${1:?} - date2=${2:?} - # Convert dates to UNIX timestamps - seconds1=$(date --utc -d "${date1:0:8} ${date1:8:2}:00:00" +%s) - seconds2=$(date --utc -d "${date2:0:8} ${date2:8:2}:00:00" +%s) - hours=$(( $((seconds1 - seconds2)) / 3600 )) # Calculate the difference in seconds and convert to hours - echo "${hours}" +nhour() { + # Function to calculate hours between two dates (This replicates prod-util NHOUR) + local date1 date2 seconds1 seconds2 hours + date1=${1:?} + date2=${2:?} + # Convert dates to UNIX timestamps + seconds1=$(date --utc -d "${date1:0:8} ${date1:8:2}:00:00" +%s) + seconds2=$(date --utc -d "${date2:0:8} ${date2:8:2}:00:00" +%s) + hours=$(($((seconds1 - seconds2)) / 3600)) # Calculate the difference in seconds and convert to hours + echo "${hours}" } -FV3_coldstarts(){ - # Function to return an comma-separated string of cold-start input files for FV3 - # Create an array of chgres-ed FV3 files - local fv3_input_files tile_files - fv3_input_files=(gfs_ctrl.nc) - tile_files=(gfs_data sfc_data) - local nn tt - for (( nn = 1; nn <= ntiles; nn++ )); do - for tt in "${tile_files[@]}"; do - fv3_input_files+=("${tt}.tile${nn}.nc") +FV3_coldstarts() { + # Function to return an comma-separated string of cold-start input files for FV3 + # Create an array of chgres-ed FV3 files + local fv3_input_files tile_files + fv3_input_files=(gfs_ctrl.nc) + tile_files=(gfs_data sfc_data) + local nn tt + for ((nn = 1; nn <= ntiles; nn++)); do + for tt in "${tile_files[@]}"; do + fv3_input_files+=("${tt}.tile${nn}.nc") + done done - done - # Create a comma separated string from array using IFS - IFS=, echo "${fv3_input_files[*]}" + # Create a comma separated string from array using IFS + IFS=, echo "${fv3_input_files[*]}" } -FV3_restarts(){ - # Function to return an comma-separated string of warm-start input files for FV3 - # Create an array of FV3 restart files - local fv3_restart_files tile_files - fv3_restart_files=(coupler.res fv_core.res.nc) - tile_files=(fv_core.res fv_srf_wnd.res fv_tracer.res phy_data sfc_data) - if [[ ${DO_CA:-"NO"} == "YES" ]]; then - tile_files+=(ca_data) - fi - local nn tt - for (( nn = 1; nn <= ntiles; nn++ )); do - for tt in "${tile_files[@]}"; do - fv3_restart_files+=("${tt}.tile${nn}.nc") +FV3_restarts() { + # Function to return an comma-separated string of warm-start input files for FV3 + # Create an array of FV3 restart files + local fv3_restart_files tile_files + fv3_restart_files=(coupler.res fv_core.res.nc) + tile_files=(fv_core.res fv_srf_wnd.res fv_tracer.res phy_data sfc_data) + if [[ ${DO_CA:-"NO"} == "YES" ]]; then + tile_files+=(ca_data) + fi + local nn tt + for ((nn = 1; nn <= ntiles; nn++)); do + for tt in "${tile_files[@]}"; do + fv3_restart_files+=("${tt}.tile${nn}.nc") + done done - done - # Create a comma separated string from array using IFS - IFS=, echo "${fv3_restart_files[*]}" + # Create a comma separated string from array using IFS + IFS=, echo "${fv3_restart_files[*]}" } -stoch_restarts(){ - # These only get copied for reruns - local stoch_restart_files - stoch_restart_files=( ) +stoch_restarts() { + # These only get copied for reruns + local stoch_restart_files + stoch_restart_files=() - if [[ "${DO_SPPT:-}" == "YES" || "${DO_SKEB:-}" == "YES" || \ + if [[ "${DO_SPPT:-}" == "YES" || "${DO_SKEB:-}" == "YES" || "${DO_SHUM:-}" == "YES" || "${DO_LAND_PERT:-}" == "YES" ]]; then - stoch_restart_files+=(atm_stoch.res.nc) - fi - if [[ "${DO_OCN:-}" == "YES" && ( "${DO_OCN_SPPT:-}" == "YES" || "${DO_OCN_PERT_EPBL}" == "YES" ) ]]; then - stoch_restart_files+=(ocn_stoch.res.nc) - fi - # Create a comma separated string from array using IFS - IFS=, echo "${stoch_restart_files[*]}" + stoch_restart_files+=(atm_stoch.res.nc) + fi + if [[ "${DO_OCN:-}" == "YES" && ("${DO_OCN_SPPT:-}" == "YES" || "${DO_OCN_PERT_EPBL}" == "YES") ]]; then + stoch_restart_files+=(ocn_stoch.res.nc) + fi + # Create a comma separated string from array using IFS + IFS=, echo "${stoch_restart_files[*]}" } # shellcheck disable=SC2034 -common_predet(){ - echo "SUB ${FUNCNAME[0]}: Defining variables for shared through model components" - - RUN=${RUN:-gdas} - rCDUMP=${rCDUMP:-${RUN}} - - ENSMEM=${ENSMEM:-000} - MEMBER=$(( 10#${ENSMEM:-"-1"} )) # -1: control, 0: ensemble mean, >0: ensemble member $MEMBER - - # Define significant cycles - half_window=$(( assim_freq / 2 )) - current_cycle="${PDY}${cyc}" - previous_cycle=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} - ${assim_freq} hours" +%Y%m%d%H) - next_cycle=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${assim_freq} hours" +%Y%m%d%H) - current_cycle_begin=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} - ${half_window} hours" +%Y%m%d%H) - current_cycle_end=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${half_window} hours" +%Y%m%d%H) - next_cycle_begin=$(date --utc -d "${next_cycle:0:8} ${next_cycle:8:2} - ${half_window} hours" +%Y%m%d%H) - forecast_end_cycle=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${FHMAX} hours" +%Y%m%d%H) - - # Define model start date for current_cycle and next_cycle as the time the forecast will start - if [[ "${DOIAU:-NO}" == "YES" ]]; then - model_start_date_current_cycle="${current_cycle_begin}" - model_start_date_next_cycle="${next_cycle_begin}" - else - model_start_date_current_cycle=${current_cycle} - if [[ "${DO_AERO_ANL:-NO}" == "YES" ]]; then - # even without IAU we want 3-hourly restarts for FGAT - model_start_date_next_cycle="${next_cycle_begin}" +common_predet() { + echo "SUB ${FUNCNAME[0]}: Defining variables for shared through model components" + + RUN=${RUN:-gdas} + rCDUMP=${rCDUMP:-${RUN}} + + ENSMEM=${ENSMEM:-000} + MEMBER=$((10#${ENSMEM:-"-1"})) # -1: control, 0: ensemble mean, >0: ensemble member $MEMBER + + # Define significant cycles + half_window=$((assim_freq / 2)) + current_cycle="${PDY}${cyc}" + previous_cycle=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} - ${assim_freq} hours" +%Y%m%d%H) + next_cycle=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${assim_freq} hours" +%Y%m%d%H) + current_cycle_begin=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} - ${half_window} hours" +%Y%m%d%H) + current_cycle_end=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${half_window} hours" +%Y%m%d%H) + next_cycle_begin=$(date --utc -d "${next_cycle:0:8} ${next_cycle:8:2} - ${half_window} hours" +%Y%m%d%H) + forecast_end_cycle=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${FHMAX} hours" +%Y%m%d%H) + + # Define model start date for current_cycle and next_cycle as the time the forecast will start + if [[ "${DOIAU:-NO}" == "YES" ]]; then + model_start_date_current_cycle="${current_cycle_begin}" + model_start_date_next_cycle="${next_cycle_begin}" else - model_start_date_next_cycle=${next_cycle} + model_start_date_current_cycle=${current_cycle} + if [[ "${DO_AERO_ANL:-NO}" == "YES" ]]; then + # even without IAU we want 3-hourly restarts for FGAT + model_start_date_next_cycle="${next_cycle_begin}" + else + model_start_date_next_cycle=${next_cycle} + fi fi - fi - FHMIN=${FHMIN:-0} - FHMAX=${FHMAX:-9} - FHOUT=${FHOUT:-3} - FHMAX_HF=${FHMAX_HF:-0} - FHOUT_HF=${FHOUT_HF:-1} + FHMIN=${FHMIN:-0} + FHMAX=${FHMAX:-9} + FHOUT=${FHOUT:-3} + FHMAX_HF=${FHMAX_HF:-0} + FHOUT_HF=${FHOUT_HF:-1} - if [[ ! -d "${COMOUT_CONF}" ]]; then mkdir -p "${COMOUT_CONF}"; fi + mkdir -p "${COMOUT_CONF}" - cd "${DATA}" && true - err=$? - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: Unable to 'cd ${DATA}', ABORT!" - exit 1 - fi + cd "${DATA}" && true + err=$? + if [[ ${err} -ne 0 ]]; then + echo "FATAL ERROR: Unable to 'cd ${DATA}', ABORT!" + exit 1 + fi - # Several model components share DATA/INPUT for input data - if [[ ! -d "${DATA}/INPUT" ]]; then mkdir -p "${DATA}/INPUT"; fi + # Several model components share DATA/INPUT for input data + mkdir -p "${DATA}/INPUT" } # shellcheck disable=SC2034 -FV3_predet(){ - echo "SUB ${FUNCNAME[0]}: Defining variables for FV3" - - if [[ ! -d "${COMOUT_ATMOS_HISTORY}" ]]; then mkdir -p "${COMOUT_ATMOS_HISTORY}"; fi - if [[ ! -d "${COMOUT_ATMOS_MASTER}" ]]; then mkdir -p "${COMOUT_ATMOS_MASTER}"; fi - if [[ ! -d "${COMOUT_ATMOS_RESTART}" ]]; then mkdir -p "${COMOUT_ATMOS_RESTART}"; fi - if [[ ! -d "${DATAoutput}/FV3ATM_OUTPUT" ]]; then mkdir -p "${DATAoutput}/FV3ATM_OUTPUT"; fi - if [[ ! -d "${DATArestart}/FV3_RESTART" ]]; then mkdir -p "${DATArestart}/FV3_RESTART"; fi - - # The $DATA/RESTART directory is used for writing FV3 restart files (it is hard-wired in the model) - # Link the output and restart directories to the DATA directory - ${NLN} "${DATAoutput}/FV3ATM_OUTPUT" "${DATA}/FV3ATM_OUTPUT" - ${NLN} "${DATArestart}/FV3_RESTART" "${DATA}/RESTART" - - FHZERO=${FHZERO:-6} - FHCYC=${FHCYC:-24} - - # Convert output settings into an explicit list for FV3 - # Create an FV3 fhr list to be used in the filenames - FV3_OUTPUT_FH="" - local fhr=${FHMIN} - if (( FHOUT_HF > 0 && FHMAX_HF > 0 )); then - FV3_OUTPUT_FH="${FV3_OUTPUT_FH} $(seq -s ' ' "${FHMIN}" "${FHOUT_HF}" "${FHMAX_HF}")" - fhr=${FHMAX_HF} - fi - FV3_OUTPUT_FH="${FV3_OUTPUT_FH} $(seq -s ' ' "${fhr}" "${FHOUT}" "${FHMAX}")" - - # If, FHOUT_HF == FHOUT, the FV3_OUTPUT_FH_NML can be cast as: - if [[ ${FHOUT_HF} -eq ${FHOUT} ]]; then - FV3_OUTPUT_FH_NML="${FHOUT} -1" - else - FV3_OUTPUT_FH_NML="${FV3_OUTPUT_FH}" - fi - - # IAU options - IAUFHRS=${IAUFHRS:-0} - IAU_DELTHRS=${IAU_DELTHRS:-0} - - #------------------------------------------------------------------ - # changeable parameters - # dycore definitions - res="${CASE:1}" - resh="${CASE_HIST:1}" - resp=$((res+1)) - npx=${resp} - npy=${resp} - npz=$((LEVS-1)) - io_layout="1,1" - #ncols=$(( (${npx}-1)*(${npy}-1)*3/2 )) - - # spectral truncation and regular grid resolution based on FV3 resolution - JCAP_CASE=$((2*res-2)) - LONB_CASE=$((4*res)) - LATB_CASE=$((2*res)) - - JCAP_CASE_HIST=$((2*resh-2)) - LONB_CASE_HIST=$((4*resh)) - LATB_CASE_HIST=$((2*resh)) - - JCAP=${JCAP:-${JCAP_CASE}} - LONB=${LONB:-${LONB_CASE}} - LATB=${LATB:-${LATB_CASE}} - - LONB_IMO=${LONB_IMO:-${LONB_CASE_HIST}} - LATB_JMO=${LATB_JMO:-${LATB_CASE_HIST}} - - # NSST Options - # nstf_name contains the NSST related parameters - # nstf_name(1) : NST_MODEL (NSST Model) : 0 = OFF, 1 = ON but uncoupled, 2 = ON and coupled - # nstf_name(2) : NST_SPINUP : 0 = OFF, 1 = ON, - # nstf_name(3) : NST_RESV (Reserved, NSST Analysis) : 0 = OFF, 1 = ON - # nstf_name(4) : ZSEA1 (in mm) : 0 - # nstf_name(5) : ZSEA2 (in mm) : 0 - # nst_anl : .true. or .false., NSST analysis over lake - NST_MODEL=${NST_MODEL:-0} - NST_SPINUP=${NST_SPINUP:-0} - NST_RESV=${NST_RESV-0} - ZSEA1=${ZSEA1:-0} - ZSEA2=${ZSEA2:-0} - nstf_name=${nstf_name:-"${NST_MODEL},${NST_SPINUP},${NST_RESV},${ZSEA1},${ZSEA2}"} - nst_anl=${nst_anl:-".false."} - - # blocking factor used for threading and general physics performance - #nyblocks=$(expr \( $npy - 1 \) \/ $layout_y ) - #nxblocks=$(expr \( $npx - 1 \) \/ $layout_x \/ 32) - #if [ $nxblocks -le 0 ]; then nxblocks=1 ; fi - blocksize=${blocksize:-32} - - # variables for controlling initialization of NCEP/NGGPS ICs - filtered_terrain=${filtered_terrain:-".true."} - gfs_dwinds=${gfs_dwinds:-".true."} - - # various debug options - no_dycore=${no_dycore:-".false."} - dycore_only=${adiabatic:-".false."} - chksum_debug=${chksum_debug:-".false."} - print_freq=${print_freq:-6} - - # the pre-conditioning of the solution - # =0 implies no pre-conditioning - # >0 means new adiabatic pre-conditioning - # <0 means older adiabatic pre-conditioning - na_init=${na_init:-1} - - local suite_file="${HOMEgfs}/sorc/ufs_model.fd/UFSATM/ccpp/suites/suite_${CCPP_SUITE}.xml" - if [[ ! -f "${suite_file}" ]]; then - echo "FATAL ERROR: CCPP Suite file ${suite_file} does not exist, ABORT!" - exit 2 - fi - - # Scan suite file to determine whether it uses Noah-MP - local num_noahmpdrv - num_noahmpdrv=$(grep -c noahmpdrv "${suite_file}") - if (( num_noahmpdrv > 0 )); then - lsm="2" - lheatstrg=".false." - landice=".false." - iopt_dveg=${iopt_dveg:-"4"} - iopt_crs=${iopt_crs:-"2"} - iopt_btr=${iopt_btr:-"1"} - iopt_run=${iopt_run:-"1"} - iopt_sfc=${iopt_sfc:-"1"} - iopt_frz=${iopt_frz:-"1"} - iopt_inf=${iopt_inf:-"1"} - iopt_rad=${iopt_rad:-"3"} - iopt_alb=${iopt_alb:-"1"} - iopt_snf=${iopt_snf:-"4"} - iopt_tbot=${iopt_tbot:-"2"} - iopt_stc=${iopt_stc:-"3"} - IALB=${IALB:-2} - IEMS=${IEMS:-2} - else - lsm="1" - lheatstrg=".true." - landice=".true." - iopt_dveg=${iopt_dveg:-"1"} - iopt_crs=${iopt_crs:-"1"} - iopt_btr=${iopt_btr:-"1"} - iopt_run=${iopt_run:-"1"} - iopt_sfc=${iopt_sfc:-"1"} - iopt_frz=${iopt_frz:-"1"} - iopt_inf=${iopt_inf:-"1"} - iopt_rad=${iopt_rad:-"1"} - iopt_alb=${iopt_alb:-"2"} - iopt_snf=${iopt_snf:-"4"} - iopt_tbot=${iopt_tbot:-"2"} - iopt_stc=${iopt_stc:-"1"} - IALB=${IALB:-1} - IEMS=${IEMS:-1} - fi - - if [[ "${TYPE}" == "nh" ]]; then # non-hydrostatic options - hydrostatic=".false." - phys_hydrostatic=".false." # enable heating in hydrostatic balance in non-hydrostatic simulation - use_hydro_pressure=".false." # use hydrostatic pressure for physics - make_nh=".true." # running in non-hydrostatic mode - pass_full_omega_to_physics_in_non_hydrostatic_mode=".true." - else # hydrostatic options - hydrostatic=".true." - phys_hydrostatic=".false." # ignored when hydrostatic = T - use_hydro_pressure=".false." # ignored when hydrostatic = T - make_nh=".false." # running in hydrostatic mode - fi - - # Conserve total energy as heat globally - consv_te=${consv_te:-1.} # range 0.-1., 1. will restore energy to orig. val. before physics - if [[ "${DO_NEST:-NO}" == "YES" ]] ; then - consv_te=0 - k_split=${k_split:-1} - k_split_nest=${k_split_nest:-4} - else +FV3_predet() { + echo "SUB ${FUNCNAME[0]}: Defining variables for FV3" + + if [[ ! -d "${COMOUT_ATMOS_HISTORY}" ]]; then mkdir -p "${COMOUT_ATMOS_HISTORY}"; fi + if [[ ! -d "${COMOUT_ATMOS_MASTER}" ]]; then mkdir -p "${COMOUT_ATMOS_MASTER}"; fi + if [[ ! -d "${COMOUT_ATMOS_RESTART}" ]]; then mkdir -p "${COMOUT_ATMOS_RESTART}"; fi + if [[ ! -d "${DATAoutput}/FV3ATM_OUTPUT" ]]; then mkdir -p "${DATAoutput}/FV3ATM_OUTPUT"; fi + if [[ ! -d "${DATArestart}/FV3_RESTART" ]]; then mkdir -p "${DATArestart}/FV3_RESTART"; fi + + # The $DATA/RESTART directory is used for writing FV3 restart files (it is hard-wired in the model) + # Link the output and restart directories to the DATA directory + ${NLN} "${DATAoutput}/FV3ATM_OUTPUT" "${DATA}/FV3ATM_OUTPUT" + ${NLN} "${DATArestart}/FV3_RESTART" "${DATA}/RESTART" + + FHZERO=${FHZERO:-6} + FHCYC=${FHCYC:-24} + + # Convert output settings into an explicit list for FV3 + # Create an FV3 fhr list to be used in the filenames + FV3_OUTPUT_FH="" + local fhr=${FHMIN} + if [[ "${FHOUT_HF}" -gt 0 && "${FHMAX_HF}" -gt 0 ]]; then + FV3_OUTPUT_FH="${FV3_OUTPUT_FH} $(seq -s ' ' "${FHMIN}" "${FHOUT_HF}" "${FHMAX_HF}")" + fhr=${FHMAX_HF} + fi + FV3_OUTPUT_FH="${FV3_OUTPUT_FH} $(seq -s ' ' "${fhr}" "${FHOUT}" "${FHMAX}")" + + if [[ "${FHOUT_HF}" -eq "${FHOUT}" ]]; then + FV3_OUTPUT_FH_NML="${FHOUT} -1" + else + FV3_OUTPUT_FH_NML="${FV3_OUTPUT_FH}" + fi + + # IAU options + IAUFHRS=${IAUFHRS:-0} + IAU_DELTHRS=${IAU_DELTHRS:-0} + + #------------------------------------------------------------------ + # changeable parameters + # dycore definitions + res="${CASE:1}" + resh="${CASE_HIST:1}" + resp=$((res + 1)) + npx=${resp} + npy=${resp} + npz=$((LEVS - 1)) + io_layout="1,1" + #ncols=$(( (${npx}-1)*(${npy}-1)*3/2 )) + + # spectral truncation and regular grid resolution based on FV3 resolution + JCAP_CASE=$((2 * res - 2)) + LONB_CASE=$((4 * res)) + LATB_CASE=$((2 * res)) + + JCAP_CASE_HIST=$((2 * resh - 2)) + LONB_CASE_HIST=$((4 * resh)) + LATB_CASE_HIST=$((2 * resh)) + + JCAP=${JCAP:-${JCAP_CASE}} + LONB=${LONB:-${LONB_CASE}} + LATB=${LATB:-${LATB_CASE}} + + LONB_IMO=${LONB_IMO:-${LONB_CASE_HIST}} + LATB_JMO=${LATB_JMO:-${LATB_CASE_HIST}} + + # NSST Options + # nstf_name contains the NSST related parameters + # nstf_name(1) : NST_MODEL (NSST Model) : 0 = OFF, 1 = ON but uncoupled, 2 = ON and coupled + # nstf_name(2) : NST_SPINUP : 0 = OFF, 1 = ON, + # nstf_name(3) : NST_RESV (Reserved, NSST Analysis) : 0 = OFF, 1 = ON + # nstf_name(4) : ZSEA1 (in mm) : 0 + # nstf_name(5) : ZSEA2 (in mm) : 0 + # nst_anl : .true. or .false., NSST analysis over lake + NST_MODEL=${NST_MODEL:-0} + NST_SPINUP=${NST_SPINUP:-0} + NST_RESV=${NST_RESV-0} + ZSEA1=${ZSEA1:-0} + ZSEA2=${ZSEA2:-0} + nstf_name=${nstf_name:-"${NST_MODEL},${NST_SPINUP},${NST_RESV},${ZSEA1},${ZSEA2}"} + nst_anl=${nst_anl:-".false."} + + # blocking factor used for threading and general physics performance + #nyblocks=$(expr \( $npy - 1 \) \/ $layout_y ) + #nxblocks=$(expr \( $npx - 1 \) \/ $layout_x \/ 32) + #if [[ $nxblocks -le 0 ]]; then nxblocks=1 ; fi + blocksize=${blocksize:-32} + + # variables for controlling initialization of NCEP/NGGPS ICs + filtered_terrain=${filtered_terrain:-".true."} + gfs_dwinds=${gfs_dwinds:-".true."} + + # various debug options + no_dycore=${no_dycore:-".false."} + dycore_only=${adiabatic:-".false."} + chksum_debug=${chksum_debug:-".false."} + print_freq=${print_freq:-6} + + # the pre-conditioning of the solution + # =0 implies no pre-conditioning + # >0 means new adiabatic pre-conditioning + # <0 means older adiabatic pre-conditioning + na_init=${na_init:-1} + + local suite_file="${HOMEgfs}/sorc/ufs_model.fd/UFSATM/ccpp/suites/suite_${CCPP_SUITE}.xml" + if [[ ! -f "${suite_file}" ]]; then + echo "FATAL ERROR: CCPP Suite file ${suite_file} does not exist, ABORT!" + exit 2 + fi + + # Scan suite file to determine whether it uses Noah-MP + local num_noahmpdrv + num_noahmpdrv=$(grep -c noahmpdrv "${suite_file}") + if [[ "${num_noahmpdrv}" -gt 0 ]]; then + lsm="2" + lheatstrg=".false." + landice=".false." + iopt_dveg=${iopt_dveg:-"4"} + iopt_crs=${iopt_crs:-"2"} + iopt_btr=${iopt_btr:-"1"} + iopt_run=${iopt_run:-"1"} + iopt_sfc=${iopt_sfc:-"1"} + iopt_frz=${iopt_frz:-"1"} + iopt_inf=${iopt_inf:-"1"} + iopt_rad=${iopt_rad:-"3"} + iopt_alb=${iopt_alb:-"1"} + iopt_snf=${iopt_snf:-"4"} + iopt_tbot=${iopt_tbot:-"2"} + iopt_stc=${iopt_stc:-"3"} + IALB=${IALB:-2} + IEMS=${IEMS:-2} + else + lsm="1" + lheatstrg=".true." + landice=".true." + iopt_dveg=${iopt_dveg:-"1"} + iopt_crs=${iopt_crs:-"1"} + iopt_btr=${iopt_btr:-"1"} + iopt_run=${iopt_run:-"1"} + iopt_sfc=${iopt_sfc:-"1"} + iopt_frz=${iopt_frz:-"1"} + iopt_inf=${iopt_inf:-"1"} + iopt_rad=${iopt_rad:-"1"} + iopt_alb=${iopt_alb:-"2"} + iopt_snf=${iopt_snf:-"4"} + iopt_tbot=${iopt_tbot:-"2"} + iopt_stc=${iopt_stc:-"1"} + IALB=${IALB:-1} + IEMS=${IEMS:-1} + fi + + if [[ "${TYPE}" == "nh" ]]; then # non-hydrostatic options + hydrostatic=".false." + phys_hydrostatic=".false." # enable heating in hydrostatic balance in non-hydrostatic simulation + use_hydro_pressure=".false." # use hydrostatic pressure for physics + make_nh=".true." # running in non-hydrostatic mode + pass_full_omega_to_physics_in_non_hydrostatic_mode=".true." + else # hydrostatic options + hydrostatic=".true." + phys_hydrostatic=".false." # ignored when hydrostatic = T + use_hydro_pressure=".false." # ignored when hydrostatic = T + make_nh=".false." # running in hydrostatic mode + fi + + # Conserve total energy as heat globally consv_te=${consv_te:-1.} # range 0.-1., 1. will restore energy to orig. val. before physics - k_split=${k_split:-2} - fi - - # time step parameters in FV3 - n_split=${n_split:-5} - - if [[ "${MONO:0:4}" == "mono" ]]; then # monotonic options - d_con=${d_con_mono:-"0."} - do_vort_damp=".false." - if [[ "${TYPE}" == "nh" ]]; then # monotonic and non-hydrostatic - hord_mt=${hord_mt_nh_mono:-"10"} - hord_xx=${hord_xx_nh_mono:-"10"} - hord_dp=${hord_xx_nh_mono:-"10"} - else # monotonic and hydrostatic - hord_mt=${hord_mt_hydro_mono:-"10"} - hord_xx=${hord_xx_hydro_mono:-"10"} - hord_dp=${hord_xx_hydro_mono:-"10"} - kord_tm=${kord_tm_hydro_mono:-"-12"} - kord_mt=${kord_mt_hydro_mono:-"12"} - kord_wz=${kord_wz_hydro_mono:-"12"} - kord_tr=${kord_tr_hydro_mono:-"12"} - fi - else # non-monotonic options - d_con=${d_con_nonmono:-"1."} - do_vort_damp=".true." - if [[ "${TYPE}" == "nh" ]]; then # non-monotonic and non-hydrostatic - hord_mt=${hord_mt_nh_nonmono:-"5"} - hord_xx=${hord_xx_nh_nonmono:-"5"} - hord_dp=${hord_dp_nh_nonmono:-"-5"} - else # non-monotonic and hydrostatic - hord_mt=${hord_mt_hydro_nonmono:-"10"} - hord_xx=${hord_xx_hydro_nonmono:-"10"} - hord_dp=${hord_xx_hydro_nonmono:-"10"} - fi - fi - - if [[ "${MONO:0:4}" != "mono" && "${TYPE}" == "nh" ]]; then - vtdm4=${vtdm4_nh_nonmono:-"0.06"} - else - vtdm4=${vtdm4:-"0.05"} - fi - - # Initial conditions are chgres-ed from GFS analysis file - nggps_ic=${nggps_ic:-".true."} - ncep_ic=${ncep_ic:-".false."} - external_ic=".true." - mountain=".false." - warm_start=".false." - read_increment=".false." - res_latlon_dynamics='""' - increment_file_on_native_grid=".false." - - # Stochastic Physics Options - do_skeb=".false." - do_shum=".false." - do_sppt=".false." - do_ca=".false." - ISEED=0 - local imem=${MEMBER#0} - local base_seed=$((current_cycle*10000 + imem*100)) - - if [[ "${DO_SKEB:-}" == "YES" ]]; then - do_skeb=".true." - ISEED_SKEB=$((base_seed + 1)) - fi - - if [[ "${DO_SHUM:-}" == "YES" ]]; then - do_shum=".true." - ISEED_SHUM=$((base_seed + 2)) - fi - - if [[ "${DO_SPPT:-}" == "YES" ]]; then - do_sppt=".true." - ISEED_SPPT=$((base_seed + 3)),$((base_seed + 4)),$((base_seed + 5)),$((base_seed + 6)),$((base_seed + 7)) - fi - - if [[ "${DO_CA:-}" == "YES" ]]; then - do_ca=".true." - ISEED_CA=$(( (base_seed + 18) % 2147483647 )) - fi - - if [[ "${DO_LAND_PERT:-}" == "YES" ]]; then - lndp_type=${lndp_type:-2} - ISEED_LNDP=$(( (base_seed + 5) % 2147483647 )) - LNDP_TAU=${LNDP_TAU:-21600} - LNDP_SCALE=${LNDP_SCALE:-500000} - lndp_var_list=${lndp_var_list:-"'smc', 'vgf',"} - lndp_prt_list=${lndp_prt_list:-"0.2,0.1"} - n_var_lndp=$(echo "${lndp_var_list}" | wc -w) - fi - - #-------------------------------------------------------------------------- - - # Fix files - FNGLAC=${FNGLAC:-"${FIXgfs}/am/global_glacier.2x2.grb"} - FNMXIC=${FNMXIC:-"${FIXgfs}/am/global_maxice.2x2.grb"} - FNTSFC=${FNTSFC:-"${FIXgfs}/am/RTGSST.1982.2012.monthly.clim.grb"} - FNSNOC=${FNSNOC:-"${FIXgfs}/am/global_snoclim.1.875.grb"} - FNZORC=${FNZORC:-"igbp"} - FNAISC=${FNAISC:-"${FIXgfs}/am/IMS-NIC.blended.ice.monthly.clim.grb"} - FNALBC2=${FNALBC2:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.facsf.tileX.nc"} - FNTG3C=${FNTG3C:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.substrate_temperature.tileX.nc"} - FNVEGC=${FNVEGC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_greenness.tileX.nc"} - FNMSKH=${FNMSKH:-"${FIXgfs}/am/global_slmask.t1534.3072.1536.grb"} - FNVMNC=${FNVMNC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_greenness.tileX.nc"} - FNVMXC=${FNVMXC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_greenness.tileX.nc"} - FNSLPC=${FNSLPC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.slope_type.tileX.nc"} - FNALBC=${FNALBC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.snowfree_albedo.tileX.nc"} - FNVETC=${FNVETC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_type.tileX.nc"} - FNSOTC=${FNSOTC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.soil_type.tileX.nc"} - FNSOCC=${FNSOCC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.soil_color.tileX.nc"} - FNABSC=${FNABSC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.maximum_snow_albedo.tileX.nc"} - FNSMCC=${FNSMCC:-"${FIXgfs}/am/global_soilmgldas.statsgo.t${JCAP}.${LONB}.${LATB}.grb"} - - # If the appropriate resolution fix file is not present, use the highest resolution available (T1534) - if [[ ! -f "${FNSMCC}" ]]; then - FNSMCC="${FIXgfs}/am/global_soilmgldas.statsgo.t1534.3072.1536.grb" - fi - - # Grid and orography data - if [[ "${cplflx}" == ".false." ]] ; then - cpreq "${FIXorog}/${CASE}/${CASE}_mosaic.nc" "${DATA}/INPUT/grid_spec.nc" - else - cpreq "${FIXorog}/${CASE}/${CASE}_mosaic.nc" "${DATA}/INPUT/${CASE}_mosaic.nc" - fi - - # Files for GWD - cpreq "${FIXugwd}/ugwp_limb_tau.nc" "${DATA}/ugwp_limb_tau.nc" - - # Files for orography, GWD tiles - local tt - for (( tt = 1; tt <= ntiles; tt++ )); do - cpreq "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile${tt}.nc" "${DATA}/INPUT/oro_data.tile${tt}.nc" - cpreq "${FIXorog}/${CASE}/${CASE}_grid.tile${tt}.nc" "${DATA}/INPUT/${CASE}_grid.tile${tt}.nc" - cpreq "${FIXugwd}/${CASE}/${CASE}_oro_data_ls.tile${tt}.nc" "${DATA}/INPUT/oro_data_ls.tile${tt}.nc" - cpreq "${FIXugwd}/${CASE}/${CASE}_oro_data_ss.tile${tt}.nc" "${DATA}/INPUT/oro_data_ss.tile${tt}.nc" - done - if [[ "${DO_NEST:-NO}" == "YES" ]] ; then - ${NLN} "${DATA}/INPUT/oro_data.tile7.nc" "${DATA}/INPUT/oro_data.nest02.tile7.nc" - ${NLN} "${DATA}/INPUT/${CASE}_grid.tile7.nc" "${DATA}/INPUT/${CASE}_grid.nest02.tile7.nc" - ${NLN} "${DATA}/INPUT/${CASE}_grid.tile7.nc" "${DATA}/INPUT/grid.nest02.tile7.nc" - ${NLN} "${DATA}/INPUT/oro_data_ls.tile7.nc" "${DATA}/INPUT/oro_data_ls.nest02.tile7.nc" - ${NLN} "${DATA}/INPUT/oro_data_ss.tile7.nc" "${DATA}/INPUT/oro_data_ss.nest02.tile7.nc" - fi - - # NoahMP table - local noahmptablefile="${PARMgfs}/ufs/noahmptable.tbl" - cpreq "${noahmptablefile}" "${DATA}/noahmptable.tbl" - - # Thompson microphysics fix files - if (( imp_physics == 8 )); then - cpreq "${FIXgfs}/am/CCN_ACTIVATE.BIN" "${DATA}/CCN_ACTIVATE.BIN" - cpreq "${FIXgfs}/am/freezeH2O.dat" "${DATA}/freezeH2O.dat" - cpreq "${FIXgfs}/am/qr_acr_qgV2.dat" "${DATA}/qr_acr_qgV2.dat" - cpreq "${FIXgfs}/am/qr_acr_qsV2.dat" "${DATA}/qr_acr_qsV2.dat" - fi - - if [[ "${new_o3forc:-YES}" == "YES" ]]; then - if [[ "${o3forc_params:-McCormack}" == "McCormack-empirical-sh-ozh" ]]; then - O3FORC="ozprdlos_2015_new_sbuvO3_tclm15_nuchem_shozhvlogp.f77" + if [[ "${DO_NEST:-NO}" == "YES" ]]; then + consv_te=0 + k_split=${k_split:-1} + k_split_nest=${k_split_nest:-4} else - O3FORC="ozprdlos_2015_new_sbuvO3_tclm15_nuchem.f77" - fi - else - O3FORC="global_o3prdlos.f77" - fi - H2OFORC=${H2OFORC:-"global_h2o_pltc.f77"} - cpreq "${FIXgfs}/am/${O3FORC}" "${DATA}/global_o3prdlos.f77" - cpreq "${FIXgfs}/am/${H2OFORC}" "${DATA}/global_h2oprdlos.f77" - - # GFS standard input data - - ISOL=${ISOL:-2} - - cpreq "${FIXgfs}/am/global_solarconstant_noaa_an.txt" "${DATA}/solarconstant_noaa_an.txt" - cpreq "${FIXgfs}/am/global_sfc_emissivity_idx.txt" "${DATA}/sfc_emissivity_idx.txt" - - # Aerosol options - IAER=${IAER:-1011} - MERRA2_6ym=${MERRA2_6ym:-".false."} - ## merra2 aerosol climo - if (( IAER == 1011 )); then - if [[ "${MERRA2_6ym}" == ".false." ]]; then -# local month mm - for (( month = 1; month <=12; month++ )); do - mm=$(printf %02d "${month}") - cpreq "${FIXgfs}/aer/merra2.aerclim.2014-2023.m${mm}.nc" "aeroclim.m${mm}.nc" - done - elif [[ "${MERRA2_6ym}" == ".true." ]]; then - year=${current_cycle:0:4} - for i in {1980..2300..5} - do - if [[ ${year} -le ${i} ]] - then - Eyear=$(printf %04d "${i}") - Syear=$(( i - 5 )) - break + consv_te=${consv_te:-1.} # range 0.-1., 1. will restore energy to orig. val. before physics + k_split=${k_split:-2} + fi + + # time step parameters in FV3 + n_split=${n_split:-5} + + if [[ "${MONO:0:4}" == "mono" ]]; then # monotonic options + d_con=${d_con_mono:-"0."} + do_vort_damp=".false." + if [[ "${TYPE}" == "nh" ]]; then # monotonic and non-hydrostatic + hord_mt=${hord_mt_nh_mono:-"10"} + hord_xx=${hord_xx_nh_mono:-"10"} + hord_dp=${hord_xx_nh_mono:-"10"} + else # monotonic and hydrostatic + hord_mt=${hord_mt_hydro_mono:-"10"} + hord_xx=${hord_xx_hydro_mono:-"10"} + hord_dp=${hord_xx_hydro_mono:-"10"} + kord_tm=${kord_tm_hydro_mono:-"-12"} + kord_mt=${kord_mt_hydro_mono:-"12"} + kord_wz=${kord_wz_hydro_mono:-"12"} + kord_tr=${kord_tr_hydro_mono:-"12"} fi - done - for (( month = 1; month <=12; month++ )); do - mm=$(printf %02d "${month}") - cpreq "${FIXgfs}/aer/y${Syear}-${Eyear}/merra2_${Syear}-${Eyear}_${mm}.nc" "aeroclim.m${mm}.nc" - done - fi # if [[ "${MERRA2_6ym}" == ".true." ]]; - fi # if (( IAER == 1011 )) - - cpreq "${FIXgfs}/am/global_climaeropac_global.txt" "${DATA}/aerosol.dat" - if (( IAER > 0 )) ; then - local file - for file in "${FIXgfs}/am/global_volcanic_aerosols"* ; do - cpreq "${file}" "${DATA}/$(basename "${file//global_}")" - done - fi - - cpreq "${FIXgfs}/lut/optics_BC.v1_3.dat" "${DATA}/optics_BC.dat" - cpreq "${FIXgfs}/lut/optics_OC.v1_3.dat" "${DATA}/optics_OC.dat" - cpreq "${FIXgfs}/lut/optics_DU.v15_3.dat" "${DATA}/optics_DU.dat" - cpreq "${FIXgfs}/lut/optics_SS.v3_3.dat" "${DATA}/optics_SS.dat" - cpreq "${FIXgfs}/lut/optics_SU.v1_3.dat" "${DATA}/optics_SU.dat" - - # CO2 options - ICO2=${ICO2:-2} - - cpreq "${FIXgfs}/am/global_co2historicaldata_glob.txt" "${DATA}/co2historicaldata_glob.txt" - cpreq "${FIXgfs}/am/co2monthlycyc.txt" "${DATA}/co2monthlycyc.txt" - # Set historical CO2 values based on whether this is a reforecast run or not - # Ref. issue 2403 - local co2dir - co2dir="fix_co2_proj" - if [[ "${reforecast:-}" == "YES" ]]; then - co2dir="co2dat_4a" - fi - if (( ICO2 > 0 )); then - local file - for file in "${FIXgfs}/am/${co2dir}/global_co2historicaldata"* ; do - cpreq "${file}" "${DATA}/$(basename "${file//global_}")" - done - fi - - # Inline UPP fix files - if [[ "${WRITE_DOPOST:-}" == ".true." ]]; then - cpreq "${POSTGRB2TBL:-${PARMgfs}/post/params_grib2_tbl_new}" "${DATA}/params_grib2_tbl_new" - cpreq "${PARMgfs}/ufs/post_itag_gfs" "${DATA}/itag" # TODO: Need a GEFS version when available in the UFS-weather-model - # TODO: These should be replaced with ones from the ufs-weather-model when available there - case ${NET} in - gfs|gcafs) - cpreq "${PARMgfs}/post/gfs/postxconfig-NT-gfs-two.txt" "${DATA}/postxconfig-NT.txt" - cpreq "${PARMgfs}/post/gfs/postxconfig-NT-gfs-f00-two.txt" "${DATA}/postxconfig-NT_FH00.txt" - ;; - gefs) - cpreq "${PARMgfs}/post/gefs/postxconfig-NT-gefs.txt" "${DATA}/postxconfig-NT.txt" - cpreq "${PARMgfs}/post/gefs/postxconfig-NT-gefs-f00.txt" "${DATA}/postxconfig-NT_FH00.txt" - # Provide ensemble header information for GEFS - if [[ "${ENSMEM}" == "000" ]]; then - export e1=1 - else - export e1=3 + else # non-monotonic options + d_con=${d_con_nonmono:-"1."} + do_vort_damp=".true." + if [[ "${TYPE}" == "nh" ]]; then # non-monotonic and non-hydrostatic + hord_mt=${hord_mt_nh_nonmono:-"5"} + hord_xx=${hord_xx_nh_nonmono:-"5"} + hord_dp=${hord_dp_nh_nonmono:-"-5"} + else # non-monotonic and hydrostatic + hord_mt=${hord_mt_hydro_nonmono:-"10"} + hord_xx=${hord_xx_hydro_nonmono:-"10"} + hord_dp=${hord_xx_hydro_nonmono:-"10"} fi - export e2="${ENSMEM:1:2}" - export e3="${NMEM_ENS}" - ;; - sfs) - cpreq "${PARMgfs}/post/sfs/postxconfig-NT-sfs.txt" "${DATA}/postxconfig-NT.txt" - cpreq "${PARMgfs}/post/sfs/postxconfig-NT-sfs.txt" "${DATA}/postxconfig-NT_FH00.txt" - # Provide ensemble header information for SFS - if [[ "${ENSMEM}" == "000" ]]; then - export e1=1 + fi + + if [[ "${MONO:0:4}" != "mono" && "${TYPE}" == "nh" ]]; then + vtdm4=${vtdm4_nh_nonmono:-"0.06"} + else + vtdm4=${vtdm4:-"0.05"} + fi + + # Initial conditions are chgres-ed from GFS analysis file + nggps_ic=${nggps_ic:-".true."} + ncep_ic=${ncep_ic:-".false."} + external_ic=".true." + mountain=".false." + warm_start=".false." + read_increment=".false." + res_latlon_dynamics='""' + increment_file_on_native_grid=".false." + + # Stochastic Physics Options + do_skeb=".false." + do_shum=".false." + do_sppt=".false." + do_ca=".false." + ISEED=0 + local imem=${MEMBER#0} + local base_seed=$((current_cycle * 10000 + imem * 100)) + + if [[ "${DO_SKEB:-}" == "YES" ]]; then + do_skeb=".true." + ISEED_SKEB=$((base_seed + 1)) + fi + + if [[ "${DO_SHUM:-}" == "YES" ]]; then + do_shum=".true." + ISEED_SHUM=$((base_seed + 2)) + fi + + if [[ "${DO_SPPT:-}" == "YES" ]]; then + do_sppt=".true." + ISEED_SPPT=$((base_seed + 3)),$((base_seed + 4)),$((base_seed + 5)),$((base_seed + 6)),$((base_seed + 7)) + fi + + if [[ "${DO_CA:-}" == "YES" ]]; then + do_ca=".true." + ISEED_CA=$(((base_seed + 18) % 2147483647)) + fi + + if [[ "${DO_LAND_PERT:-}" == "YES" ]]; then + lndp_type=${lndp_type:-2} + ISEED_LNDP=$(((base_seed + 5) % 2147483647)) + LNDP_TAU=${LNDP_TAU:-21600} + LNDP_SCALE=${LNDP_SCALE:-500000} + lndp_var_list=${lndp_var_list:-"'smc', 'vgf',"} + lndp_prt_list=${lndp_prt_list:-"0.2,0.1"} + n_var_lndp=$(echo "${lndp_var_list}" | wc -w) + fi + + #-------------------------------------------------------------------------- + + # Fix files + FNGLAC=${FNGLAC:-"${FIXgfs}/am/global_glacier.2x2.grb"} + FNMXIC=${FNMXIC:-"${FIXgfs}/am/global_maxice.2x2.grb"} + FNTSFC=${FNTSFC:-"${FIXgfs}/am/RTGSST.1982.2012.monthly.clim.grb"} + FNSNOC=${FNSNOC:-"${FIXgfs}/am/global_snoclim.1.875.grb"} + FNZORC=${FNZORC:-"igbp"} + FNAISC=${FNAISC:-"${FIXgfs}/am/IMS-NIC.blended.ice.monthly.clim.grb"} + FNALBC2=${FNALBC2:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.facsf.tileX.nc"} + FNTG3C=${FNTG3C:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.substrate_temperature.tileX.nc"} + FNVEGC=${FNVEGC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_greenness.tileX.nc"} + FNMSKH=${FNMSKH:-"${FIXgfs}/am/global_slmask.t1534.3072.1536.grb"} + FNVMNC=${FNVMNC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_greenness.tileX.nc"} + FNVMXC=${FNVMXC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_greenness.tileX.nc"} + FNSLPC=${FNSLPC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.slope_type.tileX.nc"} + FNALBC=${FNALBC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.snowfree_albedo.tileX.nc"} + FNVETC=${FNVETC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.vegetation_type.tileX.nc"} + FNSOTC=${FNSOTC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.soil_type.tileX.nc"} + FNSOCC=${FNSOCC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.soil_color.tileX.nc"} + FNABSC=${FNABSC:-"${FIXorog}/${CASE}/sfc/${CASE}.mx${OCNRES}.maximum_snow_albedo.tileX.nc"} + FNSMCC=${FNSMCC:-"${FIXgfs}/am/global_soilmgldas.statsgo.t${JCAP}.${LONB}.${LATB}.grb"} + + # If the appropriate resolution fix file is not present, use the highest resolution available (T1534) + if [[ ! -f "${FNSMCC}" ]]; then + FNSMCC="${FIXgfs}/am/global_soilmgldas.statsgo.t1534.3072.1536.grb" + fi + + # Grid and orography data + if [[ "${cplflx}" == ".false." ]]; then + cpreq "${FIXorog}/${CASE}/${CASE}_mosaic.nc" "${DATA}/INPUT/grid_spec.nc" + else + cpreq "${FIXorog}/${CASE}/${CASE}_mosaic.nc" "${DATA}/INPUT/${CASE}_mosaic.nc" + fi + + # Files for GWD + cpreq "${FIXugwd}/ugwp_limb_tau.nc" "${DATA}/ugwp_limb_tau.nc" + + # Files for orography, GWD tiles + local tt + for ((tt = 1; tt <= ntiles; tt++)); do + cpreq "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile${tt}.nc" "${DATA}/INPUT/oro_data.tile${tt}.nc" + cpreq "${FIXorog}/${CASE}/${CASE}_grid.tile${tt}.nc" "${DATA}/INPUT/${CASE}_grid.tile${tt}.nc" + cpreq "${FIXugwd}/${CASE}/${CASE}_oro_data_ls.tile${tt}.nc" "${DATA}/INPUT/oro_data_ls.tile${tt}.nc" + cpreq "${FIXugwd}/${CASE}/${CASE}_oro_data_ss.tile${tt}.nc" "${DATA}/INPUT/oro_data_ss.tile${tt}.nc" + done + if [[ "${DO_NEST:-NO}" == "YES" ]]; then + ${NLN} "${DATA}/INPUT/oro_data.tile7.nc" "${DATA}/INPUT/oro_data.nest02.tile7.nc" + ${NLN} "${DATA}/INPUT/${CASE}_grid.tile7.nc" "${DATA}/INPUT/${CASE}_grid.nest02.tile7.nc" + ${NLN} "${DATA}/INPUT/${CASE}_grid.tile7.nc" "${DATA}/INPUT/grid.nest02.tile7.nc" + ${NLN} "${DATA}/INPUT/oro_data_ls.tile7.nc" "${DATA}/INPUT/oro_data_ls.nest02.tile7.nc" + ${NLN} "${DATA}/INPUT/oro_data_ss.tile7.nc" "${DATA}/INPUT/oro_data_ss.nest02.tile7.nc" + fi + + # NoahMP table + local noahmptablefile="${PARMgfs}/ufs/noahmptable.tbl" + cpreq "${noahmptablefile}" "${DATA}/noahmptable.tbl" + + # Thompson microphysics fix files + if ((imp_physics == 8)); then + cpreq "${FIXgfs}/am/CCN_ACTIVATE.BIN" "${DATA}/CCN_ACTIVATE.BIN" + cpreq "${FIXgfs}/am/freezeH2O.dat" "${DATA}/freezeH2O.dat" + cpreq "${FIXgfs}/am/qr_acr_qgV2.dat" "${DATA}/qr_acr_qgV2.dat" + cpreq "${FIXgfs}/am/qr_acr_qsV2.dat" "${DATA}/qr_acr_qsV2.dat" + fi + + if [[ "${new_o3forc:-YES}" == "YES" ]]; then + if [[ "${o3forc_params:-McCormack}" == "McCormack-empirical-sh-ozh" ]]; then + O3FORC="ozprdlos_2015_new_sbuvO3_tclm15_nuchem_shozhvlogp.f77" else - export e1=3 + O3FORC="ozprdlos_2015_new_sbuvO3_tclm15_nuchem.f77" fi - export e2="${ENSMEM:1:2}" - export e3="${NMEM_ENS}" - ;; - *) - echo "FATAL ERROR: Unknown NET ${NET}, unable to determine appropriate post files" - exit 20 - esac - fi + else + O3FORC="global_o3prdlos.f77" + fi + H2OFORC=${H2OFORC:-"global_h2o_pltc.f77"} + cpreq "${FIXgfs}/am/${O3FORC}" "${DATA}/global_o3prdlos.f77" + cpreq "${FIXgfs}/am/${H2OFORC}" "${DATA}/global_h2oprdlos.f77" + + # GFS standard input data + + ISOL=${ISOL:-2} + + cpreq "${FIXgfs}/am/global_solarconstant_noaa_an.txt" "${DATA}/solarconstant_noaa_an.txt" + cpreq "${FIXgfs}/am/global_sfc_emissivity_idx.txt" "${DATA}/sfc_emissivity_idx.txt" + + # Aerosol options + IAER=${IAER:-1011} + MERRA2_6ym=${MERRA2_6ym:-".false."} + ## merra2 aerosol climo + if ((IAER == 1011)); then + if [[ "${MERRA2_6ym}" == ".false." ]]; then + # local month mm + for ((month = 1; month <= 12; month++)); do + mm=$(printf %02d "${month}") + cpreq "${FIXgfs}/aer/merra2.aerclim.2014-2023.m${mm}.nc" "aeroclim.m${mm}.nc" + done + elif [[ "${MERRA2_6ym}" == ".true." ]]; then + year=${current_cycle:0:4} + for i in {1980..2300..5}; do + if [[ ${year} -le ${i} ]]; then + Eyear=$(printf %04d "${i}") + Syear=$((i - 5)) + break + fi + done + for ((month = 1; month <= 12; month++)); do + mm=$(printf %02d "${month}") + cpreq "${FIXgfs}/aer/y${Syear}-${Eyear}/merra2_${Syear}-${Eyear}_${mm}.nc" "aeroclim.m${mm}.nc" + done + fi # if [[ "${MERRA2_6ym}" == ".true." ]]; + fi # if (( IAER == 1011 )) + + cpreq "${FIXgfs}/am/global_climaeropac_global.txt" "${DATA}/aerosol.dat" + if ((IAER > 0)); then + local file + for file in "${FIXgfs}/am/global_volcanic_aerosols"*; do + cpreq "${file}" "${DATA}/$(basename "${file//global_/}")" + done + fi + + cpreq "${FIXgfs}/lut/optics_BC.v1_3.dat" "${DATA}/optics_BC.dat" + cpreq "${FIXgfs}/lut/optics_OC.v1_3.dat" "${DATA}/optics_OC.dat" + cpreq "${FIXgfs}/lut/optics_DU.v15_3.dat" "${DATA}/optics_DU.dat" + cpreq "${FIXgfs}/lut/optics_SS.v3_3.dat" "${DATA}/optics_SS.dat" + cpreq "${FIXgfs}/lut/optics_SU.v1_3.dat" "${DATA}/optics_SU.dat" + + # CO2 options + ICO2=${ICO2:-2} + + cpreq "${FIXgfs}/am/global_co2historicaldata_glob.txt" "${DATA}/co2historicaldata_glob.txt" + cpreq "${FIXgfs}/am/co2monthlycyc.txt" "${DATA}/co2monthlycyc.txt" + # Set historical CO2 values based on whether this is a reforecast run or not + # Ref. issue 2403 + local co2dir + co2dir="fix_co2_proj" + if [[ "${reforecast:-}" == "YES" ]]; then + co2dir="co2dat_4a" + fi + if ((ICO2 > 0)); then + local file + for file in "${FIXgfs}/am/${co2dir}/global_co2historicaldata"*; do + cpreq "${file}" "${DATA}/$(basename "${file//global_/}")" + done + fi + + # Inline UPP fix files + if [[ "${WRITE_DOPOST:-}" == ".true." ]]; then + cpreq "${POSTGRB2TBL:-${PARMgfs}/post/params_grib2_tbl_new}" "${DATA}/params_grib2_tbl_new" + cpreq "${PARMgfs}/ufs/post_itag_gfs" "${DATA}/itag" # TODO: Need a GEFS version when available in the UFS-weather-model + # TODO: These should be replaced with ones from the ufs-weather-model when available there + case ${NET} in + gfs | gcafs) + cpreq "${PARMgfs}/post/gfs/postxconfig-NT-gfs-two.txt" "${DATA}/postxconfig-NT.txt" + cpreq "${PARMgfs}/post/gfs/postxconfig-NT-gfs-f00-two.txt" "${DATA}/postxconfig-NT_FH00.txt" + ;; + gefs) + cpreq "${PARMgfs}/post/gefs/postxconfig-NT-gefs.txt" "${DATA}/postxconfig-NT.txt" + cpreq "${PARMgfs}/post/gefs/postxconfig-NT-gefs-f00.txt" "${DATA}/postxconfig-NT_FH00.txt" + # Provide ensemble header information for GEFS + if [[ "${ENSMEM}" == "000" ]]; then + export e1=1 + else + export e1=3 + fi + export e2="${ENSMEM:1:2}" + export e3="${NMEM_ENS}" + ;; + sfs) + cpreq "${PARMgfs}/post/sfs/postxconfig-NT-sfs.txt" "${DATA}/postxconfig-NT.txt" + cpreq "${PARMgfs}/post/sfs/postxconfig-NT-sfs.txt" "${DATA}/postxconfig-NT_FH00.txt" + # Provide ensemble header information for SFS + if [[ "${ENSMEM}" == "000" ]]; then + export e1=1 + else + export e1=3 + fi + export e2="${ENSMEM:1:2}" + export e3="${NMEM_ENS}" + ;; + *) + echo "FATAL ERROR: Unknown NET ${NET}, unable to determine appropriate post files" + exit 20 + ;; + esac + fi } # Disable variable not used warnings # shellcheck disable=SC2034 -WW3_predet(){ - echo "SUB ${FUNCNAME[0]}: WW3 before run type determination" - - if [[ ! -d "${COMOUT_WAVE_HISTORY}" ]]; then mkdir -p "${COMOUT_WAVE_HISTORY}"; fi - if [[ ! -d "${COMOUT_WAVE_RESTART}" ]]; then mkdir -p "${COMOUT_WAVE_RESTART}"; fi - if [[ ! -d "${DATAoutput}/WW3_OUTPUT" ]]; then mkdir -p "${DATAoutput}/WW3_OUTPUT"; fi - if [[ ! -d "${DATArestart}/WW3_RESTART" ]]; then mkdir -p "${DATArestart}/WW3_RESTART"; fi - - # Link the output and restart directories to the DATA directory - ${NLN} "${DATAoutput}/WW3_OUTPUT" "${DATA}/WW3_OUTPUT" - ${NLN} "${DATArestart}/WW3_RESTART" "${DATA}/WW3_RESTART" - - # Files from wave prep and wave init jobs - # Copy mod_def files for wave grids - local ww3_grid - #if shel, only 1 waveGRD which is linked to mod_def.ww3 - cpreq "${COMIN_WAVE_PREP}/${RUN}.t${cyc}z.mod_def.${waveGRD}.bin" "${DATA}/mod_def.ww3" - - #If pnt_wght file exists, use it to speed up initialization for unstructured grids - # this file does not exist for structured, and the model can run without it (just slower init) - if [[ -f "${FIXgfs}/wave/pnt_wght.${waveGRD}.nc" ]]; then - cpreq "${FIXgfs}/wave/pnt_wght.${waveGRD}.nc" "${DATA}/pnt_wght.ww3.nc" - fi - - # TODO: These are generated by waveprep job, but that job is not used in v17 - # so these files are not generated. - # TODO: Remove these lines or enable waveprep job - if [[ "${WW3ICEINP}" == "YES" ]]; then - local wavicefile="${COMIN_WAVE_PREP}/${RUN}.${WAVEICE_FID}.t${current_cycle:8:2}z.ice" - if [[ ! -f "${wavicefile}" ]]; then - echo "FATAL ERROR: WW3ICEINP='${WW3ICEINP}', but missing ice file '${wavicefile}', ABORT!" - exit 1 - fi - cpreq "${wavicefile}" "${DATA}/ice.${WAVEICE_FID}" - fi - - if [[ "${WW3CURINP}" == "YES" ]]; then - local wavcurfile="${COMIN_WAVE_PREP}/${RUN}.${WAVECUR_FID}.t${current_cycle:8:2}z.cur" - if [[ ! -f "${wavcurfile}" ]]; then - echo "FATAL ERROR: WW3CURINP='${WW3CURINP}', but missing current file '${wavcurfile}', ABORT!" - exit 1 - fi - cpreq "${wavcurfile}" "${DATA}/current.${WAVECUR_FID}" - fi - - # Fix files - #if wave mesh is not the same as the ocean mesh, copy it in the file - if [[ "${MESH_WAV}" == "${MESH_OCN:-mesh.mx${OCNRES}.nc}" ]]; then - echo "Wave is on the same mesh as ocean" - else - echo "Wave is NOT on the same mesh as ocean" - cpreq "${FIXgfs}/wave/${MESH_WAV}" "${DATA}/" - fi +WW3_predet() { + echo "SUB ${FUNCNAME[0]}: WW3 before run type determination" + + if [[ ! -d "${COMOUT_WAVE_HISTORY}" ]]; then mkdir -p "${COMOUT_WAVE_HISTORY}"; fi + if [[ ! -d "${COMOUT_WAVE_RESTART}" ]]; then mkdir -p "${COMOUT_WAVE_RESTART}"; fi + if [[ ! -d "${DATAoutput}/WW3_OUTPUT" ]]; then mkdir -p "${DATAoutput}/WW3_OUTPUT"; fi + if [[ ! -d "${DATArestart}/WW3_RESTART" ]]; then mkdir -p "${DATArestart}/WW3_RESTART"; fi + + # Link the output and restart directories to the DATA directory + ${NLN} "${DATAoutput}/WW3_OUTPUT" "${DATA}/WW3_OUTPUT" + ${NLN} "${DATArestart}/WW3_RESTART" "${DATA}/WW3_RESTART" + + # Files from wave prep and wave init jobs + # Copy mod_def files for wave grids + local ww3_grid + #if shel, only 1 waveGRD which is linked to mod_def.ww3 + cpreq "${COMIN_WAVE_PREP}/${RUN}.t${cyc}z.mod_def.${waveGRD}.bin" "${DATA}/mod_def.ww3" + + #If pnt_wght file exists, use it to speed up initialization for unstructured grids + # this file does not exist for structured, and the model can run without it (just slower init) + if [[ -f "${FIXgfs}/wave/pnt_wght.${waveGRD}.nc" ]]; then + cpreq "${FIXgfs}/wave/pnt_wght.${waveGRD}.nc" "${DATA}/pnt_wght.ww3.nc" + fi + + # TODO: These are generated by waveprep job, but that job is not used in v17 + # so these files are not generated. + # TODO: Remove these lines or enable waveprep job + if [[ "${WW3ICEINP}" == "YES" ]]; then + local wavicefile="${COMIN_WAVE_PREP}/${RUN}.${WAVEICE_FID}.t${current_cycle:8:2}z.ice" + if [[ ! -f "${wavicefile}" ]]; then + echo "FATAL ERROR: WW3ICEINP='${WW3ICEINP}', but missing ice file '${wavicefile}', ABORT!" + exit 1 + fi + cpreq "${wavicefile}" "${DATA}/ice.${WAVEICE_FID}" + fi + + if [[ "${WW3CURINP}" == "YES" ]]; then + local wavcurfile="${COMIN_WAVE_PREP}/${RUN}.${WAVECUR_FID}.t${current_cycle:8:2}z.cur" + if [[ ! -f "${wavcurfile}" ]]; then + echo "FATAL ERROR: WW3CURINP='${WW3CURINP}', but missing current file '${wavcurfile}', ABORT!" + exit 1 + fi + cpreq "${wavcurfile}" "${DATA}/current.${WAVECUR_FID}" + fi + + # Fix files + #if wave mesh is not the same as the ocean mesh, copy it in the file + if [[ "${MESH_WAV}" == "${MESH_OCN:-mesh.mx${OCNRES}.nc}" ]]; then + echo "Wave is on the same mesh as ocean" + else + echo "Wave is NOT on the same mesh as ocean" + cpreq "${FIXgfs}/wave/${MESH_WAV}" "${DATA}/" + fi } # shellcheck disable=SC2034 -CICE_predet(){ - echo "SUB ${FUNCNAME[0]}: CICE before run type determination" +CICE_predet() { + echo "SUB ${FUNCNAME[0]}: CICE before run type determination" - if [[ ! -d "${COMOUT_ICE_HISTORY}" ]]; then mkdir -p "${COMOUT_ICE_HISTORY}"; fi - if [[ ! -d "${COMOUT_ICE_RESTART}" ]]; then mkdir -p "${COMOUT_ICE_RESTART}"; fi - if [[ ! -d "${COMIN_ICE_INPUT}" ]]; then mkdir -p "${COMIN_ICE_INPUT}"; fi - if [[ ! -d "${DATAoutput}/CICE_OUTPUT" ]]; then mkdir -p "${DATAoutput}/CICE_OUTPUT"; fi - if [[ ! -d "${DATArestart}/CICE_RESTART" ]]; then mkdir -p "${DATArestart}/CICE_RESTART"; fi + if [[ ! -d "${COMOUT_ICE_HISTORY}" ]]; then mkdir -p "${COMOUT_ICE_HISTORY}"; fi + if [[ ! -d "${COMOUT_ICE_RESTART}" ]]; then mkdir -p "${COMOUT_ICE_RESTART}"; fi + if [[ ! -d "${COMIN_ICE_INPUT}" ]]; then mkdir -p "${COMIN_ICE_INPUT}"; fi + if [[ ! -d "${DATAoutput}/CICE_OUTPUT" ]]; then mkdir -p "${DATAoutput}/CICE_OUTPUT"; fi + if [[ ! -d "${DATArestart}/CICE_RESTART" ]]; then mkdir -p "${DATArestart}/CICE_RESTART"; fi - # Link the output and restart directories to the DATA directory - ${NLN} "${DATAoutput}/CICE_OUTPUT" "${DATA}/CICE_OUTPUT" - ${NLN} "${DATArestart}/CICE_RESTART" "${DATA}/CICE_RESTART" + # Link the output and restart directories to the DATA directory + ${NLN} "${DATAoutput}/CICE_OUTPUT" "${DATA}/CICE_OUTPUT" + ${NLN} "${DATArestart}/CICE_RESTART" "${DATA}/CICE_RESTART" - # CICE does not have a concept of high frequency output like FV3 - # Convert output settings into an explicit list for CICE - # shellcheck disable=SC2312 - mapfile -t CICE_OUTPUT_FH < <(seq "${FHMIN}" "${FHOUT_ICE}" "${FHMAX}") || exit 10 + # CICE does not have a concept of high frequency output like FV3 + # Convert output settings into an explicit list for CICE + # shellcheck disable=SC2312 + mapfile -t CICE_OUTPUT_FH < <(seq "${FHMIN}" "${FHOUT_ICE}" "${FHMAX}") || exit 10 - # Fix files - cpreq "${FIXgfs}/cice/${ICERES}/${CICE_GRID}" "${DATA}/" - cpreq "${FIXgfs}/cice/${ICERES}/${CICE_MASK}" "${DATA}/" - cpreq "${FIXgfs}/cice/${ICERES}/${MESH_ICE}" "${DATA}/" + # Fix files + cpreq "${FIXgfs}/cice/${ICERES}/${CICE_GRID}" "${DATA}/" + cpreq "${FIXgfs}/cice/${ICERES}/${CICE_MASK}" "${DATA}/" + cpreq "${FIXgfs}/cice/${ICERES}/${MESH_ICE}" "${DATA}/" } # shellcheck disable=SC2034 -MOM6_predet(){ - echo "SUB ${FUNCNAME[0]}: MOM6 before run type determination" - - if [[ ! -d "${COMOUT_OCEAN_HISTORY}" ]]; then mkdir -p "${COMOUT_OCEAN_HISTORY}"; fi - if [[ ! -d "${COMOUT_OCEAN_RESTART}" ]]; then mkdir -p "${COMOUT_OCEAN_RESTART}"; fi - if [[ ! -d "${COMIN_OCEAN_INPUT}" ]]; then mkdir -p "${COMIN_OCEAN_INPUT}"; fi - if [[ ! -d "${DATAoutput}/MOM6_OUTPUT" ]]; then mkdir -p "${DATAoutput}/MOM6_OUTPUT"; fi - if [[ ! -d "${DATArestart}/MOM6_RESTART" ]]; then mkdir -p "${DATArestart}/MOM6_RESTART"; fi - - # Link the output and restart directories to the DATA directory - ${NLN} "${DATAoutput}/MOM6_OUTPUT" "${DATA}/MOM6_OUTPUT" - ${NLN} "${DATArestart}/MOM6_RESTART" "${DATA}/MOM6_RESTART" - - # MOM6 does not have a concept of high frequency output like FV3 - # Convert output settings into an explicit list for MOM6 - MOM6_OUTPUT_FH=$(seq -s ' ' "${FHMIN}" "${FHOUT_OCN}" "${FHMAX}") - - # If using stochastic parameterizations, create a seed that does not exceed the - # largest signed integer - local imem=${MEMBER#0} - local base_seed=$((current_cycle*10000 + imem*100)) - - if [[ "${DO_OCN_SPPT:-}" == "YES" ]]; then - ISEED_OCNSPPT=$((base_seed + 8)),$((base_seed + 9)),$((base_seed + 10)),$((base_seed + 11)),$((base_seed + 12)) - fi - - if [[ "${DO_OCN_PERT_EPBL:-}" == "YES" ]]; then - ISEED_EPBL=$((base_seed + 13)),$((base_seed + 14)),$((base_seed + 15)),$((base_seed + 16)),$((base_seed + 17)) - fi - - # Fix files for ocean; ocean_hgrid, ocean_mosaic, ocean_mask, etc. - # MOM_channels is configurable based on resolution, but is treated as a fix file - # MOM_override is a template that allows user to override default namelist settings, but is also treated as a fix file - cpreq "${FIXgfs}/mom6/${OCNRES}/"* "${DATA}/INPUT/" # TODO: These need to be explicit - - # Add to the MOM_override file, to have ISO timestamp - cat >> "${DATA}/INPUT/MOM_override" << EOF +MOM6_predet() { + echo "SUB ${FUNCNAME[0]}: MOM6 before run type determination" + + if [[ ! -d "${COMOUT_OCEAN_HISTORY}" ]]; then mkdir -p "${COMOUT_OCEAN_HISTORY}"; fi + if [[ ! -d "${COMOUT_OCEAN_RESTART}" ]]; then mkdir -p "${COMOUT_OCEAN_RESTART}"; fi + if [[ ! -d "${COMIN_OCEAN_INPUT}" ]]; then mkdir -p "${COMIN_OCEAN_INPUT}"; fi + if [[ ! -d "${DATAoutput}/MOM6_OUTPUT" ]]; then mkdir -p "${DATAoutput}/MOM6_OUTPUT"; fi + if [[ ! -d "${DATArestart}/MOM6_RESTART" ]]; then mkdir -p "${DATArestart}/MOM6_RESTART"; fi + + # Link the output and restart directories to the DATA directory + ${NLN} "${DATAoutput}/MOM6_OUTPUT" "${DATA}/MOM6_OUTPUT" + ${NLN} "${DATArestart}/MOM6_RESTART" "${DATA}/MOM6_RESTART" + + # MOM6 does not have a concept of high frequency output like FV3 + # Convert output settings into an explicit list for MOM6 + MOM6_OUTPUT_FH=$(seq -s ' ' "${FHMIN}" "${FHOUT_OCN}" "${FHMAX}") + + # If using stochastic parameterizations, create a seed that does not exceed the + # largest signed integer + local imem=${MEMBER#0} + local base_seed=$((current_cycle * 10000 + imem * 100)) + + if [[ "${DO_OCN_SPPT:-}" == "YES" ]]; then + ISEED_OCNSPPT=$((base_seed + 8)),$((base_seed + 9)),$((base_seed + 10)),$((base_seed + 11)),$((base_seed + 12)) + fi + + if [[ "${DO_OCN_PERT_EPBL:-}" == "YES" ]]; then + ISEED_EPBL=$((base_seed + 13)),$((base_seed + 14)),$((base_seed + 15)),$((base_seed + 16)),$((base_seed + 17)) + fi + + # Fix files for ocean; ocean_hgrid, ocean_mosaic, ocean_mask, etc. + # MOM_channels is configurable based on resolution, but is treated as a fix file + # MOM_override is a template that allows user to override default namelist settings, but is also treated as a fix file + cpreq "${FIXgfs}/mom6/${OCNRES}/"* "${DATA}/INPUT/" # TODO: These need to be explicit + + # Add to the MOM_override file, to have ISO timestamp + cat >> "${DATA}/INPUT/MOM_override" << EOF !#Write ISO date stamped output with 3-hourly (0.125) frequency to ocean.stats ascii file #override ISO_DATE_STAMPED_STDOUT = True #override ENERGYSAVEDAYS = 0.125 EOF - # Copy coupled grid_spec - local spec_file - spec_file="${FIXgfs}/cpl/a${CASE}o${OCNRES}/grid_spec.nc" - # Test that the file exists and is not zero-sized - if [[ -s "${spec_file}" ]]; then - cpreq "${spec_file}" "${DATA}/INPUT/" - else - echo "FATAL ERROR: coupled grid_spec file '${spec_file}' does not exist or is size 0" - exit 3 - fi + # Copy coupled grid_spec + local spec_file + spec_file="${FIXgfs}/cpl/a${CASE}o${OCNRES}/grid_spec.nc" + # Test that the file exists and is not zero-sized + if [[ -s "${spec_file}" ]]; then + cpreq "${spec_file}" "${DATA}/INPUT/" + else + echo "FATAL ERROR: coupled grid_spec file '${spec_file}' does not exist or is size 0" + exit 3 + fi } # shellcheck disable=SC2178 -CMEPS_predet(){ - echo "SUB ${FUNCNAME[0]}: CMEPS before run type determination" +CMEPS_predet() { + echo "SUB ${FUNCNAME[0]}: CMEPS before run type determination" - if [[ ! -d "${COMOUT_MED_RESTART}" ]]; then mkdir -p "${COMOUT_MED_RESTART}"; fi - if [[ ! -d "${DATArestart}/CMEPS_RESTART" ]]; then mkdir -p "${DATArestart}/CMEPS_RESTART"; fi + if [[ ! -d "${COMOUT_MED_RESTART}" ]]; then mkdir -p "${COMOUT_MED_RESTART}"; fi + if [[ ! -d "${DATArestart}/CMEPS_RESTART" ]]; then mkdir -p "${DATArestart}/CMEPS_RESTART"; fi - # Link the restart directory to the DATA directory - ${NLN} "${DATArestart}/CMEPS_RESTART" "${DATA}/CMEPS_RESTART" + # Link the restart directory to the DATA directory + ${NLN} "${DATArestart}/CMEPS_RESTART" "${DATA}/CMEPS_RESTART" } # shellcheck disable=SC2034 -GOCART_predet(){ - echo "SUB ${FUNCNAME[0]}: GOCART before run type determination" +GOCART_predet() { + echo "SUB ${FUNCNAME[0]}: GOCART before run type determination" - if [[ ! -d "${COMOUT_CHEM_HISTORY}" ]]; then mkdir -p "${COMOUT_CHEM_HISTORY}"; fi + if [[ ! -d "${COMOUT_CHEM_HISTORY}" ]]; then mkdir -p "${COMOUT_CHEM_HISTORY}"; fi - # FHMAX gets modified when IAU is on, so keep origianl value for GOCART output - GOCART_MAX=${FHMAX} + # FHMAX gets modified when IAU is on, so keep origianl value for GOCART output + GOCART_MAX=${FHMAX} - # GOCART output times can't be computed here because they may depend on FHROT + # GOCART output times can't be computed here because they may depend on FHROT } diff --git a/ush/fv3gfs_remap_weights.sh b/ush/fv3gfs_remap_weights.sh index 15dfc73e3f0..518b51c2767 100755 --- a/ush/fv3gfs_remap_weights.sh +++ b/ush/fv3gfs_remap_weights.sh @@ -10,54 +10,74 @@ #BSUB -extsched 'CRAYLINUX[]' set -ax - . $MODULESHOME/init/sh +source "${MODULESHOME}/init/sh" module load PrgEnv-intel #-------------------------------------------------- -export home_dir=/gpfs/hps3/emc/global/noscrub/$LOGNAME/git/fv3gfs/gfs.v15.0.0 -export script_dir=$home_dir/ush -export exec_dir=$home_dir/exec -export fix_fv3_dir=$home_dir/fix -export fregrid=$home_dir/exec/fregrid_parallel -export TMPDIR=/gpfs/hps/ptmp/$LOGNAME/fv3_weight - +export home_dir="/gpfs/hps3/emc/global/noscrub/${LOGNAME}/git/fv3gfs/gfs.v15.0.0" +export script_dir="${home_dir}/ush" +export exec_dir="${home_dir}/exec" +export fix_fv3_dir="${home_dir}/fix" +export fregrid="${home_dir}/exec/fregrid_parallel" +export TMPDIR="/gpfs/hps/ptmp/${LOGNAME}/fv3_weight" #--global lat-lon array size #---------------------------------------------------------- for GG in 1deg 0p5deg 0p25deg 0p125deg; do -#---------------------------------------------------------- + #---------------------------------------------------------- -if [ $GG = 1deg ]; then export nlon=360 ; export nlat=180 ;fi -if [ $GG = 0p5deg ]; then export nlon=720 ; export nlat=360 ;fi -if [ $GG = 0p25deg ]; then export nlon=1440 ; export nlat=720 ;fi -if [ $GG = 0p125deg ]; then export nlon=2880 ; export nlat=1440 ;fi + case "${GG}" in + 1deg) + export nlon=360 + export nlat=180 + ;; + 0p5deg) + export nlon=720 + export nlat=360 + ;; + 0p25deg) + export nlon=1440 + export nlat=720 + ;; + 0p125deg) + export nlon=2880 + export nlat=1440 + ;; + *) + msg="FATAL: Unsupported grid name ${GG}" + export err=100 + err_exit "${msg}" + ;; + esac -#---------------------------------------------------------- -for CASE in C48 C96 C192 C384 C768 C1152 C3072; do -#---------------------------------------------------------- -max_core=24 -export NODES=3; export thread=1 -##if [ $CASE = C3072 ]; then exportNODES=21; export thread=4; fi -export npes=$(((NODES-1)*max_core/thread)) - -export workdir=$TMPDIR/${CASE}_${GG} -mkdir -p $workdir; cd $workdir ||exit 8 - -export native_grid=$fix_fv3_dir/$CASE/${CASE}_mosaic.nc -export remap_file=$fix_fv3_dir/$CASE/remap_weights_${CASE}_${GG}.nc - -#NOTE: we are placing the first process on a node by itself to get the memory it needs -# these npes will be tightly packed on the remaining nodes - -aprun -n 1 -d 24 $fregrid --input_mosaic $native_grid \ - --nlon $nlon --nlat $nlat \ - --remap_file $remap_file \ - --debug : \ - -n $npes -d $thread $fregrid --input_mosaic $native_grid \ - --nlon $nlon --nlat $nlat \ - --remap_file $remap_file \ - --debug + #---------------------------------------------------------- + for CASE in C48 C96 C192 C384 C768 C1152 C3072; do + #---------------------------------------------------------- + max_core=24 + export NODES=3 + export thread=1 + ##if [[ ${CASE} = C3072 ]]; then exportNODES=21; export thread=4; fi + export npes=$(((NODES - 1) * max_core / thread)) -done + export workdir="${TMPDIR}/${CASE}_${GG}" + mkdir -p "${workdir}" + cd "${workdir}" || exit 8 + + export native_grid="${fix_fv3_dir}/${CASE}/${CASE}_mosaic.nc" + export remap_file="${fix_fv3_dir}/${CASE}/remap_weights_${CASE}_${GG}.nc" + + #NOTE: we are placing the first process on a node by itself to get the memory it needs + # these npes will be tightly packed on the remaining nodes + + aprun -n 1 -d 24 "${fregrid}" --input_mosaic "${native_grid}" \ + --nlon "${nlon}" --nlat "${nlat}" \ + --remap_file "${remap_file}" \ + --debug : \ + -n "${npes}" -d "${thread}" "${fregrid}" --input_mosaic "${native_grid}" \ + --nlon "${nlon}" --nlat "${nlat}" \ + --remap_file "${remap_file}" \ + --debug + + done done exit diff --git a/ush/gaussian_sfcanl.sh b/ush/gaussian_sfcanl.sh index 0652c0117c5..ba692404fe5 100755 --- a/ush/gaussian_sfcanl.sh +++ b/ush/gaussian_sfcanl.sh @@ -73,13 +73,13 @@ CASE=${CASE:-C768} CASE_HIST=${CASE_HIST:-${CASE}} resh=${CASE_HIST:1} -LONB_CASE=$((resh*4)) -LATB_CASE=$((resh*2)) +LONB_CASE=$((resh * 4)) +LATB_CASE=$((resh * 2)) LONB_SFC=${LONB_SFC:-${LONB_CASE}} LATB_SFC=${LATB_SFC:-${LATB_CASE}} DONST=${DONST:-"NO"} LEVS=${LEVS:-64} -LEVSP1=$(( LEVS + 1 )) +LEVSP1=$((LEVS + 1)) FIXWGTS=${FIXWGTS:-${FIXorog}/${CASE}/fv3_SCRIP_${CASE}_GRIDSPEC_lon${LONB_SFC}_lat${LATB_SFC}.gaussian.neareststod.nc} # Filenames. @@ -94,6 +94,7 @@ SIGLEVEL=${SIGLEVEL:-${FIXgfs}/am/global_hyblev.l${LEVSP1}.txt} ################################################################################ # Make surface analysis + # input interpolation weights cpreq "${FIXWGTS}" "./weights.nc" @@ -132,7 +133,7 @@ if [[ "${DO_LAND_IAU:-.false.}" == ".true." ]]; then fi # Executable namelist -cat < fort.41 +cat << EOF > fort.41 &setup yy=${PDY:0:4}, mm=${PDY:4:2}, @@ -155,8 +156,8 @@ export OMP_NUM_THREADS=${OMP_NUM_THREADS_SFC:-1} ${APRUNSFC} "${GAUSFCANLEXE}" export err=$? if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: ${GAUSFCANLEXE} returned non-zero exit status!" - exit "${err}" + echo "FATAL ERROR: ${GAUSFCANLEXE} returned non-zero exit status!" + exit "${err}" fi # output gaussian global surface analysis files diff --git a/ush/getdump.sh b/ush/getdump.sh index 7c853f21de0..55f4a9fc5ab 100755 --- a/ush/getdump.sh +++ b/ush/getdump.sh @@ -12,23 +12,23 @@ DUMP_SUFFIX=${DUMP_SUFFIX:-""} # Exit if SOURCE_DIR does not exist if [[ ! -s "${SOURCE_DIR}" ]]; then - echo "***ERROR*** DUMP SOURCE_DIR=${SOURCE_DIR} does not exist" - exit 99 + echo "***ERROR*** DUMP SOURCE_DIR=${SOURCE_DIR} does not exist" + exit 99 fi - + # Create TARGET_DIR if is does not exist if [[ ! -s "${TARGET_DIR}" ]]; then - mkdir -p "${TARGET_DIR}" + mkdir -p "${TARGET_DIR}" fi # Set file prefix prefix="${RUN}.t${HH}z." # Link dump files from SOURCE_DIR to TARGET_DIR -cd "${SOURCE_DIR}" +cd "${SOURCE_DIR}" || exit 1 if [[ -s "${prefix}updated.status.tm00.bufr_d" ]]; then - for file in $(ls ${prefix}*); do - ${NLN} "${SOURCE_DIR}/${file}" "${TARGET_DIR}/${file}" + for file in "${prefix}"*; do + ${NLN} "${SOURCE_DIR}/${file}" "${TARGET_DIR}/${file}" done else echo "***ERROR*** ${prefix}updated.status.tm00.bufr_d NOT FOUND in ${SOURCE_DIR}" diff --git a/ush/getges.sh b/ush/getges.sh index f7a6c95eaa0..2922261b267 100755 --- a/ush/getges.sh +++ b/ush/getges.sh @@ -48,123 +48,104 @@ # Example 5. Get the 24-hour GFS forecast sigma file valid at 1998100112. # getges -t sigcur -v 1998100112 -f 24 -e gfs sigfile # -# History: 1996 December Iredell Initial implementation -# 1997 March Iredell Nine new filetypes -# 1997 April Iredell Two new filetypes and -f option -# 1997 December Iredell Four new filetypes -# 1998 April Iredell 4-digit year allowed; -# sigges internal date no longer checked -# 1998 May Iredell T170L42 defaulted; four new filetypes -# and two filetypes deleted -# 1998 June Rogers Nam types added -# 1998 September Iredell high is default resolution -# 2000 March Iredell Cdas and -n option -# 2000 June Iredell Eight new filetypes -# 2002 April Treadon T254L64 defaulted; add angle dependent -# bias correction file -# 2003 March Iredell GFS network out to 384 hours -# 2003 August Iredell Hourly global guesses -# 2005 September Treadon Add satellite data count file (satcnt) -# 2006 September Gayno Add high-res snow analysis -# 2009 January Rogers Added sfluxgrb file -# 2011 April Rogers Added GFS pg2ges file -# 2016 May Menlove Changed GETGES_COM variable to $COMINmodel -# 2016 November Iredell Adapted getges for NEMS GSM -# Also removed a lot of dead wood -# ################################################################################ #------------------------------------------------------------------------------- # Set some default parameters. -fhbeg=03 # hour to begin searching backward for guess -fhinc=03 # hour to increment backward in search -fhend=384 # hour to end searching backward for guess +fhbeg=03 # hour to begin searching backward for guess +fhinc=03 # hour to increment backward in search +fhend=384 # hour to end searching backward for guess #------------------------------------------------------------------------------- # Get options and arguments. -netwk=global # default network -envir=prod # default environment -fhour=any # default forecast hour -quiet=YES # default quiet mode -resol=high # default resolution -typef=sigges # default filetype -valid=${PDY}${cyc} # default valid date +netwk=global # default network +envir=prod # default environment +fhour=any # default forecast hour +quiet=YES # default quiet mode +resol=high # default resolution +typef=sigges # default filetype +valid=${PDY}${cyc} # default valid date err=0 -while getopts n:e:f:qr:t:v: opt;do - case $opt in - n) netwk="$OPTARG";; - e) envir="$OPTARG";; - f) fhour="$OPTARG";; - q) quiet=NO;; - r) resol="$OPTARG";; - t) typef="$OPTARG";; - v) valid="$OPTARG";; - \?) err=1;; - esac +while getopts n:e:f:qr:t:v: opt; do + case "${opt}" in + n) netwk="${OPTARG}" ;; + e) envir="${OPTARG}" ;; + f) fhour="${OPTARG}" ;; + q) quiet=NO ;; + r) resol="${OPTARG}" ;; + t) typef="${OPTARG}" ;; + v) valid="${OPTARG}" ;; + \?) err=1 ;; + *) + echo: "Unknown option ${opt}!" + exit 2 + ;; + esac done -shift $(($OPTIND-1)) +shift $((OPTIND - 1)) gfile=$1 -if [[ -z $valid ]];then - echo "$0: either -v option or environment variables PDY and cyc must be set" >&2 -elif [[ $# -gt 1 ]];then - echo "$0: too many positional arguments" >&2 -elif [[ $err -ne 0 ]];then - echo "$0: invalid option" >&2 +if [[ -z "${valid}" ]]; then + echo "$0: either -v option or environment variables PDY and cyc must be set" >&2 +elif [[ $# -gt 1 ]]; then + echo "$0: too many positional arguments" >&2 +elif [[ "${err}" -ne 0 ]]; then + echo "$0: invalid option" >&2 fi -if [[ $gfile = '?' || $# -gt 1 || $err -ne 0 || -z $valid ||\ - $netwk = '?' || $envir = '?' || $fhour = '?' || $resol = '?' ||\ - $typef = '?' || $valid = '?' ]];then - echo "Usage: getges.sh [-n network] [-e environment] [-f fhour] [-q] [-r resolution]" >&2 - echo " [-t filetype] [-v valid] [gfile]" >&2 - if [[ $netwk = '?' ]];then - echo " network choices:" >&2 - echo " global (default), namopl, gdas, gfs, cdas, etc." >&2 - elif [[ $envir = '?' ]];then - echo " environment choices:" >&2 - echo " prod (default), test, para, dump, prx" >&2 - echo " (some network values allowed for compatibility)" >&2 - elif [[ $fhour = '?' ]];then - echo " fhour is optional specific forecast hour" >&2 - elif [[ $resol = '?' ]];then - echo " resolution choices:" >&2 - echo " high (default), 25464, 17042, 12628, low, 6228, namopl, any" >&2 - elif [[ $typef = '?' ]];then - echo " filetype choices:" >&2 - echo " sigges (default), siggm3, siggm2, siggm1, siggp1, siggp2, siggp3," >&2 - echo " sfcges, sfcgm3, sfcgm2, sfcgm1, sfcgp1, sfcgp2, sfcgp3," >&2 - echo " sfgges, sfggp3, biascr, satang, satcnt, gesfil" >&2 - echo " pgbges, pgiges, pgbgm6, pgigm6, pgbgm3, pgigm3, pgbgp3, pgigp3," >&2 - echo " sigcur, sfccur, pgbcur, pgicur, prepqc, tcvg12, tcvges, tcvitl," >&2 - echo " enggrb, enggri, icegrb, icegri, snogrb, snogri, sstgrb, sstgri," >&2 - echo " pg2cur, pg2ges, restrt," >&2 - echo " natges, natgm3, natgm2, natgm1, natgp1, natgp2, natgp3, natcur," >&2 - echo " nsfges, nsfgm3, nsfgm2, nsfgm1, nsfgp1, nsfgp2, nsfgp3, nsfcur," >&2 - echo " nstcur, nflges, nflgp3," >&2 - elif [[ $valid = '?' ]];then - echo " valid is the valid date in yyyymmddhh or yymmddhh form" >&2 - echo " (default is environmental variable $PDY$cyc)" >&2 - elif [[ $gfile = '?' ]];then - echo " gfile is the guess file to write" >&2 - echo " (default is to write the guess file name to stdout)" >&2 - else - echo " (Note: set a given option to '?' for more details)" >&2 - fi - exit 1 + +if [[ "${gfile}" == '?' || $# -gt 1 || "${err}" -ne 0 || -z "${valid}" || + "${netwk}" == '?' || "${envir}" == '?' || "${fhour}" == '?' || "${resol}" == '?' || + "${typef}" == '?' || "${valid}" == '?' ]]; then + echo "Usage: getges.sh [-n network] [-e environment] [-f fhour] [-q] [-r resolution]" >&2 + echo " [-t filetype] [-v valid] [gfile]" >&2 + if [[ "${netwk}" == '?' ]]; then + echo " network choices:" >&2 + echo " global (default), namopl, gdas, gfs, cdas, etc." >&2 + elif [[ "${envir}" == '?' ]]; then + echo " environment choices:" >&2 + echo " prod (default), test, para, dump, prx" >&2 + echo " (some network values allowed for compatibility)" >&2 + elif [[ "${fhour}" == '?' ]]; then + echo " fhour is optional specific forecast hour" >&2 + elif [[ "${resol}" == '?' ]]; then + echo " resolution choices:" >&2 + echo " high (default), 25464, 17042, 12628, low, 6228, namopl, any" >&2 + elif [[ "${typef}" == '?' ]]; then + echo " filetype choices:" >&2 + echo " sigges (default), siggm3, siggm2, siggm1, siggp1, siggp2, siggp3," >&2 + echo " sfcges, sfcgm3, sfcgm2, sfcgm1, sfcgp1, sfcgp2, sfcgp3," >&2 + echo " sfgges, sfggp3, biascr, satang, satcnt, gesfil" >&2 + echo " pgbges, pgiges, pgbgm6, pgigm6, pgbgm3, pgigm3, pgbgp3, pgigp3," >&2 + echo " sigcur, sfccur, pgbcur, pgicur, prepqc, tcvg12, tcvges, tcvitl," >&2 + echo " enggrb, enggri, icegrb, icegri, snogrb, snogri, sstgrb, sstgri," >&2 + echo " pg2cur, pg2ges, restrt," >&2 + echo " natges, natgm3, natgm2, natgm1, natgp1, natgp2, natgp3, natcur," >&2 + echo " nsfges, nsfgm3, nsfgm2, nsfgm1, nsfgp1, nsfgp2, nsfgp3, nsfcur," >&2 + echo " nstcur, nflges, nflgp3," >&2 + elif [[ "${valid}" == '?' ]]; then + echo " valid is the valid date in yyyymmddhh or yymmddhh form" >&2 + echo " (default is environmental variable ${PDY}${cyc})" >&2 + elif [[ "${gfile}" == '?' ]]; then + echo " gfile is the guess file to write" >&2 + echo " (default is to write the guess file name to stdout)" >&2 + else + echo " (Note: set a given option to '?' for more details)" >&2 + fi + exit 1 fi -if [[ $envir != prod && $envir != test && $envir != para && $envir != dump && $envir != pr? && $envir != dev ]];then - netwk=$envir - envir=prod - echo '************************************************************' >&2 - echo '* WARNING: Using "-e" is deprecated in this case. *' >&2 - echo '* Please use "-n" instead. *' >&2 - echo '************************************************************' >&2 +if [[ "${envir}" != prod && "${envir}" != test && "${envir}" != para && "${envir}" != dump && "${envir}" != pr? && "${envir}" != dev ]]; then + netwk="${envir}" + envir=prod + echo '************************************************************' >&2 + echo '* WARNING: Using "-e" is deprecated in this case. *' >&2 + echo '* Please use "-n" instead. *' >&2 + echo '************************************************************' >&2 fi -if [[ "$netwk" = "namopl" || "$resol" = "namopl" ]];then - netwk=namopl - typef=restrt - resol=namopl +if [[ "${netwk}" == "namopl" || "${resol}" == "namopl" ]]; then + netwk=namopl + typef=restrt + resol=namopl fi if [[ "${resol}" == "57464" || "${resol}" == "38264" || "${resol}" == "19064" || "${resol}" == "25464" || "${resol}" == "17042" || "${resol}" == "12628" ]]; then resol=high @@ -172,30 +153,27 @@ fi if [[ "${resol}" == "6228" ]]; then resol=low fi -resolsuf="" -if [[ ${resol} == *deg ]]; then - resolsuf=.$resol -fi -fhbeg=$(${NHOUR:?} $valid) -if [[ ${fhbeg} -le 0 ]]; then +fhbeg=$(${NHOUR:?} "${valid}") +if [[ "${fhbeg}" -le 0 ]]; then fhbeg=03 fi -((fhbeg=(10#${fhbeg}-1)/3*3+3)) -if [[ $fhbeg -lt 10 ]]; then +((fhbeg = (10#${fhbeg} - 1) / 3 * 3 + 3)) +if [[ "${fhbeg}" -lt 10 ]]; then fhbeg="0${fhbeg}" fi -if [[ $typef = enggrb ]];then - typef=icegrb - echo '************************************************************' >&2 - echo '* WARNING: Using "-t enggrb" is now deprecated. *' >&2 - echo '* Please use "-t icegrb". *' >&2 - echo '************************************************************' >&2 -elif [[ $typef = enggri ]];then - typef=icegri - echo '************************************************************' >&2 - echo '* WARNING: Using "-t enggri" is now deprecated. *' >&2 - echo '* Please use "-t icegri". *' >&2 - echo '************************************************************' >&2 + +if [[ "${typef}" == enggrb ]]; then + typef=icegrb + echo '************************************************************' >&2 + echo '* WARNING: Using "-t enggrb" is now deprecated. *' >&2 + echo '* Please use "-t icegrb". *' >&2 + echo '************************************************************' >&2 +elif [[ "${typef}" == enggri ]]; then + typef=icegri + echo '************************************************************' >&2 + echo '* WARNING: Using "-t enggri" is now deprecated. *' >&2 + echo '* Please use "-t icegri". *' >&2 + echo '************************************************************' >&2 fi #------------------------------------------------------------------------------- @@ -204,1209 +182,1485 @@ geslist="" getlist00="" # GDAS -if [[ "$netwk" = "gdas" ]];then - if [ -z "$COMINgdas" ]; then - echo "getges.sh ERROR: The \$COMINgdas variable must be defined." >&2 - exit 1 - fi - fhend=12 - case $typef in - biascr) geslist=' - $COMINgdas/gdas.t${cyc}z.abias' - ;; - biascr_pc) geslist=' - $COMINgdas/gdas.t${cyc}z.abias_pc' - ;; - biascr_air) geslist=' - $COMINgdas/gdas.t${cyc}z.abias_air' - ;; - radstat) geslist=' - $COMINgdas/gdas.t${cyc}z.radstat' - ;; - pgbges) geslist=' - $COMINgdas/gdas.t${cyc}z.pgrbh$fh - $COMINgdas/gdas.t${cyc}z.pgrbf$fh' - ;; - pg2ges) geslist=' - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$gh' - ;; - pgbgm6) geslist=' - $COMINgdas/gdas.t${cyc}z.pgrbh$fhm6 - $COMINgdas/gdas.t${cyc}z.pgrbf$fhm6' - ;; - pgbgm3) geslist=' - $COMINgdas/gdas.t${cyc}z.pgrbh$fhm3 - $COMINgdas/gdas.t${cyc}z.pgrbf$fhm3' - ;; - pgbgp3) geslist=' - $COMINgdas/gdas.t${cyc}z.pgrbh$fhp3 - $COMINgdas/gdas.t${cyc}z.pgrbf$fhp3' - ;; - pgbcur) geslist=' - $COMINgdas/gdas.t${cyc}z.pgrbh$fh - $COMINgdas/gdas.t${cyc}z.pgrbf$fh' - fhbeg=00 - ;; - pg2cur) geslist=' - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$gh' - fhbeg=00 - ;; - prepqc) geslist=' - $COMINgdas/gdas.t${cyc}z.prepbufr' - fhbeg=00 - fhend=00 - ;; - tcvg12) geslist=' - $COMINgdas/gdas.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=12 - fhend=12 - ;; - tcvges) geslist=' - $COMINgdas/gdas.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=06 - fhend=06 - ;; - tcvitl) geslist=' - $COMINgdas/gdas.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=00 - fhend=00 - ;; - icegrb) geslist=' - $COMINgdas/gdas.t${cyc}z.engicegrb' - fhbeg=00 - fhinc=06 - ;; - snogrb) geslist=' - $COMINgdas/gdas.t${cyc}z.snogrb' - fhbeg=00 - fhinc=06 - ;; - snogrb_574) geslist=' - $COMINgdas/gdas.t${cyc}z.snogrb_t574.1152.576' - fhbeg=00 - fhinc=06 - ;; - snogrb_1534) geslist=' - $COMINgdas/gdas.t${cyc}z.snogrb_t1534.3072.1536' - fhbeg=00 - fhinc=06 - ;; - sstgrb) geslist=' - $COMINgdas/gdas.t${cyc}z.sstgrb' - fhbeg=00 - fhinc=06 - ;; - natges) geslist=' - $COMINgdas/gdas.t${cyc}z.atmf$gh.nemsio' - ;; - natgm3) geslist=' - $COMINgdas/gdas.t${cyc}z.atm.f$ghm3.nemsio' - ;; - natgm2) geslist=' - $COMINgdas/gdas.t${cyc}z.atmf$ghm2.nemsio' - ;; - natgm1) geslist=' - $COMINgdas/gdas.t${cyc}z.atmf$ghm1.nemsio' - ;; - natgp1) geslist=' - $COMINgdas/gdas.t${cyc}z.atmf$ghp1.nemsio' - ;; - natgp2) geslist=' - $COMINgdas/gdas.t${cyc}z.atmf$ghp2.nemsio' - ;; - natgp3) geslist=' - $COMINgdas/gdas.t${cyc}z.atmf$ghp3.nemsio' - ;; - natcur) geslist=' - $COMINgdas/gdas.t${cyc}z.atmf$gh.nemsio' - getlist00=' - $COMINgdas/gdas.t${cyc}z.atmanl.nemsio' - fhbeg=00 - ;; - nsfges) geslist=' - $COMINgdas/gdas.t${cyc}z.sfcf$gh.nemsio' - ;; - nsfgm3) geslist=' - $COMINgdas/gdas.t${cyc}z.sfcf$ghm3.nemsio' - ;; - nsfgm2) geslist=' - $COMINgdas/gdas.t${cyc}z.sfcf$ghm2.nemsio' - ;; - nsfgm1) geslist=' - $COMINgdas/gdas.t${cyc}z.sfcf$ghm1.nemsio' - ;; - nsfgp1) geslist=' - $COMINgdas/gdas.t${cyc}z.sfcf$ghp1.nemsio' - ;; - nsfgp2) geslist=' - $COMINgdas/gdas.t${cyc}z.sfcf$ghp2.nemsio' - ;; - nsfgp3) geslist=' - $COMINgdas/gdas.t${cyc}z.sfcf$ghp3.nemsio' - ;; - nsfcur) geslist=' - $COMINgdas/gdas.t${cyc}z.sfcf$gh.nemsio' - getlist00=' - $COMINgdas/gdas.t${cyc}z.sfcanl.nemsio' - fhbeg=00 - ;; - nstcur) geslist=' - $COMINgdas/gdas.t${cyc}z.nstf$gh.nemsio' - getlist00=' - $COMINgdas/gdas.t${cyc}z.nstanl.nemsio' - fhbeg=00 - ;; - nflges) geslist=' - $COMINgdas/gdas.t${cyc}z.flxf$gh.nemsio' - ;; - nflgp3) geslist=' - $COMINgdas/gdas.t${cyc}z.flxf$ghp3.nemsio' - ;; - nflcur) geslist=' - $COMINgdas/gdas.t${cyc}z.flxf$gh.nemsio' - fhbeg=00 - ;; - esac +if [[ "${netwk}" == "gdas" ]]; then + if [[ -z "${COMINgdas}" ]]; then + echo "getges.sh ERROR: The \${COMINgdas} variable must be defined." >&2 + exit 1 + fi + fhend=12 + # shellcheck disable=SC2016 + case "${typef}" in + biascr) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.abias' + ;; + biascr_pc) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.abias_pc' + ;; + biascr_air) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.abias_air' + ;; + radstat) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.radstat' + ;; + pgbges) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fh} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fh}' + ;; + pg2ges) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${gh}' + ;; + pgbgm6) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fhm6} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fhm6}' + ;; + pgbgm3) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fhm3} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fhm3}' + ;; + pgbgp3) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fhp3} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fhp3}' + ;; + pgbcur) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fh} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fh}' + fhbeg=00 + ;; + pg2cur) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${gh}' + fhbeg=00 + ;; + prepqc) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.prepbufr' + fhbeg=00 + fhend=00 + ;; + tcvg12) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=12 + fhend=12 + ;; + tcvges) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=06 + fhend=06 + ;; + tcvitl) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=00 + fhend=00 + ;; + icegrb) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.engicegrb' + fhbeg=00 + fhinc=06 + ;; + snogrb) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.snogrb' + fhbeg=00 + fhinc=06 + ;; + snogrb_574) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.snogrb_t574.1152.576' + fhbeg=00 + fhinc=06 + ;; + snogrb_1534) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.snogrb_t1534.3072.1536' + fhbeg=00 + fhinc=06 + ;; + sstgrb) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.sstgrb' + fhbeg=00 + fhinc=06 + ;; + natges) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.atmf${gh}.nemsio' + ;; + natgm3) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.atm.f${ghm3}.nemsio' + ;; + natgm2) + geslist=' + + ${COMINgdas}/gdas.t${cyc}z.atmf${ghm2}.nemsio' + ;; + natgm1) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.atmf${ghm1}.nemsio' + ;; + natgp1) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.atmf${ghp1}.nemsio' + ;; + natgp2) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.atmf${ghp2}.nemsio' + ;; + natgp3) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.atmf${ghp3}.nemsio' + ;; + natcur) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.atmf${gh}.nemsio' + getlist00=' + ${COMINgdas}/gdas.t${cyc}z.atmanl.nemsio' + fhbeg=00 + ;; + nsfges) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.sfcf${gh}.nemsio' + ;; + nsfgm3) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghm3}.nemsio' + ;; + nsfgm2) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghm2}.nemsio' + ;; + nsfgm1) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghm1}.nemsio' + ;; + nsfgp1) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghp1}.nemsio' + ;; + nsfgp2) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghp2}.nemsio' + ;; + nsfgp3) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghp3}.nemsio' + ;; + nsfcur) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.sfcf${gh}.nemsio' + getlist00=' + ${COMINgdas}/gdas.t${cyc}z.sfcanl.nemsio' + fhbeg=00 + ;; + nstcur) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.nstf${gh}.nemsio' + getlist00=' + ${COMINgdas}/gdas.t${cyc}z.nstanl.nemsio' + fhbeg=00 + ;; + nflges) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.flxf${gh}.nemsio' + ;; + nflgp3) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.flxf${ghp3}.nemsio' + ;; + nflcur) + geslist=' + ${COMINgdas}/gdas.t${cyc}z.flxf${gh}.nemsio' + fhbeg=00 + ;; + *) + msg="FATAL ERROR: Unknown ${netwk} guess type ${typef}" + export err=101 + err_exit "${msg}" + ;; + esac # CFS-CDAS -elif [[ "$netwk" = "cfs-cdas" ]];then - if [ -z "$COMINcfs_cdas" ]; then - echo "getges.sh ERROR: The \$COMINcfs_cdas variable must be defined." >&2 - exit 1 - fi - fhend=12 - case $typef in - sigges) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sf$fh' - ;; - siggm3) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sf$fhm3' - ;; - siggm2) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sf$fhm2' - ;; - siggm1) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sf$fhm1' - ;; - siggp1) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sf$fhp1' - ;; - siggp2) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sf$fhp2' - ;; - siggp3) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sf$fhp3' - ;; - sfcges) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.bf${fh}.LIS - $COMINcfs_cdas/cdas1.t${cyc}z.bf$fh' - ;; - sfcgm3) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.bf${fhm3}.LIS - $COMINcfs_cdas/cdas1.t${cyc}z.bf$fhm3' - ;; - sfcgm2) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.bf${fhm2}.LIS - $COMINcfs_cdas/cdas1.t${cyc}z.bf$fhm2' - ;; - sfcgm1) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.bf${fhm1}.LIS - $COMINcfs_cdas/cdas1.t${cyc}z.bf$fhm1' - ;; - sfcgp1) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.bf${fhp1}.LIS - $COMINcfs_cdas/cdas1.t${cyc}z.bf$fhp1' - ;; - sfcgp2) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.bf${fhp2}.LIS - $COMINcfs_cdas/cdas1.t${cyc}z.bf$fhp2' - ;; - sfcgp3) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.bf${fhp3}.LIS - $COMINcfs_cdas/cdas1.t${cyc}z.bf$fhp3' - ;; - biascr) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.abias' - ;; - satang) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.satang' - ;; - satcnt) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.satcnt' - ;; - gesfil) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.gesfile' - fhbeg=00 - fhend=00 - ;; - sfgges) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sfluxgrbf$fh' - ;; - sfggp3) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sfluxgrbf$fhp3' - ;; - pgbges) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbh$fh - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbf$fh' - ;; - pgiges) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbih$fh - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbif$fh' - ;; - pgbgm6) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbh$fhm6 - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbf$fhm6' - ;; - pgigm6) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbih$fhm6 - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbif$fhm6' - ;; - pgbgm3) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbh$fhm3 - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbf$fhm3' - ;; - pgigm3) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbih$fhm3 - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbif$fhm3' - ;; - pgbgp3) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbh$fhp3 - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbf$fhp3' - ;; - pgigp3) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbih$fhp3 - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbif$fhp3' - ;; - sigcur) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sf$fh' - getlist00=' - $COMINcfs_cdas/cdas1.t${cyc}z.sanl' - fhbeg=00 - ;; - sfccur) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.bf$fh' - getlist00=' - $COMINcfs_cdas/cdas1.t${cyc}z.sfcanl' - fhbeg=00 - ;; - pgbcur) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbh$fh - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbf$fh' - fhbeg=00 - ;; - pgicur) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbih$fh - $COMINcfs_cdas/cdas1.t${cyc}z.pgrbif$fh' - fhbeg=00 - ;; - prepqc) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.prepbufr' - fhbeg=00 - fhend=00 - ;; - tcvg12) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=12 - fhend=12 - ;; - tcvges) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=06 - fhend=06 - ;; - tcvitl) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=00 - fhend=00 - ;; - icegrb) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.engicegrb' - fhbeg=00 - fhinc=06 - ;; - icegri) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.engicegrb.index' - fhbeg=00 - fhinc=06 - ;; - snogrb) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.snogrb' - fhbeg=00 - fhinc=06 - ;; - snogrb_high) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.snogrb_t574 - $COMINcfs_cdas/cdas1.t${cyc}z.snogrb_t382' - fhbeg=00 - fhinc=06 - ;; - snogrb_382) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.snogrb_t382' - fhbeg=00 - fhinc=06 - ;; - snogrb_574) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.snogrb_t574' - fhbeg=00 - fhinc=06 - ;; - snogri) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.snogrb.index' - fhbeg=00 - fhinc=06 - ;; - sstgrb) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sstgrb' - fhbeg=00 - fhinc=06 - ;; - sstgri) geslist=' - $COMINcfs_cdas/cdas1.t${cyc}z.sstgrb.index' - fhbeg=00 - fhinc=06 - ;; - esac +elif [[ "${netwk}" == "cfs-cdas" ]]; then + if [[ -z "${COMINcfs_cdas}" ]]; then + echo "getges.sh ERROR: The \${COMINcfs_cdas} variable must be defined." >&2 + exit 1 + fi + fhend=12 + # shellcheck disable=SC2016 + case "${typef}" in + sigges) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sf${fh}' + ;; + siggm3) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sf${fhm3}' + ;; + siggm2) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sf${fhm2}' + ;; + siggm1) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sf${fhm1}' + ;; + siggp1) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sf${fhp1}' + ;; + siggp2) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sf${fhp2}' + ;; + siggp3) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sf${fhp3}' + ;; + sfcges) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fh}.LIS + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fh}' + ;; + sfcgm3) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhm3}.LIS + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhm3}' + ;; + sfcgm2) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhm2}.LIS + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhm2}' + ;; + sfcgm1) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhm1}.LIS + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhm1}' + ;; + sfcgp1) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhp1}.LIS + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhp1}' + ;; + sfcgp2) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhp2}.LIS + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhp2}' + ;; + sfcgp3) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhp3}.LIS + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fhp3}' + ;; + biascr) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.abias' + ;; + satang) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.satang' + ;; + satcnt) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.satcnt' + ;; + gesfil) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.gesfile' + fhbeg=00 + fhend=00 + ;; + sfgges) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sfluxgrbf${fh}' + ;; + sfggp3) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sfluxgrbf${fhp3}' + ;; + pgbges) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbh${fh} + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbf${fh}' + ;; + pgiges) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbih${fh} + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbif${fh}' + ;; + pgbgm6) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbh${fhm6} + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbf${fhm6}' + ;; + pgigm6) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbih${fhm6} + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbif${fhm6}' + ;; + pgbgm3) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbh${fhm3} + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbf${fhm3}' + ;; + pgigm3) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbih${fhm3} + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbif${fhm3}' + ;; + pgbgp3) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbh${fhp3} + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbf${fhp3}' + ;; + pgigp3) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbih${fhp3} + + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbif${fhp3}' + ;; + sigcur) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sf${fh}' + getlist00=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sanl' + fhbeg=00 + ;; + sfccur) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.bf${fh}' + getlist00=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sfcanl' + fhbeg=00 + ;; + pgbcur) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbh${fh} + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbf${fh}' + fhbeg=00 + ;; + pgicur) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbih${fh} + + ${COMINcfs_cdas}/cdas1.t${cyc}z.pgrbif${fh}' + fhbeg=00 + ;; + prepqc) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.prepbufr' + fhbeg=00 + fhend=00 + ;; + tcvg12) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=12 + fhend=12 + ;; + tcvges) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=06 + fhend=06 + ;; + tcvitl) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=00 + fhend=00 + ;; + icegrb) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.engicegrb' + fhbeg=00 + fhinc=06 + ;; + icegri) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.engicegrb.index' + fhbeg=00 + fhinc=06 + ;; + snogrb) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.snogrb' + fhbeg=00 + fhinc=06 + ;; + snogrb_high) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.snogrb_t574 + ${COMINcfs_cdas}/cdas1.t${cyc}z.snogrb_t382' + fhbeg=00 + fhinc=06 + ;; + snogrb_382) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.snogrb_t382' + fhbeg=00 + fhinc=06 + ;; + snogrb_574) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.snogrb_t574' + fhbeg=00 + fhinc=06 + ;; + snogri) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.snogrb.index' + fhbeg=00 + fhinc=06 + ;; + sstgrb) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sstgrb' + fhbeg=00 + fhinc=06 + ;; + sstgri) + geslist=' + ${COMINcfs_cdas}/cdas1.t${cyc}z.sstgrb.index' + fhbeg=00 + fhinc=06 + ;; + *) + msg="FATAL ERROR: Unknown ${netwk} guess type ${typef}" + export err=101 + err_exit "${msg}" + ;; + esac # GFS -elif [[ "$netwk" = "gfs" ]];then - if [ -z "$COMINgfs" ]; then - echo "getges.sh ERROR: The \$COMINgfs variable must be defined." >&2 - exit 1 - fi - fhend=384 - case $typef in - pgbcur) geslist=' - $COMINgfs/gfs.t${cyc}z.pgrbf$fh' - fhbeg=00 - ;; - pg2cur) geslist=' - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$gh' - fhbeg=00 - ;; - prepqc) geslist=' - $COMINgfs/gfs.t${cyc}z.prepbufr' - fhbeg=00 - fhend=00 - ;; - tcvitl) geslist=' - $COMINgfs/gfs.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=00 - fhend=00 - ;; - icegrb) geslist=' - $COMINgfs/gfs.t${cyc}z.engicegrb' - fhbeg=00 - fhinc=06 - ;; - snogrb) geslist=' - $COMINgfs/gfs.t${cyc}z.snogrb' - fhbeg=00 - fhinc=06 - ;; - snogrb_1534) geslist=' - $COMINgfs/gfs.t${cyc}z.snogrb_t1534.3072.1536' - fhbeg=00 - fhinc=06 - ;; - sstgrb) geslist=' - $COMINgfs/gfs.t${cyc}z.sstgrb' - fhbeg=00 - fhinc=06 - ;; - natcur) geslist=' - $COMINgfs/gfs.t${cyc}z.atm.f$gh.nemsio' - getlist00=' - $COMINgfs/gfs.t${cyc}z.atmanl.nemsio' - fhbeg=00 - ;; - nsfcur) geslist=' - $COMINgfs/gfs.t${cyc}z.sfcf$gh.nemsio' - getlist00=' - $COMINgfs/gfs.t${cyc}z.sfcanl.nemsio' - fhbeg=00 - ;; - nstcur) geslist=' - $COMINgfs/gfs.t${cyc}z.nstf$gh.nemsio' - getlist00=' - $COMINgfs/gfs.t${cyc}z.nstanl.nemsio' - fhbeg=00 - ;; - nflcur) geslist=' - $COMINgfs/gfs.t${cyc}z.flxf$gh.nemsio' - fhbeg=00 - ;; - esac +elif [[ "${netwk}" == "gfs" ]]; then + if [[ -z "${COMINgfs}" ]]; then + echo "getges.sh ERROR: The \${COMINgfs} variable must be defined." >&2 + exit 1 + fi + fhend=384 + # shellcheck disable=SC2016 + case "${typef}" in + pgbcur) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.pgrbf${fh}' + fhbeg=00 + ;; + pg2cur) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${gh}' + fhbeg=00 + ;; + prepqc) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.prepbufr' + fhbeg=00 + fhend=00 + ;; + tcvitl) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=00 + fhend=00 + ;; + icegrb) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.engicegrb' + fhbeg=00 + fhinc=06 + ;; + snogrb) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.snogrb' + fhbeg=00 + fhinc=06 + ;; + snogrb_1534) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.snogrb_t1534.3072.1536' + fhbeg=00 + fhinc=06 + ;; + sstgrb) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.sstgrb' + fhbeg=00 + fhinc=06 + ;; + natcur) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.atm.f${gh}.nemsio' + getlist00=' + + ${COMINgfs}/gfs.t${cyc}z.atmanl.nemsio' + fhbeg=00 + ;; + nsfcur) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.sfcf${gh}.nemsio' + getlist00=' + ${COMINgfs}/gfs.t${cyc}z.sfcanl.nemsio' + fhbeg=00 + ;; + nstcur) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.nstf${gh}.nemsio' + getlist00=' + ${COMINgfs}/gfs.t${cyc}z.nstanl.nemsio' + fhbeg=00 + ;; + nflcur) + geslist=' + ${COMINgfs}/gfs.t${cyc}z.flxf${gh}.nemsio' + fhbeg=00 + ;; + *) + msg="FATAL ERROR: Unknown ${netwk} guess type ${typef}" + export err=101 + err_exit "${msg}" + ;; + esac # CDAS -elif [[ "$netwk" = "cdas" ]];then - if [ -z "$COMINcdas" ]; then - echo "getges.sh ERROR: The \$COMINcdas variable must be defined." >&2 - exit 1 - fi - fhbeg=06 - fhend=06 - case $typef in - sigges) geslist=' - $COMINcdas/cdas.t${cyc}z.sf$fh' - ;; - siggm3) geslist=' - $COMINcdas/cdas.t${cyc}z.sf$fhm3' - ;; - siggm2) geslist=' - $COMINcdas/cdas.t${cyc}z.sf$fhm2' - ;; - siggm1) geslist=' - $COMINcdas/cdas.t${cyc}z.sf$fhm1' - ;; - siggp1) geslist=' - $COMINcdas/cdas.t${cyc}z.sf$fhp1' - ;; - siggp2) geslist=' - $COMINcdas/cdas.t${cyc}z.sf$fhp2' - ;; - siggp3) geslist=' - $COMINcdas/cdas.t${cyc}z.sf$fhp3' - ;; - sfcges) geslist=' - $COMINcdas/cdas.t${cyc}z.bf$fh' - ;; - sfcgm3) geslist=' - $COMINcdas/cdas.t${cyc}z.bf$fhm3' - ;; - sfcgm2) geslist=' - $COMINcdas/cdas.t${cyc}z.bf$fhm2' - ;; - sfcgm1) geslist=' - $COMINcdas/cdas.t${cyc}z.bf$fhm1' - ;; - sfcgp1) geslist=' - $COMINcdas/cdas.t${cyc}z.bf$fhp1' - ;; - sfcgp2) geslist=' - $COMINcdas/cdas.t${cyc}z.bf$fhp2' - ;; - sfcgp3) geslist=' - $COMINcdas/cdas.t${cyc}z.bf$fhp3' - ;; - biascr) geslist=' - $COMINcdas/cdas.t${cyc}z.abias' - ;; - satang) geslist=' - $COMINcdas/cdas.t${cyc}z.satang' - ;; - satcnt) geslist=' - $COMINcdas/cdas.t${cyc}z.satcnt' - ;; - gesfil) geslist=' - $COMINcdas/cdas.t${cyc}z.gesfile' - fhbeg=00 - fhend=00 - ;; - pgbges) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbf$fh' - ;; - pgiges) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbif$fh' - ;; - pgbgm6) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbf$fhm6' - ;; - pgigm6) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbif$fhm6' - ;; - pgbgm3) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbf$fhm3' - ;; - pgigm3) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbif$fhm3' - ;; - pgbgp3) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbf$fhp3' - ;; - pgigp3) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbif$fhp3' - ;; - sigcur) geslist=' - $COMINcdas/cdas.t${cyc}z.sf$fh' - getlist00=' - $COMINcdas/cdas.t${cyc}z.sanl' - fhbeg=00 - ;; - sfccur) geslist=' - $COMINcdas/cdas.t${cyc}z.bf$fh' - getlist00=' - $COMINcdas/cdas.t${cyc}z.sfcanl' - fhbeg=00 - ;; - pgbcur) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbf$fh' - fhbeg=00 - ;; - pgicur) geslist=' - $COMINcdas/cdas.t${cyc}z.pgrbif$fh' - fhbeg=00 - ;; - prepqc) geslist=' - $COMINcdas/cdas.t${cyc}z.prepbufr' - fhbeg=00 - fhend=00 - ;; - tcvg12) geslist=' - $COMINcdas/cdas.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=12 - fhend=12 - ;; - tcvges) geslist=' - $COMINcdas/cdas.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=06 - fhend=06 - ;; - tcvitl) geslist=' - $COMINcdas/cdas.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=00 - fhend=00 - ;; - icegrb) geslist=' - $COMINcdas/cdas.t${cyc}z.engicegrb' - fhbeg=00 - fhinc=06 - ;; - icegri) geslist=' - $COMINcdas/cdas.t${cyc}z.engicegrb.index' - fhbeg=00 - fhinc=06 - ;; - snogrb) geslist=' - $COMINcdas/cdas.t${cyc}z.snogrb' - fhbeg=00 - fhinc=06 - ;; - snogri) geslist=' - $COMINcdas/cdas.t${cyc}z.snogrb.index' - fhbeg=00 - fhinc=06 - ;; - sstgrb) geslist=' - $COMINcdas/cdas.t${cyc}z.sstgrb' - fhbeg=00 - fhinc=06 - ;; - sstgri) geslist=' - $COMINcdas/cdas.t${cyc}z.sstgrb.index' - fhbeg=00 - fhinc=06 - ;; - esac +elif [[ "${netwk}" == "cdas" ]]; then + if [[ -z "${COMINcdas}" ]]; then + echo "getges.sh ERROR: The \${COMINcdas} variable must be defined." >&2 + exit 1 + fi + fhbeg=06 + fhend=06 + # shellcheck disable=SC2016 + case ${typef} in + sigges) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sf${fh}' + ;; + siggm3) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sf${fhm3}' + ;; + siggm2) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sf${fhm2}' + ;; + siggm1) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sf${fhm1}' + ;; + siggp1) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sf${fhp1}' + ;; + siggp2) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sf${fhp2}' + ;; + siggp3) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sf${fhp3}' + ;; + sfcges) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.bf${fh}' + ;; + sfcgm3) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.bf${fhm3}' + ;; + sfcgm2) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.bf${fhm2}' + ;; + sfcgm1) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.bf${fhm1}' + ;; + sfcgp1) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.bf${fhp1}' + ;; + sfcgp2) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.bf${fhp2}' + ;; + sfcgp3) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.bf${fhp3}' + ;; + biascr) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.abias' + ;; + satang) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.satang' + ;; + satcnt) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.satcnt' + ;; + gesfil) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.gesfile' + fhbeg=00 + fhend=00 + ;; + pgbges) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbf${fh}' + ;; + pgiges) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbif${fh}' + ;; + pgbgm6) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbf${fhm6}' + ;; + pgigm6) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbif${fhm6}' + ;; + pgbgm3) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbf${fhm3}' + ;; + pgigm3) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbif${fhm3}' + ;; + pgbgp3) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbf${fhp3}' + ;; + pgigp3) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbif${fhp3}' + ;; + sigcur) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sf${fh}' + getlist00=' + ${COMINcdas}/cdas.t${cyc}z.sanl' + fhbeg=00 + ;; + sfccur) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.bf${fh}' + getlist00=' + ${COMINcdas}/cdas.t${cyc}z.sfcanl' + fhbeg=00 + ;; + pgbcur) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbf${fh}' + fhbeg=00 + ;; + pgicur) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.pgrbif${fh}' + fhbeg=00 + ;; + prepqc) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.prepbufr' + fhbeg=00 + fhend=00 + ;; + tcvg12) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=12 + fhend=12 + ;; + tcvges) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=06 + fhend=06 + ;; + tcvitl) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=00 + fhend=00 + ;; + icegrb) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.engicegrb' + fhbeg=00 + fhinc=06 + ;; + icegri) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.engicegrb.index' + fhbeg=00 + fhinc=06 + ;; + snogrb) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.snogrb' + fhbeg=00 + fhinc=06 + ;; + snogri) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.snogrb.index' + fhbeg=00 + fhinc=06 + ;; + sstgrb) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sstgrb' + fhbeg=00 + fhinc=06 + ;; + sstgri) + geslist=' + ${COMINcdas}/cdas.t${cyc}z.sstgrb.index' + fhbeg=00 + fhinc=06 + ;; + *) + msg="FATAL ERROR: Unknown ${netwk} guess type ${typef}" + export err=101 + err_exit "${msg}" + ;; + esac # CDC CDAS -elif [[ "$netwk" = "cdc" ]];then - if [ -z "$COMINcdc" ]; then - echo "getges.sh ERROR: The \$COMINcdc variable must be defined." >&2 - exit 1 - fi - fhbeg=06 - fhend=06 - case $typef in - sigges) geslist=' - $COMINcdc/cdas.t${cyc}z.sf$fh' - ;; - siggm3) geslist=' - $COMINcdc/cdas.t${cyc}z.sf$fhm3' - ;; - siggm2) geslist=' - $COMINcdc/cdas.t${cyc}z.sf$fhm2' - ;; - siggm1) geslist=' - $COMINcdc/cdas.t${cyc}z.sf$fhm1' - ;; - siggp1) geslist=' - $COMINcdc/cdas.t${cyc}z.sf$fhp1' - ;; - siggp2) geslist=' - $COMINcdc/cdas.t${cyc}z.sf$fhp2' - ;; - siggp3) geslist=' - $COMINcdc/cdas.t${cyc}z.sf$fhp3' - ;; - sfcges) geslist=' - $COMINcdc/cdas.t${cyc}z.bf$fh' - ;; - sfcgm3) geslist=' - $COMINcdc/cdas.t${cyc}z.bf$fhm3' - ;; - sfcgm2) geslist=' - $COMINcdc/cdas.t${cyc}z.bf$fhm2' - ;; - sfcgm1) geslist=' - $COMINcdc/cdas.t${cyc}z.bf$fhm1' - ;; - sfcgp1) geslist=' - $COMINcdc/cdas.t${cyc}z.bf$fhp1' - ;; - sfcgp2) geslist=' - $COMINcdc/cdas.t${cyc}z.bf$fhp2' - ;; - sfcgp3) geslist=' - $COMINcdc/cdas.t${cyc}z.bf$fhp3' - ;; - biascr) geslist=' - $COMINcdc/cdas.t${cyc}z.abias' - ;; - satang) geslist=' - $COMINcdc/cdas.t${cyc}z.satang' - ;; - satcnt) geslist=' - $COMINcdc/cdas.t${cyc}z.satcnt' - ;; - gesfil) geslist=' - $COMINcdc/cdas.t${cyc}z.gesfile' - fhbeg=00 - fhend=00 - ;; - pgbges) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbf$fh' - ;; - pgiges) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbif$fh' - ;; - pgbgm6) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbf$fhm6' - ;; - pgigm6) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbif$fhm6' - ;; - pgbgm3) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbf$fhm3' - ;; - pgigm3) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbif$fhm3' - ;; - pgbgp3) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbf$fhp3' - ;; - pgigp3) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbif$fhp3' - ;; - sigcur) geslist=' - $COMINcdc/cdas.t${cyc}z.sf$fh' - getlist00=' - $COMINcdc/cdas.t${cyc}z.sanl' - fhbeg=00 - ;; - sfccur) geslist=' - $COMINcdc/cdas.t${cyc}z.bf$fh' - getlist00=' - $COMINcdc/cdas.t${cyc}z.sfcanl' - fhbeg=00 - ;; - pgbcur) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbf$fh' - fhbeg=00 - ;; - pgicur) geslist=' - $COMINcdc/cdas.t${cyc}z.pgrbif$fh' - fhbeg=00 - ;; - prepqc) geslist=' - $COMINcdc/cdas.t${cyc}z.prepbufr' - fhbeg=00 - fhend=00 - ;; - tcvg12) geslist=' - $COMINcdc/cdas.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=12 - fhend=12 - ;; - tcvges) geslist=' - $COMINcdc/cdas.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=06 - fhend=06 - ;; - tcvitl) geslist=' - $COMINcdc/cdas.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=00 - fhend=00 - ;; - icegrb) geslist=' - $COMINcdc/cdas.t${cyc}z.engicegrb' - fhbeg=00 - fhinc=06 - ;; - icegri) geslist=' - $COMINcdc/cdas.t${cyc}z.engicegrb.index' - fhbeg=00 - fhinc=06 - ;; - snogrb) geslist=' - $COMINcdc/cdas.t${cyc}z.snogrb' - fhbeg=00 - fhinc=06 - ;; - snogri) geslist=' - $COMINcdc/cdas.t${cyc}z.snogrb.index' - fhbeg=00 - fhinc=06 - ;; - sstgrb) geslist=' - $COMINcdc/cdas.t${cyc}z.sstgrb' - fhbeg=00 - fhinc=06 - ;; - sstgri) geslist=' - $COMINcdc/cdas.t${cyc}z.sstgrb.index' - fhbeg=00 - fhinc=06 - ;; - esac +elif [[ "${netwk}" == "cdc" ]]; then + if [[ -z "${COMINcdc}" ]]; then + echo "getges.sh ERROR: The \${COMINcdc} variable must be defined." >&2 + exit 1 + fi + fhbeg=06 + fhend=06 + # shellcheck disable=SC2016 + case "${typef}" in + sigges) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sf${fh}' + ;; + siggm3) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sf${fhm3}' + ;; + siggm2) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sf${fhm2}' + ;; + siggm1) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sf${fhm1}' + ;; + siggp1) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sf${fhp1}' + ;; + siggp2) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sf${fhp2}' + ;; + siggp3) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sf${fhp3}' + ;; + sfcges) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.bf${fh}' + ;; + sfcgm3) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.bf${fhm3}' + ;; + sfcgm2) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.bf${fhm2}' + ;; + sfcgm1) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.bf${fhm1}' + ;; + sfcgp1) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.bf${fhp1}' + ;; + sfcgp2) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.bf${fhp2}' + ;; + sfcgp3) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.bf${fhp3}' + ;; + biascr) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.abias' + ;; + satang) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.satang' + ;; + satcnt) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.satcnt' + ;; + gesfil) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.gesfile' + fhbeg=00 + fhend=00 + ;; + pgbges) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbf${fh}' + ;; + pgiges) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbif${fh}' + ;; + pgbgm6) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbf${fhm6}' + ;; + pgigm6) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbif${fhm6}' + ;; + pgbgm3) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbf${fhm3}' + ;; + pgigm3) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbif${fhm3}' + ;; + pgbgp3) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbf${fhp3}' + ;; + pgigp3) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbif${fhp3}' + ;; + sigcur) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sf${fh}' + getlist00=' + ${COMINcdc}/cdas.t${cyc}z.sanl' + fhbeg=00 + ;; + sfccur) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.bf${fh}' + getlist00=' + ${COMINcdc}/cdas.t${cyc}z.sfcanl' + fhbeg=00 + ;; + pgbcur) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbf${fh}' + fhbeg=00 + ;; + pgicur) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.pgrbif${fh}' + fhbeg=00 + ;; + prepqc) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.prepbufr' + fhbeg=00 + fhend=00 + ;; + tcvg12) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=12 + fhend=12 + ;; + tcvges) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=06 + fhend=06 + ;; + tcvitl) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=00 + fhend=00 + ;; + icegrb) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.engicegrb' + fhbeg=00 + fhinc=06 + ;; + icegri) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.engicegrb.index' + fhbeg=00 + fhinc=06 + ;; + snogrb) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.snogrb' + fhbeg=00 + fhinc=06 + ;; + snogri) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.snogrb.index' + fhbeg=00 + fhinc=06 + ;; + sstgrb) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sstgrb' + fhbeg=00 + fhinc=06 + ;; + sstgri) + geslist=' + ${COMINcdc}/cdas.t${cyc}z.sstgrb.index' + fhbeg=00 + fhinc=06 + ;; + *) + msg="FATAL ERROR: Unknown ${netwk} guess type ${typef}" + export err=101 + err_exit "${msg}" + ;; + esac # Any resolution production -elif [[ "$netwk" = "global" ]];then - if [ -z "$COMINgdas" ]; then - echo "getges.sh ERROR: The \$COMINgdas variable must be defined." >&2 - exit 1 - fi - if [ -z "$COMINgfs" ]; then - echo "getges.sh ERROR: The \$COMINgfs variable must be defined." >&2 - exit 1 - fi - GETGES_NWG=${GETGES_NWG:-${GESROOT:?}} - case $typef in - biascr) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.abias - $COMINgdas/gdas.t${cyc}z.abias - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.abias - $COMINgfs/gfs.t${cyc}z.abias' - fhbeg=06 - fhinc=06 - ;; - pgbges) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbh$fh - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbf$fh - $COMINgdas/gdas.t${cyc}z.pgrbh$fh - $COMINgdas/gdas.t${cyc}z.pgrbf$fh - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrbf$fh - $COMINgfs/gfs.t${cyc}z.pgrbf$fh' - ;; - pgbgm6) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbh$fhm6 - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbf$fhm6 - $COMINgdas/gdas.t${cyc}z.pgrbh$fhm6 - $COMINgdas/gdas.t${cyc}z.pgrbf$fhm6 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrbf$fhm6 - $COMINgfs/gfs.t${cyc}z.pgrbf$fhm6' - ;; - pgbgm3) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbh$fhm3 - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbf$fhm3 - $COMINgdas/gdas.t${cyc}z.pgrbh$fhm3 - $COMINgdas/gdas.t${cyc}z.pgrbf$fhm3 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrbf$fhm3 - $COMINgfs/gfs.t${cyc}z.pgrbf$fhm3' - ;; - pgbgp3) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbh$fhp3 - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbf$fhp3 - $COMINgdas/gdas.t${cyc}z.pgrbh$fhp3 - $COMINgdas/gdas.t${cyc}z.pgrbf$fhp3 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrbf$fhp3 - $COMINgfs/gfs.t${cyc}z.pgrbf$fhp3' - ;; - pg2ges) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$gh - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$gh - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$gh - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$gh' - ;; - pg2gm6) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$ghm6 - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$ghm6 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$ghm6 - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$ghm6' - ;; - pg2gm5) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$ghm5 - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$ghm5 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$ghm5 - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$ghm5' - ;; - pg2gm4) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$ghm4 - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$ghm4 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$ghm4 - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$ghm4' - ;; - pg2gm3) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$ghm3 - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$ghm3 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$ghm3 - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$ghm3' - ;; - pg2gm2) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$ghm2 - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$ghm2 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$ghm2 - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$ghm2' - ;; - pg2gm1) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$ghm1 - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$ghm1 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$ghm1 - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$ghm1' - ;; - pg2gp1) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$ghp1 - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$ghp1 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$ghp1 - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$ghp1' - ;; - pg2gp2) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$ghp2 - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$ghp2 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$ghp2 - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$ghp2' - ;; - pg2gp3) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p25.f$ghp3 - $COMINgdas/gdas.t${cyc}z.pgrb2.0p25.f$ghp3 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p25.f$ghp3 - $COMINgfs/gfs.t${cyc}z.pgrb2.0p25.f$ghp3' - ;; - pgbcur) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbh$fh - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrbf$fh - $COMINgdas/gdas.t${cyc}z.pgrbh$fh - $COMINgdas/gdas.t${cyc}z.pgrbf$fh - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrbf$fh - $COMINgfs/gfs.t${cyc}z.pgrbf$fh' - fhbeg=00 - ;; - pg2cur) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.pgrb2.0p50.f$gh - $COMINgdas/gdas.t${cyc}z.pgrb2.0p50.f$gh - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.pgrb2.0p50.f$gh - $COMINgfs/gfs.t${cyc}z.pgrb2.0p50.f$gh' - fhbeg=00 - ;; - prepqc) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.prepbufr - $COMINgdas/gdas.t${cyc}z.prepbufr - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.prepbufr - $COMINgfs/gfs.t${cyc}z.prepbufr' - fhbeg=00 - fhend=00 - ;; - tcvg12) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.syndata.tcvitals.tm00 - $COMINgdas/gdas.t${cyc}z.syndata.tcvitals.tm00 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.syndata.tcvitals.tm00 - $COMINgfs/gfs.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=12 - fhend=12 - ;; - tcvges) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.syndata.tcvitals.tm00 - $COMINgdas/gdas.t${cyc}z.syndata.tcvitals.tm00 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.syndata.tcvitals.tm00 - $COMINgfs/gfs.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=06 - fhend=06 - ;; - tcvitl) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.syndata.tcvitals.tm00 - $COMINgdas/gdas.t${cyc}z.syndata.tcvitals.tm00 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.syndata.tcvitals.tm00 - $COMINgfs/gfs.t${cyc}z.syndata.tcvitals.tm00' - fhbeg=00 - fhend=00 - ;; - icegrb) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.engicegrb - $COMINgdas/gdas.t${cyc}z.engicegrb - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.engicegrb - $COMINgfs/gfs.t${cyc}z.engicegrb' - fhbeg=00 - fhinc=06 - ;; - snogrb) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.snogrb - $COMINgdas/gdas.t${cyc}z.snogrb - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.snogrb - $COMINgfs/gfs.t${cyc}z.snogrb' - fhbeg=00 - fhinc=06 - ;; - snogrb_574) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.snogrb_t574.1152.576 - $COMINgdas/gdas.t${cyc}z.snogrb_t574.1152.576 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.snogrb_t574.1152.576 - $COMINgfs/gfs.t${cyc}z.snogrb_t574.1152.576' - fhbeg=00 - fhinc=06 - ;; - snogrb_1534) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.snogrb_t1534.3072.1536 - $COMINgdas/gdas.t${cyc}z.snogrb_t1534.3072.1536 - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.snogrb_t1534.3072.1536 - $COMINgfs/gfs.t${cyc}z.snogrb_t1534.3072.1536' - fhbeg=00 - fhinc=06 - ;; - sstgrb) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sstgrb - $COMINgdas/gdas.t${cyc}z.sstgrb - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sstgrb - $COMINgfs/gfs.t${cyc}z.sstgrb' - fhbeg=00 - fhinc=06 - ;; - natges) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.atmf$gh.nemsio - $COMINgdas/gdas.t${cyc}z.atmf$gh.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.atmf$gh.nemsio - $COMINgfs/gfs.t${cyc}z.atmf$gh.nemsio' - ;; - natgm3) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.atm.f$ghm3.nemsio - $COMINgdas/gdas.t${cyc}z.atmf$ghm3.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.atm.f$ghm3.nemsio - $COMINgfs/gfs.t${cyc}z.atmf$ghm3.nemsio' - ;; - natgm2) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.atmf$ghm2.nemsio - $COMINgdas/gdas.t${cyc}z.atmf$ghm2.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.atmf$ghm2.nemsio - $COMINgfs/gfs.t${cyc}z.atmf$ghm2.nemsio' - ;; - natgm1) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.atmf$ghm1.nemsio - $COMINgdas/gdas.t${cyc}z.atmf$ghm1.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.atmf$ghm1.nemsio - $COMINgfs/gfs.t${cyc}z.atmf$ghm1.nemsio' - ;; - natgp1) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.atmf$ghp1.nemsio - $COMINgdas/gdas.t${cyc}z.atmf$ghp1.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.atmf$ghp1.nemsio - $COMINgfs/gfs.t${cyc}z.atmf$ghp1.nemsio' - ;; - natgp2) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.atmf$ghp2.nemsio - $COMINgdas/gdas.t${cyc}z.atmf$ghp2.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.atmf$ghp2.nemsio - $COMINgfs/gfs.t${cyc}z.atmf$ghp2.nemsio' - ;; - natgp3) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.atmf$ghp3.nemsio - $COMINgdas/gdas.t${cyc}z.atmf$ghp3.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.atmf$ghp3.nemsio - $COMINgfs/gfs.t${cyc}z.atmf$ghp3.nemsio' - ;; - natcur) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.atmf$gh.nemsio - $COMINgdas/gdas.t${cyc}z.atmf$gh.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.atmf$gh.nemsio - $COMINgfs/gfs.t${cyc}z.atmf$gh.nemsio' - getlist00=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.atmanl.nemsio - $COMINgdas/gdas.t${cyc}z.atmanl.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.atmanl.nemsio - $COMINgfs/gfs.t${cyc}z.atmanl.nemsio' - fhbeg=00 - ;; - nsfges) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sfcf$gh.nemsio - $COMINgdas/gdas.t${cyc}z.sfcf$gh.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sfcf$gh.nemsio - $COMINgfs/gfs.t${cyc}z.sfcf$gh.nemsio' - ;; - nsfgm3) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sfcf$ghm3.nemsio - $COMINgdas/gdas.t${cyc}z.sfcf$ghm3.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sfcf$ghm3.nemsio - $COMINgfs/gfs.t${cyc}z.sfcf$ghm3.nemsio' - ;; - nsfgm2) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sfcf$ghm2.nemsio - $COMINgdas/gdas.t${cyc}z.sfcf$ghm2.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sfcf$ghm2.nemsio - $COMINgfs/gfs.t${cyc}z.sfcf$ghm2.nemsio' - ;; - nsfgm1) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sfcf$ghm1.nemsio - $COMINgdas/gdas.t${cyc}z.sfcf$ghm1.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sfcf$ghm1.nemsio - $COMINgfs/gfs.t${cyc}z.sfcf$ghm1.nemsio' - ;; - nsfgp1) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sfcf$ghp1.nemsio - $COMINgdas/gdas.t${cyc}z.sfcf$ghp1.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sfcf$ghp1.nemsio - $COMINgfs/gfs.t${cyc}z.sfcf$ghp1.nemsio' - ;; - nsfgp2) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sfcf$ghp2.nemsio - $COMINgdas/gdas.t${cyc}z.sfcf$ghp2.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sfcf$ghp2.nemsio - $COMINgfs/gfs.t${cyc}z.sfcf$ghp2.nemsio' - ;; - nsfgp3) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sfcf$ghp3.nemsio - $COMINgdas/gdas.t${cyc}z.sfcf$ghp3.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sfcf$ghp3.nemsio - $COMINgfs/gfs.t${cyc}z.sfcf$ghp3.nemsio' - ;; - nsfcur) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sfcf$gh.nemsio - $COMINgdas/gdas.t${cyc}z.sfcf$gh.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sfcf$gh.nemsio - $COMINgfs/gfs.t${cyc}z.sfcf$gh.nemsio' - getlist00=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.sfcanl.nemsio - $COMINgdas/gdas.t${cyc}z.sfcanl.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.sfcanl.nemsio - $COMINgfs/gfs.t${cyc}z.sfcanl.nemsio' - fhbeg=00 - ;; - nstcur) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.nstf$gh.nemsio - $COMINgdas/gdas.t${cyc}z.nstf$gh.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.nstf$gh.nemsio - $COMINgfs/gfs.t${cyc}z.nstf$gh.nemsio' - getlist00=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.nstanl.nemsio - $COMINgdas/gdas.t${cyc}z.nstanl.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.nstanl.nemsio - $COMINgfs/gfs.t${cyc}z.nstanl.nemsio' - fhbeg=00 - ;; - nflges) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.flxf$gh.nemsio - $COMINgdas/gdas.t${cyc}z.flxf$gh.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.flxf$gh.nemsio - $COMINgfs/gfs.t${cyc}z.flxf$gh.nemsio' - ;; - nflgp3) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.flxf$ghp3.nemsio - $COMINgdas/gdas.t${cyc}z.flxf$ghp3.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.flxf$ghp3.nemsio - $COMINgfs/gfs.t${cyc}z.flxf$ghp3.nemsio' - ;; - nflcur) geslist=' - $GETGES_NWG/$envir/gdas.$day/gdas.t${cyc}z.flxf$gh.nemsio - $COMINgdas/gdas.t${cyc}z.flxf$gh.nemsio - $GETGES_NWG/$envir/gfs.$day/gfs.t${cyc}z.flxf$gh.nemsio - $COMINgfs/gfs.t${cyc}z.flxf$gh.nemsio' - fhbeg=00 - ;; - esac +elif [[ "${netwk}" == "global" ]]; then + if [[ -z "${COMINgdas}" ]]; then + echo "getges.sh ERROR: The \${COMINgdas} variable must be defined." >&2 + exit 1 + fi + if [[ -z "${COMINgfs}" ]]; then + echo "getges.sh ERROR: The \${COMINgfs} variable must be defined." >&2 + exit 1 + fi + GETGES_NWG=${GETGES_NWG:-${GESROOT:?}} + # shellcheck disable=SC2016 + case "${typef}" in + biascr) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.abias + ${COMINgdas}/gdas.t${cyc}z.abias + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.abias + ${COMINgfs}/gfs.t${cyc}z.abias' + fhbeg=06 + fhinc=06 + ;; + pgbges) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbh${fh} + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbf${fh} + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fh} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fh} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrbf${fh} + ${COMINgfs}/gfs.t${cyc}z.pgrbf${fh}' + ;; + pgbgm6) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbh${fhm6} + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbf${fhm6} + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fhm6} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fhm6} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrbf${fhm6} + ${COMINgfs}/gfs.t${cyc}z.pgrbf${fhm6}' + ;; + pgbgm3) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbh${fhm3} + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbf${fhm3} + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fhm3} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fhm3} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrbf${fhm3} + ${COMINgfs}/gfs.t${cyc}z.pgrbf${fhm3}' + ;; + pgbgp3) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbh${fhp3} + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbf${fhp3} + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fhp3} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fhp3} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrbf${fhp3} + ${COMINgfs}/gfs.t${cyc}z.pgrbf${fhp3}' + ;; + pg2ges) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${gh} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${gh} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${gh} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${gh}' + ;; + pg2gm6) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${ghm6} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${ghm6} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${ghm6} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${ghm6}' + ;; + pg2gm5) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${ghm5} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${ghm5} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${ghm5} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${ghm5}' + ;; + pg2gm4) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${ghm4} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${ghm4} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${ghm4} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${ghm4}' + ;; + pg2gm3) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${ghm3} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${ghm3} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${ghm3} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${ghm3}' + ;; + pg2gm2) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${ghm2} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${ghm2} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${ghm2} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${ghm2}' + ;; + pg2gm1) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${ghm1} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${ghm1} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${ghm1} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${ghm1}' + ;; + pg2gp1) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${ghp1} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${ghp1} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${ghp1} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${ghp1}' + ;; + pg2gp2) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${ghp2} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${ghp2} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${ghp2} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${ghp2}' + ;; + pg2gp3) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p25.f${ghp3} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p25.f${ghp3} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p25.f${ghp3} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p25.f${ghp3}' + ;; + pgbcur) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbh${fh} + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrbf${fh} + ${COMINgdas}/gdas.t${cyc}z.pgrbh${fh} + ${COMINgdas}/gdas.t${cyc}z.pgrbf${fh} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrbf${fh} + ${COMINgfs}/gfs.t${cyc}z.pgrbf${fh}' + fhbeg=00 + ;; + pg2cur) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.pgrb2.0p50.f${gh} + ${COMINgdas}/gdas.t${cyc}z.pgrb2.0p50.f${gh} + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.pgrb2.0p50.f${gh} + ${COMINgfs}/gfs.t${cyc}z.pgrb2.0p50.f${gh}' + fhbeg=00 + ;; + prepqc) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.prepbufr + ${COMINgdas}/gdas.t${cyc}z.prepbufr + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.prepbufr + ${COMINgfs}/gfs.t${cyc}z.prepbufr' + fhbeg=00 + fhend=00 + ;; + tcvg12) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.syndata.tcvitals.tm00 + ${COMINgdas}/gdas.t${cyc}z.syndata.tcvitals.tm00 + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.syndata.tcvitals.tm00 + ${COMINgfs}/gfs.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=12 + fhend=12 + ;; + tcvges) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.syndata.tcvitals.tm00 + ${COMINgdas}/gdas.t${cyc}z.syndata.tcvitals.tm00 + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.syndata.tcvitals.tm00 + ${COMINgfs}/gfs.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=06 + fhend=06 + ;; + tcvitl) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.syndata.tcvitals.tm00 + ${COMINgdas}/gdas.t${cyc}z.syndata.tcvitals.tm00 + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.syndata.tcvitals.tm00 + ${COMINgfs}/gfs.t${cyc}z.syndata.tcvitals.tm00' + fhbeg=00 + fhend=00 + ;; + icegrb) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.engicegrb + ${COMINgdas}/gdas.t${cyc}z.engicegrb + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.engicegrb + ${COMINgfs}/gfs.t${cyc}z.engicegrb' + fhbeg=00 + fhinc=06 + ;; + snogrb) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.snogrb + ${COMINgdas}/gdas.t${cyc}z.snogrb + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.snogrb + ${COMINgfs}/gfs.t${cyc}z.snogrb' + fhbeg=00 + fhinc=06 + ;; + snogrb_574) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.snogrb_t574.1152.576 + ${COMINgdas}/gdas.t${cyc}z.snogrb_t574.1152.576 + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.snogrb_t574.1152.576 + ${COMINgfs}/gfs.t${cyc}z.snogrb_t574.1152.576' + fhbeg=00 + fhinc=06 + ;; + snogrb_1534) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.snogrb_t1534.3072.1536 + ${COMINgdas}/gdas.t${cyc}z.snogrb_t1534.3072.1536 + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.snogrb_t1534.3072.1536 + ${COMINgfs}/gfs.t${cyc}z.snogrb_t1534.3072.1536' + fhbeg=00 + fhinc=06 + ;; + sstgrb) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sstgrb + ${COMINgdas}/gdas.t${cyc}z.sstgrb + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sstgrb + ${COMINgfs}/gfs.t${cyc}z.sstgrb' + fhbeg=00 + fhinc=06 + ;; + natges) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.atmf${gh}.nemsio + ${COMINgdas}/gdas.t${cyc}z.atmf${gh}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.atmf${gh}.nemsio + ${COMINgfs}/gfs.t${cyc}z.atmf${gh}.nemsio' + ;; + natgm3) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.atm.f${ghm3}.nemsio + ${COMINgdas}/gdas.t${cyc}z.atmf${ghm3}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.atm.f${ghm3}.nemsio + ${COMINgfs}/gfs.t${cyc}z.atmf${ghm3}.nemsio' + ;; + natgm2) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.atmf${ghm2}.nemsio + ${COMINgdas}/gdas.t${cyc}z.atmf${ghm2}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.atmf${ghm2}.nemsio + ${COMINgfs}/gfs.t${cyc}z.atmf${ghm2}.nemsio' + ;; + natgm1) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.atmf${ghm1}.nemsio + ${COMINgdas}/gdas.t${cyc}z.atmf${ghm1}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.atmf${ghm1}.nemsio + ${COMINgfs}/gfs.t${cyc}z.atmf${ghm1}.nemsio' + ;; + natgp1) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.atmf${ghp1}.nemsio + ${COMINgdas}/gdas.t${cyc}z.atmf${ghp1}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.atmf${ghp1}.nemsio + ${COMINgfs}/gfs.t${cyc}z.atmf${ghp1}.nemsio' + ;; + natgp2) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.atmf${ghp2}.nemsio + ${COMINgdas}/gdas.t${cyc}z.atmf${ghp2}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.atmf${ghp2}.nemsio + ${COMINgfs}/gfs.t${cyc}z.atmf${ghp2}.nemsio' + ;; + natgp3) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.atmf${ghp3}.nemsio + ${COMINgdas}/gdas.t${cyc}z.atmf${ghp3}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.atmf${ghp3}.nemsio + ${COMINgfs}/gfs.t${cyc}z.atmf${ghp3}.nemsio' + ;; + natcur) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.atmf${gh}.nemsio + ${COMINgdas}/gdas.t${cyc}z.atmf${gh}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.atmf${gh}.nemsio + ${COMINgfs}/gfs.t${cyc}z.atmf${gh}.nemsio' + getlist00=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.atmanl.nemsio + ${COMINgdas}/gdas.t${cyc}z.atmanl.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.atmanl.nemsio + ${COMINgfs}/gfs.t${cyc}z.atmanl.nemsio' + fhbeg=00 + ;; + nsfges) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sfcf${gh}.nemsio + ${COMINgdas}/gdas.t${cyc}z.sfcf${gh}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sfcf${gh}.nemsio + ${COMINgfs}/gfs.t${cyc}z.sfcf${gh}.nemsio' + ;; + nsfgm3) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sfcf${ghm3}.nemsio + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghm3}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sfcf${ghm3}.nemsio + ${COMINgfs}/gfs.t${cyc}z.sfcf${ghm3}.nemsio' + ;; + nsfgm2) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sfcf${ghm2}.nemsio + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghm2}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sfcf${ghm2}.nemsio + ${COMINgfs}/gfs.t${cyc}z.sfcf${ghm2}.nemsio' + ;; + nsfgm1) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sfcf${ghm1}.nemsio + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghm1}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sfcf${ghm1}.nemsio + ${COMINgfs}/gfs.t${cyc}z.sfcf${ghm1}.nemsio' + ;; + nsfgp1) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sfcf${ghp1}.nemsio + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghp1}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sfcf${ghp1}.nemsio + ${COMINgfs}/gfs.t${cyc}z.sfcf${ghp1}.nemsio' + ;; + nsfgp2) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sfcf${ghp2}.nemsio + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghp2}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sfcf${ghp2}.nemsio + ${COMINgfs}/gfs.t${cyc}z.sfcf${ghp2}.nemsio' + ;; + nsfgp3) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sfcf${ghp3}.nemsio + ${COMINgdas}/gdas.t${cyc}z.sfcf${ghp3}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sfcf${ghp3}.nemsio + ${COMINgfs}/gfs.t${cyc}z.sfcf${ghp3}.nemsio' + ;; + nsfcur) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sfcf${gh}.nemsio + ${COMINgdas}/gdas.t${cyc}z.sfcf${gh}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sfcf${gh}.nemsio + ${COMINgfs}/gfs.t${cyc}z.sfcf${gh}.nemsio' + getlist00=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.sfcanl.nemsio + ${COMINgdas}/gdas.t${cyc}z.sfcanl.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.sfcanl.nemsio + ${COMINgfs}/gfs.t${cyc}z.sfcanl.nemsio' + fhbeg=00 + ;; + nstcur) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.nstf${gh}.nemsio + ${COMINgdas}/gdas.t${cyc}z.nstf${gh}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.nstf${gh}.nemsio + ${COMINgfs}/gfs.t${cyc}z.nstf${gh}.nemsio' + # shellcheck disable=SC2034 + getlist00=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.nstanl.nemsio + ${COMINgdas}/gdas.t${cyc}z.nstanl.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.nstanl.nemsio + ${COMINgfs}/gfs.t${cyc}z.nstanl.nemsio' + fhbeg=00 + ;; + nflges) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.flxf${gh}.nemsio + ${COMINgdas}/gdas.t${cyc}z.flxf${gh}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.flxf${gh}.nemsio + ${COMINgfs}/gfs.t${cyc}z.flxf${gh}.nemsio' + ;; + nflgp3) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.flxf${ghp3}.nemsio + ${COMINgdas}/gdas.t${cyc}z.flxf${ghp3}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.flxf${ghp3}.nemsio + ${COMINgfs}/gfs.t${cyc}z.flxf${ghp3}.nemsio' + ;; + nflcur) + geslist=' + ${GETGES_NWG}/${envir}/gdas.${day}/gdas.t${cyc}z.flxf${gh}.nemsio + ${COMINgdas}/gdas.t${cyc}z.flxf${gh}.nemsio + ${GETGES_NWG}/${envir}/gfs.${day}/gfs.t${cyc}z.flxf${gh}.nemsio + ${COMINgfs}/gfs.t${cyc}z.flxf${gh}.nemsio' + fhbeg=00 + ;; + *) + msg="FATAL ERROR: Unknown ${netwk} guess type ${typef}" + export err=101 + err_exit "${msg}" + ;; + esac fi # Check validity of options. -if [[ $fhour != any ]];then - fhbeg=$fhour - fhend=$fhour +if [[ "${fhour}" != any ]]; then + fhbeg="${fhour}" + fhend="${fhour}" fi -if [[ $valid -lt 20000000 ]];then - valid=20$valid - echo '************************************************************' >&2 - echo '* WARNING: A 2-digit year was converted to a 4-digit year. *' >&2 - echo '* Please use full a 4-digit year in this utility. *' >&2 - echo '************************************************************' >&2 +if [[ "${valid}" -lt 20000000 ]]; then + valid="20${valid}" + echo '************************************************************' >&2 + echo '* WARNING: A 2-digit year was converted to a 4-digit year. *' >&2 + echo '* Please use full a 4-digit year in this utility. *' >&2 + echo '************************************************************' >&2 fi -if [[ -z "$geslist" ]];then - echo getges.sh: filetype $typef or resolution $resol not recognized >&2 - exit 2 +if [[ -z "${geslist}" ]]; then + echo "getges.sh: filetype ${typef} or resolution ${resol} not recognized" >&2 + exit 2 fi #------------------------------------------------------------------------------- # Loop until guess is found. -fh=$fhbeg -if [ -z "$PDY" ];then echo "getges.sh WARNING: \$PDY variable not set" >&2; fi -while [[ $fh -le $fhend ]];do - ((fhm6=10#${fh}-6)) - if [[ ${fhm6} -lt 10 && ${fhm6} -ge 0 ]]; then - fhm6=0${fhm6} - fi - ((fhm5=10#${fh}-5)) - if [[ ${fhm5} -lt 10 && ${fhm5} -ge 0 ]]; then - fhm5=0${fhm5} - fi - ((fhm4=10#${fh}-4)) - if [[ ${fhm4} -lt 10 && ${fhm4} -ge 0 ]]; then - fhm4=0${fhm4} - fi - ((fhm3=10#${fh}-3)) - if [[ ${fhm3} -lt 10 && ${fhm3} -ge 0 ]]; then - fhm3=0${fhm3} - fi - ((fhm2=10#${fh}-2)) - if [[ ${fhm2} -lt 10 && ${fhm2} -ge 0 ]]; then - fhm2=0${fhm2} - fi - ((fhm1=10#${fh}-1)) - if [[ ${fhm1} -lt 10 && ${fhm1} -ge 0 ]]; then - fhm1=0${fhm1} - fi - ((fhp1=10#${fh}+1)) - if [[ ${fhp1} -lt 10 ]]; then - fhp1=0${fhp1} - fi - ((fhp2=10#${fh}+2)) - if [[ ${fhp2} -lt 10 ]]; then - fhp2=0${fhp2} - fi - ((fhp3=10#${fh}+3)) - if [[ ${fhp3} -lt 10 ]]; then - fhp3=0${fhp3} - fi - gh=$fh;[[ $gh -lt 100 ]]&&gh=0$gh - ghm6=$fhm6;[[ $ghm6 -lt 100 ]]&&ghm6=0$ghm6 - ghm5=$fhm5;[[ $ghm5 -lt 100 ]]&&ghm5=0$ghm5 - ghm4=$fhm4;[[ $ghm4 -lt 100 ]]&&ghm4=0$ghm4 - ghm3=$fhm3;[[ $ghm3 -lt 100 ]]&&ghm3=0$ghm3 - ghm2=$fhm2;[[ $ghm2 -lt 100 ]]&&ghm2=0$ghm2 - ghm1=$fhm1;[[ $ghm1 -lt 100 ]]&&ghm1=0$ghm1 - ghp1=$fhp1;[[ $ghp1 -lt 100 ]]&&ghp1=0$ghp1 - ghp2=$fhp2;[[ $ghp2 -lt 100 ]]&&ghp2=0$ghp2 - ghp3=$fhp3;[[ $ghp3 -lt 100 ]]&&ghp3=0$ghp3 - id=$(date --utc +%Y%m%d%H -d "${valid:0:8} ${valid:8:2} - ${fh} hours") +fh=${fhbeg} +if [[ -z "${PDY}" ]]; then echo "getges.sh WARNING: \${PDY} variable not set" >&2; fi +while [[ "${fh}" -le "${fhend}" ]]; do + ((fhm6 = 10#${fh} - 6)) + if [[ ${fhm6} -lt 10 && ${fhm6} -ge 0 ]]; then + fhm6=0${fhm6} + fi + ((fhm5 = 10#${fh} - 5)) + if [[ ${fhm5} -lt 10 && ${fhm5} -ge 0 ]]; then + fhm5=0${fhm5} + fi + ((fhm4 = 10#${fh} - 4)) + if [[ ${fhm4} -lt 10 && ${fhm4} -ge 0 ]]; then + fhm4=0${fhm4} + fi + ((fhm3 = 10#${fh} - 3)) + if [[ ${fhm3} -lt 10 && ${fhm3} -ge 0 ]]; then + fhm3=0${fhm3} + fi + ((fhm2 = 10#${fh} - 2)) + if [[ ${fhm2} -lt 10 && ${fhm2} -ge 0 ]]; then + fhm2=0${fhm2} + fi + ((fhm1 = 10#${fh} - 1)) + if [[ ${fhm1} -lt 10 && ${fhm1} -ge 0 ]]; then + fhm1=0${fhm1} + fi + ((fhp1 = 10#${fh} + 1)) + if [[ ${fhp1} -lt 10 ]]; then + fhp1=0${fhp1} + fi + ((fhp2 = 10#${fh} + 2)) + if [[ ${fhp2} -lt 10 ]]; then + fhp2=0${fhp2} + fi + ((fhp3 = 10#${fh} + 3)) + if [[ ${fhp3} -lt 10 ]]; then + fhp3=0${fhp3} + fi + gh="${fh}" + [[ "${gh}" -lt 100 ]] && gh="0${gh}" + ghm6="${fhm6}" + [[ "${ghm6}" -lt 100 ]] && ghm6="0${ghm6}" + ghm5="${fhm5}" + [[ "${ghm5}" -lt 100 ]] && ghm5="0${ghm5}" + ghm4="${fhm4}" + [[ "${ghm4}" -lt 100 ]] && ghm4="0${ghm4}" + ghm3="${fhm3}" + [[ "${ghm3}" -lt 100 ]] && ghm3="0${ghm3}" + ghm2="${fhm2}" + [[ "${ghm2}" -lt 100 ]] && ghm2="0${ghm2}" + ghm1="${fhm1}" + [[ "${ghm1}" -lt 100 ]] && ghm1="0${ghm1}" + ghp1="${fhp1}" + [[ "${ghp1}" -lt 100 ]] && ghp1="0${ghp1}" + ghp2="${fhp2}" + [[ "${ghp2}" -lt 100 ]] && ghp2="0${ghp2}" + ghp3="${fhp3}" + [[ "${ghp3}" -lt 100 ]] && ghp3="0${ghp3}" + id=$(date --utc +%Y%m%d%H -d "${valid:0:8} ${valid:8:2} - ${fh} hours") - day=$(echo $id | xargs | cut -c8) - cyc=$(echo $id | xargs | rev | cut -c1-2 | rev) - eval list=\$getlist$fh - if [[ -z "${list}" ]]; then - list=${geslist} - fi - for ges_var in $list;do - # Replace variables in guess with their values - eval ges_val=$ges_var - # Replace the current PDY with the valid date - ges=${ges_val/$PDY\//$day/} - if [[ "${quiet}" == "NO" ]]; then - echo Checking: "${ges}" >&2 - fi - if [[ -r "${ges}" ]]; then - break 2 - fi - done - fh=$((10#${fh}+10#${fhinc})) - if [[ ${fh} -lt 10 ]]; then - fh=0${fh} - fi + day="${id:0:8}" + cyc="${id:8:2}" + list_name="getlist${fh}" + list="${!list_name}" + if [[ -z "${list}" ]]; then + list=${geslist} + fi + for ges_var in ${list}; do + # Replace variables in guess with their values + eval ges_val="${ges_var}" + # Replace the current PDY with the valid date + ges=${ges_val/${PDY}\//${day}/} + if [[ "${quiet}" == "NO" ]]; then + echo Checking: "${ges}" >&2 + fi + if [[ -r "${ges}" ]]; then + break 2 + fi + done + fh=$((10#${fh} + 10#${fhinc})) + if [[ ${fh} -lt 10 ]]; then + fh=0${fh} + fi done -if [[ $fh -gt $fhend ]];then - echo getges.sh: unable to find $netwk.$envir.$typef.$resol.$valid >&2 - exit 8 +if [[ "${fh}" -gt "${fhend}" ]]; then + echo "getges.sh: unable to find ${netwk}.${envir}.${typef}.${resol}.${valid}" >&2 + exit 8 fi +err= #------------------------------------------------------------------------------- # Either copy guess to a file or write guess name to standard output. -if [[ -z "$gfile" ]];then - echo ${ges} - err=$? +if [[ -z "${gfile}" ]]; then + echo "${ges}" + err=0 else - cpfs ${ges} ${gfile} - err=$? + cpfs "${ges}" "${gfile}" + err=$? fi -exit ${err} +exit "${err}" diff --git a/ush/getioda.sh b/ush/getioda.sh index 417f6e4c4d1..f2db4d0a434 100755 --- a/ush/getioda.sh +++ b/ush/getioda.sh @@ -10,20 +10,20 @@ DUMP_SUFFIX=${DUMP_SUFFIX:-""} # Exit if SOURCE_DIR does not exist if [[ ! -s "${SOURCE_DIR}" ]]; then - echo "FATAL ERROR: DUMP SOURCE_DIR=${SOURCE_DIR} does not exist" - exit 99 + echo "FATAL ERROR: DUMP SOURCE_DIR=${SOURCE_DIR} does not exist" + exit 99 fi - + # Create TARGET_DIR if is does not exist if [[ ! -s "${TARGET_DIR}" ]]; then - mkdir -p "${TARGET_DIR}" + mkdir -p "${TARGET_DIR}" fi # Set file prefix prefix="${RUN}.t${HH}z." # loop through top level component directories (e.g. atmos, ocean, land, ice) -for compdir in "${SOURCE_DIR}"/*/ ; do +for compdir in "${SOURCE_DIR}"/*/; do compdir=${compdir%*/} compdir=${compdir##*/} # Skip if not a directory @@ -42,7 +42,7 @@ for compdir in "${SOURCE_DIR}"/*/ ; do set -f # Create component directory in TARGET_DIR if it does not exist if [[ ! -s "${TARGET_DIR}/${compdir}" ]]; then - mkdir -p "${TARGET_DIR}/${compdir}" + mkdir -p "${TARGET_DIR}/${compdir}" fi # Link files from SOURCE_DIR to TARGET_DIR if [[ ! -d "${SOURCE_DIR}/${compdir}" ]]; then @@ -54,11 +54,11 @@ for compdir in "${SOURCE_DIR}"/*/ ; do set +f shopt -s nullglob for source_file in "${SOURCE_DIR}/${compdir}/${prefix}"*; do - if [[ ! -e "${source_file}" ]]; then - continue - fi - targ_file=$(basename "${source_file}") - cpreq "${source_file}" "${TARGET_DIR}/${compdir}/${targ_file}" + if [[ ! -e "${source_file}" ]]; then + continue + fi + targ_file=$(basename "${source_file}") + cpreq "${source_file}" "${TARGET_DIR}/${compdir}/${targ_file}" done shopt -u nullglob set -f diff --git a/ush/gfs_bfr2gpk.sh b/ush/gfs_bfr2gpk.sh index 1e0ea9224aa..4123fe2408d 100755 --- a/ush/gfs_bfr2gpk.sh +++ b/ush/gfs_bfr2gpk.sh @@ -9,7 +9,7 @@ # # # Log: # # K. Brill/HPC 04/12/05 # -######################################################################### +######################################################################### # Set GEMPAK paths. @@ -55,7 +55,7 @@ cpfs "${snd}" "${COMOUT_ATMOS_GEMPAK}/${snd_out}" cpfs "${sfc}" "${COMOUT_ATMOS_GEMPAK}/${sfc_out}" if [[ ${SENDDBN} == "YES" ]]; then - "${DBNROOT}/bin/dbn_alert" MODEL GFS_PTYP_SFC "${job}" "${COMOUT_ATMOS_GEMPAK}/${sfc_out}" - "${DBNROOT}/bin/dbn_alert" MODEL GFS_PTYP_SND "${job}" "${COMOUT_ATMOS_GEMPAK}/${snd_out}" + "${DBNROOT}/bin/dbn_alert" MODEL GFS_PTYP_SFC "${job}" "${COMOUT_ATMOS_GEMPAK}/${sfc_out}" + "${DBNROOT}/bin/dbn_alert" MODEL GFS_PTYP_SND "${job}" "${COMOUT_ATMOS_GEMPAK}/${snd_out}" fi echo "done" > "${DATA}/gembufr.done" diff --git a/ush/gfs_bufr.sh b/ush/gfs_bufr.sh index 63f94493b54..e1b880b9ea3 100755 --- a/ush/gfs_bufr.sh +++ b/ush/gfs_bufr.sh @@ -31,33 +31,33 @@ workdir="${5}" cd "${workdir}" || exit 2 if [[ "${F00FLAG}" == "YES" ]]; then - f00flag=".true." + f00flag=".true." else - f00flag=".false." + f00flag=".false." fi export pgm="gfs_bufr.x" #. prep_step if [[ "${MAKEBUFR}" == "YES" ]]; then - bufrflag=".true." + bufrflag=".true." else - bufrflag=".false." + bufrflag=".false." fi # check if read in bufr_ij_gfs_${CASE}.txt export CASE=${CASE_HIST:-${CASE}} -if [[ -s "${PARMgfs}/product/bufr_ij_gfs_${CASE}.txt" ]]; then - # use predetermined grid point(i,j) in bufr_gfs_${CASE}.txt - ${NLN} "${PARMgfs}/product/bufr_ij_gfs_${CASE}.txt" fort.7 - np1=0 +if [[ -s "${PARMgfs}/product/bufr_ij_gfs_${CASE}.txt" ]]; then + # use predetermined grid point(i,j) in bufr_gfs_${CASE}.txt + ${NLN} "${PARMgfs}/product/bufr_ij_gfs_${CASE}.txt" fort.7 + np1=0 else - # find the nearest neighbor grid point(i,j) in the code - np1=1 - echo "No bufr_ij_gfs_${CASE}.txt For CASE ${CASE}" - echo "Find the nearest neighbor grid (i,j) in the code" + # find the nearest neighbor grid point(i,j) in the code + np1=1 + echo "No bufr_ij_gfs_${CASE}.txt For CASE ${CASE}" + echo "Find the nearest neighbor grid (i,j) in the code" fi ##fformat="netcdf" @@ -81,14 +81,14 @@ EOF filename="${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.log.f${fhr}.${logfm}" if [[ -z ${filename} ]]; then - echo "FATAL ERROR: COULD NOT LOCATE logf${fhr} file" - exit 2 + echo "FATAL ERROR: COULD NOT LOCATE logf${fhr} file" + exit 2 fi filename="${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.log.f${fhr_p}.${logfm}" if [[ -z ${filename} ]]; then - echo "FATAL ERROR: COULD NOT LOCATE logf${fhr_p} file" - exit 2 + echo "FATAL ERROR: COULD NOT LOCATE logf${fhr_p} file" + exit 2 fi #------------------------------------------------------------------ @@ -100,17 +100,16 @@ ${NLN} "${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.sfc.f${fhr_p}.${atmfm}" "flxf${fh ${NLN} "${PARMgfs}/product/bufr_gfs_${CLASS}.tbl" fort.1 ${NLN} "${STNLIST:-${PARMgfs}/product/bufr_stalist.meteo.gfs}" fort.8 - #------------------------------------------------------------------ "${EXECgfs}/${pgm}" < gfsparm > "out_gfs_bufr_${fhr}" export err=$? if [[ ${err} -ne 0 ]]; then - echo "WARNING GFS postsnd job error, Please check files " - echo "${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.atm.f${fhr}.${atmfm}" - echo "${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.sfc.f${fhr}.${atmfm}" - exit "${err}" + echo "FATAL ERROR: GFS postsnd job error, Please check files " + echo "${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.atm.f${fhr}.${atmfm}" + echo "${COMIN_ATMOS_HISTORY}/${RUN}.${cycle}.sfc.f${fhr}.${atmfm}" + err_exit fi exit 0 diff --git a/ush/gfs_bufr_netcdf.sh b/ush/gfs_bufr_netcdf.sh deleted file mode 100755 index 9b905acbaa6..00000000000 --- a/ush/gfs_bufr_netcdf.sh +++ /dev/null @@ -1,103 +0,0 @@ -#! /usr/bin/env bash - -# -# UTILITY SCRIPT NAME : gfsbufr.sh -# AUTHOR : Hua-Lu Pan -# DATE WRITTEN : 02/03/97 -# -# Abstract: This utility script produces BUFR file of -# station forecasts from the GFS suite. -# -# Input: none -# Script History Log: -# 2016-10-30 H Chuang: Tranistion to read nems output. -# Change to read flux file fields in gfs_bufr -# so remove excution of gfs_flux -# 2018-03-22 Guang Ping Lou: Making it works for either 1 hourly or 3 hourly output -# 2018-05-22 Guang Ping Lou: Making it work for both GFS and FV3GFS -# 2018-05-30 Guang Ping Lou: Make sure all files are available. -# 2019-10-10 Guang Ping Lou: Read in NetCDF files -# echo "History: February 2003 - First implementation of this utility script" -# - -if test "$F00FLAG" = "YES" -then - f00flag=".true." -else - f00flag=".false." -fi - -hh=$FSTART -while test $hh -le $FEND -do - hh=$( expr $hh + $FINT ) - if test $hh -lt 10 - then - hh=0$hh - fi -done - -export pgm="gfs_bufr.x" -#. prep_step - -if test "$MAKEBUFR" = "YES" -then - bufrflag=".true." -else - bufrflag=".false." -fi - -CLASS="class1fv3" -cat << EOF > gfsparm - &NAMMET - levs=$LEVS,makebufr=$bufrflag, - dird="$COMOUT/bufr.${cycle}/bufr", - nstart=$FSTART,nend=$FEND,nint=$FINT, - nend1=$NEND1,nint1=$NINT1,nint3=$NINT3, - nsfc=80,f00=$f00flag, -/ -EOF - -hh=$FSTART - if test $hh -lt 100 - then - hh1=$(echo "${hh#"${hh%??}"}") - hh=$hh1 - fi - -sleep_interval=10 -max_tries=360 -while test $hh -le $FEND -do - if test $hh -lt 100 - then - hh2=0$hh - else - hh2=$hh - fi - - filename="${COMIN}/${RUN}.${cycle}.logf${hh2}.txt" - if ! wait_for_file "${filename}" "${sleep_interval}" "${max_tries}" ; then - err_exit "FATAL ERROR COULD NOT LOCATE logf${hh2} file" - fi - -#------------------------------------------------------------------ - ${NLN} $COMIN/${RUN}.${cycle}.atm.f${hh2}.nc sigf${hh} - ${NLN} $COMIN/${RUN}.${cycle}.sfc.f${hh2}.nc flxf${hh} - - hh=$( expr $hh + $FINT ) - if test $hh -lt 10 - then - hh=0$hh - fi -done - -# define input BUFR table file. -${NLN} ${PARMgfs}/product/bufr_gfs_${CLASS}.tbl fort.1 -${NLN} ${STNLIST:-${PARMgfs}/product/bufr_stalist.meteo.gfs} fort.8 -${NLN} ${PARMgfs}/product/bufr_ij13km.txt fort.7 - -${APRUN_POSTSND} "${EXECgfs}/${pgm}" < gfsparm > "out_gfs_bufr_${FEND}" -export err=$? - -exit ${err} diff --git a/ush/gfs_sndp.sh b/ush/gfs_sndp.sh index af09e175dd7..5ebd81c121c 100755 --- a/ush/gfs_sndp.sh +++ b/ush/gfs_sndp.sh @@ -7,55 +7,52 @@ # 1) 2004-09-10 Steve Gilbert First Implementation ################################################################ - # Create "collectives" consisting of groupings of the soundings - # into files designated by geographical region. Each input - # file gfs_collective*.list (1-9) contains the list of stations to - # put in a particular collective output file. +# Create "collectives" consisting of groupings of the soundings +# into files designated by geographical region. Each input +# file gfs_collective*.list (1-9) contains the list of stations to +# put in a particular collective output file. export m=$1 -mkdir $DATA/$m -cd $DATA/$m - cpreq ${FIXgfs}/product/gfs_collective${m}.list $DATA/$m/. - CCCC=KWBC - file_list=gfs_collective${m}.list +mkdir -p "${DATA}/${m}" +cd "${DATA}/${m}" || exit 2 +cpreq "${FIXgfs}/product/gfs_collective${m}.list" "${DATA}/${m}/" +CCCC=KWBC +file_list=gfs_collective${m}.list - if [ $m -le 2 ] - then - WMOHEAD=JUSA4$m - elif [ $m -le 6 ] - then - WMOHEAD=JUSB4$m - else - WMOHEAD=JUSX4$m - fi +if [[ ${m} -le 2 ]]; then + WMOHEAD="JUSA4${m}" +elif [[ ${m} -le 6 ]]; then + WMOHEAD="JUSB4${m}" +else + WMOHEAD="JUSX4${m}" +fi - for stn in $(cat $file_list) - do - cpreq "${COMIN_ATMOS_BUFR}/bufr.${stn}.${PDY}${cyc}" "${DATA}/${m}/bufrin" - export pgm=tocsbufr.x - #. prep_step - export FORT11=$DATA/${m}/bufrin - export FORT51=./bufrout - ${EXECgfs}/${pgm} << EOF +while IFS= read -r stn; do + cpreq "${COMIN_ATMOS_BUFR}/bufr.${stn}.${PDY}${cyc}" "${DATA}/${m}/bufrin" + export pgm=tocsbufr.x + #. prep_step + export FORT11="${DATA}/${m}/bufrin" + export FORT51=./bufrout + "${EXECgfs}/${pgm}" << EOF &INPUT - BULHED="$WMOHEAD",KWBX="$CCCC", + BULHED="${WMOHEAD}",KWBX="${CCCC}", NCEP2STD=.TRUE., SEPARATE=.TRUE., MAXFILESIZE=600000 / EOF - export err=$?; - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR Failed during execution of ${pgm}" - exit "${err}" - fi + export err=$? + if [[ ${err} -ne 0 ]]; then + echo "FATAL ERROR Failed during execution of ${pgm}" + exit "${err}" + fi - cat "${DATA}/${m}/bufrout" >> "${DATA}/${m}/gfs_collective${m}.fil" - rm -f "${DATA}/${m}/bufrin" "${DATA}/${m}/bufrout" - done + cat "${DATA}/${m}/bufrout" >> "${DATA}/${m}/gfs_collective${m}.fil" + rm -f "${DATA}/${m}/bufrin" "${DATA}/${m}/bufrout" +done < "${file_list}" - if [[ ${SENDDBN} == 'YES' ]] ; then - cpfs "${DATA}/${m}/gfs_collective${m}.fil" "${COMOUT_ATMOS_WMO}/gfs_collective${m}.postsnd_${cyc}" - "${DBNROOT}/bin/dbn_alert" NTC_LOW BUFR "${job}" \ - "${COMOUT_ATMOS_WMO}/gfs_collective${m}.postsnd_${cyc}" - fi - cpfs "${DATA}/${m}/gfs_collective${m}.fil" "${COMOUT_ATMOS_BUFR}/." +if [[ "${SENDDBN}" == 'YES' ]]; then + cpfs "${DATA}/${m}/gfs_collective${m}.fil" "${COMOUT_ATMOS_WMO}/gfs_collective${m}.postsnd_${cyc}" + "${DBNROOT}/bin/dbn_alert" NTC_LOW BUFR "${job}" \ + "${COMOUT_ATMOS_WMO}/gfs_collective${m}.postsnd_${cyc}" +fi +cpfs "${DATA}/${m}/gfs_collective${m}.fil" "${COMOUT_ATMOS_BUFR}/." diff --git a/ush/gfs_truncate_enkf.sh b/ush/gfs_truncate_enkf.sh deleted file mode 100755 index 7225b4e5925..00000000000 --- a/ush/gfs_truncate_enkf.sh +++ /dev/null @@ -1,52 +0,0 @@ -#! /usr/bin/env bash - -member=$1 -export SIGINP=$2 -export SIGOUT=$3 -export JCAP=$4 -export LATB=$5 -export LONB=$6 - -DATATMP=$DATA/$member -mkdir -p $DATATMP -cd $DATATMP - -export LEVS=${LEVS_LORES:-64} - -export CHGRESSH=${CHGRESSH:-${USHgfs}/global_chgres.sh} -export CHGRESEXEC=${CHGRESEXEC-${EXECgfs}/global_chgres} -export OROGRAPHY=${OROGRAPHY_LORES:-${FIXgfs}/am/global_orography.t$JCAP.$LONB.$LATB.grb} -export OROGRAPHY_UF=${OROGRAPHY_UF_LORES:-${FIXgfs}/am/global_orography_uf.t$JCAP.$LONB.$LATB.grb} -export LONSPERLAT=${LONSPERLAT_LORES:-${FIXgfs}/am/global_lonsperlat.t${JCAP}.$LONB.$LATB.txt} -export SLMASK=${SLMASK_LORES:-${FIXgfs}/am/global_slmask.t$JCAP.$LONB.$LATB.grb} -export MTNVAR=${MTNVAR_LORES:-${FIXgfs}/am/global_mtnvar.t$JCAP.$LONB.$LATB.f77} -export SIGLEVEL=${SIGLEVEL_LORES:-${FIXgfs}/am/global_hyblev.l${LEVS}.txt} -export O3CLIM=${O3CLIM:-${FIXgfs}/am/global_o3clim.txt} - -use_ufo=.true. - -NTRAC=3 -IALB=0 -idvc_a=2 -idvt=21 -IDSL=1 -IDVM=0 -LATCH=8 -OUTTYP=2 -export CHGRESTHREAD=${CHGRESTHREAD_LORES:-2} -export CHGRESVARS="use_ufo=$use_ufo,IALB=$ialb,ntrac=$NTRAC,idvc=$idvc_a,idvt=$idvt,idsl=$IDSL,IDVM=$IDVM,OUTTYP=$OUTTYP," - -export DATA=$DATATMP - -export APRUNC=${APRUNC:-""} -export VERBOSE=YES - -echo "execute $CHGRESSH for $member" -$CHGRESSH -rc=$? - -export ERR=$rc -export err=$ERR - -exit $err - diff --git a/ush/global_cycle.sh b/ush/global_cycle.sh index 661833898bb..0918e943a11 100755 --- a/ush/global_cycle.sh +++ b/ush/global_cycle.sh @@ -205,9 +205,9 @@ CYCLEXEC=${CYCLEXEC:-${EXECgfs}/global_cycle${XC}} FHOUR=${FHOUR:-00} CRES=${CASE:1} -JCAP_CASE=$((2*CRES-2)) -LONB_CASE=$((4*CRES)) -LATB_CASE=$((2*CRES)) +JCAP_CASE=$((2 * CRES - 2)) +LONB_CASE=$((4 * CRES)) +LATB_CASE=$((2 * CRES)) DELTSFC=${DELTSFC:-0} LSOIL=${LSOIL:-4} @@ -225,10 +225,10 @@ DONST=${DONST:-"NO"} DO_SFCCYCLE=${DO_SFCCYCLE:-.true.} GCYCLE_DO_SOILINCR=${GCYCLE_DO_SOILINCR:-.false.} GCYCLE_DO_SNOWINCR=${GCYCLE_DO_SNOWINCR:-.false.} -if [[ "${GCYCLE_DO_SOILINCR}" == ".true." ]] || [[ "${GCYCLE_DO_SNOWINCR}" == ".true." ]] ; then - DO_LANDINCR=".true." +if [[ "${GCYCLE_DO_SOILINCR}" == ".true." ]] || [[ "${GCYCLE_DO_SNOWINCR}" == ".true." ]]; then + DO_LANDINCR=".true." else - DO_LANDINCR=".false." + DO_LANDINCR=".false." fi GCYCLE_INTERP_LANDINCR=${GCYCLE_INTERP_LANDINCR:-.false.} zsea1=${zsea1:-0} @@ -330,7 +330,6 @@ cat << EOF > fort.36 / EOF - cat << EOF > fort.37 &NAMSFCD NST_FILE="${NST_FILE}", @@ -341,7 +340,7 @@ cat << EOF > fort.37 / EOF -${APRUNCY} "${CYCLEXEC}" 1>"${PGMOUT}" 2>"${PGMERR}" +${APRUNCY} "${CYCLEXEC}" 1> "${PGMOUT}" 2> "${PGMERR}" export err=$? diff --git a/ush/global_savefits.sh b/ush/global_savefits.sh index da62bf6ad9e..b23f1f694db 100755 --- a/ush/global_savefits.sh +++ b/ush/global_savefits.sh @@ -1,5 +1,5 @@ #! /usr/bin/env bash - + ######################################################## # save fit and horiz files for all analysis cycles ######################################################## @@ -10,7 +10,7 @@ export fh1=06 export fh2=00 # #dir=${FIT_DIR}/${EXP} -dir=${FIT_DIR} +dir="${FIT_DIR}" mkdir -p "${dir}" cd "${dir}" || exit 8 cpreq "${COMOUT}/f${fh1}.raob.${PDY}${cyc}" . @@ -24,8 +24,8 @@ cpreq "${COMOUT}/f${fh2}.acft.${PDY}${cyc}" . export typ=anl #dir=${HORZ_DIR}/${EXP}/${typ} -dir=${HORZ_DIR}/${typ} -mkdir -p ${dir} +dir="${HORZ_DIR}/${typ}" +mkdir -p "${dir}" cd "${dir}" || exit 8 cpreq "${COMOUT}/adpupa.mand.${typ}.${PDY}${cyc}" "adpupa.mand.${PDY}${cyc}" cpreq "${COMOUT}/adpsfc.${typ}.${PDY}${cyc}" "adpsfc.${PDY}${cyc}" @@ -36,35 +36,35 @@ cpreq "${COMOUT}/aircft.${typ}.${PDY}${cyc}" "aircft.${PDY}${cyc}" # save fit and horiz files for forecasts verifying at 00Z and 12Z cycles ######################################################################### if [[ "${cyc}" == "00" || "${cyc}" == "12" ]]; then - if [[ "${cyc}" == "00" ]]; then - export fh1=24 - export fh2=48 - fi - if [[ "${cyc}" == "12" ]]; then - export fh1=12 - export fh2=36 - fi - #dir=${FIT_DIR}/${EXP} - dir=${FIT_DIR} - mkdir -p "${dir}" - cd "${dir}" || exit 8 - cpreq "${COMOUT}/f${fh1}.raob.${PDY}${cyc}" . - cpreq "${COMOUT}/f${fh2}.raob.${PDY}${cyc}" . - cpreq "${COMOUT}/f${fh1}.sfc.${PDY}${cyc}" . - cpreq "${COMOUT}/f${fh2}.sfc.${PDY}${cyc}" . - cpreq "${COMOUT}/f${fh1}.acar.${PDY}${cyc}" . - cpreq "${COMOUT}/f${fh2}.acar.${PDY}${cyc}" . - cpreq "${COMOUT}/f${fh1}.acft.${PDY}${cyc}" . - cpreq "${COMOUT}/f${fh2}.acft.${PDY}${cyc}" . - export typ=fcs - #dir=${HORZ_DIR}/${EXP}/${typ} - dir=${HORZ_DIR}/${typ} - mkdir -p "${dir}" - cd "${dir}" || exit 8 - cpreq "${COMOUT}/adpupa.mand.${typ}.${PDY}${cyc}" "adpupa.mand.${PDY}${cyc}" - cpreq "${COMOUT}/adpsfc.${typ}.${PDY}${cyc}" "adpsfc.${PDY}${cyc}" - cpreq "${COMOUT}/sfcshp.${typ}.${PDY}${cyc}" "sfcshp.${PDY}${cyc}" - cpreq "${COMOUT}/aircar.${typ}.${PDY}${cyc}" "aircar.${PDY}${cyc}" - cpreq "${COMOUT}/aircft.${typ}.${PDY}${cyc}" "aircft.${PDY}${cyc}" + if [[ "${cyc}" == "00" ]]; then + export fh1=24 + export fh2=48 + fi + if [[ "${cyc}" == "12" ]]; then + export fh1=12 + export fh2=36 + fi + #dir=${FIT_DIR}/${EXP} + dir="${FIT_DIR}" + mkdir -p "${dir}" + cd "${dir}" || exit 8 + cpreq "${COMOUT}/f${fh1}.raob.${PDY}${cyc}" . + cpreq "${COMOUT}/f${fh2}.raob.${PDY}${cyc}" . + cpreq "${COMOUT}/f${fh1}.sfc.${PDY}${cyc}" . + cpreq "${COMOUT}/f${fh2}.sfc.${PDY}${cyc}" . + cpreq "${COMOUT}/f${fh1}.acar.${PDY}${cyc}" . + cpreq "${COMOUT}/f${fh2}.acar.${PDY}${cyc}" . + cpreq "${COMOUT}/f${fh1}.acft.${PDY}${cyc}" . + cpreq "${COMOUT}/f${fh2}.acft.${PDY}${cyc}" . + export typ=fcs + #dir=${HORZ_DIR}/${EXP}/${typ} + dir="${HORZ_DIR}/${typ}" + mkdir -p "${dir}" + cd "${dir}" || exit 8 + cpreq "${COMOUT}/adpupa.mand.${typ}.${PDY}${cyc}" "adpupa.mand.${PDY}${cyc}" + cpreq "${COMOUT}/adpsfc.${typ}.${PDY}${cyc}" "adpsfc.${PDY}${cyc}" + cpreq "${COMOUT}/sfcshp.${typ}.${PDY}${cyc}" "sfcshp.${PDY}${cyc}" + cpreq "${COMOUT}/aircar.${typ}.${PDY}${cyc}" "aircar.${PDY}${cyc}" + cpreq "${COMOUT}/aircft.${typ}.${PDY}${cyc}" "aircft.${PDY}${cyc}" fi ######################################################################### diff --git a/ush/interp_atmos_master.sh b/ush/interp_atmos_master.sh index 00bbde65043..b43b05c889b 100755 --- a/ush/interp_atmos_master.sh +++ b/ush/interp_atmos_master.sh @@ -4,9 +4,9 @@ # Generate 0.25 / 0.5 / 1 degree interpolated grib2 files for each input grib2 file # trim's RH and tweaks sea-ice cover -input_file=${1:-"pgb2file_in"} # Input pressure grib2 file -output_file_prefix=${2:-"pgb2file_out"} # Prefix for output grib2 file; the prefix is appended by resolution e.g. _0p25 -grid_string=${3:-"0p25"} # Target grids; e.g. "0p25" or "0p25:0p50"; If multiple, they need to be ":" seperated +input_file=${1:-"pgb2file_in"} # Input pressure grib2 file +output_file_prefix=${2:-"pgb2file_out"} # Prefix for output grib2 file; the prefix is appended by resolution e.g. _0p25 +grid_string=${3:-"0p25"} # Target grids; e.g. "0p25" or "0p25:0p50"; If multiple, they need to be ":" seperated # wgrib2 options for regridding defaults="-set_grib_type same -set_bitmap 1 -set_grib_max_bits 16" @@ -32,42 +32,42 @@ IFS=':' read -ra grids <<< "${grid_string}" output_grids="" for grid in "${grids[@]}"; do - gridopt="grid${grid}" - output_grids="${output_grids} -new_grid ${!gridopt} ${output_file_prefix}_${grid}" + gridopt="grid${grid}" + output_grids="${output_grids} -new_grid ${!gridopt} ${output_file_prefix}_${grid}" done #shellcheck disable=SC2086 ${WGRIB2} "${input_file}" ${defaults} \ - ${interp_winds} \ - ${interp_bilinear} \ - ${interp_neighbor} \ - ${interp_budget} \ - ${increased_bits} \ - ${output_grids} + ${interp_winds} \ + ${interp_bilinear} \ + ${interp_neighbor} \ + ${interp_budget} \ + ${increased_bits} \ + ${output_grids} export err=$? if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: WGRIB2 failed to generate interpolated grib2 file!" - exit "${err}" + echo "FATAL ERROR: WGRIB2 failed to generate interpolated grib2 file!" + exit "${err}" fi # trim and mask for all grids for grid in "${grids[@]}"; do - trim_rh "${output_file_prefix}_${grid}" - export err=$? - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: Failed during the execution of trim_rh" - exit "${err}" - fi - # shellcheck disable=SC2312 - var_count=$(${WGRIB2} "${output_file_prefix}_${grid}" -match "LAND|ICEC" |wc -l) - if [[ "${var_count}" -eq 2 ]]; then - mod_icec "${output_file_prefix}_${grid}" + trim_rh "${output_file_prefix}_${grid}" export err=$? if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: Failed during execution of mod_icec" - exit "${err}" + echo "FATAL ERROR: Failed during the execution of trim_rh" + exit "${err}" + fi + # shellcheck disable=SC2312 + var_count=$(${WGRIB2} "${output_file_prefix}_${grid}" -match "LAND|ICEC" | wc -l) + if [[ "${var_count}" -eq 2 ]]; then + mod_icec "${output_file_prefix}_${grid}" + export err=$? + if [[ ${err} -ne 0 ]]; then + echo "FATAL ERROR: Failed during execution of mod_icec" + exit "${err}" + fi fi - fi done exit 0 diff --git a/ush/interp_atmos_sflux.sh b/ush/interp_atmos_sflux.sh index 2aff2cc58aa..859691cdf73 100755 --- a/ush/interp_atmos_sflux.sh +++ b/ush/interp_atmos_sflux.sh @@ -3,9 +3,9 @@ # This script takes in a master flux file and creates interpolated flux files at various interpolated resolutions # Generate 0.25 / 0.5 / 1 degree interpolated grib2 flux files for each input sflux grib2 file -input_file=${1:-"sfluxfile_in"} # Input sflux grib2 file -output_file_prefix=${2:-"sfluxfile_out"} # Prefix for output sflux grib2 file; the prefix is appended by resolution e.g. _0p25 -grid_string=${3:-"1p00"} # Target grids; e.g. "0p25" or "0p25:0p50"; If multiple, they need to be ":" seperated +input_file=${1:-"sfluxfile_in"} # Input sflux grib2 file +output_file_prefix=${2:-"sfluxfile_out"} # Prefix for output sflux grib2 file; the prefix is appended by resolution e.g. _0p25 +grid_string=${3:-"1p00"} # Target grids; e.g. "0p25" or "0p25:0p50"; If multiple, they need to be ":" seperated # wgrib2 options for regridding defaults="-set_grib_type same -set_bitmap 1 -set_grib_max_bits 16" @@ -28,22 +28,22 @@ IFS=':' read -ra grids <<< "${grid_string}" output_grids="" for grid in "${grids[@]}"; do - gridopt="grid${grid}" - output_grids="${output_grids} -new_grid ${!gridopt} ${output_file_prefix}_${grid}" + gridopt="grid${grid}" + output_grids="${output_grids} -new_grid ${!gridopt} ${output_file_prefix}_${grid}" done #shellcheck disable=SC2086 ${WGRIB2} "${input_file}" ${defaults} \ - ${interp_winds} \ - ${interp_bilinear} \ - ${interp_neighbor} \ - ${interp_budget} \ - ${increased_bits} \ - ${output_grids} + ${interp_winds} \ + ${interp_bilinear} \ + ${interp_neighbor} \ + ${interp_budget} \ + ${increased_bits} \ + ${output_grids} export err=$? if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: WGRIB2 failed to interpolate surface flux parameters to a new grib2 file" - exit "${err}" + echo "FATAL ERROR: WGRIB2 failed to interpolate surface flux parameters to a new grib2 file" + exit "${err}" fi exit 0 diff --git a/ush/jjob_header.sh b/ush/jjob_header.sh index 5de17f73a49..f69524b732a 100755 --- a/ush/jjob_header.sh +++ b/ush/jjob_header.sh @@ -46,8 +46,8 @@ source "${HOMEgfs}/ush/preamble.sh" OPTIND=1 while getopts "c:e:" option; do case "${option}" in - c) read -ra configs <<< "${OPTARG}" ;; - e) env_job=${OPTARG} ;; + c) read -ra configs <<< "${OPTARG}" ;; + e) env_job=${OPTARG} ;; :) export err=1 err_exit "[${BASH_SOURCE[0]}]: ${option} requires an argument" @@ -58,7 +58,7 @@ while getopts "c:e:" option; do ;; esac done -shift $((OPTIND-1)) +shift $((OPTIND - 1)) if [[ -z ${env_job} ]]; then export err=1 @@ -74,11 +74,10 @@ if [[ ${WIPE_DATA:-YES} == "YES" ]]; then fi mkdir -p "${DATA}" if ! cd "${DATA}"; then - export err=1 - err_exit "[${BASH_SOURCE[0]}]: ${DATA} does not exist" + export err=1 + err_exit "[${BASH_SOURCE[0]}]: ${DATA} does not exist" fi - ############################################## # Determine Job Output Name on System ############################################## @@ -89,7 +88,6 @@ export pgmerr=errfile # Needs to be set for err_chk/err_exit export pgm=${pgm:-} - ############################################## # Run setpdy and initialize PDY variables ############################################## @@ -97,7 +95,6 @@ export cycle="t${cyc}z" setpdy.sh || true source ./PDY || true - ############################# # Source relevant config files ############################# @@ -106,16 +103,15 @@ for config in "${configs[@]:-''}"; do source "${EXPDIR}/config.${config}" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "[${BASH_SOURCE[0]}]: Unable to load config config.${config}" + err_exit "[${BASH_SOURCE[0]}]: Unable to load config config.${config}" fi done - ########################################## # Source machine runtime environment ########################################## source "${HOMEgfs}/env/${machine}.env" "${env_job}" && true export err=$? if [[ ${err} -ne 0 ]]; then - err_exit "[${BASH_SOURCE[0]}]: Error while sourcing machine environment ${machine}.env for job ${env_job}" + err_exit "[${BASH_SOURCE[0]}]: Error while sourcing machine environment ${machine}.env for job ${env_job}" fi diff --git a/ush/link_crtm_fix.sh b/ush/link_crtm_fix.sh index 7a3654b8405..9f0d583b94f 100755 --- a/ush/link_crtm_fix.sh +++ b/ush/link_crtm_fix.sh @@ -6,30 +6,30 @@ # 3. Nowhere. Give up. Whine. CRTM_FIX="${1:-${CRTM_FIX:-MISSING}}" -if [[ "${CRTM_FIX}" == "MISSING" ]] ; then - echo "Please specify CRTM fix location. Giving up." 1>&2 - exit 19 +if [[ "${CRTM_FIX}" == "MISSING" ]]; then + echo "Please specify CRTM fix location. Giving up." 1>&2 + exit 19 fi -if [[ ! -d "${CRTM_FIX}" ]] ; then - echo "${CRTM_FIX}: \${CRTM_FIX} is not a directory. Giving up." 1>&2 - exit 38 +if [[ ! -d "${CRTM_FIX}" ]]; then + echo "${CRTM_FIX}: \${CRTM_FIX} is not a directory. Giving up." 1>&2 + exit 38 fi for what in "amsre_aqua" "imgr_g11" "imgr_g12" "imgr_g13" \ - "imgr_g15" "imgr_mt1r" "imgr_mt2" "seviri_m10" \ - "ssmi_f13" "ssmi_f14" "ssmi_f15" "ssmis_f16" \ - "ssmis_f17" "ssmis_f18" "ssmis_f19" "ssmis_f20" \ - "tmi_trmm" "v.seviri_m10" "imgr_insat3d" "abi_gr" "ahi_himawari8" ; do - ${NLN} "${CRTM_FIX}/${what}.TauCoeff.bin" "${what}.TauCoeff.bin" - ${NLN} "${CRTM_FIX}/${what}.SpcCoeff.bin" "${what}.SpcCoeff.bin" + "imgr_g15" "imgr_mt1r" "imgr_mt2" "seviri_m10" \ + "ssmi_f13" "ssmi_f14" "ssmi_f15" "ssmis_f16" \ + "ssmis_f17" "ssmis_f18" "ssmis_f19" "ssmis_f20" \ + "tmi_trmm" "v.seviri_m10" "imgr_insat3d" "abi_gr" "ahi_himawari8"; do + ${NLN} "${CRTM_FIX}/${what}.TauCoeff.bin" "${what}.TauCoeff.bin" + ${NLN} "${CRTM_FIX}/${what}.SpcCoeff.bin" "${what}.SpcCoeff.bin" done -for what in 'Aerosol' 'Cloud' ; do - ${NLN} "${CRTM_FIX}/${what}Coeff.bin" "${what}Coeff.bin" +for what in 'Aerosol' 'Cloud'; do + ${NLN} "${CRTM_FIX}/${what}Coeff.bin" "${what}Coeff.bin" done -for what in "${CRTM_FIX}/"*Emis* ; do - ${NLN} "${what}" "$(basename "${what}")" +for what in "${CRTM_FIX}/"*Emis*; do + ${NLN} "${what}" "$(basename "${what}")" done exit 0 diff --git a/ush/make_tif.sh b/ush/make_tif.sh index b5adfdc6f3b..70987cf51ec 100755 --- a/ush/make_tif.sh +++ b/ush/make_tif.sh @@ -15,15 +15,15 @@ ORIG=KWBC PDYHH="${PDY}${cyc}" if [[ "${HEADER}" == "YES" ]]; then - INPATH="${DATA}/${outname}" - SUB=DFAX1064 - "${HOMEgfs}/ush/make_NTC_file.pl" "${WMO}" "${ORIG}" "${PDYHH}" "${SUB}" "${INPATH}" "${OUTPATH}" -# -# Send the graphic to TOC + INPATH="${DATA}/${outname}" + SUB=DFAX1064 + "${HOMEgfs}/ush/make_NTC_file.pl" "${WMO}" "${ORIG}" "${PDYHH}" "${SUB}" "${INPATH}" "${OUTPATH}" + # + # Send the graphic to TOC - cpfs "${OUTPATH}" "${COMOUT_ATMOS_WMO}/gfs_500_hgt_tmp_nh_anl_${cyc}.tif" - if [[ "${SENDDBN}" == "YES" ]]; then + cpfs "${OUTPATH}" "${COMOUT_ATMOS_WMO}/gfs_500_hgt_tmp_nh_anl_${cyc}.tif" + if [[ "${SENDDBN}" == "YES" ]]; then - "${DBNROOT}/bin/dbn_alert" GRIB_LOW "${NET}" "${job}" "${COMOUT_ATMOS_WMO}/gfs_500_hgt_tmp_nh_anl_${cyc}.tif" - fi + "${DBNROOT}/bin/dbn_alert" GRIB_LOW "${NET}" "${job}" "${COMOUT_ATMOS_WMO}/gfs_500_hgt_tmp_nh_anl_${cyc}.tif" + fi fi diff --git a/ush/module-setup.sh b/ush/module-setup.sh index 4065c67e4cd..13e41879804 100755 --- a/ush/module-setup.sh +++ b/ush/module-setup.sh @@ -3,9 +3,9 @@ set -u source "${HOMEgfs}/ush/detect_machine.sh" -if [[ ${MACHINE_ID} = hera* ]] ; then +if [[ ${MACHINE_ID} = hera* ]]; then # We are on NOAA Hera - if ( ! eval module help > /dev/null 2>&1 ) ; then + if (! eval module help > /dev/null 2>&1); then source /apps/lmod/lmod/init/bash fi export LMOD_SYSTEM_DEFAULT_MODULES=contrib @@ -13,9 +13,9 @@ if [[ ${MACHINE_ID} = hera* ]] ; then module reset set -u -elif [[ ${MACHINE_ID} = ursa* ]] ; then +elif [[ ${MACHINE_ID} = ursa* ]]; then # We are on NOAA Ursa - if ( ! eval module help > /dev/null 2>&1 ) ; then + if (! eval module help > /dev/null 2>&1); then source /apps/lmod/lmod/init/bash fi export LMOD_SYSTEM_DEFAULT_MODULES=lmod @@ -23,9 +23,9 @@ elif [[ ${MACHINE_ID} = ursa* ]] ; then module reset set -u -elif [[ ${MACHINE_ID} = hercules* ]] ; then +elif [[ ${MACHINE_ID} = hercules* ]]; then # We are on Hercules - if ( ! eval module help > /dev/null 2>&1 ) ; then + if (! eval module help > /dev/null 2>&1); then source /apps/other/lmod/lmod/init/bash fi export LMOD_SYSTEM_DEFAULT_MODULES=contrib @@ -33,9 +33,9 @@ elif [[ ${MACHINE_ID} = hercules* ]] ; then module reset set -u -elif [[ ${MACHINE_ID} = orion* ]] ; then +elif [[ ${MACHINE_ID} = orion* ]]; then # We are on Orion - if ( ! eval module help > /dev/null 2>&1 ) ; then + if (! eval module help > /dev/null 2>&1); then source /apps/lmod/lmod/init/bash fi #export LMOD_SYSTEM_DEFAULT_MODULES=git/2.28.0 # contrib has a lot of stuff we shouldn't put in MODULEPATH @@ -43,30 +43,29 @@ elif [[ ${MACHINE_ID} = orion* ]] ; then module purge # reset causes issues on Orion sometimes. #set -u - elif [[ ${MACHINE_ID} = wcoss2 ]]; then # We are on WCOSS2 # Ignore default modules of the same version lower in the search path (req'd by spack-stack) #export LMOD_TMOD_FIND_FIRST=yes #TODO: Uncomment this when using spack-stack for the entire workflow module reset -elif [[ ${MACHINE_ID} = cheyenne* ]] ; then +elif [[ ${MACHINE_ID} = cheyenne* ]]; then # We are on NCAR Cheyenne - if ( ! eval module help > /dev/null 2>&1 ) ; then + if (! eval module help > /dev/null 2>&1); then source /glade/u/apps/ch/modulefiles/default/localinit/localinit.sh fi module purge -elif [[ ${MACHINE_ID} = stampede* ]] ; then +elif [[ ${MACHINE_ID} = stampede* ]]; then # We are on TACC Stampede - if ( ! eval module help > /dev/null 2>&1 ) ; then + if (! eval module help > /dev/null 2>&1); then source /opt/apps/lmod/lmod/init/bash fi module purge -elif [[ ${MACHINE_ID} = gaeac5 ]] ; then +elif [[ ${MACHINE_ID} = gaeac5 ]]; then # We are on GAEA C5. - if ( ! eval module help > /dev/null 2>&1 ) ; then + if (! eval module help > /dev/null 2>&1); then # We cannot simply load the module command. The GAEA # /etc/profile modifies a number of module-related variables # before loading the module command. Without those variables, @@ -77,14 +76,14 @@ elif [[ ${MACHINE_ID} = gaeac5 ]] ; then module reset elif [[ ${MACHINE_ID} = gaeac6 ]]; then # We are on GAEA C6. - if ( ! eval module help > /dev/null 2>&1 ) ; then + if (! eval module help > /dev/null 2>&1); then source /opt/cray/pe/lmod/lmod/init/bash fi module reset elif [[ ${MACHINE_ID} = expanse* ]]; then # We are on SDSC Expanse - if ( ! eval module help > /dev/null 2>&1 ) ; then + if (! eval module help > /dev/null 2>&1); then source /etc/profile.d/modules.sh fi module purge @@ -109,7 +108,7 @@ fi # If this function exists in the environment, run it; else do not ftype=$(type -t set_strict || echo "") if [[ "${ftype}" == "function" ]]; then - set_strict + set_strict else - set +u + set +u fi diff --git a/ush/month_name.sh b/ush/month_name.sh index 02af45149d7..c84133356a5 100755 --- a/ush/month_name.sh +++ b/ush/month_name.sh @@ -5,7 +5,7 @@ # SCRIPT: month_name.sh # # This script returns the name/abreviation of a month -# in a small text file, month_name.txt. It also echos the +# in a small text file, month_name.txt. It also echos the # name/abreviation to stdout. The form of the returned # name/abreviation is specified by the script arguments. # @@ -17,7 +17,7 @@ # ----------- ------ ---------------------------- # # 6/06 Mon Jun -# 8/08 Month August +# 8/08 Month August # 9/09 MON SEP # 11 MONTH NOVEMBER # @@ -26,7 +26,7 @@ # by either of the following methods: # # MM=`cat month_name.txt` after executing month_name.sh -# - OR - +# - OR - # MM=`month_name.sh 5 MON` (for example) # # @@ -36,77 +36,100 @@ # #################################################################### - typeset -Z2 month_num - - - month_num=$1 - month_spec=$2 - - case ${month_num} in - - 01) Mon=Jan - Month=January ;; - - 02) Mon=Feb - Month=February ;; - - 03) Mon=Mar - Month=March ;; - - 04) Mon=Apr - Month=April ;; - - 05) Mon=May - Month=May ;; - - 06) Mon=Jun - Month=June ;; - - 07) Mon=Jul - Month=July ;; - - 08) Mon=Aug - Month=August ;; - - 09) Mon=Sep - Month=September ;; - - 10) Mon=Oct - Month=October ;; - - 11) Mon=Nov - Month=November ;; - - 12) Mon=Dec - Month=December ;; +typeset -Z2 month_num + +month_num=$1 +month_spec=$2 + +case ${month_num} in + + 01) + Mon=Jan + Month=January + ;; + + 02) + Mon=Feb + Month=February + ;; + + 03) + Mon=Mar + Month=March + ;; + + 04) + Mon=Apr + Month=April + ;; + + 05) + Mon=May + Month=May + ;; + + 06) + Mon=Jun + Month=June + ;; + + 07) + Mon=Jul + Month=July + ;; + + 08) + Mon=Aug + Month=August + ;; + + 09) + Mon=Sep + Month=September + ;; + + 10) + Mon=Oct + Month=October + ;; + + 11) + Mon=Nov + Month=November + ;; + + 12) + Mon=Dec + Month=December + ;; *) echo "FATAL ERROR input month number (${month_num}) is invalid" exit 2 + ;; - esac - +esac - if [[ "${month_spec}" == "Mon" ]]; then +if [[ "${month_spec}" == "Mon" ]]; then echo "${Mon}" echo "${Mon}" > month_name.txt - elif [[ "${month_spec}" == "Month" ]]; then +elif [[ "${month_spec}" == "Month" ]]; then echo "${Month}" echo "${Month}" > month_name.txt - elif [[ "${month_spec}" == "MON" ]]; then +elif [[ "${month_spec}" == "MON" ]]; then MON="${Mon^^}" echo "${MON}" echo "${MON}" > month_name.txt - elif [[ "${month_spec}" == "MONTH" ]]; then +elif [[ "${month_spec}" == "MONTH" ]]; then MONTH="${Month^^}" echo "${MONTH}" echo "${MONTH}" > month_name.txt - fi +fi diff --git a/ush/ocnice_extractvars.sh b/ush/ocnice_extractvars.sh index 96f6558d07b..2e6eb0237ea 100755 --- a/ush/ocnice_extractvars.sh +++ b/ush/ocnice_extractvars.sh @@ -18,69 +18,69 @@ fhout_ocnice=${5} comout_rfcst_prod_ocnice=${6} if [[ ! -d "${subdata}" ]]; then - mkdir -p "${subdata}" + mkdir -p "${subdata}" fi -for (( nh = FHMIN_GFS + fhout_ocnice; nh <= FHMAX_GFS; nh = nh + fhout_ocnice )); do - fnh=$(printf "%3.3d" "${nh}") +for ((nh = FHMIN_GFS + fhout_ocnice; nh <= FHMAX_GFS; nh = nh + fhout_ocnice)); do + fnh=$(printf "%3.3d" "${nh}") - if [[ ${component_name} == "ocn" ]]; then - if [[ "${datares}" == "native" ]]; then - com_dir=${COMIN_OCEAN_HISTORY} - infile="${com_dir}/${RUN}.ocean.t${cyc}z.${fhout_ocnice}hr_avg.f${fnh}.nc" - new_infile=${subdata}/${RUN}.ocean.t${cyc}z.${fhout_ocnice}hr_avg.f${fnh}_ext.nc - else - com_dir=${COMIN_OCEAN_NETCDF} - infile="${com_dir}/${datares}/${RUN}.ocean.t${cyc}z.${datares}.f${fnh}.nc" - new_infile=${subdata}/${RUN}.ocean.t${cyc}z.${datares}.f${fnh}_ext.nc - fi - # For ocean products, add an argument to extract a subset of levels - otherargs=(-d "${depthvar_name},""${zmin},""${zmax}") - elif [[ ${component_name} == "ice" ]]; then - if [[ "${datares}" == "native" ]]; then - com_dir=${COMIN_ICE_HISTORY} - infile="${com_dir}/${RUN}.ice.t${cyc}z.${fhout_ocnice}hr_avg.f${fnh}.nc" - new_infile=${subdata}/${RUN}.ice.t${cyc}z.${fhout_ocnice}hr_avg.f${fnh}_ext.nc - else - com_dir=${COMIN_ICE_NETCDF} - infile="${com_dir}/${datares}/${RUN}.ice.t${cyc}z.${datares}.f${fnh}.nc" - new_infile=${subdata}/${RUN}.ice.t${cyc}z.${datares}.f${fnh}_ext.nc + if [[ ${component_name} == "ocn" ]]; then + if [[ "${datares}" == "native" ]]; then + com_dir=${COMIN_OCEAN_HISTORY} + infile="${com_dir}/${RUN}.ocean.t${cyc}z.${fhout_ocnice}hr_avg.f${fnh}.nc" + new_infile=${subdata}/${RUN}.ocean.t${cyc}z.${fhout_ocnice}hr_avg.f${fnh}_ext.nc + else + com_dir=${COMIN_OCEAN_NETCDF} + infile="${com_dir}/${datares}/${RUN}.ocean.t${cyc}z.${datares}.f${fnh}.nc" + new_infile=${subdata}/${RUN}.ocean.t${cyc}z.${datares}.f${fnh}_ext.nc + fi + # For ocean products, add an argument to extract a subset of levels + otherargs=(-d "${depthvar_name},""${zmin},""${zmax}") + elif [[ ${component_name} == "ice" ]]; then + if [[ "${datares}" == "native" ]]; then + com_dir=${COMIN_ICE_HISTORY} + infile="${com_dir}/${RUN}.ice.t${cyc}z.${fhout_ocnice}hr_avg.f${fnh}.nc" + new_infile=${subdata}/${RUN}.ice.t${cyc}z.${fhout_ocnice}hr_avg.f${fnh}_ext.nc + else + com_dir=${COMIN_ICE_NETCDF} + infile="${com_dir}/${datares}/${RUN}.ice.t${cyc}z.${datares}.f${fnh}.nc" + new_infile=${subdata}/${RUN}.ice.t${cyc}z.${datares}.f${fnh}_ext.nc + fi + otherargs=() fi - otherargs=() - fi - outfile=${subdata}/${RUN}.${component_name}.t${cyc}z.${datares}.f${fnh}.nc + outfile=${subdata}/${RUN}.${component_name}.t${cyc}z.${datares}.f${fnh}.nc - if [[ -f "${infile}" ]]; then #check if input file exists before extraction - if ! cpfs "${infile}" "${new_infile}"; then - echo "FATAL ERROR: Failed to copy ${infile} to ${new_infile}." - exit 1 - fi - varsrequested=$(paste -s "${varlist}") - varsinfile=$(cdo -showname "${new_infile}") - varsavailable="" - for i in ${varsrequested}; do - # Check if variable from parm file is available in netcdf file. If variable is not in netcdf file, do not try to extract that variable. - if [[ ${varsinfile} == *"${i}"* ]]; then - varsavailable+="${i}," - else - echo "WARNING: ${i} is not available in ${new_infile}." - fi - done - if [[ -z "${varsavailable}" ]]; then - echo "WARNING: No variables from parm file ${varlist} are available in netcdf file ${new_infile}." - else - ocnice_vars=${varsavailable::-1} - ncks -v "${ocnice_vars}" "${otherargs[@]}" "${new_infile}" "${outfile}" - fi - if [[ ${datacompress} -eq 1 ]]; then - ${COMPRSCMD} "${outfile}" - copy_to_comout "${outfile}.bz2" "${comout_rfcst_prod_ocnice}" + if [[ -f "${infile}" ]]; then #check if input file exists before extraction + if ! cpfs "${infile}" "${new_infile}"; then + echo "FATAL ERROR: Failed to copy ${infile} to ${new_infile}." + exit 1 + fi + varsrequested=$(paste -s "${varlist}") + varsinfile=$(cdo -showname "${new_infile}") + varsavailable="" + for i in ${varsrequested}; do + # Check if variable from parm file is available in netcdf file. If variable is not in netcdf file, do not try to extract that variable. + if [[ ${varsinfile} == *"${i}"* ]]; then + varsavailable+="${i}," + else + echo "WARNING: ${i} is not available in ${new_infile}." + fi + done + if [[ -z "${varsavailable}" ]]; then + echo "WARNING: No variables from parm file ${varlist} are available in netcdf file ${new_infile}." + else + ocnice_vars=${varsavailable::-1} + ncks -v "${ocnice_vars}" "${otherargs[@]}" "${new_infile}" "${outfile}" + fi + if [[ ${datacompress} -eq 1 ]]; then + ${COMPRSCMD} "${outfile}" + copy_to_comout "${outfile}.bz2" "${comout_rfcst_prod_ocnice}" + else + copy_to_comout "${outfile}" "${comout_rfcst_prod_ocnice}" + fi else - copy_to_comout "${outfile}" "${comout_rfcst_prod_ocnice}" + echo "WARNING: ${infile} does not exist in ${com_dir}." fi - else - echo "WARNING: ${infile} does not exist in ${com_dir}." - fi done # nh exit 0 diff --git a/ush/ozn_xtrct.sh b/ush/ozn_xtrct.sh index a84c00f45b7..d45674bdb12 100755 --- a/ush/ozn_xtrct.sh +++ b/ush/ozn_xtrct.sh @@ -5,16 +5,16 @@ # # This script performs the data extraction from the oznstat # diagnostic files. The resulting data (*.ieee_d) files, GrADS -# control files and stdout files will be moved to the +# control files and stdout files will be moved to the # $TANKverf_ozn. # -# Calling scripts must define: +# Calling scripts must define: # $TANKverf_ozn # $PDY # $cyc # -# Return values are -# 0 = normal +# Return values are +# 0 = normal # 2 = unable to generate satype list; may indicate no diag # files found in oznstat file #------------------------------------------------------------------ @@ -22,33 +22,32 @@ #-------------------------------------------------- # check_diag_files # -# Compare $satype (which contains the contents of +# Compare $satype (which contains the contents of # gdas_oznmon_satype.txt to $avail_satype which is # determined by the contents of the oznstat file. # Report any missing diag files in a file named # bad_diag.$PDY$cyc # check_diag_files() { - pdate=$1 - found_satype=$2 - avail_satype=$3 + pdate=$1 + found_satype=$2 + avail_satype=$3 - out_file="bad_diag.${pdate}" + out_file="bad_diag.${pdate}" - printf "\n\n--> check_diag_files\n" + printf "\n\n--> check_diag_files\n" - for type in ${found_satype}; do - len_check=$(echo "${avail_satype}" | grep "${type}" | wc -c) + for type in ${found_satype}; do + if ! grep -q "${type}" <<< "${avail_satype}"; then + echo "missing diag file -- diag_${type}_ges.${pdate}.gz not found" >> "./${out_file}" + fi + done - if [[ ${len_check} -le 1 ]]; then - echo "missing diag file -- diag_${type}_ges.${pdate}.gz not found" >> "./${out_file}" - fi - done - - echo "<-- check_diag_files"; echo ""; echo "" + echo "<-- check_diag_files" + echo "" + echo "" } - iret=0 VALIDATE_DATA=${VALIDATE_DATA:-0} nregion=${nregion:-6} @@ -56,13 +55,13 @@ DO_DATA_RPT=${DO_DATA_RPT:-0} netcdf_boolean=".false." if [[ ${OZNMON_NETCDF} -eq 1 ]]; then - netcdf_boolean=".true." + netcdf_boolean=".true." fi OZNMON_NEW_HDR=${OZNMON_NEW_HDR:-0} new_hdr="F" if [[ ${OZNMON_NEW_HDR} -eq 1 ]]; then - new_hdr="T" + new_hdr="T" fi #------------------------------------------------------------------ @@ -70,28 +69,25 @@ fi # validate=".FALSE." if [[ ${VALIDATE_DATA} -eq 1 ]]; then - if [[ ! -e ${ozn_val_file} && ! -h ${ozn_val_file} ]]; then - echo "WARNING: VALIDATE_DATA set to 1, but unable to locate ${ozn_val_file}" - echo " Setting VALIDATE_DATA to 0/OFF" - VALIDATE_DATA=0 - else - validate=".TRUE." - val_file=$(basename "${ozn_val_file}") - cpreq "${ozn_val_file}" "${val_file}" - tar -xvf "${val_file}" - fi + if [[ ! -e ${ozn_val_file} && ! -L ${ozn_val_file} ]]; then + echo "WARNING: VALIDATE_DATA set to 1, but unable to locate ${ozn_val_file}" + echo " Setting VALIDATE_DATA to 0/OFF" + VALIDATE_DATA=0 + else + validate=".TRUE." + val_file=$(basename "${ozn_val_file}") + cpreq "${ozn_val_file}" "${val_file}" + tar -xvf "${val_file}" + fi fi echo "VALIDATE_DATA, validate = ${VALIDATE_DATA}, ${validate} " - - #------------------------------------------------------------------ -# ozn_ptype here is the processing type which is intended to be "ges" +# ozn_ptype here is the processing type which is intended to be "ges" # or "anl". Default is "ges". # ozn_ptype=${ozn_ptype:-"ges anl"} - #--------------------------------------------------------------------------- # Build satype list from the available diag files. # @@ -99,58 +95,63 @@ ozn_ptype=${ozn_ptype:-"ges anl"} # a problem, reported by an iret value of 2 # -avail_satype=$(ls -1 d*ges* | sed -e 's/_/ /g;s/\./ /' | gawk '{ print $2 "_" $3 }') +declare -a avail_satype +ges_file_pattern='(diag_)(.*)(_ges)' +for ges_file in *; do + if [[ "${ges_file}" =~ ${ges_file_pattern} ]]; then + avail_satype+=("${BASH_REMATCH[2]}") + fi +done if [[ ${DO_DATA_RPT} -eq 1 ]]; then - if [[ -e ${SATYPE_FILE} ]]; then - satype=$(cat "${SATYPE_FILE}") - check_diag_files "${PDY}${cyc}" "${satype}" "${avail_satype}" - else - echo "WARNING: missing ${SATYPE_FILE}" - fi + if [[ -e ${SATYPE_FILE} ]]; then + satype=$(cat "${SATYPE_FILE}") + check_diag_files "${PDY}${cyc}" "${satype}" "${avail_satype[*]}" + else + echo "WARNING: missing ${SATYPE_FILE}" + fi fi len_satype=$(echo -n "${satype}" | wc -c) if [[ ${len_satype} -le 1 ]]; then - satype=${avail_satype} + satype="${avail_satype[*]}" fi echo "${satype}" - len_satype=$(echo -n "${satype}" | wc -c) if [[ ${DO_DATA_RPT} -eq 1 && ${len_satype} -lt 1 ]]; then - iret=2 + iret=2 else - #-------------------------------------------------------------------- - # Copy extraction programs to working directory - # - cpreq "${EXECgfs}/oznmon_time.x" ./oznmon_time.x - cpreq "${EXECgfs}/oznmon_horiz.x" ./oznmon_horiz.x - - #--------------------------------------------------------------------------- - # Outer loop over $ozn_ptype (default values 'ges', 'anl') - # - for ptype in ${ozn_ptype}; do - - iyy="${PDY:0:4}" - imm="${PDY:4:2}" - idd="${PDY:6:2}" - ihh=${cyc} - - for type in ${avail_satype}; do - if [[ -f "diag_${type}_${ptype}.${PDY}${cyc}.gz" ]]; then - mv "diag_${type}_${ptype}.${PDY}${cyc}.gz" "${type}.${ptype}.gz" - gunzip "./${type}.${ptype}.gz" - - echo "processing ptype, type: ${ptype}, ${type}" - rm -f input - -cat << EOF > input + #-------------------------------------------------------------------- + # Copy extraction programs to working directory + # + cpreq "${EXECgfs}/oznmon_time.x" ./oznmon_time.x + cpreq "${EXECgfs}/oznmon_horiz.x" ./oznmon_horiz.x + + #--------------------------------------------------------------------------- + # Outer loop over $ozn_ptype (default values 'ges', 'anl') + # + for ptype in ${ozn_ptype}; do + + iyy="${PDY:0:4}" + imm="${PDY:4:2}" + idd="${PDY:6:2}" + ihh=${cyc} + + for type in "${avail_satype[@]}"; do + if [[ -f "diag_${type}_${ptype}.${PDY}${cyc}.gz" ]]; then + mv "diag_${type}_${ptype}.${PDY}${cyc}.gz" "${type}.${ptype}.gz" + gunzip "./${type}.${ptype}.gz" + + echo "processing ptype, type: ${ptype}, ${type}" + rm -f input + + cat << EOF > input &INPUT satname='${type}', iyy=${iyy}, @@ -173,28 +174,27 @@ cat << EOF > input / EOF + echo "oznmon_time.x HAS STARTED ${type}" - echo "oznmon_time.x HAS STARTED ${type}" - - ./oznmon_time.x < input > "stdout.time.${type}.${ptype}" + ./oznmon_time.x < input > "stdout.time.${type}.${ptype}" - echo "oznmon_time.x HAS ENDED ${type}" + echo "oznmon_time.x HAS ENDED ${type}" - if [[ ! -d ${TANKverf_ozn}/time ]]; then - mkdir -p "${TANKverf_ozn}/time" - fi - cpfs "${type}.${ptype}.ctl" "${TANKverf_ozn}/time/" - cpfs "${type}.${ptype}.${PDY}${cyc}.ieee_d" "${TANKverf_ozn}/time/" - - if compgen -G "bad*" > /dev/null; then - for bad_file in bad*; do - cpfs "${bad_file}" "${TANKverf_ozn}/time/" - done - fi - - rm -f input + if [[ ! -d ${TANKverf_ozn}/time ]]; then + mkdir -p "${TANKverf_ozn}/time" + fi + cpfs "${type}.${ptype}.ctl" "${TANKverf_ozn}/time/" + cpfs "${type}.${ptype}.${PDY}${cyc}.ieee_d" "${TANKverf_ozn}/time/" -cat << EOF > input + if compgen -G "bad*" > /dev/null; then + for bad_file in bad*; do + cpfs "${bad_file}" "${TANKverf_ozn}/time/" + done + fi + + rm -f input + + cat << EOF > input &INPUT satname='${type}', iyy=${iyy}, @@ -209,38 +209,37 @@ cat << EOF > input / EOF - echo "oznmon_horiz.x HAS STARTED ${type}" - - ./oznmon_horiz.x < input > "stdout.horiz.${type}.${ptype}" + echo "oznmon_horiz.x HAS STARTED ${type}" - echo "oznmon_horiz.x HAS ENDED ${type}" + ./oznmon_horiz.x < input > "stdout.horiz.${type}.${ptype}" - if [[ ! -d ${TANKverf_ozn}/horiz ]]; then - mkdir -p "${TANKverf_ozn}/horiz" - fi - cpfs "${type}.${ptype}.ctl" "${TANKverf_ozn}/horiz/" + echo "oznmon_horiz.x HAS ENDED ${type}" - ${COMPRESS} "${type}.${ptype}.${PDY}${cyc}.ieee_d" - cpfs "${type}.${ptype}.${PDY}${cyc}.ieee_d.${Z}" "${TANKverf_ozn}/horiz/" + if [[ ! -d ${TANKverf_ozn}/horiz ]]; then + mkdir -p "${TANKverf_ozn}/horiz" + fi + cpfs "${type}.${ptype}.ctl" "${TANKverf_ozn}/horiz/" + ${COMPRESS} "${type}.${ptype}.${PDY}${cyc}.ieee_d" + cpfs "${type}.${ptype}.${PDY}${cyc}.ieee_d.${Z}" "${TANKverf_ozn}/horiz/" - echo "finished processing ptype, type: ${ptype}, ${type}" + echo "finished processing ptype, type: ${ptype}, ${type}" - else - echo "diag file for ${type}.${ptype} not found" - fi + else + echo "diag file for ${type}.${ptype} not found" + fi - done # type in satype + done # type in satype - done # ptype in $ozn_ptype + done # ptype in $ozn_ptype - tar -cvf stdout.horiz.tar stdout.horiz* - ${COMPRESS} stdout.horiz.tar - cpfs "stdout.horiz.tar.${Z}" "${TANKverf_ozn}/horiz/" + tar -cvf stdout.horiz.tar stdout.horiz* + ${COMPRESS} stdout.horiz.tar + cpfs "stdout.horiz.tar.${Z}" "${TANKverf_ozn}/horiz/" - tar -cvf stdout.time.tar stdout.time* - ${COMPRESS} stdout.time.tar - cpfs "stdout.time.tar.${Z}" "${TANKverf_ozn}/time/" + tar -cvf stdout.time.tar stdout.time* + ${COMPRESS} stdout.time.tar + cpfs "stdout.time.tar.${Z}" "${TANKverf_ozn}/time/" fi -exit ${iret} +exit "${iret}" diff --git a/ush/parsing_model_configure_FV3.sh b/ush/parsing_model_configure_FV3.sh index c8d2d00f8a8..a5f141cd253 100755 --- a/ush/parsing_model_configure_FV3.sh +++ b/ush/parsing_model_configure_FV3.sh @@ -3,78 +3,78 @@ # parsing model_configure for UFSWM FV3 # shellcheck disable=SC2034 -FV3_model_configure(){ +FV3_model_configure() { -local restile=${CASE_HIST:1} + local restile=${CASE_HIST:1} -# Prepare local variables for use in model_configure.IN from UFSWM -# The ones already defined are left commented as a reminder + # Prepare local variables for use in model_configure.IN from UFSWM + # The ones already defined are left commented as a reminder -local model_start_date -if [[ "${DOIAU}" == "YES" ]]; then - model_start_date="${previous_cycle}" -else - model_start_date="${current_cycle}" -fi + local model_start_date + if [[ "${DOIAU}" == "YES" ]]; then + model_start_date="${previous_cycle}" + else + model_start_date="${current_cycle}" + fi -local SYEAR=${model_start_date:0:4} -local SMONTH=${model_start_date:4:2} -local SDAY=${model_start_date:6:2} -local SHOUR=${model_start_date:8:2} -# FHMAX -local FHROT=${IAU_FHROT:-0} -local DT_ATMOS=${DELTIM} -local RESTART_INTERVAL="${FV3_RESTART_FH[*]}" -local RESTART_FH="${CMEPS_RESTART_FH:-" "}" -# QUILTING -local QUILTING_RESTART="${QUILTING_RESTART:-${QUILTING}}" -local WRITE_GROUP=${WRITE_GROUP:-1} -local WRTTASK_PER_GROUP=${WRTTASK_PER_GROUP:-24} -local ITASKS=1 -local OUTPUT_HISTORY=${OUTPUT_HISTORY:-".true."} -if [[ "${DO_JEDIATMVAR:-}" == "YES" || "${DO_HISTORY_FILE_ON_NATIVE_GRID:-"NO"}" == "YES" ]]; then - local HISTORY_FILE_ON_NATIVE_GRID=".true." -else - local HISTORY_FILE_ON_NATIVE_GRID=".false." -fi -local WRITE_DOPOST=${WRITE_DOPOST:-".false."} -local WRITE_NSFLIP=${WRITE_NSFLIP:-".false."} -local NUM_FILES=${NUM_FILES:-2} -local FILENAME_BASE="'atm' 'sfc'" -# OUTPUT_GRID -local OUTPUT_FILE="'${OUTPUT_FILETYPE_ATM}' '${OUTPUT_FILETYPE_SFC}'" -local ZSTANDARD_LEVEL=${zstandard_level:-0} -local IDEFLATE=${ideflate:-0} # netCDF zlib lossless compression (0-9); 0: no compression -local QUANTIZE_NSD=${quantize_nsd:-0} # netCDF compression -local ICHUNK2D=$((4*restile)) -local JCHUNK2D=$((2*restile)) -local ICHUNK3D=$((4*restile)) -local JCHUNK3D=$((2*restile)) -local KCHUNK3D=1 -local IMO=${LONB_IMO} -local JMO=${LATB_JMO} -local OUTPUT_FH=${FV3_OUTPUT_FH_NML} -local IAU_OFFSET=${IAU_OFFSET:-0} -local USE_FV3_ROUTEHANDLES=.false. + local SYEAR=${model_start_date:0:4} + local SMONTH=${model_start_date:4:2} + local SDAY=${model_start_date:6:2} + local SHOUR=${model_start_date:8:2} + # FHMAX + local FHROT=${IAU_FHROT:-0} + local DT_ATMOS=${DELTIM} + local RESTART_INTERVAL="${FV3_RESTART_FH[*]}" + local RESTART_FH="${CMEPS_RESTART_FH:-" "}" + # QUILTING + local QUILTING_RESTART="${QUILTING_RESTART:-${QUILTING}}" + local WRITE_GROUP=${WRITE_GROUP:-1} + local WRTTASK_PER_GROUP=${WRTTASK_PER_GROUP:-24} + local ITASKS=1 + local OUTPUT_HISTORY=${OUTPUT_HISTORY:-".true."} + if [[ "${DO_JEDIATMVAR:-}" == "YES" || "${DO_HISTORY_FILE_ON_NATIVE_GRID:-"NO"}" == "YES" ]]; then + local HISTORY_FILE_ON_NATIVE_GRID=".true." + else + local HISTORY_FILE_ON_NATIVE_GRID=".false." + fi + local WRITE_DOPOST=${WRITE_DOPOST:-".false."} + local WRITE_NSFLIP=${WRITE_NSFLIP:-".false."} + local NUM_FILES=${NUM_FILES:-2} + local FILENAME_BASE="'atm' 'sfc'" + # OUTPUT_GRID + local OUTPUT_FILE="'${OUTPUT_FILETYPE_ATM}' '${OUTPUT_FILETYPE_SFC}'" + local ZSTANDARD_LEVEL=${zstandard_level:-0} + local IDEFLATE=${ideflate:-0} # netCDF zlib lossless compression (0-9); 0: no compression + local QUANTIZE_NSD=${quantize_nsd:-0} # netCDF compression + local ICHUNK2D=$((4 * restile)) + local JCHUNK2D=$((2 * restile)) + local ICHUNK3D=$((4 * restile)) + local JCHUNK3D=$((2 * restile)) + local KCHUNK3D=1 + local IMO=${LONB_IMO} + local JMO=${LATB_JMO} + local OUTPUT_FH=${FV3_OUTPUT_FH_NML} + local IAU_OFFSET=${IAU_OFFSET:-0} + local USE_FV3_ROUTEHANDLES=.false. -#set FV3 output directory: -local FV3ATM_OUTPUT_DIR="./FV3ATM_OUTPUT" + #set FV3 output directory: + local FV3ATM_OUTPUT_DIR="./FV3ATM_OUTPUT" -# Ensure the template exists -if [[ "${DO_NEST:-NO}" == "YES" ]] ; then - local NEST_IMO=${npx_nest} - local NEST_JMO=${npy_nest} - template="${PARMgfs}/ufs/input_global_nest.nml.IN" -else - template="${PARMgfs}/ufs/model_configure.IN" -fi -if [[ ! -f ${template} ]]; then - echo "FATAL ERROR: template '${template}' does not exist, ABORT!" - exit 1 -fi -rm -f "${DATA}/model_configure" -atparse < "${template}" >> "${DATA}/model_configure" -echo "Rendered model_configure" -cat "${DATA}/model_configure" + # Ensure the template exists + if [[ "${DO_NEST:-NO}" == "YES" ]]; then + local NEST_IMO=${npx_nest} + local NEST_JMO=${npy_nest} + template="${PARMgfs}/ufs/input_global_nest.nml.IN" + else + template="${PARMgfs}/ufs/model_configure.IN" + fi + if [[ ! -f ${template} ]]; then + echo "FATAL ERROR: template '${template}' does not exist, ABORT!" + exit 1 + fi + rm -f "${DATA}/model_configure" + atparse < "${template}" >> "${DATA}/model_configure" + echo "Rendered model_configure" + cat "${DATA}/model_configure" } diff --git a/ush/parsing_namelists_CICE.sh b/ush/parsing_namelists_CICE.sh index b2b0a97aca3..2815db5a022 100755 --- a/ush/parsing_namelists_CICE.sh +++ b/ush/parsing_namelists_CICE.sh @@ -4,149 +4,147 @@ # Disable variable not used warnings # shellcheck disable=SC2034 -CICE_namelists(){ +CICE_namelists() { -# "warm_start" here refers to whether CICE model is warm starting or not. -# Per JM, in the case of the Prototypes, the sea-ice ICs were obtained from CPC. -# CPC sea-ice initial conditions are created from SIS2 sea-ice model. -# Hence, the prototypes always set this to "initial" -# in order for the CICE model to _initialize_ from the SIS2 ICs. -# However, in the SOCA cycled system, if starting from a previously cycled SOCA run, -# the CICE ICs are obtained from the previous cycle of the UFS S2S, -# so the CICE namelist should be set to "continue" -# TODO: Is there a way to interrogate the restart file to know if this is a -# SIS2 restart or a CICE restart, instead of relying on "${warm_start}" -if [[ "${warm_start}" = ".true." ]]; then - local runtype="continue" - local use_restart_time=".true." -else - local runtype="initial" - local use_restart_time=".false." -fi + # "warm_start" here refers to whether CICE model is warm starting or not. + # Per JM, in the case of the Prototypes, the sea-ice ICs were obtained from CPC. + # CPC sea-ice initial conditions are created from SIS2 sea-ice model. + # Hence, the prototypes always set this to "initial" + # in order for the CICE model to _initialize_ from the SIS2 ICs. + # However, in the SOCA cycled system, if starting from a previously cycled SOCA run, + # the CICE ICs are obtained from the previous cycle of the UFS S2S, + # so the CICE namelist should be set to "continue" + # TODO: Is there a way to interrogate the restart file to know if this is a + # SIS2 restart or a CICE restart, instead of relying on "${warm_start}" + if [[ "${warm_start}" = ".true." ]]; then + local runtype="continue" + local use_restart_time=".true." + else + local runtype="initial" + local use_restart_time=".false." + fi -# Get correct MPI options for NPROC and grid -local processor_shape=${cice6_processor_shape:-'slenderX2'} -local shape=${processor_shape#${processor_shape%?}} -local NPX=$(( ntasks_cice6 / shape )) #number of processors in x direction -local NPY=$(( ntasks_cice6 / NPX )) #number of processors in y direction -if (( $(( NX_GLB % NPX )) == 0 )); then - local block_size_x=$(( NX_GLB / NPX )) -else - local block_size_x=$(( (NX_GLB / NPX) + 1 )) -fi -if (( $(( NY_GLB % NPY )) == 0 )); then - local block_size_y=$(( NY_GLB / NPY )) -else - local block_size_y=$(( (NY_GLB / NPY) + 1 )) -fi + # Get correct MPI options for NPROC and grid + local processor_shape=${cice6_processor_shape:-'slenderX2'} + local shape=${processor_shape#"${processor_shape%?}"} + local NPX=$((ntasks_cice6 / shape)) #number of processors in x direction + local NPY=$((ntasks_cice6 / NPX)) #number of processors in y direction + if (($((NX_GLB % NPX)) == 0)); then + local block_size_x=$((NX_GLB / NPX)) + else + local block_size_x=$(((NX_GLB / NPX) + 1)) + fi + if (($((NY_GLB % NPY)) == 0)); then + local block_size_y=$((NY_GLB / NPY)) + else + local block_size_y=$(((NY_GLB / NPY) + 1)) + fi -local sec stepsperhr npt -sec=$(to_seconds "${current_cycle:8:2}0000") -stepsperhr=$((3600/ICETIM)) -npt=$((FHMAX*stepsperhr)) # Need this in order for dump_last to work + local sec stepsperhr npt + sec=$(to_seconds "${current_cycle:8:2}0000") + stepsperhr=$((3600 / ICETIM)) + npt=$((FHMAX * stepsperhr)) # Need this in order for dump_last to work -# Prepare local variables for use in ice_in_template from UFSWM -# The ones already defined are left commented as a reminder -# setup_nml section -local SYEAR=${current_cycle:0:4} -local SMONTH=${current_cycle:4:2} -local SDAY=${current_cycle:6:2} -local SECS=${sec} -local DT_CICE=${ICETIM} -local CICE_NPT=${npt} -local CICE_RUNTYPE=${runtype} -local CICE_RUNID="unknown" -local CICE_USE_RESTART_TIME=${use_restart_time} -local CICE_RESTART_DIR="./CICE_RESTART/" -local CICE_RESTART_FILE="cice_model.res" -local CICE_ICE_IC='cice_model.res.nc' -local CICE_RESTART_DEFLATE=0 -local CICE_RESTART_CHUNK=0,0 -local CICE_RESTART_STRIDE=-99 -local CICE_RESTART_ROOT=-99 -local CICE_RESTART_REARR="box" -local CICE_RESTART_IOTASKS=-99 -local CICE_RESTART_FORMAT="pnetcdf2" -local CICE_DUMPFREQ="y" # "h","d","m" or "y" for restarts at intervals of "hours", "days", "months" or "years" -local CICE_DUMPFREQ_N=10000 # Set this to a really large value, as cice, mom6 and cmeps restart interval is controlled by ufs.configure -local CICE_DIAGFREQ=$(( 86400 / DT_CICE )) # frequency of diagnostic output in timesteps, recommended for 1x per day -if [[ "${RUN}" == "gefs" ]]; then - local CICE_DIAGFREQ1=$((( FHOUT_ICE * 3600 )/ DT_CICE )) # Number of timesteps within FHOUT_ICE - local CICE_HISTFREQ_N="0, 0, 0, ${CICE_DIAGFREQ1}, 1" -else - local CICE_HISTFREQ_N="0, 0, ${FHOUT_ICE}, 0, 1" -fi -local CICE_hist_suffix="'x','x','x','x','x'" -if [[ "${RUN}" =~ "gdas" ]]; then - local CICE_HIST_AVG=".false., .false., .false., .false., .false." # DA needs instantaneous -else - local CICE_HIST_AVG=".true., .true., .true., .true., .true." # GFS long forecaset wants averaged over CICE_HISTFREQ_N -fi -local CICE_HISTORY_FORMAT="pnetcdf2" -local CICE_HISTORY_DIR="./CICE_OUTPUT/" -local CICE_INCOND_DIR="./CICE_OUTPUT/" -local CICE_HISTORY_IOTASKS=-99 -local CICE_HISTORY_REARR="box" -local CICE_HISTORY_ROOT=-99 -local CICE_HISTORY_STRIDE=-99 -local CICE_HISTORY_CHUNK=0,0 -local CICE_HISTORY_DEFLATE=0 -local CICE_HISTORY_PREC=4 -# grid_nml section -# CICE_GRID -# CICE_MASK -local CICE_GRIDATM="A" # A-grid for atmosphere (FV3) -local CICE_GRIDOCN="A" # A-grid for ocean (MOM6) -local CICE_GRIDICE="B" # B-grid for seaice (CICE6) -# tracer_nml section -local CICE_TR_POND_LVL=".true." # Use level melt ponds -# (if CICE_TR_POND_LVL=true): - # -- if true, initialize the level ponds from restart (if runtype=continue) - # -- if false, re-initialize level ponds to zero (if runtype=initial or continue) -local CICE_RESTART_POND_LVL=".false." # Restart level ponds from restart file (if runtype=continue) -# thermo_nml section -local CICE_KTHERM=2 # 0=zero-layer thermodynamics, 1=fixed-salinity profile, 2=mushy thermodynamics -# dynamics_nml section -# NONE -# shortwave_nml section -# NONE -# ponds_nml section -# NONE -# snow_nml section -# NONE -# forcing_nml section -local CICE_FRAZIL_FWSALT=${FRAZIL_FWSALT:-".true."} -local CICE_TFREEZE_OPTION=${tfrz_option:-"mushy"} -# domain_nml section -local CICE_NPROC=${ntasks_cice6} -# NX_GLB -# NY_GLB -local CICE_BLCKX=${block_size_x} -local CICE_BLCKY=${block_size_y} -local CICE_DECOMP=${processor_shape} -# ice_prescribed_nml section -local CICE_PRESCRIBED="false" -local MESH_DICE="none" -local stream_files_dice="none" + # Prepare local variables for use in ice_in_template from UFSWM + # The ones already defined are left commented as a reminder + # setup_nml section + local SYEAR=${current_cycle:0:4} + local SMONTH=${current_cycle:4:2} + local SDAY=${current_cycle:6:2} + local SECS=${sec} + local DT_CICE=${ICETIM} + local CICE_NPT=${npt} + local CICE_RUNTYPE=${runtype} + local CICE_RUNID="unknown" + local CICE_USE_RESTART_TIME=${use_restart_time} + local CICE_RESTART_DIR="./CICE_RESTART/" + local CICE_RESTART_FILE="cice_model.res" + local CICE_ICE_IC='cice_model.res.nc' + local CICE_RESTART_DEFLATE=0 + local CICE_RESTART_CHUNK=0,0 + local CICE_RESTART_STRIDE=-99 + local CICE_RESTART_ROOT=-99 + local CICE_RESTART_REARR="box" + local CICE_RESTART_IOTASKS=-99 + local CICE_RESTART_FORMAT="pnetcdf2" + local CICE_DUMPFREQ="y" # "h","d","m" or "y" for restarts at intervals of "hours", "days", "months" or "years" + local CICE_DUMPFREQ_N=10000 # Set this to a really large value, as cice, mom6 and cmeps restart interval is controlled by ufs.configure + local CICE_DIAGFREQ=$((86400 / DT_CICE)) # frequency of diagnostic output in timesteps, recommended for 1x per day + if [[ "${RUN}" == "gefs" ]]; then + local CICE_DIAGFREQ1=$(((FHOUT_ICE * 3600) / DT_CICE)) # Number of timesteps within FHOUT_ICE + local CICE_HISTFREQ_N="0, 0, 0, ${CICE_DIAGFREQ1}, 1" + else + local CICE_HISTFREQ_N="0, 0, ${FHOUT_ICE}, 0, 1" + fi + local CICE_hist_suffix="'x','x','x','x','x'" + if [[ "${RUN}" =~ "gdas" ]]; then + local CICE_HIST_AVG=".false., .false., .false., .false., .false." # DA needs instantaneous + else + local CICE_HIST_AVG=".true., .true., .true., .true., .true." # GFS long forecaset wants averaged over CICE_HISTFREQ_N + fi + local CICE_HISTORY_FORMAT="pnetcdf2" + local CICE_HISTORY_DIR="./CICE_OUTPUT/" + local CICE_INCOND_DIR="./CICE_OUTPUT/" + local CICE_HISTORY_IOTASKS=-99 + local CICE_HISTORY_REARR="box" + local CICE_HISTORY_ROOT=-99 + local CICE_HISTORY_STRIDE=-99 + local CICE_HISTORY_CHUNK=0,0 + local CICE_HISTORY_DEFLATE=0 + local CICE_HISTORY_PREC=4 + # grid_nml section + # CICE_GRID + # CICE_MASK + local CICE_GRIDATM="A" # A-grid for atmosphere (FV3) + local CICE_GRIDOCN="A" # A-grid for ocean (MOM6) + local CICE_GRIDICE="B" # B-grid for seaice (CICE6) + # tracer_nml section + local CICE_TR_POND_LVL=".true." # Use level melt ponds + # (if CICE_TR_POND_LVL=true): + # -- if true, initialize the level ponds from restart (if runtype=continue) + # -- if false, re-initialize level ponds to zero (if runtype=initial or continue) + local CICE_RESTART_POND_LVL=".false." # Restart level ponds from restart file (if runtype=continue) + # thermo_nml section + local CICE_KTHERM=2 # 0=zero-layer thermodynamics, 1=fixed-salinity profile, 2=mushy thermodynamics + # dynamics_nml section + # NONE + # shortwave_nml section + # NONE + # ponds_nml section + # NONE + # snow_nml section + # NONE + # forcing_nml section + local CICE_FRAZIL_FWSALT=${FRAZIL_FWSALT:-".true."} + local CICE_TFREEZE_OPTION=${tfrz_option:-"mushy"} + # domain_nml section + local CICE_NPROC=${ntasks_cice6} + # NX_GLB + # NY_GLB + local CICE_BLCKX=${block_size_x} + local CICE_BLCKY=${block_size_y} + local CICE_DECOMP=${processor_shape} + # ice_prescribed_nml section + local CICE_PRESCRIBED="false" + local MESH_DICE="none" + local stream_files_dice="none" + # Ensure the template exists + local template=${CICE_TEMPLATE:-"${PARMgfs}/ufs/ice_in.IN"} + if [[ ! -f "${template}" ]]; then + echo "FATAL ERROR: template '${template}' does not exist, ABORT!" + exit 1 + fi + rm -f "${DATA}/ice_in" + atparse < "${template}" >> "${DATA}/ice_in" + echo "Rendered ice_in:" + cat "${DATA}/ice_in" - -# Ensure the template exists -local template=${CICE_TEMPLATE:-"${PARMgfs}/ufs/ice_in.IN"} -if [[ ! -f "${template}" ]]; then - echo "FATAL ERROR: template '${template}' does not exist, ABORT!" - exit 1 -fi -rm -f "${DATA}/ice_in" -atparse < "${template}" >> "${DATA}/ice_in" -echo "Rendered ice_in:" -cat "${DATA}/ice_in" - -# Create a ice.restart_file when runtype is "continue" -# This file is not needed when runtype is "initial" -rm -f "${DATA}/ice.restart_file" -if [[ "${runtype}" == "continue" ]]; then - echo "${DATA}/cice_model.res.nc" > "${DATA}/ice.restart_file" -fi + # Create a ice.restart_file when runtype is "continue" + # This file is not needed when runtype is "initial" + rm -f "${DATA}/ice.restart_file" + if [[ "${runtype}" == "continue" ]]; then + echo "${DATA}/cice_model.res.nc" > "${DATA}/ice.restart_file" + fi } diff --git a/ush/parsing_namelists_FV3.sh b/ush/parsing_namelists_FV3.sh index 4b6bfff80fe..dfdfecacb52 100755 --- a/ush/parsing_namelists_FV3.sh +++ b/ush/parsing_namelists_FV3.sh @@ -4,495 +4,495 @@ # Disable variable not used warnings # shellcheck disable=SC2034 -FV3_namelists(){ - -# setup the tables -DIAG_TABLE=${DIAG_TABLE:-${PARMgfs}/ufs/fv3/diag_table} -DIAG_TABLE_APPEND=${DIAG_TABLE_APPEND:-${PARMgfs}/ufs/fv3/diag_table_aod} -DATA_TABLE=${DATA_TABLE:-${PARMgfs}/ufs/MOM6_data_table.IN} -FIELD_TABLE=${FIELD_TABLE:-${PARMgfs}/ufs/fv3/field_table} - -# set cdmbgwd -if (( gwd_opt == 2 )) && [[ ${do_gsl_drag_ls_bl} == ".true." ]]; then - cdmbgwd=${cdmbgwd_gsl} -fi - -# ensure non-prognostic tracers are set -dnats=${dnats:-0} - -# build the diag_table -{ -echo "UFS_Weather_Model_Forecast" -if [[ "${DOIAU}" = "YES" ]]; then - echo "${previous_cycle:0:4} ${previous_cycle:4:2} ${previous_cycle:6:2} ${previous_cycle:8:2} 0 0" -else - echo "${current_cycle:0:4} ${current_cycle:4:2} ${current_cycle:6:2} ${current_cycle:8:2} 0 0" -fi -cat "${DIAG_TABLE}" -if [[ -n "${AERO_DIAG_TABLE:-}" ]]; then - cat "${AERO_DIAG_TABLE}" -fi -cat "${DIAG_TABLE_APPEND}" -} >> diag_table_template - -local template=diag_table_template -local SYEAR=${current_cycle:0:4} -local SMONTH=${current_cycle:4:2} -local SDAY=${current_cycle:6:2} -local CHOUR=${current_cycle:8:2} -local MOM6_OUTPUT_DIR="./MOM6_OUTPUT" - -atparse < "${template}" >> "diag_table" - - -# copy data table -cpreq "${DATA_TABLE}" data_table - -# build field_table -if [[ -n "${AERO_FIELD_TABLE:-}" ]]; then - nrec=$(wc -l < "${FIELD_TABLE}") - prec=${nrec} - if (( dnats > 0 )); then - prec=$( grep -F -n TRACER "${FIELD_TABLE}" 2> /dev/null | tail -n "${dnats}" | head -1 | cut -d: -f1 ) - prec=${prec:-0} - prec=$(( prec > 0 ? prec - 1 : prec )) - fi - { \ - head -n "${prec}" "${FIELD_TABLE}" ; \ - cat "${AERO_FIELD_TABLE}" ; \ - tail -n $(( nrec - prec )) "${FIELD_TABLE}" ; \ - } > field_table - # add non-prognostic tracers from additional table - dnats=$(( dnats + dnats_aero )) -else - cpreq "${FIELD_TABLE}" field_table -fi - -# Set variables for global_control.nml template - -local BLOCKSIZE=${blocksize} -local CHKSUM_DEBUG=${chksum_debug} -local DYCORE_ONLY=${dycore_only} -local CCPP_SUITE=${CCPP_SUITE} - -local MAX_OUTPUT_FIELDS=300 - -local DOMAINS_STACK_SIZE=${domains_stack_size:-3000000} -local PRINT_MEMORY_USAGE=${print_memory_usage:-".false."} - -local INPES=${layout_x} -local JNPES=${layout_y} -local IO_LAYOUT=${io_layout} -local NPX=${npx} -local NPY=${npy} -local NTILES=${ntiles} -local NPZ=${npz} -local DZ_MIN=${dz_min:-"6"} -local PSM_BC=${psm_bc:-"0"} -local MAKE_NH=${make_nh} -local FV_DEBUG=${fv_debug:-".false."} -local RANGE_WARN=${range_warn:-".true."} -local N_SPONGE=${n_sponge:-"10"} -local NUDGE_QV=${nudge_qv:-".false."} -local NUDGE_DZ=${nudge_dz:-".false."} -local TAU=${tau:-10.} -local FAST_TAU_W_SEC=${fast_tau_w_sec:-"0.2"} -local RF_CUTOFF=${rf_cutoff:-"7.5e2"} -local D2_BG_K1=${d2_bg_k1:-"0.15"} -local D2_BG_K2=${d2_bg_k2:-"0.02"} -local KORD_TM=${kord_tm:-"-9"} -local KORD_MT=${kord_mt:-"9"} -local KORD_WZ=${kord_wz:-"9"} -local KORD_TR=${kord_tr:-"9"} -local HYDROSTATIC=${hydrostatic} -local PHYS_HYDROSTATIC=${phys_hydrostatic} -local USE_HYDRO_PRESSURE=${use_hydro_pressure} -local UPDATE_FULL_OMEGA=${pass_full_omega_to_physics_in_non_hydrostatic_mode:-".false."} -local K_SPLIT=${k_split} -local N_SPLIT=${n_split} -local NWAT=${nwat:-2} -local NA_INIT=${na_init} -local DNATS=${dnats} -local FV_SG_ADJ=${fv_sg_adj:-"450"} -local NORD=${nord:-3} -local DDDMP=${dddmp:-0.1} -local D4_BG=${d4_bg:-0.15} -local VTDM4=${vtdm4} -local DELT_MAX=${delt_max:-"0.002"} -local DO_VORT_DAMP=${do_vort_damp} -local EXTERNAL_IC=${external_ic} -local EXTERNAL_ETA=${external_eta:-.true.} -local GFS_PHIL=${gfs_phil:-".false."} -local NGGPS_IC=${nggps_ic} -local MOUNTAIN=${mountain} -local NCEP_IC=${ncep_ic} -local D_CON=${d_con} -local HORD_MT=${hord_mt} -local HORD_VT=${hord_xx} -local HORD_TM=${hord_xx} -local HORD_DP=${hord_dp} -local HORD_TR=${hord_tr:-"8"} -local ADJUST_DRY_MASS=${adjust_dry_mass:-".true."} -local DRY_MASS=${dry_mass:-98320.0} -local CONSV_TE=${consv_te} -local DO_SAT_ADJ=${do_sat_adj:-".false."} -local PRINT_FREQ=${print_freq} -local WARM_START=${warm_start} -local NO_DYCORE=${no_dycore} -local AGRID_VEL_RST=${agrid_vel_rst:-".true."} -local READ_INCREMENT=${read_increment} -local RES_LATLON_DYNAMICS=${res_latlon_dynamics} -local ATM_IGNORE_RST_CKSUM=.false. -local INCREMENT_FILE_ON_NATIVE_GRID=${increment_file_on_native_grid:-.false.} - -local FILTERED_TERRAIN=${filtered_terrain} -local NPZP=${LEVS} #levp -local GFS_DWINDS=${gfs_dwinds} - -local FHZERO=${FHZERO:-6} -local H2O_PHYS=${h2o_phys:-".true."} -local LDIAG3D=${ldiag3d:-".false."} -local QDIAG3D=${qdiag3d:-".false."} -local PRINT_DIFF_PGR=${print_diff_pgr:-".false."} -local FHCYC=${FHCYC} -local USE_UFO=${use_ufo:-".true."} -local PRE_RAD=${pre_rad:-".false."} -local IMP_PHYSICS=${imp_physics:-"99"} - -local default_dt_inner=$(( DELTIM/2 )) -local IOVR=${iovr:-"3"} -local LTAEROSOL=${ltaerosol:-".false."} -local MRAEROSOL=.false. -local LTHAILAWARE=.false. -local LRADAR=${lradar:-".true."} -local TTENDLIM=${ttendlim:-"-999"} -local DT_INNER=${dt_inner:-"${default_dt_inner}"} -local SEDI_SEMI=${sedi_semi:-".true."} -local DECFL=${decfl:-"10"} -local OZ_PHYS_NEW=${oz_phys:-".false."} -local OZ_PHYS_OLD=${oz_phys_2015:-".true."} -local LSOIL_LSM=${lsoil_lsm:-"4"} -local DO_MYNNEDMF=${do_mynnedmf:-".false."} -local DO_MYNNSFCLAY=${do_mynnsfclay:-".false."} -local ICLOUD_BL=${icloud_bl:-"1"} -local BL_MYNN_EDMF=${bl_mynn_edmf:-"1"} -local BL_MYNN_TKEADVECT=${bl_mynn_tkeadvect:-".true."} -local BL_MYNN_EDMF_MOM=${bl_mynn_edmf_mom:-"1"} -local TTE_EDMF=${tte_edmf:-".false."} -local CSCALE=${cscale:-"1.0"} -local DO_NGW_EC=${do_ngw_ec:-".false."} -local DO_UGWP=${do_ugwp:-".false."} -local DO_TOFD=${do_tofd:-".false."} -local GWD_OPT=${gwd_opt:-"2"} -local DO_UGWP_V0=${do_ugwp_v0:-".false."} -local DO_UGWP_V1=${do_ugwp_v1:-".true."} -local DO_UGWP_V0_OROG_ONLY=${do_ugwp_v0_orog_only:-".false."} -local DO_UGWP_V0_NST_ONLY=${do_ugwp_v0_nst_only:-".false."} -local DO_GSL_DRAG_LS_BL=${do_gsl_drag_ls_bl:-".true."} -local DO_GSL_DRAG_SS=${do_gsl_drag_ss:-".true."} -local DO_GSL_DRAG_TOFD=${do_gsl_drag_tofd:-".true."} -local DO_GWD_OPT_PSL=${do_gwd_opt_psl:-".false."} -local DO_UGWP_V1_OROG_ONLY=${do_ugwp_v1_orog_only:-".false."} -local MIN_LAKEICE=${min_lakeice:-"0.15"} -local MIN_SEAICE=${min_seaice:-"0.15"} -local USE_CICE_ALB=${use_cice_alb:-".false."} - -local PDFCLD=${pdfcld:-".false."} -local FHSWR=${FHSWR:-"3600."} -local FHLWR=${FHLWR:-"3600."} -local IALB=${IALB:-"1"} -local IEMS=${IEMS:-"1"} -local IAER=${IAER} -local ICLIQ_SW=${icliq_sw:-"2"} -local ICO2=${ICO2} -local ISUBC_SW=${isubc_sw:-"2"} -local ISUBC_LW=${isubc_lw:-"2"} -local ISOL=${ISOL:-"2"} -local LWHTR=${lwhtr:-".true."} -local SWHTR=${swhtr:-".true."} -local CNVGWD=${cnvgwd:-".true."} -local SHAL_CNV=${shal_cnv:-".true."} -local CAL_PRE=${cal_pre:-".true."} -local REDRAG=${redrag:-".true."} -local DSPHEAT=${dspheat:-".true."} -local HYBEDMF=${hybedmf:-".false."} -local SATMEDMF=${satmedmf:-".true."} -local ISATMEDMF=${isatmedmf:-"1"} -local LHEATSTRG=${lheatstrg:-".false."} -local LSEASPRAY=${lseaspray:-".true."} -local RANDOM_CLDS=${random_clds:-".true."} -local TRANS_TRAC=${trans_trac:-".true."} -local CNVCLD=${cnvcld:-".true."} -local XR_CNVCLD=${xr_cnvcld:-".true."} -local IMFSHALCNV=${imfshalcnv:-"2"} -local IMFDEEPCNV=${imfdeepcnv:-"2"} -local PROGSIGMA=${progsigma:-".true."} -local BETASCU=${betascu:-"8.0"} -local BETAMCU=${betamcu:-"1.0"} -local BETADCU=${betadcu:-"2.0"} -local RAS=${ras:-".false."} -local CDMBGWD=${cdmbgwd:-"3.5,0.25"} -local PSL_GWD_DX_FACTOR=${psl_gwd_dx_factor:-"6.0"} -local PRSLRD0=${prslrd0:-"0."} -local IVEGSRC=${ivegsrc:-"1"} -local ISOT=${isot:-"1"} -local LSOIL=${lsoil:-"4"} -local LSM=${lsm:-"2"} -local IOPT_DVEG=${iopt_dveg:-"1"} -local IOPT_CRS=${iopt_crs:-"1"} -local IOPT_BTR=${iopt_btr:-"1"} -local IOPT_RUN=${iopt_run:-"1"} -local IOPT_SFC=${iopt_sfc:-"1"} -local IOPT_TRS=${iopt_trs:-"2"} -local IOPT_DIAG=${iopt_diag:-"2"} -local IOPT_FRZ=${iopt_frz:-"1"} -local IOPT_INF=${iopt_inf:-"1"} -local IOPT_RAD=${iopt_rad:-"1"} -local IOPT_ALB=${iopt_alb:-"2"} -local IOPT_SNF=${iopt_snf:-"4"} -local IOPT_TBOT=${iopt_tbot:-"2"} -local IOPT_STC=${iopt_stc:-"1"} -local DEBUG=${gfs_phys_debug:-".false."} -local NSTF_NAME=${nstf_name} -local NST_ANL=${nst_anl} -local PSAUTCO=${psautco:-"0.0008,0.0005"} -local PRAUTCO=${prautco:-"0.00015,0.00015"} -local LGFDLMPRAD=${lgfdlmprad:-".false."} -local EFFR_IN=${effr_in:-".false."} -local LDIAG_UGWP=${ldiag_ugwp:-".false."} -local DO_RRTMGP=${do_RRTMGP:-".false."} -local ACTIVE_GASES=${active_gases:-"'h2o_co2_o3_n2o_ch4_o2'"} -local NGASES=${ngases:-"6"} -local LW_FILE_GAS=${lw_file_gas:-"'rrtmgp-data-lw-g128-210809.nc'"} -local LW_FILE_CLOUDS=${lw_file_clouds:-"'rrtmgp-cloud-optics-coeffs-lw.nc'"} -local SW_FILE_GAS=${sw_file_gas:-"'rrtmgp-data-sw-g112-210809.nc'"} -local SW_FILE_CLOUDS=${sw_file_clouds:-"'rrtmgp-cloud-optics-coeffs-sw.nc'"} -local RRTMGP_NGPTSSW=${rrtmgp_nGptsSW:-"112"} -local RRTMGP_NGPTSLW=${rrtmgp_nGptsLW:-"128"} -local RRTMGP_NBANDSLW=${rrtmgp_nBandsLW:-"16"} -local RRTMGP_NBANDSSW=${rrtmgp_nBandsSW:-"14"} -local DOGP_CLDOPTICS_LUT=${doGP_cldoptics_LUT:-".false."} -local DOGP_LWSCAT=${doGP_lwscat:-".false."} -local DOGP_SGS_CNV=.true. - -local DO_SPPT=${do_sppt:-".false."} -local DO_SHUM=${do_shum:-".false."} -local DO_SKEB=${do_skeb:-".false."} -local FRAC_GRID=${FRAC_GRID:-".true."} -local CPLCHM=${cplchm:-".false."} -local CPLFLX=${cplflx:-".false."} -local CPLICE=${cplice:-".false."} -local CPLWAV=${cplwav:-".false."} -local CPLWAV2ATM=${cplwav2atm:-".false."} -local USE_MED_FLUX=${use_med_flux:-".false."} -local CPLLND=${cpllnd:-".false."} -local CPLLND2ATM=${cpllnd2atm:-".false."} -local USE_OCEANUV=${use_oceanuv:-".false."} - -# CPL CHM options -if [[ ${cplchm} = ".true." ]]; then - local FSCAV_AERO=${fscav_aero:-'*:0.0'} -else - local FSCAV_AERO='"*:0.3","so2:0.0","msa:0.0","dms:0.0","nh3:0.4","nh4:0.6","bc1:0.6","bc2:0.6","oc1:0.4","oc2:0.4","dust1:0.6","dust2:0.6","dust3:0.6","dust4:0.6","dust5:0.6","seas1:0.5","seas2:0.5","seas3:0.5","seas4:0.5","seas5:0.5"' -fi - -local IAUFHRS=${IAUFHRS} -local IAU_DELTHRS=${IAU_DELTHRS} -local IAU_INC_FILES=${IAU_INC_FILES:-"''"} -local IAU_DRYMASSFIXER=.false. -local IAU_FILTER_INCREMENTS=${IAU_FILTER_INCREMENTS:-".false."} - -# CA options -local DO_CA=".true." -local CA_GLOBAL=${ca_global:-".false."} -local CA_SGS=${ca_sgs:-".true."} -local NCA=${nca:-"1"} -local NCELLS=${ncells:-"5"} -local NLIVES=${nlives:-"12"} -local NSEED=${nseed:-"1"} -local NFRACSEED=${nfracseed:-"0.5"} -local NTHRESH=${nthresh:-"18"} -local CA_TRIGGER=${ca_trigger:-".true."} -local NSPINUP=${nspinup:-"1"} -local ISEED_CA=${ISEED_CA:-"12345"} - -# Land pert options -local LNDP_TYPE=${lndp_type:-2} -local N_VAR_LNDP=${n_var_lndp:-0} - -local LCNORM=${lcnorm:-".false."} -local PERT_MP=${PERT_MP:-".false."} -local PERT_RADTEND=${PERT_RADTEND:-".false."} -local PERT_CLDS=${PERT_CLDS:-".false."} - -if [[ ${DO_SPPT} = ".true." ]]; then - local PERT_CLDS=".true." -fi - -if [[ "${DOIAU}" = "YES" ]]; then - local HIDE_AIAU=" " -else - local HIDE_AIAU="!" -fi - -#GWP options -if [[ ${knob_ugwp_version} -eq 0 ]]; then - local HIDE_UGWPV0=" " - local HIDE_UGWPV1="!" -elif [[ ${knob_ugwp_version} -eq 1 ]]; then - local HIDE_UGWPV0="!" - local HIDE_UGWPV1=" " -else - local HIDE_UGWPV0="!" - local HIDE_UGWPV1="!" -fi - -# Common GWP options -local KNOB_UGWP_SOLVER=${knob_ugwp_solver:-2} -local KNOB_UGWP_SOURCE=${knob_ugwp_source:-1,1,0,0} -local KNOB_UGWP_WVSPEC=${knob_ugwp_wvspec:-1,25,25,25} -local KNOB_UGWP_AZDIR=${knob_ugwp_azdir:-2,4,4,4} -local KNOB_UGWP_STOCH=${knob_ugwp_stoch:-0,0,0,0} -local KNOB_UGWP_EFFAC=${knob_ugwp_effac:-1,1,1,1} -local KNOB_UGWP_DOAXYZ=${knob_ugwp_doaxyz:-1} -local KNOB_UGWP_DOHEAT=${knob_ugwp_doheat:-1} -# UGWP Version 0 options -local KNOB_UGWP_DOKDIS=${knob_ugwp_dokdis:-1} -local KNOB_UGWP_NDX4LH=${knob_ugwp_ndx4lh:-1} -local KNOB_UGWP_VERSION=${knob_ugwp_version:-0} -local LAUNCH_LEVEL=${launch_level:-54} -# UGWP Version 1 options -local KNOB_UGWP_DOKDIS=${knob_ugwp_dokdis:-2} -local KNOB_UGWP_NDX4LH=${knob_ugwp_ndx4lh:-4} -local KNOB_UGWP_VERSION=${knob_ugwp_version:-1} -local KNOB_UGWP_PALAUNCH=${knob_ugwp_palaunch:-275.0e2} -local KNOB_UGWP_NSLOPE=${knob_ugwp_nslope:-1} -local KNOB_UGWP_LZMAX=${knob_ugwp_lzmax:-15.750e3} -local KNOB_UGWP_LZMIN=${knob_ugwp_lzmin:-0.75e3} -local KNOB_UGWP_LZSTAR=${knob_ugwp_lzstar:-2.0e3} -local KNOB_UGWP_TAUMIN=${knob_ugwp_taumin:-0.25e-3} -local KNOB_UGWP_TAUAMP=${knob_ugwp_tauamp:-3.0e-3} -local KNOB_UGWP_LHMET=${knob_ugwp_lhmet:-200.0e3} -local KNOB_UGWP_OROSOLV=${knob_ugwp_orosolv:-\'pss-1986\'} - -# gfdl_cloud_microphysics options -local REIFLAG=${reiflag:-"2"} - -# interpolator_nml options - -# nam sfc options -local FNGLAC="'${FNGLAC}'" -local FNMXIC="'${FNMXIC}'" -local FNTSFC="'${FNTSFC}'" -local FNSNOC="'${FNSNOC}'" -local FNZORC="'${FNZORC}'" -local FNALBC="'${FNALBC}'" -local FNALBC2="'${FNALBC2}'" -local FNAISC="'${FNAISC}'" -local FNTG3C="'${FNTG3C}'" -local FNVEGC="'${FNVEGC}'" -local FNVETC="'${FNVETC}'" -local FNSOTC="'${FNSOTC}'" -local FNSOCC="'${FNSOCC}'" -local FNSMCC="'${FNSMCC}'" -local FNMSKH="'${FNMSKH}'" -local FNTSFA="'${FNTSFA}'" -local FNACNA="'${FNACNA:-}'" -local FNSNOA="'${FNSNOA:-}'" -local FNVMNC="'${FNVMNC:-}'" -local FNVMXC="'${FNVMXC:-}'" -local FNSLPC="'${FNSLPC:-}'" -local FNABSC="'${FNABSC:-}'" -local LDEBUG=${LDEBUG:-".false."} -local FSMCL2=${FSMCL2:+\'${FSMCL2}\'}${FSMCL2:-99999} -local FSMCL3=${FSMCL3:+\'${FSMCL3}\'}${FSMCL3:-99999} -local FSMCL4=${FSMCL4:+\'${FSMCL4}\'}${FSMCL4:-99999} -local LANDICE=${landice:-".true."} -local FTSFS=${FTSFS:-90} -local FAISL=${FAISL:+\'${FAISL}\'}${FAISL:-99999} -local FAISS=${FAISS:+\'${FAISS}\'}${FAISS:-99999} -local FSNOL=${FSNOL:+\'${FSNOL}\'}${FSNOL:-99999} -local FSNOS=${FSNOS:+\'${FSNOS}\'}${FSNOS:-99999} -local FSICL=${FSICL:-99999} -local FSICS=${FSICS:-99999} -local FTSFL=${FTSFL:+\'${FTSFL}\'}${FTSFL:-99999} -local FVETL=${FVETL:+\'${FVETL}\'}${FVETL:-99999} -local FSOTL=${FSOTL:+\'${FSOTL}\'}${FSOTL:-99999} -local FVMNL=${FvmnL:+\'${FvmnL}\'}${FvmnL:-99999} -local FVMXL=${FvmxL:+\'${FvmxL}\'}${FvmxL:-99999} -local FSLPL=${FSLPL:+\'${FSLPL}\'}${FSLPL:-99999} -local FABSL=${FABSL:+\'${FABSL}\'}${FABSL:-99999} -local FNTSFA="'${FNTSFA:-}'" - -#fv_grid_nml options - -#nam stochy options -local NEW_LSCALE=${new_lscale:-".false."} -local STOCHINI=${stochini:-".false."} -local SKEB=${SKEB:-0} -local ISEED_SKEB=${ISEED_SKEB:-${ISEED}} -local SKEB_TAU=${SKEB_TAU:-"-999."} -local SKEB_LSCALE=${SKEB_LSCALE:-"-999."} -local SKEBNORM=${SKEBNORM:-"1"} -local SKEB_NPASS=${SKEB_NPASS:-"30"} -local SKEB_VDOF=${SKEB_VDOF:-"5"} -local SKEBINT=${SKEBINT:-"0"} -local SHUM=${SHUM:-"-999."} -local ISEED_SHUM=${ISEED_SHUM:-${ISEED}} -local SHUM_TAU=${SHUM_TAU:-"-999."} -local SHUM_LSCALE=${SHUM_LSCALE:-"-999."} -local SHUMINT=${SHUMINT:-"0"} -local SPPT=${SPPT:-"-999."} -local ISEED_SPPT=${ISEED_SPPT:-${ISEED}} -local SPPT_TAU=${SPPT_TAU:-"-999."} -local SPPT_LSCALE=${SPPT_LSCALE:-"-999."} -local SPPT_LOGIT=${SPPT_LOGIT:-".true."} -local SPPT_SFCLIMIT=${SPPT_SFCLIMIT:-".true."} -local USE_ZMTNBLCK=${use_zmtnblck:-".true."} -local SPPTINT=${SPPTINT:-"0"} -local PBL_TAPER=${pbl_taper:-"0,0,0,0.125,0.25,0.5,0.75"} -local OCNSPPT=${OCNSPPT:-"0.8,0.4,0.2,0.08,0.04"} -local OCNSPPT_LSCALE=${OCNSPPT_LSCALE:-"500.E3,1000.E3,2000.E3,2000.E3,2000.E3"} -local OCNSPPT_TAU=${OCNSPPT_TAU:-"2.16E4,2.592E5,2.592E6,7.776E6,3.1536E7"} -local ISEED_OCNSPPT=${ISEED_OCNSPPT:-${ISEED}} -local EPBL=${EPBL:-"0.8,0.4,0.2,0.08,0.04"} -local EPBL_LSCALE=${EPBL_LSCALE:-"500.E3,1000.E3,2000.E3,2000.E3,2000.E3"} -local EPBL_TAU=${EPBL_TAU:-"2.16E4,2.592E5,2.592E6,7.776E6,3.1536E7"} -local ISEED_EPBL=${ISEED_EPBL:-${ISEED}} -local LNDP_TYPE=${lndp_type:-"0"} -local LNDP_MODEL_TYPE=${lndp_model_type:-"0"} -local LNDP_TAU=${LNDP_TAU:-"21600"} -local LNDP_LSCALE=${LNDP_SCALE:-"500000"} -local ISEED_LNDP=${ISEED_LNDP:-${ISEED}} -local LNDP_VAR_LIST=${lndp_var_list:-"'XXX'"} -local LNDP_PRT_LIST=${lndp_prt_list:-"-999"} - -local MOM6_OUTPUT_DIR=MOM6_OUTPUT/ -local MOM6_RESTART_SETTING=${MOM6_RESTART_SETTING:-'n'} -local MOM6_RESTART_DIR=MOM6_RESTART/ - -# Land IAU defaults -local DO_LAND_IAU=${DO_LAND_IAU:-".false."} -local LAND_IAU_FHRS=${IAUFHRS} -local LAND_IAU_DELHRS=${IAU_DELTHRS} -local LAND_IAU_INC_FILES="'sfc_inc',''" -local LSOIL_INCR=${LSOIL_INCR:-2} -local LAND_IAU_FILTER_INC=".false." -local LAND_IAU_UPD_STC=".true." -local LAND_IAU_UPD_SLC=".true." -local LAND_IAU_DO_STCSMC_ADJ=".true." -local LAND_IAU_MIN_T_INC=0.0001 -local LAND_IAU_MIN_SLC_INC=0.000001 - -# Check will need to be modified in the future -# once GW is ready to add in land IAU -if [[ "${DO_LAND_IAU}" = ".true." ]]; then - local HIDE_LIAU=" " -else - local HIDE_LIAU="!" -fi - -local global_template="${HOMEgfs}/parm/ufs/global_control.nml.IN" -atparse < "${global_template}" >> "input.nml" +FV3_namelists() { + + # setup the tables + DIAG_TABLE=${DIAG_TABLE:-${PARMgfs}/ufs/fv3/diag_table} + DIAG_TABLE_APPEND=${DIAG_TABLE_APPEND:-${PARMgfs}/ufs/fv3/diag_table_aod} + DATA_TABLE=${DATA_TABLE:-${PARMgfs}/ufs/MOM6_data_table.IN} + FIELD_TABLE=${FIELD_TABLE:-${PARMgfs}/ufs/fv3/field_table} + + # set cdmbgwd + if ((gwd_opt == 2)) && [[ ${do_gsl_drag_ls_bl} == ".true." ]]; then + cdmbgwd=${cdmbgwd_gsl} + fi + + # ensure non-prognostic tracers are set + dnats=${dnats:-0} + + # build the diag_table + { + echo "UFS_Weather_Model_Forecast" + if [[ "${DOIAU}" = "YES" ]]; then + echo "${previous_cycle:0:4} ${previous_cycle:4:2} ${previous_cycle:6:2} ${previous_cycle:8:2} 0 0" + else + echo "${current_cycle:0:4} ${current_cycle:4:2} ${current_cycle:6:2} ${current_cycle:8:2} 0 0" + fi + cat "${DIAG_TABLE}" + if [[ -n "${AERO_DIAG_TABLE:-}" ]]; then + cat "${AERO_DIAG_TABLE}" + fi + cat "${DIAG_TABLE_APPEND}" + } >> diag_table_template + + local template=diag_table_template + local SYEAR=${current_cycle:0:4} + local SMONTH=${current_cycle:4:2} + local SDAY=${current_cycle:6:2} + local CHOUR=${current_cycle:8:2} + local MOM6_OUTPUT_DIR="./MOM6_OUTPUT" + + atparse < "${template}" >> "diag_table" + + # copy data table + cpreq "${DATA_TABLE}" data_table + + # build field_table + if [[ -n "${AERO_FIELD_TABLE:-}" ]]; then + nrec=$(wc -l < "${FIELD_TABLE}") + prec=${nrec} + if ((dnats > 0)); then + # shellcheck disable=SC2312 + prec=$(grep -F -n TRACER "${FIELD_TABLE}" 2> /dev/null | tail -n "${dnats}" | head -1 | cut -d: -f1) + prec=${prec:-0} + prec=$((prec > 0 ? prec - 1 : prec)) + fi + { + head -n "${prec}" "${FIELD_TABLE}" + cat "${AERO_FIELD_TABLE}" + tail -n $((nrec - prec)) "${FIELD_TABLE}" + } > field_table + # add non-prognostic tracers from additional table + dnats=$((dnats + dnats_aero)) + else + cpreq "${FIELD_TABLE}" field_table + fi + + # Set variables for global_control.nml template + + local BLOCKSIZE=${blocksize} + local CHKSUM_DEBUG=${chksum_debug} + local DYCORE_ONLY=${dycore_only} + local CCPP_SUITE=${CCPP_SUITE} + + local MAX_OUTPUT_FIELDS=300 + + local DOMAINS_STACK_SIZE=${domains_stack_size:-3000000} + local PRINT_MEMORY_USAGE=${print_memory_usage:-".false."} + + local INPES=${layout_x} + local JNPES=${layout_y} + local IO_LAYOUT=${io_layout} + local NPX=${npx} + local NPY=${npy} + local NTILES=${ntiles} + local NPZ=${npz} + local DZ_MIN=${dz_min:-"6"} + local PSM_BC=${psm_bc:-"0"} + local MAKE_NH=${make_nh} + local FV_DEBUG=${fv_debug:-".false."} + local RANGE_WARN=${range_warn:-".true."} + local N_SPONGE=${n_sponge:-"10"} + local NUDGE_QV=${nudge_qv:-".false."} + local NUDGE_DZ=${nudge_dz:-".false."} + local TAU=${tau:-10.} + local FAST_TAU_W_SEC=${fast_tau_w_sec:-"0.2"} + local RF_CUTOFF=${rf_cutoff:-"7.5e2"} + local D2_BG_K1=${d2_bg_k1:-"0.15"} + local D2_BG_K2=${d2_bg_k2:-"0.02"} + local KORD_TM=${kord_tm:-"-9"} + local KORD_MT=${kord_mt:-"9"} + local KORD_WZ=${kord_wz:-"9"} + local KORD_TR=${kord_tr:-"9"} + local HYDROSTATIC=${hydrostatic} + local PHYS_HYDROSTATIC=${phys_hydrostatic} + local USE_HYDRO_PRESSURE=${use_hydro_pressure} + local UPDATE_FULL_OMEGA=${pass_full_omega_to_physics_in_non_hydrostatic_mode:-".false."} + local K_SPLIT=${k_split} + local N_SPLIT=${n_split} + local NWAT=${nwat:-2} + local NA_INIT=${na_init} + local DNATS=${dnats} + local FV_SG_ADJ=${fv_sg_adj:-"450"} + local NORD=${nord:-3} + local DDDMP=${dddmp:-0.1} + local D4_BG=${d4_bg:-0.15} + local VTDM4=${vtdm4} + local DELT_MAX=${delt_max:-"0.002"} + local DO_VORT_DAMP=${do_vort_damp} + local EXTERNAL_IC=${external_ic} + local EXTERNAL_ETA=${external_eta:-.true.} + local GFS_PHIL=${gfs_phil:-".false."} + local NGGPS_IC=${nggps_ic} + local MOUNTAIN=${mountain} + local NCEP_IC=${ncep_ic} + local D_CON=${d_con} + local HORD_MT=${hord_mt} + local HORD_VT=${hord_xx} + local HORD_TM=${hord_xx} + local HORD_DP=${hord_dp} + local HORD_TR=${hord_tr:-"8"} + local ADJUST_DRY_MASS=${adjust_dry_mass:-".true."} + local DRY_MASS=${dry_mass:-98320.0} + local CONSV_TE=${consv_te} + local DO_SAT_ADJ=${do_sat_adj:-".false."} + local PRINT_FREQ=${print_freq} + local WARM_START=${warm_start} + local NO_DYCORE=${no_dycore} + local AGRID_VEL_RST=${agrid_vel_rst:-".true."} + local READ_INCREMENT=${read_increment} + local RES_LATLON_DYNAMICS=${res_latlon_dynamics} + local ATM_IGNORE_RST_CKSUM=.false. + local INCREMENT_FILE_ON_NATIVE_GRID=${increment_file_on_native_grid:-.false.} + + local FILTERED_TERRAIN=${filtered_terrain} + local NPZP=${LEVS} #levp + local GFS_DWINDS=${gfs_dwinds} + + local FHZERO=${FHZERO:-6} + local H2O_PHYS=${h2o_phys:-".true."} + local LDIAG3D=${ldiag3d:-".false."} + local QDIAG3D=${qdiag3d:-".false."} + local PRINT_DIFF_PGR=${print_diff_pgr:-".false."} + local FHCYC=${FHCYC} + local USE_UFO=${use_ufo:-".true."} + local PRE_RAD=${pre_rad:-".false."} + local IMP_PHYSICS=${imp_physics:-"99"} + + local default_dt_inner=$((DELTIM / 2)) + local IOVR=${iovr:-"3"} + local LTAEROSOL=${ltaerosol:-".false."} + local MRAEROSOL=.false. + local LTHAILAWARE=.false. + local LRADAR=${lradar:-".true."} + local TTENDLIM=${ttendlim:-"-999"} + local DT_INNER=${dt_inner:-"${default_dt_inner}"} + local SEDI_SEMI=${sedi_semi:-".true."} + local DECFL=${decfl:-"10"} + local OZ_PHYS_NEW=${oz_phys:-".false."} + local OZ_PHYS_OLD=${oz_phys_2015:-".true."} + local LSOIL_LSM=${lsoil_lsm:-"4"} + local DO_MYNNEDMF=${do_mynnedmf:-".false."} + local DO_MYNNSFCLAY=${do_mynnsfclay:-".false."} + local ICLOUD_BL=${icloud_bl:-"1"} + local BL_MYNN_EDMF=${bl_mynn_edmf:-"1"} + local BL_MYNN_TKEADVECT=${bl_mynn_tkeadvect:-".true."} + local BL_MYNN_EDMF_MOM=${bl_mynn_edmf_mom:-"1"} + local TTE_EDMF=${tte_edmf:-".false."} + local CSCALE=${cscale:-"1.0"} + local DO_NGW_EC=${do_ngw_ec:-".false."} + local DO_UGWP=${do_ugwp:-".false."} + local DO_TOFD=${do_tofd:-".false."} + local GWD_OPT=${gwd_opt:-"2"} + local DO_UGWP_V0=${do_ugwp_v0:-".false."} + local DO_UGWP_V1=${do_ugwp_v1:-".true."} + local DO_UGWP_V0_OROG_ONLY=${do_ugwp_v0_orog_only:-".false."} + local DO_UGWP_V0_NST_ONLY=${do_ugwp_v0_nst_only:-".false."} + local DO_GSL_DRAG_LS_BL=${do_gsl_drag_ls_bl:-".true."} + local DO_GSL_DRAG_SS=${do_gsl_drag_ss:-".true."} + local DO_GSL_DRAG_TOFD=${do_gsl_drag_tofd:-".true."} + local DO_GWD_OPT_PSL=${do_gwd_opt_psl:-".false."} + local DO_UGWP_V1_OROG_ONLY=${do_ugwp_v1_orog_only:-".false."} + local MIN_LAKEICE=${min_lakeice:-"0.15"} + local MIN_SEAICE=${min_seaice:-"0.15"} + local USE_CICE_ALB=${use_cice_alb:-".false."} + + local PDFCLD=${pdfcld:-".false."} + local FHSWR=${FHSWR:-"3600."} + local FHLWR=${FHLWR:-"3600."} + local IALB=${IALB:-"1"} + local IEMS=${IEMS:-"1"} + local IAER=${IAER} + local ICLIQ_SW=${icliq_sw:-"2"} + local ICO2=${ICO2} + local ISUBC_SW=${isubc_sw:-"2"} + local ISUBC_LW=${isubc_lw:-"2"} + local ISOL=${ISOL:-"2"} + local LWHTR=${lwhtr:-".true."} + local SWHTR=${swhtr:-".true."} + local CNVGWD=${cnvgwd:-".true."} + local SHAL_CNV=${shal_cnv:-".true."} + local CAL_PRE=${cal_pre:-".true."} + local REDRAG=${redrag:-".true."} + local DSPHEAT=${dspheat:-".true."} + local HYBEDMF=${hybedmf:-".false."} + local SATMEDMF=${satmedmf:-".true."} + local ISATMEDMF=${isatmedmf:-"1"} + local LHEATSTRG=${lheatstrg:-".false."} + local LSEASPRAY=${lseaspray:-".true."} + local RANDOM_CLDS=${random_clds:-".true."} + local TRANS_TRAC=${trans_trac:-".true."} + local CNVCLD=${cnvcld:-".true."} + local XR_CNVCLD=${xr_cnvcld:-".true."} + local IMFSHALCNV=${imfshalcnv:-"2"} + local IMFDEEPCNV=${imfdeepcnv:-"2"} + local PROGSIGMA=${progsigma:-".true."} + local BETASCU=${betascu:-"8.0"} + local BETAMCU=${betamcu:-"1.0"} + local BETADCU=${betadcu:-"2.0"} + local RAS=${ras:-".false."} + local CDMBGWD=${cdmbgwd:-"3.5,0.25"} + local PSL_GWD_DX_FACTOR=${psl_gwd_dx_factor:-"6.0"} + local PRSLRD0=${prslrd0:-"0."} + local IVEGSRC=${ivegsrc:-"1"} + local ISOT=${isot:-"1"} + local LSOIL=${lsoil:-"4"} + local LSM=${lsm:-"2"} + local IOPT_DVEG=${iopt_dveg:-"1"} + local IOPT_CRS=${iopt_crs:-"1"} + local IOPT_BTR=${iopt_btr:-"1"} + local IOPT_RUN=${iopt_run:-"1"} + local IOPT_SFC=${iopt_sfc:-"1"} + local IOPT_TRS=${iopt_trs:-"2"} + local IOPT_DIAG=${iopt_diag:-"2"} + local IOPT_FRZ=${iopt_frz:-"1"} + local IOPT_INF=${iopt_inf:-"1"} + local IOPT_RAD=${iopt_rad:-"1"} + local IOPT_ALB=${iopt_alb:-"2"} + local IOPT_SNF=${iopt_snf:-"4"} + local IOPT_TBOT=${iopt_tbot:-"2"} + local IOPT_STC=${iopt_stc:-"1"} + local DEBUG=${gfs_phys_debug:-".false."} + local NSTF_NAME=${nstf_name} + local NST_ANL=${nst_anl} + local PSAUTCO=${psautco:-"0.0008,0.0005"} + local PRAUTCO=${prautco:-"0.00015,0.00015"} + local LGFDLMPRAD=${lgfdlmprad:-".false."} + local EFFR_IN=${effr_in:-".false."} + local LDIAG_UGWP=${ldiag_ugwp:-".false."} + local DO_RRTMGP=${do_RRTMGP:-".false."} + local ACTIVE_GASES=${active_gases:-"'h2o_co2_o3_n2o_ch4_o2'"} + local NGASES=${ngases:-"6"} + local LW_FILE_GAS=${lw_file_gas:-"'rrtmgp-data-lw-g128-210809.nc'"} + local LW_FILE_CLOUDS=${lw_file_clouds:-"'rrtmgp-cloud-optics-coeffs-lw.nc'"} + local SW_FILE_GAS=${sw_file_gas:-"'rrtmgp-data-sw-g112-210809.nc'"} + local SW_FILE_CLOUDS=${sw_file_clouds:-"'rrtmgp-cloud-optics-coeffs-sw.nc'"} + local RRTMGP_NGPTSSW=${rrtmgp_nGptsSW:-"112"} + local RRTMGP_NGPTSLW=${rrtmgp_nGptsLW:-"128"} + local RRTMGP_NBANDSLW=${rrtmgp_nBandsLW:-"16"} + local RRTMGP_NBANDSSW=${rrtmgp_nBandsSW:-"14"} + local DOGP_CLDOPTICS_LUT=${doGP_cldoptics_LUT:-".false."} + local DOGP_LWSCAT=${doGP_lwscat:-".false."} + local DOGP_SGS_CNV=.true. + + local DO_SPPT=${do_sppt:-".false."} + local DO_SHUM=${do_shum:-".false."} + local DO_SKEB=${do_skeb:-".false."} + local FRAC_GRID=${FRAC_GRID:-".true."} + local CPLCHM=${cplchm:-".false."} + local CPLFLX=${cplflx:-".false."} + local CPLICE=${cplice:-".false."} + local CPLWAV=${cplwav:-".false."} + local CPLWAV2ATM=${cplwav2atm:-".false."} + local USE_MED_FLUX=${use_med_flux:-".false."} + local CPLLND=${cpllnd:-".false."} + local CPLLND2ATM=${cpllnd2atm:-".false."} + local USE_OCEANUV=${use_oceanuv:-".false."} + + # CPL CHM options + if [[ "${cplchm}" = ".true." ]]; then + local FSCAV_AERO=${fscav_aero:-'*:0.0'} + else + local FSCAV_AERO='"*:0.3","so2:0.0","msa:0.0","dms:0.0","nh3:0.4","nh4:0.6","bc1:0.6","bc2:0.6","oc1:0.4","oc2:0.4","dust1:0.6","dust2:0.6","dust3:0.6","dust4:0.6","dust5:0.6","seas1:0.5","seas2:0.5","seas3:0.5","seas4:0.5","seas5:0.5"' + fi + + local IAUFHRS=${IAUFHRS} + local IAU_DELTHRS=${IAU_DELTHRS} + local IAU_INC_FILES=${IAU_INC_FILES:-"''"} + local IAU_DRYMASSFIXER=.false. + local IAU_FILTER_INCREMENTS=${IAU_FILTER_INCREMENTS:-".false."} + + # CA options + local DO_CA=".true." + local CA_GLOBAL=${ca_global:-".false."} + local CA_SGS=${ca_sgs:-".true."} + local NCA=${nca:-"1"} + local NCELLS=${ncells:-"5"} + local NLIVES=${nlives:-"12"} + local NSEED=${nseed:-"1"} + local NFRACSEED=${nfracseed:-"0.5"} + local NTHRESH=${nthresh:-"18"} + local CA_TRIGGER=${ca_trigger:-".true."} + local NSPINUP=${nspinup:-"1"} + local ISEED_CA=${ISEED_CA:-"12345"} + + # Land pert options + local LNDP_TYPE=${lndp_type:-2} + local N_VAR_LNDP=${n_var_lndp:-0} + + local LCNORM=${lcnorm:-".false."} + local PERT_MP=${PERT_MP:-".false."} + local PERT_RADTEND=${PERT_RADTEND:-".false."} + local PERT_CLDS=${PERT_CLDS:-".false."} + + if [[ "${DO_SPPT}" = ".true." ]]; then + local PERT_CLDS=".true." + fi + + if [[ "${DOIAU}" = "YES" ]]; then + local HIDE_AIAU=" " + else + local HIDE_AIAU="!" + fi + + #GWP options + if [[ "${knob_ugwp_version}" -eq 0 ]]; then + local HIDE_UGWPV0=" " + local HIDE_UGWPV1="!" + elif [[ "${knob_ugwp_version}" -eq 1 ]]; then + local HIDE_UGWPV0="!" + local HIDE_UGWPV1=" " + else + local HIDE_UGWPV0="!" + local HIDE_UGWPV1="!" + fi + + # Common GWP options + local KNOB_UGWP_SOLVER=${knob_ugwp_solver:-2} + local KNOB_UGWP_SOURCE=${knob_ugwp_source:-1,1,0,0} + local KNOB_UGWP_WVSPEC=${knob_ugwp_wvspec:-1,25,25,25} + local KNOB_UGWP_AZDIR=${knob_ugwp_azdir:-2,4,4,4} + local KNOB_UGWP_STOCH=${knob_ugwp_stoch:-0,0,0,0} + local KNOB_UGWP_EFFAC=${knob_ugwp_effac:-1,1,1,1} + local KNOB_UGWP_DOAXYZ=${knob_ugwp_doaxyz:-1} + local KNOB_UGWP_DOHEAT=${knob_ugwp_doheat:-1} + # UGWP Version 0 options + local KNOB_UGWP_DOKDIS=${knob_ugwp_dokdis:-1} + local KNOB_UGWP_NDX4LH=${knob_ugwp_ndx4lh:-1} + local KNOB_UGWP_VERSION=${knob_ugwp_version:-0} + local LAUNCH_LEVEL=${launch_level:-54} + # UGWP Version 1 options + local KNOB_UGWP_DOKDIS=${knob_ugwp_dokdis:-2} + local KNOB_UGWP_NDX4LH=${knob_ugwp_ndx4lh:-4} + local KNOB_UGWP_VERSION=${knob_ugwp_version:-1} + local KNOB_UGWP_PALAUNCH=${knob_ugwp_palaunch:-275.0e2} + local KNOB_UGWP_NSLOPE=${knob_ugwp_nslope:-1} + local KNOB_UGWP_LZMAX=${knob_ugwp_lzmax:-15.750e3} + local KNOB_UGWP_LZMIN=${knob_ugwp_lzmin:-0.75e3} + local KNOB_UGWP_LZSTAR=${knob_ugwp_lzstar:-2.0e3} + local KNOB_UGWP_TAUMIN=${knob_ugwp_taumin:-0.25e-3} + local KNOB_UGWP_TAUAMP=${knob_ugwp_tauamp:-3.0e-3} + local KNOB_UGWP_LHMET=${knob_ugwp_lhmet:-200.0e3} + local KNOB_UGWP_OROSOLV=${knob_ugwp_orosolv:-\'pss-1986\'} + + # gfdl_cloud_microphysics options + local REIFLAG=${reiflag:-"2"} + + # interpolator_nml options + + # nam sfc options + local FNGLAC="'${FNGLAC}'" + local FNMXIC="'${FNMXIC}'" + local FNTSFC="'${FNTSFC}'" + local FNSNOC="'${FNSNOC}'" + local FNZORC="'${FNZORC}'" + local FNALBC="'${FNALBC}'" + local FNALBC2="'${FNALBC2}'" + local FNAISC="'${FNAISC}'" + local FNTG3C="'${FNTG3C}'" + local FNVEGC="'${FNVEGC}'" + local FNVETC="'${FNVETC}'" + local FNSOTC="'${FNSOTC}'" + local FNSOCC="'${FNSOCC}'" + local FNSMCC="'${FNSMCC}'" + local FNMSKH="'${FNMSKH}'" + local FNTSFA="'${FNTSFA}'" + local FNACNA="'${FNACNA:-}'" + local FNSNOA="'${FNSNOA:-}'" + local FNVMNC="'${FNVMNC:-}'" + local FNVMXC="'${FNVMXC:-}'" + local FNSLPC="'${FNSLPC:-}'" + local FNABSC="'${FNABSC:-}'" + local LDEBUG=${LDEBUG:-".false."} + local FSMCL2=${FSMCL2:+\'${FSMCL2}\'}${FSMCL2:-99999} + local FSMCL3=${FSMCL3:+\'${FSMCL3}\'}${FSMCL3:-99999} + local FSMCL4=${FSMCL4:+\'${FSMCL4}\'}${FSMCL4:-99999} + local LANDICE=${landice:-".true."} + local FTSFS=${FTSFS:-90} + local FAISL=${FAISL:+\'${FAISL}\'}${FAISL:-99999} + local FAISS=${FAISS:+\'${FAISS}\'}${FAISS:-99999} + local FSNOL=${FSNOL:+\'${FSNOL}\'}${FSNOL:-99999} + local FSNOS=${FSNOS:+\'${FSNOS}\'}${FSNOS:-99999} + local FSICL=${FSICL:-99999} + local FSICS=${FSICS:-99999} + local FTSFL=${FTSFL:+\'${FTSFL}\'}${FTSFL:-99999} + local FVETL=${FVETL:+\'${FVETL}\'}${FVETL:-99999} + local FSOTL=${FSOTL:+\'${FSOTL}\'}${FSOTL:-99999} + local FVMNL=${FvmnL:+\'${FvmnL}\'}${FvmnL:-99999} + local FVMXL=${FvmxL:+\'${FvmxL}\'}${FvmxL:-99999} + local FSLPL=${FSLPL:+\'${FSLPL}\'}${FSLPL:-99999} + local FABSL=${FABSL:+\'${FABSL}\'}${FABSL:-99999} + local FNTSFA="'${FNTSFA:-}'" + + #fv_grid_nml options + + #nam stochy options + local NEW_LSCALE=${new_lscale:-".false."} + local STOCHINI=${stochini:-".false."} + local SKEB=${SKEB:-0} + local ISEED_SKEB=${ISEED_SKEB:-${ISEED}} + local SKEB_TAU=${SKEB_TAU:-"-999."} + local SKEB_LSCALE=${SKEB_LSCALE:-"-999."} + local SKEBNORM=${SKEBNORM:-"1"} + local SKEB_NPASS=${SKEB_NPASS:-"30"} + local SKEB_VDOF=${SKEB_VDOF:-"5"} + local SKEBINT=${SKEBINT:-"0"} + local SHUM=${SHUM:-"-999."} + local ISEED_SHUM=${ISEED_SHUM:-${ISEED}} + local SHUM_TAU=${SHUM_TAU:-"-999."} + local SHUM_LSCALE=${SHUM_LSCALE:-"-999."} + local SHUMINT=${SHUMINT:-"0"} + local SPPT=${SPPT:-"-999."} + local ISEED_SPPT=${ISEED_SPPT:-${ISEED}} + local SPPT_TAU=${SPPT_TAU:-"-999."} + local SPPT_LSCALE=${SPPT_LSCALE:-"-999."} + local SPPT_LOGIT=${SPPT_LOGIT:-".true."} + local SPPT_SFCLIMIT=${SPPT_SFCLIMIT:-".true."} + local USE_ZMTNBLCK=${use_zmtnblck:-".true."} + local SPPTINT=${SPPTINT:-"0"} + local PBL_TAPER=${pbl_taper:-"0,0,0,0.125,0.25,0.5,0.75"} + local OCNSPPT=${OCNSPPT:-"0.8,0.4,0.2,0.08,0.04"} + local OCNSPPT_LSCALE=${OCNSPPT_LSCALE:-"500.E3,1000.E3,2000.E3,2000.E3,2000.E3"} + local OCNSPPT_TAU=${OCNSPPT_TAU:-"2.16E4,2.592E5,2.592E6,7.776E6,3.1536E7"} + local ISEED_OCNSPPT=${ISEED_OCNSPPT:-${ISEED}} + local EPBL=${EPBL:-"0.8,0.4,0.2,0.08,0.04"} + local EPBL_LSCALE=${EPBL_LSCALE:-"500.E3,1000.E3,2000.E3,2000.E3,2000.E3"} + local EPBL_TAU=${EPBL_TAU:-"2.16E4,2.592E5,2.592E6,7.776E6,3.1536E7"} + local ISEED_EPBL=${ISEED_EPBL:-${ISEED}} + local LNDP_TYPE=${lndp_type:-"0"} + local LNDP_MODEL_TYPE=${lndp_model_type:-"0"} + local LNDP_TAU=${LNDP_TAU:-"21600"} + local LNDP_LSCALE=${LNDP_SCALE:-"500000"} + local ISEED_LNDP=${ISEED_LNDP:-${ISEED}} + local LNDP_VAR_LIST=${lndp_var_list:-"'XXX'"} + local LNDP_PRT_LIST=${lndp_prt_list:-"-999"} + + local MOM6_OUTPUT_DIR=MOM6_OUTPUT/ + local MOM6_RESTART_SETTING=${MOM6_RESTART_SETTING:-'n'} + local MOM6_RESTART_DIR=MOM6_RESTART/ + + # Land IAU defaults + local DO_LAND_IAU=${DO_LAND_IAU:-".false."} + local LAND_IAU_FHRS=${IAUFHRS} + local LAND_IAU_DELHRS=${IAU_DELTHRS} + local LAND_IAU_INC_FILES="'sfc_inc',''" + local LSOIL_INCR=${LSOIL_INCR:-2} + local LAND_IAU_FILTER_INC=".false." + local LAND_IAU_UPD_STC=".true." + local LAND_IAU_UPD_SLC=".true." + local LAND_IAU_DO_STCSMC_ADJ=".true." + local LAND_IAU_MIN_T_INC=0.0001 + local LAND_IAU_MIN_SLC_INC=0.000001 + + # Check will need to be modified in the future + # once GW is ready to add in land IAU + if [[ "${DO_LAND_IAU}" = ".true." ]]; then + local HIDE_LIAU=" " + else + local HIDE_LIAU="!" + fi + + local global_template="${HOMEgfs}/parm/ufs/global_control.nml.IN" + atparse < "${global_template}" >> "input.nml" } diff --git a/ush/parsing_namelists_FV3_nest.sh b/ush/parsing_namelists_FV3_nest.sh index 325021e7c38..89e16efca30 100755 --- a/ush/parsing_namelists_FV3_nest.sh +++ b/ush/parsing_namelists_FV3_nest.sh @@ -5,105 +5,104 @@ # Disable variable not used warnings and 'masking return value' warnings # shellcheck disable=SC2034 # shellcheck disable=SC2312 -FV3_namelists_nest(){ - -# First argument tells us which namelist we're writing: -# global = writing input.nml for running global with a nest -# nest = writing input_nest02.nml for running the nest -namelist_mode="${1:-global}" - -if [[ "${namelist_mode}" == "nest" ]] ; then - nml_file=input_nest02.nml - only_input_nml="YES" -else - nml_file=input.nml - only_input_nml="NO" -fi - -# setup the tables -DIAG_TABLE=${DIAG_TABLE:-${PARMgfs}/ufs/fv3/diag_table} -DIAG_TABLE_APPEND=${DIAG_TABLE_APPEND:-${PARMgfs}/ufs/fv3/diag_table_aod} -DATA_TABLE=${DATA_TABLE:-${PARMgfs}/ufs/MOM6_data_table.IN} -FIELD_TABLE=${FIELD_TABLE:-${PARMgfs}/ufs/fv3/field_table} - -# set cdmbgwd -if (( gwd_opt == 2 )) && [[ ${do_gsl_drag_ls_bl} == ".true." ]]; then - cdmbgwd=${cdmbgwd_gsl} -fi - -# ensure non-prognostic tracers are set -dnats=${dnats:-0} - -if [[ "${only_input_nml:-NO}" == "NO" ]] ; then -# build the diag_table -{ -echo "UFS_Weather_Model_Forecast" -if [[ "${DOIAU}" = "YES" ]]; then - echo "${previous_cycle:0:4} ${previous_cycle:4:2} ${previous_cycle:6:2} ${previous_cycle:8:2} 0 0" -else - echo "${current_cycle:0:4} ${current_cycle:4:2} ${current_cycle:6:2} ${current_cycle:8:2} 0 0" -fi -cat "${DIAG_TABLE}" -if [[ -n "${AERO_DIAG_TABLE:-}" ]]; then - cat "${AERO_DIAG_TABLE}" -fi -cat "${DIAG_TABLE_APPEND}" -} >> diag_table_template - -local template=diag_table_template -local SYEAR=${current_cycle:0:4} -local SMONTH=${current_cycle:4:2} -local SDAY=${current_cycle:6:2} -local CHOUR=${current_cycle:8:2} -local MOM6_OUTPUT_DIR="./MOM6_OUTPUT" - -atparse < "${template}" >> "diag_table" - - -# copy data table -cpreq "${DATA_TABLE}" data_table - -# build field_table -if [[ -n "${AERO_FIELD_TABLE:-}" ]]; then - nrec=$(wc -l < "${FIELD_TABLE}") - prec=${nrec} - if (( dnats > 0 )); then - prec=$( grep -F -n TRACER "${FIELD_TABLE}" 2> /dev/null | tail -n "${dnats}" | head -1 | cut -d: -f1 ) - prec=${prec:-0} - prec=$(( prec > 0 ? prec - 1 : prec )) - fi - { \ - head -n "${prec}" "${FIELD_TABLE}" ; \ - cat "${AERO_FIELD_TABLE}" ; \ - tail -n $(( nrec - prec )) "${FIELD_TABLE}" ; \ - } > field_table - # add non-prognostic tracers from additional table - dnats=$(( dnats + dnats_aero )) -else - cpreq "${FIELD_TABLE}" field_table -fi -fi # only_input_nml - -if [[ "${namelist_mode}" == "global" ]] ; then - layout_x_here=${layout_x} - layout_y_here=${layout_y} - ntiles_here=6 - npx_here=${npx} - npy_here=${npy} - k_split_here=${k_split} -else - layout_x_here=${layout_x_nest} - layout_y_here=${layout_y_nest} - ntiles_here=1 - nested_here=.true. - twowaynest_here=${twowaynest:-.true.} - nestupdate_here=${nestupdate:-7} - npx_here=${npx_nest} - npy_here=${npy_nest} - k_split_here=${k_split_nest} -fi - -cat > "${nml_file}" <> diag_table_template + + local template=diag_table_template + local SYEAR=${current_cycle:0:4} + local SMONTH=${current_cycle:4:2} + local SDAY=${current_cycle:6:2} + local CHOUR=${current_cycle:8:2} + local MOM6_OUTPUT_DIR="./MOM6_OUTPUT" + + atparse < "${template}" >> "diag_table" + + # copy data table + cpreq "${DATA_TABLE}" data_table + + # build field_table + if [[ -n "${AERO_FIELD_TABLE:-}" ]]; then + nrec=$(wc -l < "${FIELD_TABLE}") + prec=${nrec} + if ((dnats > 0)); then + prec=$(grep -F -n TRACER "${FIELD_TABLE}" 2> /dev/null | tail -n "${dnats}" | head -1 | cut -d: -f1) + prec=${prec:-0} + prec=$((prec > 0 ? prec - 1 : prec)) + fi + { + head -n "${prec}" "${FIELD_TABLE}" + cat "${AERO_FIELD_TABLE}" + tail -n $((nrec - prec)) "${FIELD_TABLE}" + } > field_table + # add non-prognostic tracers from additional table + dnats=$((dnats + dnats_aero)) + else + cpreq "${FIELD_TABLE}" field_table + fi + fi # only_input_nml + + if [[ "${namelist_mode}" == "global" ]]; then + layout_x_here=${layout_x} + layout_y_here=${layout_y} + ntiles_here=6 + npx_here=${npx} + npy_here=${npy} + k_split_here=${k_split} + else + layout_x_here=${layout_x_nest} + layout_y_here=${layout_y_nest} + ntiles_here=1 + nested_here=.true. + twowaynest_here=${twowaynest:-.true.} + nestupdate_here=${nestupdate:-7} + npx_here=${npx_nest} + npy_here=${npy_nest} + k_split_here=${k_split_nest} + fi + + cat > "${nml_file}" << EOF &atmos_model_nml blocksize = ${blocksize} chksum_debug = ${chksum_debug} @@ -209,24 +208,24 @@ cat > "${nml_file}" <> "${nml_file}" <> "${nml_file}" << EOF do_schmidt = .true. target_lat = ${TARGET_LAT} target_lon = ${TARGET_LON} stretch_fac = ${stretch_fac} EOF -fi + fi -if [[ "${DO_NEST:-NO}" == "YES" && "${namelist_mode}" == "nest" ]] ; then - cat >> "${nml_file}" <> "${nml_file}" << EOF nested = .true. twowaynest = ${twowaynest:-.true.} ! .true. nestupdate = 7 EOF -fi + fi -cat >> "${nml_file}" <> "${nml_file}" << EOF / &external_ic_nml @@ -250,15 +249,15 @@ cat >> "${nml_file}" <> "${nml_file}" << EOF + case "${CCPP_SUITE:-}" in + "FV3_GFS_v15p2_coupled") + cat >> "${nml_file}" << EOF oz_phys = .false. oz_phys_2015 = .true. EOF - ;; - "FV3_GSD_v0") - cat >> "${nml_file}" << EOF + ;; + "FV3_GSD_v0") + cat >> "${nml_file}" << EOF iovr = ${iovr:-"3"} ltaerosol = ${ltaerosol:-".false."} lradar = ${lradar:-".false."} @@ -276,9 +275,9 @@ EOF min_seaice = ${min_seaice:-"0.15"} use_cice_alb = ${use_cice_alb:-".false."} EOF - ;; - FV3_GFS_v16_coupled*) - cat >> "${nml_file}" << EOF + ;; + FV3_GFS_v16_coupled*) + cat >> "${nml_file}" << EOF iovr = ${iovr:-"3"} ltaerosol = ${ltaerosol:-".false."} lradar = ${lradar:-".false."} @@ -294,9 +293,9 @@ EOF min_lakeice = ${min_lakeice:-"0.15"} min_seaice = ${min_seaice:-"0.15"} EOF - ;; - FV3_GFS_v16*) - cat >> "${nml_file}" << EOF + ;; + FV3_GFS_v16*) + cat >> "${nml_file}" << EOF iovr = ${iovr:-"3"} ltaerosol = ${ltaerosol:-".false."} lradar = ${lradar:-".false."} @@ -313,10 +312,10 @@ EOF min_lakeice = ${min_lakeice:-"0.15"} min_seaice = ${min_seaice:-"0.15"} EOF - ;; - FV3_GFS_v17*) - local default_dt_inner=$(( DELTIM/2 )) - cat >> "${nml_file}" << EOF + ;; + FV3_GFS_v17*) + local default_dt_inner=$((DELTIM / 2)) + cat >> "${nml_file}" << EOF iovr = ${iovr:-"3"} ltaerosol = ${ltaerosol:-".false."} lradar = ${lradar:-".true."} @@ -349,10 +348,10 @@ EOF min_seaice = ${min_seaice:-"0.15"} use_cice_alb = ${use_cice_alb:-".false."} EOF - ;; - FV3_global_nest*) - local default_dt_inner=$(( DELTIM/2 )) - cat >> "${nml_file}" << EOF + ;; + FV3_global_nest*) + local default_dt_inner=$((DELTIM / 2)) + cat >> "${nml_file}" << EOF iovr = ${iovr:-"3"} lcnorm = ${lcnorm:-".false."} ltaerosol = ${ltaerosol:-".false."} @@ -385,15 +384,15 @@ EOF min_seaice = ${min_seaice:-"0.15"} use_cice_alb = ${use_cice_alb:-".false."} EOF - ;; - *) - cat >> "${nml_file}" << EOF + ;; + *) + cat >> "${nml_file}" << EOF iovr = ${iovr:-"3"} EOF - ;; -esac + ;; + esac -cat >> "${nml_file}" <> "${nml_file}" << EOF pdfcld = ${pdfcld:-".false."} fhswr = ${FHSWR:-"3600."} fhlwr = ${FHLWR:-"3600."} @@ -471,13 +470,13 @@ cat >> "${nml_file}" <> "${nml_file}" << EOF + if [[ ${cplchm} = ".true." ]]; then + cat >> "${nml_file}" << EOF fscav_aero = ${fscav_aero:-'*:0.0'} EOF -fi + fi -cat >> "${nml_file}" <> "${nml_file}" << EOF do_sppt = ${do_sppt:-".false."} do_shum = ${do_shum:-".false."} do_skeb = ${do_skeb:-".false."} @@ -489,27 +488,27 @@ cat >> "${nml_file}" <> "${nml_file}" <> "${nml_file}" << EOF pert_mp = .false. pert_radtend = .false. pert_clds = .true. EOF -fi + fi -# Add namelist for IAU -if [[ ${DOIAU} = "YES" ]]; then - cat >> "${nml_file}" << EOF + # Add namelist for IAU + if [[ ${DOIAU} = "YES" ]]; then + cat >> "${nml_file}" << EOF iaufhrs = ${IAUFHRS} iau_delthrs = ${IAU_DELTHRS} iau_inc_files= ${IAU_INC_FILES} iau_drymassfixer = .false. iau_filter_increments = ${IAU_FILTER_INCREMENTS:-".false."} EOF -fi + fi -if [[ ${DO_CA:-"NO"} = "YES" ]]; then - cat >> "${nml_file}" << EOF + if [[ ${DO_CA:-"NO"} = "YES" ]]; then + cat >> "${nml_file}" << EOF do_ca = .true. ca_global = ${ca_global:-".false."} ca_sgs = ${ca_sgs:-".true."} @@ -523,24 +522,24 @@ if [[ ${DO_CA:-"NO"} = "YES" ]]; then nspinup = ${nspinup:-"1"} iseed_ca = ${ISEED_CA:-"12345"} EOF -fi + fi -if [[ "${DO_LAND_PERT:-NO}" == "YES" ]]; then - cat >> "${nml_file}" << EOF + if [[ "${DO_LAND_PERT:-NO}" == "YES" ]]; then + cat >> "${nml_file}" << EOF lndp_type = ${lndp_type:-2} n_var_lndp = ${n_var_lndp:-0} EOF -fi + fi -# Close &gfs_physics_nml section -cat >> "${nml_file}" << EOF + # Close &gfs_physics_nml section + cat >> "${nml_file}" << EOF / EOF -if [[ "${namelist_mode}" == "global" ]] ; then - cat >> "${nml_file}" << EOF + if [[ "${namelist_mode}" == "global" ]]; then + cat >> "${nml_file}" << EOF &fv_nest_nml - grid_pes = $(( layout_x * layout_y * 6 )),$(( layout_x_nest * layout_y_nest )) + grid_pes = $((layout_x * layout_y * 6)),$((layout_x_nest * layout_y_nest)) tile_coarse = 0,6 num_tile_top = 6 p_split = 1 @@ -549,10 +548,10 @@ if [[ "${namelist_mode}" == "global" ]] ; then nest_joffsets = 0,${nest_joffset} / EOF -fi + fi -if [[ ${knob_ugwp_version} -eq 0 ]]; then - cat >> "${nml_file}" << EOF + if [[ ${knob_ugwp_version} -eq 0 ]]; then + cat >> "${nml_file}" << EOF &cires_ugwp_nml knob_ugwp_solver = ${knob_ugwp_solver:-2} knob_ugwp_source = ${knob_ugwp_source:-1,1,0,0} @@ -568,10 +567,10 @@ if [[ ${knob_ugwp_version} -eq 0 ]]; then launch_level = ${launch_level:-54} / EOF -fi + fi -if [[ ${knob_ugwp_version} -eq 1 ]]; then - cat >> "${nml_file}" << EOF + if [[ ${knob_ugwp_version} -eq 1 ]]; then + cat >> "${nml_file}" << EOF &cires_ugwp_nml knob_ugwp_solver = ${knob_ugwp_solver:-2} knob_ugwp_source = ${knob_ugwp_source:-1,1,0,0} @@ -595,11 +594,11 @@ if [[ ${knob_ugwp_version} -eq 1 ]]; then knob_ugwp_orosolv = ${knob_ugwp_orosolv:-'pss-1986'} / EOF -fi + fi -echo "" >> "${nml_file}" + echo "" >> "${nml_file}" -cat >> "${nml_file}" <> "${nml_file}" << EOF &gfdl_cloud_microphysics_nml sedi_transport = .true. do_sedi_heat = .false. @@ -704,28 +703,28 @@ cat >> "${nml_file}" <> "${nml_file}" <> "${nml_file}" << EOF grid_file = 'INPUT/grid_spec.nc' EOF -fi + fi -cat >> "${nml_file}" <> "${nml_file}" << EOF ${fv_grid_nml:-} / EOF -# Add namelist for stochastic physics options -echo "" >> "${nml_file}" -#if [ $MEMBER -gt 0 ]; then -if [[ "${DO_SPPT}" = "YES" || "${DO_SHUM}" = "YES" || "${DO_SKEB}" = "YES" || "${DO_LAND_PERT}" = "YES" ]]; then + # Add namelist for stochastic physics options + echo "" >> "${nml_file}" + #if [[ $MEMBER -gt 0 ]]; then + if [[ "${DO_SPPT}" = "YES" || "${DO_SHUM}" = "YES" || "${DO_SKEB}" = "YES" || "${DO_LAND_PERT}" = "YES" ]]; then - cat >> "${nml_file}" << EOF + cat >> "${nml_file}" << EOF &nam_stochy EOF - if [[ ${DO_SKEB} = "YES" ]]; then - cat >> "${nml_file}" << EOF + if [[ ${DO_SKEB} = "YES" ]]; then + cat >> "${nml_file}" << EOF skeb = ${SKEB} iseed_skeb = ${ISEED_SKEB:-${ISEED}} skeb_tau = ${SKEB_TAU:-"-999."} @@ -734,19 +733,19 @@ EOF skeb_npass = ${SKEB_NPASS:-"30"} skeb_vdof = ${SKEB_VDOF:-"5"} EOF - fi + fi - if [[ ${DO_SHUM} = "YES" ]]; then - cat >> "${nml_file}" << EOF + if [[ ${DO_SHUM} = "YES" ]]; then + cat >> "${nml_file}" << EOF shum = ${SHUM} iseed_shum = ${ISEED_SHUM:-${ISEED}} shum_tau = ${SHUM_TAU:-"-999."} shum_lscale = ${SHUM_LSCALE:-"-999."} EOF - fi + fi - if [[ ${DO_SPPT} = "YES" ]]; then - cat >> "${nml_file}" << EOF + if [[ ${DO_SPPT} = "YES" ]]; then + cat >> "${nml_file}" << EOF sppt = ${SPPT} iseed_sppt = ${ISEED_SPPT:-${ISEED}} sppt_tau = ${SPPT_TAU:-"-999."} @@ -756,50 +755,50 @@ EOF use_zmtnblck = ${use_zmtnblck:-".true."} pbl_taper = ${pbl_taper:-"0,0,0,0.125,0.25,0.5,0.75"} EOF - fi + fi - if [[ "${DO_OCN_SPPT:-NO}" == "YES" ]]; then - cat >> "${nml_file}" <> "${nml_file}" << EOF OCNSPPT=${OCNSPPT} OCNSPPT_LSCALE=${OCNSPPT_LSCALE} OCNSPPT_TAU=${OCNSPPT_TAU} ISEED_OCNSPPT=${ISEED_OCNSPPT:-${ISEED}} EOF - fi + fi - if [[ "${DO_OCN_PERT_EPBL:-NO}" == "YES" ]]; then - cat >> "${nml_file}" <> "${nml_file}" << EOF EPBL=${EPBL} EPBL_LSCALE=${EPBL_LSCALE} EPBL_TAU=${EPBL_TAU} ISEED_EPBL=${ISEED_EPBL:-${ISEED}} EOF - fi + fi - if [[ "${DO_OCN_SPPT:-NO}" == "YES" ]]; then - cat >> "${nml_file}" <> "${nml_file}" << EOF OCNSPPT=${OCNSPPT} OCNSPPT_LSCALE=${OCNSPPT_LSCALE} OCNSPPT_TAU=${OCNSPPT_TAU} ISEED_OCNSPPT=${ISEED_OCNSPPT:-${ISEED}} EOF - fi + fi - if [[ "${DO_OCN_PERT_EPBL:-NO}" == "YES" ]]; then - cat >> "${nml_file}" <> "${nml_file}" << EOF EPBL=${EPBL} EPBL_LSCALE=${EPBL_LSCALE} EPBL_TAU=${EPBL_TAU} ISEED_EPBL=${ISEED_EPBL:-${ISEED}} EOF - fi + fi - cat >> "${nml_file}" << EOF + cat >> "${nml_file}" << EOF / EOF - if [[ ${DO_LAND_PERT} = "YES" ]]; then - cat >> "${nml_file}" << EOF + if [[ ${DO_LAND_PERT} = "YES" ]]; then + cat >> "${nml_file}" << EOF &nam_sfcperts lndp_type = ${lndp_type} LNDP_TAU = ${LNDP_TAU} @@ -809,27 +808,27 @@ EOF lndp_prt_list = ${lndp_prt_list} / EOF - else - cat >> "${nml_file}" << EOF + else + cat >> "${nml_file}" << EOF &nam_sfcperts / EOF - fi + fi -else + else - cat >> "${nml_file}" << EOF + cat >> "${nml_file}" << EOF &nam_stochy / &nam_sfcperts / EOF -fi + fi -# Echo out formatted ""${nml_file}"" -echo "====================================" -echo "FV3_namelists_nest(): '${nml_file}'" -cat "${nml_file}" -echo "====================================" + # Echo out formatted ""${nml_file}"" + echo "====================================" + echo "FV3_namelists_nest(): '${nml_file}'" + cat "${nml_file}" + echo "====================================" } diff --git a/ush/parsing_namelists_GOCART.sh b/ush/parsing_namelists_GOCART.sh index 2a08a90b0bc..26399356407 100755 --- a/ush/parsing_namelists_GOCART.sh +++ b/ush/parsing_namelists_GOCART.sh @@ -3,52 +3,52 @@ # Disable variable not used warnings # shellcheck disable=SC2034 GOCART_namelists() { - # copying GOCART configuration files - if [[ -n "${AERO_CONFIG_DIR}" ]]; then + # copying GOCART configuration files + if [[ -n "${AERO_CONFIG_DIR}" ]]; then - local base_in - local fhout_aero_padded - fhout_aero_padded=$(printf "%02d" "${FHOUT_AERO}") - # Only instantaneous AOD is output right now - local inst_aod_freq="${fhout_aero_padded}0000" + local base_in + local fhout_aero_padded + fhout_aero_padded=$(printf "%02d" "${FHOUT_AERO}") + # Only instantaneous AOD is output right now + local inst_aod_freq="${fhout_aero_padded}0000" - # Other gocart fields not currently used - local inst_du_ss_freq="120000" - local tavg_du_ss_freq="120000" - local inst_ca_freq="120000" - local inst_ni_freq="120000" - local inst_su_freq="120000" - local inst_du_bin_freq="010000" - local tavg_du_bin_freq="030000" - local inst_ss_bin_freq="060000" - local inst_ca_bin_freq="120000" - local inst_ni_bin_freq="120000" - local inst_su_bin_freq="120000" - local inst_2d_freq="030000" - local inst_3d_freq="060000" - local tavg_2d_rad_freq="120000" - local tavg_3d_rad_freq="120000" + # Other gocart fields not currently used + local inst_du_ss_freq="120000" + local tavg_du_ss_freq="120000" + local inst_ca_freq="120000" + local inst_ni_freq="120000" + local inst_su_freq="120000" + local inst_du_bin_freq="010000" + local tavg_du_bin_freq="030000" + local inst_ss_bin_freq="060000" + local inst_ca_bin_freq="120000" + local inst_ni_bin_freq="120000" + local inst_su_bin_freq="120000" + local inst_2d_freq="030000" + local inst_3d_freq="060000" + local tavg_2d_rad_freq="120000" + local tavg_3d_rad_freq="120000" - for template_in in "${AERO_CONFIG_DIR}/"*.rc; do - base_in="$(basename "${template_in}")" - atparse < "${template_in}" >> "${DATA}/${base_in}" - status=$? - if [[ ${status} -ne 0 ]]; then - exit "${status}" - fi - done + for template_in in "${AERO_CONFIG_DIR}/"*.rc; do + base_in="$(basename "${template_in}")" + atparse < "${template_in}" >> "${DATA}/${base_in}" + status=$? + if [[ ${status} -ne 0 ]]; then + exit "${status}" + fi + done - # attempt to generate ExtData configuration file if not provided - if [[ ! -f "${DATA}/AERO_ExtData.rc" ]]; then - { \ - echo "PrimaryExports%%" ; \ - cat "${AERO_CONFIG_DIR}/ExtData.other" ; \ - cat "${AERO_CONFIG_DIR}/ExtData.${AERO_EMIS_FIRE:-none}" ; \ - echo "%%" ; \ - } > "${DATA}/AERO_ExtData.rc" - # shellcheck disable=SC2320 - status=$? - if (( status != 0 )); then exit "${status}"; fi + # attempt to generate ExtData configuration file if not provided + if [[ ! -f "${DATA}/AERO_ExtData.rc" ]]; then + { + echo "PrimaryExports%%" + cat "${AERO_CONFIG_DIR}/ExtData.other" + cat "${AERO_CONFIG_DIR}/ExtData.${AERO_EMIS_FIRE:-none}" + echo "%%" + } > "${DATA}/AERO_ExtData.rc" + # shellcheck disable=SC2320 + status=$? + if ((status != 0)); then exit "${status}"; fi + fi fi - fi } diff --git a/ush/parsing_namelists_MOM6.sh b/ush/parsing_namelists_MOM6.sh index bb810b60f7e..b8c7293681c 100755 --- a/ush/parsing_namelists_MOM6.sh +++ b/ush/parsing_namelists_MOM6.sh @@ -2,90 +2,90 @@ # Disable variable not used warnings # shellcheck disable=SC2034 -MOM6_namelists(){ +MOM6_namelists() { -# ================================================================ -# MOM_input -# --------- -# Prepare local variables for use in MOM_input.IN from UFSWM -# The ones already defined are left commented as a reminder -# == MOM options to start from coarsed grained restarts, set to off by default -# options only available for 05 and 1 degree grids -# as restarts are coarsed grained/interpolated from the 0.25 degrees grid -local MOM6_INIT_FROM_Z=${MOM6_INIT_FROM_Z:-True} -local MOM6_WARMSTART_FILE=${MOM6_WARMSTART_FILE:-"none"} -local MOM6_INIT_UV=${MOM6_INIT_UV:-"zero"} -# == MOM_domains section == -# NX_GLB -# NY_GLB -# == MOM section == -# DT_DYNAM_MOM6 -# DT_THERM_MOM6 -# MOM6_THERMO_SPAN -# == MOM_grid_init section == -local MOM6_TOPOEDITS=${TOPOEDITS} -# MOM6_ALLOW_LANDMASK_CHANGES -# == MOM_diag_mediator section == -# MOM6_DIAG_COORD_DEF_Z_FILE -# MOM6_DIAG_MISVAL -# == MOM_diabatic_aux section == -local MOM6_CHLCLIM=${CHLCLIM} -# == MOM_energetic_PBL section == -# MOM6_USE_LI2016 -if [[ "${cplwav}" == ".true." ]] ; then - local MOM6_USE_WAVES="True" -else - local MOM6_USE_WAVES="False" -fi -# == MOM_oda_incupd section == -local ODA_TEMPINC_VAR=${ODA_TEMPINC_VAR:-"Temp"} -local ODA_SALTINC_VAR=${ODA_SALTINC_VAR:-"Salt"} -local ODA_THK_VAR=${ODA_THK_VAR:-"h"} -local ODA_INCUPD_UV="True" -local ODA_UINC_VAR=${ODA_UINC_VAR:-"u"} -local ODA_VINC_VAR=${ODA_VINC_VAR:-"v"} -# ODA_INCUPD -# ODA_INCUPD_NHOURS -# == MOM_surface_forcing section == -# MOM6_RIVER_RUNOFF -# == ocean_stochastics section == -if [[ "${DO_OCN_SPPT}" == "YES" ]]; then - local DO_OCN_SPPT="True" # TODO: This is problematic if DO_OCN_SPPT is going to be used elsewhere -else - local DO_OCN_SPPT="False" -fi -if [[ "${DO_OCN_PERT_EPBL}" == "YES" ]]; then - local PERT_EPBL="True" -else - local PERT_EPBL="False" -fi -local MOM6_HFREEZE=20.0 -# Ensure the template exists -local template=${MOM6_INPUT_TEMPLATE:-"${PARMgfs}/ufs/MOM_input_${OCNRES}.IN"} -if [[ ! -f "${template}" ]]; then - echo "FATAL ERROR: template '${template}' does not exist, ABORT!" - exit 1 -fi -rm -f "${DATA}/INPUT/MOM_input" -atparse < "${template}" >> "${DATA}/INPUT/MOM_input" -echo "Rendered MOM_input:" -cat "${DATA}/INPUT/MOM_input" + # ---------------------------------------------------------------- + # MOM_input + # --------- + # Prepare local variables for use in MOM_input.IN from UFSWM + # The ones already defined are left commented as a reminder + # == MOM options to start from coarsed grained restarts, set to off by default + # options only available for 05 and 1 degree grids + # as restarts are coarsed grained/interpolated from the 0.25 degrees grid + local MOM6_INIT_FROM_Z=${MOM6_INIT_FROM_Z:-True} + local MOM6_WARMSTART_FILE=${MOM6_WARMSTART_FILE:-"none"} + local MOM6_INIT_UV=${MOM6_INIT_UV:-"zero"} + # == MOM_domains section == + # NX_GLB + # NY_GLB + # == MOM section == + # DT_DYNAM_MOM6 + # DT_THERM_MOM6 + # MOM6_THERMO_SPAN + # == MOM_grid_init section == + local MOM6_TOPOEDITS=${TOPOEDITS} + # MOM6_ALLOW_LANDMASK_CHANGES + # == MOM_diag_mediator section == + # MOM6_DIAG_COORD_DEF_Z_FILE + # MOM6_DIAG_MISVAL + # == MOM_diabatic_aux section == + local MOM6_CHLCLIM=${CHLCLIM} + # == MOM_energetic_PBL section == + # MOM6_USE_LI2016 + if [[ "${cplwav}" == ".true." ]]; then + local MOM6_USE_WAVES="True" + else + local MOM6_USE_WAVES="False" + fi + # == MOM_oda_incupd section == + local ODA_TEMPINC_VAR=${ODA_TEMPINC_VAR:-"Temp"} + local ODA_SALTINC_VAR=${ODA_SALTINC_VAR:-"Salt"} + local ODA_THK_VAR=${ODA_THK_VAR:-"h"} + local ODA_INCUPD_UV="True" + local ODA_UINC_VAR=${ODA_UINC_VAR:-"u"} + local ODA_VINC_VAR=${ODA_VINC_VAR:-"v"} + # ODA_INCUPD + # ODA_INCUPD_NHOURS + # == MOM_surface_forcing section == + # MOM6_RIVER_RUNOFF + # == ocean_stochastics section == + if [[ "${DO_OCN_SPPT}" == "YES" ]]; then + local DO_OCN_SPPT="True" # TODO: This is problematic if DO_OCN_SPPT is going to be used elsewhere + else + local DO_OCN_SPPT="False" + fi + if [[ "${DO_OCN_PERT_EPBL}" == "YES" ]]; then + local PERT_EPBL="True" + else + local PERT_EPBL="False" + fi + local MOM6_HFREEZE=20.0 + # Ensure the template exists + local template=${MOM6_INPUT_TEMPLATE:-"${PARMgfs}/ufs/MOM_input_${OCNRES}.IN"} + if [[ ! -f "${template}" ]]; then + echo "FATAL ERROR: template '${template}' does not exist, ABORT!" + exit 1 + fi + rm -f "${DATA}/INPUT/MOM_input" + atparse < "${template}" >> "${DATA}/INPUT/MOM_input" + echo "Rendered MOM_input:" + cat "${DATA}/INPUT/MOM_input" -# ================================================================ -# data_table -# ---------- -# Prepare local variables for use in MOM6_data_table.IN from UFSWM -local MOM6_FRUNOFF=${FRUNOFF} + # ---------------------------------------------------------------- + # data_table + # ---------- + # Prepare local variables for use in MOM6_data_table.IN from UFSWM + local MOM6_FRUNOFF=${FRUNOFF} -# Ensure the template exists -local template=${MOM6_DATA_TABLE_TEMPLATE:-"${PARMgfs}/ufs/MOM6_data_table.IN"} -if [[ ! -f "${template}" ]]; then - echo "FATAL ERROR: template '${template}' does not exist, ABORT!" - exit 1 -fi -rm -f "${DATA}/data_table" -atparse < "${template}" >> "${DATA}/data_table" -echo "Rendered data_table:" -cat "${DATA}/data_table" + # Ensure the template exists + local template=${MOM6_DATA_TABLE_TEMPLATE:-"${PARMgfs}/ufs/MOM6_data_table.IN"} + if [[ ! -f "${template}" ]]; then + echo "FATAL ERROR: template '${template}' does not exist, ABORT!" + exit 1 + fi + rm -f "${DATA}/data_table" + atparse < "${template}" >> "${DATA}/data_table" + echo "Rendered data_table:" + cat "${DATA}/data_table" } diff --git a/ush/parsing_namelists_WW3.sh b/ush/parsing_namelists_WW3.sh index ddcfdb47a26..5f19fdfc58a 100755 --- a/ush/parsing_namelists_WW3.sh +++ b/ush/parsing_namelists_WW3.sh @@ -1,70 +1,82 @@ #! /usr/bin/env bash -WW3_namelists(){ +WW3_namelists() { -# WW3 namelists/input generation + # WW3 namelists/input generation - FHMAX_WAV="${FHMAX_WAV:-384}" + FHMAX_WAV="${FHMAX_WAV:-384}" -# --------------------------------------------------------------------------- # -# Buoy location file + # --------------------------------------------------------------------------- # + # Buoy location file - if [ -f "${PARMgfs}/wave/wave_${NET}.buoys" ] - then - cpreq "${PARMgfs}/wave/wave_${NET}.buoys" "${DATA}/ww3_points.list" - fi + if [[ -f "${PARMgfs}/wave/wave_${NET}.buoys" ]]; then + cpreq "${PARMgfs}/wave/wave_${NET}.buoys" "${DATA}/ww3_points.list" + fi - if [ -f "${DATA}/ww3_points.list" ] - then - set +x - echo "ww3_points.list copied (${PARMgfs}/wave/wave_${NET}.buoys)." - set_trace - else - echo "FATAL ERROR : ww3_points.list (${PARMgfs}/wave/wave_${NET}.buoys) NOT FOUND" - exit 12 - fi + if [[ -f "${DATA}/ww3_points.list" ]]; then + set +x + echo "ww3_points.list copied (${PARMgfs}/wave/wave_${NET}.buoys)." + set_trace + else + echo "FATAL ERROR : ww3_points.list (${PARMgfs}/wave/wave_${NET}.buoys) NOT FOUND" + exit 12 + fi - #set coupling to ice/current - WW3_ICE="F" - WW3_CUR="F" + #set coupling to ice/current + WW3_ICE="F" + WW3_CUR="F" - case ${WW3ICEINP} in - 'YES' ) - WW3_ICE="T";; - 'CPL' ) - WW3_ICE="C";; - esac + case ${WW3ICEINP} in + 'YES') + WW3_ICE="T" + ;; + 'CPL') + WW3_ICE="C" + ;; + *) + msg="FATAL: Unknown WW3ICEIMP ${WW3ICEINP}" + export err=100 + err_exit "${msg}" + ;; + esac - case ${WW3CURINP} in - 'YES' ) - WW3_CUR="T";; - 'CPL' ) - WW3_CUR="C";; - esac + case ${WW3CURINP} in + 'YES') + WW3_CUR="T" + ;; + 'CPL') + WW3_CUR="C" + ;; + *) + msg="FATAL: Unknown WW3CURINP ${WW3CURINP}" + export err=100 + err_exit "${msg}" + ;; + esac - # Variables used in atparse of shel template - export WW3_IC1="F" - export WW3_IC5="F" - export WW3_WLEV="F" - export WW3_ICE - export WW3_CUR - export WW3_OUTPARS="${OUTPARS_WAV}" - export WW3_DTFLD="${DTFLD_WAV}" - export WW3_DTPNT="${DTPNT_WAV}" + # Variables used in atparse of shel template + export WW3_IC1="F" + export WW3_IC5="F" + export WW3_WLEV="F" + export WW3_ICE + export WW3_CUR + export WW3_OUTPARS="${OUTPARS_WAV}" + export WW3_DTFLD="${DTFLD_WAV}" + export WW3_DTPNT="${DTPNT_WAV}" - export WW3_GRD_OUTDIR="./WW3_OUTPUT/" - export WW3_PNT_OUTDIR="./WW3_OUTPUT/" - export WW3_RST_OUTDIR="./WW3_RESTART/" + export WW3_GRD_OUTDIR="./WW3_OUTPUT/" + export WW3_PNT_OUTDIR="./WW3_OUTPUT/" + export WW3_RST_OUTDIR="./WW3_RESTART/" - # Ensure the template exists - local template=${WW3_INPUT_TEMPLATE:-"${PARMgfs}/ufs/ww3_shel.nml.IN"} - if [[ ! -f "${template}" ]]; then - echo "FATAL ERROR: template '${template}' does not exist, ABORT!" - exit 1 - fi - rm -f "${DATA}/ww3_shel.nml" - atparse < "${template}" >> "${DATA}/ww3_shel.nml" - echo "Rendered ww3_shel.nml:" - cat "${DATA}/ww3_shel.nml" + # Ensure the template exists + local template=${WW3_INPUT_TEMPLATE:-"${PARMgfs}/ufs/ww3_shel.nml.IN"} + if [[ ! -f "${template}" ]]; then + echo "FATAL ERROR: template '${template}' does not exist, ABORT!" + exit 1 + fi + rm -f "${DATA}/ww3_shel.nml" + atparse < "${template}" >> "${DATA}/ww3_shel.nml" + echo "Rendered ww3_shel.nml:" + cat "${DATA}/ww3_shel.nml" } diff --git a/ush/parsing_ufs_configure.sh b/ush/parsing_ufs_configure.sh index 75b2cae2264..c860d855b9a 100755 --- a/ush/parsing_ufs_configure.sh +++ b/ush/parsing_ufs_configure.sh @@ -9,124 +9,124 @@ # shellcheck disable=SC2034 UFS_configure() { -echo "SUB ${FUNCNAME[0]}: ufs.configure begins" - -# Setup ufs.configure -local esmf_logkind=${esmf_logkind:-"ESMF_LOGKIND_MULTI"} #options: ESMF_LOGKIND_MULTI_ON_ERROR, ESMF_LOGKIND_MULTI, ESMF_LOGKIND_NONE -local DumpFields=${DumpFields:-false} -local cap_dbug_flag=${cap_dbug_flag:-0} - -# Determine "cmeps_run_type" based on the availability of the mediator restart file -# If it is a warm_start, we already copied the mediator restart to DATA, if it was present -# If the mediator restart was not present, despite being a "warm_start", we put out a WARNING -# in forecast_postdet.sh function CMEPS_postdet -if [[ -f "${DATA}/ufs.cpld.cpl.r.nc" ]]; then - local cmeps_run_type='continue' -else - local cmeps_run_type='startup' -fi - -# Atm-related -local atm_model="fv3" -local atm_petlist_bounds="0 $(( ATMPETS-1 ))" -local atm_omp_num_threads="${ATMTHREADS}" - -local med_model="cmeps" -local med_petlist_bounds="0 $(( MEDPETS-1 ))" -local med_omp_num_threads="${MEDTHREADS}" - -# vector remapping -local MAPUV3D=true - -if [[ "${cpl}" = ".true." ]]; then - local coupling_interval_slow_sec="${CPL_SLOW}" -fi - -local WRITE_ENDOFRUN_RESTART=.false. - -if [[ "${cplflx}" = ".true." ]]; then - - local use_coldstart=${use_coldstart:-".false."} - local use_mommesh=${USE_MOMMESH:-"true"} - - local ocn_model="mom6" - local ocn_petlist_bounds="${ATMPETS} $(( ATMPETS+OCNPETS-1 ))" - local ocn_omp_num_threads="${OCNTHREADS}" - local RUNTYPE="${cmeps_run_type}" - local CMEPS_RESTART_DIR="CMEPS_RESTART/" - local CPLMODE="${cplmode}" - local CMEPS_PIO_FORMAT='pnetcdf' - local CMEPS_PIO_STRIDE=4 - local CMEPS_PIO_IOTASKS=-99 - local CMEPS_PIO_REARR='box' - local CMEPS_PIO_ROOT=-99 - local coupling_interval_fast_sec="${CPL_FAST}" - local RESTART_N=999999 - local ocean_albedo_limit=0.06 - local ATMTILESIZE="${CASE:1}" - local ocean_albedo_limit=0.06 - local pio_rearranger=${pio_rearranger:-"box"} - local MED_history_n=1000000 - - local histaux_enabled=".false." -fi - -if [[ "${cplice}" = ".true." ]]; then - - local ice_model="cice6" - local ice_petlist_bounds="$(( ATMPETS+OCNPETS )) $(( ATMPETS+OCNPETS+ICEPETS-1 ))" - local ice_omp_num_threads="${ICETHREADS}" - local FHMAX="${FHMAX_GFS}" # TODO: How did this get in here hard-wired to FHMAX_GFS? -fi - -if [[ "${cplwav}" = ".true." ]]; then - - local wav_model="ww3" - local wav_petlist_bounds="$(( ATMPETS+OCNPETS+ICEPETS )) $(( ATMPETS+OCNPETS+ICEPETS+WAVPETS-1 ))" - local wav_omp_num_threads="${WAVTHREADS}" - - local WW3_user_histname="false" - local WW3_historync="false" - local WW3_restartnc="true" - local WW3_PIO_FORMAT="pnetcdf" - local WW3_PIO_IOTASKS=-99 - local WW3_PIO_STRIDE=4 - local WW3_PIO_REARR="box" - local WW3_PIO_ROOT=-99 - -fi - -if [[ "${cplchm}" = ".true." ]]; then - - local chm_model="gocart" - local chm_petlist_bounds="0 $(( CHMPETS-1 ))" - local chm_omp_num_threads="${CHMTHREADS}" - local coupling_interval_sec="${CPL_FAST}" - -fi - -#Set ESMF_THREADING variable for ufs configure -if [[ "${USE_ESMF_THREADING}" = "YES" ]]; then - local ESMF_THREADING="true" -else - local ESMF_THREADING="false" -fi - -# Ensure the template exists -if [[ ! -r "${ufs_configure_template}" ]]; then - echo "FATAL ERROR: template '${ufs_configure_template}' does not exist, ABORT!" - exit 1 -else - echo "INFO: using ufs.configure template: '${ufs_configure_template}'" -fi - -rm -f "${DATA}/ufs.configure" -atparse < "${ufs_configure_template}" >> "${DATA}/ufs.configure" -echo "Rendered ufs.configure:" -cat ufs.configure - -cpreq "${HOMEgfs}/sorc/ufs_model.fd/tests/parm/fd_ufs.yaml" fd_ufs.yaml - -echo "SUB ${FUNCNAME[0]}: ufs.configure ends" + echo "SUB ${FUNCNAME[0]}: ufs.configure begins" + + # Setup ufs.configure + local esmf_logkind=${esmf_logkind:-"ESMF_LOGKIND_MULTI"} #options: ESMF_LOGKIND_MULTI_ON_ERROR, ESMF_LOGKIND_MULTI, ESMF_LOGKIND_NONE + local DumpFields=${DumpFields:-false} + local cap_dbug_flag=${cap_dbug_flag:-0} + + # Determine "cmeps_run_type" based on the availability of the mediator restart file + # If it is a warm_start, we already copied the mediator restart to DATA, if it was present + # If the mediator restart was not present, despite being a "warm_start", we put out a WARNING + # in forecast_postdet.sh function CMEPS_postdet + if [[ -f "${DATA}/ufs.cpld.cpl.r.nc" ]]; then + local cmeps_run_type='continue' + else + local cmeps_run_type='startup' + fi + + # Atm-related + local atm_model="fv3" + local atm_petlist_bounds="0 $((ATMPETS - 1))" + local atm_omp_num_threads="${ATMTHREADS}" + + local med_model="cmeps" + local med_petlist_bounds="0 $((MEDPETS - 1))" + local med_omp_num_threads="${MEDTHREADS}" + + # vector remapping + local MAPUV3D=true + + if [[ "${cpl}" = ".true." ]]; then + local coupling_interval_slow_sec="${CPL_SLOW}" + fi + + local WRITE_ENDOFRUN_RESTART=.false. + + if [[ "${cplflx}" = ".true." ]]; then + + local use_coldstart=${use_coldstart:-".false."} + local use_mommesh=${USE_MOMMESH:-"true"} + + local ocn_model="mom6" + local ocn_petlist_bounds="${ATMPETS} $((ATMPETS + OCNPETS - 1))" + local ocn_omp_num_threads="${OCNTHREADS}" + local RUNTYPE="${cmeps_run_type}" + local CMEPS_RESTART_DIR="CMEPS_RESTART/" + local CPLMODE="${cplmode}" + local CMEPS_PIO_FORMAT='pnetcdf' + local CMEPS_PIO_STRIDE=4 + local CMEPS_PIO_IOTASKS=-99 + local CMEPS_PIO_REARR='box' + local CMEPS_PIO_ROOT=-99 + local coupling_interval_fast_sec="${CPL_FAST}" + local RESTART_N=999999 + local ocean_albedo_limit=0.06 + local ATMTILESIZE="${CASE:1}" + local ocean_albedo_limit=0.06 + local pio_rearranger=${pio_rearranger:-"box"} + local MED_history_n=1000000 + + local histaux_enabled=".false." + fi + + if [[ "${cplice}" = ".true." ]]; then + + local ice_model="cice6" + local ice_petlist_bounds="$((ATMPETS + OCNPETS)) $((ATMPETS + OCNPETS + ICEPETS - 1))" + local ice_omp_num_threads="${ICETHREADS}" + local FHMAX="${FHMAX_GFS}" # TODO: How did this get in here hard-wired to FHMAX_GFS? + fi + + if [[ "${cplwav}" = ".true." ]]; then + + local wav_model="ww3" + local wav_petlist_bounds="$((ATMPETS + OCNPETS + ICEPETS)) $((ATMPETS + OCNPETS + ICEPETS + WAVPETS - 1))" + local wav_omp_num_threads="${WAVTHREADS}" + + local WW3_user_histname="false" + local WW3_historync="false" + local WW3_restartnc="true" + local WW3_PIO_FORMAT="pnetcdf" + local WW3_PIO_IOTASKS=-99 + local WW3_PIO_STRIDE=4 + local WW3_PIO_REARR="box" + local WW3_PIO_ROOT=-99 + + fi + + if [[ "${cplchm}" = ".true." ]]; then + + local chm_model="gocart" + local chm_petlist_bounds="0 $((CHMPETS - 1))" + local chm_omp_num_threads="${CHMTHREADS}" + local coupling_interval_sec="${CPL_FAST}" + + fi + + #Set ESMF_THREADING variable for ufs configure + if [[ "${USE_ESMF_THREADING}" = "YES" ]]; then + local ESMF_THREADING="true" + else + local ESMF_THREADING="false" + fi + + # Ensure the template exists + if [[ ! -r "${ufs_configure_template}" ]]; then + echo "FATAL ERROR: template '${ufs_configure_template}' does not exist, ABORT!" + exit 1 + else + echo "INFO: using ufs.configure template: '${ufs_configure_template}'" + fi + + rm -f "${DATA}/ufs.configure" + atparse < "${ufs_configure_template}" >> "${DATA}/ufs.configure" + echo "Rendered ufs.configure:" + cat ufs.configure + + cpreq "${HOMEgfs}/sorc/ufs_model.fd/tests/parm/fd_ufs.yaml" fd_ufs.yaml + + echo "SUB ${FUNCNAME[0]}: ufs.configure ends" } diff --git a/ush/preamble.sh b/ush/preamble.sh index aac23c4b39b..df24338ac83 100755 --- a/ush/preamble.sh +++ b/ush/preamble.sh @@ -80,7 +80,7 @@ postamble() { # if [[ -v 'POSTAMBLE_CMD' ]]; then - ${POSTAMBLE_CMD} + ${POSTAMBLE_CMD} fi # Calculate the elapsed time @@ -111,10 +111,10 @@ function err_exit() { msg1=${*:-Job ${jobid} failed} if [[ -n "${pgm}" ]]; then - msg1+=", ERROR IN ${pgm}" + msg1+=", ERROR IN ${pgm}" fi if [[ -n "${err}" ]]; then - msg1+=" RETURN CODE ${err}" + msg1+=" RETURN CODE ${err}" fi msg2=" @@ -134,38 +134,38 @@ function err_exit() { # list files in temporary working directory if [[ -n "${DATA}" ]]; then - >&2 echo "${DATA}" - >&2 ls -ltr "${DATA}" + >&2 echo "${DATA}" + >&2 ls -ltr "${DATA}" else - >&2 echo "WARNING: DATA variable not defined" + >&2 echo "WARNING: DATA variable not defined" fi # save standard output if [[ -n "${pgmout}" ]]; then - if [[ -s errfile ]]; then - echo "----- contents of errfile -----" >> "${pgmout}" - cat errfile >> "${pgmout}" - fi - >&2 cat "${pgmout}" + if [[ -s errfile ]]; then + echo "----- contents of errfile -----" >> "${pgmout}" + cat errfile >> "${pgmout}" + fi + >&2 cat "${pgmout}" elif [[ -s errfile ]]; then - >&2 cat errfile + >&2 cat errfile fi # Write to ecflow log: if [[ "${SENDECF}" == "YES" ]]; then - timeout 30 ecflow_client --msg "${ECF_NAME}: ${msg1}" - timeout 30 ssh "${ECF_HOST}" "echo \"${msg}2\" >> ${ECF_JOBOUT:?}" + timeout 30 ecflow_client --msg "${ECF_NAME}: ${msg1}" + timeout 30 ssh "${ECF_HOST}" "echo \"${msg}2\" >> ${ECF_JOBOUT:?}" fi # KILL THE JOB: if [[ "${SENDECF}" == "YES" ]]; then - ecflow_client --kill="${ECF_NAME:?}" + ecflow_client --kill="${ECF_NAME:?}" fi if [[ -n "${PBS_JOBID}" ]]; then - qdel "${PBS_JOBID}" + qdel "${PBS_JOBID}" elif [[ -n "${SLURM_JOB_ID}" ]]; then - scancel "${SLURM_JOB_ID}" + scancel "${SLURM_JOB_ID}" fi } diff --git a/ush/prep_sfc_ice_blend.sh b/ush/prep_sfc_ice_blend.sh index a60adfeb91c..19a411312d3 100755 --- a/ush/prep_sfc_ice_blend.sh +++ b/ush/prep_sfc_ice_blend.sh @@ -66,13 +66,13 @@ pgmout=${pgmout:-"OUTPUT"} #------------------------------------------------------------------------ if [[ -f "${IMS_FILE}" ]]; then - cpfs "${IMS_FILE}" ./ims.grib2 - ${WGRIB2} ims.grib2 -match "ICEC" -grib ims.icec.grib2 - grid173="0 0 0 0 0 0 0 0 4320 2160 0 0 89958000 42000 48 -89958000 359958000 83000 83000 0" - ${COPYGB2} -x -i3 -g "${grid173}" ims.icec.grib2 ims.icec.5min.grib2 + cpfs "${IMS_FILE}" ./ims.grib2 + ${WGRIB2} ims.grib2 -match "ICEC" -grib ims.icec.grib2 + grid173="0 0 0 0 0 0 0 0 4320 2160 0 0 89958000 42000 48 -89958000 359958000 83000 83000 0" + ${COPYGB2} -x -i3 -g "${grid173}" ims.icec.grib2 ims.icec.5min.grib2 else - echo "WARNING: IMS ${IMS_FILE} ice data missing. Can not run program ${pgm}." - exit 3 + echo "WARNING: IMS ${IMS_FILE} ice data missing. Can not run program ${pgm}." + exit 3 fi #------------------------------------------------------------------------ @@ -80,10 +80,9 @@ fi # Copy old blended data to current directory. #------------------------------------------------------------------------ -if [[ ! -f "${FIVE_MIN_ICE_FILE}" ]] -then - echo "WARNING: ${FIVE_MIN_ICE_FILE} data missing. Can not run program ${pgm}." - exit 5 +if [[ ! -f "${FIVE_MIN_ICE_FILE}" ]]; then + echo "WARNING: ${FIVE_MIN_ICE_FILE} data missing. Can not run program ${pgm}." + exit 5 fi #------------------------------------------------------------------------ @@ -118,16 +117,16 @@ export err=$? #------------------------------------------------------------------------ if [[ "${err}" -ne 0 ]]; then - echo "WARNING: ${pgm} completed abnormally. The old ice blend file will be used." - # Exit but do not call err_exit. Calling script will handle use of older file - exit "${err}" + echo "WARNING: ${pgm} completed abnormally. The old ice blend file will be used." + # Exit but do not call err_exit. Calling script will handle use of older file + exit "${err}" else - ${WGRIB2} -set_int 3 51 42000 "${BLENDED_ICE_FILE}" -grib "${BLENDED_ICE_FILE}.corner" - ${CNVGRIB} -g21 "${BLENDED_ICE_FILE}.corner" "${BLENDED_ICE_FILE}.bitmap" - rm -f "${BLENDED_ICE_FILE}" - ${COPYGB} -M "#1.57" -x "${BLENDED_ICE_FILE}.bitmap" "${BLENDED_ICE_FILE}" - cpfs "${BLENDED_ICE_FILE}" "${COMOUT_OBS}" - rm -f "${BLENDED_ICE_FILE}.corner" "${BLENDED_ICE_FILE}.bitmap" + ${WGRIB2} -set_int 3 51 42000 "${BLENDED_ICE_FILE}" -grib "${BLENDED_ICE_FILE}.corner" + ${CNVGRIB} -g21 "${BLENDED_ICE_FILE}.corner" "${BLENDED_ICE_FILE}.bitmap" + rm -f "${BLENDED_ICE_FILE}" + ${COPYGB} -M "#1.57" -x "${BLENDED_ICE_FILE}.bitmap" "${BLENDED_ICE_FILE}" + cpfs "${BLENDED_ICE_FILE}" "${COMOUT_OBS}" + rm -f "${BLENDED_ICE_FILE}.corner" "${BLENDED_ICE_FILE}.bitmap" fi exit 0 diff --git a/ush/prep_sfc_snow.sh b/ush/prep_sfc_snow.sh index 0e017011005..edd523abc17 100755 --- a/ush/prep_sfc_snow.sh +++ b/ush/prep_sfc_snow.sh @@ -44,7 +44,7 @@ # ######################################################################### -source "${USHgfs}/atparse.bash" # include function atparse for parsing @[XYZ] templated files +source "${USHgfs}/atparse.bash" # include function atparse for parsing @[XYZ] templated files #------------------------------------------------------------------------ # The snow2mdl executable and namelist @@ -84,7 +84,7 @@ CLIMO_QC=${CLIMO_QC:-"${FIXgfs}/am/emcsfc_snow_cover_climo.grib2"} #------------------------------------------------------------------------ MODEL_SNOW_FILE=${MODEL_SNOW_FILE:-"snogrb_model"} -OUTPUT_GRIB2=${OUTPUT_GRIB2:-".false."} # grib 1 when false. +OUTPUT_GRIB2=${OUTPUT_GRIB2:-".false."} # grib 1 when false. #------------------------------------------------------------------------ # Do a quick check of the ims data to ensure it exists and is not corrupt. @@ -92,10 +92,10 @@ OUTPUT_GRIB2=${OUTPUT_GRIB2:-".false."} # grib 1 when false. #------------------------------------------------------------------------ if [[ -f ${IMS_FILE} ]]; then - cpreq "${IMS_FILE}" "${DATA}/imssnow96.grib2" + cpreq "${IMS_FILE}" "${DATA}/imssnow96.grib2" else - echo "WARNING: Missing IMS data. Will not run ${SNOW2MDLEXEC}." - exit 7 + echo "WARNING: Missing IMS data. Will not run ${SNOW2MDLEXEC}." + exit 7 fi #------------------------------------------------------------------------ @@ -106,11 +106,11 @@ fi ${WGRIB2} -d 1 "imssnow96.grib2" err=$? if [[ ${err} -ne 0 ]]; then - echo "WARNING: Corrupt IMS data. Will not run ${SNOW2MDLEXEC}." - exit 9 + echo "WARNING: Corrupt IMS data. Will not run ${SNOW2MDLEXEC}." + exit 9 else - tempdate=$(${WGRIB2} -t "imssnow96.grib2" | head -1) || true - IMSDATE=${tempdate#*d=} + tempdate=$(${WGRIB2} -t "imssnow96.grib2" | head -1) || true + IMSDATE=${tempdate#*d=} fi #------------------------------------------------------------------------ @@ -119,24 +119,24 @@ fi #------------------------------------------------------------------------ if [[ ! -f ${AFWA_GLOBAL_FILE} ]]; then - echo "WARNING: Missing AFWS data. Will not run ${SNOW2MDLEXEC}." - exit 3 + echo "WARNING: Missing AFWS data. Will not run ${SNOW2MDLEXEC}." + exit 3 else - cpreq "${AFWA_GLOBAL_FILE}" "${DATA}/snow.usaf.grib2" - ${WGRIB2} -d 1 "snow.usaf.grib2" - err=$? - if [[ ${err} -ne 0 ]]; then - echo "WARNING: Corrupt AFWS data. Will not run ${SNOW2MDLEXEC}." - exit "${err}" - else - tempdate=$(${WGRIB2} -d 1 -t "snow.usaf.grib2") - AFWADATE=${tempdate#*d=} - two_days_ago=$(date --utc -d "${IMSDATE:0:8} ${IMSDATE:8:2} - 48 hours" +%Y%m%d%H) - if [[ ${AFWADATE} -lt ${two_days_ago} ]]; then - echo "WARNING: Found old AFWA data. Will not run ${SNOW2MDLEXEC}." - exit 4 + cpreq "${AFWA_GLOBAL_FILE}" "${DATA}/snow.usaf.grib2" + ${WGRIB2} -d 1 "snow.usaf.grib2" + err=$? + if [[ ${err} -ne 0 ]]; then + echo "WARNING: Corrupt AFWS data. Will not run ${SNOW2MDLEXEC}." + exit "${err}" + else + tempdate=$(${WGRIB2} -d 1 -t "snow.usaf.grib2") + AFWADATE=${tempdate#*d=} + two_days_ago=$(date --utc -d "${IMSDATE:0:8} ${IMSDATE:8:2} - 48 hours" +%Y%m%d%H) + if [[ ${AFWADATE} -lt ${two_days_ago} ]]; then + echo "WARNING: Found old AFWA data. Will not run ${SNOW2MDLEXEC}." + exit 4 + fi fi - fi fi #------------------------------------------------------------------------ @@ -145,12 +145,12 @@ fi export IMSYEAR=${IMSDATE:0:4} export IMSMONTH=${IMSDATE:4:2} export IMSDAY=${IMSDATE:6:2} -export IMSHOUR=0 # emc convention is to use 00Z. +export IMSHOUR=0 # emc convention is to use 00Z. # Render the namelist template if [[ ! -f "${SNOW2MDLNMLTMPL}" ]]; then - echo "FATAL ERROR: template '${SNOW2MDLNMLTMPL}' does not exist, ABORT!" - exit 1 + echo "FATAL ERROR: template '${SNOW2MDLNMLTMPL}' does not exist, ABORT!" + exit 1 fi rm -f ./fort.41 atparse < "${SNOW2MDLNMLTMPL}" >> "./fort.41" @@ -166,12 +166,12 @@ source prep_step err=$? if [[ ${err} -ne 0 ]]; then - echo "WARNING: ${pgm} completed abnormally." - exit "${err}" + echo "WARNING: ${pgm} completed abnormally." + exit "${err}" else - echo "${pgm} completed normally." - cpfs "${MODEL_SNOW_FILE}" "${COMOUT_OBS}" - rm -f "${MODEL_SNOW_FILE}" + echo "${pgm} completed normally." + cpfs "${MODEL_SNOW_FILE}" "${COMOUT_OBS}" + rm -f "${MODEL_SNOW_FILE}" fi rm -f ./fort.41 diff --git a/ush/product_functions.sh b/ush/product_functions.sh index 05b23fbee2b..300bf003927 100755 --- a/ush/product_functions.sh +++ b/ush/product_functions.sh @@ -1,40 +1,40 @@ #! /usr/bin/env bash function trim_rh() { - # trim RH values larger than 100. - local filename=$1 - ${WGRIB2} "${filename}" \ + # trim RH values larger than 100. + local filename=$1 + ${WGRIB2} "${filename}" \ -not_if ':RH:' -grib "${filename}.new" \ -if ':RH:' -rpn "10:*:0.5:+:floor:1000:min:10:/" -set_grib_type same \ -set_scaling -1 0 -grib_out "${filename}.new" - rc=$? - if (( rc == 0 )); then mv "${filename}.new" "${filename}"; fi - return "${rc}" + rc=$? + if ((rc == 0)); then mv "${filename}.new" "${filename}"; fi + return "${rc}" } function mod_icec() { - # modify icec based on land-sea mask - local filename=$1 - ${WGRIB2} "${filename}" \ - -if 'LAND' -rpn 'sto_1' -fi \ - -if 'ICEC' -rpn 'rcl_1:0:==:*' -fi \ - -set_grib_type same \ - -set_scaling same same \ - -grib_out "${filename}.new" - rc=$? - if (( rc == 0 )); then mv "${filename}.new" "${filename}"; fi - return "${rc}" + # modify icec based on land-sea mask + local filename=$1 + ${WGRIB2} "${filename}" \ + -if 'LAND' -rpn 'sto_1' -fi \ + -if 'ICEC' -rpn 'rcl_1:0:==:*' -fi \ + -set_grib_type same \ + -set_scaling same same \ + -grib_out "${filename}.new" + rc=$? + if ((rc == 0)); then mv "${filename}.new" "${filename}"; fi + return "${rc}" } function scale_dec() { - # change the scaling for temperature, precipitable water, and water-equivalent accumlated snow depth - local filename=$1 - ${WGRIB2} "${filename}" -not_if ':(TMP|PWAT|WEASD):' -grib "${filename}.new" \ - -if ':(TMP|PWAT):' -set_grib_type same \ - -set_scaling -1 0 -grib_out "${filename}.new" \ - -if ':(WEASD):' -set_grib_type same \ - -set_scaling 0 0 -grib_out "${filename}.new" - rc=$? - if (( rc == 0 )); then mv "${filename}.new" "${filename}"; fi - return "${rc}" + # change the scaling for temperature, precipitable water, and water-equivalent accumlated snow depth + local filename=$1 + ${WGRIB2} "${filename}" -not_if ':(TMP|PWAT|WEASD):' -grib "${filename}.new" \ + -if ':(TMP|PWAT):' -set_grib_type same \ + -set_scaling -1 0 -grib_out "${filename}.new" \ + -if ':(WEASD):' -set_grib_type same \ + -set_scaling 0 0 -grib_out "${filename}.new" + rc=$? + if ((rc == 0)); then mv "${filename}.new" "${filename}"; fi + return "${rc}" } diff --git a/ush/radmon_diag_ck.sh b/ush/radmon_diag_ck.sh index ca9129b6df4..a8e65a57fe5 100755 --- a/ush/radmon_diag_ck.sh +++ b/ush/radmon_diag_ck.sh @@ -2,173 +2,162 @@ #---------------------------------------------------------------- # Check the contents of the radstat file and compare to -# the ${run}_radmon_satype.txt file. Report any missing +# the ${run}_radmon_satype.txt file. Report any missing # or zero sized diag files. -# - - function usage { - echo "Usage: radmon_diag_ck.sh -rad radstat --sat satype --out output " - echo "" - echo " -r,--rad radstat file (required)" - echo " File name or path to radstat file." - echo "" - echo " -s,--sat satype file (required)" - echo " File name or path to satype file." - echo "" - echo " -o,--out output file name (required)" - echo " File name for missing diag file report." - } +# +function usage { + echo "Usage: radmon_diag_ck.sh -rad radstat --sat satype --out output " + echo "" + echo " -r,--rad radstat file (required)" + echo " File name or path to radstat file." + echo "" + echo " -s,--sat satype file (required)" + echo " File name or path to satype file." + echo "" + echo " -o,--out output file name (required)" + echo " File name for missing diag file report." +} echo "--> radmon_diag_ck.sh" - #-------------------------- # Process input arguments # - nargs=$# - if [[ ${nargs} -ne 6 ]]; then - usage - exit 1 - fi - - while [[ $# -ge 1 ]] - do - key="$1" - echo "${key}" - - case ${key} in - -r|--rad) +nargs=$# +if [[ ${nargs} -ne 6 ]]; then + usage + exit 1 +fi + +while [[ $# -ge 1 ]]; do + key="$1" + echo "${key}" + + case ${key} in + -r | --rad) radstat_file="$2" shift # past argument - ;; - -s|--sat) + ;; + -s | --sat) satype_file="$2" shift # past argument - ;; - -o|--out) + ;; + -o | --out) output_file="$2" shift # past argument - ;; - *) - #unspecified key + ;; + *) + #unspecified key echo " unsupported key = ${key}" - ;; - esac + ;; + esac - shift - done + shift +done # set -ax - echo " radstat_file = ${radstat_file}" - echo " satype_file = ${satype_file}" - echo " output_file = ${output_file}" - - missing_diag="" - zero_len_diag="" - - #--------------------------------------------- - # get list of diag files in the radstat file - # - radstat_contents=`tar -tf "${radstat_file}" | grep '_ges' | - gawk -F"diag_" '{print $2}' | - gawk -F"_ges" '{print $1}'` - - - #--------------------------------------------- - # load contents of satype_file into an array - # - satype_contents=$(cat "${satype_file}") - - - #------------------------------------------------- - # compare $satype_contents and $radstat_contents - # report anything missing - # - for sat in ${satype_contents}; do - content_count=$(echo "${radstat_contents}" | grep -c "${sat}" || true) - - if (( content_count <= 0 )); then +echo " radstat_file = ${radstat_file}" +echo " satype_file = ${satype_file}" +echo " output_file = ${output_file}" + +missing_diag="" +zero_len_diag="" + +#--------------------------------------------- +# get list of diag files in the radstat file +# +# shellcheck disable=SC2312 +radstat_contents=$(tar -tf "${radstat_file}" | grep -Po '(?<=diag_).*(?=_ges.*)') + +#--------------------------------------------- +# load contents of satype_file into an array +# +readarray -t satype_contents < "${satype_file}" + +#------------------------------------------------- +# compare $satype_contents and $radstat_contents +# report anything missing +# +for sat in "${satype_contents[@]}"; do + content_count=$(echo "${radstat_contents}" | grep -c "${sat}") + + if [[ "${content_count}" -le 0 ]]; then missing_diag="${missing_diag} ${sat}" - fi - - done - - echo "" - echo "missing_diag = ${missing_diag}" - echo "" - - - #--------------------------------------------------------- - # Check for zero sized diag files. The diag files in - # the radstat file (which is a tar file) are gzipped. - # I find that 0 sized, gzipped file has a size of ~52 - # (I assume that's for header and block size). - # - # So for this check we'll assume anything in the radstat - # file with a size of > 1000 bytes is suspect. (That's - # overkill, 100 is probably sufficient, but I'm the - # nervous type.) So we'll extract, uncompress, and check - # the actual file size of those. Anything with an - # uncompressed size of 0 goes on the zero_len_diag list. - # - - # TODO Rewrite these array parsing commands to avoid using Bash's sloppy word splitting - # File sizes contain only digits and immediately precede the date - # shellcheck disable=SC2207 - sizes=($(tar -vtf "${radstat_file}" --wildcards '*_ges*' | grep -P -o '(\d)+(?= \d{4}-\d{2}-\d{2})')) - # Filenames are the last group of non-whitespace characters - # shellcheck disable=SC2207 - filenames=($(tar -vtf "${radstat_file}" --wildcards '*_ges*' | grep -P -o '\S+$')) - # shellcheck disable= - - - for file_num in "${!filenames[@]}"; do - file_name="${filenames[${file_num}]}" - file_size="${sizes[${file_num}]}" - - if (( file_size <= 1000 )); then - tar -xf "${radstat_file}" "${file_name}" - gunzip "${file_name}" - uz_file_name="${file_name%.*}" - uz_file_size=$(stat -c "%s" "${uz_file_name}") - - - if (( uz_file_size <= 0 )); then + fi + +done + +echo "" +echo "missing_diag = ${missing_diag}" +echo "" + +#--------------------------------------------------------- +# Check for zero sized diag files. The diag files in +# the radstat file (which is a tar file) are gzipped. +# I find that 0 sized, gzipped file has a size of ~52 +# (I assume that's for header and block size). +# +# So for this check we'll assume anything in the radstat +# file with a size of > 1000 bytes is suspect. (That's +# overkill, 100 is probably sufficient, but I'm the +# nervous type.) So we'll extract, uncompress, and check +# the actual file size of those. Anything with an +# uncompressed size of 0 goes on the zero_len_diag list. +# + +declare -A file_sizes + +# Parse the filename and filesize from tar's verbose output and store in an associative array +# Field $6 of verbose tar output is the filename, field $3 is the size +# Caution: this method is not robust if the filename contains spaces +# shellcheck disable=SC2312 +while IFS='|' read -r name size; do + file_sizes[${name}]=${size} +done < <(tar -vtf "${radstat_file}" --wildcards '*_ges*' | awk '$3 ~ /^[0-9]+$/ { print $6 "|" $3 }') + +for file_name in "${!file_sizes[@]}"; do + file_size="${file_sizes["${file_name}"]}" + + if ((file_size <= 1000)); then + tar -xf "${radstat_file}" "${file_name}" + gunzip "${file_name}" + uz_file_name="${file_name%.*}" + uz_file_size=$(stat -c "%s" "${uz_file_name}") + + if ((uz_file_size <= 0)); then # Remove leading diag_ sat=${uz_file_name#diag_} # Remove trailing _ges* sat=${sat%_ges*} zero_len_diag="${zero_len_diag} ${sat}" - fi - - rm -f "${uz_file_name}" - fi + fi - done + rm -f "${uz_file_name}" + fi - echo "" - echo "zero_len_diag = ${zero_len_diag}" - echo "" +done +echo "" +echo "zero_len_diag = ${zero_len_diag}" +echo "" - #----------------------------------------- - # Write results to $output_file - # - if [[ ${#zero_len_diag} -gt 0 ]]; then - for zld in ${zero_len_diag}; do - echo " Zero Length diagnostic file: ${zld}" >> "${output_file}" - done - fi - - if [[ ${#missing_diag} -gt 0 ]]; then - for md in ${missing_diag}; do - echo " Missing diagnostic file : ${md}" >> "${output_file}" - done - fi - +#----------------------------------------- +# Write results to $output_file +# +if [[ ${#zero_len_diag} -gt 0 ]]; then + for zld in ${zero_len_diag}; do + echo " Zero Length diagnostic file: ${zld}" >> "${output_file}" + done +fi + +if [[ ${#missing_diag} -gt 0 ]]; then + for md in ${missing_diag}; do + echo " Missing diagnostic file : ${md}" >> "${output_file}" + done +fi echo "<-- radmon_diag_ck.sh" exit diff --git a/ush/radmon_err_rpt.sh b/ush/radmon_err_rpt.sh index c288f5f3518..7f85f4cfb80 100755 --- a/ush/radmon_err_rpt.sh +++ b/ush/radmon_err_rpt.sh @@ -4,7 +4,7 @@ #### UNIX Script Documentation Block # . . # Script name: radmon_err_rpt.sh -# Script description: Compare the contents of error files from two different +# Script description: Compare the contents of error files from two different # cycles. # # Author: Ed Safford Org: NP23 Date: 2012-02-02 @@ -15,7 +15,7 @@ # in both files are reported. # # This script is run as a child script of radmon_verf_time.sh. The parent -# script creates/copies the error files into a temporary working +# script creates/copies the error files into a temporary working # directory before invoking this script. # # @@ -55,135 +55,130 @@ outfile=${7:-${outfile:?}} # Other variables err=0 -RADMON_SUFFIX=${RADMON_SUFFIX} have_diag_rpt=0 if [[ -s "${diag_rpt}" ]]; then - have_diag_rpt=1 + have_diag_rpt=1 else - err=1 + err=1 fi echo "have_diag_rpt = ${have_diag_rpt}" #----------------------------------------------------------------------------- -# read each line in the $file1 -# search $file2 for the same satname, channel, and region +# read each line in the $file1 +# search $file2 for the same satname, channel, and region # if same combination is in both files, add the values to the output file -# -{ while read myline; do - echo "myline = ${myline}" - bound="" - - echo "${myline}" - satname=$(echo "${myline}" | gawk '{print $1}') - channel=$(echo "${myline}" | gawk '{print $3}') - region=$(echo "${myline}" | gawk '{print $5}') - value1=$(echo "${myline}" | gawk '{print $7}') - bound=$(echo "${myline}" | gawk '{print $9}') - -# -# Check findings against diag_report. If the satellite/instrument is on the -# diagnostic report it means the diagnostic file file for the -# satelite/instrument is missing for this cycle, so skip any additional -# error checking for that source. Otherwise, evaluate as per normal. # - - diag_match="" - diag_match_len=0 - - if [[ ${have_diag_rpt} == 1 ]]; then - diag_match=$(gawk "/${satname}/" "${diag_rpt}") - diag_match_len=$(echo ${#diag_match}) - fi - - - if [[ ${diag_match_len} == 0 ]]; then - - if [[ ${type} == "chan" ]]; then - echo "looking for match for ${satname} and ${channel}" - { while read myline2; do - satname2=$(echo "${myline2}" | gawk '{print $1}') - channel2=$(echo "${myline2}" | gawk '{print $3}') - - if [[ ${satname} == ${satname2} && ${channel} == ${channel2} ]]; then - match="${satname} channel= ${channel}" - echo "match from gawk = ${match}" - break; - else - match="" +{ while read -r myline; do + echo "myline = ${myline}" + bound="" + + echo "${myline}" + satname=$(echo "${myline}" | gawk '{print $1}') + channel=$(echo "${myline}" | gawk '{print $3}') + region=$(echo "${myline}" | gawk '{print $5}') + value1=$(echo "${myline}" | gawk '{print $7}') + bound=$(echo "${myline}" | gawk '{print $9}') + + # + # Check findings against diag_report. If the satellite/instrument is on the + # diagnostic report it means the diagnostic file file for the + # satelite/instrument is missing for this cycle, so skip any additional + # error checking for that source. Otherwise, evaluate as per normal. + # + + diag_match="" + diag_match_len=0 + + if [[ "${have_diag_rpt}" -eq 1 ]]; then + diag_match=$(gawk "/${satname}/" "${diag_rpt}") + diag_match_len=${#diag_match} + fi + + if [[ "${diag_match_len}" -eq 0 ]]; then + + if [[ "${type}" == "chan" ]]; then + echo "looking for match for ${satname} and ${channel}" + { while read -r myline2; do + satname2=$(echo "${myline2}" | gawk '{print $1}') + channel2=$(echo "${myline2}" | gawk '{print $3}') + + if [[ "${satname}" == "${satname2}" && "${channel}" == "${channel2}" ]]; then + match="${satname} channel= ${channel}" + echo "match from gawk = ${match}" + break + else + match="" + fi + + done; } < "${file2}" + + else + match=$(gawk "/${satname}/ && /channel= ${channel} / && /region= ${region} /" "${file2}") + echo match = "${match}" + + match_len=${#match} + if ((match_len > 0)); then + channel2=$(echo "${match}" | gawk '{print $3}') + + if [[ "${channel2}" != "${channel}" ]]; then + match="" + fi fi - done } < "${file2}" - + fi + match_len=${#match} - else - match=$(gawk "/${satname}/ && /channel= ${channel} / && /region= ${region} /" "${file2}") - echo match = "${match}" + if [[ "${match_len}" -gt 0 ]]; then - match_len=$(echo ${#match}) - if (( match_len > 0 )); then - channel2=$(echo "${match}" | gawk '{print $3}') - - if [[ ${channel2} != ${channel} ]]; then - match="" - fi - fi + value2=$(echo "${match}" | gawk '{print $7}') + bound2=$(echo "${match}" | gawk '{print $9}') - fi - match_len=$(echo ${#match}) - - if (( match_len > 0 )); then + if [[ ${type} == "chan" ]]; then + tmpa=" ${satname} channel= ${channel}" + tmpb="" - value2=$(echo "${match}" | gawk '{print $7}') - bound2=$(echo "${match}" | gawk '{print $9}') + elif [[ ${type} == "pen" ]]; then + tmpa="${satname} channel= ${channel} region= ${region}" + tmpb="${cycle1} ${value1} ${bound}" - if [[ ${type} == "chan" ]]; then - tmpa=" ${satname} channel= ${channel}" - tmpb="" + elif [[ ${type} == "cnt" ]]; then + tmpa="${satname} channel= ${channel} region= ${region}" + tmpb="${cycle1} ${value1} ${bound}" - elif [[ ${type} == "pen" ]]; then - tmpa="${satname} channel= ${channel} region= ${region}" - tmpb="${cycle1} ${value1} ${bound}" - - elif [[ ${type} == "cnt" ]]; then - tmpa="${satname} channel= ${channel} region= ${region}" - tmpb="${cycle1} ${value1} ${bound}" - - else - tmpa="${satname} channel= ${channel} region= ${region}" - tmpb="${cycle1}: ${type}= ${value1}" - fi + else + tmpa="${satname} channel= ${channel} region= ${region}" + tmpb="${cycle1}: ${type}= ${value1}" + fi - line1="${tmpa} ${tmpb}" - echo "${line1}" >> "${outfile}" + line1="${tmpa} ${tmpb}" + echo "${line1}" >> "${outfile}" - if [[ ${type} != "chan" ]]; then - tmpc=$(echo "${tmpa}" |sed 's/[a-z]/ /g' | sed 's/[0-9]/ /g' | sed 's/=/ /g' | sed 's/_/ /g' | sed 's/-/ /g') + if [[ ${type} != "chan" ]]; then + tmpc="${tmpa//[a-z0-9\-_\=]/}" - if [[ ${type} == "pen" || ${type} == "cnt" ]]; then - line2=" ${tmpc} ${cycle2} ${value2} ${bound2}" - else - line2=" ${tmpc} ${cycle2}: ${type}= ${value2}" - fi + if [[ ${type} == "pen" || ${type} == "cnt" ]]; then + line2=" ${tmpc} ${cycle2} ${value2} ${bound2}" + else + line2=" ${tmpc} ${cycle2}: ${type}= ${value2}" + fi - echo "${line2}" >> "${outfile}" - fi - - #----------------------------------------- - # add hyperlink to warning entry - # - line3=" http://www.emc.ncep.noaa.gov/gmb/gdas/radiance/es_rad/${RADMON_SUFFIX}/index.html?sat=${satname}®ion=${region}&channel=${channel}&stat=${type}" - if [[ ${channel} -gt 0 ]]; then - echo "${line3}" >> "${outfile}" - echo "" >> "${outfile}" - fi - fi - fi -done } < "${file1}" + echo "${line2}" >> "${outfile}" + fi + #----------------------------------------- + # add hyperlink to warning entry + # + line3=" http://www.emc.ncep.noaa.gov/gmb/gdas/radiance/es_rad/${RADMON_SUFFIX}/index.html?sat=${satname}®ion=${region}&channel=${channel}&stat=${type}" + if [[ "${channel}" -gt 0 ]]; then + echo "${line3}" >> "${outfile}" + echo "" >> "${outfile}" + fi + fi + fi +done; } < "${file1}" ################################################################################ # Post processing -exit ${err} - +exit "${err}" diff --git a/ush/radmon_verf_angle.sh b/ush/radmon_verf_angle.sh index 79046fae44f..1a4d8d5aa3c 100755 --- a/ush/radmon_verf_angle.sh +++ b/ush/radmon_verf_angle.sh @@ -69,14 +69,11 @@ rgnTM=${rgnTM:-} echo " REGIONAL_RR, rgnHH, rgnTM = ${REGIONAL_RR}, ${rgnHH}, ${rgnTM}" netcdf_boolean=".false." -if [[ ${RADMON_NETCDF} -eq 1 ]]; then - netcdf_boolean=".true." +if [[ "${RADMON_NETCDF}" -eq 1 ]]; then + netcdf_boolean=".true." fi echo " RADMON_NETCDF, netcdf_boolean = ${RADMON_NETCDF}, ${netcdf_boolean}" -which prep_step -which startmsg - # File names touch "${pgmout}" @@ -86,11 +83,10 @@ VERBOSE=${VERBOSE:-NO} LITTLE_ENDIAN=${LITTLE_ENDIAN:-0} USE_ANL=${USE_ANL:-0} - if [[ ${USE_ANL} -eq 1 ]]; then - gesanl="ges anl" + gesanl="ges anl" else - gesanl="ges" + gesanl="ges" fi angle_exec=radmon_angle.x @@ -101,12 +97,12 @@ scaninfo=scaninfo.txt # Copy extraction program and supporting files to working directory cpreq "${EXECgfs}/${angle_exec}" ./ -cpreq "${shared_scaninfo}" ./${scaninfo} +cpreq "${shared_scaninfo}" "./${scaninfo}" #-------------------------------------------------------------------- # Run program for given time -export pgm=${angle_exec} +export pgm="${angle_exec}" iyy="${PDY:0:4}" imm="${PDY:4:2}" @@ -117,39 +113,38 @@ touch "./errfile" for type in ${SATYPE}; do - if [[ ! -s ${type} ]]; then - echo "ZERO SIZED: ${type}" - continue - fi - - for dtype in ${gesanl}; do - - echo "pgm = ${pgm}" - echo "pgmout = ${pgmout}" - source prep_step - - if [[ ${dtype} == "anl" ]]; then - data_file="${type}_anl.${PDY}${cyc}.ieee_d" - ctl_file=${type}_anl.ctl - angl_ctl=angle.${ctl_file} - else - data_file="${type}.${PDY}${cyc}.ieee_d" - ctl_file=${type}.ctl - angl_ctl=angle.${ctl_file} - fi - - angl_file="" - if [[ ${REGIONAL_RR} -eq 1 ]]; then - angl_file=${rgnHH}.${data_file}.${rgnTM} - fi - - - if [[ -f input ]]; then - rm -f input - fi - - nchanl=-999 - cat << EOF > input + if [[ ! -s "${type}" ]]; then + echo "ZERO SIZED: ${type}" + continue + fi + + for dtype in ${gesanl}; do + + echo "pgm = ${pgm}" + echo "pgmout = ${pgmout}" + source prep_step + + if [[ "${dtype}" == "anl" ]]; then + data_file="${type}_anl.${PDY}${cyc}.ieee_d" + ctl_file="${type}_anl.ctl" + angl_ctl="angle.${ctl_file}" + else + data_file="${type}.${PDY}${cyc}.ieee_d" + ctl_file="${type}.ctl" + angl_ctl="angle.${ctl_file}" + fi + + angl_file="" + if [[ "${REGIONAL_RR}" -eq 1 ]]; then + angl_file="${rgnHH}.${data_file}.${rgnTM}" + fi + + if [[ -f input ]]; then + rm -f input + fi + + nchanl=-999 + cat << EOF > input &INPUT satname='${type}', iyy=${iyy}, @@ -167,44 +162,42 @@ for type in ${SATYPE}; do / EOF - startmsg - ./${angle_exec} < input >> "${pgmout}" 2>>errfile - export err=$? - - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: ${angle_exec} failed for instrument ${type} and datatype ${dtype}!" - exit "${err}" - fi - - if [[ -s ${angl_file} ]]; then - ${COMPRESS} -f "${angl_file}" - fi + startmsg + "./${angle_exec}" < input >> "${pgmout}" 2>> errfile + export err=$? - if [[ -s ${angl_ctl} ]]; then - ${COMPRESS} -f "${angl_ctl}" - fi + if [[ ${err} -ne 0 ]]; then + echo "FATAL ERROR: ${angle_exec} failed for instrument ${type} and datatype ${dtype}!" + exit "${err}" + fi + if [[ -s "${angl_file}" ]]; then + ${COMPRESS} -f "${angl_file}" + fi - done # for dtype in ${gesanl} loop + if [[ -s "${angl_ctl}" ]]; then + ${COMPRESS} -f "${angl_ctl}" + fi -done # for type in ${SATYPE} loop + done # for dtype in ${gesanl} loop +done # for type in ${SATYPE} loop "${USHgfs}/rstprod.sh" tar_file=radmon_angle.tar if compgen -G "angle*.ieee_d*" > /dev/null || compgen -G "angle*.ctl*" > /dev/null; then - tar -cf "${tar_file}" angle*.ieee_d* angle*.ctl* - ${COMPRESS} ${tar_file} - mv "${tar_file}.${Z}" "${TANKverf_rad}/." - - if [[ ${RAD_AREA} = "rgn" ]]; then - cwd=$(pwd) - cd "${TANKverf_rad}" - tar -xf "${tar_file}.${Z}" - rm -f "${tar_file}.${Z}" - cd "${cwd}" - fi + tar -cf "${tar_file}" angle*.ieee_d* angle*.ctl* + ${COMPRESS} "${tar_file}" + mv "${tar_file}.${Z}" "${TANKverf_rad}/." + + if [[ "${RAD_AREA}" == "rgn" ]]; then + cwd=$(pwd) + cd "${TANKverf_rad}" || exit 1 + tar -xf "${tar_file}.${Z}" + rm -f "${tar_file}.${Z}" + cd "${cwd}" || exit 1 + fi fi ################################################################################ diff --git a/ush/radmon_verf_bcoef.sh b/ush/radmon_verf_bcoef.sh index a4af9155d14..fa92f0d0432 100755 --- a/ush/radmon_verf_bcoef.sh +++ b/ush/radmon_verf_bcoef.sh @@ -4,13 +4,13 @@ #### UNIX Script Documentation Block # . . # Script name: radmon_verf_bcoef.sh -# Script description: Extract bias correction coefficients data from radiance +# Script description: Extract bias correction coefficients data from radiance # diagnostic files. # # Author: Ed Safford Org: NP23 Date: 2012-02-02 # -# Abstract: This script extracts bias correction coefficient related data from -# radiance diagnostic files (which are an output from GSI runs), +# Abstract: This script extracts bias correction coefficient related data from +# radiance diagnostic files (which are an output from GSI runs), # storing the extracted data in small binary files. # # This script is a child script of exgdas_vrfyrad.sh.sms. The parent @@ -35,11 +35,11 @@ # defaults to none # LITTLE_ENDIAN flag for LE machine # defaults to 0 (big endian) -# USE_ANL use analysis files as inputs in addition to +# USE_ANL use analysis files as inputs in addition to # the ges files. Default is 0 (ges only) # # Modules and files referenced: -# scripts : +# scripts : # # programs : $bcoef_exec # @@ -60,8 +60,8 @@ #################################################################### netcdf_boolean=".false." -if [[ ${RADMON_NETCDF} -eq 1 ]]; then - netcdf_boolean=".true." +if [[ "${RADMON_NETCDF}" -eq 1 ]]; then + netcdf_boolean=".true." fi echo " RADMON_NETCDF, netcdf_boolean = ${RADMON_NETCDF}, ${netcdf_boolean}" @@ -77,25 +77,24 @@ SATYPE=${SATYPE:-} LITTLE_ENDIAN=${LITTLE_ENDIAN:-0} USE_ANL=${USE_ANL:-0} - bcoef_exec=radmon_bcoef.x -if [[ ${USE_ANL} -eq 1 ]]; then - gesanl="ges anl" +if [[ "${USE_ANL}" -eq 1 ]]; then + gesanl="ges anl" else - gesanl="ges" + gesanl="ges" fi #-------------------------------------------------------------------- # Copy extraction program and supporting files to working directory -cpreq "${EXECgfs}/${bcoef_exec}" ./${bcoef_exec} -cpreq "${biascr}" ./biascr.txt +cpreq "${EXECgfs}/${bcoef_exec}" "./${bcoef_exec}" +cpreq "${biascr}" ./biascr.txt #-------------------------------------------------------------------- # Run program for given time -export pgm=${bcoef_exec} +export pgm="${bcoef_exec}" iyy="${PDY:0:4}" imm="${PDY:4:2}" @@ -107,39 +106,36 @@ npredr=5 for type in ${SATYPE}; do - if [[ ! -s ${type} ]]; then - echo "ZERO SIZED: ${type}" - continue - fi - - for dtype in ${gesanl}; do - - source prep_step + if [[ ! -s "${type}" ]]; then + echo "ZERO SIZED: ${type}" + continue + fi - if [[ ${dtype} == "anl" ]]; then - data_file="${type}_anl.${PDY}${cyc}.ieee_d" - ctl_file=${type}_anl.ctl - bcoef_ctl=bcoef.${ctl_file} - else - data_file="${type}.${PDY}${cyc}.ieee_d" - ctl_file=${type}.ctl - bcoef_ctl=bcoef.${ctl_file} - fi + for dtype in ${gesanl}; do - if [[ ${REGIONAL_RR} -eq 1 ]]; then - bcoef_file=${rgnHH}.bcoef.${data_file}.${rgnTM} - else - bcoef_file=bcoef.${data_file} - fi + source prep_step + if [[ "${dtype}" == "anl" ]]; then + data_file="${type}_anl.${PDY}${cyc}.ieee_d" + ctl_file="${type}_anl.ctl" + bcoef_ctl="bcoef.${ctl_file}" + else + data_file="${type}.${PDY}${cyc}.ieee_d" + ctl_file="${type}.ctl" + bcoef_ctl="bcoef.${ctl_file}" + fi - if [[ -f input ]]; - then - rm -f input - fi + if [[ "${REGIONAL_RR}" -eq 1 ]]; then + bcoef_file="${rgnHH}.bcoef.${data_file}.${rgnTM}" + else + bcoef_file="bcoef.${data_file}" + fi + if [[ -f input ]]; then + rm -f input + fi - cat << EOF > input + cat << EOF > input &INPUT satname='${type}', npredr=${npredr}, @@ -156,50 +152,46 @@ for type in ${SATYPE}; do netcdf=${netcdf_boolean}, / EOF - startmsg - ./${bcoef_exec} < input >>"${pgmout}" 2>>errfile - export err=$? - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: ${bcoef_exec} failed for instrument ${type} and datatype ${dtype}" - exit "${err}" - fi - - -#------------------------------------------------------------------- -# move data, control, and stdout files to $TANKverf_rad and compress -# - - if [[ -s ${bcoef_file} ]]; then - ${COMPRESS} "${bcoef_file}" - fi - - if [[ -s ${bcoef_ctl} ]]; then - ${COMPRESS} "${bcoef_ctl}" - fi - - - done # dtype in $gesanl loop + startmsg + "./${bcoef_exec}" < input >> "${pgmout}" 2>> errfile + export err=$? + if [[ "${err}" -ne 0 ]]; then + echo "FATAL ERROR: ${bcoef_exec} failed for instrument ${type} and datatype ${dtype}" + exit "${err}" + fi + + #------------------------------------------------------------------- + # move data, control, and stdout files to $TANKverf_rad and compress + # + + if [[ -s "${bcoef_file}" ]]; then + ${COMPRESS} "${bcoef_file}" + fi + + if [[ -s "${bcoef_ctl}" ]]; then + ${COMPRESS} "${bcoef_ctl}" + fi + + done # dtype in $gesanl loop done # type in $SATYPE loop - "${USHgfs}/rstprod.sh" if compgen -G "bcoef*.ieee_d*" > /dev/null || compgen -G "bcoef*.ctl*" > /dev/null; then - tar_file=radmon_bcoef.tar - tar -cf ${tar_file} bcoef*.ieee_d* bcoef*.ctl* - ${COMPRESS} ${tar_file} - mv "${tar_file}.${Z}" "${TANKverf_rad}" - - if [[ ${RAD_AREA} = "rgn" ]]; then - cwd=$(pwd) - cd "${TANKverf_rad}" || exit 1 - tar -xf "${tar_file}.${Z}" - rm -f "${tar_file}.${Z}" - cd "${cwd}" || exit 1 - fi + tar_file=radmon_bcoef.tar + tar -cf "${tar_file}" bcoef*.ieee_d* bcoef*.ctl* + ${COMPRESS} "${tar_file}" + mv "${tar_file}.${Z}" "${TANKverf_rad}" + + if [[ ${RAD_AREA} = "rgn" ]]; then + cwd=$(pwd) + cd "${TANKverf_rad}" || exit 1 + tar -xf "${tar_file}.${Z}" + rm -f "${tar_file}.${Z}" + cd "${cwd}" || exit 1 + fi fi - ################################################################################ # Post processing diff --git a/ush/radmon_verf_bcor.sh b/ush/radmon_verf_bcor.sh index 134f0d1dd1a..dcf9e2d2ec0 100755 --- a/ush/radmon_verf_bcor.sh +++ b/ush/radmon_verf_bcor.sh @@ -73,26 +73,25 @@ USE_ANL=${USE_ANL:-0} bcor_exec=radmon_bcor.x netcdf_boolean=".false." -if [[ ${RADMON_NETCDF} -eq 1 ]]; then - netcdf_boolean=".true." +if [[ "${RADMON_NETCDF}" -eq 1 ]]; then + netcdf_boolean=".true." fi -if [[ ${USE_ANL} -eq 1 ]]; then - gesanl="ges anl" +if [[ "${USE_ANL}" -eq 1 ]]; then + gesanl="ges anl" else - gesanl="ges" + gesanl="ges" fi - #-------------------------------------------------------------------- # Copy extraction program to working directory -cpreq "${EXECgfs}/${bcor_exec}" ./${bcor_exec} +cpreq "${EXECgfs}/${bcor_exec}" "./${bcor_exec}" #-------------------------------------------------------------------- # Run program for given time -export pgm=${bcor_exec} +export pgm="${bcor_exec}" iyy="${PDY:0:4}" imm="${PDY:4:2}" @@ -103,39 +102,35 @@ touch "./errfile" for type in ${SATYPE}; do - for dtype in ${gesanl}; do - - source prep_step - - if [[ ${dtype} == "anl" ]]; then - data_file="${type}_anl.${PDY}${cyc}.ieee_d" - bcor_file=bcor.${data_file} - ctl_file=${type}_anl.ctl - bcor_ctl=bcor.${ctl_file} - stdout_file=stdout.${type}_anl - bcor_stdout=bcor.${stdout_file} - input_file=${type}_anl - else - data_file="${type}.${PDY}${cyc}.ieee_d" - bcor_file=bcor.${data_file} - ctl_file=${type}.ctl - bcor_ctl=bcor.${ctl_file} - stdout_file=stdout.${type} - bcor_stdout=bcor.${stdout_file} - input_file=${type} - fi - - if [[ -f input ]]; then - rm -f input - fi - - # Check for 0 length input file here and avoid running - # the executable if $input_file doesn't exist or is 0 bytes - # - if [[ -s "${input_file}" ]]; then - nchanl=-999 - - cat << EOF > input + for dtype in ${gesanl}; do + + source prep_step + + if [[ ${dtype} == "anl" ]]; then + data_file="${type}_anl.${PDY}${cyc}.ieee_d" + bcor_file=bcor.${data_file} + ctl_file=${type}_anl.ctl + bcor_ctl=bcor.${ctl_file} + input_file=${type}_anl + else + data_file="${type}.${PDY}${cyc}.ieee_d" + bcor_file=bcor.${data_file} + ctl_file=${type}.ctl + bcor_ctl=bcor.${ctl_file} + input_file=${type} + fi + + if [[ -f input ]]; then + rm -f input + fi + + # Check for 0 length input file here and avoid running + # the executable if $input_file doesn't exist or is 0 bytes + # + if [[ -s "${input_file}" ]]; then + nchanl=-999 + + cat << EOF > input &INPUT satname='${type}', iyy=${iyy}, @@ -153,47 +148,45 @@ for type in ${SATYPE}; do / EOF - startmsg - ./${bcor_exec} < input >> "${pgmout}" 2>>errfile - export err=$? - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: ${bcor_exec} failed for instrument ${type} and datatype ${dtype}!" - exit "${err}" - fi - + startmsg + "./${bcor_exec}" < input >> "${pgmout}" 2>> errfile + export err=$? + if [[ "${err}" -ne 0 ]]; then + msg="FATAL ERROR: ${bcor_exec} failed for instrument ${type} and datatype ${dtype}!" + err_exit "${msg}" + fi -#------------------------------------------------------------------- -# move data, control, and stdout files to $TANKverf_rad and compress -# + #------------------------------------------------------------------- + # move data, control, and stdout files to $TANKverf_rad and compress + # - if [[ -s ${bcor_file} ]]; then - ${COMPRESS} "${bcor_file}" - fi + if [[ -s "${bcor_file}" ]]; then + ${COMPRESS} "${bcor_file}" + fi - if [[ -s ${bcor_ctl} ]]; then - ${COMPRESS} "${bcor_ctl}" - fi + if [[ -s "${bcor_ctl}" ]]; then + ${COMPRESS} "${bcor_ctl}" + fi - fi - done # dtype in $gesanl loop + fi + done # dtype in $gesanl loop done # type in $SATYPE loop - "${USHgfs}/rstprod.sh" tar_file=radmon_bcor.tar if compgen -G "bcor*.ieee_d*" > /dev/null || compgen -G "bcor*.ctl*" > /dev/null; then - tar -cf "${tar_file}" bcor*.ieee_d* bcor*.ctl* - ${COMPRESS} ${tar_file} - mv "${tar_file}.${Z}" "${TANKverf_rad}/." - - if [[ ${RAD_AREA} = "rgn" ]]; then - cwd=$(pwd) - cd "${TANKverf_rad}" || exit 1 - tar -xf "${tar_file}.${Z}" - rm -f "${tar_file}.${Z}" - cd "${cwd}" || exit 1 - fi + tar -cf "${tar_file}" bcor*.ieee_d* bcor*.ctl* + ${COMPRESS} "${tar_file}" + mv "${tar_file}.${Z}" "${TANKverf_rad}/." + + if [[ ${RAD_AREA} = "rgn" ]]; then + cwd=$(pwd) + cd "${TANKverf_rad}" || exit 1 + tar -xf "${tar_file}.${Z}" + rm -f "${tar_file}.${Z}" + cd "${cwd}" || exit 1 + fi fi ################################################################################ diff --git a/ush/radmon_verf_time.sh b/ush/radmon_verf_time.sh index 0158697304c..9f9ab5471df 100755 --- a/ush/radmon_verf_time.sh +++ b/ush/radmon_verf_time.sh @@ -81,7 +81,6 @@ diag_hdr=diag_hdr.txt diag=diag.txt obs_err=obs_err.txt -obs_hdr=obs_hdr.txt pen_err=pen_err.txt pen_hdr=pen_hdr.txt @@ -91,8 +90,8 @@ count_hdr=count_hdr.txt count_err=count_err.txt netcdf_boolean=".false." -if [[ ${RADMON_NETCDF} -eq 1 ]]; then - netcdf_boolean=".true." +if [[ "${RADMON_NETCDF}" -eq 1 ]]; then + netcdf_boolean=".true." fi DO_DATA_RPT=${DO_DATA_RPT:-1} @@ -108,13 +107,12 @@ LITTLE_ENDIAN=${LITTLE_ENDIAN:-0} time_exec=radmon_time.x USE_ANL=${USE_ANL:-0} -if [[ ${USE_ANL} -eq 1 ]]; then - gesanl="ges anl" +if [[ "${USE_ANL}" -eq 1 ]]; then + gesanl="ges anl" else - gesanl="ges" + gesanl="ges" fi - #-------------------------------------------------------------------- # Copy extraction program and base files to working directory #------------------------------------------------------------------- @@ -126,22 +124,22 @@ idd="${PDY:6:2}" ihh=${cyc} local_base="local_base" -if [[ ${DO_DATA_RPT} -eq 1 ]]; then - - if [[ -e ${base_file}.${Z} ]]; then - cpreq "${base_file}.${Z}" "./${local_base}.${Z}" - ${UNCOMPRESS} "${local_base}.${Z}" - else - cpreq "${base_file}" ./${local_base} - fi - - if [[ ! -s ./${local_base} ]]; then - echo "RED LIGHT: local_base file not found" - else - echo "Confirming local_base file is good = ${local_base}" - tar -xf ./${local_base} - echo "local_base is untarred" - fi +if [[ "${DO_DATA_RPT}" -eq 1 ]]; then + + if [[ -e "${base_file}.${Z}" ]]; then + cpreq "${base_file}.${Z}" "./${local_base}.${Z}" + ${UNCOMPRESS} "${local_base}.${Z}" + else + cpreq "${base_file}" "./${local_base}" + fi + + if [[ ! -s "./${local_base}" ]]; then + echo "RED LIGHT: local_base file not found" + else + echo "Confirming local_base file is good = ${local_base}" + tar -xf "./${local_base}" + echo "local_base is untarred" + fi fi export pgm=${time_exec} @@ -150,41 +148,40 @@ export pgm=${time_exec} #-------------------------------------------------------------------- for type in ${SATYPE}; do - if [[ ! -s ${type} ]]; then - echo "ZERO SIZED: ${type}" - continue - fi - - source prep_step - - for dtype in ${gesanl}; do - - if [[ -f input ]] - then - rm -f input - fi - - if [[ ${dtype} == "anl" ]]; then - data_file="${type}_anl.${PDY}${cyc}.ieee_d" - ctl_file=${type}_anl.ctl - time_ctl=time.${ctl_file} - else - data_file="${type}.${PDY}${cyc}.ieee_d" - ctl_file=${type}.ctl - time_ctl=time.${ctl_file} - fi - - if [[ ${REGIONAL_RR} -eq 1 ]]; then - time_file=${rgnHH}.time.${data_file}.${rgnTM} - else - time_file=time.${data_file} - fi - -#-------------------------------------------------------------------- -# Run program for given satellite/instrument -#-------------------------------------------------------------------- - nchanl=-999 - cat << EOF > input + if [[ ! -s ${type} ]]; then + echo "ZERO SIZED: ${type}" + continue + fi + + source prep_step + + for dtype in ${gesanl}; do + + if [[ -f input ]]; then + rm -f input + fi + + if [[ "${dtype}" == "anl" ]]; then + data_file="${type}_anl.${PDY}${cyc}.ieee_d" + ctl_file="${type}_anl.ctl" + time_ctl="time.${ctl_file}" + else + data_file="${type}.${PDY}${cyc}.ieee_d" + ctl_file="${type}.ctl" + time_ctl="time.${ctl_file}" + fi + + if [[ "${REGIONAL_RR}" -eq 1 ]]; then + time_file="${rgnHH}.time.${data_file}.${rgnTM}" + else + time_file="time.${data_file}" + fi + + #-------------------------------------------------------------------- + # Run program for given satellite/instrument + #-------------------------------------------------------------------- + nchanl=-999 + cat << EOF > input &INPUT satname='${type}', iyy=${iyy}, @@ -202,62 +199,59 @@ for type in ${SATYPE}; do / EOF - ./${time_exec} < input >> stdout."${type}" 2>>errfile - export err=$? + "./${time_exec}" < input >> "stdout.${type}" 2>> errfile + export err=$? - if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: failed to calculate radiance time statistics for instrument ${type} and datatype ${dtype}!" - exit "${err}" - fi + if [[ "${err}" -ne 0 ]]; then + echo "FATAL ERROR: failed to calculate radiance time statistics for instrument ${type} and datatype ${dtype}!" + exit "${err}" + fi -#------------------------------------------------------------------- -# move data, control, and stdout files to $TANKverf_rad and compress -#------------------------------------------------------------------- - cat "stdout.${type}" >> stdout.time + #------------------------------------------------------------------- + # move data, control, and stdout files to $TANKverf_rad and compress + #------------------------------------------------------------------- + cat "stdout.${type}" >> stdout.time - if [[ -s ${time_file} ]]; then - ${COMPRESS} "${time_file}" - fi + if [[ -s "${time_file}" ]]; then + ${COMPRESS} "${time_file}" + fi - if [[ -s ${time_ctl} ]]; then - ${COMPRESS} "${time_ctl}" - fi + if [[ -s "${time_ctl}" ]]; then + ${COMPRESS} "${time_ctl}" + fi - done + done done - "${USHgfs}/rstprod.sh" if compgen -G "time*.ieee_d*" > /dev/null || compgen -G "time*.ctl*" > /dev/null; then - tar_file=radmon_time.tar - tar -cf "${tar_file}" time*.ieee_d* time*.ctl* - ${COMPRESS} ${tar_file} - mv "${tar_file}.${Z}" "${TANKverf_rad}/." - - if [[ ${RAD_AREA} = "rgn" ]]; then - cwd=$(pwd) - cd "${TANKverf_rad}" || exit 1 - tar -xf "${tar_file}.${Z}" - rm -f "${tar_file}.${Z}" - cd "${cwd}" || exit 1 - fi + tar_file=radmon_time.tar + tar -cf "${tar_file}" time*.ieee_d* time*.ctl* + ${COMPRESS} "${tar_file}" + mv "${tar_file}.${Z}" "${TANKverf_rad}/." + + if [[ "${RAD_AREA}" == "rgn" ]]; then + cwd=$(pwd) + cd "${TANKverf_rad}" || exit 1 + tar -xf "${tar_file}.${Z}" + rm -f "${tar_file}.${Z}" + cd "${cwd}" || exit 1 + fi fi - - #################################################################### #------------------------------------------------------------------- # Begin error analysis and reporting #------------------------------------------------------------------- #################################################################### -if [[ ${DO_DATA_RPT} -eq 1 ]]; then +if [[ "${DO_DATA_RPT}" -eq 1 ]]; then -#--------------------------- -# build report disclaimer -# - cat << EOF > ${disclaimer} + #--------------------------- + # build report disclaimer + # + cat << EOF > "${disclaimer}" *********************** WARNING *************************** @@ -266,16 +260,15 @@ RECEIVED. PLEASE DIRECT REPLIES TO edward.safford@noaa.gov *********************** WARNING *************************** EOF + #------------------------------------------------------------------- + # Check for missing diag files + # + tmp_satype="./tmp_satype.txt" + echo "${SATYPE}" > "${tmp_satype}" + "${USHgfs}/radmon_diag_ck.sh" --rad "${radstat}" --sat "${tmp_satype}" --out "${diag}" -#------------------------------------------------------------------- -# Check for missing diag files -# - tmp_satype="./tmp_satype.txt" - echo "${SATYPE}" > ${tmp_satype} - "${USHgfs}/radmon_diag_ck.sh" --rad "${radstat}" --sat "${tmp_satype}" --out "${diag}" - - if [[ -s ${diag} ]]; then - cat << EOF > ${diag_hdr} + if [[ -s "${diag}" ]]; then + cat << EOF > "${diag_hdr}" Problem Reading Diagnostic File @@ -285,137 +278,134 @@ EOF EOF - cat ${diag_hdr} >> ${diag_report} - cat ${diag} >> ${diag_report} - - echo >> ${diag_report} - - rm -f "${diag_hdr}" - fi - -#------------------------------------------------------------------- -# move warning notification to TANKverf -# - if [[ -s ${diag} ]]; then - lines=$(wc -l <${diag}) - echo "lines in diag = ${lines}" - - if [[ ${lines} -gt 0 ]]; then - cat "${diag_report}" - cpfs "${diag}" "${TANKverf_rad}/bad_diag.${PDY}${cyc}" - else - rm -f "${diag_report}" - fi - fi - - - - #---------------------------------------------------------------- - # Identify bad_pen and bad_chan files for this cycle and - # previous cycle - - bad_pen=bad_pen.${PDY}${cyc} - bad_chan=bad_chan.${PDY}${cyc} - low_count=low_count.${PDY}${cyc} - - qdate=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") - pday="${qdate:0:8}" - - prev_bad_pen=bad_pen.${qdate} - prev_bad_chan=bad_chan.${qdate} - prev_low_count=low_count.${qdate} - - prev_bad_pen=${TANKverf_radM1}/${prev_bad_pen} - prev_bad_chan=${TANKverf_radM1}/${prev_bad_chan} - prev_low_count=${TANKverf_radM1}/${prev_low_count} - - if [[ -s ${bad_pen} ]]; then - echo "pad_pen = ${bad_pen}" - fi - if [[ -s ${prev_bad_pen} ]]; then - echo "prev_pad_pen = ${prev_bad_pen}" - fi - - if [[ -s ${bad_chan} ]]; then - echo "bad_chan = ${bad_chan}" - fi - if [[ -s ${prev_bad_chan} ]]; then - echo "prev_bad_chan = ${prev_bad_chan}" - fi - if [[ -s ${low_count} ]]; then - echo "low_count = ${low_count}" - fi - if [[ -s ${prev_low_count} ]]; then - echo "prev_low_count = ${prev_low_count}" - fi - - do_pen=0 - do_chan=0 - do_cnt=0 - - if [[ -s ${bad_pen} && -s ${prev_bad_pen} ]]; then - do_pen=1 - fi - - if [[ -s ${low_count} && -s ${prev_low_count} ]]; then - do_cnt=1 - fi - - #-------------------------------------------------------------------- - # avoid doing the bad_chan report for REGIONAL_RR sources -- because - # they run hourly they often have 0 count channels for off-hour runs. - # - if [[ -s ${bad_chan} && -s ${prev_bad_chan} && REGIONAL_RR -eq 0 ]]; then - do_chan=1 - fi - - #-------------------------------------------------------------------- - # Remove extra spaces in new bad_pen & low_count files - # - if [[ -s ${bad_pen} ]]; then - gawk '{$1=$1}1' "${bad_pen}" > tmp.bad_pen - mv -f tmp.bad_pen "${bad_pen}" - fi - if [[ -s ${low_count} ]]; then - gawk '{$1=$1}1' "${low_count}" > tmp.low_count - mv -f tmp.low_count "${low_count}" - fi - - echo " do_pen, do_chan, do_cnt = ${do_pen}, ${do_chan}, ${do_cnt}" - echo " diag_report = ${diag_report} " - if [[ ${do_pen} -eq 1 || ${do_chan} -eq 1 || ${do_cnt} -eq 1 || -s ${diag_report} ]]; then - - if [[ ${do_pen} -eq 1 ]]; then - - echo "calling radmon_err_rpt for pen" - ${radmon_err_rpt} "${prev_bad_pen}" "${bad_pen}" pen "${qdate}" \ - "${PDY}${cyc}" ${diag_report} ${pen_err} - fi - - if [[ ${do_chan} -eq 1 ]]; then - - echo "calling radmon_err_rpt for chan" - ${radmon_err_rpt} "${prev_bad_chan}" "${bad_chan}" chan "${qdate}" \ - "${PDY}${cyc}" ${diag_report} ${chan_err} - fi - - if [[ ${do_cnt} -eq 1 ]]; then - - echo "calling radmon_err_rpt for cnt" - ${radmon_err_rpt} "${prev_low_count}" "${low_count}" cnt "${qdate}" \ - "${PDY}${cyc}" ${diag_report} ${count_err} - fi - - #------------------------------------------------------------------- - # put together the unified error report with any obs, chan, and - # penalty problems and mail it - - if [[ -s ${obs_err} || -s ${pen_err} || -s ${chan_err} || -s ${count_err} || -s ${diag_report} ]]; then - - echo DOING ERROR REPORTING - - - cat << EOF > ${report} + { + cat "${diag_hdr}" + cat "${diag}" + echo + } >> "${diag_report}" + + rm -f "${diag_hdr}" + fi + + #------------------------------------------------------------------- + # move warning notification to TANKverf + # + if [[ -s "${diag}" ]]; then + lines=$(wc -l < "${diag}") + echo "lines in diag = ${lines}" + + if [[ "${lines}" -gt 0 ]]; then + cat "${diag_report}" + cpfs "${diag}" "${TANKverf_rad}/bad_diag.${PDY}${cyc}" + else + rm -f "${diag_report}" + fi + fi + + #---------------------------------------------------------------- + # Identify bad_pen and bad_chan files for this cycle and + # previous cycle + + bad_pen="bad_pen.${PDY}${cyc}" + bad_chan="bad_chan.${PDY}${cyc}" + low_count="low_count.${PDY}${cyc}" + + qdate=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") + + prev_bad_pen=bad_pen.${qdate} + prev_bad_chan=bad_chan.${qdate} + prev_low_count=low_count.${qdate} + + prev_bad_pen=${TANKverf_radM1}/${prev_bad_pen} + prev_bad_chan=${TANKverf_radM1}/${prev_bad_chan} + prev_low_count=${TANKverf_radM1}/${prev_low_count} + + if [[ -s "${bad_pen}" ]]; then + echo "pad_pen = ${bad_pen}" + fi + if [[ -s "${prev_bad_pen}" ]]; then + echo "prev_pad_pen = ${prev_bad_pen}" + fi + + if [[ -s "${bad_chan}" ]]; then + echo "bad_chan = ${bad_chan}" + fi + if [[ -s "${prev_bad_chan}" ]]; then + echo "prev_bad_chan = ${prev_bad_chan}" + fi + if [[ -s "${low_count}" ]]; then + echo "low_count = ${low_count}" + fi + if [[ -s "${prev_low_count}" ]]; then + echo "prev_low_count = ${prev_low_count}" + fi + + do_pen=0 + do_chan=0 + do_cnt=0 + + if [[ -s "${bad_pen}" && -s "${prev_bad_pen}" ]]; then + do_pen=1 + fi + + if [[ -s "${low_count}" && -s "${prev_low_count}" ]]; then + do_cnt=1 + fi + + #-------------------------------------------------------------------- + # avoid doing the bad_chan report for REGIONAL_RR sources -- because + # they run hourly they often have 0 count channels for off-hour runs. + # + if [[ -s "${bad_chan}" && -s "${prev_bad_chan}" && "${REGIONAL_RR}" -eq 0 ]]; then + do_chan=1 + fi + + #-------------------------------------------------------------------- + # Remove extra spaces in new bad_pen & low_count files + # + if [[ -s "${bad_pen}" ]]; then + gawk '{$1=$1}1' "${bad_pen}" > tmp.bad_pen + mv -f tmp.bad_pen "${bad_pen}" + fi + if [[ -s "${low_count}" ]]; then + gawk '{$1=$1}1' "${low_count}" > tmp.low_count + mv -f tmp.low_count "${low_count}" + fi + + echo " do_pen, do_chan, do_cnt = ${do_pen}, ${do_chan}, ${do_cnt}" + echo " diag_report = ${diag_report} " + if [[ "${do_pen}" -eq 1 || "${do_chan}" -eq 1 || "${do_cnt}" -eq 1 || -s "${diag_report}" ]]; then + + if [[ ${do_pen} -eq 1 ]]; then + + echo "calling radmon_err_rpt for pen" + ${radmon_err_rpt} "${prev_bad_pen}" "${bad_pen}" pen "${qdate}" \ + "${PDY}${cyc}" "${diag_report}" "${pen_err}" + fi + + if [[ "${do_chan}" -eq 1 ]]; then + + echo "calling radmon_err_rpt for chan" + ${radmon_err_rpt} "${prev_bad_chan}" "${bad_chan}" chan "${qdate}" \ + "${PDY}${cyc}" "${diag_report}" "${chan_err}" + fi + + if [[ "${do_cnt}" -eq 1 ]]; then + + echo "calling radmon_err_rpt for cnt" + ${radmon_err_rpt} "${prev_low_count}" "${low_count}" cnt "${qdate}" \ + "${PDY}${cyc}" "${diag_report}" "${count_err}" + fi + + #------------------------------------------------------------------- + # put together the unified error report with any obs, chan, and + # penalty problems and mail it + + if [[ -s "${obs_err}" || -s "${pen_err}" || -s "${chan_err}" || -s "${count_err}" || -s "${diag_report}" ]]; then + + echo DOING ERROR REPORTING + + cat << EOF > "${report}" Radiance Monitor warning report Net: ${RADMON_SUFFIX} @@ -424,16 +414,16 @@ Radiance Monitor warning report EOF - if [[ -s ${diag_report} ]]; then - echo OUTPUTING DIAG_REPORT - cat ${diag_report} >> ${report} - fi + if [[ -s "${diag_report}" ]]; then + echo OUTPUTING DIAG_REPORT + cat "${diag_report}" >> "${report}" + fi - if [[ -s ${chan_err} ]]; then + if [[ -s "${chan_err}" ]]; then - echo OUTPUTING CHAN_ERR + echo OUTPUTING CHAN_ERR - cat << EOF > ${chan_hdr} + cat << EOF > "${chan_hdr}" The following channels report 0 observational counts over the past two cycles: @@ -442,14 +432,14 @@ EOF EOF - cat ${chan_hdr} >> ${report} - cat ${chan_err} >> ${report} + cat "${chan_hdr}" >> "${report}" + cat "${chan_err}" >> "${report}" - fi + fi - if [[ -s ${count_err} ]]; then + if [[ -s "${count_err}" ]]; then - cat << EOF > ${count_hdr} + cat << EOF > "${count_hdr}" @@ -460,14 +450,13 @@ Satellite/Instrument Obs Count Avg Count EOF - cat ${count_hdr} >> ${report} - cat ${count_err} >> ${report} - fi + cat "${count_hdr}" >> "${report}" + cat "${count_err}" >> "${report}" + fi + if [[ -s "${pen_err}" ]]; then - if [[ -s ${pen_err} ]]; then - - cat << EOF > ${pen_hdr} + cat << EOF > "${pen_hdr}" Penalty values outside of the established normal range were found @@ -477,51 +466,53 @@ EOF ============ ======= ====== Cycle Penalty Bound ----- ------- ----- EOF - cat "${pen_hdr}" >> "${report}" - cat "${pen_err}" >> "${report}" - rm -f "${pen_hdr}" - rm -f "${pen_err}" - fi - - echo >> ${report} - cat ${disclaimer} >> ${report} - echo >> ${report} - fi - - #------------------------------------------------------------------- - # dump report to log file - # - if [[ -s ${report} ]]; then - lines=$(wc -l <${report}) - if [[ ${lines} -gt 2 ]]; then - cat ${report} - - cpfs ${report} "${TANKverf_rad}/warning.${PDY}${cyc}" - fi - fi - - fi - - #------------------------------------------------------------------- - # copy new bad_pen, bad_chan, and low_count files to $TANKverf_rad - # - if [[ -s ${bad_chan} ]]; then - mv "${bad_chan}" "${TANKverf_rad}/." - fi - - if [[ -s ${bad_pen} ]]; then - mv "${bad_pen}" "${TANKverf_rad}/." - fi - - if [[ -s ${low_count} ]]; then - mv "${low_count}" "${TANKverf_rad}/." - fi + cat "${pen_hdr}" >> "${report}" + cat "${pen_err}" >> "${report}" + rm -f "${pen_hdr}" + rm -f "${pen_err}" + fi + + { + echo + cat "${disclaimer}" + echo + } >> "${report}" + fi + + #------------------------------------------------------------------- + # dump report to log file + # + if [[ -s "${report}" ]]; then + lines=$(wc -l < "${report}") + if [[ "${lines}" -gt 2 ]]; then + cat "${report}" + + cpfs "${report}" "${TANKverf_rad}/warning.${PDY}${cyc}" + fi + fi + + fi + + #------------------------------------------------------------------- + # copy new bad_pen, bad_chan, and low_count files to $TANKverf_rad + # + if [[ -s "${bad_chan}" ]]; then + mv "${bad_chan}" "${TANKverf_rad}/." + fi + + if [[ -s "${bad_pen}" ]]; then + mv "${bad_pen}" "${TANKverf_rad}/." + fi + + if [[ -s "${low_count}" ]]; then + mv "${low_count}" "${TANKverf_rad}/." + fi fi - for type in ${SATYPE}; do - rm -f "stdout.${type}" - done +for type in ${SATYPE}; do + rm -f "stdout.${type}" +done ################################################################################ #------------------------------------------------------------------- diff --git a/ush/regrid_gsiSfcIncr_to_tile.sh b/ush/regrid_gsiSfcIncr_to_tile.sh index 5e2fe1cf59f..ffc3d9b8200 100755 --- a/ush/regrid_gsiSfcIncr_to_tile.sh +++ b/ush/regrid_gsiSfcIncr_to_tile.sh @@ -14,8 +14,8 @@ CASE_IN=${CASE_IN:-${CASE_ENS}} LFHR=${LFHR:-6} # get resolutions -LONB_CASE_IN=$((4*${CASE_IN:1})) -LATB_CASE_IN=$((2*${CASE_IN:1})) +LONB_CASE_IN=$((4 * ${CASE_IN:1})) +LATB_CASE_IN=$((2 * ${CASE_IN:1})) ntiles=6 @@ -23,7 +23,7 @@ APREFIX_ENS="enkfgdas.t${cyc}z." LSOIL_INCR=${LSOIL_INCR:-2} -export n_vars=$(( LSOIL_INCR*2 )) +export n_vars=$((LSOIL_INCR * 2)) soilt_incr_vars=$(seq -s ',' -f '"soilt%g_inc"' 1 "${LSOIL_INCR}") slc_incr_vars=$(seq -s ',' -f '"slc%g_inc"' 1 "${LSOIL_INCR}") @@ -46,10 +46,10 @@ regrid_nml_tmpl="${PARMgfs}/regrid_sfc/regrid.nml_tmpl" if [[ "${LFHR}" -ge 0 ]]; then soilinc_fhrs=("${LFHR}") -else # construct restart times for deterministic member - soilinc_fhrs=("${assim_freq}") # increment file at middle of window - if [[ "${DOIAU:-}" == "YES" ]]; then # Update surface restarts at beginning of window - half_window=$(( assim_freq / 2 )) +else # construct restart times for deterministic member + soilinc_fhrs=("${assim_freq}") # increment file at middle of window + if [[ "${DOIAU:-}" == "YES" ]]; then # Update surface restarts at beginning of window + half_window=$((assim_freq / 2)) soilinc_fhrs+=("${half_window}") fi fi @@ -65,22 +65,22 @@ chmod 755 cmdfile_in.0 # Append fixed files command file to master command file { -echo "#!/bin/bash" + echo "#!/bin/bash" -# input, fixed files -echo "cpreq ${FIXorog}/${CASE_IN}/gaussian.${LONB_CASE_IN}.${LATB_CASE_IN}.nc \ + # input, fixed files + echo "cpreq ${FIXorog}/${CASE_IN}/gaussian.${LONB_CASE_IN}.${LATB_CASE_IN}.nc \ ${DATA}/gaussian_scrip.nc" -# output, fixed files -echo "cpreq ${FIXorog}/${CASE_OUT}/${CASE_OUT}_mosaic.nc \ + # output, fixed files + echo "cpreq ${FIXorog}/${CASE_OUT}/${CASE_OUT}_mosaic.nc \ ${DATA}/${CASE_OUT}_mosaic.nc" -for n in $(seq 1 "${ntiles}"); do - echo "cpreq ${FIXorog}/${CASE_OUT}/sfc/${CASE_OUT}.mx${OCNRES_OUT}.vegetation_type.tile${n}.nc \ + for n in $(seq 1 "${ntiles}"); do + echo "cpreq ${FIXorog}/${CASE_OUT}/sfc/${CASE_OUT}.mx${OCNRES_OUT}.vegetation_type.tile${n}.nc \ ${DATA}/vegetation_type.tile${n}.nc" - echo "cpreq ${FIXorog}/${CASE_OUT}/${CASE_OUT}_grid.tile${n}.nc \ + echo "cpreq ${FIXorog}/${CASE_OUT}/${CASE_OUT}_grid.tile${n}.nc \ ${DATA}/${CASE_OUT}_grid.tile${n}.nc" -done + done } >> cmdfile_in.0 if [[ "${NMEM_REGRID}" -gt 1 ]]; then @@ -101,64 +101,64 @@ if [[ "${NMEM_REGRID}" -gt 1 ]]; then # Create commands to stage input files { - echo "#!/bin/bash" - - echo "mkdir -p ${DATA}/${memdir}" + echo "#!/bin/bash" - for FHR in "${soilinc_fhrs[@]}"; do - echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}increment.sfc.i00${FHR}.nc \ - ${DATA}/${memdir}/sfci00${FHR}.nc" - done + echo "mkdir -p ${DATA}/${memdir}" - if [[ "${DO_LAND_IAU}" = ".true." ]]; then - for FHI in "${landifhrs[@]}"; do - echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}increment.sfc.i00${FHI}.nc \ - ${DATA}/${memdir}/sfci00${FHI}.nc" + for FHR in "${soilinc_fhrs[@]}"; do + echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}increment.sfc.i00${FHR}.nc \ + ${DATA}/${memdir}/sfci00${FHR}.nc" done - fi + + if [[ "${DO_LAND_IAU}" = ".true." ]]; then + for FHI in "${landifhrs[@]}"; do + echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}increment.sfc.i00${FHI}.nc \ + ${DATA}/${memdir}/sfci00${FHI}.nc" + done + fi } >> "cmdfile_in.${imem}" # Create commands to copy output files { - echo "#!/bin/bash" + echo "#!/bin/bash" + + if [[ "${DO_LAND_IAU}" = ".false." || "${RUN}" == "gdas" || "${RUN}" == "gfs" ]]; then + for FHR in "${soilinc_fhrs[@]}"; do + for n in $(seq 1 "${ntiles}"); do + echo "cpfs ${DATA}/${memdir}/sfci00${FHR}.mem${imem}.tile${n}.nc \ + ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.i00${FHR}.tile${n}.nc" + done + done + fi - if [[ "${DO_LAND_IAU}" = ".false." || "${RUN}" == "gdas" || "${RUN}" == "gfs" ]]; then - for FHR in "${soilinc_fhrs[@]}"; do + if [[ "${DO_LAND_IAU}" = ".true." ]]; then for n in $(seq 1 "${ntiles}"); do - echo "cpfs ${DATA}/${memdir}/sfci00${FHR}.mem${imem}.tile${n}.nc \ - ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.i00${FHR}.tile${n}.nc" + echo "cpfs ${DATA}/${memdir}/sfci.mem${imem}.tile${n}.nc \ + ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.tile${n}.nc" done - done - fi - - if [[ "${DO_LAND_IAU}" = ".true." ]]; then - for n in $(seq 1 "${ntiles}"); do - echo "cpfs ${DATA}/${memdir}/sfci.mem${imem}.tile${n}.nc \ - ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.tile${n}.nc" - done - fi + fi } >> "cmdfile_out.${imem}" - done # for imem in $(seq 1 "${NMEM_REGRID}"); do + done # for imem in $(seq 1 "${NMEM_REGRID}"); do in_dir=$(seq -s ", " -f "'./mem%03g/'" 1 "${NMEM_REGRID}") -else # deterministic member only (NMEM_REGRID=1) +else # deterministic member only (NMEM_REGRID=1) echo "INFO: Preparing to regrid surface increments for deterministic member." # Create commands to stage input files and append to the cmdfile.0 { - for FHR in "${soilinc_fhrs[@]}"; do - echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}ensmean_increment.sfc.i00${FHR}.nc \ - ${DATA}/sfci00${FHR}.nc" - done - - if [[ "${DO_LAND_IAU}" = ".true." ]]; then - for FHI in "${landifhrs[@]}"; do - echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}ensmean_increment.sfc.i00${FHI}.nc \ - ${DATA}/sfci00${FHI}.nc" + for FHR in "${soilinc_fhrs[@]}"; do + echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}ensmean_increment.sfc.i00${FHR}.nc \ + ${DATA}/sfci00${FHR}.nc" done - fi + + if [[ "${DO_LAND_IAU}" = ".true." ]]; then + for FHI in "${landifhrs[@]}"; do + echo "cpreq ${COMIN_SOIL_ANALYSIS_MEM}/${APREFIX_ENS}ensmean_increment.sfc.i00${FHI}.nc \ + ${DATA}/sfci00${FHI}.nc" + done + fi } >> "cmdfile_in.0" in_dir="'./'" @@ -167,26 +167,25 @@ else # deterministic member only (NMEM_REGRID=1) touch cmdfile_out.0 chmod 755 cmdfile_out.0 { - echo "#!/bin/bash" + echo "#!/bin/bash" - if [[ "${DO_LAND_IAU}" = ".false." || "${RUN}" == "gdas" || "${RUN}" == "gfs" ]]; then - for FHR in "${soilinc_fhrs[@]}"; do - for n in $(seq 1 "${ntiles}"); do - echo "cpfs ${DATA}/sfci00${FHR}.mem1.tile${n}.nc \ - ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.i00${FHR}.tile${n}.nc" + if [[ "${DO_LAND_IAU}" = ".false." || "${RUN}" == "gdas" || "${RUN}" == "gfs" ]]; then + for FHR in "${soilinc_fhrs[@]}"; do + for n in $(seq 1 "${ntiles}"); do + echo "cpfs ${DATA}/sfci00${FHR}.mem1.tile${n}.nc \ + ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.i00${FHR}.tile${n}.nc" + done done - done - fi + fi - if [[ "${DO_LAND_IAU}" = ".true." ]]; then - for n in $(seq 1 "${ntiles}"); do - echo "cpfs ${DATA}/sfci.mem1.tile${n}.nc \ - ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.tile${n}.nc" - done - fi + if [[ "${DO_LAND_IAU}" = ".true." ]]; then + for n in $(seq 1 "${ntiles}"); do + echo "cpfs ${DATA}/sfci.mem1.tile${n}.nc \ + ${COMOUT_ATMOS_ANALYSIS_MEM}/increment.sfc.tile${n}.nc" + done + fi } >> "cmdfile_out.0" - fi # Create master MPMD command files for input and output @@ -240,10 +239,10 @@ if [[ "${DO_LAND_IAU}" = ".false." || "${RUN}" == "gdas" || "${RUN}" == "gfs" ]] # Run regrid executable export pgm="${REGRID_EXEC}" ${APRUN_REGRID} "${REGRID_EXEC}" - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "${REGRID_EXEC} failed to regrid soil increments (without LANDIAU), ABORT!" - fi + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "${REGRID_EXEC} failed to regrid soil increments (without LANDIAU), ABORT!" + fi done fi @@ -261,11 +260,11 @@ if [[ "${DO_LAND_IAU}" = ".true." ]]; then # Run regrid executable export pgm="${REGRID_EXEC}" - ${APRUN_REGRID} "${REGRID_EXEC}" - export err=$? - if [[ ${err} -ne 0 ]]; then - err_exit "${pgm} failed to regrid soil increments (with LANDIAU), ABORT!" - fi + ${APRUN_REGRID} "${REGRID_EXEC}" + export err=$? + if [[ ${err} -ne 0 ]]; then + err_exit "${pgm} failed to regrid soil increments (with LANDIAU), ABORT!" + fi fi # Run MPMD to save output files diff --git a/ush/rstprod.sh b/ush/rstprod.sh index 8370c79fa8c..56936eda221 100755 --- a/ush/rstprod.sh +++ b/ush/rstprod.sh @@ -3,15 +3,15 @@ #--------------------------------------------------------- # rstprod.sh # -# Restrict data from select sensors and satellites +# Restrict data from select sensors and satellites #--------------------------------------------------------- # Restrict select sensors and satellites export CHGRP_CMD=${CHGRP_CMD:-"chgrp ${group_name:-rstprod}"} rlist="saphir abi_g16" -for rtype in $rlist; do +for rtype in ${rlist}; do if compgen -G "*${rtype}*" > /dev/null; then - ${CHGRP_CMD} *${rtype}* + ${CHGRP_CMD} ./*"${rtype}"* fi done diff --git a/ush/run_mpmd.sh b/ush/run_mpmd.sh index 6ffbd3106d1..89e65daaa97 100755 --- a/ush/run_mpmd.sh +++ b/ush/run_mpmd.sh @@ -34,12 +34,12 @@ cmdfile=${1:?"run_mpmd requires an input file containing commands to execute in # If USE_CFP is not set, run in serial mode if [[ "${USE_CFP:-}" != "YES" ]]; then - echo "INFO: Using serial mode for MPMD job" - chmod 755 "${cmdfile}" - bash +x "${cmdfile}" > mpmd.out 2>&1 - rc=$? - cat mpmd.out - exit "${rc}" + echo "INFO: Using serial mode for MPMD job" + chmod 755 "${cmdfile}" + bash +x "${cmdfile}" > mpmd.out 2>&1 + rc=$? + cat mpmd.out + exit "${rc}" fi # Set OMP_NUM_THREADS to 1 to avoid oversubscription when doing MPMD @@ -58,56 +58,56 @@ cat << EOF INFO: The proc_num corresponds to the line in '${mpmd_cmdfile}' EOF -if [[ "${launcher:-}" =~ ^srun.* ]]; then # srun-based system e.g. Hera, Orion, etc. - - # Slurm requires a counter in front of each line in the script - # Read the incoming cmdfile and create srun usable cmdfile - nm=0 - # shellcheck disable=SC2312 - while IFS= read -r line; do - echo "${nm} ${line}" >> "${mpmd_cmdfile}" - ((nm=nm+1)) - done < "${cmdfile}" - - set +e - # shellcheck disable=SC2086 - ${launcher:-} ${mpmd_opt:-} -n ${nprocs} "${mpmd_cmdfile}" - err=$? - set_strict - -elif [[ "${launcher:-}" =~ ^mpiexec.* ]]; then # mpiexec - - # Redirect output from each process to its own stdout - # Read the incoming cmdfile and create mpiexec usable cmdfile - nm=0 - echo "#!/bin/bash" >> "${mpmd_cmdfile}" - # shellcheck disable=SC2312 - while IFS= read -r line; do - echo "${line} > mpmd.${nm}.out" >> "${mpmd_cmdfile}" - ((nm=nm+1)) - done < "${cmdfile}" - chmod 755 "${mpmd_cmdfile}" - - # shellcheck disable=SC2086 - ${launcher:-} -np ${nprocs} ${mpmd_opt:-} "${mpmd_cmdfile}" - err=$? +if [[ "${launcher:-}" =~ ^srun.* ]]; then # srun-based system e.g. Hera, Orion, etc. + + # Slurm requires a counter in front of each line in the script + # Read the incoming cmdfile and create srun usable cmdfile + nm=0 + # shellcheck disable=SC2312 + while IFS= read -r line; do + echo "${nm} ${line}" >> "${mpmd_cmdfile}" + ((nm = nm + 1)) + done < "${cmdfile}" + + set +e + # shellcheck disable=SC2086 + ${launcher:-} ${mpmd_opt:-} -n ${nprocs} "${mpmd_cmdfile}" + err=$? + set_strict + +elif [[ "${launcher:-}" =~ ^mpiexec.* ]]; then # mpiexec + + # Redirect output from each process to its own stdout + # Read the incoming cmdfile and create mpiexec usable cmdfile + nm=0 + echo "#!/bin/bash" >> "${mpmd_cmdfile}" + # shellcheck disable=SC2312 + while IFS= read -r line; do + echo "${line} > mpmd.${nm}.out" >> "${mpmd_cmdfile}" + ((nm = nm + 1)) + done < "${cmdfile}" + chmod 755 "${mpmd_cmdfile}" + + # shellcheck disable=SC2086 + ${launcher:-} -np ${nprocs} ${mpmd_opt:-} "${mpmd_cmdfile}" + err=$? else - echo "FATAL ERROR: CFP is not usable with launcher: '${launcher:-}'" - err=1 + echo "FATAL ERROR: CFP is not usable with launcher: '${launcher:-}'" + err=1 fi # On success concatenate processor specific output into a single mpmd.out if [[ ${err} -eq 0 ]]; then - rm -f "${mpmd_cmdfile}" - out_files=$(find . -name 'mpmd.*.out') - for file in ${out_files}; do - cat "${file}" >> mpmd.out - rm -f "${file}" - done - cat mpmd.out + rm -f "${mpmd_cmdfile}" + out_files=$(find . -name 'mpmd.*.out') + for file in ${out_files}; do + cat "${file}" >> mpmd.out + rm -f "${file}" + done + cat mpmd.out fi exit "${err}" diff --git a/ush/syndat_getjtbul.sh b/ush/syndat_getjtbul.sh index 16c41b21efe..0ce21ef7efd 100755 --- a/ush/syndat_getjtbul.sh +++ b/ush/syndat_getjtbul.sh @@ -7,7 +7,7 @@ # 2-digit year starting in column 20 or a 4-digit year # starting in column 20. # Mar 2013, DStokes - modified for WCOSS. Added option to email developer. -# Oct 2013, DStokes - Add check of stormname length and truncate if needed +# Oct 2013, DStokes - Add check of stormname length and truncate if needed # in response to recent problems with JTWC reports. # Remove option to email developer. # @@ -17,142 +17,136 @@ # Imported variables that must be passed in: # DATA - path to working directory -# pgmout - string indicating path to for standard output file # TANK_TROPCY - path to home directory containing tropical cyclone record # data base -cd $DATA +cd "${DATA}" || exit 1 -if [ "$#" -ne '1' ]; then - echo "**NON-FATAL ERROR PROGRAM SYNDAT_GETJTBUL run date not in \ +if [[ "$#" -ne '1' ]]; then + echo "**NON-FATAL ERROR PROGRAM SYNDAT_GETJTBUL run date not in \ positional parameter 1" - -echo "Leaving sub-shell syndat_getjtbul.sh to recover JTWC Bulletins" \ - >> $pgmout -echo " " >> $pgmout - - exit + exit fi run_date=$1 ymd=${run_date:2:6} -echo $PDYm1 -pdym1=$PDYm1 - -echo " " >> $pgmout -echo "Entering sub-shell syndat_getjtbul.sh to recover JTWC Bulletins" \ - >> $pgmout -echo " " >> $pgmout +echo "${PDYm1}" +pdym1=${PDYm1} +echo +echo "Entering sub-shell syndat_getjtbul.sh to recover JTWC Bulletins" +echo -if test ${cyc} -eq "00" -then +if [[ "${cyc}" -eq "00" ]]; then -# For 00Z cycle, need to go to prior day's tank -# --------------------------------------------- + # For 00Z cycle, need to go to prior day's tank + # --------------------------------------------- - jtwcdir=$TANK_TROPCY/${PDY}/wtxtbul - jtwcdirm1=$TANK_TROPCY/$pdym1/wtxtbul + jtwcdir="${TANK_TROPCY}/${PDY}/wtxtbul" + jtwcdirm1="${TANK_TROPCY}/${pdym1}/wtxtbul" else - jtwcdir=$TANK_TROPCY/${PDY}/wtxtbul + jtwcdir="${TANK_TROPCY}/${PDY}/wtxtbul" fi - set +x echo echo " Run date is ${run_date}" echo echo " PDY is ${PDY}" echo -echo " pdym1 is $pdym1" +echo " pdym1 is ${pdym1}" echo echo " ymddir is ${PDY}" echo set_trace -find=$ymd" "${cyc} -echo "looking for string $find in $jtwcdir/tropcyc" >> $pgmout +find="${ymd} ${cyc}" +echo "looking for string ${find} in ${jtwcdir}/tropcyc" rm -f jtwcbul -grep "$ymd ${cyc}" $jtwcdir/tropcyc | grep JTWC > jtwcbul -if [ -s jtwcbul ]; then - echo "String found: contents of JTWC bulletin are:" >> $pgmout - cat jtwcbul >> $pgmout +# shellcheck disable=SC2312 +grep "${ymd} ${cyc}" "${jtwcdir}/tropcyc" | grep JTWC > jtwcbul +if [[ -s jtwcbul ]]; then + echo "String found: contents of JTWC bulletin are:" + cat jtwcbul else - echo "String not found: no JTWC bulletins available for this run" >> $pgmout + echo "String not found: no JTWC bulletins available for this run" fi -if test ${cyc} -eq "00" -then - grep "$ymd ${cyc}" $jtwcdirm1/tropcyc | grep JTWC >> jtwcbul - if [ -s jtwcbul ]; then - echo "String found: contents of JTWC bulletin are:" >> $pgmout - cat jtwcbul >> $pgmout - else - echo "String not found: no JTWC bulletins available for this run" >> $pgmout - fi +if [[ "${cyc}" == "00" ]]; then + # shellcheck disable=SC2312 + grep "${ymd} ${cyc}" "${jtwcdirm1}/tropcyc" | grep JTWC >> jtwcbul + if [[ -s jtwcbul ]]; then + echo "String found: contents of JTWC bulletin are:" + cat jtwcbul + else + echo "String not found: no JTWC bulletins available for this run" + fi fi # Check for and truncate stormnames with length greater than nine characters and leave rest of record intact. # This spell makes no attempt to correct any other potential errors in the record format. perl -wpi.ORIG -e 's/(^.... ... )(\S{9,9})(\S{1,})/$1$2/' jtwcbul diff jtwcbul.ORIG jtwcbul > jtwcbul_changes.txt -if [ -s jtwcbul_changes.txt ]; then - echo "***WARNING: SOME JTWC VITALS SEGMENTS REQUIRED PRELIMINARY MODIFICATION!" - cat jtwcbul_changes.txt +if [[ -s jtwcbul_changes.txt ]]; then + echo "***WARNING: SOME JTWC VITALS SEGMENTS REQUIRED PRELIMINARY MODIFICATION!" + cat jtwcbul_changes.txt fi # Execute bulletin processing -[ -s jtwcbul ] && echo "Processing JTWC bulletin halfs into tcvitals records" >> $pgmout +if [[ -s jtwcbul ]]; then + echo "Processing JTWC bulletin halfs into tcvitals records" +fi -pgm=$(basename ${EXECgfs}/syndat_getjtbul.x) +pgm=$(basename "${EXECgfs}/syndat_getjtbul.x") export pgm -if [ -s prep_step ]; then - set +u - source prep_step - set -u +if [[ -s prep_step ]]; then + set +u + source prep_step + set -u else - [ -f errfile ] && rm errfile - unset FORT00 $(env | grep "^FORT[0-9]\{1,\}=" | awk -F= '{print $1}') + [[ -f errfile ]] && rm errfile + # shellcheck disable=SC2046,SC2312 + unset FORT00 $(env | grep "^FORT[0-9]\{1,\}=" | awk -F= '{print $1}') fi rm -f fnoc export FORT11=jtwcbul export FORT51=fnoc -time -p ${EXECgfs}/${pgm} >> $pgmout 2> errfile +# shellcheck disable=SC2312 +time -p "${EXECgfs}/${pgm}" 2> errfile errget=$? -###cat errfile -cat errfile >> $pgmout +cat errfile rm errfile set +x echo -echo 'The foreground exit status for SYNDAT_GETJTBUL is ' $errget +echo "The foreground exit status for SYNDAT_GETJTBUL is ${errget}" echo set_trace -if [ "$errget" -gt '0' ];then - if [ "$errget" -eq '1' ];then - msg="No JTWC bulletins in $jtwcdir/tropcyc, no JTWC tcvitals \ -available for qctropcy for ${run_date}" - if [[ "$RUN" == "gfs" ]]; then - if [[ "${SENDSDM}" == "YES" ]]; then - export ecf_family=$(echo $ECF_NAME |awk 'BEGIN {FS="/j"} {print $1}') - echo $msg > $COMOUT/${NET}_${RUN}.t${cyc}z.emailbody - echo "export subject='No JTWC bulletins available for ${run_date} ${RUN} run'" >$COMOUT/${NET}_${RUN}.t${cyc}z.emailvar - # JY echo "export maillist='sdm@noaa.gov'" >> $COMOUT/${NET}_${RUN}.t${cyc}z.emailvar - echo "export maillist=$maillist" >> $COMOUT/${NET}_${RUN}.t${cyc}z.emailvar - ecflow_client --run ${ecf_family}/j${RUN}_jtwc_bull_email +if [[ "${errget}" -gt '0' ]]; then + if [[ "${errget}" -eq '1' ]]; then + msg="No JTWC bulletins in ${jtwcdir}/tropcyc, no JTWC tcvitals available for qctropcy for ${run_date}" + if [[ "${RUN}" == "gfs" ]]; then + if [[ "${SENDSDM}" == "YES" ]]; then + ecf_family=$(echo "${ECF_NAME}" | awk 'BEGIN {FS="/j"} {print $1}') + export ecf_family + echo "${msg}" > "${COMOUT}/${NET}_${RUN}.t${cyc}z.emailbody" + echo "export subject='No JTWC bulletins available for ${run_date} ${RUN} run'" > "${COMOUT}/${NET}_${RUN}.t${cyc}z.emailvar" + # JY echo "export maillist='sdm@noaa.gov'" >> $COMOUT/${NET}_${RUN}.t${cyc}z.emailvar + echo "export maillist=${maillist}" >> "${COMOUT}/${NET}_${RUN}.t${cyc}z.emailvar" + ecflow_client --run "${ecf_family}/j${RUN}_jtwc_bull_email" + fi fi - fi - else - echo "**NON-FATAL ERROR PROGRAM SYNDAT_GETJTBUL FOR ${run_date} \ -RETURN CODE $errget" - fi + else + echo "**NON-FATAL ERROR PROGRAM SYNDAT_GETJTBUL FOR ${run_date} \ +RETURN CODE ${errget}" + fi else - echo "program SYNDAT_GETJTBUL completed normally for ${run_date}, JTWC \ + echo "program SYNDAT_GETJTBUL completed normally for ${run_date}, JTWC \ rec. passed to qctropcy" fi set +x @@ -163,13 +157,13 @@ echo "----------------------------------------------------------" echo set_trace -if [ "$errget" -eq '0' ];then - echo "Completed JTWC tcvitals records are:" >> $pgmout - cat fnoc >> $pgmout +if [[ "${errget}" -eq '0' ]]; then + echo "Completed JTWC tcvitals records are:" + cat fnoc fi -echo "Leaving sub-shell syndat_getjtbul.sh to recover JTWC Bulletins" \ - >> $pgmout -echo " " >> "${pgmout}" +echo "Leaving sub-shell syndat_getjtbul.sh to recover JTWC Bulletins" + +echo " " exit diff --git a/ush/syndat_qctropcy.sh b/ush/syndat_qctropcy.sh index 022851c3e45..deef9ad515a 100755 --- a/ush/syndat_qctropcy.sh +++ b/ush/syndat_qctropcy.sh @@ -63,7 +63,7 @@ # (Default: not set) # TIMEIT - optional time and resource reporting (Default: not set) -ARCHSYND=${ARCHSYND:-$COMROOTp3/gfs/prod/syndat} +ARCHSYND=${ARCHSYND:-${COMROOTp3}/gfs/prod/syndat} HOMENHC=${HOMENHC:-/gpfs/dell2/nhc/save/guidance/storm-data/ncep} TANK_TROPCY=${TANK_TROPCY:-${DCOMROOT}/us007003} @@ -71,47 +71,41 @@ slmask=${slmask:-${FIXgfs}/am/syndat_slmask.t126.gaussian} copy_back=${copy_back:-YES} files_override=${files_override:-""} -cd $DATA +cd "${DATA}" || exit 2 msg="Tropical Cyclone tcvitals QC processing has begun" set +x echo -echo $msg +echo "${msg}" echo set_trace -echo $msg >> $pgmout -if [ "$#" -ne '1' ]; then - msg="**NON-FATAL ERROR PROGRAM SYNDAT_QCTROPCY run date not in \ +if [[ "$#" -ne '1' ]]; then + msg="**NON-FATAL ERROR PROGRAM SYNDAT_QCTROPCY run date not in \ positional parameter 1" - set +x - echo - echo $msg - echo - set_trace - echo $msg >> $pgmout - msg="**NO TROPICAL CYCLONE tcvitals processed --> non-fatal" - set +x - echo - echo $msg - echo - set_trace - echo $msg >> $pgmout - -# Copy null files into "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.$tmmark" and -# "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.$tmmark" so later ftp attempts will find and -# copy the zero-length file and avoid wasting time with multiple attempts -# to remote machine(s) -# (Note: Only do so if files don't already exist) - - if [[ ! -s "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" ]]; then - touch "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" - fi - if [[ ! -s "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.${tmmark}" ]]; then - touch "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.${tmmark}" - fi - - exit + set +x + echo + echo "${msg}" + echo + msg="**NO TROPICAL CYCLONE tcvitals processed --> non-fatal" + echo + echo "${msg}" + echo + + # Copy null files into "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.$tmmark" and + # "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.$tmmark" so later ftp attempts will find and + # copy the zero-length file and avoid wasting time with multiple attempts + # to remote machine(s) + # (Note: Only do so if files don't already exist) + + if [[ ! -s "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" ]]; then + touch "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" + fi + if [[ ! -s "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.${tmmark}" ]]; then + touch "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.${tmmark}" + fi + + exit fi run_date=$1 @@ -124,29 +118,30 @@ set_trace year=${run_date:0:4} - # Copy the seasonal statistics from archive directory to local -cpreq $ARCHSYND/syndat_akavit akavit; touch akavit -cpreq $ARCHSYND/syndat_dateck dateck -cpreq $ARCHSYND/syndat_stmcat.scr stmcat.scr; touch stmcat.scr -cpreq $ARCHSYND/syndat_stmcat stmcat; touch stmcat -cpreq $ARCHSYND/syndat_sthisto sthisto -cpreq $ARCHSYND/syndat_sthista sthista +cpreq "${ARCHSYND}/syndat_akavit" akavit +touch akavit +cpreq "${ARCHSYND}/syndat_dateck" dateck +cpreq "${ARCHSYND}/syndat_stmcat.scr" stmcat.scr +touch stmcat.scr +cpreq "${ARCHSYND}/syndat_stmcat" stmcat +touch stmcat +cpreq "${ARCHSYND}/syndat_sthisto" sthisto +cpreq "${ARCHSYND}/syndat_sthista" sthista touch dateck -dateck_size=$(ls -l dateck | awk '{ print $5 }') -if [ $dateck_size -lt 10 ]; then - msg="***WARNING: Archive run date check file not available or shorter than expected.\ +dateck_size=$(find ./ -name dateck -printf "%s") + +if [[ ${dateck_size} -lt 10 ]]; then + msg="WARNING: Archive run date check file not available or shorter than expected.\ Using dummy date 1900010100 to allow code to continue" - echo 1900010100 > dateck - set +x - echo -e "\n${msg}\n" - set_trace - echo $msg >> $pgmout + echo 1900010100 > dateck + set +x + echo -e "\n${msg}\n" + set_trace fi - # Generate the correct RUNID and FILES value based on $NET, $RUN and $cyc # Copy this into parm file, then cat the remaining switches in the parm file # Note: FILES=T for 00Z GDAS at tm00 (last run of day centered on 00Z) @@ -154,136 +149,133 @@ fi # 12Z GDAS at tm00 (last run of day centered on 12Z) # 18Z GDAS at tm00 (last run of day centered on 18Z) -net=$NET +net="${NET}" files=F, -if [ "$RUN" = 'ndas' ]; then - net=ndas -elif [ "$RUN" = 'gdas' ]; then - files=T, +if [[ "${RUN}" == 'ndas' ]]; then + net=ndas +elif [[ "${RUN}" == 'gdas' ]]; then + files=T, fi -if [ -n "$files_override" ]; then # for testing, typically want FILES=F - files_override=$(echo "$files_override" | tr [a-z] [A-Z] | tr -d [.] | cut -c 1) - if [ "$files_override" = 'T' -o "$files_override" = 'F' ]; then - msg="***WARNING: Variable files setting will be overriden from $files to $files_override. Override expected if testing." - files=$files_override - else - msg="***WARNING: Invalid attempt to override files setting. Will stay with default for this job" - fi - set +x - echo -e "\n${msg}\n" - set_trace - echo $msg >> $pgmout + +if [[ -n "${files_override}" ]]; then # for testing, typically want FILES=F + files_override=${files_override^^} + files_override=${files_override//./} + files_override=${files_override:0:1} + if [[ "${files_override}" == 'T' || "${files_override}" == 'F' ]]; then + msg="WARNING: Variable files setting will be overriden from ${files} to ${files_override}. Override expected if testing." + files=${files_override} + else + msg="WARNING: Invalid attempt to override files setting. Will stay with default for this job" + fi + set +x + echo -e "\n${msg}\n" + set_trace fi -echo " &INPUT RUNID = '${net}_${tmmark}_${cyc}', FILES = $files " > vitchk.inp -cat ${PARMgfs}/relo/syndat_qctropcy.${RUN}.parm >> vitchk.inp +echo " &INPUT RUNID = '${net}_${tmmark}_${cyc}', FILES = ${files} " > vitchk.inp +cat "${PARMgfs}/relo/syndat_qctropcy.${RUN}.parm" >> vitchk.inp # Copy the fixed fields -cpreq ${FIXgfs}/am/syndat_fildef.vit fildef.vit -cpreq ${FIXgfs}/am/syndat_stmnames stmnames - +cpreq "${FIXgfs}/am/syndat_fildef.vit" fildef.vit +cpreq "${FIXgfs}/am/syndat_stmnames" stmnames rm -f nhc fnoc lthistry - ######################################################################### # There are five possible sources of tropical cyclone bogus messages # All are input to program syndat_qctropcy # ------------------------------------------------------------------ -if [ -s ${HOMENHC}/tcvitals ]; then - echo "tcvitals found" >> $pgmout - cpreq ${HOMENHC}/tcvitals nhc +if [[ -s "${HOMENHC}/tcvitals" ]]; then + echo "tcvitals found" + cpreq "${HOMENHC}/tcvitals" nhc else - echo "WARNING: tcvitals not found, create empty tcvitals" >> $pgmout - > nhc + echo "WARNING: tcvitals not found, create empty tcvitals" fi # NHC ... copy into working directory as nhc; copy to archive touch nhc -[ "$copy_back" = 'YES' ] && cat nhc >> $ARCHSYND/syndat_tcvitals.$year +if [[ "${copy_back}" == 'YES' ]]; then + cat nhc >> "${ARCHSYND}/syndat_tcvitals.${year}" +fi mv -f nhc nhc1 -${USHgfs}/parse-storm-type.pl nhc1 > nhc +"${USHgfs}/parse-storm-type.pl" nhc1 > nhc cpreq -p nhc nhc.ORIG # JTWC/FNOC ... execute syndat_getjtbul script to write into working directory # as fnoc; copy to archive -${USHgfs}/syndat_getjtbul.sh ${run_date} +"${USHgfs}/syndat_getjtbul.sh" "${run_date}" touch fnoc -[ "$copy_back" = 'YES' ] && cat fnoc >> $ARCHSYND/syndat_tcvitals.$year +if [[ "${copy_back}" == 'YES' ]]; then + cat fnoc >> "${ARCHSYND}/syndat_tcvitals.${year}" +fi mv -f fnoc fnoc1 -${USHgfs}/parse-storm-type.pl fnoc1 > fnoc +"${USHgfs}/parse-storm-type.pl" fnoc1 > fnoc if [[ "${SENDDBN}" == "YES" ]]; then - $DBNROOT/bin/dbn_alert MODEL SYNDAT_TCVITALS $job $ARCHSYND/syndat_tcvitals.$year + "${DBNROOT}/bin/dbn_alert" MODEL SYNDAT_TCVITALS "${job}" "${ARCHSYND}/syndat_tcvitals.${year}" fi ######################################################################### - -cpreq $slmask slmask.126 - +cpreq "${slmask}" slmask.126 # Execute program syndat_qctropcy -pgm=$(basename ${EXECgfs}/syndat_qctropcy.x) +pgm=$(basename "${EXECgfs}/syndat_qctropcy.x") export pgm -if [ -s prep_step ]; then - set +u - source prep_step - set -u +if [[ -s prep_step ]]; then + set +u + source prep_step + set -u else - [ -f errfile ] && rm errfile - unset FORT00 $(env | grep "^FORT[0-9]\{1,\}=" | awk -F= '{print $1}') + [[ -f errfile ]] && rm errfile + # shellcheck disable=SC2046,SC2312 + unset FORT00 $(env | grep "^FORT[0-9]\{1,\}=" | awk -F= '{print $1}') fi -echo "${run_date}" > run_date.dat +echo "${run_date}" > run_date.dat export FORT11=slmask.126 export FORT12=run_date.dat -${EXECgfs}/${pgm} >> $pgmout 2> errfile +"${EXECgfs}/${pgm}" errqct=$? -###cat errfile -cat errfile >> $pgmout -rm errfile set +x echo -echo "The foreground exit status for SYNDAT_QCTROPCY is " $errqct +echo "The foreground exit status for SYNDAT_QCTROPCY is ${errqct}" echo set_trace -if [ "$errqct" -gt '0' ];then - msg="**NON-FATAL ERROR PROGRAM SYNDAT_QCTROPCY RETURN CODE $errqct" - set +x - echo - echo $msg - echo - set_trace - echo $msg >> $pgmout - msg="**NO TROPICAL CYCLONE tcvitals processed --> non-fatal" - set +x - echo - echo $msg - echo - set_trace - echo $msg >> $pgmout - -# In the event of a ERROR in PROGRAM SYNDAT_QCTROPCY, copy null files into -# "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.$tmmark" and "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.$tmmark" -# so later ftp attempts will find and copy the zero-length file and avoid -# wasting time with multiple attempts to remote machine(s) -# (Note: Only do so if files don't already exist) - - if [[ ! -s "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" ]]; then - touch "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" - fi - if [[ ! -s ${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.${tmmark} ]]; then - touch "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.${tmmark}" - fi - - exit +if [[ "${errqct}" -gt '0' ]]; then + msg="**NON-FATAL ERROR PROGRAM SYNDAT_QCTROPCY RETURN CODE ${errqct}" + set +x + echo + echo "${msg}" + echo + set_trace + msg="**NO TROPICAL CYCLONE tcvitals processed --> non-fatal" + set +x + echo + echo "${msg}" + echo + set_trace + + # In the event of a ERROR in PROGRAM SYNDAT_QCTROPCY, copy null files into + # "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.$tmmark" and "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.$tmmark" + # so later ftp attempts will find and copy the zero-length file and avoid + # wasting time with multiple attempts to remote machine(s) + # (Note: Only do so if files don't already exist) + + if [[ ! -s "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" ]]; then + touch "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" + fi + if [[ ! -s ${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.${tmmark} ]]; then + touch "${COMOUT_OBS}/${RUN}.${cycle}.jtwc-fnoc.tcvitals.${tmmark}" + fi + + exit fi set +x echo @@ -293,17 +285,16 @@ echo "----------------------------------------------------------" echo set_trace -if [ "$copy_back" = 'YES' ]; then - cat lthistry>>$ARCHSYND/syndat_lthistry.$year - cpfs akavit $ARCHSYND/syndat_akavit - cpfs dateck $ARCHSYND/syndat_dateck - cpfs stmcat.scr $ARCHSYND/syndat_stmcat.scr - cpfs stmcat $ARCHSYND/syndat_stmcat - cpfs sthisto $ARCHSYND/syndat_sthisto - cpfs sthista $ARCHSYND/syndat_sthista +if [[ "${copy_back}" == 'YES' ]]; then + cat lthistry >> "${ARCHSYND}/syndat_lthistry.${year}" + cpfs akavit "${ARCHSYND}/syndat_akavit" + cpfs dateck "${ARCHSYND}/syndat_dateck" + cpfs stmcat.scr "${ARCHSYND}/syndat_stmcat.scr" + cpfs stmcat "${ARCHSYND}/syndat_stmcat" + cpfs sthisto "${ARCHSYND}/syndat_sthisto" + cpfs sthista "${ARCHSYND}/syndat_sthista" fi - diff nhc nhc.ORIG > /dev/null errdiff=$? @@ -311,54 +302,50 @@ errdiff=$? # Update NHC file in ${HOMENHC} ################################### -if test "$errdiff" -ne '0' -then +if [[ "${errdiff}" -ne 0 ]]; then - if [ "$copy_back" = 'YES' -a ${envir} = 'prod' ]; then - if [ -s ${HOMENHC}/tcvitals ]; then - cpfs nhc ${HOMENHC}/tcvitals - fi + if [[ "${copy_back}" == 'YES' && ${envir} == 'prod' ]]; then + if [[ -s "${HOMENHC}/tcvitals" ]]; then + cpfs nhc "${HOMENHC}/tcvitals" + fi - err=$? + err=$? - if [ "$err" -ne '0' ]; then - msg="###ERROR: Previous NHC Synthetic Data Record File \ + if [[ "${err}" -ne 0 ]]; then + msg="###ERROR: Previous NHC Synthetic Data Record File \ ${HOMENHC}/tcvitals not updated by syndat_qctropcy" - else - msg="Previous NHC Synthetic Data Record File \ + else + msg="Previous NHC Synthetic Data Record File \ ${HOMENHC}/tcvitals successfully updated by syndat_qctropcy" - fi + fi - set +x - echo - echo $msg - echo - set_trace - echo $msg >> $pgmout - fi + set +x + echo + echo "${msg}" + echo + set_trace + fi else - msg="Previous NHC Synthetic Data Record File ${HOMENHC}/tcvitals \ + msg="Previous NHC Synthetic Data Record File ${HOMENHC}/tcvitals \ not changed by syndat_qctropcy" - set +x - echo - echo $msg - echo - set_trace - echo $msg >> $pgmout + set +x + echo + echo "${msg}" + echo + set_trace fi ################################### - # This is the file that connects to the later RELOCATE and/or PREP scripts cpfs current "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" # Create the DBNet alert if [[ "${SENDDBN}" == "YES" ]]; then - "${DBNROOT}/bin/dbn_alert" "MODEL" "GDAS_TCVITALS" "${job}" "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" + "${DBNROOT}/bin/dbn_alert" "MODEL" "GDAS_TCVITALS" "${job}" "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" fi # Write JTWC/FNOC Tcvitals to /com path since not saved anywhere else diff --git a/ush/tropcy_relocate.sh b/ush/tropcy_relocate.sh index 38caecba3b6..d7b21daba56 100755 --- a/ush/tropcy_relocate.sh +++ b/ush/tropcy_relocate.sh @@ -168,53 +168,46 @@ # #### -qid=$$ - # obtain the center date/time for relocation processing # ----------------------------------------------------- -if [ $# -ne 1 ] ; then - err0=1 +if [[ $# -ne 1 ]]; then + err0=1 else - run_date=$1 - if [ "${#run_date}" -ne '10' ]; then - err0=1 - else - cycle="t${run_date:8:2}z" - err0=0 - fi + run_date=$1 + if [[ "${#run_date}" -ne '10' ]]; then + err0=1 + else + cycle="t${run_date:8:2}z" + err0=0 + fi fi -if test $err0 -ne 0 -then -# problem with obtaining date record so exit - set +x - echo - echo "problem with obtaining date record;" - echo "ABNORMAL EXIT!!!!!!!!!!!" - echo - set_trace - exit 9 +if [[ "${err0}" -ne 0 ]]; then + # problem with obtaining date record so exit + export err="${err0}" + msg="FATAL ERROR: problem with obtaining date record" + err_exit "${msg}" fi -modhr=$(expr ${cyc} % 3) +modhr=$((cyc % 3)) + +cat << EOF + +"CENTER DATE/TIME FOR RELOCATION PROCESSING IS ${run_date}" -set +x -echo -echo "CENTER DATE/TIME FOR RELOCATION PROCESSING IS ${run_date}" -echo -set_trace +EOF #---------------------------------------------------------------------------- # Create variables needed for this script and its children # -------------------------------------------------------- -envir_getges=${envir_getges:-$envir} -if [ $modhr -eq 0 ]; then - network_getges=${network_getges:-global} +envir_getges=${envir_getges:-${envir}} +if [[ "${modhr}" -eq 0 ]]; then + network_getges=${network_getges:-global} else - network_getges=${network_getges:-gfs} + network_getges=${network_getges:-gfs} fi GRIBVERSION=${GRIBVERSION:-"grib2"} @@ -235,173 +228,159 @@ GETTX=${GETTX:-${EXECgfs}/gettrk} echo "Attempt to perform tropical cyclone relocation for ${run_date}" -if [ $modhr -ne 0 ]; then +if [[ "${modhr}" -ne 0 ]]; then -# if center date/time for relocation processing isn't a multiple of 3-hrs, exit -# ----------------------------------------------------------------------------- - - set +x - echo - echo "cannot perform tropical cyclone processing because cycle hour is not a multiple of 3-hrs;" - echo "ABNORMAL EXIT!!!!!!!!!!!" - echo - set_trace - exit 9 + # if center date/time for relocation processing isn't a multiple of 3-hrs, exit + # ----------------------------------------------------------------------------- + export err=9 + msg="FATAL ERROR: cannot perform tropical cyclone processing because cycle hour is not a multiple of 3-hrs" + err_exit "${msg}" fi -for fhr in 6 12 ;do - if [ ! -s tcvitals.m${fhr} ]; then # This should never exist, right ???? - -# create a null tcvitals file for 06 or 12 hours ago -# use getges to overwrite with any found - - >tcvitals.m${fhr} - set +x - echo -echo "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" -echo " Get TCVITALS file valid for -$fhr hrs relative to center" -echo " relocation processing date/time" -echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - echo - set_trace - ${USHgfs}/getges.sh -e $envir_getges -n $network_getges \ - -v ${run_date} -f $fhr -t tcvges tcvitals.m${fhr} - set +x - echo -echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - echo - set_trace - fi +for fhr in 6 12; do + if [[ ! -s "tcvitals.m${fhr}" ]]; then # This should never exist, right ???? + + # create a null tcvitals file for 06 or 12 hours ago + # use getges to overwrite with any found + + rm -f "tcvitals.m${fhr}" + touch "tcvitals.m${fhr}" + cat << EOF + +VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV + Get TCVITALS file valid for -${fhr} hrs relative to center + relocation processing date/time +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + +EOF + "${USHgfs}/getges.sh" -e "${envir_getges}" -n "${network_getges}" \ + -v "${run_date}" -f "${fhr}" -t tcvges "tcvitals.m${fhr}" + cat << EOF + +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + +EOF + fi done # Next line needed to assure that only an analysis file will have the # relocation codes run on it export CMODEL=gdas -if [ "$GRIBVERSION" = "grib1" ]; then - export gribver=1 - pgpref=pgbg +if [[ "${GRIBVERSION}" == "grib1" ]]; then + export gribver=1 + pgpref=pgbg else - export gribver=2 # default - pgpref=pg2g + export gribver=2 # default + pgpref=pg2g fi -for fhr in $( seq -6 $BKGFREQ 3 ) ; do - - if [ $fhr -lt 0 ]; then - tpref=m$(expr $fhr \* -1) - elif [ $fhr -eq 0 ]; then - tpref=es - elif [ $fhr -gt 0 ]; then - tpref=p$fhr - fi - - sges=sg${tpref}prep - if [[ ${fhr} -lt -3 ]]; then - sges=NULL - fi - echo $sges -# stype=sigg${tpref} - stype=natg${tpref} - if [[ "${RUN}" = cdas1 ]]; then - stype="sigg${tpref}" ## for cfs - fi - pges=pg${tpref}prep - ptype=${pgpref}${tpref} - - if [ $sges != NULL -a ! -s $sges ]; then - set +x - echo -echo "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" -echo " Get global sigma GUESS valid for $fhr hrs relative to center" -echo " relocation processing date/time" -echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - echo - set_trace - ${USHgfs}/getges.sh -e $envir_getges -n $network_getges \ - -v ${run_date} -t $stype $sges - errges=$? - if test $errges -ne 0; then -# problem obtaining global sigma first guess so exit - set +x - echo - echo "problem obtaining global sigma guess valid $fhr hrs relative \ -to center relocation date/time;" - echo "ABNORMAL EXIT!!!!!!!!!!!" - echo - set_trace - exit 9 - fi - -# For center time sigma guess file obtained via getges, store pathname from -# getges into ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pre-relocate_pathname.$tmmark and, for now, -# also in ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark - if relocation processing stops -# due to an error or due to no input tcvitals records found, then the center -# time sigma guess will not be modified and this getges file will be read in -# subsequent PREP processing; if relocation processing continues and the -# center sigma guess is modified, then ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark will -# be removed later in this script {the subsequent PREP step will correctly -# update ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark to point to the sgesprep file -# updated here by the relocation} -# ---------------------------------------------------------------------------- - - if [ $fhr = "0" ]; then - "${USHgfs}/getges.sh" -e "${envir_getges}" -n "${network_getges}" -v "${run_date}" \ - -t "${stype}" > "${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pre-relocate_pathname.${tmmark}" - cpfs "${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pre-relocate_pathname.${tmmark}" \ - "${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.${tmmark}" - fi - set +x - echo -echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - echo - set_trace - fi - if [ ! -s $pges ]; then - set +x - echo -echo "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" -echo " Get global pressure grib GUESS valid for $fhr hrs relative to center" -echo " relocation processing date/time" -echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - echo - set_trace - ${USHgfs}/getges.sh -e $envir_getges -n $network_getges \ - -v ${run_date} -t $ptype $pges - errges=$? - if test $errges -ne 0; then -# problem obtaining global pressure grib guess so exit - set +x - echo - echo "problem obtaining global pressure grib guess valid $fhr hrs \ -relative to center relocation date/time;" - echo "ABNORMAL EXIT!!!!!!!!!!!" - echo - set_trace - exit 9 - fi - set +x - echo -echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - echo - set_trace - fi +for fhr in $(seq -6 "${BKGFREQ}" 3); do + + if [[ "${fhr}" -lt 0 ]]; then + tpref="m$((-fhr))" + elif [[ ${fhr} -eq 0 ]]; then + tpref=es + elif [[ ${fhr} -gt 0 ]]; then + tpref="p${fhr}" + fi + + sges="sg${tpref}prep" + if [[ "${fhr}" -lt -3 ]]; then + sges=NULL + fi + echo "${sges}" + # stype=sigg${tpref} + stype="natg${tpref}" + if [[ "${RUN}" == cdas1 ]]; then + stype="sigg${tpref}" ## for cfs + fi + pges="pg${tpref}prep" + ptype="${pgpref}${tpref}" + + if [[ "${sges}" != NULL && ! -s "${sges}" ]]; then + cat << EOF + +VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV + Get global sigma GUESS valid for ${fhr} hrs relative to center + relocation processing date/time +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + +EOF + "${USHgfs}/getges.sh" -e "${envir_getges}" -n "${network_getges}" \ + -v "${run_date}" -t "${stype}" "${sges}" + errges=$? + if [[ "${errges}" -ne 0 ]]; then + # problem obtaining global sigma first guess so exit + export err="${errges}" + msg="FATAL ERROR: problem obtaining global sigma guess valid ${fhr} hrs relative to center relocation date/time" + err_exit "${msg}" + fi + + # For center time sigma guess file obtained via getges, store pathname from + # getges into ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pre-relocate_pathname.$tmmark and, for now, + # also in ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark - if relocation processing stops + # due to an error or due to no input tcvitals records found, then the center + # time sigma guess will not be modified and this getges file will be read in + # subsequent PREP processing; if relocation processing continues and the + # center sigma guess is modified, then ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark will + # be removed later in this script {the subsequent PREP step will correctly + # update ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark to point to the sgesprep file + # updated here by the relocation} + # ---------------------------------------------------------------------------- + + if [[ ${fhr} -eq 0 ]]; then + "${USHgfs}/getges.sh" -e "${envir_getges}" -n "${network_getges}" -v "${run_date}" \ + -t "${stype}" > "${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pre-relocate_pathname.${tmmark}" + cpfs "${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pre-relocate_pathname.${tmmark}" \ + "${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.${tmmark}" + fi + cat << EOF + +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + +EOF + fi + if [[ ! -s "${pges}" ]]; then + cat << EOF + +VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV + Get global pressure grib GUESS valid for ${fhr} hrs relative to center + relocation processing date/time +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + +EOF + "${USHgfs}/getges.sh" -e "${envir_getges}" -n "${network_getges}" \ + -v "${run_date}" -t "${ptype}" "${pges}" + errges=$? + if [[ "${errges}" -ne 0 ]]; then + # problem obtaining global pressure grib guess so exit + export err="${errges}" + msg="FATAL ERROR: problem obtaining global pressure grib guess valid ${fhr} hrs relative to center relocation date/time;" + err_exit "${msg}" + fi + cat << EOF + +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + +EOF + fi done -if [ -f ${tstsp}syndata.tcvitals.$tmmark ]; then - cpreq ${tstsp}syndata.tcvitals.$tmmark tcvitals.now +if [[ -f "${tstsp}syndata.tcvitals.${tmmark}" ]]; then + cpreq "${tstsp}syndata.tcvitals.${tmmark}" tcvitals.now else - cpreq "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" "tcvitals.now" + cpreq "${COMOUT_OBS}/${RUN}.${cycle}.syndata.tcvitals.${tmmark}" "tcvitals.now" fi +if [[ -s tcvitals.m12 ]]; then cat tcvitals.m12 > VITL; fi +if [[ -s tcvitals.m6 ]]; then cat tcvitals.m6 >> VITL; fi +if [[ -s tcvitals.now ]]; then cat tcvitals.now >> VITL; fi -[ -s tcvitals.m12 ] && cat tcvitals.m12 > VITL -[ -s tcvitals.m6 ] && cat tcvitals.m6 >> VITL -[ -s tcvitals.now ] && cat tcvitals.now >> VITL - -MP_PULSE=0 -MP_TIMEOUT=600 +export MP_PULSE=0 +export MP_TIMEOUT=600 GDATE10=$(date --utc +%Y%m%d%H -d "${run_date:0:8} ${run_date:8:2} - 6 hours") +export GDATE10 # make unique combined tcvitals file for t-12, t-6 and t+0 -- # if tcvitals does not contains record from current time, skip relocation @@ -410,199 +389,179 @@ GDATE10=$(date --utc +%Y%m%d%H -d "${run_date:0:8} ${run_date:8:2} - 6 hours") grep "${PDY} ${cyc}" VITL errgrep=$? -> tcvitals -if [ $errgrep -ne 0 ] ; then - echo "NO TCVITAL RECORDS FOUND FOR ${run_date} - EXIT TROPICAL CYCLONE \ +rm -f tcvitals +touch tcvitals +if [[ "${errgrep}" -ne 0 ]]; then + echo "NO TCVITAL RECORDS FOUND FOR ${run_date} - EXIT TROPICAL CYCLONE \ RELOCATION PROCESSING" -# The existence of ${COMOUT_OBS}/${RUN}.${cycle}.tropcy_relocation_status.$tmmark file will tell the -# subsequent PREP processing that RELOCATION processing occurred, echo -# "NO RECORDS to process" into it to further tell PREP processing that records -# were not processed by relocation and the global sigma guess was NOT -# modified by tropical cyclone relocation (because no tcvitals records were -# found) -# Note: When tropical cyclone relocation does run to completion and the -# global sigma guess is modified, the parent script to this will echo -# "RECORDS PROCESSED" into ${COMOUT_OBS}/${RUN}.${cycle}.tropcy_relocation_status.$tmmark -# assuming it doesn't already exist (meaning "NO RECORDS to process" -# was NOT echoed into it here) -# ---------------------------------------------------------------------------- - - echo "NO RECORDS to process" > "${COMOUT_OBS}/${RUN}.${cycle}.tropcy_relocation_status.${tmmark}" - if [[ ! -s "${COMOUT_OBS}/${RUN}.${cycle}.tcvitals.relocate.${tmmark}" ]]; then - touch "${COMOUT_OBS}/${RUN}.${cycle}.tcvitals.relocate.${tmmark}" - fi + # The existence of ${COMOUT_OBS}/${RUN}.${cycle}.tropcy_relocation_status.$tmmark file will tell the + # subsequent PREP processing that RELOCATION processing occurred, echo + # "NO RECORDS to process" into it to further tell PREP processing that records + # were not processed by relocation and the global sigma guess was NOT + # modified by tropical cyclone relocation (because no tcvitals records were + # found) + # Note: When tropical cyclone relocation does run to completion and the + # global sigma guess is modified, the parent script to this will echo + # "RECORDS PROCESSED" into ${COMOUT_OBS}/${RUN}.${cycle}.tropcy_relocation_status.$tmmark + # assuming it doesn't already exist (meaning "NO RECORDS to process" + # was NOT echoed into it here) + # ---------------------------------------------------------------------------- + + echo "NO RECORDS to process" > "${COMOUT_OBS}/${RUN}.${cycle}.tropcy_relocation_status.${tmmark}" + if [[ ! -s "${COMOUT_OBS}/${RUN}.${cycle}.tcvitals.relocate.${tmmark}" ]]; then + touch "${COMOUT_OBS}/${RUN}.${cycle}.tcvitals.relocate.${tmmark}" + fi else - cat VITL >>tcvitals - grep "${PDY} ${cyc}" VITL > tcvitals.now1 - - -# create model forecast track location file -# $DATA/$RUN.$cycle.relocate.model_track.tm00 -# -------------------------------------------- - - ${USHgfs}/tropcy_relocate_extrkr.sh - err=$? - if [ $err -ne 0 ]; then - -# problem: script tropcy_relocate_extrkr.sh failed -# ------------------------------------------------ - - set +x - echo - echo "${USHgfs}/tropcy_relocate_extrkr.sh failed" - echo "ABNORMAL EXIT!!!!!!!!!!!" - echo - set_trace - exit 9 - fi - -# relocate model tropical cyclone vortices in ges sigma files -# ----------------------------------------------------------- - - rm -f fort.* - - ${NLN} $DATA/tcvitals.now1 fort.11 - ${NLN} $DATA/model_track.all fort.30 - ${NLN} $DATA/rel_inform1 fort.62 - ${NLN} $DATA/tcvitals.relocate0 fort.65 - - i1=20 - i2=53 - for fhr in $( seq -3 $BKGFREQ 3 ) ; do - - if [ $fhr -lt 0 ]; then - tpref=m$(expr $fhr \* -1) - elif [ $fhr -eq 0 ]; then - tpref=es - elif [ $fhr -gt 0 ]; then - tpref=p$fhr - fi - - ${NLN} $DATA/sg${tpref}prep fort.$i1 - ${NLN} $DATA/sg${tpref}prep.relocate fort.$i2 - - i1=$((i1+1)) - i2=$((i2+BKGFREQ)) - - done - -# if LATB or LONB is unset or <= 0, the sigma header values are used -# ------------------------------------------------------------------ - - set +u - [ -z "$LONB" ] && LONB=0 - [ -z "$LATB" ] && LATB=0 - set -u - - i1=0 - for gesfhr in $( seq 3 $BKGFREQ 9 ) ; do - - echo ${gesfhr} ${LONB} ${LATB} ${BKGFREQ} > "parm.${i1}" - - i1=$((i1+1)) - - done - -# setup and run the mpi relocation code -# ------------------------------------- - - export MP_EUILIB=us - export MP_EUIDEVICE=sn_all - export MP_USE_BULK_XFER=yes - export RELOX_threads=${RELOX_threads:-16} - export KMP_STACKSIZE=1024m - export OMP_NUM_THREADS=$RELOX_threads - export MP_TASK_AFFINITY=core:$RELOX_threads - - ${APRNRELOC:-mpirun.lsf} $RELOX >stdo.prints - errSTATUS=$? - -# copy relocation print output here and there -# ------------------------------------------- - - cat $DATA/stdo.prints >> $pgmout - cat $DATA/stdo.[0-9]* >> $pgmout - cat $DATA/stdo.prints >> relocate.out - cat $DATA/stdo.[0-9]* >> relocate.out - -# check for success -# ----------------- - - echo; set_trace - if [ "$errSTATUS" -gt '0' ]; then - exit 9 - fi - -# further check for success -# ------------------------- - - for fhr in $( seq -3 $BKGFREQ 3 ) ; do - - if [ $fhr -lt 0 ]; then - tpref=m$(expr $fhr \* -1) - elif [ $fhr -eq 0 ]; then - tpref=es - elif [ $fhr -gt 0 ]; then - tpref=p$fhr - fi - - sges=sg${tpref}prep - - if [ -s $sges.relocate ] ; then - mv $sges.relocate $sges - else - -# problem: $sges.relocate does not exist -# -------------------------------------- - - echo "FATAL ERROR: The file ${sges}.relocate does not exist" - exit 9 - fi - done - - if [ -s tcvitals.relocate0 ]; then - mv tcvitals.relocate0 tcvitals - else - >tcvitals - fi - rm -f RELOCATE_GES cmd - - - cpfs "rel_inform1" "${COMOUT_OBS}/${RUN}.${cycle}.inform.relocate.${tmmark}" - cpfs "tcvitals" "${COMOUT_OBS}/${RUN}.${cycle}.tcvitals.relocate.${tmmark}" - if [[ "${SENDDBN}" == "YES" ]]; then - if test "$RUN" = "gdas1" - then - "${DBNROOT}/bin/dbn_alert" "MODEL" "GDAS1_TCI" "${job}" "${COMOUT_OBS}/${RUN}.${cycle}.inform.relocate.${tmmark}" - "${DBNROOT}/bin/dbn_alert" "MODEL" "GDAS1_TCI" "${job}" "${COMOUT_OBS}/${RUN}.${cycle}.tcvitals.relocate.${tmmark}" - fi - if test "$RUN" = "gfs" - then - "${DBNROOT}/bin/dbn_alert" "MODEL" "GFS_TCI" "${job}" "${COMOUT_OBS}/${RUN}.${cycle}.inform.relocate.${tmmark}" - "${DBNROOT}/bin/dbn_alert" "MODEL" "GFS_TCI" "${job}" "${COMOUT_OBS}/${RUN}.${cycle}.tcvitals.relocate.${tmmark}" - fi - fi - -# -------------------------------------------------------------------------- -# Since relocation processing has ended sucessfully (and the center sigma -# guess has been modified), remove ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark (which -# had earlier had getges center sigma guess pathname written into it - in -# case of error or no input tcvitals records found) - the subsequent PREP -# step will correctly update ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark to point to -# the sgesprep file updated here by the relocation -# -------------------------------------------------------------------------- - - rm -f "${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.${tmmark}" - - echo "TROPICAL CYCLONE RELOCATION PROCESSING SUCCESSFULLY COMPLETED FOR ${run_date}" + cat VITL >> tcvitals + grep "${PDY} ${cyc}" VITL > tcvitals.now1 + + # create model forecast track location file + # $DATA/$RUN.$cycle.relocate.model_track.tm00 + # -------------------------------------------- + + "${USHgfs}/tropcy_relocate_extrkr.sh" + err=$? + if [[ "${err}" -ne 0 ]]; then + + # problem: script tropcy_relocate_extrkr.sh failed + # ------------------------------------------------ + export err + echo "FATAL ERROR: ${USHgfs}/tropcy_relocate_extrkr.sh failed" + err_exit "${msg}" + fi + + # relocate model tropical cyclone vortices in ges sigma files + # ----------------------------------------------------------- + + rm -f fort.* + + ${NLN} "${DATA}/tcvitals.now1" fort.11 + ${NLN} "${DATA}/model_track.all" fort.30 + ${NLN} "${DATA}/rel_inform1" fort.62 + ${NLN} "${DATA}/tcvitals.relocate0" fort.65 + + i1=20 + i2=53 + for ((fhr = -3; fhr <= 3; fhr += BKGFREQ)); do + if [[ "${fhr}" -lt 0 ]]; then + tpref="m$((-fhr))" + elif [[ "${fhr}" -eq 0 ]]; then + tpref=es + elif [[ "${fhr}" -gt 0 ]]; then + tpref="p${fhr}" + fi + + ${NLN} "${DATA}/sg${tpref}prep" "fort.${i1}" + ${NLN} "${DATA}/sg${tpref}prep.relocate" "fort.${i2}" + + i1=$((i1 + 1)) + i2=$((i2 + BKGFREQ)) + + done + + # if LATB or LONB is unset or <= 0, the sigma header values are used + # ------------------------------------------------------------------ + + if [[ -z "${LONB}" ]]; then LONB=0; fi + if [[ -z "${LATB}" ]]; then LATB=0; fi + + i1=0 + for ((gesfhr = 3; gesfhr <= 0; gesfhr += BKGFREQ)); do + echo "${gesfhr} ${LONB} ${LATB} ${BKGFREQ}" > "parm.${i1}" + i1=$((i1 + 1)) + done + + # setup and run the mpi relocation code + # ------------------------------------- + + export MP_EUILIB=us + export MP_EUIDEVICE=sn_all + export MP_USE_BULK_XFER=yes + export RELOX_threads=${RELOX_threads:-16} + export KMP_STACKSIZE=1024m + export OMP_NUM_THREADS=${RELOX_threads} + export MP_TASK_AFFINITY=core:${RELOX_threads} + + ${APRNRELOC:-mpirun.lsf} "${RELOX}" > stdo.prints + errSTATUS=$? + + # copy relocation print output here and there + # ------------------------------------------- + + cat "${DATA}/stdo.prints" + cat "${DATA}/stdo.[0-9]"* + cat "${DATA}/stdo.prints" >> relocate.out + cat "${DATA}/stdo.[0-9]"* >> relocate.out + + # check for success + # ----------------- + + echo + if [[ "${errSTATUS}" -gt '0' ]]; then + export err="${errSTATUS}" + err_exit + fi + + # further check for success + # ------------------------- + + for ((fhr = -3; fhr <= 3; fhr += BKGFREQ)); do + if [[ "${fhr}" -lt 0 ]]; then + tpref="m$((-fhr))" + elif [[ "${fhr}" -eq 0 ]]; then + tpref=es + elif [[ "${fhr}" -gt 0 ]]; then + tpref="p${fhr}" + fi + + sges="sg${tpref}prep" + + if [[ -s "${sges}.relocate" ]]; then + mv "${sges}.relocate" "${sges}" + else + + # problem: $sges.relocate does not exist + # -------------------------------------- + + export err=9 + msg="FATAL ERROR: The file ${sges}.relocate does not exist" + err_exit "${msg}" + fi + done + + if [[ -s tcvitals.relocate0 ]]; then + mv tcvitals.relocate0 tcvitals + else + rm -f tcvitals + touch tcvitals + fi + rm -f RELOCATE_GES cmd + + cpfs "rel_inform1" "${COMOUT_OBS}/${RUN}.${cycle}.inform.relocate.${tmmark}" + cpfs "tcvitals" "${COMOUT_OBS}/${RUN}.${cycle}.tcvitals.relocate.${tmmark}" + if [[ "${SENDDBN}" == "YES" ]]; then + "${DBNROOT}/bin/dbn_alert" "MODEL" "${RUN^^}_TCI" "${job}" "${COMOUT_OBS}/${RUN}.${cycle}.inform.relocate.${tmmark}" + "${DBNROOT}/bin/dbn_alert" "MODEL" "${RUN^^}_TCI" "${job}" "${COMOUT_OBS}/${RUN}.${cycle}.tcvitals.relocate.${tmmark}" + fi + + # -------------------------------------------------------------------------- + # Since relocation processing has ended sucessfully (and the center sigma + # guess has been modified), remove ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark (which + # had earlier had getges center sigma guess pathname written into it - in + # case of error or no input tcvitals records found) - the subsequent PREP + # step will correctly update ${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.$tmmark to point to + # the sgesprep file updated here by the relocation + # -------------------------------------------------------------------------- + + rm -f "${COMOUT_OBS}/${RUN}.${cycle}.sgesprep_pathname.${tmmark}" + + echo "TROPICAL CYCLONE RELOCATION PROCESSING SUCCESSFULLY COMPLETED FOR ${run_date}" # end GFDL ges manipulation # ------------------------- fi - exit 0 - diff --git a/ush/tropcy_relocate_extrkr.sh b/ush/tropcy_relocate_extrkr.sh index 42b53df4cf1..8427908ba6b 100755 --- a/ush/tropcy_relocate_extrkr.sh +++ b/ush/tropcy_relocate_extrkr.sh @@ -3,18 +3,13 @@ # This script is executed by the script tropcy_relocate.sh # -------------------------------------------------------- -export machine=${machine:-ZEUS} -export machine=$(echo $machine|tr '[a-z]' '[A-Z]') -#if [ $machine = ZEUS ] ; then -# module load intel -# module load mpt -#fi +export machine=${machine^^} +export err pgm # Variable "gribver" defines if input GRIB data is in # GRIB1 (gribver=1) or GRIB2 (gribver=2) format. export gribver=${gribver:-1} -user=$LOGNAME # PDYcyc - 10 digit date # RUN - network run (gfs, gdas, etc) # DATA - working directory @@ -24,14 +19,14 @@ user=$LOGNAME export APRNGETTX=${APRNGETTX:-""} TIMEIT="" -[ -s $DATA/timex ] && TIMEIT=$DATA/timex - -vdir=${vdir:-$DATA/trakout} -if [ ! -d ${vdir} ]; then - mkdir -p ${vdir} +if [[ -s "${DATA}/timex" ]]; then + TIMEIT="${DATA}/timex" fi -cd $vdir +vdir=${vdir:-${DATA}/trakout} +mkdir -p "${vdir}" + +cd "${vdir}" || exit 1 # This script kicks off the hurricane tracker system. You have the option of # running the tracker on several operational models (the system will @@ -40,7 +35,6 @@ cd $vdir # will ONLY be able to read GRIB data. To run the tracker, fill in the # required fields below on the "export" lines, then llsubmit this script. - # ------------------- # 1. ENTER MODEL TYPE # ------------------- @@ -55,8 +49,7 @@ cd $vdir # # Example: export CMODEL=gfs -export CMODEL=${CMODEL:-$RUN} - +export CMODEL=${CMODEL:-${RUN}} # ------------------- # 2. ENTER FILE NAME @@ -81,7 +74,6 @@ export CMODEL=${CMODEL:-$RUN} export INPFILE=${INPFILE:-} - # ------------------------------- # 3. ENTER FORECAST HOUR INTERVAL # ------------------------------- @@ -105,8 +97,7 @@ export FHINT=${FHINT:-03} # # Enter the starting date, in yyyymmddhh format, of the forecast: -export YYYYMMDDHH=$GDATE10 - +export YYYYMMDDHH=${GDATE10} # ------------------------- # 5. ENTER STORM IDENTIFIER @@ -118,7 +109,6 @@ export YYYYMMDDHH=$GDATE10 export INPSTORM= - # ----------------------------------------- # 6. ENTER NAME OF AUXILIARY TC VITALS FILE # ----------------------------------------- @@ -143,7 +133,6 @@ export INPSTORM= export AUXTCVIT= - # ----------------------------------------------------- # ENTER THRESHOLDS FOR USE IN VERIFYING STORM STRUCTURE # ----------------------------------------------------- @@ -175,7 +164,6 @@ export V850THRESH=3.000 # Set the default for background files to be 3 hourly export BKGFREQ=${BKGFREQ:-1} - # This script is the second in a set of 2 that starts the tracker for either # operational or user-defined model output. This script makes sure that the # data files exist, it also pulls all of the needed data records out of the @@ -184,29 +172,24 @@ export BKGFREQ=${BKGFREQ:-1} # updates the TC Vitals (if necessary). It then executes the gettrk # executable, which actually does the tracking. - -inpstorm=${INPSTORM} inpfile=${INPFILE} fhint=${FHINT} cmodel=${CMODEL} symdh=${YYYYMMDDHH} -auxtcvit=${AUXTCVIT} -user=$LOGNAME -#export TMPDIR=/nfstmp/${user}/trak/${RANDOM} -export TMPDIR=$DATA/trak/${RANDOM} -if [ ! -d $TMPDIR ]; then mkdir -p $TMPDIR; fi -if [ -s ${TMPDIR}/tmpsynvit ]; then rm ${TMPDIR}/tmpsynvit; fi -if [ -s ${TMPDIR}/tmprawvit ]; then rm ${TMPDIR}/tmprawvit; fi +export TMPDIR=${DATA}/trak/${RANDOM} +mkdir -p "${TMPDIR}" +rm -f "${TMPDIR}/tmpsynvit" +rm -f "${TMPDIR}/tmprawvit" export flag_pgb=${flag_pgb:-q} -wgrib_parmlist=" HGT:850 HGT:700 UGRD:850 UGRD:700 UGRD:500 VGRD:850 VGRD:700 VGRD:500 SurfaceU SurfaceV ABSV:850 ABSV:700 PRMSL:MSL MSLET" +wgrib_parmlist="HGT:850 HGT:700 UGRD:850 UGRD:700 UGRD:500 VGRD:850 VGRD:700 VGRD:500 SurfaceU SurfaceV ABSV:850 ABSV:700 PRMSL:MSL MSLET" -export maxtime=22 # Max number of forecast time levels +export maxtime=22 # Max number of forecast time levels -if [ ! -d ${vdir} ]; then mkdir -p ${vdir}; fi -if [ ! -d ${TMPDIR} ]; then mkdir -p ${TMPDIR}; fi +mkdir -p "${vdir}" +mkdir -p "${TMPDIR}" scc=${symdh:0:2} syy=${symdh:2:2} @@ -216,100 +199,124 @@ shh=${symdh:8:2} dishh=${shh} symd=${symdh:0:8} -case ${shh} in - 0|00) dishh="00";; - 3|03) dishh="03";; - 6|06) dishh="06";; - 12) dishh="12";; - 15) dishh="15";; - 18) dishh="18";; -esac - #---------------------------------------------------# # Convert the input model to lowercase letters and # check to see if it's a valid model, and assign a # model ID number to it. #---------------------------------------------------# -cmodel=$(echo ${cmodel} | tr "[A-Z]" "[a-z]") +cmodel=${cmodel,,} case ${cmodel} in - gdas) set +x; echo " "; echo " ++ operational GDAS chosen"; set_trace; - fcstlen=9 ; - fcsthrs="" - for fhr in $( seq 0 $BKGFREQ 9); do - fhrchar=$(printf %02d $fhr) - fcsthrs="$fcsthrs $fhrchar" - done - atcfnum=72 ; - atcfname="gdas" ; - atcfout="gdas" ; - if [ $BKGFREQ -eq 1 ]; then - atcffreq=100 - elif [ $BKGFREQ -eq 3 ]; then - atcffreq=300 - fi - mslpthresh=0.0015 - v850thresh=1.5000 - modtyp='global' - file_sequence="onebig" - lead_time_units='hours' - export PHASEFLAG=n - export WCORE_DEPTH=1.0 - #export PHASE_SCHEME=vtt - #export PHASE_SCHEME=cps - export PHASE_SCHEME=both - export STRUCTFLAG=n - export IKEFLAG=n - export trkrtype='tracker' - # g2_jpdtn sets the variable that will be used as "JPDTN" for - # the call to getgb2, if gribver=2. jpdtn=1 for ens data, - # jpdtn=0 for deterministic data. - g2_jpdtn=0 - model=8;; - gfs) set +x; echo " "; echo " ++ operational GFS chosen"; set_trace; - fcsthrsgfs=' 00 06 12 18 24 30 36 42 48 54 60 66 72 78'; - gfsdir=$COMIN; - gfsgfile=gfs.t${dishh}z.pgrbf; - model=1;; - mrf) set +x; echo " "; echo " ++ operational MRF chosen"; set_trace; - fcsthrsmrf=' 00 12 24 36 48 60 72'; - mrfdir=$COMIN; - mrfgfile=drfmr.t${dishh}z.pgrbf; - model=2;; - ukmet) set +x; echo " "; echo " ++ operational UKMET chosen"; set_trace; - fcsthrsukmet=' 00 12 24 36 48 60 72'; - ukmetdir=$COMIN; - ukmetgfile=ukmet.t${dishh}z.ukmet; - model=3;; - ecmwf) set +x; echo " "; echo " ++ operational ECMWF chosen"; set_trace; - fcsthrsecmwf=' 00 24 48 72'; - ecmwfdir=$COMIN; - ecmwfgfile=ecmgrb25.t12z; - model=4;; - ngm) set +x; echo " "; echo " ++ operational NGM chosen"; set_trace; - fcsthrsngm=' 00 06 12 18 24 30 36 42 48'; - ngmdir=$COMIN; - ngmgfile=ngm.t${dishh}z.pgrb.f; - model=5;; - nam) set +x; echo " "; echo " ++ operational Early NAM chosen"; set_trace; - fcsthrsnam=' 00 06 12 18 24 30 36 42 48'; - namdir=$COMIN; - namgfile=nam.t${dishh}z.awip32; - model=6;; - ngps) set +x; echo " "; echo " ++ operational NAVGEM chosen"; set_trace; - fcsthrsngps=' 00 12 24 36 48 60 72'; - #ngpsdir=/com/hourly/prod/hourly.${symd}; - ngpsdir=$OMIN; - ngpsgfile=fnoc.t${dishh}z; - model=7;; - other) set +x; echo " "; echo " Model selected by user is ${cmodel}, which is a "; - echo "user-defined model, NOT operational...."; echo " "; set_trace; - model=9;; - *) set +x; echo " "; echo " !!! Model selected is not recognized."; - echo " Model= ---> ${cmodel} <--- ..... Please submit the script again...."; - echo " "; set_trace; exit 8;; + gdas) + echo " " + echo " ++ operational GDAS chosen" + fcsthrs="" + for fhr in $(seq 0 "${BKGFREQ}" 9); do + fhrchar=$(printf %02d "${fhr}") + fcsthrs="${fcsthrs} ${fhrchar}" + done + atcfnum=72 + atcfname="gdas" + if [[ "${BKGFREQ}" -eq 1 ]]; then + atcffreq=100 + elif [[ "${BKGFREQ}" -eq 3 ]]; then + atcffreq=300 + fi + modtyp='global' + file_sequence="onebig" + lead_time_units='hours' + export PHASEFLAG=n + export WCORE_DEPTH=1.0 + export PHASE_SCHEME=both + export STRUCTFLAG=n + export IKEFLAG=n + export trkrtype='tracker' + # g2_jpdtn sets the variable that will be used as "JPDTN" for + # the call to getgb2, if gribver=2. jpdtn=1 for ens data, + # jpdtn=0 for deterministic data. + g2_jpdtn=0 + model=8 + ;; + gfs) + echo " " + echo " ++ operational GFS chosen" + fcsthrsgfs='00 06 12 18 24 30 36 42 48 54 60 66 72 78' + gfsdir="${COMIN}" + gfsgfile=gfs.t${dishh}z.pgrbf + model=1 + ;; + mrf) + echo " " + echo " ++ operational MRF chosen" + fcsthrsmrf='00 12 24 36 48 60 72' + mrfdir="${COMIN}" + mrfgfile=drfmr.t${dishh}z.pgrbf + model=2 + ;; + ukmet) + echo " " + echo " ++ operational UKMET chosen" + fcsthrsukmet='00 12 24 36 48 60 72' + ukmetdir="${COMIN}" + ukmetgfile=ukmet.t${dishh}z.ukmet + model=3 + ;; + ecmwf) + echo " " + echo " ++ operational ECMWF chosen" + ecmwfdir="${COMIN}" + ecmwfgfile=ecmgrb25.t12z + model=4 + ;; + ngm) + set +x + echo " " + echo " ++ operational NGM chosen" + set_trace + fcsthrsngm='00 06 12 18 24 30 36 42 48' + ngmdir="${COMIN}" + ngmgfile=ngm.t${dishh}z.pgrb.f + model=5 + ;; + nam) + echo " " + echo " ++ operational Early NAM chosen" + fcsthrsnam='00 06 12 18 24 30 36 42 48' + namdir="${COMIN}" + namgfile=nam.t${dishh}z.awip32 + model=6 + ;; + ngps) + echo " " + echo " ++ operational NAVGEM chosen" + fcsthrsngps='00 12 24 36 48 60 72' + #ngpsdir=/com/hourly/prod/hourly.${symd}; + ngpsdir="${COMIN}" + ngpsgfile=fnoc.t${dishh}z + model=7 + ;; + other) + cat << EOF +Model selected by user is ${cmodel}, which is a +user-defined model, NOT operational.... + +EOF + model=9 + ;; + *) + msg=$( + cat << EOF + +FATAL ERROR: Model selected is not recognized. +Model= ---> ${cmodel} <--- ..... Please submit the script again.... + +EOF + ) + err=8 + err_exit "${msg}" + ;; esac @@ -323,14 +330,11 @@ esac # if the model is user-defined. #------------------------------------------------- -fct=1 -while [ ${fct} -le 14 ]; -do - fh[${fct}]=99 - let fct=fct+1 +export fh +for ((fct = 1; fct <= 14; fct++)); do + fh[fct]=99 done - #------------------------------------------------------# # Set the directories for the operational files. For # a user-specified model, we need to process the @@ -338,142 +342,125 @@ done # data directory, etc..... #------------------------------------------------------# -if [ ${cmodel} = 'other' ]; then - -# This next bit of code tears apart the input file name to get the -# data directory and data file names. pos1, pos2, pos3 and pos4 -# refer to character string positions in the filename string. The -# idea of this next bit of code is to pull the file name apart to -# get a shell for the file name, so that if a user has a file -# name such as pgbf00.97090100, the script knows where in the -# string to substitute the forecast hours. IMPORTANT NOTE: The -# file name that the user enters must have the characters "XX" in -# in place of the forecast hour characters "00" in order for this -# to work. -# -# pos1= character position immediately before "00" starts -# pos2= character position at which "00" starts -# pos3= character position immediately after "00" -# pos4= character position of last character in name - - otherdir=$(dirname ${inpfile}) - fname=$(basename ${inpfile}) - - pos2=$(echo ${fname} | awk '{ match($0,/XX/); print RSTART }') - pos4=$(echo ${fname} | awk '{ match($0,/$/); print RSTART }') - let pos4=pos4-1 - let pos1=pos2-1 - let pos3=pos2+2 - - if [ ${pos2} -eq 0 ]; then - set +x - echo " " - echo " !!! ERROR! Something wrong with name of input file name for the" - echo " analysis file. Either the input file is missing, or you did not" - echo " replace the forecast hour characters 00 with XX. Please check the" - echo " name in the kickoff script and qsub it again. Exiting....." - echo " " - set_trace - exit 8 - fi - - fnamebeg=$(echo ${fname} | cut -c1-${pos1}) - if [ ${pos4} -ge ${pos3} ]; then - fnameend=$(echo ${fname} | cut -c${pos3}-${pos4}) - else - fnameend="" - fi - - fflag='y' - fhour=0 - fcsthrsother='' - fhrct=0 - while [ ${fflag} = 'y' ]; - do - - if [ ${fhrct} -eq 14 ]; then - set +x - echo " " - echo " !!! Exiting loop, only processing 14 forecast files ...." - echo " " - set_trace - break +if [[ "${cmodel}" == 'other' ]]; then + + # This next bit of code tears apart the input file name to get the + # data directory and data file names. pos1, pos2, pos3 and pos4 + # refer to character string positions in the filename string. The + # idea of this next bit of code is to pull the file name apart to + # get a shell for the file name, so that if a user has a file + # name such as pgbf00.97090100, the script knows where in the + # string to substitute the forecast hours. IMPORTANT NOTE: The + # file name that the user enters must have the characters "XX" in + # in place of the forecast hour characters "00" in order for this + # to work. + # + # pos1= character position immediately before "00" starts + # pos2= character position at which "00" starts + # pos3= character position immediately after "00" + # pos4= character position of last character in name + + otherdir=$(dirname "${inpfile}") + fname=$(basename "${inpfile}") + + fnamebeg=$(grep -Po '.*(?=XX)' <<< "${fname}") + fnameend=$(grep -Po '(?<=XX).*($)' <<< "${fname}") + + if [[ -z "${fnamebeg}" ]]; then + read -r -d '' msg << EOF +FATAL ERROR: Something wrong with name of input file name for the +analysis file. Either the input file is missing, or you did not +replace the forecast hour characters 00 with XX. Please check the +name in the kickoff script and qsub it again. +EOF + err=8 + err_exit "${msg}" fi - if [ ${fhour} -lt 10 ]; then - fhour=0${fhour} - fi + fflag='y' + fhour=0 + fcsthrsother='' + fhrct=0 + while [[ ${fflag} == 'y' ]]; do - if [ -s ${otherdir}/${fnamebeg}${fhour}${fnameend} ]; then - maxhour=${fhour} - fcsthrsother=${fcsthrsother}" ${fhour}" - set +x - echo " " - echo " +++ Found file ${fnamebeg}${fhour}${fnameend}" - echo " " - set_trace - let fhrct=fhrct+1 - else - fflag='n' - fi + if [[ "${fhrct}" -eq 14 ]]; then + cat << EOF - let fhour=fhour+fhint - - done - - if [ ! -s ${otherdir}/${fnamebeg}00${fnameend} ]; then - set +x - echo " " - echo " !!! ERROR in $(basename $0)" - echo " !!! Input analysis file cannot be found." - echo " !!! The tracker is looking for this file in: " - echo " !!! ----> ${otherdir}/${fnamebeg}00${fnameend}" - echo " !!! Please check the directory to make sure the file" - echo " !!! is there and then submit this job again." - echo " " - set_trace - exit 8 - fi - - set +x - echo " " - echo " Max forecast hour is $maxhour" - echo " List of forecast hours: $fcsthrsother" - echo " " - set_trace - -# -------------------------------------------------- -# In order for the fortran program to know how many -# forecast times there are and what those forecast -# hours are, we need to include this information in -# the namelist file. So first, put this information -# into an array, then at the end of this script, -# we'll put it into the namelist file. - - fhour=0 - fct=1 - while [ ${fct} -le 14 ]; - do - - if [ ${fhour} -le ${maxhour} ]; then - fh[${fct}]=${fhour} - else - fh[${fct}]=99 +!!! Exiting loop, only processing 14 forecast files .... + +EOF + break + fi + + fhour=$(printf '%02d' "${fhour}") + + if [[ -s "${otherdir}/${fnamebeg}${fhour}${fnameend}" ]]; then + maxhour=${fhour} + fcsthrsother="${fcsthrsother} ${fhour}" + cat << EOF + ++++ Found file ${fnamebeg}${fhour}${fnameend} + +EOF + fhrct=$((fhrct + 1)) + else + fflag='n' + fi + + fhour=$((fhour + fhint)) + + done + + if [[ ! -s "${otherdir}/${fnamebeg}00${fnameend}" ]]; then + msg=$( + cat << EOF + +!!! FATAL ERROR in $(basename "$0"): +!!! Input analysis file cannot be found. +!!! The tracker is looking for this file in: +!!! ----> ${otherdir}/${fnamebeg}00${fnameend} +!!! Please check the directory to make sure the file +!!! is there and then submit this job again. + +EOF + ) + err=8 + err_exit "${msg}" fi - let fct=fct+1 - let fhour=fhour+fhint + cat << EOF - done +Max forecast hour is ${maxhour} +List of forecast hours: ${fcsthrsother} +EOF + + # -------------------------------------------------- + # In order for the fortran program to know how many + # forecast times there are and what those forecast + # hours are, we need to include this information in + # the namelist file. So first, put this information + # into an array, then at the end of this script, + # we'll put it into the namelist file. + + fhour=0 + for ((fcnt = 1; fcnt <= 14; fcnt++)); do + if [[ "${fhour}" -le "${maxhour}" ]]; then + fh[fct]=${fhour} + else + fh[fct]=99 + fi + fhour=$((fhour + fhint)) + done fi -cpfs $DATA/tcvitals ${vdir}/vitals.${symd}${dishh} +cpfs "${DATA}/tcvitals" "${vdir}/vitals.${symd}${dishh}" -grep -v TEST ${vdir}/vitals.${symd}${dishh} | \ - awk 'substr($0,6,1) !~ /[8-9]/ {print $0}' >${vdir}/tempvit.nonameless +# shellcheck disable=SC2312 +grep -v TEST "${vdir}/vitals.${symd}${dishh}" | + awk 'substr($0,6,1) !~ /[8-9]/ {print $0}' > "${vdir}/tempvit.nonameless" -mv ${vdir}/tempvit.nonameless ${vdir}/vitals.${symd}${dishh} +mv "${vdir}/tempvit.nonameless" "${vdir}/vitals.${symd}${dishh}" #--------------------------------------------------------------# # Now run a fortran program that will read all the TC vitals @@ -492,18 +479,16 @@ syy6=${ymdh6ago:2:2} smm6=${ymdh6ago:4:2} sdd6=${ymdh6ago:6:2} shh6=${ymdh6ago:8:2} -symd6=${ymdh6ago:2:6} ymdh6ahead=$(date --utc +%Y%m%d%H -d "${symd} ${dishh} + 6 hours") syyp6=${ymdh6ahead:2:2} smmp6=${ymdh6ahead:4:2} sddp6=${ymdh6ahead:6:2} shhp6=${ymdh6ahead:8:2} -symdp6=${ymdh6ahead:2:6} vit_incr=6 -cat<$TMPDIR/suv_input +cat << EOF > "${TMPDIR}/suv_input" &datenowin dnow%yy=${syy}, dnow%mm=${smm}, dnow%dd=${sdd}, dnow%hh=${dishh}/ &dateoldin dold%yy=${syy6}, dold%mm=${smm6}, @@ -513,17 +498,20 @@ cat<$TMPDIR/suv_input &hourinfo vit_hr_incr=${vit_incr}/ EOF -numvitrecs=$(cat ${vdir}/vitals.${symd}${dishh} | wc -l) -if [ ${numvitrecs} -eq 0 ]; then - set +x - echo " " - echo "!!! ERROR -- There are no vitals records for this time period." - echo "!!! File ${vdir}/vitals.${symd}${dishh} is empty." - echo "!!! It could just be that there are no storms for the current" - echo "!!! time. Please check the dates and submit this job again...." - echo " " - set_trace - exit 8 +numvitrecs=$(wc -l "${vdir}/vitals.${symd}${dishh}") +if [[ ${numvitrecs} -eq 0 ]]; then + msg=$( + cat << EOF + +!!! FATAL ERROR: There are no vitals records for this time period. +!!! File ${vdir}/vitals.${symd}${dishh} is empty. +!!! It could just be that there are no storms for the current +!!! time. Please check the dates and submit this job again.... + +EOF + ) + err=8 + err_exit "${msg}" fi # - - - - - - - - - - - - - @@ -543,8 +531,8 @@ fi # was messing up the "(length($4) == 8)" statement logic. # - - - - - - - - - - - - - -sed -e "s/\:/ /g" ${vdir}/vitals.${symd}${dishh} > ${TMPDIR}/tempvit -mv ${TMPDIR}/tempvit ${vdir}/vitals.${symd}${dishh} +sed -e "s/\:/ /g" "${vdir}/vitals.${symd}${dishh}" > "${TMPDIR}/tempvit" +mv "${TMPDIR}/tempvit" "${vdir}/vitals.${symd}${dishh}" awk ' { @@ -560,78 +548,61 @@ awk ' printf ("%s19%s\n",substr($0,1,19),substr($0,20)) } } -} ' ${vdir}/vitals.${symd}${dishh} >${TMPDIR}/vitals.${symd}${dishh}.y4 - -mv ${TMPDIR}/vitals.${symd}${dishh}.y4 ${vdir}/vitals.${symd}${dishh} +} ' "${vdir}/vitals.${symd}${dishh}" > "${TMPDIR}/vitals.${symd}${dishh}.y4" -#cpfs $auxtcvit ${vdir}/vitals.${symd}${dishh} +mv "${TMPDIR}/vitals.${symd}${dishh}.y4" "${vdir}/vitals.${symd}${dishh}" -pgm=$(basename $SUPVX) -if [ -s $DATA/prep_step ]; then - set +e - . $DATA/prep_step - set_strict +pgm=$(basename "${SUPVX}") +if [[ -s "${DATA}/prep_step" ]]; then + source "${DATA}/prep_step" else - [ -f errfile ] && rm errfile - export XLFUNITS=0 - unset $(env | grep XLFUNIT | awk -F= '{print $1}') - - if [ -z "${XLFRTEOPTS:-}" ]; then - export XLFRTEOPTS="unit_vars=yes" - else - export XLFRTEOPTS="${XLFRTEOPTS}:unit_vars=yes" - fi - -fi - -if [ -s fort.* ]; then - rm fort.* + [[ -f errfile ]] && rm errfile + export XLFUNITS=0 + # shellcheck disable=SC2046,SC2312 + unset $(env | grep XLFUNIT | awk -F= '{print $1}') + export XLFRTEOPTS="${XLFRTEOPTS:+${XLFRTEOPTS}:}unit_vars=yes" fi -${NLN} ${vdir}/vitals.${symd}${dishh} fort.31 -${NLN} ${vdir}/vitals.upd.${cmodel}.${symd}${dishh} fort.51 +rm -f fort.* -##$XLF_LINKSSH -#if [ -z $XLF_LINKSSH ] ; then -#if [ -s $XLF_LINKSSH ; then $XLF_LINKSSH ; fi -#fi +${NLN} "${vdir}/vitals.${symd}${dishh}" fort.31 +${NLN} "${vdir}/vitals.upd.${cmodel}.${symd}${dishh}" fort.51 -$TIMEIT $SUPVX <$TMPDIR/suv_input > outout 2> errfile +${TIMEIT} "${SUPVX}" < "${TMPDIR}/suv_input" > outout 2> errfile err=$? -###cat errfile cat errfile >> outout cat outout >> supvit.out -set +u -[ -n "../$pgmout" ] && cat outout >> ../$pgmout -set -u +if [[ -n "${pgmout}" ]]; then + cat outout >> "../${pgmout}" +fi rm outout -set +x -echo -echo 'The foreground exit status for SUPVIT is ' $err -echo -set_trace - -if [ $err -eq 0 ]; then - set +x - echo " " - echo " Normal end for program supvitql (which updates TC vitals file)." - echo " " - set_trace +cat << EOF + +The foreground exit status for SUPVIT is ${err} + +EOF + +if [[ "${err}" -eq 0 ]]; then + cat << EOF + +Normal end for program supvitql (which updates TC vitals file). + +EOF else - set +x - echo " " - echo "!!! ERROR -- An error occurred while running supvitql, " - echo "!!! which is the program that updates the TC Vitals file." - echo "!!! Return code from supvitql = ${err}" - echo "!!! model= ${cmodel}, forecast initial time = ${symd}${dishh}" - echo "!!! Exiting...." - echo " " - set_trace -fi -if [[ ${err} -gt 0 ]]; then - exit 9 -fi + msg=$( + cat << EOF +!!! FATAL ERROR: An error occurred while running supvitql, +!!! which is the program that updates the TC Vitals file. +!!! Return code from supvitql = ${err} +!!! model= ${cmodel}, forecast initial time = ${symd}${dishh} +!!! Exiting.... + +EOF + ) + err=9 + err_exit "${msg}" +fi #------------------------------------------------------------------# # Now select all storms to be processed, that is, process every @@ -640,57 +611,52 @@ fi # then exit. #------------------------------------------------------------------# -numvitrecs=$(cat ${vdir}/vitals.upd.${cmodel}.${symd}${dishh} | wc -l) -if [ ${numvitrecs} -eq 0 ]; then - set +x - echo " " - echo "!!! ERROR -- There are no vitals records for this time period " - echo "!!! in the UPDATED vitals file." - echo "!!! File ${vdir}/vitals.upd.${cmodel}.${symd}${dishh} is empty." - echo "!!! Please check the dates and submit this job again...." - echo " " - set_trace - exit 8 +numvitrecs=$(wc -l "${vdir}/vitals.upd.${cmodel}.${symd}${dishh}") +if [[ "${numvitrecs}" -eq 0 ]]; then + cat << EOF + +!!! ERROR -- There are no vitals records for this time period +!!! in the UPDATED vitals file. +!!! File ${vdir}/vitals.upd.${cmodel}.${symd}${dishh} is empty. +!!! Please check the dates and submit this job again.... + +EOF + err=8 + err_exit fi -set +x -echo " " | tee storm_list -echo " " | tee -a storm_list -echo " " | tee -a storm_list -echo " *--------------------------------*" | tee -a storm_list -echo " | STORM SELECTION |" | tee -a storm_list -echo " *--------------------------------*" | tee -a storm_list -echo " " | tee -a storm_list -echo " Below is a list of the storms to be processed: " | tee -a storm_list -echo " " | tee -a storm_list -cat ${vdir}/vitals.upd.${cmodel}.${symd}${dishh} | tee -a storm_list -echo " " | tee -a storm_list -set_trace - -set +u -[ -n "../$pgmout" ] && cat storm_list >> ../$pgmout -set -u +# shellcheck disable=SC2312 +cat << EOF | tee stormlist + + + +*--------------------------------* +| STORM SELECTION | +*--------------------------------* + +Below is a list of the storms to be processed: + +$(cat "${vdir}/vitals.upd.${cmodel}.${symd}${dishh}") + +EOF + +if [[ -n "${pgmout}" ]]; then + cat storm_list >> "../${pgmout}" +fi rm storm_list -ict=1 -while [ $ict -le 15 ] -do - stormflag[${ict}]=3 - let ict=ict+1 +for ((ict = 1; ict <= 15; ict++)); do + stormflag[ict]=3 done dtg_current="${symd} ${dishh}00" -smax=$( grep "${dtg_current}" ${vdir}/vitals.upd.${cmodel}.${symd}${dishh} | wc -l) +smax=$(grep -c "${dtg_current}" "${vdir}/vitals.upd.${cmodel}.${symd}${dishh}") -sct=1 -while [ ${sct} -le ${smax} ] -do - stormflag[${sct}]=1 - let sct=sct+1 +for ((ict = 1; ict <= smax; ict++)); do + stormflag[sct]=1 done - #-----------------------------------------------------------------# # # ------ CUT APART INPUT GRIB FILES ------- @@ -711,201 +677,214 @@ done # sure to check the lbms in your fortran program after getgb). #-----------------------------------------------------------------# -set +x -echo " " -echo " -----------------------------------------" -echo " NOW CUTTING APART INPUT GRIB FILES TO " -echo " CREATE 1 BIG GRIB INPUT FILE " -echo " -----------------------------------------" -echo " " -set_trace +cat << EOF + +----------------------------------------- + NOW CUTTING APART INPUT GRIB FILES TO + CREATE 1 BIG GRIB INPUT FILE +----------------------------------------- + +EOF #grid='255 0 151 71 70000 190000 128 0000 340000 1000 1000 64' #grid='255 0 360 181 90000 0000 128 -90000 -1000 1000 1000 64' #grid='255 0 360 181 90000 0000 128 -90000 -1000 1000 1000 0' -regflag=$(grep NHC ${vdir}/vitals.upd.${cmodel}.${symd}${dishh} | wc -l) +regflag=$(grep -c NHC "${vdir}/vitals.upd.${cmodel}.${symd}${dishh}") # ---------------------------- # Process NGM, if selected # ---------------------------- -if [ ${model} -eq 5 ]; then - - grid='255 0 151 71 70000 190000 128 0000 340000 1000 1000 64' - - if [ ${regflag} = 'n' ]; then - set +x - echo " " - echo " *******************************************************************" - echo " !!! NGM model has been selected, but there are no storms in the" - echo " !!! TC Vitals file that are from NHC. Therefore, unless you have" - echo " !!! entered your own auxiliary TC vitals file that has a storm " - echo " !!! within the NGM domain, the tracker will exit after reading " - echo " !!! in the analysis data." - echo " *******************************************************************" - echo " " - set_trace - fi - - if [ -s ${vdir}/ngmlatlon.pgrb.${symd}${dishh} ]; then - rm ${vdir}/ngmlatlon.pgrb.${symd}${dishh} - fi - - for fhour in ${fcsthrsngm} - do - - if [ ! -s ${ngmdir}/${ngmgfile}${fhour} ]; then - set +x - echo " " - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " !!! NGM File missing: ${ngmdir}/${ngmgfile}${fhour}" - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - set_trace - continue - fi - if [ -s $TMPDIR/tmpixfile ]; then rm $TMPDIR/tmpixfile; fi - ${GRBINDEX:?} ${ngmdir}/${ngmgfile}${fhour} $TMPDIR/tmpixfile - x1=$TMPDIR/tmpixfile - - set +x - echo " " - echo " Extracting NGM GRIB data for forecast hour = $fhour" - echo " " - set_trace - - g1=${ngmdir}/${ngmgfile}${fhour} - - ${COPYGB:?} -g"$grid" -k'2*-1 104 -1 33 100 850' $g1 $x1 $TMPDIR/ngmllu850.grb.f${fhour}; rcc1=$? - ${COPYGB:?} -g"$grid" -k'2*-1 104 -1 33 100 700' $g1 $x1 $TMPDIR/ngmllu700.grb.f${fhour}; rcc2=$? - ${COPYGB:?} -g"$grid" -k'2*-1 104 -1 33 100 500' $g1 $x1 $TMPDIR/ngmllu500.grb.f${fhour}; rcc3=$? - ${COPYGB:?} -g"$grid" -k'2*-1 104 -1 33 105 10' $g1 $x1 $TMPDIR/ngmllu10m.grb.f${fhour}; rcc4=$? - ${COPYGB:?} -g"$grid" -k'2*-1 104 -1 41 100 850' $g1 $x1 $TMPDIR/ngmllav850.grb.f${fhour}; rcc5=$? - ${COPYGB:?} -g"$grid" -k'2*-1 104 -1 41 100 700' $g1 $x1 $TMPDIR/ngmllav700.grb.f${fhour}; rcc6=$? - ${COPYGB:?} -g"$grid" -k'2*-1 104 -1 7 100 850' $g1 $x1 $TMPDIR/ngmllz850.grb.f${fhour}; rcc7=$? - ${COPYGB:?} -g"$grid" -k'2*-1 104 -1 7 100 700' $g1 $x1 $TMPDIR/ngmllz700.grb.f${fhour}; rcc8=$? - ${COPYGB:?} -g"$grid" -k'2*-1 104 -1 2 102 0' $g1 $x1 $TMPDIR/ngmllmslp.grb.f${fhour}; rcc9=$? - - if [ $rcc1 -eq 134 -o $rcc2 -eq 134 -o $rcc3 -eq 134 -o $rcc4 -eq 134 -o $rcc5 -eq 134 -o \ - $rcc6 -eq 134 -o $rcc7 -eq 134 -o $rcc8 -eq 134 -o $rcc9 -eq 134 ]; then - set +x - echo " " - echo "!!! ERROR using $COPYGB to interpolate ngm data. We will stop execution because" - echo "!!! some variables may have been copied okay, while some obviously have not, " - echo "!!! and that could lead to unreliable results from the tracker. Check to make" - echo "!!! sure you've allocated enough memory for this job (error 134 using $COPYGB is " - echo "!!! typically due to using more memory than you've allocated). Exiting....." - echo " " - set_trace - exit 8 +if [[ "${model}" -eq 5 ]]; then + + grid='255 0 151 71 70000 190000 128 0000 340000 1000 1000 64' + + if [[ "${regflag}" == 'n' ]]; then + cat << EOF + +******************************************************************* +!!! NGM model has been selected, but there are no storms in the +!!! TC Vitals file that are from NHC. Therefore, unless you have +!!! entered your own auxiliary TC vitals file that has a storm +!!! within the NGM domain, the tracker will exit after reading +!!! in the analysis data. +******************************************************************* + +EOF fi - cat $TMPDIR/ngmllu850.grb.f${fhour} $TMPDIR/ngmllu700.grb.f${fhour} \ - $TMPDIR/ngmllu500.grb.f${fhour} $TMPDIR/ngmllz850.grb.f${fhour} \ - $TMPDIR/ngmllz700.grb.f${fhour} $TMPDIR/ngmllmslp.grb.f${fhour} \ - $TMPDIR/ngmllav850.grb.f${fhour} $TMPDIR/ngmllav700.grb.f${fhour} \ - $TMPDIR/ngmllu10m.grb.f${fhour} \ - >>${vdir}/ngmlatlon.pgrb.${symd}${dishh} + rm -f "${vdir}/ngmlatlon.pgrb.${symd}${dishh}" - done + for fhour in ${fcsthrsngm}; do - ${GRBINDEX:?} ${vdir}/ngmlatlon.pgrb.${symd}${dishh} ${vdir}/ngmlatlon.pgrb.ix.${symd}${dishh} - gribfile=${vdir}/ngmlatlon.pgrb.${symd}${dishh} - ixfile=${vdir}/ngmlatlon.pgrb.ix.${symd}${dishh} + if [[ ! -s "${ngmdir}/${ngmgfile}${fhour}" ]]; then + cat << EOF -fi +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! NGM File missing: ${ngmdir}/${ngmgfile}${fhour} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +EOF + continue + fi + rm -f "${TMPDIR}/tmpixfile" + ${GRBINDEX:?} "${ngmdir}/${ngmgfile}${fhour}" "${TMPDIR}/tmpixfile" + x1="${TMPDIR}/tmpixfile" + + cat << EOF +Extracting NGM GRIB data for forecast hour = ${fhour} + +EOF + + g1="${ngmdir}/${ngmgfile}${fhour}" + + ${COPYGB:?} -g"${grid}" -k'2*-1 104 -1 33 100 850' "${g1}" "${x1}" "${TMPDIR}/ngmllu850.grb.f${fhour}" + rcc1=$? + ${COPYGB:?} -g"${grid}" -k'2*-1 104 -1 33 100 700' "${g1}" "${x1}" "${TMPDIR}/ngmllu700.grb.f${fhour}" + rcc2=$? + ${COPYGB:?} -g"${grid}" -k'2*-1 104 -1 33 100 500' "${g1}" "${x1}" "${TMPDIR}/ngmllu500.grb.f${fhour}" + rcc3=$? + ${COPYGB:?} -g"${grid}" -k'2*-1 104 -1 33 105 10' "${g1}" "${x1}" "${TMPDIR}/ngmllu10m.grb.f${fhour}" + rcc4=$? + ${COPYGB:?} -g"${grid}" -k'2*-1 104 -1 41 100 850' "${g1}" "${x1}" "${TMPDIR}/ngmllav850.grb.f${fhour}" + rcc5=$? + ${COPYGB:?} -g"${grid}" -k'2*-1 104 -1 41 100 700' "${g1}" "${x1}" "${TMPDIR}/ngmllav700.grb.f${fhour}" + rcc6=$? + ${COPYGB:?} -g"${grid}" -k'2*-1 104 -1 7 100 850' "${g1}" "${x1}" "${TMPDIR}/ngmllz850.grb.f${fhour}" + rcc7=$? + ${COPYGB:?} -g"${grid}" -k'2*-1 104 -1 7 100 700' "${g1}" "${x1}" "${TMPDIR}/ngmllz700.grb.f${fhour}" + rcc8=$? + ${COPYGB:?} -g"${grid}" -k'2*-1 104 -1 2 102 0' "${g1}" "${x1}" "${TMPDIR}/ngmllmslp.grb.f${fhour}" + rcc9=$? + + if [[ ${rcc1} -eq 134 || ${rcc2} -eq 134 || ${rcc3} -eq 134 || ${rcc4} -eq 134 || ${rcc5} -eq 134 || + ${rcc6} -eq 134 || ${rcc7} -eq 134 || ${rcc8} -eq 134 || ${rcc9} -eq 134 ]]; then + msg=$( + cat << EOF + +!!! FATAL ERROR using ${COPYGB} to interpolate ngm data. We will stop execution because +!!! some variables may have been copied okay, while some obviously have not, +!!! and that could lead to unreliable results from the tracker. Check to make +!!! sure you've allocated enough memory for this job (error 134 using ${COPYGB} is +!!! typically due to using more memory than you've allocated). Exiting..... + +EOF + ) + err=8 + err_exit "${msg}" + fi + + cat "${TMPDIR}/ngmllu850.grb.f${fhour}" "${TMPDIR}/ngmllu700.grb.f${fhour}" \ + "${TMPDIR}/ngmllu500.grb.f${fhour}" "${TMPDIR}/ngmllz850.grb.f${fhour}" \ + "${TMPDIR}/ngmllz700.grb.f${fhour}" "${TMPDIR}/ngmllmslp.grb.f${fhour}" \ + "${TMPDIR}/ngmllav850.grb.f${fhour}" "${TMPDIR}/ngmllav700.grb.f${fhour}" \ + "${TMPDIR}/ngmllu10m.grb.f${fhour}" \ + >> "${vdir}/ngmlatlon.pgrb.${symd}${dishh}" + + done + + ${GRBINDEX:?} "${vdir}/ngmlatlon.pgrb.${symd}${dishh}" "${vdir}/ngmlatlon.pgrb.ix.${symd}${dishh}" + gribfile="${vdir}/ngmlatlon.pgrb.${symd}${dishh}" + ixfile="${vdir}/ngmlatlon.pgrb.ix.${symd}${dishh}" + +fi # ---------------------------------- # Process Early NAM, if selected # ---------------------------------- -if [ ${model} -eq 6 ]; then - - grid='255 0 301 141 70000 190000 128 0000 340000 500 500 64' - - if [ ${regflag} = 'n' ]; then - set +x - echo " " - echo " *******************************************************************" - echo " !!! NAM model has been selected, but there are no storms in the" - echo " !!! TC Vitals file that are from NHC. Therefore, unless you have" - echo " !!! entered your own auxiliary TC vitals file that has a storm " - echo " !!! within the NAM domain, the tracker will exit after reading " - echo " !!! in the analysis data." - echo " *******************************************************************" - echo " " - set_trace - fi - - if [ -s ${vdir}/namlatlon.pgrb.${symd}${dishh} ]; then - rm ${vdir}/namlatlon.pgrb.${symd}${dishh} - fi - - for fhour in ${fcsthrsnam} - do - - if [ ! -s ${namdir}/${namgfile}${fhour}.tm00 ]; then - set +x - echo " " - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " !!! Early NAM File missing: ${namdir}/${namgfile}${fhour}.tm00" - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - set_trace - continue - fi - if [ -s $TMPDIR/tmpixfile ]; then rm $TMPDIR/tmpixfile; fi - ${GRBINDEX:?} ${namdir}/${namgfile}${fhour}.tm00 $TMPDIR/tmpixfile - x1=$TMPDIR/tmpixfile - - set +x - echo " " - echo " Extracting Early NAM GRIB data for forecast hour = $fhour" - echo " " - set_trace - - g1=${namdir}/${namgfile}${fhour}.tm00 - - if [ -s $TMPDIR/namlatlon.pgrb ]; then rm $TMPDIR/namlatlon.pgrb; fi - ${COPYGB:?} -g"$grid" -k'4*-1 33 100 850' $g1 $x1 $TMPDIR/namllu850.grb.f${fhour}; rcc1=$? - ${COPYGB:?} -g"$grid" -k'4*-1 33 100 700' $g1 $x1 $TMPDIR/namllu700.grb.f${fhour}; rcc2=$? - ${COPYGB:?} -g"$grid" -k'4*-1 33 100 500' $g1 $x1 $TMPDIR/namllu500.grb.f${fhour}; rcc3=$? - ${COPYGB:?} -g"$grid" -k'4*-1 33 105 10' $g1 $x1 $TMPDIR/namllu10m.grb.f${fhour}; rcc4=$? - ${COPYGB:?} -g"$grid" -k'4*-1 41 100 850' $g1 $x1 $TMPDIR/namllav850.grb.f${fhour}; rcc5=$? - ${COPYGB:?} -g"$grid" -k'4*-1 41 100 700' $g1 $x1 $TMPDIR/namllav700.grb.f${fhour}; rcc6=$? - ${COPYGB:?} -g"$grid" -k'4*-1 7 100 850' $g1 $x1 $TMPDIR/namllz850.grb.f${fhour}; rcc7=$? - ${COPYGB:?} -g"$grid" -k'4*-1 7 100 700' $g1 $x1 $TMPDIR/namllz700.grb.f${fhour}; rcc8=$? - ${COPYGB:?} -g"$grid" -k'4*-1 2 102 0' $g1 $x1 $TMPDIR/namllmslp.grb.f${fhour}; rcc9=$? - - if [ $rcc1 -eq 134 -o $rcc2 -eq 134 -o $rcc3 -eq 134 -o $rcc4 -eq 134 -o $rcc5 -eq 134 -o \ - $rcc6 -eq 134 -o $rcc7 -eq 134 -o $rcc8 -eq 134 -o $rcc9 -eq 134 ]; then - set +x - echo " " - echo "!!! ERROR using $COPYGB to interpolate nam data. We will stop execution because" - echo "!!! some variables may have been copied okay, while some obviously have not, " - echo "!!! and that could lead to unreliable results from the tracker. Check to make" - echo "!!! sure you've allocated enough memory for this job (error 134 using $COPYGB is " - echo "!!! typically due to using more memory than you've allocated). Exiting....." - echo " " - set_trace - exit 8 +if [[ "${model}" -eq 6 ]]; then + + grid='255 0 301 141 70000 190000 128 0000 340000 500 500 64' + + if [[ "${regflag}" == 'n' ]]; then + cat << EOF + +******************************************************************* +!!! NAM model has been selected, but there are no storms in the +!!! TC Vitals file that are from NHC. Therefore, unless you have +!!! entered your own auxiliary TC vitals file that has a storm +!!! within the NAM domain, the tracker will exit after reading +!!! in the analysis data. +******************************************************************* + +EOF fi - cat $TMPDIR/namllu850.grb.f${fhour} $TMPDIR/namllu700.grb.f${fhour} \ - $TMPDIR/namllu500.grb.f${fhour} $TMPDIR/namllz850.grb.f${fhour} \ - $TMPDIR/namllz700.grb.f${fhour} $TMPDIR/namllmslp.grb.f${fhour} \ - $TMPDIR/namllav850.grb.f${fhour} $TMPDIR/namllav700.grb.f${fhour} \ - $TMPDIR/namllu10m.grb.f${fhour} \ - >>${vdir}/namlatlon.pgrb.${symd}${dishh} + rm -f "${vdir}/namlatlon.pgrb.${symd}${dishh}" - done + for fhour in ${fcsthrsnam}; do + if [[ ! -s "${namdir}/${namgfile}${fhour}.tm00" ]]; then + cat << EOF - ${GRBINDEX:?} ${vdir}/namlatlon.pgrb.${symd}${dishh} ${vdir}/namlatlon.pgrb.ix.${symd}${dishh} - gribfile=${vdir}/namlatlon.pgrb.${symd}${dishh} - ixfile=${vdir}/namlatlon.pgrb.ix.${symd}${dishh} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! Early NAM File missing: ${namdir}/${namgfile}${fhour}.tm00 +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +EOF + continue + fi + rm -f "${TMPDIR}/tmpixfile" + ${GRBINDEX:?} "${namdir}/${namgfile}${fhour}.tm00" "${TMPDIR}/tmpixfile" + x1="${TMPDIR}/tmpixfile" -fi + cat << EOF + +Extracting Early NAM GRIB data for forecast hour = ${fhour} + +EOF + g1="${namdir}/${namgfile}${fhour}.tm00" + + rm -f "${TMPDIR}/namlatlon.pgrb" + ${COPYGB:?} -g"${grid}" -k'4*-1 33 100 850' "${g1}" "${x1}" "${TMPDIR}/namllu850.grb.f${fhour}" + rcc1=$? + ${COPYGB:?} -g"${grid}" -k'4*-1 33 100 700' "${g1}" "${x1}" "${TMPDIR}/namllu700.grb.f${fhour}" + rcc2=$? + ${COPYGB:?} -g"${grid}" -k'4*-1 33 100 500' "${g1}" "${x1}" "${TMPDIR}/namllu500.grb.f${fhour}" + rcc3=$? + ${COPYGB:?} -g"${grid}" -k'4*-1 33 105 10' "${g1}" "${x1}" "${TMPDIR}/namllu10m.grb.f${fhour}" + rcc4=$? + ${COPYGB:?} -g"${grid}" -k'4*-1 41 100 850' "${g1}" "${x1}" "${TMPDIR}/namllav850.grb.f${fhour}" + rcc5=$? + ${COPYGB:?} -g"${grid}" -k'4*-1 41 100 700' "${g1}" "${x1}" "${TMPDIR}/namllav700.grb.f${fhour}" + rcc6=$? + ${COPYGB:?} -g"${grid}" -k'4*-1 7 100 850' "${g1}" "${x1}" "${TMPDIR}/namllz850.grb.f${fhour}" + rcc7=$? + ${COPYGB:?} -g"${grid}" -k'4*-1 7 100 700' "${g1}" "${x1}" "${TMPDIR}/namllz700.grb.f${fhour}" + rcc8=$? + ${COPYGB:?} -g"${grid}" -k'4*-1 2 102 0' "${g1}" "${x1}" "${TMPDIR}/namllmslp.grb.f${fhour}" + rcc9=$? + + if [[ "${rcc1}" -eq 134 || "${rcc2}" -eq 134 || "${rcc3}" -eq 134 || "${rcc4}" -eq 134 || "${rcc5}" -eq 134 || + "${rcc6}" -eq 134 || "${rcc7}" -eq 134 || "${rcc8}" -eq 134 || "${rcc9}" -eq 134 ]]; then + cat << EOF + +!!! FATAL ERROR using ${COPYGB} to interpolate nam data. We will stop execution because +!!! some variables may have been copied okay, while some obviously have not, +!!! and that could lead to unreliable results from the tracker. Check to make +!!! sure you've allocated enough memory for this job (error 134 using ${COPYGB} is +!!! typically due to using more memory than you've allocated). Exiting..... + +EOF + err=8 + err_exit + fi + + cat "${TMPDIR}/namllu850.grb.f${fhour}" "${TMPDIR}/namllu700.grb.f${fhour}" \ + "${TMPDIR}/namllu500.grb.f${fhour}" "${TMPDIR}/namllz850.grb.f${fhour}" \ + "${TMPDIR}/namllz700.grb.f${fhour}" "${TMPDIR}/namllmslp.grb.f${fhour}" \ + "${TMPDIR}/namllav850.grb.f${fhour}" "${TMPDIR}/namllav700.grb.f${fhour}" \ + "${TMPDIR}/namllu10m.grb.f${fhour}" \ + >> "${vdir}/namlatlon.pgrb.${symd}${dishh}" + + done + + ${GRBINDEX:?} "${vdir}/namlatlon.pgrb.${symd}${dishh}" "${vdir}/namlatlon.pgrb.ix.${symd}${dishh}" + gribfile="${vdir}/namlatlon.pgrb.${symd}${dishh}" + ixfile="${vdir}/namlatlon.pgrb.ix.${symd}${dishh}" + +fi # ------------------------------ # Process ECMWF, if selected @@ -924,643 +903,575 @@ fi # be taken out, and the data should then be processed as the other normal # full-coverage global models (ukmet, mrf, gfs, NAVGEM) currently are. -if [ ${model} -eq 4 ]; then - - if [ ! -s ${ecmwfdir}/${ecmwfgfile} ]; then - set +x - echo " " - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " !!! ECMWF GRIB or Index File missing from directory: ${ecmwfdir}" - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " " - echo " !!! Due to missing ECMWF file, execution is ending...." - echo " " - set_trace - exit 8 - fi - - ${GRBINDEX:?} ${ecmwfdir}/${ecmwfgfile} $TMPDIR/${ecmwfgfile}.ix - x1=$TMPDIR/${ecmwfgfile}.ix - - if [ -s ${vdir}/ecmwf.bufzone.grb.${symd}${dishh} ]; then - rm ${vdir}/ecmwf.bufzone.grb.${symd}${dishh} - fi - if [ -s ${vdir}/ecmwf.bufzone.ix.${symd}${dishh} ]; then - rm ${vdir}/ecmwf.bufzone.ix.${symd}${dishh} - fi - - g1=${ecmwfdir}/${ecmwfgfile} - ecgrid='255 0 144 33 40000 0000 128 -40000 357500 2500 2500 64' - ${COPYGB:?} -g"$ecgrid" $g1 $x1 ${vdir}/ecmwf.bufzone.grb.${symd}${dishh} - ${GRBINDEX:?} ${vdir}/ecmwf.bufzone.grb.${symd}${dishh} ${vdir}/ecmwf.bufzone.ix.${symd}${dishh} - gribfile=${vdir}/ecmwf.bufzone.grb.${symd}${dishh} - ixfile=${vdir}/ecmwf.bufzone.ix.${symd}${dishh} +if [[ "${model}" -eq 4 ]]; then + if [[ ! -s "${ecmwfdir}/${ecmwfgfile}" ]]; then + msg=$( + cat << EOF -fi +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! ECMWF GRIB or Index File missing from directory: ${ecmwfdir} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +!!! Due to missing ECMWF file, execution is ending.... + +EOF + ) + err=8 + err_exit "${msg}" + fi + + ${GRBINDEX:?} "${ecmwfdir}/${ecmwfgfile}" "${TMPDIR}/${ecmwfgfile}.ix" + x1="${TMPDIR}/${ecmwfgfile}.ix" + rm -f "${vdir}/ecmwf.bufzone.grb.${symd}${dishh}" + rm -f "${vdir}/ecmwf.bufzone.ix.${symd}${dishh}" + + g1="${ecmwfdir}/${ecmwfgfile}" + ecgrid='255 0 144 33 40000 0000 128 -40000 357500 2500 2500 64' + ${COPYGB:?} -g"${ecgrid}" "${g1}" "${x1}" "${vdir}/ecmwf.bufzone.grb.${symd}${dishh}" + ${GRBINDEX:?} "${vdir}/ecmwf.bufzone.grb.${symd}${dishh}" "${vdir}/ecmwf.bufzone.ix.${symd}${dishh}" + gribfile="${vdir}/ecmwf.bufzone.grb.${symd}${dishh}" + ixfile="${vdir}/ecmwf.bufzone.ix.${symd}${dishh}" + +fi # ------------------------------ # Process GFS, if selected # ------------------------------ -if [ ${model} -eq 1 ]; then +if [[ "${model}" -eq 1 ]]; then - if [ -s ${vdir}/gfsgribfile.${symd}${dishh} ]; then - rm ${vdir}/gfsgribfile.${symd}${dishh} - fi + rm -f "${vdir}/gfsgribfile.${symd}${dishh}" - for fhour in ${fcsthrsgfs} - do + for fhour in ${fcsthrsgfs}; do + if [[ ! -s "${gfsdir}/${gfsgfile}${fhour}" ]]; then + cat << EOF - if [ ! -s ${gfsdir}/${gfsgfile}${fhour} ]; then - set +x - echo " " - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " !!! GFS File missing: ${gfsdir}/${gfsgfile}${fhour}" - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - set_trace - continue - fi - - gfile=${gfsdir}/${gfsgfile}${fhour} - ${WGRIB:?} -s $gfile >$TMPDIR/gfs.ix - - for parm in ${wgrib_parmlist} - do - case ${parm} in - "SurfaceU") - grep "UGRD:10 m " $TMPDIR/gfs.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/gfsgribfile.${symd}${dishh} ;; - "SurfaceV") - grep "VGRD:10 m " $TMPDIR/gfs.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/gfsgribfile.${symd}${dishh} ;; - *) - grep "${parm}" $TMPDIR/gfs.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/gfsgribfile.${symd}${dishh} ;; - esac +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! GFS File missing: ${gfsdir}/${gfsgfile}${fhour} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +EOF + continue + fi + + gfile="${gfsdir}/${gfsgfile}${fhour}" + ${WGRIB:?} -s "${gfile}" > "${TMPDIR}/gfs.ix" + + for parm in ${wgrib_parmlist}; do + case "${parm}" in + "SurfaceU") parm="UGRD:10 m" ;; + "SurfaceV") parm="VGRD:10 m" ;; + *) ;; + esac + # shellcheck disable=SC2312 + grep "${parm}" "${TMPDIR}/gfs.ix" | ${WGRIB:?} -s "${gfile}" -i -grib -append \ + -o "${vdir}/gfsgribfile.${symd}${dishh}" + done done - done - - ${GRBINDEX:?} ${vdir}/gfsgribfile.${symd}${dishh} ${vdir}/gfsixfile.${symd}${dishh} - gribfile=${vdir}/gfsgribfile.${symd}${dishh} - ixfile=${vdir}/gfsixfile.${symd}${dishh} + ${GRBINDEX:?} "${vdir}/gfsgribfile.${symd}${dishh}" "${vdir}/gfsixfile.${symd}${dishh}" + gribfile="${vdir}/gfsgribfile.${symd}${dishh}" + ixfile="${vdir}/gfsixfile.${symd}${dishh}" fi - # ------------------------------ # Process GDAS, if selected # ------------------------------ -if [ ${model} -eq 8 ]; then +if [[ "${model}" -eq 8 ]]; then - export nest_type="fixed" - export trkrebd=360.0 - export trkrwbd=0.0 - export trkrnbd=85.0 - export trkrsbd=-85.0 - rundescr="xxxx" - atcfdescr="xxxx" + export nest_type="fixed" + export trkrebd=360.0 + export trkrwbd=0.0 + export trkrnbd=85.0 + export trkrsbd=-85.0 + rundescr="xxxx" + atcfdescr="xxxx" - if [ -s ${vdir}/gdasgribfile.${symd}${dishh} ]; then - rm ${vdir}/gdasgribfile.${symd}${dishh} - fi + rm -f "${vdir}/gdasgribfile.${symd}${dishh}" - if [ ${gribver} -eq 1 ]; then + if [[ "${gribver}" -eq 1 ]]; then - # Use GRIB1 input data + # Use GRIB1 input data - for fhr in $( seq -6 $BKGFREQ 3 ); do - if [ $fhr -lt 0 ]; then - fpref=pgm$(expr $fhr \* -1) - elif [ $fhr -eq 0 ]; then - fpref=pges - elif [ $fhr -gt 0 ]; then - fpref=pgp$fhr - fi - gfile=$DATA/${fpref}prep + for ((fhr = -6; fhr <= 3; fhr += BKGFREQ)); do + if [[ "${fhr}" -lt 0 ]]; then + fpref="pgm$((-fhr))" + elif [[ "${fhr}" -eq 0 ]]; then + fpref=pges + elif [[ "${fhr}" -gt 0 ]]; then + fpref="pgp${fhr}" + fi + gfile="${DATA}/${fpref}prep" - if [ ! -s $gfile ]; then - set +x - echo " " - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " !!! gdas File missing: $gfile" - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " " - set_trace - continue - fi + if [[ ! -s "${gfile}" ]]; then + cat << EOF - ${WGRIB:?} -s $gfile >$TMPDIR/gdas.ix +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! gdas File missing: ${gfile} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - for parm in ${wgrib_parmlist} - do +EOF + continue + fi - case ${parm} in - "SurfaceU") - grep "UGRD:10 m " $TMPDIR/gdas.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/gdasgribfile.${symd}${dishh} ;; - "SurfaceV") - grep "VGRD:10 m " $TMPDIR/gdas.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/gdasgribfile.${symd}${dishh} ;; - *) - grep "${parm}" $TMPDIR/gdas.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/gdasgribfile.${symd}${dishh} ;; - esac + ${WGRIB:?} -s "${gfile}" > "${TMPDIR}/gdas.ix" - done + for parm in ${wgrib_parmlist}; do + case "${parm}" in + "SurfaceU") parm="UGRD:10 m" ;; + "SurfaceV") parm="VGRD:10 m" ;; + *) ;; + esac + # shellcheck disable=SC2312 + grep "${parm}" "${TMPDIR}/gdas.ix" | ${WGRIB:?} -s "${gfile}" -i -grib -append \ + -o "${vdir}/gdasgribfile.${symd}${dishh}" + done - done + done - else + else - # Use GRIB2 input data.... + # Use GRIB2 input data.... + for ((fhr = -6; fhr <= 3; fhr += BKGFREQ)); do + if [[ "${fhr}" -lt 0 ]]; then + fhour="0$((-fhr))" + fpref=pgm$((-fhr)) + elif [[ "${fhr}" -eq 0 ]]; then + fhour=00 + fpref=pges + elif [[ "${fhr}" -gt 0 ]]; then + fhour="0${fhr}" + fpref="pgp${fhr}" + fi + gfile="${DATA}/${fpref}prep" + + if [[ ! -s "${gfile}" ]]; then + cat << EOF + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! gdas File missing: ${gfile} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - for fhr in $( seq -6 $BKGFREQ 3 ); do - if [ $fhr -lt 0 ]; then - fhour=0$(expr $fhr \* -1) - fpref=pgm$(expr $fhr \* -1) - elif [ $fhr -eq 0 ]; then - fhour=00 - fpref=pges - elif [ $fhr -gt 0 ]; then - fhour=0$fhr - fpref=pgp$fhr - fi - gfile=$DATA/${fpref}prep +EOF + continue + fi - if [ ! -s $gfile ]; then - set +x - echo " " - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " !!! gdas File missing: $gfile" - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " " - set_trace - continue - fi - - ${WGRIB2:?} -s $gfile >$TMPDIR/gdas.ix - - for parm in ${wgrib_parmlist} - do - case ${parm} in - "SurfaceU") - grep "UGRD:10 m " $TMPDIR/gdas.ix | ${WGRIB2:?} -i $gfile -append -grib \ - ${vdir}/gdasgribfile.${symd}${dishh} ;; - "SurfaceV") - grep "VGRD:10 m " $TMPDIR/gdas.ix | ${WGRIB2:?} -i $gfile -append -grib \ - ${vdir}/gdasgribfile.${symd}${dishh} ;; - *) - grep "${parm}" $TMPDIR/gdas.ix | ${WGRIB2:?} -i $gfile -append -grib \ - ${vdir}/gdasgribfile.${symd}${dishh} ;; - esac - done + ${WGRIB2:?} -s "${gfile}" > "${TMPDIR}/gdas.ix" - done + for parm in ${wgrib_parmlist}; do + case "${parm}" in + "SurfaceU") parm="UGRD:10 m" ;; + "SurfaceV") parm="VGRD:10 m" ;; + *) ;; + esac + # shellcheck disable=SC2312 + grep "${parm}" "${TMPDIR}/gdas.ix" | ${WGRIB2:?} -i "${gfile}" -append -grib \ + "${vdir}/gdasgribfile.${symd}${dishh}" + done - fi + done - if [ ${gribver} -eq 1 ]; then - ${GRBINDEX:?} ${vdir}/gdasgribfile.${symd}${dishh} ${vdir}/gdasixfile.${symd}${dishh} - else - ${GRB2INDEX:?} ${vdir}/gdasgribfile.${symd}${dishh} ${vdir}/gdasixfile.${symd}${dishh} - fi + fi - gribfile=${vdir}/gdasgribfile.${symd}${dishh} - ixfile=${vdir}/gdasixfile.${symd}${dishh} + if [[ "${gribver}" -eq 1 ]]; then + ${GRBINDEX:?} "${vdir}/gdasgribfile.${symd}${dishh}" "${vdir}/gdasixfile.${symd}${dishh}" + else + ${GRB2INDEX:?} "${vdir}/gdasgribfile.${symd}${dishh}" "${vdir}/gdasixfile.${symd}${dishh}" + fi + + gribfile="${vdir}/gdasgribfile.${symd}${dishh}" + ixfile="${vdir}/gdasixfile.${symd}${dishh}" fi + # ------------------------------ # Process MRF, if selected # ------------------------------ -if [ ${model} -eq 2 ]; then +if [[ "${model}" -eq 2 ]]; then - if [ -s ${vdir}/mrfgribfile.${symd}${dishh} ]; then - rm ${vdir}/mrfgribfile.${symd}${dishh} - fi + rm -f "${vdir}/mrfgribfile.${symd}${dishh}" - for fhour in ${fcsthrsmrf} - do + for fhour in ${fcsthrsmrf}; do + if [[ ! -s "${mrfdir}/${mrfgfile}${fhour}" ]]; then + cat << EOF - if [ ! -s ${mrfdir}/${mrfgfile}${fhour} ]; then - set +x - echo " " - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " !!! MRF File missing: ${mrfdir}/${mrfgfile}${fhour}" - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " " - set_trace - continue - fi +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! MRF File missing: ${mrfdir}/${mrfgfile}${fhour} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - gfile=${mrfdir}/${mrfgfile}${fhour} - ${WGRIB:?} -s $gfile >$TMPDIR/mrf.ix - - for parm in ${wgrib_parmlist} - do - - case ${parm} in - "SurfaceU") - grep "UGRD:10 m " $TMPDIR/mrf.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/mrfgribfile.${symd}${dishh} ;; - "SurfaceV") - grep "VGRD:10 m " $TMPDIR/mrf.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/mrfgribfile.${symd}${dishh} ;; - *) - grep "${parm}" $TMPDIR/mrf.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/mrfgribfile.${symd}${dishh} ;; - esac +EOF + continue + fi + + gfile="${mrfdir}/${mrfgfile}${fhour}" + ${WGRIB:?} -s "${gfile}" > "${TMPDIR}/mrf.ix" + + for parm in ${wgrib_parmlist}; do + case "${parm}" in + "SurfaceU") parm="UGRD:10 m" ;; + "SurfaceV") parm="VGRD:10 m" ;; + *) ;; + esac + # shellcheck disable=SC2312 + grep "${parm}" "${TMPDIR}/mrf.ix" | ${WGRIB:?} -s "${gfile}" -i -grib -append \ + -o "${vdir}/mrfgribfile.${symd}${dishh}" + done done - done - - ${GRBINDEX:?} ${vdir}/mrfgribfile.${symd}${dishh} ${vdir}/mrfixfile.${symd}${dishh} - gribfile=${vdir}/mrfgribfile.${symd}${dishh} - ixfile=${vdir}/mrfixfile.${symd}${dishh} + ${GRBINDEX:?} "${vdir}/mrfgribfile.${symd}${dishh}" "${vdir}/mrfixfile.${symd}${dishh}" + gribfile="${vdir}/mrfgribfile.${symd}${dishh}" + ixfile="${vdir}/mrfixfile.${symd}${dishh}" fi - # ------------------------------ # Process UKMET, if selected # ------------------------------ -if [ ${model} -eq 3 ]; then +if [[ "${model}" -eq 3 ]]; then - if [ -s ${vdir}/ukmetgribfile.${symd}${dishh} ]; then - rm ${vdir}/ukmetgribfile.${symd}${dishh} - fi + rm -f "${vdir}/ukmetgribfile.${symd}${dishh}" - wgrib_parmlist=' HGT:850 HGT:700 UGRD:850 UGRD:700 UGRD:500 VGRD:850 VGRD:700 VGRD:500 UGRD:sfc VGRD:sfc ABSV:850 ABSV:700 PRMSL:MSL ' + wgrib_parmlist='HGT:850 HGT:700 UGRD:850 UGRD:700 UGRD:500 VGRD:850 VGRD:700 VGRD:500 UGRD:sfc VGRD:sfc ABSV:850 ABSV:700 PRMSL:MSL ' - for fhour in ${fcsthrsukmet} - do + for fhour in ${fcsthrsukmet}; do + if [[ ! -s "${ukmetdir}/${ukmetgfile}${fhour}" ]]; then + cat << EOF - if [ ! -s ${ukmetdir}/${ukmetgfile}${fhour} ]; then - set +x - echo " " - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " !!! UKMET File missing: ${ukmetdir}/${ukmetgfile}${fhour}" - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " " - set_trace - continue - fi +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! UKMET File missing: ${ukmetdir}/${ukmetgfile}${fhour} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - gfile=${ukmetdir}/${ukmetgfile}${fhour} - ${WGRIB:?} -s $gfile >$TMPDIR/ukmet.ix +EOF + continue + fi - for parm in ${wgrib_parmlist} - do - grep "${parm}" $TMPDIR/ukmet.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/ukmetgribfile.${symd}${dishh} - done + gfile="${ukmetdir}/${ukmetgfile}${fhour}" + ${WGRIB:?} -s "${gfile}" > "${TMPDIR}/ukmet.ix" - done + for parm in ${wgrib_parmlist}; do + # shellcheck disable=SC2312 + grep "${parm}" "${TMPDIR}/ukmet.ix" | ${WGRIB:?} -s "${gfile}" -i -grib -append \ + -o "${vdir}/ukmetgribfile.${symd}${dishh}" + done - ${GRBINDEX:?} ${vdir}/ukmetgribfile.${symd}${dishh} ${vdir}/ukmetixfile.${symd}${dishh} - gribfile=${vdir}/ukmetgribfile.${symd}${dishh} - ixfile=${vdir}/ukmetixfile.${symd}${dishh} + done -fi + ${GRBINDEX:?} "${vdir}/ukmetgribfile.${symd}${dishh}" "${vdir}/ukmetixfile.${symd}${dishh}" + gribfile="${vdir}/ukmetgribfile.${symd}${dishh}" + ixfile="${vdir}/ukmetixfile.${symd}${dishh}" +fi # ------------------------------ # Process NAVGEM, if selected # ------------------------------ -if [ ${model} -eq 7 ]; then - - if [ -s ${vdir}/ngpsgribfile.${symd}${dishh} ]; then - rm ${vdir}/ngpsgribfile.${symd}${dishh} - fi - - if [ ! -s ${ngpsdir}/${ngpsgfile} ]; then - set +x - echo " " - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " !!! NAVGEM File missing: ${ngpsdir}/${ngpsgfile}" - echo " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " " - echo " !!! Due to missing NAVGEM file, execution is ending...." - echo " " - set_trace - exit 8 - fi - - gfile=${ngpsdir}/${ngpsgfile} - ${WGRIB:?} -s $gfile >$TMPDIR/ngps.ix - - for fhour in ${fcsthrsngps} - do - - if [ $fhour = '00' ]; then - vtstring=":anl:" - else - vtstring="${fhour}hr" +if [[ "${model}" -eq 7 ]]; then + + rm -f "${vdir}/ngpsgribfile.${symd}${dishh}" + + if [[ ! -s "${ngpsdir}/${ngpsgfile}" ]]; then + msg=$( + cat << EOF + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! NAVGEM File missing: ${ngpsdir}/${ngpsgfile} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +!!! Due to missing NAVGEM file, execution is ending.... + +EOF + ) + err=8 + err_exit "${msg}" fi - for parm in ${wgrib_parmlist} - do - case ${parm} in - "SurfaceU") - grep "UGRD:19 m " $TMPDIR/ngps.ix | grep ${vtstring} | \ - ${WGRIB:?} -s $gfile -i -grib -append -o ${vdir}/ngpsgribfile.${symd}${dishh} ;; - "SurfaceV") - grep "VGRD:19 m " $TMPDIR/ngps.ix | grep ${vtstring} | \ - ${WGRIB:?} -s $gfile -i -grib -append -o ${vdir}/ngpsgribfile.${symd}${dishh} ;; - *) - grep "${parm}" $TMPDIR/ngps.ix | grep ${vtstring} | \ - ${WGRIB:?} -s $gfile -i -grib -append -o ${vdir}/ngpsgribfile.${symd}${dishh} ;; - esac - done + gfile="${ngpsdir}/${ngpsgfile}" + ${WGRIB:?} -s "${gfile}" > "${TMPDIR}/ngps.ix" + + for fhour in ${fcsthrsngps}; do + if [[ "${fhour}" == '00' ]]; then + vtstring=":anl:" + else + vtstring="${fhour}hr" + fi + + for parm in ${wgrib_parmlist}; do + case "${parm}" in + "SurfaceU") parm="UGRD:19 m" ;; + "SurfaceV") parm="VGRD:19 m" ;; + *) ;; + esac + # shellcheck disable=SC2312 + grep "${parm}" "${TMPDIR}/ngps.ix" | grep "${vtstring}" | + ${WGRIB:?} -s "${gfile}" -i -grib -append -o "${vdir}/ngpsgribfile.${symd}${dishh}" + done - done + done - ${GRBINDEX:?} ${vdir}/ngpsgribfile.${symd}${dishh} ${vdir}/ngpsixfile.${symd}${dishh} - gribfile=${vdir}/ngpsgribfile.${symd}${dishh} - ixfile=${vdir}/ngpsixfile.${symd}${dishh} + ${GRBINDEX:?} "${vdir}/ngpsgribfile.${symd}${dishh}" "${vdir}/ngpsixfile.${symd}${dishh}" + gribfile="${vdir}/ngpsgribfile.${symd}${dishh}" + ixfile="${vdir}/ngpsixfile.${symd}${dishh}" fi - # --------------------------------------------- # Process User-specified Model, if selected # --------------------------------------------- -if [ ${model} -eq 9 ]; then +if [[ "${model}" -eq 9 ]]; then -# We need to first check whether or not the data in the file are stored -# on a lat/lon grid or not. We do this by scanning the analysis file -# with Wesley's grib utility, and checking the value of the "Data -# Representation Type", which is stored in byte #6 in the GDS of each -# grib file. A value of 0 indicates an equidistant lat/lon grid. + # We need to first check whether or not the data in the file are stored + # on a lat/lon grid or not. We do this by scanning the analysis file + # with Wesley's grib utility, and checking the value of the "Data + # Representation Type", which is stored in byte #6 in the GDS of each + # grib file. A value of 0 indicates an equidistant lat/lon grid. - if [ -s ${vdir}/otherlatlon.pgrb.${symdh} ]; then - rm ${vdir}/otherlatlon.pgrb.${symdh} - fi + rm -f "${vdir}/otherlatlon.pgrb.${symdh}" - gridtyp=$(${WGRIB:?} -GDS10 ${otherdir}/${fnamebeg}00${fnameend} | \ - awk -FGDS10= '{print $2}' | awk '{print $6}' | sed -n 1p) + # shellcheck disable=SC2312 + gridtyp=$(${WGRIB:?} -GDS10 "${otherdir}/${fnamebeg}00${fnameend}" | + awk -FGDS10= '{print $2}' | awk '{print $6}' | sed -n 1p) - if [ ${gridtyp} -eq 0 ]; then + if [[ "${gridtyp}" -eq 0 ]]; then -# The data are already on a lat/lon grid, we do not need to -# interpolate the data, just pull out the records that we need -# using wgrib. + # The data are already on a lat/lon grid, we do not need to + # interpolate the data, just pull out the records that we need + # using wgrib. - for fhour in ${fcsthrsother} - do + for fhour in ${fcsthrsother}; do + if [[ ! -s "${otherdir}/${fnamebeg}${fhour}${fnameend}" ]]; then + cat << EOF - if [ ! -s ${otherdir}/${fnamebeg}${fhour}${fnameend} ]; then - set +x - echo " " - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo "!!! Forecast File missing: ${otherdir}/${fnamebeg}00${fnameend}" - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " " - set_trace - continue - fi +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! Forecast File missing: ${otherdir}/${fnamebeg}00${fnameend} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - gfile=${otherdir}/${fnamebeg}${fhour}${fnameend} - ${WGRIB:?} -s $gfile >$TMPDIR/other.ix +EOF + continue + fi - for parm in ${wgrib_parmlist} - do + gfile="${otherdir}/${fnamebeg}${fhour}${fnameend}" + ${WGRIB:?} -s "${gfile}" > "${TMPDIR}/other.ix" - case ${parm} in - "SurfaceU") - grep "UGRD:10 m " $TMPDIR/other.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/otherlatlon.pgrb.${symdh} ;; - "SurfaceV") - grep "VGRD:10 m " $TMPDIR/other.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/otherlatlon.pgrb.${symdh} ;; - *) - grep "${parm}" $TMPDIR/other.ix | ${WGRIB:?} -s $gfile -i -grib -append \ - -o ${vdir}/otherlatlon.pgrb.${symdh} ;; - esac + for parm in ${wgrib_parmlist}; do + case "${parm}" in + "SurfaceU") parm="UGRD:10 m" ;; + "SurfaceV") parm="VGRD:10 m" ;; + *) ;; + esac + # shellcheck disable=SC2312 + grep "${parm}" "${TMPDIR}/other.ix" | ${WGRIB:?} -s "${gfile}" -i -grib -append \ + -o "${vdir}/otherlatlon.pgrb.${symdh}" + done - done + done - done + else - else + # The data are on a grid that is something other than a lat/lon grid. + # Use Mark Iredell's interpolator to interpolate the data to a lat/lon + # grid and pull out the records that we need. -# The data are on a grid that is something other than a lat/lon grid. -# Use Mark Iredell's interpolator to interpolate the data to a lat/lon -# grid and pull out the records that we need. + othergrid='255 0 360 181 90000 0000 128 -90000 -1000 1000 1000 64' - othergrid='255 0 360 181 90000 0000 128 -90000 -1000 1000 1000 64' + for fhour in ${fcsthrsother}; do - for fhour in ${fcsthrsother} - do + if [[ ! -s "${otherdir}/${fnamebeg}${fhour}${fnameend}" ]]; then + cat << EOF - if [ ! -s ${otherdir}/${fnamebeg}${fhour}${fnameend} ]; then - set +x - echo " " - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo "!!! Forecast File missing: ${otherdir}/${fnamebeg}00${fnameend}" - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo " " - set +x - continue - fi - - if [ -s $TMPDIR/tmpixfile ]; then rm $TMPDIR/tmpixfile; fi - ${GRBINDEX:?} ${otherdir}/${fnamebeg}${fhour}${fnameend} $TMPDIR/tmpixfile - x1=$TMPDIR/tmpixfile - - g1=${otherdir}/${fnamebeg}${fhour}${fnameend} - - ${COPYGB:?} -g"$othergrid" -k'4*-1 33 100 850' $g1 $x1 $TMPDIR/otherllu850.grb.f${fhour}; rcc1=$? - ${COPYGB:?} -g"$othergrid" -k'4*-1 33 100 700' $g1 $x1 $TMPDIR/otherllu700.grb.f${fhour}; rcc2=$? - ${COPYGB:?} -g"$othergrid" -k'4*-1 33 100 500' $g1 $x1 $TMPDIR/otherllu500.grb.f${fhour}; rcc3=$? - ${COPYGB:?} -g"$othergrid" -k'4*-1 33 105 10' $g1 $x1 $TMPDIR/otherllu10m.grb.f${fhour}; rcc4=$? - ${COPYGB:?} -g"$othergrid" -k'4*-1 41 100 850' $g1 $x1 $TMPDIR/otherllav850.grb.f${fhour}; rcc5=$? - ${COPYGB:?} -g"$othergrid" -k'4*-1 41 100 700' $g1 $x1 $TMPDIR/otherllav700.grb.f${fhour}; rcc6=$? - ${COPYGB:?} -g"$othergrid" -k'4*-1 7 100 850' $g1 $x1 $TMPDIR/otherllz850.grb.f${fhour}; rcc7=$? - ${COPYGB:?} -g"$othergrid" -k'4*-1 7 100 700' $g1 $x1 $TMPDIR/otherllz700.grb.f${fhour}; rcc8=$? - ${COPYGB:?} -g"$othergrid" -k'4*-1 2 102 0' $g1 $x1 $TMPDIR/otherllmslp.grb.f${fhour}; rcc9=$? - - if [ $rcc1 -eq 134 -o $rcc2 -eq 134 -o $rcc3 -eq 134 -o $rcc4 -eq 134 -o $rcc5 -eq 134 -o \ - $rcc6 -eq 134 -o $rcc7 -eq 134 -o $rcc8 -eq 134 -o $rcc9 -eq 134 ]; then - set +x - echo " " - echo "!!! ERROR using $COPYGB to interpolate data. We will stop execution because" - echo "!!! some variables may have been copied okay, while some obviously have not, " - echo "!!! and that could lead to unreliable results from the tracker. Check to make" - echo "!!! sure you've allocated enough memory for this job (error 134 using $COPYGB is " - echo "!!! typically due to using more memory than you've allocated). Exiting....." - echo " " - set_trace - exit 8 - fi +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!! Forecast File missing: ${otherdir}/${fnamebeg}00${fnameend} +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - cat $TMPDIR/otherllu850.grb.f${fhour} $TMPDIR/otherllu700.grb.f${fhour} \ - $TMPDIR/otherllu500.grb.f${fhour} $TMPDIR/otherllz850.grb.f${fhour} \ - $TMPDIR/otherllz700.grb.f${fhour} $TMPDIR/otherllmslp.grb.f${fhour} \ - $TMPDIR/otherllav850.grb.f${fhour} $TMPDIR/otherllav700.grb.f${fhour} \ - $TMPDIR/otherllu10m.grb.f${fhour} \ - >>${vdir}/otherlatlon.pgrb.${symdh} +EOF + continue + fi + + rm -f "${TMPDIR}/tmpixfile" + ${GRBINDEX:?} "${otherdir}/${fnamebeg}${fhour}${fnameend}" "${TMPDIR}/tmpixfile" + x1="${TMPDIR}/tmpixfile" + + g1="${otherdir}/${fnamebeg}${fhour}${fnameend}" + + ${COPYGB:?} -g"${othergrid}" -k'4*-1 33 100 850' "${g1}" "${x1}" "${TMPDIR}/otherllu850.grb.f${fhour}" + rcc1=$? + ${COPYGB:?} -g"${othergrid}" -k'4*-1 33 100 700' "${g1}" "${x1}" "${TMPDIR}/otherllu700.grb.f${fhour}" + rcc2=$? + ${COPYGB:?} -g"${othergrid}" -k'4*-1 33 100 500' "${g1}" "${x1}" "${TMPDIR}/otherllu500.grb.f${fhour}" + rcc3=$? + ${COPYGB:?} -g"${othergrid}" -k'4*-1 33 105 10' "${g1}" "${x1}" "${TMPDIR}/otherllu10m.grb.f${fhour}" + rcc4=$? + ${COPYGB:?} -g"${othergrid}" -k'4*-1 41 100 850' "${g1}" "${x1}" "${TMPDIR}/otherllav850.grb.f${fhour}" + rcc5=$? + ${COPYGB:?} -g"${othergrid}" -k'4*-1 41 100 700' "${g1}" "${x1}" "${TMPDIR}/otherllav700.grb.f${fhour}" + rcc6=$? + ${COPYGB:?} -g"${othergrid}" -k'4*-1 7 100 850' "${g1}" "${x1}" "${TMPDIR}/otherllz850.grb.f${fhour}" + rcc7=$? + ${COPYGB:?} -g"${othergrid}" -k'4*-1 7 100 700' "${g1}" "${x1}" "${TMPDIR}/otherllz700.grb.f${fhour}" + rcc8=$? + ${COPYGB:?} -g"${othergrid}" -k'4*-1 2 102 0' "${g1}" "${x1}" "${TMPDIR}/otherllmslp.grb.f${fhour}" + rcc9=$? + + if [[ "${rcc1}" -eq 134 || "${rcc2}" -eq 134 || "${rcc3}" -eq 134 || "${rcc4}" -eq 134 || "${rcc5}" -eq 134 || + "${rcc6}" -eq 134 || "${rcc7}" -eq 134 || "${rcc8}" -eq 134 || "${rcc9}" -eq 134 ]]; then + msg=$( + cat << EOF + +!!! FATAL ERROR using ${COPYGB} to interpolate data. We will stop execution because +!!! some variables may have been copied okay, while some obviously have not, +!!! and that could lead to unreliable results from the tracker. Check to make +!!! sure you've allocated enough memory for this job (error 134 using ${COPYGB} is +!!! typically due to using more memory than you've allocated). Exiting..... - done +EOF + ) + err=8 + err_exit "${msg}" + fi - fi + cat "${TMPDIR}/otherllu850.grb.f${fhour}" "${TMPDIR}/otherllu700.grb.f${fhour}" \ + "${TMPDIR}/otherllu500.grb.f${fhour}" "${TMPDIR}/otherllz850.grb.f${fhour}" \ + "${TMPDIR}/otherllz700.grb.f${fhour}" "${TMPDIR}/otherllmslp.grb.f${fhour}" \ + "${TMPDIR}/otherllav850.grb.f${fhour}" "${TMPDIR}/otherllav700.grb.f${fhour}" \ + "${TMPDIR}/otherllu10m.grb.f${fhour}" \ + >> "${vdir}/otherlatlon.pgrb.${symdh}" - ${GRBINDEX:?} ${vdir}/otherlatlon.pgrb.${symdh} ${vdir}/otherlatlon.pgrb.ix.${symdh} - gribfile=${vdir}/otherlatlon.pgrb.${symdh} - ixfile=${vdir}/otherlatlon.pgrb.ix.${symdh} + done -fi + fi + + ${GRBINDEX:?} "${vdir}/otherlatlon.pgrb.${symdh}" "${vdir}/otherlatlon.pgrb.ix.${symdh}" + gribfile="${vdir}/otherlatlon.pgrb.${symdh}" + ixfile="${vdir}/otherlatlon.pgrb.ix.${symdh}" +fi #-------------------------------------------# # Now qsub the jobs to run the tracker # #-------------------------------------------# -ist=1 -while [ $ist -le 15 ] -do - if [ ${stormflag[${ist}]} -ne 1 ] - then - set +x; echo "Storm number $ist NOT selected for processing"; set_trace - else - set +x; echo "Storm number $ist IS selected for processing...."; set_trace - fi - let ist=ist+1 +for ((ist = 1; ist <= 15; ist++)); do + if [[ "${stormflag[ist]}" -ne 1 ]]; then + echo "Storm number ${ist} NOT selected for processing" + else + echo "Storm number ${ist} IS selected for processing...." + fi done # Load the forecast hours for this particular model into an array # that will be passed into the executable via a namelist.... -ifh=1 -while [ $ifh -le ${maxtime} ] -do - fh[${ifh}]=$( echo ${fcsthrs} | awk '{print $n}' n=$ifh) - let ifh=ifh+1 +for ((ifh = 1; ifh <= mattime; ifh++)); do + fh[ifh]=$(echo "${fcsthrs}" | awk '{print $n}' n="${ifh}") done -namelist=${vdir}/gettrk.input.${cmodel}.${symdh} -ATCFNAME=$( echo "${atcfname}" | tr '[a-z]' '[A-Z]') +namelist="${vdir}/gettrk.input.${cmodel}.${symdh}" + +export atcfymdh="${scc}${syy}${smm}${sdd}${shh}" -export atcfymdh=${scc}${syy}${smm}${sdd}${shh} contour_interval=100.0 write_vit=n want_oci=.TRUE. -echo "&datein inp%bcc=${scc},inp%byy=${syy},inp%bmm=${smm}," >${namelist} -echo " inp%bdd=${sdd},inp%bhh=${shh},inp%model=${model}," >>${namelist} -echo " inp%modtyp='${modtyp}'," >>${namelist} -echo " inp%lt_units='${lead_time_units}'," >>${namelist} -echo " inp%file_seq='${file_sequence}'," >>${namelist} -echo " inp%nesttyp='${nest_type}'/" >>${namelist} -echo "&atcfinfo atcfnum=${atcfnum},atcfname='${ATCFNAME}'," >>${namelist} -echo " atcfymdh=${atcfymdh},atcffreq=${atcffreq}/" >>${namelist} -echo "&trackerinfo trkrinfo%westbd=${trkrwbd}," >>${namelist} -echo " trkrinfo%eastbd=${trkrebd}," >>${namelist} -echo " trkrinfo%northbd=${trkrnbd}," >>${namelist} -echo " trkrinfo%southbd=${trkrsbd}," >>${namelist} -echo " trkrinfo%type='${trkrtype}'," >>${namelist} -echo " trkrinfo%mslpthresh=${MSLPTHRESH}," >>${namelist} -echo " trkrinfo%v850thresh=${V850THRESH}," >>${namelist} -echo " trkrinfo%gridtype='${modtyp}'," >>${namelist} -echo " trkrinfo%contint=${contour_interval}," >>${namelist} -echo " trkrinfo%want_oci=${want_oci}," >>${namelist} -echo " trkrinfo%out_vit='${write_vit}'," >>${namelist} -echo " trkrinfo%gribver=${gribver}," >>${namelist} -echo " trkrinfo%g2_jpdtn=${g2_jpdtn}/" >>${namelist} -echo "&phaseinfo phaseflag='${PHASEFLAG}'," >>${namelist} -echo " phasescheme='${PHASE_SCHEME}'," >>${namelist} -echo " wcore_depth=${WCORE_DEPTH}/" >>${namelist} -echo "&structinfo structflag='${STRUCTFLAG}'," >>${namelist} -echo " ikeflag='${IKEFLAG}'/" >>${namelist} -echo "&fnameinfo gmodname='${atcfname}'," >>${namelist} -echo " rundescr='${rundescr}'," >>${namelist} -echo " atcfdescr='${atcfdescr}'/" >>${namelist} -echo "&verbose verb=3/" >>${namelist} -echo "&waitinfo use_waitfor='n'," >>${namelist} -echo " wait_min_age=10," >>${namelist} -echo " wait_min_size=100," >>${namelist} -echo " wait_max_wait=1800," >>${namelist} -echo " wait_sleeptime=5," >>${namelist} -echo " per_fcst_command=''/" >>${namelist} - -pgm=$(basename $GETTX) -if [ -s $DATA/prep_step ]; then - . $DATA/prep_step -else - [ -f errfile ] && rm errfile - export XLFUNITS=0 - unset $(env | grep XLFUNIT | awk -F= '{print $1}') - - set +u - if [ -z "$XLFRTEOPTS" ]; then - export XLFRTEOPTS="unit_vars=yes" - else - export XLFRTEOPTS="${XLFRTEOPTS}:unit_vars=yes" - fi - set -u +cat << EOF > "${namelist}" +&datein inp%bcc=${scc},inp%byy=${syy},inp%bmm=${smm}, + inp%bdd=${sdd},inp%bhh=${shh},inp%model=${model}, + inp%modtyp='${modtyp}', + inp%lt_units='${lead_time_units}', + inp%file_seq='${file_sequence}', + inp%nesttyp='${nest_type}'/ +&atcfinfo atcfnum=${atcfnum},atcfname='${atcfname^^}', + atcfymdh=${atcfymdh},atcffreq=${atcffreq}/ +&trackerinfo trkrinfo%westbd=${trkrwbd}, + trkrinfo%eastbd=${trkrebd}, + trkrinfo%northbd=${trkrnbd}, + trkrinfo%southbd=${trkrsbd}, + trkrinfo%type='${trkrtype}', + trkrinfo%mslpthresh=${MSLPTHRESH}, + trkrinfo%v850thresh=${V850THRESH}, + trkrinfo%gridtype='${modtyp}', + trkrinfo%contint=${contour_interval}, + trkrinfo%want_oci=${want_oci}, + trkrinfo%out_vit='${write_vit}', + trkrinfo%gribver=${gribver}, + trkrinfo%g2_jpdtn=${g2_jpdtn}/ +&phaseinfo phaseflag='${PHASEFLAG}', + phasescheme='${PHASE_SCHEME}', + wcore_depth=${WCORE_DEPTH}/ +&structinfo structflag='${STRUCTFLAG}', + ikeflag='${IKEFLAG}'/ +&fnameinfo gmodname='${atcfname}', + rundescr='${rundescr}', + atcfdescr='${atcfdescr}'/ +&verbose verb=3/ +&waitinfo use_waitfor='n', + wait_min_age=10, + wait_min_size=100, + wait_max_wait=1800, + wait_sleeptime=5, + per_fcst_command=''/ +EOF +pgm=$(basename "${GETTX}") +if [[ -s "${DATA}/prep_step" ]]; then + source "${DATA}/prep_step" +else + rm -f errfile + export XLFUNITS=0 + # shellcheck disable=SC2046,SC2312 + unset $(env | grep XLFUNIT | awk -F= '{print $1}') + export XLFRTEOPTS="${XLFRTEOPTS:+${XLFRTEOPTS}:}unit_vars=yes" fi -touch ${vdir}/tmp.gfs.atcfunix.${symdh} +touch "${vdir}/tmp.gfs.atcfunix.${symdh}" #---------------------------------- -if [ -s fort.* ]; then - rm fort.* +rm -f fort.* + +${NLN} "${gribfile}" fort.11 +${NLN} "${vdir}/tmp.gfs.atcfunix.${symdh}" fort.14 +${NLN} "${vdir}/vitals.upd.${cmodel}.${symd}${dishh}" fort.12 +${NLN} "${ixfile}" fort.31 +${NLN} "${vdir}/trak.${cmodel}.all.${symdh}" fort.61 +${NLN} "${vdir}/trak.${cmodel}.atcf.${symdh}" fort.62 +${NLN} "${vdir}/trak.${cmodel}.radii.${symdh}" fort.63 +${NLN} "${vdir}/trak.${cmodel}.atcfunix.${symdh}" fort.64 + +if [[ "${BKGFREQ}" -eq 1 ]]; then + ${NLN} "${FIXgfs}/am/${cmodel}.tracker_leadtimes_hrly" "fort.15" +elif [[ "${BKGFREQ}" -eq 3 ]]; then + ${NLN} "${FIXgfs}/am/${cmodel}.tracker_leadtimes" "fort.15" fi -${NLN} ${gribfile} fort.11 -${NLN} ${vdir}/tmp.gfs.atcfunix.${symdh} fort.14 -${NLN} ${vdir}/vitals.upd.${cmodel}.${symd}${dishh} fort.12 -${NLN} ${ixfile} fort.31 -${NLN} ${vdir}/trak.${cmodel}.all.${symdh} fort.61 -${NLN} ${vdir}/trak.${cmodel}.atcf.${symdh} fort.62 -${NLN} ${vdir}/trak.${cmodel}.radii.${symdh} fort.63 -${NLN} ${vdir}/trak.${cmodel}.atcfunix.${symdh} fort.64 - -if [ $BKGFREQ -eq 1 ]; then - ${NLN} ${FIXgfs}/am/${cmodel}.tracker_leadtimes_hrly fort.15 -elif [ $BKGFREQ -eq 3 ]; then - ${NLN} ${FIXgfs}/am/${cmodel}.tracker_leadtimes fort.15 -fi - -##$XLF_LINKSSH -#if [ -z $XLF_LINKSSH ] ; then -###if [ -s $XLF_LINKSSH ; then $XLF_LINKSSH ; fi -#fi - -$TIMEIT ${APRNGETTX} $GETTX <${namelist} > outout 2> errfile +${TIMEIT} "${APRNGETTX}" "${GETTX}" < "${namelist}" > outout 2> errfile err=$? -###cat errfile cat errfile >> outout -cat outout > ${DATA}/model_track.out -set +u -[ -n "../$pgmout" ] && cat outout >> ../$pgmout -set -u -rm outout -set +x -echo -echo 'The foreground exit status for GETTRK is ' $err -echo -set_trace - -if [[ ${err} -gt 0 ]]; then - exit 9 +cat outout > "${DATA}/model_track.out" +if [[ -n "${pgmout}" ]]; then + cat outout >> "../${pgmout}" fi +rm outout +cat << EOF + +"The foreground exit status for GETTRK is ${err}" + +EOF -if [ -s fort.* ]; then - rm fort.* +if [[ "${err}" -gt 0 ]]; then + err=9 + err_exit fi -cpreq "${vdir}/trak.${cmodel}.all.${symdh}" "${DATA}/model_track.all" +rm -f fort.* +cpreq "${vdir}/trak.${cmodel}.all.${symdh}" "${DATA}/model_track.all" exit 0 diff --git a/ush/wave_domain_grid.sh b/ush/wave_domain_grid.sh index 753e3045d8f..7ca92790bea 100644 --- a/ush/wave_domain_grid.sh +++ b/ush/wave_domain_grid.sh @@ -10,34 +10,135 @@ ####################### process_grdID() { - grdID=$1 - case ${grdID} in - glo_10m) GRDREGION='global' ; GRDRES=0p16 ; GRIDNR=255 ; MODNR=11 ;; - glo_15mxt) GRDREGION='global' ; GRDRES=0p25 ; GRIDNR=255 ; MODNR=11 ;; - glo_30mxt) GRDREGION='global' ; GRDRES=0p50 ; GRIDNR=255 ; MODNR=11 ;; - glo_30m) GRDREGION='global' ; GRDRES=0p50 ; GRIDNR=255 ; MODNR=11 ;; - glo_025) GRDREGION='global' ; GRDRES=0p25 ; GRIDNR=255 ; MODNR=11 ;; - glo_100) GRDREGION='global' ; GRDRES=1p00 ; GRIDNR=255 ; MODNR=11 ;; - glo_200) GRDREGION='global' ; GRDRES=2p00 ; GRIDNR=255 ; MODNR=11 ;; - glo_500) GRDREGION='global' ; GRDRES=5p00 ; GRIDNR=255 ; MODNR=11 ;; - at_10m) GRDREGION='atlocn' ; GRDRES=0p16 ; GRIDNR=255 ; MODNR=11 ;; - ep_10m) GRDREGION='epacif' ; GRDRES=0p16 ; GRIDNR=255 ; MODNR=11 ;; - wc_10m) GRDREGION='wcoast' ; GRDRES=0p16 ; GRIDNR=255 ; MODNR=11 ;; - ak_10m) GRDREGION='alaska' ; GRDRES=0p16 ; GRIDNR=255 ; MODNR=11 ;; - aoc_9km) GRDREGION='arctic' ; GRDRES=9km ; GRIDNR=255 ; MODNR=11 ;; - ant_9km) GRDREGION='antarc' ; GRDRES=9km ; GRIDNR=255 ; MODNR=11 ;; - gnh_10m) GRDREGION='global' ; GRDRES=0p16 ; GRIDNR=255 ; MODNR=11 ;; - gsh_15m) GRDREGION='gsouth' ; GRDRES=0p25 ; GRIDNR=255 ; MODNR=11 ;; - ao_20m) GRDREGION='arctic' ; GRDRES=0p33 ; GRIDNR=255 ; MODNR=11 ;; - so_20m) GRDREGION='antarc' ; GRDRES=0p33 ; GRIDNR=255 ; MODNR=11 ;; - reg025) GRDREGION='global' ; GRDRES=0p25 ; GRIDNR=255 ; MODNR=11 ;; - gwes_30m) GRDREGION='global' ; GRDRES=0p50 ; GRIDNR=255 ; MODNR=10 ;; - *) - echo "FATAL ERROR: No grid specific wave config values exist for ${grdID}. Aborting." - exit 1 ;; - esac - grdNAME="${GRDREGION}.${GRDRES}" - echo "grdNAME=${grdNAME}" - echo "GRIDNR=${GRIDNR}" - echo "MODNR=${MODNR}" + grdID=$1 + case ${grdID} in + glo_10m) + GRDREGION='global' + GRDRES=0p16 + GRIDNR=255 + MODNR=11 + ;; + glo_15mxt) + GRDREGION='global' + GRDRES=0p25 + GRIDNR=255 + MODNR=11 + ;; + glo_30mxt) + GRDREGION='global' + GRDRES=0p50 + GRIDNR=255 + MODNR=11 + ;; + glo_30m) + GRDREGION='global' + GRDRES=0p50 + GRIDNR=255 + MODNR=11 + ;; + glo_025) + GRDREGION='global' + GRDRES=0p25 + GRIDNR=255 + MODNR=11 + ;; + glo_100) + GRDREGION='global' + GRDRES=1p00 + GRIDNR=255 + MODNR=11 + ;; + glo_200) + GRDREGION='global' + GRDRES=2p00 + GRIDNR=255 + MODNR=11 + ;; + glo_500) + GRDREGION='global' + GRDRES=5p00 + GRIDNR=255 + MODNR=11 + ;; + at_10m) + GRDREGION='atlocn' + GRDRES=0p16 + GRIDNR=255 + MODNR=11 + ;; + ep_10m) + GRDREGION='epacif' + GRDRES=0p16 + GRIDNR=255 + MODNR=11 + ;; + wc_10m) + GRDREGION='wcoast' + GRDRES=0p16 + GRIDNR=255 + MODNR=11 + ;; + ak_10m) + GRDREGION='alaska' + GRDRES=0p16 + GRIDNR=255 + MODNR=11 + ;; + aoc_9km) + GRDREGION='arctic' + GRDRES=9km + GRIDNR=255 + MODNR=11 + ;; + ant_9km) + GRDREGION='antarc' + GRDRES=9km + GRIDNR=255 + MODNR=11 + ;; + gnh_10m) + GRDREGION='global' + GRDRES=0p16 + GRIDNR=255 + MODNR=11 + ;; + gsh_15m) + GRDREGION='gsouth' + GRDRES=0p25 + GRIDNR=255 + MODNR=11 + ;; + ao_20m) + GRDREGION='arctic' + GRDRES=0p33 + GRIDNR=255 + MODNR=11 + ;; + so_20m) + GRDREGION='antarc' + GRDRES=0p33 + GRIDNR=255 + MODNR=11 + ;; + reg025) + GRDREGION='global' + GRDRES=0p25 + GRIDNR=255 + MODNR=11 + ;; + gwes_30m) + GRDREGION='global' + GRDRES=0p50 + GRIDNR=255 + MODNR=10 + ;; + *) + echo "FATAL ERROR: No grid specific wave config values exist for ${grdID}. Aborting." + exit 1 + ;; + esac + grdNAME="${GRDREGION}.${GRDRES}" + echo "grdNAME=${grdNAME}" + echo "GRIDNR=${GRIDNR}" + echo "MODNR=${MODNR}" } diff --git a/ush/wave_extractvars.sh b/ush/wave_extractvars.sh index 37551358b28..dde21a2c690 100755 --- a/ush/wave_extractvars.sh +++ b/ush/wave_extractvars.sh @@ -18,28 +18,28 @@ com_dir=${!com_varname} subdata=${1} if [[ ! -d "${subdata}" ]]; then - mkdir -p "${subdata}" + mkdir -p "${subdata}" fi -for (( nh = FHOUT_WAV_EXTRACT; nh <= FHMAX_WAV; nh = nh + FHOUT_WAV_EXTRACT )); do - fnh=$(printf "%3.3d" "${nh}") - - infile=${com_dir}/${RUN}.wave.t${cyc}z.global.${wavres}.f${fnh}.grib2 - new_infile=${subdata}/${RUN}.wave.t${cyc}z.global.${wavres}.f${fnh}_ext.grib2 - outfile=${subdata}/${RUN}.wave.t${cyc}z.global.${wavres}.f${fnh}.grib2 - rm -f "${outfile}" # Remove outfile if it already exists before extraction - - if [[ -f "${infile}" ]]; then # Check if input file exists before extraction - if ! cpfs "${infile}" "${new_infile}"; then - echo "FATAL ERROR: Failed to copy ${infile} to ${new_infile}." - exit 1 +for ((nh = FHOUT_WAV_EXTRACT; nh <= FHMAX_WAV; nh = nh + FHOUT_WAV_EXTRACT)); do + fnh=$(printf "%3.3d" "${nh}") + + infile=${com_dir}/${RUN}.wave.t${cyc}z.global.${wavres}.f${fnh}.grib2 + new_infile=${subdata}/${RUN}.wave.t${cyc}z.global.${wavres}.f${fnh}_ext.grib2 + outfile=${subdata}/${RUN}.wave.t${cyc}z.global.${wavres}.f${fnh}.grib2 + rm -f "${outfile}" # Remove outfile if it already exists before extraction + + if [[ -f "${infile}" ]]; then # Check if input file exists before extraction + if ! cpfs "${infile}" "${new_infile}"; then + echo "FATAL ERROR: Failed to copy ${infile} to ${new_infile}." + exit 1 + fi + # shellcheck disable=SC2312 + ${WGRIB2} "${new_infile}" | grep -F -f "${varlist_wav}" | ${WGRIB2} -i "${new_infile}" -append -grib "${outfile}" + else + echo "WARNING: ${infile} does not exist in ${com_dir}." fi - # shellcheck disable=SC2312 - ${WGRIB2} "${new_infile}" | grep -F -f "${varlist_wav}" | ${WGRIB2} -i "${new_infile}" -append -grib "${outfile}" - else - echo "WARNING: ${infile} does not exist in ${com_dir}." - fi - copy_to_comout "${outfile}" "${ARC_RFCST_PROD_WAV}" + copy_to_comout "${outfile}" "${ARC_RFCST_PROD_WAV}" done # nh exit 0 diff --git a/ush/wave_grib2_sbs.sh b/ush/wave_grib2_sbs.sh index b112248f6f8..d36b7d25632 100755 --- a/ush/wave_grib2_sbs.sh +++ b/ush/wave_grib2_sbs.sh @@ -25,7 +25,6 @@ # --------------------------------------------------------------------------- # # 0. Preparations - # Script inputs grdID=$1 GRIDNR=$2 @@ -56,8 +55,8 @@ outfile="${RUN}.t${cyc}z.${grid_region}.${grid_res}.f${FH3}.grib2" # Check if outfile exists in COM if [[ -s "${com_dir}/${outfile}" ]] && [[ -s "${com_dir}/${outfile}.idx" ]]; then - echo "File ${com_dir}/${outfile}[.idx] found, skipping generation process" - exit 0 + echo "File ${com_dir}/${outfile}[.idx] found, skipping generation process" + exit 0 fi # Copy template files to grib_DATA (required for ww3_grib.x) @@ -70,8 +69,8 @@ ${NLN} "${DATA}/mod_def.${grdID}" "./mod_def.ww3" ${NLN} "${DATA}/out_grd.${grdID}" "./out_grd.ww3" # Create the input file for the ww3_grib2 code -ngrib=1 # only one time slice -dtgrib=3600 # only one time slice +ngrib=1 # only one time slice +dtgrib=3600 # only one time slice tstart="${valid_time:0:8} ${valid_time:8:2}0000" sed -e "s/TIME/${tstart}/g" \ @@ -89,28 +88,28 @@ source prep_step "${EXECgfs}/${pgm}" > "grib2_${grid_region}_${FH3}.out" 2>&1 export err=$? if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: ${pgm} returned non-zero status: ${err}; exiting!" - exit "${err}" + echo "FATAL ERROR: ${pgm} returned non-zero status: ${err}; exiting!" + exit "${err}" fi cat "grib2_${grid_region}_${FH3}.out" if [[ ! -s gribfile ]]; then - echo "FATAL ERROR: '${pgm}' failed!" - exit 2 + echo "FATAL ERROR: '${pgm}' failed!" + exit 2 fi if [[ ${fhr} -gt 0 ]]; then - ${WGRIB2} gribfile -set_date "${PDY}${cyc}" -set_ftime "${fhr} hour fcst" -grib "${outfile}" - err=$? + ${WGRIB2} gribfile -set_date "${PDY}${cyc}" -set_ftime "${fhr} hour fcst" -grib "${outfile}" + err=$? else - ${WGRIB2} gribfile -set_date "${PDY}${cyc}" -set_ftime "${fhr} hour fcst" \ - -set table_1.4 1 -set table_1.2 1 -grib "${outfile}" - err=$? + ${WGRIB2} gribfile -set_date "${PDY}${cyc}" -set_ftime "${fhr} hour fcst" \ + -set table_1.4 1 -set table_1.2 1 -grib "${outfile}" + err=$? fi if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: Error creating '${outfile}' with '${WGRIB2}'" - exit 3 + echo "FATAL ERROR: Error creating '${outfile}' with '${WGRIB2}'" + exit 3 fi # Create index @@ -118,41 +117,41 @@ ${WGRIB2} -s "${outfile}" > "${outfile}.idx" # Move grib files to COM directory if [[ -s "${outfile}" && -s "${outfile}.idx" ]]; then - cpfs "${outfile}" "${com_dir}/${outfile}" - cpfs "${outfile}.idx" "${com_dir}/${outfile}.idx" - echo "INFO: Copied ${outfile} and ${outfile}.idx from ${grib_DATA} to COM" + cpfs "${outfile}" "${com_dir}/${outfile}" + cpfs "${outfile}.idx" "${com_dir}/${outfile}.idx" + echo "INFO: Copied ${outfile} and ${outfile}.idx from ${grib_DATA} to COM" else - echo "FATAL ERROR: ${outfile} and ${outfile}.idx not found in ${grib_DATA} to copy to COM" - exit 4 + echo "FATAL ERROR: ${outfile} and ${outfile}.idx not found in ${grib_DATA} to copy to COM" + exit 4 fi # Create grib2 subgrid if this is the source grid if [[ "${grdID}" == "${WAV_SUBGRBSRC}" ]]; then - for subgrb in ${WAV_SUBGRB}; do - subgrbref=$(echo ${!subgrb} | cut -d " " -f 1-20) - subgrbnam=$(echo ${!subgrb} | cut -d " " -f 21) - subgrbres=$(echo ${!subgrb} | cut -d " " -f 22) - subfnam="${RUN}.t${cyc}z.${subgrbnam}.${subgrbres}.f${FH3}.grib2" - - ${COPYGB2} -g "${subgrbref}" -i0 -x "${outfile}" "${subfnam}" - ${WGRIB2} -s "${subfnam}" > "${subfnam}.idx" - - if [[ -s "${subfnam}" && -s "${subfnam}.idx" ]]; then - cpfs "${subfnam}" "${com_dir}/${subfnam}" - cpfs "${subfnam}.idx" "${com_dir}/${subfnam}.idx" - echo "INFO: Copied ${subfnam} and ${subfnam}.idx from ${GRIBDATA} to COM" - else - echo "FATAL ERROR: ${subfnam} and ${subfnam}.idx not found in ${grib_DATA} to copy to COM" - exit 5 - fi - done + for subgrb in ${WAV_SUBGRB}; do + subgrbref=$(echo "${!subgrb}" | cut -d " " -f 1-20) + subgrbnam=$(echo "${!subgrb}" | cut -d " " -f 21) + subgrbres=$(echo "${!subgrb}" | cut -d " " -f 22) + subfnam="${RUN}.t${cyc}z.${subgrbnam}.${subgrbres}.f${FH3}.grib2" + + ${COPYGB2} -g "${subgrbref}" -i0 -x "${outfile}" "${subfnam}" + ${WGRIB2} -s "${subfnam}" > "${subfnam}.idx" + + if [[ -s "${subfnam}" && -s "${subfnam}.idx" ]]; then + cpfs "${subfnam}" "${com_dir}/${subfnam}" + cpfs "${subfnam}.idx" "${com_dir}/${subfnam}.idx" + echo "INFO: Copied ${subfnam} and ${subfnam}.idx from ${GRIBDATA} to COM" + else + echo "FATAL ERROR: ${subfnam} and ${subfnam}.idx not found in ${grib_DATA} to copy to COM" + exit 5 + fi + done fi if [[ "${SENDDBN}" == 'YES' && "${outfile}" != *global.0p50* ]]; then - echo "INFO: Alerting GRIB file as ${outfile}" - echo "INFO: Alerting GRIB index file as ${outfile}.idx" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_WAVE_GB2" "${job}" "${com_dir}/${outfile}" - "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_WAVE_GB2_WIDX" "${job}" "${com_dir}/${outfile}.idx" + echo "INFO: Alerting GRIB file as ${outfile}" + echo "INFO: Alerting GRIB index file as ${outfile}.idx" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_WAVE_GB2" "${job}" "${com_dir}/${outfile}" + "${DBNROOT}/bin/dbn_alert" MODEL "${RUN^^}_WAVE_GB2_WIDX" "${job}" "${com_dir}/${outfile}.idx" else - echo "INFO: ${outfile} is global.0p50 or SENDDBN is NO, no alert sent" + echo "INFO: ${outfile} is global.0p50 or SENDDBN is NO, no alert sent" fi diff --git a/ush/wave_grid_interp_sbs.sh b/ush/wave_grid_interp_sbs.sh index ed41b813610..3e4fc585687 100755 --- a/ush/wave_grid_interp_sbs.sh +++ b/ush/wave_grid_interp_sbs.sh @@ -41,18 +41,18 @@ ${NLN} "${DATA}/out_grd.${waveGRD}" "./out_grd.${waveGRD}" # Link mod_def files from DATA into interp_DATA for ID in ${waveGRD} ${grdID}; do - ${NLN} "${DATA}/mod_def.${ID}" "./mod_def.${ID}" + ${NLN} "${DATA}/mod_def.${ID}" "./mod_def.${ID}" done # Check if there is an interpolation weights file available, and copy it if so if [[ -f "${FIXgfs}/wave/ww3_gint.WHTGRIDINT.bin.${waveGRD}.${grdID}" ]]; then - echo "INFO: Interpolation weights found at: '${FIXgfs}/wave/ww3_gint.WHTGRIDINT.bin.${waveGRD}.${grdID}'" - cpreq "${FIXgfs}/wave/ww3_gint.WHTGRIDINT.bin.${waveGRD}.${grdID}" "./WHTGRIDINT.bin" - weights_found=1 + echo "INFO: Interpolation weights found at: '${FIXgfs}/wave/ww3_gint.WHTGRIDINT.bin.${waveGRD}.${grdID}'" + cpreq "${FIXgfs}/wave/ww3_gint.WHTGRIDINT.bin.${waveGRD}.${grdID}" "./WHTGRIDINT.bin" + weights_found=1 else - echo "WARNING: No weights file found at: '${FIXgfs}/wave/ww3_gint.WHTGRIDINT.bin.${waveGRD}.${grdID}'" - echo "INFO: Interpolation will create a new weights file" - weights_found=0 + echo "WARNING: No weights file found at: '${FIXgfs}/wave/ww3_gint.WHTGRIDINT.bin.${waveGRD}.${grdID}'" + echo "INFO: Interpolation will create a new weights file" + weights_found=0 fi # Create the input file for the interpolation code @@ -69,26 +69,26 @@ cat ww3_gint.inp export pgm="${NET,,}_ww3_gint.x" source prep_step echo "INFO: Executing '${pgm}'" -"${EXECgfs}/${pgm}" > grid_interp.${grdID}.out 2>&1 +"${EXECgfs}/${pgm}" > "grid_interp.${grdID}.out" 2>&1 cat "grid_interp.${grdID}.out" if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR: '${pgm}' failed!" - exit 3 + echo "FATAL ERROR: '${pgm}' failed!" + exit 3 fi if [[ ${weights_found} -eq 0 ]]; then - echo "INFO: Interpolation created a new weights file at: '${interp_DATA}/WHTGRIDINT.bin'" + echo "INFO: Interpolation created a new weights file at: '${interp_DATA}/WHTGRIDINT.bin'" fi # Link output file (interpolated output) within DATA (this program generates this file) if [[ -f "./out_grd.${grdID}" ]]; then - if [[ -f "${DATA}/out_grd.${grdID}" ]]; then - echo "FATAL ERROR: '${DATA}/out_grd.${grdID}' already exists, ABORT!" - exit 4 - else - ${NLN} "${interp_DATA}/out_grd.${grdID}" "${DATA}/out_grd.${grdID}" - fi + if [[ -f "${DATA}/out_grd.${grdID}" ]]; then + echo "FATAL ERROR: '${DATA}/out_grd.${grdID}' already exists, ABORT!" + exit 4 + else + ${NLN} "${interp_DATA}/out_grd.${grdID}" "${DATA}/out_grd.${grdID}" + fi else - echo "FATAL ERROR: '${pgm}' failed to generate output file at: '${interp_DATA}/out_grd.${grdID}'" - exit 4 + echo "FATAL ERROR: '${pgm}' failed to generate output file at: '${interp_DATA}/out_grd.${grdID}'" + exit 4 fi diff --git a/ush/wave_grid_moddef.sh b/ush/wave_grid_moddef.sh index 7cf6d3aa20b..65ee1550337 100755 --- a/ush/wave_grid_moddef.sh +++ b/ush/wave_grid_moddef.sh @@ -21,44 +21,43 @@ # 0. Preparations # 0.a Basic modes of operation - grdID=${1?Must provide grdID} +grdID=${1?Must provide grdID} - echo "INFO: Generating mod_def file for ${grdID}" +echo "INFO: Generating mod_def file for ${grdID}" - mkdir -p "moddef_${grdID}" - cd "moddef_${grdID}" || exit 2 +mkdir -p "moddef_${grdID}" +cd "moddef_${grdID}" || exit 2 # --------------------------------------------------------------------------- # # 2. Create mod_def file +rm -f "ww3_grid.inp" +${NLN} "../ww3_grid.inp.${grdID}" "ww3_grid.inp" - rm -f "ww3_grid.inp" - ${NLN} "../ww3_grid.inp.${grdID}" "ww3_grid.inp" +if [[ -f "../${grdID}.msh" ]]; then + rm -f "${grdID}.msh" + ${NLN} "../${grdID}.msh" "${grdID}.msh" +fi - if [[ -f "../${grdID}.msh" ]]; then - rm -f "${grdID}.msh" - ${NLN} "../${grdID}.msh" "${grdID}.msh" - fi +export pgm="${NET,,}_ww3_grid.x" - export pgm="${NET,,}_ww3_grid.x" +echo "INFO: Executing ${EXECgfs}/${NET,,}_ww3_grid.x" - echo "INFO: Executing ${EXECgfs}/${NET,,}_ww3_grid.x" +"${EXECgfs}/${pgm}" +export err=$? - "${EXECgfs}/${pgm}" - export err=$? - - if [[ "${err}" != '0' ]]; then +if [[ "${err}" != '0' ]]; then echo "FATAL ERROR: Error in ${pgm}" exit "${err}" - fi +fi - if [[ -f mod_def.ww3 ]];then +if [[ -f mod_def.ww3 ]]; then cpfs "mod_def.ww3" "${COMOUT_WAVE_PREP}/${RUN}.t${cyc}z.mod_def.${grdID}.bin" mv "mod_def.ww3" "../mod_def.${grdID}" - else +else echo "FATAL ERROR: Mod def file not created for ${grdID}" exit 4 - fi +fi # --------------------------------------------------------------------------- # # 3. Clean up diff --git a/ush/wave_outp_cat.sh b/ush/wave_outp_cat.sh index b4482497666..b7200516425 100755 --- a/ush/wave_outp_cat.sh +++ b/ush/wave_outp_cat.sh @@ -29,16 +29,16 @@ specdir=$3 # 0.b Check if buoy location set if [[ $# -lt 1 ]]; then - echo 'FATAL ERROR: LOCATION ID IN ww3_outp_spec.sh NOT SET ***' - exit 1 + echo 'FATAL ERROR: LOCATION ID IN ww3_outp_spec.sh NOT SET ***' + exit 1 fi # 0.c Define directories and the search path. # The tested variables should be exported by the postprocessor script. if [[ -z "${DTPNT_WAV+0}" || -z "${FHMIN_WAV+0}" || -z "${WAV_MOD_TAG+0}" || -z "${STA_DIR+0}" ]]; then - echo 'FATAL ERROR: EXPORTED VARIABLES IN ww3_outp_cat.sh NOT SET ***' - exit 3 + echo 'FATAL ERROR: EXPORTED VARIABLES IN ww3_outp_cat.sh NOT SET ***' + exit 3 fi # --------------------------------------------------------------------------- # @@ -47,53 +47,53 @@ fi echo " Generate input file for ww3_outp." if [[ "${specdir}" == "bull" ]]; then - outfile="${STA_DIR}/${specdir}/${WAV_MOD_TAG}.${buoy}.bull" - coutfile="${STA_DIR}/c${specdir}/${WAV_MOD_TAG}.${buoy}.cbull" - rm -f "${outfile}" "${coutfile}" + outfile="${STA_DIR}/${specdir}/${WAV_MOD_TAG}.${buoy}.bull" + coutfile="${STA_DIR}/c${specdir}/${WAV_MOD_TAG}.${buoy}.cbull" + rm -f "${outfile}" "${coutfile}" else - outfile="${STA_DIR}/${specdir}/${WAV_MOD_TAG}.${buoy}.spec" - rm -f "${outfile}" + outfile="${STA_DIR}/${specdir}/${WAV_MOD_TAG}.${buoy}.spec" + rm -f "${outfile}" fi fhr=${FHMIN_WAV} fhrp=${fhr} while [[ ${fhr} -le ${MAXHOUR} ]]; do - ymdh=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${fhr} hours") - if [[ "${specdir}" == "bull" ]]; then - outfilefhr="${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.bull" - coutfilefhr="${STA_DIR}/c${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.cbull" - else - outfilefhr="${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.spec" - fi - - if [[ -f "${outfilefhr}" ]]; then - if [[ "$specdir" == "bull" ]]; then - cat "${outfilefhr}" >> "${STA_DIR}/${specdir}/${WAV_MOD_TAG}.${buoy}.bull" - cat "${coutfilefhr}" >> "${STA_DIR}/c${specdir}/${WAV_MOD_TAG}.${buoy}.cbull" - rm -f "${outfilefhr}" "${coutfilefhr}" + ymdh=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${fhr} hours") + if [[ "${specdir}" == "bull" ]]; then + outfilefhr="${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.bull" + coutfilefhr="${STA_DIR}/c${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.cbull" else - cat "${outfilefhr}" >> "${STA_DIR}/${specdir}/${WAV_MOD_TAG}.${buoy}.spec" - #rm -f "${outfilefhr}" + outfilefhr="${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.spec" fi - else - echo "FATAL ERROR: OUTPUT DATA FILE FOR BUOY ${buoy} at ${ymdh} NOT FOUND" - exit 9 - fi - FHINCP=$(( DTPNT_WAV / 3600 )) - if [[ ${fhr} -eq ${fhrp} ]]; then - fhrp=$((fhr+FHINCP)) - fi - echo "${fhrp}" + if [[ -f "${outfilefhr}" ]]; then + if [[ "${specdir}" == "bull" ]]; then + cat "${outfilefhr}" >> "${STA_DIR}/${specdir}/${WAV_MOD_TAG}.${buoy}.bull" + cat "${coutfilefhr}" >> "${STA_DIR}/c${specdir}/${WAV_MOD_TAG}.${buoy}.cbull" + rm -f "${outfilefhr}" "${coutfilefhr}" + else + cat "${outfilefhr}" >> "${STA_DIR}/${specdir}/${WAV_MOD_TAG}.${buoy}.spec" + #rm -f "${outfilefhr}" + fi + else + echo "FATAL ERROR: OUTPUT DATA FILE FOR BUOY ${buoy} at ${ymdh} NOT FOUND" + exit 9 + fi + + FHINCP=$((DTPNT_WAV / 3600)) + if [[ ${fhr} -eq ${fhrp} ]]; then + fhrp=$((fhr + FHINCP)) + fi + echo "${fhrp}" - fhr=${fhrp} # no gridded output, loop with out_pnt stride + fhr=${fhrp} # no gridded output, loop with out_pnt stride done if [[ ! -f "${outfile}" ]]; then - echo "FATAL ERROR: OUTPUTFILE ${outfile} not created " - exit 2 + echo "FATAL ERROR: OUTPUTFILE ${outfile} not created " + exit 2 fi # End of ww3_outp_cat.sh ---------------------------------------------------- # diff --git a/ush/wave_outp_spec.sh b/ush/wave_outp_spec.sh index e365741809f..96bfc196d9c 100755 --- a/ush/wave_outp_spec.sh +++ b/ush/wave_outp_spec.sh @@ -31,31 +31,31 @@ workdir=$4 # 0.b Check if buoy location set if [[ $# -lt 1 ]]; then - echo 'FATAL ERROR: LOCATION ID IN wave_outp_spec.sh NOT SET' - exit 1 + echo 'FATAL ERROR: LOCATION ID IN wave_outp_spec.sh NOT SET' + exit 1 else - point=$(awk "{if (\$2 == \"${buoy}\"){print \$1; exit} }" "${DATA}/buoy_log.ww3") - if [[ -z "${point}" ]]; then - echo 'FATAL ERROR: LOCATION ID IN ww3_outp_spec.sh NOT RECOGNIZED' - exit 2 - else - printf "\n Location ID/# : %s (%s) ${buoy} (${point})\n Spectral output start time : %s" "${buoy}" "${point}" "${ymdh}" - fi + point=$(awk "{if (\$2 == \"${buoy}\"){print \$1; exit} }" "${DATA}/buoy_log.ww3") + if [[ -z "${point}" ]]; then + echo 'FATAL ERROR: LOCATION ID IN ww3_outp_spec.sh NOT RECOGNIZED' + exit 2 + else + printf "\n Location ID/# : %s (%s) ${buoy} (${point})\n Spectral output start time : %s" "${buoy}" "${point}" "${ymdh}" + fi fi # 0.c Define directories and the search path. # The tested variables should be exported by the postprocessor script. if [[ -z "${PDY+0}" || -z "${cyc+0}" || -z "${dtspec+0}" || -z "${EXECgfs+0}" || -z "${WAV_MOD_TAG+0}" || -z "${STA_DIR+0}" ]]; then - echo 'FATAL ERROR: EXPORTED VARIABLES IN ww3_outp_spec.sh NOT SET' - exit 3 + echo 'FATAL ERROR: EXPORTED VARIABLES IN ww3_outp_spec.sh NOT SET' + exit 3 fi -cd "${workdir}" +cd "${workdir}" || exit 1 rm -rf "${specdir}_${buoy}" mkdir -p "${specdir}_${buoy}" -cd "${specdir}_${buoy}" +cd "${specdir}_${buoy}" || exit 1 cat << EOF @@ -86,22 +86,22 @@ tstart="${ymdh:0:8} ${ymdh:8:2}0000" printf " Output starts at %s.\n" "${tstart}" if [[ "${specdir}" == "bull" ]]; then - truntime="${PDY} ${cyc}0000" - sed -e "s/TIME/${tstart}/g" \ - -e "s/DT/${dtspec}/g" \ - -e "s/POINT/${point}/g" \ - -e "s/REFT/${truntime}/g" \ - "${DATA}/ww3_outp_bull.inp.tmpl" > ww3_outp.inp - outfile="${buoy}.bull" - coutfile="${buoy}.cbull" + truntime="${PDY} ${cyc}0000" + sed -e "s/TIME/${tstart}/g" \ + -e "s/DT/${dtspec}/g" \ + -e "s/POINT/${point}/g" \ + -e "s/REFT/${truntime}/g" \ + "${DATA}/ww3_outp_bull.inp.tmpl" > ww3_outp.inp + outfile="${buoy}.bull" + coutfile="${buoy}.cbull" else - sed -e "s/TIME/${tstart}/g" \ - -e "s/DT/${dtspec}/g" \ - -e "s/POINT/${point}/g" \ - -e "s/ITYPE/1/g" \ - -e "s/FORMAT/F/g" \ - "${DATA}/ww3_outp_spec.inp.tmpl" > ww3_outp.inp - outfile="ww3.${tstart:2:5}${tstart:9:2}.spc" + sed -e "s/TIME/${tstart}/g" \ + -e "s/DT/${dtspec}/g" \ + -e "s/POINT/${point}/g" \ + -e "s/ITYPE/1/g" \ + -e "s/FORMAT/F/g" \ + "${DATA}/ww3_outp_spec.inp.tmpl" > ww3_outp.inp + outfile="ww3.${tstart:2:5}${tstart:9:2}.spc" fi # 2.b Run the postprocessor @@ -114,8 +114,8 @@ echo " Executing ${EXECgfs}/${pgm}" "${EXECgfs}/${pgm}" 1> "outp_${specdir}_${buoy}.out" 2>&1 export err=$? if [[ ${err} -ne 0 ]]; then - echo "FATAL ERROR : ERROR IN ${pgm} *** " - exit 4 + echo "FATAL ERROR : ERROR IN ${pgm} *** " + exit 4 fi # --------------------------------------------------------------------------- # @@ -126,31 +126,31 @@ YMDHE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${FHMAX_WAV_PNT} hours") model_start_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} + ${OFFSET_START_HOUR} hours") if [[ -f "${outfile}" ]]; then - if [[ "${ymdh}" == "${model_start_date}" ]]; then - if [[ "${specdir}" == "bull" ]]; then - sed '9,$d' "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.bull" - sed '8,$d' "${coutfile}" >> "${STA_DIR}/c${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.cbull" - else - cat "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.spec" - fi - elif [[ "${ymdh}" == "${YMDHE}" ]]; then - if [[ "${specdir}" == "bull" ]]; then - sed '1,7d' "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.bull" - sed '1,6d' "${coutfile}" >> "${STA_DIR}/c${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.cbull" - else - sed -n "/^${ymdh:0:8} ${ymdh:8:2}0000$/,\$p" "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.spec" - fi - else - if [[ "${specdir}" == "bull" ]]; then - sed '8q;d' "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.bull" - sed '7q;d' "${coutfile}" >> "${STA_DIR}/c${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.cbull" - else - sed -n "/^${ymdh:0:8} ${ymdh:8:2}0000$/,\$p" "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.spec" - fi - fi + if [[ "${ymdh}" == "${model_start_date}" ]]; then + if [[ "${specdir}" == "bull" ]]; then + sed '9,$d' "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.bull" + sed '8,$d' "${coutfile}" >> "${STA_DIR}/c${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.cbull" + else + cat "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.spec" + fi + elif [[ "${ymdh}" == "${YMDHE}" ]]; then + if [[ "${specdir}" == "bull" ]]; then + sed '1,7d' "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.bull" + sed '1,6d' "${coutfile}" >> "${STA_DIR}/c${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.cbull" + else + sed -n "/^${ymdh:0:8} ${ymdh:8:2}0000$/,\$p" "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.spec" + fi + else + if [[ "${specdir}" == "bull" ]]; then + sed '8q;d' "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.bull" + sed '7q;d' "${coutfile}" >> "${STA_DIR}/c${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.cbull" + else + sed -n "/^${ymdh:0:8} ${ymdh:8:2}0000$/,\$p" "${outfile}" >> "${STA_DIR}/${specdir}fhr/${WAV_MOD_TAG}.${ymdh}.${buoy}.spec" + fi + fi else - echo "FATAL ERROR: OUTPUT DATA FILE FOR BUOY '${buoy}' NOT FOUND" - exit 5 + echo "FATAL ERROR: OUTPUT DATA FILE FOR BUOY '${buoy}' NOT FOUND" + exit 5 fi # 3.b Clean up the rest diff --git a/ush/wave_prnc_cur.sh b/ush/wave_prnc_cur.sh index cdeecc1f7c5..a52b9336dc6 100755 --- a/ush/wave_prnc_cur.sh +++ b/ush/wave_prnc_cur.sh @@ -31,10 +31,10 @@ fext='f' # Timing has to be made relative to the single 00z RTOFS cycle for that PDY -mkdir -p rtofs_${ymdh_rtofs} -cd rtofs_${ymdh_rtofs} +mkdir -p "rtofs_${ymdh_rtofs}" +cd "rtofs_${ymdh_rtofs}" || exit 1 -ncks -x -v sst,sss,layer_density "${curfile} cur_uv_${PDY}_${fext}${fh3}.nc" +ncks -x -v sst,sss,layer_density "${curfile}" "cur_uv_${PDY}_${fext}${fh3}.nc" ncks -O -a -h -x -v Layer "cur_uv_${PDY}_${fext}${fh3}.nc" "cur_temp1.nc" ncwa -h -O -a Layer cur_temp1.nc cur_temp2.nc ncrename -h -O -v MT,time -d MT,time cur_temp2.nc @@ -44,28 +44,27 @@ mv -f "cur_temp3.nc" "cur_uv_${PDY}_${fext}${fh3}_flat.nc" # Convert to regular lat lon file # If weights need to be regenerated due to CDO ver change, use: # $CDO genbil,r4320x2160 rtofs_glo_2ds_f000_3hrly_prog.nc weights.nc -cpreq ${FIXgfs}/wave/weights_rtofs_to_r4320x2160.nc ./weights.nc +cpreq "${FIXgfs}/wave/weights_rtofs_to_r4320x2160.nc" ./weights.nc # Interpolate to regular 5 min grid ${CDO} remap,r4320x2160,weights.nc "cur_uv_${PDY}_${fext}${fh3}_flat.nc" "cur_5min_01.nc" # Perform 9-point smoothing twice to make RTOFS data less noisy when # interpolating from 1/12 deg RTOFS grid to 1/6 deg wave grid -if [ "WAV_CUR_CDO_SMOOTH" = "YES" ]; then - ${CDO} -f nc -smooth9 "cur_5min_01.nc" "cur_5min_02.nc" - ${CDO} -f nc -smooth9 "cur_5min_02.nc" "cur_glo_uv_${PDY}_${fext}${fh3}_5min.nc" +if [[ "${WAV_CUR_CDO_SMOOTH}" == "YES" ]]; then + ${CDO} -f nc -smooth9 "cur_5min_01.nc" "cur_5min_02.nc" + ${CDO} -f nc -smooth9 "cur_5min_02.nc" "cur_glo_uv_${PDY}_${fext}${fh3}_5min.nc" else - mv "cur_5min_01.nc" "cur_glo_uv_${PDY}_${fext}${fh3}_5min.nc" + mv "cur_5min_01.nc" "cur_glo_uv_${PDY}_${fext}${fh3}_5min.nc" fi # Cleanup rm -f cur_temp[123].nc cur_5min_??.nc "cur_glo_uv_${PDY}_${fext}${fh3}.nc weights.nc" -if [ ${flagfirst} = "T" ] -then - sed -e "s/HDRFL/T/g" ${PARMgfs}/wave/ww3_prnc.cur.${WAVECUR_FID}.inp.tmpl > ww3_prnc.inp +if [[ "${flagfirst}" = "T" ]]; then + sed -e "s/HDRFL/T/g" "${PARMgfs}/wave/ww3_prnc.cur.${WAVECUR_FID}.inp.tmpl" > ww3_prnc.inp else - sed -e "s/HDRFL/F/g" ${PARMgfs}/wave/ww3_prnc.cur.${WAVECUR_FID}.inp.tmpl > ww3_prnc.inp + sed -e "s/HDRFL/F/g" "${PARMgfs}/wave/ww3_prnc.cur.${WAVECUR_FID}.inp.tmpl" > ww3_prnc.inp fi rm -f cur.nc @@ -75,22 +74,15 @@ ${NLN} "${DATA}/mod_def.${WAVECUR_FID}" ./mod_def.ww3 export pgm="${NET,,}_ww3_prnc.x" source prep_step -"${EXECgfs}/${pgm}" 1> prnc_${WAVECUR_FID}_${ymdh_rtofs}.out 2>&1 -export err=$?; err_chk -if [ "$err" != '0' ] -then - cat prnc_${WAVECUR_FID}_${ymdh_rtofs}.out - set $setoff - echo ' ' - echo '******************************************** ' - echo "*** WARNING: NON-FATAL ERROR IN ${pgm} *** " - echo '******************************************** ' - echo ' ' - set $seton - echo "WARNING: NON-FATAL ERROR IN ${pgm}." - exit 4 +"${EXECgfs}/${pgm}" 1> "prnc_${WAVECUR_FID}_${ymdh_rtofs}.out" 2>&1 +export err=$? +err_chk +if [[ "${err}" -ne 0 ]]; then + cat "prnc_${WAVECUR_FID}_${ymdh_rtofs}.out" + echo "WARNING: NON-FATAL ERROR IN ${pgm}." + exit 4 fi -mv -f current.ww3 ${DATA}/rtofs.${ymdh_rtofs} +mv -f current.ww3 "${DATA}/rtofs.${ymdh_rtofs}" -cd ${DATA} +cd "${DATA}" || exit 1 diff --git a/ush/wave_prnc_ice.sh b/ush/wave_prnc_ice.sh index 3812b5e8120..caeba3a0d05 100755 --- a/ush/wave_prnc_ice.sh +++ b/ush/wave_prnc_ice.sh @@ -29,100 +29,96 @@ # 0.a Basic modes of operation - rm -rf ice - mkdir ice - cd ice - ${NLN} "${DATA}/postmsg" postmsg +rm -rf ice +mkdir ice +cd ice || exit 1 +${NLN} "${DATA}/postmsg" postmsg # 0.b Define directories and the search path. # The tested variables should be exported by the postprocessor script. - set +x - cat << EOF +set +x +cat << EOF +--------------------------------+ ! Make ice fields | +--------------------------------+ - Model TAG : $WAV_MOD_TAG + Model TAG : ${WAV_MOD_TAG} Model ID : ${RUN}.wave - Ice grid ID : $WAVEICE_FID - Ice file : $WAVICEFILE + Ice grid ID : ${WAVEICE_FID} + Ice file : ${WAVICEFILE} Making ice fields. EOF - if [[ -z "${YMDH}" ]] || [[ -z "${cycle}" ]] || \ - [[ -z "${COMOUT_WAVE_PREP}" ]] || [[ -z "${FIXgfs}" ]] || [[ -z "${EXECgfs}" ]] || \ - [[ -z "${WAV_MOD_TAG}" ]] || [[ -z "${WAVEICE_FID}" ]] || [[ -z "${COMIN_OBS}" ]]; then +if [[ -z "${YMDH}" ]] || [[ -z "${cycle}" ]] || + [[ -z "${COMOUT_WAVE_PREP}" ]] || [[ -z "${FIXgfs}" ]] || [[ -z "${EXECgfs}" ]] || + [[ -z "${WAV_MOD_TAG}" ]] || [[ -z "${WAVEICE_FID}" ]] || [[ -z "${COMIN_OBS}" ]]; then echo 'ERROR: EXPORTED VARIABLES IN preprocessor NOT SET ***' exit 1 - fi +fi # 0.c Links to working directory - ${NLN} ${DATA}/mod_def.$WAVEICE_FID mod_def.ww3 +${NLN} "${DATA}/mod_def.${WAVEICE_FID}" mod_def.ww3 # --------------------------------------------------------------------------- # # 1. Get the necessary files # 1.a Copy the ice data file - file=${COMIN_OBS}/${WAVICEFILE} +file="${COMIN_OBS}/${WAVICEFILE}" - if [ -f $file ] - then - cpreq $file ice.grib - fi +if [[ -f "${file}" ]]; then + cpreq "${file}" ice.grib +fi - if [ -f ice.grib ] - then - echo " ice.grib copied ($file)." - else - echo "ERROR: NO ICE FILE $file" - exit 2 - fi +if [[ -f ice.grib ]]; then + echo " ice.grib copied (${file})." +else + msg="FATAL ERROR: NO ICE FILE ${file}" + export err=2 + err_exit "${msg}" +fi # --------------------------------------------------------------------------- # # 2. Process the GRIB packed ice file # 2.a Unpack data - echo ' Extracting data from ice.grib ...' +echo ' Extracting data from ice.grib ...' - $WGRIB2 ice.grib -netcdf icean_5m.nc 2>&1 > wgrib.out +${WGRIB2} ice.grib -netcdf icean_5m.nc wgrib.out 2>&1 - err=$? +err=$? - if [ "$err" != '0' ] - then +if [[ "${err}" -ne 0 ]]; then cat wgrib.out echo 'ERROR: FAILURE WHILE UNPACKING GRIB ICE FILE *** ' exit 3 - fi - - rm -f wgrib.out - rm -f ice.grib - rm -f ice.index +fi +rm -f wgrib.out +rm -f ice.grib +rm -f ice.index # 2.d Run through preprocessor wave_prep - printf " Run through preprocessor ...\n" +printf " Run through preprocessor ...\n" - cpreq -f ${DATA}/ww3_prnc.ice.$WAVEICE_FID.inp.tmpl ww3_prnc.inp +cpreq -f "${DATA}/ww3_prnc.ice.${WAVEICE_FID}.inp.tmpl" ww3_prnc.inp - export pgm="${NET,,}_ww3_prnc.x" - source prep_step +export pgm="${NET,,}_ww3_prnc.x" +source prep_step - "${EXECgfs}/${pgm}" 1> prnc_${WAVEICE_FID}_${cycle}.out 2>&1 - export err=$? - if [[ ${err} -ne 0 ]] - then - cat prnc_${WAVEICE_FID}_${cycle}.out - echo "ERROR: failure in ${pgm}" - exit 4 - fi +"${EXECgfs}/${pgm}" 1> "prnc_${WAVEICE_FID}_${cycle}.out" 2>&1 +export err=$? +if [[ ${err} -ne 0 ]]; then + cat "prnc_${WAVEICE_FID}_${cycle}.out" + msg="FATAL ERROR: failure in ${pgm}" + err_exit "${msg}" +fi - rm -f wave_prep.out ww3_prep.inp ice.raw mod_def.ww3 +rm -f wave_prep.out ww3_prep.inp ice.raw mod_def.ww3 # --------------------------------------------------------------------------- # # 3. Save the ice file @@ -130,17 +126,15 @@ EOF # Ice file name will have ensemble member number if WW3ATMIENS=T # and only WAV_MOD_ID if WW3ATMIENS=F # - if [ "${WW3ATMIENS}" = "T" ] - then - icefile=${WAV_MOD_TAG}.${WAVEICE_FID}.$cycle.ice - elif [ "${WW3ATMIENS}" = "F" ] - then - icefile=${RUN}.wave.${WAVEICE_FID}.$cycle.ice - fi - - echo " Saving ice.ww3 as ${COMOUT_WAVE_PREP}/${icefile}" - cpfs ice.ww3 "${COMOUT_WAVE_PREP}/${icefile}" - rm -f ice.ww3 +if [[ "${WW3ATMIENS}" == "T" ]]; then + icefile="${WAV_MOD_TAG}.${WAVEICE_FID}.${cycle}.ice" +elif [[ "${WW3ATMIENS}" == "F" ]]; then + icefile="${RUN}.wave.${WAVEICE_FID}.${cycle}.ice" +fi + +echo " Saving ice.ww3 as ${COMOUT_WAVE_PREP}/${icefile}" +cpfs ice.ww3 "${COMOUT_WAVE_PREP}/${icefile}" +rm -f ice.ww3 # --------------------------------------------------------------------------- # # 4. Clean up the directory diff --git a/ush/wave_tar.sh b/ush/wave_tar.sh index 9e278c79b02..e24def1e11f 100755 --- a/ush/wave_tar.sh +++ b/ush/wave_tar.sh @@ -27,25 +27,23 @@ # 0.a Basic modes of operation - cd "${DATA}" - echo "Making TAR FILE" - - alertName=$(echo $RUN|tr [a-z] [A-Z]) - +cd "${DATA}" || exit 1 +echo "Making TAR FILE" +export err # 0.b Check if type set - if [[ "$#" -lt '3' ]] - then - echo 'FATAL ERROR: VARIABLES IN ww3_tar.sh NOT SET' - exit 1 - else +if [[ "$#" -lt '3' ]]; then + msg='FATAL ERROR: VARIABLES IN ww3_tar.sh NOT SET' + err=1 + err_exit "${msg}" +else ID=$1 type=$2 nb=$3 - fi +fi - cat << EOF +cat << EOF +--------------------------------+ ! Make tar file | @@ -55,122 +53,120 @@ Number of files : $3 EOF - filext=$type - if [[ "$type" == "ibp" ]]; then - filext='spec' - fi - if [[ "$type" == "ibpbull" ]]; then - filext='bull' - fi - if [[ "$type" == "ibpcbull" ]]; then - filext='cbull' - fi - - rm -rf TAR_${filext}_$ID - mkdir TAR_${filext}_$ID +filext=${type} +if [[ "${type}" == "ibp" ]]; then + filext='spec' +fi +if [[ "${type}" == "ibpbull" ]]; then + filext='bull' +fi +if [[ "${type}" == "ibpcbull" ]]; then + filext='cbull' +fi + +rm -rf "TAR_${filext}_${ID}" +mkdir "TAR_${filext}_${ID}" # this directory is used only for error capturing # 0.c Define directories and the search path. # The tested variables should be exported by the postprocessor script. - if [[ -z "${COMOUT_WAVE_STATION+x}" || -z "${SENDDBN+x}" || -z "${STA_DIR+x}" ]]; then - echo 'FATAL ERROR: EXPORTED VARIABLES IN ww3_tar.sh NOT SET' - exit 2 - fi +if [[ -z "${COMOUT_WAVE_STATION+x}" || -z "${SENDDBN+x}" || -z "${STA_DIR+x}" ]]; then + msg='FATAL ERROR: EXPORTED VARIABLES IN ww3_tar.sh NOT SET' + err=2 + err_exit "${msg}" +fi # --------------------------------------------------------------------------- # # 2. Generate tar file (spectral files are compressed) - printf "\n Making tar file ..." - - countMAX=5 - tardone='no' - sleep_interval=10 - - while [[ "${tardone}" = "no" ]] - do - - nf=$(find . -maxdepth 1 -type f -name "*.$filext" | wc -l) - nbm2=$(( $nb - 2 )) - if [[ ${nf} -ge ${nbm2} ]] - then - - tar -cf "${ID}.${type}.tar" ./*."${filext}" - err=$? - - if [[ ${err} -ne 0 ]] - then - echo 'FATAL ERROR: TAR CREATION FAILED *** ' - exit 3 - fi +printf "\n Making tar file ..." + +countMAX=5 +tardone='no' +sleep_interval=10 + +while [[ "${tardone}" == "no" ]]; do + # shellcheck disable=SC2312 + nf=$(find . -maxdepth 1 -type f -name "*.${filext}" -printf '.' | wc -c) + nbm2=$((nb - 2)) + if [[ ${nf} -ge ${nbm2} ]]; then + + tar -cf "${ID}.${type}.tar" ./*."${filext}" + err=$? + + if [[ ${err} -ne 0 ]]; then + msg='FATAL ERROR: TAR CREATION FAILED *** ' + err=3 + err_exit "${msg}" + fi + + filename="${ID}.${type}.tar" + if ! wait_for_file "${filename}" "${sleep_interval}" "${countMAX}"; then + msg="FATAL ERROR: File ${filename} not found after waiting $((sleep_interval * (countMAX + 1))) secs" + err=3 + err_exit "${msg}" + fi + + if [[ -f "${ID}.${type}.tar" ]]; then + tardone='yes' + fi + fi - filename="${ID}.${type}.tar" - if ! wait_for_file "${filename}" "${sleep_interval}" "${countMAX}" ; then - echo "FATAL ERROR: File ${filename} not found after waiting $(( sleep_interval * (countMAX + 1) )) secs" - exit 3 - fi +done - if [[ -f "${ID}.${type}.tar" ]] - then - tardone='yes' - fi - fi +if [[ "${tardone}" == 'no' ]]; then + msg='FATAL ERROR: TAR CREATION FAILED *** ' + err=3 + err_exit "${msg}" +fi - done - - if [[ "${tardone}" == 'no' ]] - then - echo 'FATAL ERROR: TAR CREATION FAILED *** ' - exit 3 - fi - - if [[ "${type}" == 'spec' ]] - then - if [[ -s "${ID}.${type}.tar" ]] - then - file_name="${ID}.${type}.tar.gz" - /usr/bin/gzip -c "${ID}.${type}.tar" > "${file_name}" - err=$? - - if [[ ${err} -ne 0 ]] - then - echo 'FATAL ERROR: SPECTRAL TAR COMPRESSION FAILED *** ' - exit 4 - fi +if [[ "${type}" == 'spec' ]]; then + if [[ -s "${ID}.${type}.tar" ]]; then + file_name="${ID}.${type}.tar.gz" + /usr/bin/gzip -c "${ID}.${type}.tar" > "${file_name}" + err=$? + + if [[ ${err} -ne 0 ]]; then + msg='FATAL ERROR: SPECTRAL TAR COMPRESSION FAILED *** ' + err=4 + err_exit + fi fi - else +else file_name="${ID}.${type}.tar" - fi +fi # --------------------------------------------------------------------------- # # 3. Move data to /com - echo " Moving tar file ${file_name} to ${COMOUT_WAVE_STATION} ..." +echo " Moving tar file ${file_name} to ${COMOUT_WAVE_STATION} ..." - cpfs "${file_name}" "${COMOUT_WAVE_STATION}/." +cpfs "${file_name}" "${COMOUT_WAVE_STATION}/." - err=$? +err=$? - if [[ ${err} -ne 0 ]]; then - echo 'FATAL ERROR: TAR COPY FAILED *** ' - exit 4 - fi +if [[ ${err} -ne 0 ]]; then + msg='FATAL ERROR: TAR COPY FAILED *** ' + export err=4 + err_exit "${msg}" +fi - if [[ "${SENDDBN}" == "YES" ]]; then +if [[ "${SENDDBN}" == "YES" ]]; then echo " Alerting TAR file as ${COMOUT_WAVE_STATION}/${file_name}" - "${DBNROOT}/bin/dbn_alert MODEL" "${alertName}_WAVE_TAR" "${job}" \ - "${COMOUT_WAVE_STATION}/${file_name}" - fi + "${DBNROOT}/bin/dbn_alert MODEL" "${RUN^^}_WAVE_TAR" "${job}" \ + "${COMOUT_WAVE_STATION}/${file_name}" +fi # --------------------------------------------------------------------------- # # 4. Final clean up -cd "${DATA}" +cd "${DATA}" || exit 1 -if [[ ${KEEPDATA:-NO} == "NO" ]]; then - set -v - rm -rf ${STA_DIR}/${type} - set +v +if [[ "${KEEPDATA:-NO}" == "NO" ]]; then + set -v + rm -rf "${STA_DIR:?}/${type}" + set +v fi # End of ww3_tar.sh ----------------------------------------------------- # From 49812c7088cd36f4ce61d9e9ba436e0473d266da Mon Sep 17 00:00:00 2001 From: Ed Safford <62339196+EdwardSafford-NOAA@users.noreply.github.com> Date: Thu, 11 Dec 2025 06:39:40 -0500 Subject: [PATCH 22/27] Ensure minmon scripts do not fail silently (#4308) If the cpfs calls within the ush/minmon* scripts have been modified to ensure any error code is reported, both in the script log and via error code returned to the calling ex-script. --- ush/minmon_xtrct_costs.pl | 6 ++++-- ush/minmon_xtrct_gnorms.pl | 12 ++++++++---- ush/minmon_xtrct_reduct.pl | 3 ++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ush/minmon_xtrct_costs.pl b/ush/minmon_xtrct_costs.pl index 765526b40d1..3dfd8f47951 100755 --- a/ush/minmon_xtrct_costs.pl +++ b/ush/minmon_xtrct_costs.pl @@ -214,11 +214,13 @@ if( -e $filename2 ) { my $newfile2 = "${tankdir}/${filename2}"; - system("cpfs $filename2 $newfile2"); + system("cpfs $filename2 ${newfile2}") == 0 + or die "cpfs failed to copy ${filename2} to ${newfile2} with exit code $?"; } if( -e $filename3 ) { my $newfile3 = "${tankdir}/${filename3}"; - system("cpfs $filename3 $newfile3"); + system("cpfs ${filename3} ${newfile3}") == 0 + or die "cpfs failed to copy ${filename3} to ${newfile3} with exit code $?"; } } # $rc still == 0 after reading gmon_cost.txt diff --git a/ush/minmon_xtrct_gnorms.pl b/ush/minmon_xtrct_gnorms.pl index d4913b0619b..c0e9e1e0a54 100755 --- a/ush/minmon_xtrct_gnorms.pl +++ b/ush/minmon_xtrct_gnorms.pl @@ -111,7 +111,8 @@ sub updateGnormData { print OUTFILE @filearray; close( OUTFILE ); - system("cpfs $outfile $gdfile"); + system("cpfs ${outfile} ${gdfile}") == 0 + or die "cpfs failed to copy ${outfile} to ${gdfile} with exit code $?"; } @@ -419,17 +420,20 @@ sub updateGnormData { } if( -e $filename2 ) { - system("cpfs $filename2 ${tankdir}/."); + system("cpfs ${filename2} ${tankdir}/.") == 0 + or die "cpfs failed to copy ${filename2} to ${tankdir} with exit code $?"; } my $gdfile = "gnorm_data.txt"; if( -e $gdfile ) { - system("cpfs $gdfile ${tankdir}/."); + system("cpfs ${gdfile} ${tankdir}/.") == 0 + or die "cpfs failed to copy ${gdfile} to ${tankdir} with exit code $?"; } my $errmsg = "${cdate}.errmsg.txt"; if( -e $errmsg ) { - system("cpfs $errmsg ${tankdir}/."); + system("cpfs ${errmsg} ${tankdir}/.") == 0 + or die "cpfs failed to copy ${errmsg} to ${tankdir} with exit code $?"; } } # $rc still == 0 after reading gmon_gnorm.txt diff --git a/ush/minmon_xtrct_reduct.pl b/ush/minmon_xtrct_reduct.pl index 7290a27ba5c..b2d10755ac1 100755 --- a/ush/minmon_xtrct_reduct.pl +++ b/ush/minmon_xtrct_reduct.pl @@ -77,7 +77,8 @@ if( -e $outfile ) { my $newfile = "${tankdir}/${outfile}"; - system("cpfs $outfile $newfile"); + system("cpfs ${outfile} ${newfile}") == 0 + or die "cpfs failed to copy ${outfile} to ${newfile} with exit code $?"; } } else { # $infile does not exist From 841467367adec996e261189d04e868cfe179ec41 Mon Sep 17 00:00:00 2001 From: AntonMFernando-NOAA <167725623+AntonMFernando-NOAA@users.noreply.github.com> Date: Thu, 11 Dec 2025 06:41:04 -0500 Subject: [PATCH 23/27] Refactor Local Archiving: Move YAML Logic to archive_vars.py and Handle Ensemble/Deterministic Archiving (#4298) - The archiving process includes two separate components: local archiving (arch_vrfy) and external tar creation (arch_tar). This issue focuses only on local archiving. This will handle: - Archiving of ensemble output files - Archiving of deterministic (control) output files - Logic, COM paths, and cycle-dependent variables currently defined in the YAML files ( `***_arcdir.yaml.j2`) will be moved into archive_vars.py. The YAML files will retain only the file-specific archiving definitions. --- dev/jobs/JGLOBAL_ARCHIVE_VRFY | 6 + dev/scripts/exglobal_archive_vrfy.py | 36 +---- dev/scripts/exglobal_enkf_earc_vrfy.py | 36 ++--- parm/archive/enkf_arcdir.yaml.j2 | 25 +++ parm/archive/gcafs_arcdir.yaml.j2 | 135 +++++----------- parm/archive/gefs_arcdir.yaml.j2 | 46 ++---- parm/archive/gfs_arcdir.yaml.j2 | 216 +++++++++---------------- ush/python/pygfs/task/archive.py | 6 +- ush/python/pygfs/utils/archive_vars.py | 186 +++++++++++++++++++++ 9 files changed, 378 insertions(+), 314 deletions(-) create mode 100644 parm/archive/enkf_arcdir.yaml.j2 create mode 100644 ush/python/pygfs/utils/archive_vars.py diff --git a/dev/jobs/JGLOBAL_ARCHIVE_VRFY b/dev/jobs/JGLOBAL_ARCHIVE_VRFY index e5965c22706..2e6e9a42d37 100755 --- a/dev/jobs/JGLOBAL_ARCHIVE_VRFY +++ b/dev/jobs/JGLOBAL_ARCHIVE_VRFY @@ -20,6 +20,12 @@ for grid in "0p25" "0p50" "1p00"; do "COMIN_ATMOS_GRIB_${grid}:COM_ATMOS_GRIB_GRID_TMPL" done +# GEFS-specific: Ensemble statistics path +if [[ "${RUN}" == "gefs" ]]; then + MEMDIR="ensstat" YMD=${PDY} HH=${cyc} GRID="1p00" declare_from_tmpl -rx \ + COMIN_ATMOS_ENSSTAT_1p00:COM_ATMOS_GRIB_GRID_TMPL +fi + ############################################################### # Run archive script ############################################################### diff --git a/dev/scripts/exglobal_archive_vrfy.py b/dev/scripts/exglobal_archive_vrfy.py index 5054908fc4d..634c1c1db34 100755 --- a/dev/scripts/exglobal_archive_vrfy.py +++ b/dev/scripts/exglobal_archive_vrfy.py @@ -3,6 +3,7 @@ import os from pygfs.task.archive import Archive +from pygfs.utils.archive_vars import ArchiveVrfyVars from wxflow import AttrDict, Logger, cast_strdict_as_dtypedict, logit, chdir # initialize root logger @@ -14,38 +15,17 @@ def main(): config = cast_strdict_as_dtypedict(os.environ) - # Instantiate the Archive object + # Instantiate the Archive task 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', - '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', 'DO_GSISOILDA', 'DO_LAND_IAU'] - - 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) + # Collect all archive variables in complete arch_dict for YAML templates + # Use static utility methods from ArchiveVrfyVars + arch_dict = ArchiveVrfyVars.get_all_yaml_vars(archive.task_config) - with chdir(config.ROTDIR): + # Pass arch_dict to configure_vrfy which will render the Jinja2 YAML + arcdir_set = archive.configure_vrfy(arch_dict) - # Determine which archives to create - arcdir_set = archive.configure_vrfy(archive_dict) + with chdir(config.ROTDIR): # Populate the product archive (ARCDIR) archive.execute_store_products(arcdir_set) diff --git a/dev/scripts/exglobal_enkf_earc_vrfy.py b/dev/scripts/exglobal_enkf_earc_vrfy.py index 973a4257b91..4315cf0ca69 100755 --- a/dev/scripts/exglobal_enkf_earc_vrfy.py +++ b/dev/scripts/exglobal_enkf_earc_vrfy.py @@ -3,6 +3,7 @@ import os from pygfs.task.archive import Archive +from pygfs.utils.archive_vars import ArchiveVrfyVars from wxflow import AttrDict, Logger, cast_strdict_as_dtypedict, chdir, logit # initialize root logger @@ -14,37 +15,20 @@ def main(): config = cast_strdict_as_dtypedict(os.environ) - # Instantiate the Archive object + # Instantiate the Archive task 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', - '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', 'DO_GSISOILDA', 'DO_LAND_IAU'] + # Collect all archive variables in complete arch_dict for YAML templates + # Use static utility methods from ArchiveVrfyVars + arch_dict = ArchiveVrfyVars.get_all_yaml_vars(archive.task_config) - 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!") + # Pass arch_dict to configure_vrfy which will render the Jinja2 YAML + arcdir_set = archive.configure_vrfy(arch_dict) - # Also import all COMIN* directory and template variables - for key in archive.task_config.keys(): - if key.startswith("COMIN"): - archive_dict[key] = archive.task_config[key] + with chdir(config.ROTDIR): - 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) + # Populate the product archive (ARCDIR) + archive.execute_store_products(arcdir_set) if __name__ == '__main__': diff --git a/parm/archive/enkf_arcdir.yaml.j2 b/parm/archive/enkf_arcdir.yaml.j2 new file mode 100644 index 00000000000..5219f035610 --- /dev/null +++ b/parm/archive/enkf_arcdir.yaml.j2 @@ -0,0 +1,25 @@ +# Variables provided by archive_vars.py: +# - cycle_HH, cycle_YMDH, cycle_YMD, head +# - ARCDIR +# - All COMIN_* paths + +# Ensemble (EnKF) archiving template +# Used for: enkfgdas, enkfgfs, enkfgcafs, enkfgcdas + +# Build head string (e.g., 'gfs.t00z.') +{% set head = RUN + ".t" + cycle_HH + "z." %} + +mkdir: + - "{{ ARCDIR }}" + +copy_opt: + # Ensemble analysis statistics + {% if DO_JEDIATMENS == True %} + - ["{{ COMIN_ATMOS_ANALYSIS_ENSSTAT }}/{{ head }}stat.atm.tar", + "{{ ARCDIR }}/atmensstat.{{ RUN }}.{{ cycle_YMDH }}"] + {% else %} + - ["{{ COMIN_ATMOS_ANALYSIS_ENSSTAT }}/{{ head }}enkfstat.txt", + "{{ ARCDIR }}/enkfstat.{{ RUN }}.{{ cycle_YMDH }}"] + - ["{{ COMIN_ATMOS_ANALYSIS_ENSSTAT }}/{{ head }}gsistat_ensmean.txt", + "{{ ARCDIR }}/gsistat.{{ RUN }}.{{ cycle_YMDH }}.ensmean"] + {% endif %} diff --git a/parm/archive/gcafs_arcdir.yaml.j2 b/parm/archive/gcafs_arcdir.yaml.j2 index 325ffba80e6..c7b3d8dff65 100644 --- a/parm/archive/gcafs_arcdir.yaml.j2 +++ b/parm/archive/gcafs_arcdir.yaml.j2 @@ -1,107 +1,58 @@ -{% set cycle_HH = current_cycle | strftime("%H") %} -{% set cycle_YMDH = current_cycle | to_YMDH %} -{% set cycle_YMD = current_cycle | to_YMD %} -{% set head = RUN + ".t" + cycle_HH + "z." %} - -# Select data to store in the ARCDIR and VFYARC from deterministic runs -# This file set will contain all source-destination pairs to send to the FileHandler for copying -{% set file_set = [] %} - -# Declare the VFYARC where Fit2Obs data will be sent -{% set VFYARC = ROTDIR ~ "/vrfyarch" %} +# Variables provided by archive_vars.py: +# - cycle_HH, cycle_YMDH, cycle_YMD, head +# - VFYARC +# - All COMIN_* paths -# Deterministic files -{% if "enkf" not in RUN %} - # Common files to be added to both the gcafs and gcdas keys below - {% set det_files = [] %} +# Deterministic GCAFS/GCDAS archiving template +# Used for: gcafs, gcdas - # Deterministic analysis files (generated for cycled experiments) - {% set det_anl_files = [] %} - - {% if DO_AERO_ANL %} - {% do det_anl_files.append([COMIN_CHEM_ANALYSIS ~ "/" ~ head ~ "aerostat.tgz", - ARCDIR ~ "/aerostat." ~ RUN ~ "." ~ cycle_YMDH ~ ".tgz"]) %} - {% endif %} +# Build head string (e.g., 'gfs.t00z.') +{% set head = RUN + ".t" + cycle_HH + "z." %} - {% if DO_PREP_OBS_AERO == True %} - {% do det_anl_files.append([COMIN_OBS ~ "/" ~ head ~ "aeroobs", - ARCDIR ~ "/aeroobs." ~ RUN ~ "." ~ cycle_YMDH]) %} - {% do det_anl_files.append([COMIN_OBS ~ "/" ~ head ~ "aeroawobs", - ARCDIR ~ "/aeroawobs." ~ RUN ~ "." ~ cycle_YMDH]) %} - {% endif %} +mkdir: + - "{{ ARCDIR }}" +{% if DO_FIT2OBS == True %} + - "{{ VFYARC }}/{{ RUN }}.{{ cycle_YMD }}/{{ cycle_HH }}" +{% endif %} - # GCAFS-specific files - {% set gfs_files = [] %} +copy_req: +{% if RUN == "gcafs" %} + # GCAFS forecast files - REQUIRED {% for fhr in range(0, FHMAX_GFS + 1, FHOUT_GFS) %} - {% do gfs_files.append([COMIN_ATMOS_GRIB_1p00 ~ "/" ~ head ~ "pres_a.1p00.f" ~ '%03d'|format(fhr) ~ ".grib2", - ARCDIR ~ "/pgbf" ~ '%02d'|format(fhr) ~ "." ~ RUN ~ "." ~ cycle_YMDH ~ ".grib2"]) %} + - ["{{ COMIN_ATMOS_GRIB_1p00 }}/{{ head }}pres_a.1p00.f{{ '%03d'|format(fhr) }}.grib2", + "{{ ARCDIR }}/pgbf{{ '%02d'|format(fhr) }}.{{ RUN }}.{{ cycle_YMDH }}.grib2"] {% endfor %} - # GCAFS Fit2Obs data - {% set fit2obs_files = [] %} - {% for fhr in range(0, FHMAX_FITS + 1, 6) %} - {% set sfcfile = "/" + head + "sfc.f" + '%03d'|format(fhr) + ".nc" %} - {% set sigfile = "/" + head + "atm.f" + '%03d'|format(fhr) + ".nc" %} - {% do fit2obs_files.append([COMIN_ATMOS_HISTORY ~ "/" ~ sfcfile, - VFYARC ~ "/" ~ RUN ~ "." ~ cycle_YMD ~ "/" ~ cycle_HH ~ "/" ~ sfcfile ]) %} - {% do fit2obs_files.append([COMIN_ATMOS_HISTORY ~ "/" ~ sigfile, - VFYARC ~ "/" ~ RUN ~ "." ~ cycle_YMD ~ "/" ~ cycle_HH ~ "/" ~ sigfile ]) %} - {% endfor %} + {% if DO_FIT2OBS == True %} + # GCAFS Fit2Obs data - REQUIRED if DO_FIT2OBS is enabled + {% for fhr in range(0, FHMAX_FITS + 1, 6) %} + - ["{{ COMIN_ATMOS_HISTORY }}/{{ head }}sfc.f{{ '%03d'|format(fhr) }}.nc", + "{{ VFYARC }}/{{ RUN }}.{{ cycle_YMD }}/{{ cycle_HH }}/{{ head }}sfc.f{{ '%03d'|format(fhr) }}.nc"] + - ["{{ COMIN_ATMOS_HISTORY }}/{{ head }}atm.f{{ '%03d'|format(fhr) }}.nc", + "{{ VFYARC }}/{{ RUN }}.{{ cycle_YMD }}/{{ cycle_HH }}/{{ head }}atm.f{{ '%03d'|format(fhr) }}.nc"] + {% endfor %} + {% endif %} +{% endif %} - # GCDAS-specific files - {% set gdas_files = [] %} +{% if RUN == "gcdas" %} + # GCDAS forecast files - REQUIRED {% for fhr in range(0, FHMAX + 1, FHOUT) %} - {% do gdas_files.append([COMIN_ATMOS_GRIB_1p00 ~ "/" ~ head ~ "pres_a.1p00.f" ~ '%03d'|format(fhr) ~ ".grib2", - ARCDIR ~ "/pgbf" ~ '%02d'|format(fhr) ~ "." ~ RUN ~ "." ~ cycle_YMDH ~ ".grib2"]) %} + - ["{{ COMIN_ATMOS_GRIB_1p00 }}/{{ head }}pres_a.1p00.f{{ '%03d'|format(fhr) }}.grib2", + "{{ ARCDIR }}/pgbf{{ '%02d'|format(fhr) }}.{{ RUN }}.{{ cycle_YMDH }}.grib2"] {% endfor %} +{% endif %} - # Now append the necessary file pairs to file_set - # Common deterministic files - {% set file_set = file_set + det_files %} - {% if MODE == "cycled" %} - {% set file_set = file_set + det_anl_files %} - {% endif %} - - # Run-specific deterministic files - {% if RUN == "gcafs" %} - {% set file_set = file_set + gfs_files %} - # Fit2Obs files - {% if DO_FIT2OBS == True %} - {% set file_set = file_set + fit2obs_files %} - {% endif %} - {% elif RUN == "gcdas" %} - {% set file_set = file_set + gdas_files %} +{% if MODE == "cycled" %} + # Deterministic analysis files (cycled mode only) - REQUIRED + {% if DO_AERO_ANL %} + - ["{{ COMIN_CHEM_ANALYSIS }}/{{ head }}aerostat.tgz", + "{{ ARCDIR }}/aerostat.{{ RUN }}.{{ cycle_YMDH }}.tgz"] {% endif %} -{% else %} # End of deterministic files - - # Ensemble analysis files - {% set enkf_files = [] %} - {% if DO_JEDIATMENS == True %} - {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "atmensstat", - ARCDIR ~ "/atmensstat." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% else %} - {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "enkfstat.txt", - ARCDIR ~ "/enkfstat." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "gsistat_ensmean.txt", - ARCDIR ~ "/gsistat." ~ RUN ~ "." ~ cycle_YMDH ~ ".ensmean"]) %} + {% if DO_PREP_OBS_AERO == True %} + - ["{{ COMIN_OBS }}/{{ head }}aeroobs", + "{{ ARCDIR }}/aeroobs.{{ RUN }}.{{ cycle_YMDH }}"] + - ["{{ COMIN_OBS }}/{{ head }}aeroawobs", + "{{ ARCDIR }}/aeroawobs.{{ RUN }}.{{ cycle_YMDH }}"] {% endif %} - - # Construct the final file set - {% set file_set = file_set + enkf_files %} - {% endif %} - - -# Actually write the yaml -mkdir: - - "{{ ARCDIR }}" - - {% if DO_FIT2OBS == True %} - - "{{ VFYARC }}/{{ RUN }}.{{ cycle_YMD }}/{{ cycle_HH }}" - {% endif %} - -copy: - {% for source_dest_pair in file_set %} - - {{ source_dest_pair }} - {% endfor %} diff --git a/parm/archive/gefs_arcdir.yaml.j2 b/parm/archive/gefs_arcdir.yaml.j2 index 2f8da8bd444..8be329861ec 100644 --- a/parm/archive/gefs_arcdir.yaml.j2 +++ b/parm/archive/gefs_arcdir.yaml.j2 @@ -1,36 +1,20 @@ -{% set cycle_HH = current_cycle | strftime("%H") %} -{% set cycle_YMDH = current_cycle | to_YMDH %} -{% set cycle_YMD = current_cycle | to_YMD %} -{% set head = RUN + ".t" + cycle_HH + "z." %} - -# Declare the GEFS_ARCH where atmos data will be sent -{% set GEFS_ARCH = ROTDIR ~ "/gefsarch" %} - -{% set file_set = [] %} +# Variables provided by archive_vars.py: +# - cycle_HH, cycle_YMDH, cycle_YMD, head +# - VFYARC (archive directory) +# - COMIN_ATMOS_ENSSTAT_1p00 (calculated in Python with MEMDIR='ensstat') -{% set tmpl_dict = ({ '${ROTDIR}':ROTDIR, - '${RUN}':RUN, - '${YMD}':cycle_YMD, - '${HH}':cycle_HH, - '${GRID}': '1p00', - '${MEMDIR}': 'ensstat' }) %} +# Build head string (e.g., 'gfs.t00z.') +{% set head = RUN + ".t" + cycle_HH + "z." %} -{% set COMIN_ATMOS_ENSSTAT_1p00 = COM_ATMOS_GRIB_GRID_TMPL | replace_tmpl(tmpl_dict) %} +# Create directories first +mkdir: + - "{{ VFYARC }}" -# Select ensstat files to copy to the arcdir -{% set ensstat_files = [] %} -{% if path_exists(COMIN_ATMOS_ENSSTAT_1p00) %} +# Define all source-destination pairs for archiving +# Use copy_req for files that MUST exist (raise error if missing) +copy_req: + # GEFS ensemble mean forecast files - REQUIRED {% for fhr in range(FHMIN_GFS, FHMAX_GFS + FHOUT_GFS, FHOUT_GFS) %} - {% do ensstat_files.append([COMIN_ATMOS_ENSSTAT_1p00 ~ "/" ~ head ~ "mean.pres_." ~ - "1p00" ~ ".f" ~ '%03d'|format(fhr) ~ ".grib2", - GEFS_ARCH]) %} + - ["{{ COMIN_ATMOS_ENSSTAT_1p00 }}/{{ head }}mean.pres_.1p00.f{{ '%03d'|format(fhr) }}.grib2", + "{{ VFYARC }}/{{ head }}mean.pres_.1p00.f{{ '%03d'|format(fhr) }}.grib2"] {% endfor %} -{% endif %} -{% set file_set = ensstat_files %} -# Actually write the yaml -mkdir: - - "{{ GEFS_ARCH }}" -copy: - {% for source_dest_pair in file_set %} - - {{ source_dest_pair }} - {% endfor %} diff --git a/parm/archive/gfs_arcdir.yaml.j2 b/parm/archive/gfs_arcdir.yaml.j2 index ed873b21c8b..9fffe5a1b7e 100644 --- a/parm/archive/gfs_arcdir.yaml.j2 +++ b/parm/archive/gfs_arcdir.yaml.j2 @@ -1,164 +1,108 @@ -{% set cycle_HH = current_cycle | strftime("%H") %} -{% set cycle_YMDH = current_cycle | to_YMDH %} -{% set cycle_YMD = current_cycle | to_YMD %} -{% set head = RUN + ".t" + cycle_HH + "z." %} - -# Select data to store in the ARCDIR and VFYARC from deterministic runs -# This file set will contain all source-destination pairs to send to the FileHandler for copying -{% set file_set = [] %} +# Variables provided by archive_vars.py: +# - cycle_HH, cycle_YMDH, cycle_YMD, head +# - VFYARC, GEFS_ARCH +# - All COMIN_* paths -# Declare the VFYARC where Fit2Obs data will be sent -{% set VFYARC = ROTDIR ~ "/vrfyarch" %} +# Deterministic GFS/GDAS archiving template +# Used for: gfs, gdas -# Deterministic files -{% if "enkf" not in RUN %} - # Common files to be added to both the gfs and gdas keys below - {% set det_files = [] %} - # Cyclone forecasts, produced for both gdas and gfs cycles - ## Only created if tracking is on and there were systems to track - {% if path_exists(COMIN_ATMOS_TRACK ~ "/atcfunix." ~ RUN ~ "." ~ cycle_YMDH) %} - {% do det_files.append([COMIN_ATMOS_TRACK ~ "/atcfunix." ~ RUN ~ "." ~ cycle_YMDH, - ARCDIR ~"/atcfunix." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% do det_files.append([COMIN_ATMOS_TRACK ~ "/atcfunixp." ~ RUN ~ "." ~ cycle_YMDH, - ARCDIR ~ "/atcfunixp." ~ RUN ~ "." ~ cycle_YMDH]) %} - {% endif %} +# Build head string (e.g., 'gfs.t00z.') +{% set head = RUN + ".t" + cycle_HH + "z." %} - # Cyclone tracking data - {% for basin in ["epac", "natl"] %} - {% if path_exists(COMIN_ATMOS_TRACK + "/" + basin) %} - {% do det_files.append([COMIN_ATMOS_TRACK ~ "/" ~ basin, - ARCDIR ~ "/" ~ basin ]) %} - {% endif %} - {% endfor %} +mkdir: + - "{{ ARCDIR }}" +{% if DO_FIT2OBS == True %} + - "{{ VFYARC }}/{{ RUN }}.{{ cycle_YMD }}/{{ cycle_HH }}" +{% endif %} - # Deterministic analysis files (generated for cycled experiments) - {% set det_anl_files = [] %} - # Analysis data (if we are running in cycled mode) - {% do det_anl_files.append([COMIN_ATMOS_GRIB_1p00 ~ "/" ~ head ~ "pres_a.1p00.analysis.grib2", - ARCDIR ~ "/pgbanl." ~ RUN ~ "." ~ cycle_YMDH ~ ".grib2"]) %} +copy_opt: +# Cyclone tracking files (optional - only exist when storms are tracked) + - ["{{ COMIN_ATMOS_TRACK }}/atcfunix.{{ RUN }}.{{ cycle_YMDH }}", + "{{ ARCDIR }}/atcfunix.{{ RUN }}.{{ cycle_YMDH }}"] + - ["{{ COMIN_ATMOS_TRACK }}/atcfunixp.{{ RUN }}.{{ cycle_YMDH }}", + "{{ ARCDIR }}/atcfunixp.{{ RUN }}.{{ cycle_YMDH }}"] + +# Cyclone tracking data by basin +{% for basin in ["epac", "natl"] %} + - ["{{ COMIN_ATMOS_TRACK }}/{{ basin }}", + "{{ ARCDIR }}/{{ basin }}"] +{% endfor %} + +{% if MODE == "cycled" %} + # Deterministic analysis files (cycled mode only) + - ["{{ COMIN_ATMOS_GRIB_1p00 }}/{{ head }}pres_a.1p00.analysis.grib2", + "{{ ARCDIR }}/pgbanl.{{ RUN }}.{{ cycle_YMDH }}.grib2"] {% if DO_JEDIATMVAR == True %} - {% do det_anl_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "stat.atm.tar", - ARCDIR ~ "/atmstat." ~ RUN ~ "." ~ cycle_YMDH ]) %} + - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ head }}stat.atm.tar", + "{{ ARCDIR }}/atmstat.{{ RUN }}.{{ cycle_YMDH }}"] {% else %} - {% do det_anl_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "gsistat.txt", - ARCDIR ~ "/gsistat." ~ RUN ~ "." ~ cycle_YMDH ]) %} + - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ head }}gsistat.txt", + "{{ ARCDIR }}/gsistat.{{ RUN }}.{{ cycle_YMDH }}"] {% endif %} {% if DO_JEDISNOWDA == True %} - {% do det_anl_files.append([COMIN_SNOW_ANALYSIS ~ "/" ~ head ~ "snow_analysis.ioda_hofx.tar", - ARCDIR ~ "/snowstat." ~ RUN ~ "." ~ cycle_YMDH ~ ".tar"]) %} + - ["{{ COMIN_SNOW_ANALYSIS }}/{{ head }}snow_analysis.ioda_hofx.tar", + "{{ ARCDIR }}/snowstat.{{ RUN }}.{{ cycle_YMDH }}.tar"] {% endif %} {% if DO_AERO_ANL %} - {% do det_anl_files.append([COMIN_CHEM_ANALYSIS ~ "/" ~ head ~ "aerostat.tgz", - ARCDIR ~ "/aerostat." ~ RUN ~ "." ~ cycle_YMDH ~ ".tgz"]) %} + - ["{{ COMIN_CHEM_ANALYSIS }}/{{ head }}aerostat.tgz", + "{{ ARCDIR }}/aerostat.{{ RUN }}.{{ cycle_YMDH }}.tgz"] {% endif %} {% if DO_PREP_OBS_AERO == True %} - {% do det_anl_files.append([COMIN_OBS ~ "/" ~ head ~ "aeroobs", - ARCDIR ~ "/aeroobs." ~ RUN ~ "." ~ cycle_YMDH]) %} - {% do det_anl_files.append([COMIN_OBS ~ "/" ~ head ~ "aeroawobs", - ARCDIR ~ "/aeroawobs." ~ RUN ~ "." ~ cycle_YMDH]) %} + - ["{{ COMIN_OBS }}/{{ head }}aeroobs", + "{{ ARCDIR }}/aeroobs.{{ RUN }}.{{ cycle_YMDH }}"] + - ["{{ COMIN_OBS }}/{{ head }}aeroawobs", + "{{ ARCDIR }}/aeroawobs.{{ RUN }}.{{ cycle_YMDH }}"] {% endif %} +{% endif %} - # GFS-specific files - {% set gfs_files = [] %} +{% if RUN == "gfs" %} + # GFS forecast files {% for fhr in range(0, FHMAX_GFS + 1, FHOUT_GFS) %} - {% do gfs_files.append([COMIN_ATMOS_GRIB_1p00 ~ "/" ~ head ~ "pres_a.1p00.f" ~ '%03d'|format(fhr) ~ ".grib2", - ARCDIR ~ "/pgbf" ~ '%02d'|format(fhr) ~ "." ~ RUN ~ "." ~ cycle_YMDH ~ ".grib2"]) %} + - ["{{ COMIN_ATMOS_GRIB_1p00 }}/{{ head }}pres_a.1p00.f{{ '%03d'|format(fhr) }}.grib2", + "{{ ARCDIR }}/pgbf{{ '%02d'|format(fhr) }}.{{ RUN }}.{{ cycle_YMDH }}.grib2"] {% endfor %} - # Cyclone genesis data (only present if there are storms) - {% if path_exists(COMIN_ATMOS_GENESIS ~ "/storms.gfso.atcf_gen." ~ cycle_YMDH) %} - {% do gfs_files.append([COMIN_ATMOS_GENESIS ~ "/storms.gfso.atcf_gen." ~ cycle_YMDH, - ARCDIR ~ "/storms.gfso.atcf_gen." ~ cycle_YMDH ]) %} - {% do gfs_files.append([COMIN_ATMOS_GENESIS ~ "/storms.gfso.atcf_gen.altg." ~ cycle_YMDH, - ARCDIR ~ "/storms.gfso.atcf_gen.altg." ~ cycle_YMDH ]) %} - {% endif %} - - {% if path_exists(COMIN_ATMOS_GENESIS ~ "/trak.gfso.atcfunix." ~ cycle_YMDH) %} - {% do gfs_files.append([COMIN_ATMOS_GENESIS ~ "/trak.gfso.atcfunix." ~ cycle_YMDH, - ARCDIR ~ "/trak.gfso.atcfunix." ~ cycle_YMDH ]) %} - {% do gfs_files.append([COMIN_ATMOS_GENESIS ~ "/trak.gfso.atcfunix.altg." ~ cycle_YMDH, - ARCDIR ~ "/trak.gfso.atcfunix.altg." ~ cycle_YMDH ]) %} - {% endif %} + - ["{{ COMIN_ATMOS_GENESIS }}/storms.gfso.atcf_gen.{{ cycle_YMDH }}", + "{{ ARCDIR }}/storms.gfso.atcf_gen.{{ cycle_YMDH }}"] + - ["{{ COMIN_ATMOS_GENESIS }}/storms.gfso.atcf_gen.altg.{{ cycle_YMDH }}", + "{{ ARCDIR }}/storms.gfso.atcf_gen.altg.{{ cycle_YMDH }}"] + - ["{{ COMIN_ATMOS_GENESIS }}/trak.gfso.atcfunix.{{ cycle_YMDH }}", + "{{ ARCDIR }}/trak.gfso.atcfunix.{{ cycle_YMDH }}"] + - ["{{ COMIN_ATMOS_GENESIS }}/trak.gfso.atcfunix.altg.{{ cycle_YMDH }}", + "{{ ARCDIR }}/trak.gfso.atcfunix.altg.{{ cycle_YMDH }}"] + {% if DO_FIT2OBS == True %} # GFS Fit2Obs data - {% set fit2obs_files = [] %} - {% for fhr in range(0, FHMAX_FITS + 1, 6) %} - {% set sfcfile = "/" + head + "sfc.f" + '%03d'|format(fhr) + ".nc" %} - {% set sigfile = "/" + head + "atm.f" + '%03d'|format(fhr) + ".nc" %} - {% do fit2obs_files.append([COMIN_ATMOS_HISTORY ~ "/" ~ sfcfile, - VFYARC ~ "/" ~ RUN ~ "." ~ cycle_YMD ~ "/" ~ cycle_HH ~ "/" ~ sfcfile ]) %} - {% do fit2obs_files.append([COMIN_ATMOS_HISTORY ~ "/" ~ sigfile, - VFYARC ~ "/" ~ RUN ~ "." ~ cycle_YMD ~ "/" ~ cycle_HH ~ "/" ~ sigfile ]) %} - {% endfor %} + {% for fhr in range(0, FHMAX_FITS + 1, 6) %} + {% set sfcfile = head + "sfc.f" + '%03d'|format(fhr) + ".nc" %} + {% set sigfile = head + "atm.f" + '%03d'|format(fhr) + ".nc" %} + - ["{{ COMIN_ATMOS_HISTORY }}/{{ sfcfile }}", + "{{ VFYARC }}/{{ RUN }}.{{ cycle_YMD }}/{{ cycle_HH }}/{{ sfcfile }}"] + - ["{{ COMIN_ATMOS_HISTORY }}/{{ sigfile }}", + "{{ VFYARC }}/{{ RUN }}.{{ cycle_YMD }}/{{ cycle_HH }}/{{ sigfile }}"] + {% endfor %} + {% endif %} - # GDAS-specific files - {% set gdas_files = [] %} +{% elif RUN == "gdas" %} + # GDAS forecast files {% for fhr in range(0, FHMAX + 1, FHOUT) %} - {% do gdas_files.append([COMIN_ATMOS_GRIB_1p00 ~ "/" ~ head ~ "pres_a.1p00.f" ~ '%03d'|format(fhr) ~ ".grib2", - ARCDIR ~ "/pgbf" ~ '%02d'|format(fhr) ~ "." ~ RUN ~ "." ~ cycle_YMDH ~ ".grib2"]) %} + - ["{{ COMIN_ATMOS_GRIB_1p00 }}/{{ head }}pres_a.1p00.f{{ '%03d'|format(fhr) }}.grib2", + "{{ ARCDIR }}/pgbf{{ '%02d'|format(fhr) }}.{{ RUN }}.{{ cycle_YMDH }}.grib2"] {% endfor %} - {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "abias.txt", - ARCDIR ~ "/abias." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "abias_pc.txt", - ARCDIR ~ "/abias_pc." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "abias_air.txt", - ARCDIR ~ "/abias_air." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "abias_int.txt", - ARCDIR ~ "/abias_int." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% do gdas_files.append([COMIN_ATMOS_ANALYSIS ~ "/" ~ head ~ "analysis.dtf.a006.nc", - ARCDIR ~ "/dtfanl." ~ RUN ~ "." ~ cycle_YMDH ~ ".nc"]) %} - - # Now append the necessary file pairs to file_set - # Common deterministic files - {% set file_set = file_set + det_files %} - {% if MODE == "cycled" %} - {% set file_set = file_set + det_anl_files %} - {% endif %} - - # Run-specific deterministic files - {% if RUN == "gfs" %} - {% set file_set = file_set + gfs_files %} - # Fit2Obs files - {% if DO_FIT2OBS == True %} - {% set file_set = file_set + fit2obs_files %} - {% endif %} - {% elif RUN == "gdas" %} - {% set file_set = file_set + gdas_files %} - {% endif %} - -{% else %} # End of deterministic files - - # Ensemble analysis files - {% set enkf_files = [] %} - {% if DO_JEDIATMENS == True %} - {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "stat.atm.tar", - ARCDIR ~ "/atmensstat." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% else %} - {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "enkfstat.txt", - ARCDIR ~ "/enkfstat." ~ RUN ~ "." ~ cycle_YMDH ]) %} - {% do enkf_files.append([COMIN_ATMOS_ANALYSIS_ENSSTAT ~ "/" ~ head ~ "gsistat_ensmean.txt", - ARCDIR ~ "/gsistat." ~ RUN ~ "." ~ cycle_YMDH ~ ".ensmean"]) %} - {% endif %} - - # Construct the final file set - {% set file_set = file_set + enkf_files %} + # GDAS bias correction files + - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ head }}abias.txt", + "{{ ARCDIR }}/abias.{{ RUN }}.{{ cycle_YMDH }}"] + - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ head }}abias_pc.txt", + "{{ ARCDIR }}/abias_pc.{{ RUN }}.{{ cycle_YMDH }}"] + - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ head }}abias_air.txt", + "{{ ARCDIR }}/abias_air.{{ RUN }}.{{ cycle_YMDH }}"] + - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ head }}abias_int.txt", + "{{ ARCDIR }}/abias_int.{{ RUN }}.{{ cycle_YMDH }}"] + - ["{{ COMIN_ATMOS_ANALYSIS }}/{{ head }}analysis.dtf.a006.nc", + "{{ ARCDIR }}/dtfanl.{{ RUN }}.{{ cycle_YMDH }}.nc"] {% endif %} - - -# Actually write the yaml -mkdir: - - "{{ ARCDIR }}" - - {% if DO_FIT2OBS == True %} - - "{{ VFYARC }}/{{ RUN }}.{{ cycle_YMD }}/{{ cycle_HH }}" - {% endif %} - -copy_opt: - {% for source_dest_pair in file_set %} - - {{ source_dest_pair }} - {% endfor %} diff --git a/ush/python/pygfs/task/archive.py b/ush/python/pygfs/task/archive.py index d6a60364041..389075472e2 100644 --- a/ush/python/pygfs/task/archive.py +++ b/ush/python/pygfs/task/archive.py @@ -72,7 +72,11 @@ def configure_vrfy(self, arch_dict: Dict[str, Any]) -> (Dict[str, Any]): archive_parm = os.path.join(arch_dict.PARMgfs, "archive") # Collect the dataset to archive locally - arcdir_j2yaml = os.path.join(archive_parm, f"{arch_dict.NET}_arcdir.yaml.j2") + # Select template based on RUN type: ensemble (enkf) or deterministic (NET) + if "enkf" in arch_dict.RUN: + arcdir_j2yaml = os.path.join(archive_parm, "enkf_arcdir.yaml.j2") + else: + arcdir_j2yaml = os.path.join(archive_parm, f"{arch_dict.NET}_arcdir.yaml.j2") # Add the glob.glob function for capturing log filenames arch_dict['glob'] = glob.glob diff --git a/ush/python/pygfs/utils/archive_vars.py b/ush/python/pygfs/utils/archive_vars.py new file mode 100644 index 00000000000..182d918e996 --- /dev/null +++ b/ush/python/pygfs/utils/archive_vars.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python3 +""" +Archive Variables Utility Module + +Overview +-------- +This module provides utility functions to collect variables needed by YAML templates +for archiving verification (vrfy) data for GFS, GEFS, and GCAFS systems. File set +generation logic (loops, conditionals, path construction) is handled by the YAML +templates themselves. + +Architecture +------------ +Python provides VARIABLES → YAML templates build FILE SETS + +Python Code Responsibilities: + - Compute cycle-specific variables (cycle_HH, cycle_YMDH, cycle_YMD, head) + - Calculate COM directory paths with grid loops (0p25, 0p50, 1p00) + - Extract configuration keys (RUN, DO_* flags, FHMAX*, etc.) + +YAML Template Responsibilities (parm/archive/*_arcdir.yaml.j2): + - Build file sets with source → destination mappings + - Handle loops (forecast hours, grids, basins) + - Apply conditionals (DO_* flags, MODE, RUN type) + - Create mkdir lists for directory creation + +Key Functions +------------- +get_all_yaml_vars(config_dict): + Main entry point - collects all variables for YAML templates + +add_config_vars(config_dict): + Extracts configuration keys and COM* variables (created in job scripts) + +_get_cycle_vars(config_dict): + Computes cycle-specific variables (cycle_HH, cycle_YMDH, cycle_YMD, head) + +Logging +------- +All public operational functions are decorated with @logit(logger). +""" +import os +from logging import getLogger +from typing import Any, Dict +from wxflow import AttrDict, logit, to_YMD, to_YMDH + +logger = getLogger(__name__.split('.')[-1]) + + +class ArchiveVrfyVars: + """ + Utility class for collecting archive verification variables. + + This class provides variables for YAML templates that handle archiving + for three systems: + - GFS: Global Forecast System + - GEFS: Global Ensemble Forecast System + - GCAFS: Global Climate Analysis Forecast System + + The YAML templates (parm/archive/*_arcdir.yaml.j2) contain all file set + generation logic. This class only provides the variables they need. + """ + + @staticmethod + @logit(logger) + def get_all_yaml_vars(config_dict: AttrDict) -> Dict[str, Any]: + """Collect all variables needed for YAML templates. + + This method provides only the VARIABLES needed by the YAML templates + (cycle vars, COM paths, config keys). + + Parameters + ---------- + config_dict : AttrDict + Configuration dictionary from Archive.task_config + + Returns + ------- + Dict[str, Any] + Dictionary containing variables for Jinja2 templates: + - cycle_HH, cycle_YMDH, cycle_YMD, head: Cycle-specific variables + - COMIN_*, COMOUT_*, COM_*: All COM directory paths (from job scripts) + - Config keys: RUN, PSLOT, ROTDIR, DO_* flags, FHMAX*, etc. + """ + # Build arch_dict with variables for Jinja2 templates + arch_dict = AttrDict() + + # Add config variables (config keys, COM* variables from job scripts) + arch_dict.update(ArchiveVrfyVars.add_config_vars(config_dict)) + + # Add cycle-specific variables + arch_dict.update(ArchiveVrfyVars._get_cycle_vars(config_dict)) + + logger.info(f"Collected {len(arch_dict)} variables for YAML templates") + logger.debug(f"arch_dict keys: {list(arch_dict.keys())}") + + return arch_dict + + @staticmethod + @logit(logger) + def add_config_vars(config_dict: AttrDict) -> Dict[str, Any]: + """Collect configuration keys and COM* variables for archive operations. + + Formats resolution variables (OCNRES, ICERES) to 3 digits and extracts + all configuration keys and COM* directory paths needed for archiving. + + Parameters + ---------- + config_dict : AttrDict + Configuration dictionary from Archive.task_config + + Returns + ------- + Dict[str, Any] + Dictionary with config keys and all COM_*, COMIN_*, COMOUT_* variables + """ + general_dict = {} + + # Update resolution keys to be 3 digits if they are part of config_dict + for key in ['OCNRES', 'ICERES']: + if key in config_dict: + config_dict[key] = f"{config_dict[key]:03d}" + + # Configuration keys to extract (if present) + config_keys = ['current_cycle', 'RUN', 'PSLOT', 'ROTDIR', 'PARMgfs', + 'ARCDIR', 'MODE', 'DO_JEDIATMENS', 'DO_FIT2OBS', 'DO_JEDIATMVAR', + 'DO_JEDISNOWDA', 'DO_AERO_ANL', 'DO_PREP_OBS_AERO', 'NET', + 'FHOUT_GFS', 'FHMAX_HF_GFS', 'FHMAX_FITS', 'FHMAX', 'FHOUT', + 'FHMAX_GFS', 'DO_GSISOILDA', 'DO_LAND_IAU'] + + # Add FHMIN_GFS only if RUN does not contain 'enkf' + if 'enkf' not in config_dict.get('RUN', ''): + config_keys.append('FHMIN_GFS') + + # Extract keys if they exist in config_dict + for key in config_keys: + if key in config_dict: + general_dict[key] = config_dict[key] + else: + logger.warning(f"Config key '{key}' not found in config_dict; skipping.") + + # Import COM* directory and template variables created by job scripts + # Job scripts use declare_from_tmpl -rx which exports variables to environment + for key in config_dict.keys(): + if key.startswith(("COM_", "COMIN_", "COMOUT_")): + general_dict[key] = config_dict.get(key) + + logger.info(f"Collected {len(general_dict)} general archive variables") + logger.debug(f"General variables: {list(general_dict.keys())}") + + return general_dict + + @staticmethod + @logit(logger) + def _get_cycle_vars(config_dict: AttrDict) -> Dict[str, Any]: + """Calculate cycle-specific variables. + + Parameters + ---------- + config_dict : AttrDict + Configuration dictionary from Archive.task_config + + Returns + ------- + Dict[str, Any] + Dictionary containing: + - cycle_HH: Cycle hour (e.g., '00', '06') + - cycle_YMDH: Full cycle timestamp (YYYYMMDDHH) + - cycle_YMD: Cycle date (YYYYMMDD) + - head: System head designation (e.g., 'gfs.t00z.') + - VFYARC: Verification archive directory (ROTDIR/vrfyarch) + """ + current_cycle = config_dict.current_cycle + cycle_HH = current_cycle.strftime("%H") + cycle_YMDH = to_YMDH(current_cycle) + cycle_YMD = to_YMD(current_cycle) + + # Archive directory (used by all systems) + VFYARC = os.path.join(config_dict.ROTDIR, "vrfyarch") + + return { + 'cycle_HH': cycle_HH, + 'cycle_YMDH': cycle_YMDH, + 'cycle_YMD': cycle_YMD, + 'VFYARC': VFYARC + } From ebd2615542a2b47bc32f9dd8390f0c73b4bffa80 Mon Sep 17 00:00:00 2001 From: David Huber <69919478+DavidHuber-NOAA@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:50:37 +0000 Subject: [PATCH 24/27] Add escape dependencies for *gdas cleanup jobs before the first gfs cycle (#4305) # Description This adds dependencies on the `gdas_cleanup` and `enkfgdas_cleanup` jobs when `SDATE_gfs` several cycles beyond `SDATE` to prevent the cleanup jobs from never executing. Resolves #4262 # Type of change - [x] Bug fix (fixes something broken) # Change characteristics - Is this change expected to change outputs (e.g. value changes to existing outputs, new files stored in COM, files removed from COM, filename changes, additions/subtractions to archives)? NO - Is this a breaking change (a change in existing functionality)? NO - Does this change require a documentation update? NO - Does this change require an update to any of the following submodules? NO # How has this been tested? Generated a full suite of XMLs and checked the output databases. Generated an additional XML with `SDATE=2021122018`, `SDATE_gfs=2021122500` and `EDATE=2021123100` and verified the dependency matrix. # Checklist - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] My changes generate no new warnings - [x] New and existing tests pass with my changes - [x] This change is covered by an existing CI test or a new one has been added --- .github/ISSUE_TEMPLATE/bug_report.yml | 1 - .github/ISSUE_TEMPLATE/new_feature.yml | 1 - dev/parm/config/gcafs/config.base.j2 | 2 -- dev/parm/config/gefs/config.base.j2 | 2 -- dev/parm/config/gfs/config.base.j2 | 2 -- dev/parm/config/sfs/config.base.j2 | 2 -- dev/workflow/rocoto/gfs_tasks.py | 43 ++++++++++++++++++++------ 7 files changed, 33 insertions(+), 20 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 3e5e84d2d08..308a8585f20 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,6 +1,5 @@ name: Bug Report description: Report something that is incorrect or broken -labels: ["triage"] type: "bug" projects: ["NOAA-EMC/41"] diff --git a/.github/ISSUE_TEMPLATE/new_feature.yml b/.github/ISSUE_TEMPLATE/new_feature.yml index fee7d641e8f..512c0395ad7 100644 --- a/.github/ISSUE_TEMPLATE/new_feature.yml +++ b/.github/ISSUE_TEMPLATE/new_feature.yml @@ -1,6 +1,5 @@ name: New Feature description: New capability is desired -labels: ["triage"] type: "feature" projects: ["NOAA-EMC/41"] diff --git a/dev/parm/config/gcafs/config.base.j2 b/dev/parm/config/gcafs/config.base.j2 index a4c1e8b72fc..c091f269c62 100644 --- a/dev/parm/config/gcafs/config.base.j2 +++ b/dev/parm/config/gcafs/config.base.j2 @@ -148,8 +148,6 @@ source "${EXPDIR}/config.com" export LOGSCRIPT=${LOGSCRIPT:-""} #export LOGSCRIPT=${LOGSCRIPT:-"startmsg"} -export REDOUT="1>" -export REDERR="2>" export SENDECF=${SENDECF:-"NO"} export SENDSDM=${SENDSDM:-"NO"} diff --git a/dev/parm/config/gefs/config.base.j2 b/dev/parm/config/gefs/config.base.j2 index 56a924fe104..a44ca83d6aa 100644 --- a/dev/parm/config/gefs/config.base.j2 +++ b/dev/parm/config/gefs/config.base.j2 @@ -111,8 +111,6 @@ source "${EXPDIR}/config.com" export LOGSCRIPT=${LOGSCRIPT:-""} #export LOGSCRIPT=${LOGSCRIPT:-"startmsg"} -export REDOUT="1>" -export REDERR="2>" export SENDECF=${SENDECF:-"NO"} export SENDSDM=${SENDSDM:-"NO"} diff --git a/dev/parm/config/gfs/config.base.j2 b/dev/parm/config/gfs/config.base.j2 index 1b703918fb9..a624674aceb 100644 --- a/dev/parm/config/gfs/config.base.j2 +++ b/dev/parm/config/gfs/config.base.j2 @@ -144,8 +144,6 @@ source "${EXPDIR}/config.com" export LOGSCRIPT=${LOGSCRIPT:-""} #export LOGSCRIPT=${LOGSCRIPT:-"startmsg"} -export REDOUT="1>" -export REDERR="2>" export SENDECF=${SENDECF:-"NO"} export SENDSDM=${SENDSDM:-"NO"} diff --git a/dev/parm/config/sfs/config.base.j2 b/dev/parm/config/sfs/config.base.j2 index bff4c3be6ce..860f892ce15 100644 --- a/dev/parm/config/sfs/config.base.j2 +++ b/dev/parm/config/sfs/config.base.j2 @@ -110,8 +110,6 @@ source "${EXPDIR}/config.com" export LOGSCRIPT=${LOGSCRIPT:-""} #export LOGSCRIPT=${LOGSCRIPT:-"startmsg"} -export REDOUT="1>" -export REDERR="2>" export SENDECF=${SENDECF:-"NO"} export SENDSDM=${SENDSDM:-"NO"} diff --git a/dev/workflow/rocoto/gfs_tasks.py b/dev/workflow/rocoto/gfs_tasks.py index f3e7c3d3e69..690bc3cb16a 100644 --- a/dev/workflow/rocoto/gfs_tasks.py +++ b/dev/workflow/rocoto/gfs_tasks.py @@ -2385,14 +2385,37 @@ def globus_earc(self): # Cleanup def cleanup(self): - deps = [] - dep_dict = {'type': 'task', 'name': 'gfs_fcst_seg0', 'offset': - f"{timedelta_to_HMS(self._base['interval_gfs'])}"} - deps.append(rocoto.add_dependency(dep_dict)) - dep_dict = {'type': 'cycleexist', 'condition': 'not', - 'offset': f"{timedelta_to_HMS(self._base['interval_gfs'])}"} - deps.append(rocoto.add_dependency(dep_dict)) - dep_next_fcst_seg = rocoto.create_dependency(dep_condition='or', dep=deps) + + # Build a dependency on the next GFS forecast. + # This will only be used for GDAS/ENKFGDAS cycles with 6-hourly GFS intervals + # to prevent clobbering files needed by the GFS forecast prematurely. + assim_freq = self._base.get('assim_freq', 6) + interval_gfs = int(self._base.get('INTERVAL_GFS', 0)) + if interval_gfs >= assim_freq: + deps = [] + dep_dict = {'type': 'task', 'name': 'gfs_fcst_seg0', 'offset': + f"{timedelta_to_HMS(self._base['interval_gfs'])}"} + deps.append(rocoto.add_dependency(dep_dict)) + dep_dict = {'type': 'cycleexist', 'condition': 'not', + 'offset': f"{timedelta_to_HMS(self._base['interval_gfs'])}"} + deps.append(rocoto.add_dependency(dep_dict)) + # Only start checking this if we are at/past the first GFS cycle + sdate_gfs = self._base.get('SDATE_GFS') + sdate = self._base.get('SDATE') + if sdate_gfs: + n_cycles = int((sdate_gfs - sdate).total_seconds() // 3600 // assim_freq) + # Start at the first full cycle (1 cycle after SDATE) + # End two cycles before SDATE_gfs + # One cycle before SDATE_gfs must depend on the next forecast segment. + for cycle in range(1, n_cycles - 1): + offset = timedelta_to_HMS(to_timedelta(f'{cycle * assim_freq}H')) + skip_date = (sdate + to_timedelta(f'{cycle * assim_freq}H')).strftime("%Y%m%d%H") + dep_dict = {'type': 'streq', 'left': '@Y@m@d@H', 'right': skip_date} + deps.append(rocoto.add_dependency(dep_dict)) + + dep_next_fcst_seg = rocoto.create_dependency(dep_condition='or', dep=deps) + + # Now start building RUN-specific dependencies deps = [] if 'enkf' in self.run: dep_dict = {'type': 'task', 'name': f'{self.run}_earc_vrfy'} @@ -2403,7 +2426,7 @@ def cleanup(self): else: dep_dict = {'type': 'metatask', 'name': f'{self.run}_earc_tars'} deps.append(rocoto.add_dependency(dep_dict)) - if self.run in ['enkfgdas'] and self._base["INTERVAL_GFS"] == 6: + if self.run in ['enkfgdas'] and interval_gfs == assim_freq: deps.append(dep_next_fcst_seg) else: @@ -2415,7 +2438,7 @@ def cleanup(self): dep_dict = {'type': 'task', 'name': f'{self.run}_vminmon'} deps.append(rocoto.add_dependency(dep_dict)) elif self.run in ['gdas']: - if self._base["INTERVAL_GFS"] == 6: + if interval_gfs == assim_freq: deps.append(dep_next_fcst_seg) dep_dict = {'type': 'task', 'name': f'{self.run}_atmanlprod'} deps.append(rocoto.add_dependency(dep_dict)) From 4e03e8adca9c15ea4e0075f2dc42f91fa21edca7 Mon Sep 17 00:00:00 2001 From: Taylor Roper Date: Thu, 11 Dec 2025 04:54:45 -0700 Subject: [PATCH 25/27] Update noaacloud data paths to come from lustre mount linked to noaa-nws-global-pds bucket (#4301) This updates the noaacloud data paths to come from an FSx for Lustre mount provisioned with a data repository association to the S3 bucket [noaa-nws-global-pds](https://noaa-nws-global-pds.s3.amazonaws.com/index.html). --- dev/workflow/hosts/awspw.yaml | 10 +++++----- modulefiles/gw_run.noaacloud.lua | 2 +- sorc/link_workflow.sh | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/workflow/hosts/awspw.yaml b/dev/workflow/hosts/awspw.yaml index d3c9cbd9172..1f2aca56e40 100644 --- a/dev/workflow/hosts/awspw.yaml +++ b/dev/workflow/hosts/awspw.yaml @@ -1,16 +1,16 @@ # Paths -IODADIR: '/bucket/dump' -DMPDIR: '/bucket/dump' +IODADIR: '/lustre/dump_ur' +DMPDIR: '/lustre/dump_ur' BASE_GIT: '/contrib/git' -BASE_DATA: '/bucket/global-workflow-shared-data' -BASE_IC: '/bucket/global-workflow-shared-data/ICSDIR' +BASE_DATA: '/lustre/data' +BASE_IC: '/lustre/data/ICSDIR' AERO_INPUTS_DIR: '/contrib/global-workflow-shared-data/data/GEFS_ExtData/20250310' PACKAGEROOT: '' #TODO: This does not yet exist. HOMEDIR: '/contrib/${USER}' STMP: '/lustre/${USER}/stmp/' PTMP: '/lustre/${USER}/ptmp/' NOSCRUB: '${HOMEDIR}' -COMINsyn: '/bucket/syndat' +COMINsyn: '/lustre/syndat' # BQS properties SCHEDULER: slurm QUEUE: batch diff --git a/modulefiles/gw_run.noaacloud.lua b/modulefiles/gw_run.noaacloud.lua index 4f7da7cd202..99eb924bed1 100644 --- a/modulefiles/gw_run.noaacloud.lua +++ b/modulefiles/gw_run.noaacloud.lua @@ -24,6 +24,6 @@ load(pathJoin("fit2obs", (os.getenv("fit2obs_ver") or "None"))) load(pathJoin("imagemagick", (os.getenv("imagemagick_ver") or "None"))) -setenv("CRTM_FIX", "/contrib/global-workflow-shared-data/fix/crtm/v2.4.0.2") +setenv("CRTM_FIX", "/lustre/fix/crtm/v2.4.0.2") whatis("Description: GFS run environment") diff --git a/sorc/link_workflow.sh b/sorc/link_workflow.sh index f1d44cce281..207b23188fc 100755 --- a/sorc/link_workflow.sh +++ b/sorc/link_workflow.sh @@ -76,7 +76,7 @@ case "${machine}" in "hercules") FIX_DIR="/work2/noaa/global/role-global/fix" ;; "gaeac5") FIX_DIR="/gpfs/f5/ufs-ard/world-shared/global/glopara/data/fix" ;; "gaeac6") FIX_DIR="/gpfs/f6/drsa-precip3/world-shared/role.glopara/fix" ;; -"noaacloud") FIX_DIR="/contrib/global-workflow-shared-data/fix" ;; +"noaacloud") FIX_DIR="/lustre/fix" ;; *) echo "FATAL: Unknown target machine ${machine}, couldn't set FIX_DIR" exit 1 From ac94b9a63ee5f13074a0cde70530080984b6718a Mon Sep 17 00:00:00 2001 From: Jessica Meixner Date: Fri, 12 Dec 2025 07:26:09 -0500 Subject: [PATCH 26/27] Update for ufs-weather-model (#4314) Updating ufs-weather-model, in particular for two updates for GFSv17. --- sorc/ufs_model.fd | 2 +- ush/parsing_namelists_CICE.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sorc/ufs_model.fd b/sorc/ufs_model.fd index 2a33f2c8ee2..6f22f57403d 160000 --- a/sorc/ufs_model.fd +++ b/sorc/ufs_model.fd @@ -1 +1 @@ -Subproject commit 2a33f2c8ee265e75d5df18b652a23bf674528899 +Subproject commit 6f22f57403db693dee3b6979a4e6f58ade633e86 diff --git a/ush/parsing_namelists_CICE.sh b/ush/parsing_namelists_CICE.sh index 2815db5a022..6bcb52cc10a 100755 --- a/ush/parsing_namelists_CICE.sh +++ b/ush/parsing_namelists_CICE.sh @@ -67,6 +67,7 @@ CICE_namelists() { local CICE_RESTART_REARR="box" local CICE_RESTART_IOTASKS=-99 local CICE_RESTART_FORMAT="pnetcdf2" + local CICE_RESTART_MOD='none' local CICE_DUMPFREQ="y" # "h","d","m" or "y" for restarts at intervals of "hours", "days", "months" or "years" local CICE_DUMPFREQ_N=10000 # Set this to a really large value, as cice, mom6 and cmeps restart interval is controlled by ufs.configure local CICE_DIAGFREQ=$((86400 / DT_CICE)) # frequency of diagnostic output in timesteps, recommended for 1x per day From 2c767b35bbfa26e15662757d04c29f9fb550835d Mon Sep 17 00:00:00 2001 From: "jessica.meixner" Date: Fri, 12 Dec 2025 09:22:05 -0500 Subject: [PATCH 27/27] update gdasapp hash --- sorc/gdas.cd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorc/gdas.cd b/sorc/gdas.cd index 887b7efb9aa..740245c65a2 160000 --- a/sorc/gdas.cd +++ b/sorc/gdas.cd @@ -1 +1 @@ -Subproject commit 887b7efb9aaaa26cf4ad0eead0b4b73306df64b3 +Subproject commit 740245c65a2ac036ea1778bb8c1870493b2d3204