Skip to content

Commit

Permalink
Change fcst segments to breakpoints, move to config.fcst
Browse files Browse the repository at this point in the history
Changes the way forecast segments are defined. Restores the original
`FHMIN_GFS` and `FHMAX_GFS` and then adds a local `breakpnts` variable
that contains the intermediate stopping points (if any). The original
list of segment endpoints is then constructed from that.

The determination of the `FHMIN` and `FHMAX` based on the segment is
moved from `config.base` to `config.fcst`. This required adding some
additional checks in `config.fcst` to clip other `FHMAX` variables to
`FHMAX`.
  • Loading branch information
WalterKolczynski-NOAA committed Jul 29, 2024
1 parent eb17358 commit d9f01cb
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 38 deletions.
19 changes: 6 additions & 13 deletions parm/config/gefs/config.base
Original file line number Diff line number Diff line change
Expand Up @@ -233,19 +233,12 @@ export FHOUT_ICE=3
export gfs_cyc=@gfs_cyc@ # 0: no GFS cycle, 1: 00Z only, 2: 00Z and 12Z only, 4: all 4 cycles.

# GFS output and frequency
# Forecast hour intervals to run the forecast over
# For a single-segment forecast, this is simply "$FHMIN_GFS,$FHMAX_GFS"
export FCST_SEGMENTS_STR_GFS="@FCST_SEGMENTS_GFS@"
IFS=', ' read -ra FCST_SEGMENTS_GFS <<< "${FCST_SEGMENTS_STR_GFS}"
if (( ${FCST_SEGMENT:- -1} < 0 )); then
# Jobs other than the forecast don't care about segments, only the
# absolute start and end
declare -x FHMIN_GFS=${FCST_SEGMENTS_GFS[0]}
declare -x FHMAX_GFS=${FCST_SEGMENTS_GFS[-1]}
else
declare -x FHMIN_GFS=${FCST_SEGMENTS_GFS[${FCST_SEGMENT}]}
declare -x FHMAX_GFS=${FCST_SEGMENTS_GFS[${FCST_SEGMENT}+1]}
fi
export FHMIN_GFS=0
export FHMAX_GFS="@FHMAX_GFS@"
# Intermediate times to stop forecast when running in segments
breakpnts="@FCST_BREAKPOINTS@"
export FCST_SEGMENTS="${FHMIN_GFS},${breakpnts:+${breakpnts},}${FHMAX_GFS}"

export FHOUT_GFS=6
export FHMAX_HF_GFS=@FHMAX_HF_GFS@
export FHOUT_HF_GFS=1
Expand Down
14 changes: 9 additions & 5 deletions parm/config/gefs/config.fcst
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,19 @@ string="--fv3 ${CASE}"
# shellcheck disable=SC2086
source "${EXPDIR}/config.ufs" ${string}

export FHMIN=${FHMIN_GFS}
# shellcheck disable=SC2153
export FHMAX=${FHMAX_GFS}
# Convert comma-separated string into bash array
IFS=', ' read -ra segments <<< "${FCST_SEGMENTS}"
# Determine MIN and MAX based on the forecast segment
export FHMIN=${segments[${FCST_SEGMENT}]}
export FHMAX=${segments[${FCST_SEGMENT}+1]}
# Cap other FHMAX variables at FHMAX for the segment
export FHMAX_HF=$(( FHMAX_HF_GFS > FHMAX ? FHMAX : FHMAX_HF_GFS ))
export FHMAX_WAV=$(( FHMAX_WAV > FHMAX ? FHMAX : FHMAX_WAV ))
# shellcheck disable=SC2153
export FHOUT=${FHOUT_GFS}
export FHMAX_HF=${FHMAX_HF_GFS}
export FHOUT_HF=${FHOUT_HF_GFS}
export FHOUT_OCN=${FHOUT_OCN_GFS}
export FHOUT_ICE=${FHOUT_ICE_GFS}
export FHOUT_ICE=${FHOUT_ICE_GFS}

# Get task specific resources
source "${EXPDIR}/config.resources" fcst
Expand Down
3 changes: 2 additions & 1 deletion parm/config/gefs/yaml/defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ base:
DO_AWIPS: "NO"
KEEPDATA: "NO"
DO_EXTRACTVARS: "NO"
FCST_SEGMENTS_GFS: "0,48,120"
FHMAX_GFS: 120
FHMAX_HF_GFS: 0
FCST_BREAKPOINTS: "48"
REPLAY_ICS: "NO"
USE_OCN_PERTURB_FILES: "false"
18 changes: 5 additions & 13 deletions parm/config/gfs/config.base
Original file line number Diff line number Diff line change
Expand Up @@ -289,19 +289,11 @@ export EUPD_CYC="@EUPD_CYC@"
export gfs_cyc=@gfs_cyc@ # 0: no GFS cycle, 1: 00Z only, 2: 00Z and 12Z only, 4: all 4 cycles.

# GFS output and frequency
# Comma-separated forecast hour intervals to run the forecast over
# For a single-segment forecast, this is simply "$FHMIN_GFS,$FHMAX_GFS"
export FCST_SEGMENTS_STR_GFS="@FCST_SEGMENTS_GFS@"
IFS=', ' read -ra FCST_SEGMENTS_GFS <<< "${FCST_SEGMENTS_STR_GFS}"
if (( ${FCST_SEGMENT:- -1} < 0 )); then
# Jobs other than the forecast don't care about segments, only the
# absolute start and end
declare -x FHMIN_GFS=${FCST_SEGMENTS_GFS[0]}
declare -x FHMAX_GFS=${FCST_SEGMENTS_GFS[-1]}
else
declare -x FHMIN_GFS=${FCST_SEGMENTS_GFS[${FCST_SEGMENT}]}
declare -x FHMAX_GFS=${FCST_SEGMENTS_GFS[${FCST_SEGMENT}+1]}
fi
export FHMIN_GFS=0
export FHMAX_GFS="@FHMAX_GFS@"
# Intermediate times to stop forecast when running in segments
breakpnts="@FCST_BREAKPOINTS@"
export FCST_SEGMENTS="${FHMIN_GFS},${breakpnts:+${breakpnts},}${FHMAX_GFS}"
export FHOUT_GFS=3 # 3 for ops
export FHMAX_HF_GFS=@FHMAX_HF_GFS@
export FHOUT_HF_GFS=1
Expand Down
12 changes: 8 additions & 4 deletions parm/config/gfs/config.fcst
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ source "${EXPDIR}/config.ufs" ${string}
# Forecast length for GFS forecast
case ${RUN} in
*gfs)
export FHMIN=${FHMIN_GFS}
# shellcheck disable=SC2153
export FHMAX=${FHMAX_GFS}
# Convert comma-separated string into bash array
IFS=', ' read -ra segments <<< "${FCST_SEGMENTS}"
# Determine MIN and MAX based on the forecast segment
export FHMIN=${segments[${FCST_SEGMENT}]}
export FHMAX=${segments[${FCST_SEGMENT}+1]}
# Cap other FHMAX variables at FHMAX for the segment
export FHMAX_HF=$(( FHMAX_HF_GFS > FHMAX ? FHMAX : FHMAX_HF_GFS ))
export FHMAX_WAV=$(( FHMAX_WAV > FHMAX ? FHMAX : FHMAX_WAV ))
# shellcheck disable=SC2153
export FHOUT=${FHOUT_GFS}
export FHMAX_HF=${FHMAX_HF_GFS}
export FHOUT_HF=${FHOUT_HF_GFS}
export FHOUT_OCN=${FHOUT_OCN_GFS}
export FHOUT_ICE=${FHOUT_ICE_GFS}
Expand Down
3 changes: 2 additions & 1 deletion parm/config/gfs/yaml/defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ base:
DO_GENESIS: "YES"
DO_GENESIS_FSU: "NO"
DO_METP: "YES"
FCST_SEGMENTS_GFS: "0,120"
FHMAX_GFS: 120
FHMAX_HF_GFS: 0
FCST_BREAKPOINTS: ""
DO_VRFY_OCEANDA: "NO"
GSI_SOILANAL: "NO"
EUPD_CYC: "gdas"
Expand Down
28 changes: 27 additions & 1 deletion workflow/applications/applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ def __init__(self, conf: Configuration) -> None:
self.do_hpssarch = _base.get('HPSSARCH', False)

self.nens = _base.get('NMEM_ENS', 0)
self.fcst_segments = _base.get('FCST_SEGMENTS_STR_GFS', None)
self.fcst_segments = _base.get('FCST_SEGMENTS', None)

if not AppConfig.is_monotonic(self.fcst_segments):
raise ValueError(f'Forecast segments do not increase monotonically: {",".join(self.fcst_segments)}')

self.wave_cdumps = None
if self.do_wave:
Expand Down Expand Up @@ -204,3 +207,26 @@ def get_gfs_interval(gfs_cyc: int) -> timedelta:
return to_timedelta(gfs_internal_map[str(gfs_cyc)])
except KeyError:
raise KeyError(f'Invalid gfs_cyc = {gfs_cyc}')

@staticmethod
def is_monotonic(test_list: List, check_decreasing: bool = False) -> bool:
"""
Determine if an array is monotonically increasing or decreasing
TODO: Move this into wxflow somewhere
Inputs
test_list: List
A list of comparable values to check
check_decreasing: bool [default: False]
Check whether list is monotonically decreasing
Returns
bool: Whether the list is monotonically increasing (if check_decreasing
if False) or decreasing (if check_decreasing is True)
"""
if check_decreasing:
return all(x>y for x, y in zip(test_list, test_list[1:]))
else:
return all(x<y for x, y in zip(test_list, test_list[1:]))

0 comments on commit d9f01cb

Please sign in to comment.