From 6f1693081662f241fafc930b1afc88125f7f5aff Mon Sep 17 00:00:00 2001 From: Kate Friedman Date: Tue, 14 Nov 2023 11:15:02 -0500 Subject: [PATCH 1/3] Refine fit2obs job in rocoto mesh (#2047) This PR adjusts the `fit2obs` job in the rocoto mesh to better define when it exists and how the archive job dependencies accommodate it not being in the first half cycle. Changes in PR: 1. Remove the `fit2obs` job from the first half cycle `cycledef`. 2. Adjust the archive job dependencies to now include the `fit2obs` job in the new logic check added in PR #1983. The `gdasarch` job in the first half cycle will check if `gdasfit2obs` is complete OR no prior cycle exists. Also cleaned up this new logic check block some to make it a tad simpler. 3. Also, fix the addition of the `fit2obs` config to the config list in setup scripts. Now tied to whether `fit2obs` job is on instead of always adding the config to the list. Resolves #2043 --- workflow/applications/gfs_cycled.py | 5 ++- workflow/rocoto/gfs_tasks.py | 52 +++++++++++++---------------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/workflow/applications/gfs_cycled.py b/workflow/applications/gfs_cycled.py index cdb5e18f3e..3b8472d3c8 100644 --- a/workflow/applications/gfs_cycled.py +++ b/workflow/applications/gfs_cycled.py @@ -47,7 +47,7 @@ def _get_app_configs(self): if self.do_ocean: configs += ['ocnpost'] - configs += ['sfcanl', 'analcalc', 'fcst', 'post', 'vrfy', 'fit2obs', 'arch', 'cleanup'] + configs += ['sfcanl', 'analcalc', 'fcst', 'post', 'vrfy', 'arch', 'cleanup'] if self.do_hybvar: if self.do_jediatmens: @@ -56,6 +56,9 @@ def _get_app_configs(self): configs += ['eobs', 'eomg', 'ediag', 'eupd'] configs += ['ecen', 'esfc', 'efcs', 'echgres', 'epos', 'earc'] + if self.do_fit2obs: + configs += ['fit2obs'] + if self.do_verfozn: configs += ['verfozn'] diff --git a/workflow/rocoto/gfs_tasks.py b/workflow/rocoto/gfs_tasks.py index 4843ef68a8..24d31521c2 100644 --- a/workflow/rocoto/gfs_tasks.py +++ b/workflow/rocoto/gfs_tasks.py @@ -922,11 +922,8 @@ def fit2obs(self): deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep=deps) - cycledef = 'gdas_half,gdas' if self.cdump in ['gdas'] else self.cdump - resources = self.get_resource('fit2obs') - task = create_wf_task('fit2obs', resources, cdump=self.cdump, envar=self.envars, dependency=dependencies, - cycledef=cycledef) + task = create_wf_task('fit2obs', resources, cdump=self.cdump, envar=self.envars, dependency=dependencies) return task @@ -957,33 +954,32 @@ def metp(self): def arch(self): deps = [] dependencies = [] - if self.app_config.do_verfozn or self.app_config.do_verfrad or self.app_config.do_vminmon: - if self.app_config.mode in ['cycled']: - if self.cdump in ['gfs']: - if self.app_config.do_vminmon: - dep_dict = {'type': 'task', 'name': f'{self.cdump}vminmon'} - deps.append(rocoto.add_dependency(dep_dict)) - elif self.cdump in ['gdas']: - deps2 = [] - if self.app_config.do_verfozn: - dep_dict = {'type': 'task', 'name': f'{self.cdump}verfozn'} - deps2.append(rocoto.add_dependency(dep_dict)) - if self.app_config.do_verfrad: - dep_dict = {'type': 'task', 'name': f'{self.cdump}verfrad'} - deps2.append(rocoto.add_dependency(dep_dict)) - if self.app_config.do_vminmon: - dep_dict = {'type': 'task', 'name': f'{self.cdump}vminmon'} - deps2.append(rocoto.add_dependency(dep_dict)) - dependencies = rocoto.create_dependency(dep_condition='and', dep=deps2) - dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': '-06:00:00'} - dependencies.append(rocoto.add_dependency(dep_dict)) - dependencies = rocoto.create_dependency(dep_condition='or', dep=dependencies) + if self.app_config.mode in ['cycled']: + if self.cdump in ['gfs']: + if self.app_config.do_vminmon: + dep_dict = {'type': 'task', 'name': f'{self.cdump}vminmon'} + deps.append(rocoto.add_dependency(dep_dict)) + elif self.cdump in ['gdas']: # Block for handling half cycle dependencies + deps2 = [] + if self.app_config.do_fit2obs: + dep_dict = {'type': 'task', 'name': f'{self.cdump}fit2obs'} + deps2.append(rocoto.add_dependency(dep_dict)) + if self.app_config.do_verfozn: + dep_dict = {'type': 'task', 'name': f'{self.cdump}verfozn'} + deps2.append(rocoto.add_dependency(dep_dict)) + if self.app_config.do_verfrad: + dep_dict = {'type': 'task', 'name': f'{self.cdump}verfrad'} + deps2.append(rocoto.add_dependency(dep_dict)) + if self.app_config.do_vminmon: + dep_dict = {'type': 'task', 'name': f'{self.cdump}vminmon'} + deps2.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep_condition='and', dep=deps2) + dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': '-06:00:00'} + dependencies.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep_condition='or', dep=dependencies) if self.app_config.do_vrfy: dep_dict = {'type': 'task', 'name': f'{self.cdump}vrfy'} deps.append(rocoto.add_dependency(dep_dict)) - if self.cdump in ['gdas'] and self.app_config.do_fit2obs: - dep_dict = {'type': 'task', 'name': f'{self.cdump}fit2obs'} - deps.append(rocoto.add_dependency(dep_dict)) if self.app_config.do_wave: dep_dict = {'type': 'task', 'name': f'{self.cdump}wavepostsbs'} deps.append(rocoto.add_dependency(dep_dict)) From 2cd6a589305a9ac9d3a9a0d2136e66e42f09d3bf Mon Sep 17 00:00:00 2001 From: "Henry R. Winterbottom" <49202169+HenryWinterbottom-NOAA@users.noreply.github.com> Date: Tue, 14 Nov 2023 12:05:20 -0700 Subject: [PATCH 2/3] Moves UFS WM configuration files to `COM_CONF` (#2054) The UFS weather-model (WM) files are place in the COM_CONF path rather than the respective component model COM history paths. Resolves #2015 --- jobs/JGLOBAL_FORECAST | 2 +- scripts/exgdas_enkf_fcst.sh | 2 +- ush/forecast_postdet.sh | 9 ++++++--- ush/forecast_predet.sh | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/jobs/JGLOBAL_FORECAST b/jobs/JGLOBAL_FORECAST index e42c81eaa4..b2825af54f 100755 --- a/jobs/JGLOBAL_FORECAST +++ b/jobs/JGLOBAL_FORECAST @@ -46,7 +46,7 @@ declare -rx gcyc="${GDATE:8:2}" # Construct COM variables from templates (see config.com) YMD=${PDY} HH=${cyc} generate_com -rx COM_ATMOS_RESTART COM_ATMOS_INPUT COM_ATMOS_ANALYSIS \ - COM_ATMOS_HISTORY COM_ATMOS_MASTER COM_TOP + COM_ATMOS_HISTORY COM_ATMOS_MASTER COM_TOP COM_CONF RUN=${rCDUMP} YMD="${gPDY}" HH="${gcyc}" generate_com -rx \ COM_ATMOS_RESTART_PREV:COM_ATMOS_RESTART_TMPL diff --git a/scripts/exgdas_enkf_fcst.sh b/scripts/exgdas_enkf_fcst.sh index 7eb2a3a711..fd6136ddd2 100755 --- a/scripts/exgdas_enkf_fcst.sh +++ b/scripts/exgdas_enkf_fcst.sh @@ -131,7 +131,7 @@ for imem in $(seq "${ENSBEG}" "${ENSEND}"); do # Construct COM variables from templates (see config.com) # Can't make these read-only because we are looping over members MEMDIR="${memchar}" YMD=${PDY} HH=${cyc} generate_com -x COM_ATMOS_RESTART COM_ATMOS_INPUT COM_ATMOS_ANALYSIS \ - COM_ATMOS_HISTORY COM_ATMOS_MASTER + COM_ATMOS_HISTORY COM_ATMOS_MASTER COM_CONF MEMDIR="${memchar}" YMD="${gPDY}" HH="${gcyc}" generate_com -x COM_ATMOS_RESTART_PREV:COM_ATMOS_RESTART_TMPL diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index bafa61dd0e..ac59fcacac 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -514,7 +514,10 @@ FV3_out() { done else # No need to copy FV3 restart files when RUN=gfs or gefs - ${NCP} "${DATA}/input.nml" "${COM_ATMOS_HISTORY}/input.nml" + ${NCP} "${DATA}/input.nml" "${COM_CONF}/ufs.input.nml" + ${NCP} "${DATA}/model_configure" "${COM_CONF}/ufs.model_configure" + ${NCP} "${DATA}/nems.configure" "${COM_CONF}/ufs.nems.configure" + ${NCP} "${DATA}/diag_table" "${COM_CONF}/ufs.diag_table" fi echo "SUB ${FUNCNAME[0]}: Output data for FV3 copied" } @@ -853,7 +856,7 @@ MOM6_out() { # Copy MOM_input from DATA to COM_OCEAN_INPUT after the forecast is run (and successfull) if [[ ! -d ${COM_OCEAN_INPUT} ]]; then mkdir -p "${COM_OCEAN_INPUT}"; fi - ${NCP} "${DATA}/INPUT/MOM_input" "${COM_OCEAN_INPUT}/" + ${NCP} "${DATA}/INPUT/MOM_input" "${COM_CONF}/ufs.MOM_input" # TODO: mediator should have its own CMEPS_out() function # Copy mediator restarts from DATA to COM @@ -991,7 +994,7 @@ CICE_out() { # Copy ice_in namelist from DATA to COMOUTice after the forecast is run (and successfull) if [[ ! -d "${COM_ICE_INPUT}" ]]; then mkdir -p "${COM_ICE_INPUT}"; fi - ${NCP} "${DATA}/ice_in" "${COM_ICE_INPUT}/ice_in" + ${NCP} "${DATA}/ice_in" "${COM_CONF}/ufs.ice_in" } GOCART_rc() { diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index ce0b50f818..84d377019a 100755 --- a/ush/forecast_predet.sh +++ b/ush/forecast_predet.sh @@ -88,7 +88,7 @@ common_predet(){ tcyc=${scyc} fi - + mkdir -p "${COM_CONF}" cd "${DATA}" || ( echo "FATAL ERROR: Unable to 'cd ${DATA}', ABORT!"; exit 8 ) } From 0a0d6984e094d2a551d5d8331102142e7db13fc2 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Tue, 14 Nov 2023 14:08:26 -0500 Subject: [PATCH 3/3] Enable warm starting of the model for forecast-only mode (#2031) This PR: - adds an option to warm|cold start the ufs-weather-model when setting up an experiment for GFS/GEFS - adds the capability to stage FV3 restarts when the atmosphere is warm started from FV3 restarts. This would be used in the GEFS free-forecast for part of the reforecast capability. - If a coupled model is warm started for the atmosphere, also check if mediator restarts are present. If so, stage mediator restarts to allow restarting the coupled model. Fixes #2016 --- ci/cases/pr/C48_S2SA_gefs.yaml | 2 +- parm/config/gefs/config.base.emc.dyn | 7 +- scripts/exglobal_stage_ic.sh | 102 +++++++++++++++++++-------- workflow/setup_expt.py | 3 +- 4 files changed, 82 insertions(+), 32 deletions(-) diff --git a/ci/cases/pr/C48_S2SA_gefs.yaml b/ci/cases/pr/C48_S2SA_gefs.yaml index 927a979b13..2abbf0043e 100644 --- a/ci/cases/pr/C48_S2SA_gefs.yaml +++ b/ci/cases/pr/C48_S2SA_gefs.yaml @@ -9,9 +9,9 @@ arguments: resens: 48 nens: 2 gfs_cyc: 1 + start: cold comrot: {{ 'RUNTESTS' | getenv }}/COMROT expdir: {{ 'RUNTESTS' | getenv }}/EXPDIR - icsdir: {{ 'ICSDIR_ROOT' | getenv }}/C48C48mx500 idate: 2021032312 edate: 2021032312 yaml: {{ HOMEgfs }}/ci/platforms/gefs_ci_defaults.yaml diff --git a/parm/config/gefs/config.base.emc.dyn b/parm/config/gefs/config.base.emc.dyn index b62c921ed0..04fc396e5a 100644 --- a/parm/config/gefs/config.base.emc.dyn +++ b/parm/config/gefs/config.base.emc.dyn @@ -282,11 +282,16 @@ export NMEM_ENS=@NMEM_ENS@ export ENSMEM="000" export MEMDIR="mem${ENSMEM}" +export DOIAU="NO" # While we are not doing IAU, we may want to warm start w/ IAU in the future # Check if cycle is cold starting if [[ "${EXP_WARM_START}" = ".false." ]]; then - export IAU_FHROT=0 + export IAU_FHROT=0 else + if [[ "${DOIAU}" = "YES" ]]; then export IAU_FHROT=3 + else + export IAU_FHROT=0 + fi fi # turned on nsst in anal and/or fcst steps, and turn off rtgsst diff --git a/scripts/exglobal_stage_ic.sh b/scripts/exglobal_stage_ic.sh index 53042c7e45..6276255167 100755 --- a/scripts/exglobal_stage_ic.sh +++ b/scripts/exglobal_stage_ic.sh @@ -9,9 +9,9 @@ gPDY="${GDATE:0:8}" gcyc="${GDATE:8:2}" MEMDIR_ARRAY=() -if [[ "${RUN}" == "gefs" ]]; then +if [[ "${RUN:-}" = "gefs" ]]; then # Populate the member_dirs array based on the value of NMEM_ENS - for ((ii = 0; ii <= "${NMEM_ENS}"; ii++)); do + for ((ii = 0; ii <= "${NMEM_ENS:-0}"; ii++)); do MEMDIR_ARRAY+=("mem$(printf "%03d" "${ii}")") done else @@ -27,35 +27,58 @@ error_message() { ############################################################### for MEMDIR in "${MEMDIR_ARRAY[@]}"; do - # Stage the FV3 initial conditions to ROTDIR (cold start) - YMD=${PDY} HH=${cyc} generate_com COM_ATMOS_INPUT - [[ ! -d "${COM_ATMOS_INPUT}" ]] && mkdir -p "${COM_ATMOS_INPUT}" - src="${BASE_CPLIC}/${CPL_ATMIC}/${PDY}${cyc}/${MEMDIR}/atmos/gfs_ctrl.nc" - tgt="${COM_ATMOS_INPUT}/gfs_ctrl.nc" - ${NCP} "${src}" "${tgt}" - rc=$? - ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" - err=$((err + rc)) - for ftype in gfs_data sfc_data; do - for ((tt = 1; tt <= 6; tt++)); do - src="${BASE_CPLIC}/${CPL_ATMIC}/${PDY}${cyc}/${MEMDIR}/atmos/${ftype}.tile${tt}.nc" - tgt="${COM_ATMOS_INPUT}/${ftype}.tile${tt}.nc" - ${NCP} "${src}" "${tgt}" - rc=$? - tgt="${COM_ATMOS_INPUT}/${ftype}.tile${tt}.nc" + + # Stage atmosphere initial conditions to ROTDIR + if [[ ${EXP_WARM_START:-".false."} = ".true." ]]; then + # Stage the FV3 restarts to ROTDIR (warm start) + RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_ATMOS_RESTART_PREV:COM_ATMOS_RESTART_TMPL + [[ ! -d "${COM_ATMOS_RESTART_PREV}" ]] && mkdir -p "${COM_ATMOS_RESTART_PREV}" + for ftype in coupler.res fv_core.res.nc; do + src="${BASE_CPLIC}/${CPL_ATMIC:-}/${PDY}${cyc}/${MEMDIR}/atmos/${PDY}.${cyc}0000.${ftype}" + tgt="${COM_ATMOS_RESTART_PREV}/${PDY}.${cyc}0000.${ftype}" ${NCP} "${src}" "${tgt}" rc=$? ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" err=$((err + rc)) done - done + for ftype in ca_data fv_core.res fv_srf_wnd.res fv_tracer.res phy_data sfc_data; do + for ((tt = 1; tt <= 6; tt++)); do + src="${BASE_CPLIC}/${CPL_ATMIC:-}/${PDY}${cyc}/${MEMDIR}/atmos/${PDY}.${cyc}0000.${ftype}.tile${tt}.nc" + tgt="${COM_ATMOS_RESTART_PREV}/${PDY}.${cyc}0000.${ftype}.tile${tt}.nc" + ${NCP} "${src}" "${tgt}" + rc=$? + ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" + err=$((err + rc)) + done + done + else + # Stage the FV3 cold-start initial conditions to ROTDIR + YMD=${PDY} HH=${cyc} generate_com COM_ATMOS_INPUT + [[ ! -d "${COM_ATMOS_INPUT}" ]] && mkdir -p "${COM_ATMOS_INPUT}" + src="${BASE_CPLIC}/${CPL_ATMIC:-}/${PDY}${cyc}/${MEMDIR}/atmos/gfs_ctrl.nc" + tgt="${COM_ATMOS_INPUT}/gfs_ctrl.nc" + ${NCP} "${src}" "${tgt}" + rc=$? + ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" + err=$((err + rc)) + for ftype in gfs_data sfc_data; do + for ((tt = 1; tt <= 6; tt++)); do + src="${BASE_CPLIC}/${CPL_ATMIC:-}/${PDY}${cyc}/${MEMDIR}/atmos/${ftype}.tile${tt}.nc" + tgt="${COM_ATMOS_INPUT}/${ftype}.tile${tt}.nc" + ${NCP} "${src}" "${tgt}" + rc=$? + ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" + err=$((err + rc)) + done + done + fi # Stage ocean initial conditions to ROTDIR (warm start) if [[ "${DO_OCN:-}" = "YES" ]]; then - RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_OCEAN_RESTART - [[ ! -d "${COM_OCEAN_RESTART}" ]] && mkdir -p "${COM_OCEAN_RESTART}" - src="${BASE_CPLIC}/${CPL_OCNIC}/${PDY}${cyc}/${MEMDIR}/ocean/${PDY}.${cyc}0000.MOM.res.nc" - tgt="${COM_OCEAN_RESTART}/${PDY}.${cyc}0000.MOM.res.nc" + RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_OCEAN_RESTART_PREV:COM_OCEAN_RESTART_TMPL + [[ ! -d "${COM_OCEAN_RESTART_PREV}" ]] && mkdir -p "${COM_OCEAN_RESTART_PREV}" + src="${BASE_CPLIC}/${CPL_OCNIC:-}/${PDY}${cyc}/${MEMDIR}/ocean/${PDY}.${cyc}0000.MOM.res.nc" + tgt="${COM_OCEAN_RESTART_PREV}/${PDY}.${cyc}0000.MOM.res.nc" ${NCP} "${src}" "${tgt}" rc=$? ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" @@ -66,7 +89,7 @@ for MEMDIR in "${MEMDIR_ARRAY[@]}"; do ;; "025" ) for nn in $(seq 1 3); do - src="${BASE_CPLIC}/${CPL_OCNIC}/${PDY}${cyc}/${MEMDIR}/ocean/${PDY}.${cyc}0000.MOM.res_${nn}.nc" + src="${BASE_CPLIC}/${CPL_OCNIC:-}/${PDY}${cyc}/${MEMDIR}/ocean/${PDY}.${cyc}0000.MOM.res_${nn}.nc" tgt="${COM_OCEAN_RESTART}/${PDY}.${cyc}0000.MOM.res_${nn}.nc" ${NCP} "${src}" "${tgt}" rc=$? @@ -80,13 +103,33 @@ for MEMDIR in "${MEMDIR_ARRAY[@]}"; do err=$((err + rc)) ;; esac + + # TODO: Do mediator restarts exists in a ATMW configuration? + # TODO: No mediator is presumably involved in an ATMA configuration + if [[ ${EXP_WARM_START:-".false."} = ".true." ]]; then + # Stage the mediator restarts to ROTDIR (warm start/restart the coupled model) + RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_MED_RESTART_PREV:COM_MED_RESTART_TMPL + [[ ! -d "${COM_MED_RESTART_PREV}" ]] && mkdir -p "${COM_MED_RESTART_PREV}" + src="${BASE_CPLIC}/${CPL_MEDIC:-}/${PDY}${cyc}/${MEMDIR}/med/${PDY}.${cyc}0000.ufs.cpld.cpl.r.nc" + tgt="${COM_MED_RESTART_PREV}/${PDY}.${cyc}0000.ufs.cpld.cpl.r.nc" + if [[ -f "${src}" ]]; then + ${NCP} "${src}" "${tgt}" + rc=$? + ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" + err=$((err + rc)) + else + echo "WARNING: No mediator restarts available with warm_start=${EXP_WARM_START}" + fi + fi + fi + # Stage ice initial conditions to ROTDIR (warm start) if [[ "${DO_ICE:-}" = "YES" ]]; then - RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_ICE_RESTART - [[ ! -d "${COM_ICE_RESTART}" ]] && mkdir -p "${COM_ICE_RESTART}" - src="${BASE_CPLIC}/${CPL_ICEIC}/${PDY}${cyc}/${MEMDIR}/ice/${PDY}.${cyc}0000.cice_model.res.nc" - tgt="${COM_ICE_RESTART}/${PDY}.${cyc}0000.cice_model.res.nc" + RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_ICE_RESTART_PREV:COM_ICE_RESTART_TMPL + [[ ! -d "${COM_ICE_RESTART_PREV}" ]] && mkdir -p "${COM_ICE_RESTART_PREV}" + src="${BASE_CPLIC}/${CPL_ICEIC:-}/${PDY}${cyc}/${MEMDIR}/ice/${PDY}.${cyc}0000.cice_model.res.nc" + tgt="${COM_ICE_RESTART_PREV}/${PDY}.${cyc}0000.cice_model.res.nc" ${NCP} "${src}" "${tgt}" rc=$? ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" @@ -98,7 +141,7 @@ for MEMDIR in "${MEMDIR_ARRAY[@]}"; do YMD=${PDY} HH=${cyc} generate_com COM_WAVE_RESTART [[ ! -d "${COM_WAVE_RESTART}" ]] && mkdir -p "${COM_WAVE_RESTART}" for grdID in ${waveGRD}; do # TODO: check if this is a bash array; if so adjust - src="${BASE_CPLIC}/${CPL_WAVIC}/${PDY}${cyc}/${MEMDIR}/wave/${PDY}.${cyc}0000.restart.${grdID}" + src="${BASE_CPLIC}/${CPL_WAVIC:-}/${PDY}${cyc}/${MEMDIR}/wave/${PDY}.${cyc}0000.restart.${grdID}" tgt="${COM_WAVE_RESTART}/${PDY}.${cyc}0000.restart.${grdID}" ${NCP} "${src}" "${tgt}" rc=$? @@ -108,6 +151,7 @@ for MEMDIR in "${MEMDIR_ARRAY[@]}"; do fi done # for MEMDIR in "${MEMDIR_ARRAY[@]}"; do + ############################################################### # Check for errors and exit if any of the above failed if [[ "${err}" -ne 0 ]]; then diff --git a/workflow/setup_expt.py b/workflow/setup_expt.py index a808cafd91..b1fa439052 100755 --- a/workflow/setup_expt.py +++ b/workflow/setup_expt.py @@ -432,7 +432,8 @@ def _gfs_or_gefs_forecast_args(parser): return parser def _gefs_args(parser): - parser.add_argument('--start', help=SUPPRESS, type=str, required=False, default='cold') + parser.add_argument('--start', help='restart mode: warm or cold', type=str, + choices=['warm', 'cold'], required=False, default='cold') parser.add_argument('--configdir', help=SUPPRESS, type=str, required=False, default=os.path.join(_top, 'parm/config/gefs')) parser.add_argument('--yaml', help='Defaults to substitute from', type=str, required=False,