diff --git a/parm/config/gefs/config.base.emc.dyn b/parm/config/gefs/config.base.emc.dyn index 051a2188c3..0b19da2a36 100644 --- a/parm/config/gefs/config.base.emc.dyn +++ b/parm/config/gefs/config.base.emc.dyn @@ -220,9 +220,10 @@ export gfs_cyc=@gfs_cyc@ # 0: no GFS cycle, 1: 00Z only, 2: 00Z and 12Z only, 4: export FHMIN_GFS=0 export FHMIN=${FHMIN_GFS} export FHMAX_GFS=@FHMAX_GFS@ -export FHOUT_GFS=6 # Must be 6 for S2S until #1629 is addressed; 3 for ops +export FHOUT_GFS=6 export FHMAX_HF_GFS=0 export FHOUT_HF_GFS=1 +export FHOUT_OCNICE_GFS=6 if (( gfs_cyc != 0 )); then export STEP_GFS=$(( 24 / gfs_cyc )) else diff --git a/parm/config/gefs/config.fcst b/parm/config/gefs/config.fcst index 6a2a852e0b..74a84e1173 100644 --- a/parm/config/gefs/config.fcst +++ b/parm/config/gefs/config.fcst @@ -27,6 +27,7 @@ export FHMAX=${FHMAX_GFS} export FHOUT=${FHOUT_GFS} export FHMAX_HF=${FHMAX_HF_GFS} export FHOUT_HF=${FHOUT_HF_GFS} +export FHOUT_OCNICE=${FHOUT_OCNICE_GFS} # Get task specific resources source "${EXPDIR}/config.resources" fcst diff --git a/parm/config/gfs/config.base.emc.dyn b/parm/config/gfs/config.base.emc.dyn index 16aed843ba..5c02b000ef 100644 --- a/parm/config/gfs/config.base.emc.dyn +++ b/parm/config/gfs/config.base.emc.dyn @@ -248,6 +248,7 @@ fi export FHMIN=0 export FHMAX=9 export FHOUT=3 # Will be changed to 1 in config.base if (DOHYBVAR set to NO and l4densvar set to false) +export FHOUT_OCNICE=3 # Cycle to run EnKF (set to BOTH for both gfs and gdas) export EUPD_CYC="gdas" @@ -258,9 +259,10 @@ export gfs_cyc=@gfs_cyc@ # 0: no GFS cycle, 1: 00Z only, 2: 00Z and 12Z only, 4: # GFS output and frequency export FHMIN_GFS=0 export FHMAX_GFS=@FHMAX_GFS@ -export FHOUT_GFS=6 # Must be 6 for S2S until #1629 is addressed; 3 for ops +export FHOUT_GFS=3 # Must be 6 for S2S until #1629 is addressed; 3 for ops export FHMAX_HF_GFS=0 export FHOUT_HF_GFS=1 +export FHOUT_OCNICE_GFS=6 if (( gfs_cyc != 0 )); then export STEP_GFS=$(( 24 / gfs_cyc )) else diff --git a/parm/config/gfs/config.fcst b/parm/config/gfs/config.fcst index d2e2664e9c..c03c97e56f 100644 --- a/parm/config/gfs/config.fcst +++ b/parm/config/gfs/config.fcst @@ -30,6 +30,7 @@ case ${RUN} in export FHOUT=${FHOUT_GFS} export FHMAX_HF=${FHMAX_HF_GFS} export FHOUT_HF=${FHOUT_HF_GFS} + export FHOUT_OCNICE=${FHOUT_OCNICE_GFS} ;; *gdas) export FHMAX_HF=0 diff --git a/parm/ufs/fv3/diag_table b/parm/ufs/fv3/diag_table index b972b3470c..47106cb294 100644 --- a/parm/ufs/fv3/diag_table +++ b/parm/ufs/fv3/diag_table @@ -1,7 +1,7 @@ "fv3_history", 0, "hours", 1, "hours", "time" "fv3_history2d", 0, "hours", 1, "hours", "time" -"ocn%4yr%2mo%2dy%2hr", 6, "hours", 1, "hours", "time", 6, "hours", "1901 1 1 0 0 0" -"ocn_daily%4yr%2mo%2dy", 1, "days", 1, "days", "time", 1, "days", "1901 1 1 0 0 0" +"ocn%4yr%2mo%2dy%2hr", @[FHOUT_OCNICE], "hours", 1, "hours", "time", @[FHOUT_OCNICE], "hours", "@[SYEAR] @[SMONTH] @[SDAY] @[CHOUR] 0 0" +"ocn_daily%4yr%2mo%2dy", 1, "days", 1, "days", "time", 1, "days", "@[SYEAR] @[SMONTH] @[SDAY] @[CHOUR] 0 0" ############## # Ocean fields diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index 1aaa1a4b9d..ab02270b46 100755 --- a/ush/forecast_predet.sh +++ b/ush/forecast_predet.sh @@ -229,7 +229,7 @@ CICE_predet(){ # Convert output settings into an explicit list for CICE # Ignore "not used" warning # shellcheck disable=SC2034 - CICE_OUTPUT_FH=$(seq -s ' ' "${FHMIN}" "${FHOUT}" "${FHMAX}") + CICE_OUTPUT_FH=$(seq -s ' ' "${FHMIN}" "${FHOUT_OCNICE}" "${FHMAX}") } @@ -247,7 +247,7 @@ MOM6_predet(){ # Convert output settings into an explicit list for MOM6 # Ignore "not used" warning # shellcheck disable=SC2034 - MOM6_OUTPUT_FH=$(seq -s ' ' "${FHMIN}" "${FHOUT}" "${FHMAX}") + MOM6_OUTPUT_FH=$(seq -s ' ' "${FHMIN}" "${FHOUT_OCNICE}" "${FHMAX}") } diff --git a/ush/parsing_namelists_CICE.sh b/ush/parsing_namelists_CICE.sh index 3f1798d3e9..2dab096d16 100755 --- a/ush/parsing_namelists_CICE.sh +++ b/ush/parsing_namelists_CICE.sh @@ -62,7 +62,7 @@ local CICE_RESTART_FILE="cice_model.res" 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=6 -local CICE_HISTFREQ_N="0, 0, ${FHOUT}, 1, 1" +local CICE_HISTFREQ_N="0, 0, ${FHOUT_OCNICE}, 1, 1" if [[ "${RUN}" =~ "gdas" ]]; then local CICE_HIST_AVG=".false., .false., .false., .false., .false." # DA needs instantaneous else diff --git a/ush/parsing_namelists_FV3.sh b/ush/parsing_namelists_FV3.sh index 83e0c10525..88a0065076 100755 --- a/ush/parsing_namelists_FV3.sh +++ b/ush/parsing_namelists_FV3.sh @@ -9,6 +9,8 @@ ## This script is a direct execution. ##### +# Disable variable not used warnings +# shellcheck disable=SC2034 FV3_namelists(){ # setup the tables @@ -33,7 +35,15 @@ if [[ -n "${AERO_DIAG_TABLE:-}" ]]; then cat "${AERO_DIAG_TABLE}" fi cat "${DIAG_TABLE_APPEND}" -} >> diag_table +} >> 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} +source "${HOMEgfs}/ush/atparse.bash" +atparse < "${template}" >> "diag_table" # copy data table diff --git a/ush/python/pygfs/task/oceanice_products.py b/ush/python/pygfs/task/oceanice_products.py index 968acb0750..c865a9f408 100644 --- a/ush/python/pygfs/task/oceanice_products.py +++ b/ush/python/pygfs/task/oceanice_products.py @@ -61,7 +61,7 @@ def __init__(self, config: Dict[str, Any]) -> None: # TODO: This is a bit of a hack, but it works for now # FIXME: find a better way to provide the averaging period # This will be different for ocean and ice, so when they are made flexible, this will need to be addressed - avg_period = f"{self.config.FORECAST_HOUR-self.config.FHOUT_GFS:03d}-{self.config.FORECAST_HOUR:03d}" + avg_period = f"{self.config.FORECAST_HOUR-self.config.FHOUT_OCNICE_GFS:03d}-{self.config.FORECAST_HOUR:03d}" localdict = AttrDict( {'component': self.config.COMPONENT, diff --git a/workflow/rocoto/gfs_tasks.py b/workflow/rocoto/gfs_tasks.py index 83623f42d2..dd5b0cd551 100644 --- a/workflow/rocoto/gfs_tasks.py +++ b/workflow/rocoto/gfs_tasks.py @@ -929,19 +929,7 @@ def atmanlprod(self): @staticmethod def _get_ufs_postproc_grps(cdump, config, component='atmos'): - # Make a local copy of the config to avoid modifying the original - local_config = config.copy() - - # Ocean/Ice components do not have a HF output option like the atmosphere - if component in ['ocean', 'ice']: - local_config['FHMAX_HF_GFS'] = config['FHMAX_GFS'] - local_config['FHOUT_HF_GFS'] = config['FHOUT_GFS'] - - fhrs = Tasks._get_forecast_hours(cdump, local_config) - - # ocean/ice components do not have fhr 0 as they are averaged output - if component in ['ocean', 'ice']: - fhrs.remove(0) + fhrs = Tasks._get_forecast_hours(cdump, config, component=component) nfhrs_per_grp = config.get('NFHRS_PER_GROUP', 1) ngrps = len(fhrs) // nfhrs_per_grp if len(fhrs) % nfhrs_per_grp == 0 else len(fhrs) // nfhrs_per_grp + 1 diff --git a/workflow/rocoto/tasks.py b/workflow/rocoto/tasks.py index 540f6ebe47..77847133a9 100644 --- a/workflow/rocoto/tasks.py +++ b/workflow/rocoto/tasks.py @@ -120,23 +120,37 @@ def _template_to_rocoto_cycstring(self, template: str, subs_dict: dict = {}) -> rocoto_conversion_dict.get) @staticmethod - def _get_forecast_hours(cdump, config) -> List[str]: - fhmin = config['FHMIN'] - fhmax = config['FHMAX'] - fhout = config['FHOUT'] + def _get_forecast_hours(cdump, config, component='atmos') -> List[str]: + # Make a local copy of the config to avoid modifying the original + local_config = config.copy() + + # Ocean/Ice components do not have a HF output option like the atmosphere + if component in ['ocean', 'ice']: + local_config['FHMAX_HF_GFS'] = config['FHMAX_GFS'] + local_config['FHOUT_HF_GFS'] = config['FHOUT_OCNICE_GFS'] + local_config['FHOUT_GFS'] = config['FHOUT_OCNICE_GFS'] + local_config['FHOUT'] = config['FHOUT_OCNICE'] + + fhmin = local_config['FHMIN'] + fhmax = local_config['FHMAX'] + fhout = local_config['FHOUT'] # Get a list of all forecast hours fhrs = [] if cdump in ['gdas']: fhrs = list(range(fhmin, fhmax + fhout, fhout)) elif cdump in ['gfs', 'gefs']: - fhmax = config['FHMAX_GFS'] - fhout = config['FHOUT_GFS'] - fhmax_hf = config['FHMAX_HF_GFS'] - fhout_hf = config['FHOUT_HF_GFS'] + fhmax = local_config['FHMAX_GFS'] + fhout = local_config['FHOUT_GFS'] + fhmax_hf = local_config['FHMAX_HF_GFS'] + fhout_hf = local_config['FHOUT_HF_GFS'] fhrs_hf = range(fhmin, fhmax_hf + fhout_hf, fhout_hf) fhrs = list(fhrs_hf) + list(range(fhrs_hf[-1] + fhout, fhmax + fhout, fhout)) + # ocean/ice components do not have fhr 0 as they are averaged output + if component in ['ocean', 'ice']: + fhrs.remove(0) + return fhrs def get_resource(self, task_name):