From 3d0f42768303e91e9677f911567be43f78e74e0a Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Thu, 20 Nov 2025 17:34:13 +0000 Subject: [PATCH 01/35] Enable set -o pipefail to catch errors in piped commands --- ush/preamble.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ush/preamble.sh b/ush/preamble.sh index fab7d163a93..439ad0d6bea 100755 --- a/ush/preamble.sh +++ b/ush/preamble.sh @@ -33,8 +33,8 @@ 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, undefined variable, or error in a pipeline (e.g. if and command in "cmd | cmd2" fails) + set -euo pipefail fi } From 4ad6542239d1c48008ba9882a07da1d1b3f40fef Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Thu, 20 Nov 2025 17:35:07 +0000 Subject: [PATCH 02/35] Refactor cleanup task and add checks for gempak files --- dev/parm/config/gfs/config.cleanup | 24 ++++--- scripts/exglobal_cleanup.sh | 100 +++++++++++++++++++---------- 2 files changed, 82 insertions(+), 42 deletions(-) diff --git a/dev/parm/config/gfs/config.cleanup b/dev/parm/config/gfs/config.cleanup index 543d624caf2..62b4aca2efd 100644 --- a/dev/parm/config/gfs/config.cleanup +++ b/dev/parm/config/gfs/config.cleanup @@ -9,22 +9,30 @@ 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 +# Selectively remove files between SELECTIVE_RM_MIN and SELECTIVE_RM_MIN hours old, based on exclude_string +# Remove all RTOFS files older than RTOFS_CLEANUP_MAX hours +# Remove all files, except GEMPAK files, older than SELECTIVE_RM_MAX hours, based on gempak_exclude_string +# Remove all files older than the max of all SELECTIVE_RM* variables +# Retain all files newer than SELECTIVE_RM_MIN hours -if [[ "${DO_GEMPAK}" == "YES" && "${RUN}" == "gfs" ]]; then - export RMOLDSTD=346 - export RMOLDEND=222 +export SELECTIVE_CLEANUP_MAX=144 +export SELECTIVE_CLEANUP_MIN=24 +export GEMPAK_CLEANUP_MAX=240 +export RTOFS_CLEANUP_MAX=48 +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 # 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 exclude_string="" case ${RUN} in - gdas | gfs) exclude_string="*prepbufr*, *cnvstat.tar*, *analysis.atm.a*.nc" ;; - enkf*) exclude_string="*f006.ens*" ;; + gdas | gfs) exclude_string+="*prepbufr*, *cnvstat.tar*, *analysis.atm.a*.nc" ;; + enkf*) exclude_string+="*f006.ens*" ;; *) exclude_string="" ;; esac -export exclude_string echo "END: config.cleanup" diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index c460cc8282c..b6036b97211 100755 --- a/scripts/exglobal_cleanup.sh +++ b/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,32 @@ 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_MAX=${RTOFS_CLEANUP_MAX:-48} +GEMPAK_CLEANUP_MAX=${GEMPAK_CLEANUP_MAX:-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") +last_selective_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${SELECTIVE_CLEANUP_MIN} hours") +first_selective_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${SELECTIVE_CLEANUP_MAX} hours") +last_rtofs_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RTOFS_CLEANUP_MAX} hours") +last_gempak_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${GEMPAK_CLEANUP_MAX} hours") +exclude_string="${exclude_string:-}" + +# Find the last date among all cleanup targets +max_cleanup_max="${SELECTIVE_CLEANUP_MAX:-120}" +for cleanup_max in "${RTOFS_CLEANUP_MAX}" "${GEMPAK_CLEANUP_MAX}"; do + if [[ ${cleanup_max} -gt ${max_cleanup_max} ]]; then + max_cleanup_max=${cleanup_max} + fi +done + +last_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${max_cleanup_max} hours") + function remove_files() { local directory=$1 shift @@ -31,53 +50,63 @@ function remove_files() { echo "No directory ${directory} to remove files from, skiping" return fi - local find_exclude_string="" - for exclude in "$@"; do - find_exclude_string+="${find_exclude_string} -name ${exclude} -or" + # Find all files and links in the directory and store as an arry + # Run find only once for efficiency + flist=($(find "${directory}" -type f -or -type l)) + + # Now remove those files that match the exclude patterns + for exclude_pattern in "$@"; do + # Use a temporary array to hold files that do not match the exclude pattern + temp_flist=() + for file in "${flist[@]}"; do + case "$(basename "${file}")" in + ${exclude_pattern}) + # Match found, skip this file + ;; + *) + # No match, keep this file + temp_flist+=("${file}") + ;; + esac + done + flist=("${temp_flist[@]}") 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 - # 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 - else - # String is empty → no exclusion - find "${directory}" -type l -ignore_readdir_race -delete - fi + # Delete all files in flist. + for file in "${flist[@]}"; do + rm -f "${file}" + done # Remove any empty directories find "${directory}" -type d -empty -delete } -for (( current_date=first_date; current_date <= last_date; \ +# Now start removing old COM files/directories +for (( current_date=first_selective_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" + + # Extend the exclude list for gempak files if needed + if [[ "${RUN}" == "gfs" && ${current_date} -lt ${last_gempak_date} && "${DO_GEMPAK}" == "YES" ]]; then + # Provide the gempak exclude pattern(s) + exclude_string+=", *gfs_1p00_*" + 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 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 < last_rtofs_date )); then rm -rf "${rtofs_dir}" ; fi fi fi done @@ -108,13 +137,16 @@ if [[ "${RUN}" == "gfs" ]]; then fi # Remove $RUN.$rPDY for the older of GDATE or RDATE -GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RMOLDSTD:-120} hours") +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 + rm -rf "${deletion_target}" +fi # sync and wait to avoid filesystem synchronization issues sync && sleep 1 From 8e4322b572e7ffe30c0b97c5fabbe001e15c7def Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Thu, 20 Nov 2025 17:52:02 +0000 Subject: [PATCH 03/35] Shellcheck fixes --- scripts/exglobal_cleanup.sh | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index b6036b97211..901d646f05f 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -52,22 +52,17 @@ function remove_files() { fi # Find all files and links in the directory and store as an arry # Run find only once for efficiency - flist=($(find "${directory}" -type f -or -type l)) + mapfile -t flist < <(find "${directory}" -type f -or -type l) # Now remove those files that match the exclude patterns for exclude_pattern in "$@"; do # Use a temporary array to hold files that do not match the exclude pattern temp_flist=() for file in "${flist[@]}"; do - case "$(basename "${file}")" in - ${exclude_pattern}) - # Match found, skip this file - ;; - *) - # No match, keep this file - temp_flist+=("${file}") - ;; - esac + # shellcheck disable=SC2254 + if [[ ! $(basename "${file}") == ${exclude_pattern} ]]; then + temp_flist+=("${file}") + fi done flist=("${temp_flist[@]}") done From c6a23cfec21eb0d5e10fe48b55bafb307f8a3526 Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Thu, 20 Nov 2025 20:56:18 +0000 Subject: [PATCH 04/35] Ignore 2312 --- .shellcheckrc | 3 +++ scripts/exglobal_cleanup.sh | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.shellcheckrc b/.shellcheckrc index 67fabfe1576..11ecc905ddf 100644 --- a/.shellcheckrc +++ b/.shellcheckrc @@ -17,3 +17,6 @@ disable=SC2174 # Disable warning of functions in test statements disable=SC2310 + +# Disable warning of piped commands masking exit codes; this is covered by set -o pipefail +disable=SC2312 diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index 901d646f05f..fb51627185f 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -59,7 +59,7 @@ function remove_files() { # Use a temporary array to hold files that do not match the exclude pattern temp_flist=() for file in "${flist[@]}"; do - # shellcheck disable=SC2254 + # shellcheck disable=SC2053 if [[ ! $(basename "${file}") == ${exclude_pattern} ]]; then temp_flist+=("${file}") fi From 484235c9bd1d5c2b63ee93d6b9fc8917fc67ece5 Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Thu, 20 Nov 2025 20:58:13 +0000 Subject: [PATCH 05/35] Remove unused variable --- scripts/exglobal_cleanup.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index fb51627185f..8f4c71086f6 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -27,7 +27,6 @@ GEMPAK_CLEANUP_MAX=${GEMPAK_CLEANUP_MAX:-240} # 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_selective_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${SELECTIVE_CLEANUP_MIN} hours") first_selective_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${SELECTIVE_CLEANUP_MAX} hours") last_rtofs_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RTOFS_CLEANUP_MAX} hours") last_gempak_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${GEMPAK_CLEANUP_MAX} hours") From 749f91737f028497031af9285218ae79d60f29e6 Mon Sep 17 00:00:00 2001 From: David Huber Date: Fri, 21 Nov 2025 14:28:50 +0000 Subject: [PATCH 06/35] Disable pipefail exits for now --- .shellcheckrc | 3 --- ush/preamble.sh | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.shellcheckrc b/.shellcheckrc index 11ecc905ddf..67fabfe1576 100644 --- a/.shellcheckrc +++ b/.shellcheckrc @@ -17,6 +17,3 @@ disable=SC2174 # Disable warning of functions in test statements disable=SC2310 - -# Disable warning of piped commands masking exit codes; this is covered by set -o pipefail -disable=SC2312 diff --git a/ush/preamble.sh b/ush/preamble.sh index 439ad0d6bea..2b418c58173 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, undefined variable, or error in a pipeline (e.g. if and command in "cmd | cmd2" fails) - set -euo pipefail + # 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 ceeae5e4713ee15337724a04afbe05a3aa065822 Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Fri, 21 Nov 2025 14:41:20 +0000 Subject: [PATCH 07/35] Shellcheck issues --- scripts/exglobal_cleanup.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index 8f4c71086f6..13dbc5beb32 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -51,7 +51,8 @@ function remove_files() { fi # Find all files and links in the directory and store as an arry # Run find only once for efficiency - mapfile -t flist < <(find "${directory}" -type f -or -type l) + flist=() + mapfile -t flist < <(find "${directory}" -type f -or -type l) || true # Now remove those files that match the exclude patterns for exclude_pattern in "$@"; do @@ -91,7 +92,9 @@ for (( current_date=first_selective_date; current_date <= last_date; \ # 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. - 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 From 7006ec5af54d604a023355e50889cbdd6bc5047f Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Fri, 21 Nov 2025 14:52:40 +0000 Subject: [PATCH 08/35] Fix bufrsnd tarball creation --- scripts/exgfs_atmos_postsnd.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/exgfs_atmos_postsnd.sh b/scripts/exgfs_atmos_postsnd.sh index a366b1fad50..24408b872f5 100755 --- a/scripts/exgfs_atmos_postsnd.sh +++ b/scripts/exgfs_atmos_postsnd.sh @@ -148,12 +148,11 @@ 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 -tar -cf - . | /usr/bin/gzip > "${RUN}.${cycle}.bufrsnd.tar.gz" -cd "${DATA}" || exit 2 +################################################### +# Tar and gzip the bufr files created placed in COM +################################################### +tar -czf "${RUN}.${cycle}.bufrsnd.tar.gz" -C "${COMOUT_ATMOS_BUFR}" bufr.* +cpfs "${RUN}.${cycle}.bufrsnd.tar.gz" "${COMOUT_ATMOS_BUFR}/" ######################################## # Send the single tar file to OSO From 4efde5ada950c7bb39658f32f7fdd1b97cfc36ca Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Fri, 21 Nov 2025 19:18:44 +0000 Subject: [PATCH 09/35] Correct archiving to actually pull the data used --- jobs/JGFS_ATMOS_POSTSND | 1 + scripts/exgfs_atmos_postsnd.sh | 35 ++++++++++++++++++++-------------- ush/gfs_sndp.sh | 14 ++++++++------ 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/jobs/JGFS_ATMOS_POSTSND b/jobs/JGFS_ATMOS_POSTSND index d2d7491f9fb..10f6248081e 100755 --- a/jobs/JGFS_ATMOS_POSTSND +++ b/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/scripts/exgfs_atmos_postsnd.sh b/scripts/exgfs_atmos_postsnd.sh index 24408b872f5..559c074a0fa 100755 --- a/scripts/exgfs_atmos_postsnd.sh +++ b/scripts/exgfs_atmos_postsnd.sh @@ -148,20 +148,6 @@ else fi ${runscript} "${fhr}" "${fhr_p}" "${FINT}" "${F00FLAG}" "${DATA}" -################################################### -# Tar and gzip the bufr files created placed in COM -################################################### -tar -czf "${RUN}.${cycle}.bufrsnd.tar.gz" -C "${COMOUT_ATMOS_BUFR}" bufr.* -cpfs "${RUN}.${cycle}.bufrsnd.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" -fi - ######################################## # Create Regional Collectives of BUFR # data and add appropriate WMO Headers @@ -182,6 +168,27 @@ chmod +x cmdfile ${APRUN_POSTSNDCFP} cmdfile +############################################################### +# Tar and gzip the bufr files in used to create the collectives +############################################################### +# The lists of files are located in ${DATA}//bufr_snd_files.list +for (( m = 1; m <= NUM_SND_COLLECTIVES; m++ )); do + cat "${DATA}/${m}/bufr_snd_files.list" >> "${DATA}/all_bufr_snd_files.list" +done + +tar -czf "${RUN}.${cycle}.bufrsnd.tar.gz" -T "${DATA}/all_bufr_snd_files.list" -C "${COMIN_ATMOS_BUFR}" + +cpfs "${RUN}.${cycle}.bufrsnd.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" +fi + + ######################################## # Read BUFR output and transfer into # GEMPAK surface and sounding data files diff --git a/ush/gfs_sndp.sh b/ush/gfs_sndp.sh index 3d1cd01401c..703e73845fa 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,21 @@ 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" + bufr_target="bufr.${stn}.${PDY}${cyc}" + cpreq "${COMIN_ATMOS_BUFR}/${bufr_target}" "${DATA}/${m}/bufrin" + # Also write the filename to a list for files to tar + echo "${bufr_target}" >> "${DATA}/${m}/bufr_snd_files.list" export pgm=tocsbufr.x #. prep_step export FORT11=$DATA/${m}/bufrin @@ -59,4 +62,3 @@ EOF "${COMOUT_ATMOS_WMO}/gfs_collective${m}.postsnd_${cyc}" fi cpfs "${DATA}/${m}/gfs_collective${m}.fil" "${COMOUT_ATMOS_BUFR}/." - From 214eb5056aa7321ea53ad2297dccbcaf51158ff0 Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Fri, 21 Nov 2025 19:31:53 +0000 Subject: [PATCH 10/35] Correct positional arguments --- scripts/exgfs_atmos_postsnd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/exgfs_atmos_postsnd.sh b/scripts/exgfs_atmos_postsnd.sh index 559c074a0fa..5ebd42e01af 100755 --- a/scripts/exgfs_atmos_postsnd.sh +++ b/scripts/exgfs_atmos_postsnd.sh @@ -176,7 +176,7 @@ for (( m = 1; m <= NUM_SND_COLLECTIVES; m++ )); do cat "${DATA}/${m}/bufr_snd_files.list" >> "${DATA}/all_bufr_snd_files.list" done -tar -czf "${RUN}.${cycle}.bufrsnd.tar.gz" -T "${DATA}/all_bufr_snd_files.list" -C "${COMIN_ATMOS_BUFR}" +tar -czf "${RUN}.${cycle}.bufrsnd.tar.gz" -C "${COMIN_ATMOS_BUFR}" -T "${DATA}/all_bufr_snd_files.list" cpfs "${RUN}.${cycle}.bufrsnd.tar.gz" "${COMOUT_ATMOS_BUFR}/" From ebb0e33eee42eb1ef17df8b3525ed3d4b31d75e4 Mon Sep 17 00:00:00 2001 From: DavidHuber-NOAA Date: Fri, 21 Nov 2025 19:50:30 +0000 Subject: [PATCH 11/35] Tar all bufr files --- scripts/exgfs_atmos_postsnd.sh | 37 ++++++++++++++++------------------ 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/scripts/exgfs_atmos_postsnd.sh b/scripts/exgfs_atmos_postsnd.sh index 5ebd42e01af..c22dc54a970 100755 --- a/scripts/exgfs_atmos_postsnd.sh +++ b/scripts/exgfs_atmos_postsnd.sh @@ -148,6 +148,23 @@ else fi ${runscript} "${fhr}" "${fhr_p}" "${FINT}" "${F00FLAG}" "${DATA}" +############################################ +# Tar and gzip the bufr files created so far +############################################ +find "${COMIN_ATMOS_BUFR}/bufr.*" -printf '%f\n' > "${DATA}/all_bufr_files.txt" + +tar -czf "${RUN}.${cycle}.bufrsnd.tar.gz" -C "${COMIN_ATMOS_BUFR}" -T "${DATA}/all_bufr_files.txt" + +cpfs "${RUN}.${cycle}.bufrsnd.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" +fi + ######################################## # Create Regional Collectives of BUFR # data and add appropriate WMO Headers @@ -168,26 +185,6 @@ chmod +x cmdfile ${APRUN_POSTSNDCFP} cmdfile -############################################################### -# Tar and gzip the bufr files in used to create the collectives -############################################################### -# The lists of files are located in ${DATA}//bufr_snd_files.list -for (( m = 1; m <= NUM_SND_COLLECTIVES; m++ )); do - cat "${DATA}/${m}/bufr_snd_files.list" >> "${DATA}/all_bufr_snd_files.list" -done - -tar -czf "${RUN}.${cycle}.bufrsnd.tar.gz" -C "${COMIN_ATMOS_BUFR}" -T "${DATA}/all_bufr_snd_files.list" - -cpfs "${RUN}.${cycle}.bufrsnd.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" -fi - ######################################## # Read BUFR output and transfer into From cdf5a8fd37bd554b413a3eb2057856b23724044c Mon Sep 17 00:00:00 2001 From: David Huber Date: Fri, 21 Nov 2025 22:31:17 +0000 Subject: [PATCH 12/35] Use a find command instead --- scripts/exgfs_atmos_postsnd.sh | 2 +- ush/gfs_sndp.sh | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/exgfs_atmos_postsnd.sh b/scripts/exgfs_atmos_postsnd.sh index c22dc54a970..16b3a71e81e 100755 --- a/scripts/exgfs_atmos_postsnd.sh +++ b/scripts/exgfs_atmos_postsnd.sh @@ -151,7 +151,7 @@ ${runscript} "${fhr}" "${fhr_p}" "${FINT}" "${F00FLAG}" "${DATA}" ############################################ # Tar and gzip the bufr files created so far ############################################ -find "${COMIN_ATMOS_BUFR}/bufr.*" -printf '%f\n' > "${DATA}/all_bufr_files.txt" +find "${COMIN_ATMOS_BUFR}" -maxdepth 1 -type f -name "bufr.*" -printf '%f\n' > "${DATA}/all_bufr_files.txt" tar -czf "${RUN}.${cycle}.bufrsnd.tar.gz" -C "${COMIN_ATMOS_BUFR}" -T "${DATA}/all_bufr_files.txt" diff --git a/ush/gfs_sndp.sh b/ush/gfs_sndp.sh index 703e73845fa..98738f10c64 100755 --- a/ush/gfs_sndp.sh +++ b/ush/gfs_sndp.sh @@ -32,8 +32,6 @@ cd $DATA/$m do bufr_target="bufr.${stn}.${PDY}${cyc}" cpreq "${COMIN_ATMOS_BUFR}/${bufr_target}" "${DATA}/${m}/bufrin" - # Also write the filename to a list for files to tar - echo "${bufr_target}" >> "${DATA}/${m}/bufr_snd_files.list" export pgm=tocsbufr.x #. prep_step export FORT11=$DATA/${m}/bufrin From 3303cc4f44851334a0766ce21c83bf66b4a68b41 Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 25 Nov 2025 19:03:34 +0000 Subject: [PATCH 13/35] Do not load gh anymore --- modulefiles/gw_setup.gaeac6.lua | 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 - 5 files changed, 6 deletions(-) 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/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") From 473c7b5860ccecd9cc50696fb6c7eed74169e1f1 Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 25 Nov 2025 19:07:51 +0000 Subject: [PATCH 14/35] Enable archiving on WCOSS2 by default --- dev/workflow/hosts/wcoss2.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/workflow/hosts/wcoss2.yaml b/dev/workflow/hosts/wcoss2.yaml index 9f82d8e9e81..2e619ce76f2 100644 --- a/dev/workflow/hosts/wcoss2.yaml +++ b/dev/workflow/hosts/wcoss2.yaml @@ -26,4 +26,4 @@ CHGRP_RSTPROD: 'YES' CHGRP_CMD: 'chgrp rstprod' # Features SUPPORTED_RESOLUTIONS: ['C1152', 'C768', 'C384', 'C192', 'C96', 'C48'] -DO_ARCHCOM: 'NO' +DO_ARCHCOM: 'YES' From 7cda2421bd9152674b58b0b9e0682e8d4e8c7c21 Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 25 Nov 2025 19:15:12 +0000 Subject: [PATCH 15/35] Make the bufr soundings and surface files EE2-compliant --- ush/gfs_bfr2gpk.sh | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) 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" From 41effff274d8c4950f8faea13067b6ec204a8fcf Mon Sep 17 00:00:00 2001 From: David Huber Date: Wed, 26 Nov 2025 14:51:44 +0000 Subject: [PATCH 16/35] Update soundings tarball name to be EE2-compliant --- scripts/exgfs_atmos_postsnd.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/exgfs_atmos_postsnd.sh b/scripts/exgfs_atmos_postsnd.sh index 16b3a71e81e..0a33ec7f9f2 100755 --- a/scripts/exgfs_atmos_postsnd.sh +++ b/scripts/exgfs_atmos_postsnd.sh @@ -153,16 +153,16 @@ ${runscript} "${fhr}" "${fhr_p}" "${FINT}" "${F00FLAG}" "${DATA}" ############################################ find "${COMIN_ATMOS_BUFR}" -maxdepth 1 -type f -name "bufr.*" -printf '%f\n' > "${DATA}/all_bufr_files.txt" -tar -czf "${RUN}.${cycle}.bufrsnd.tar.gz" -C "${COMIN_ATMOS_BUFR}" -T "${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}.bufrsnd.tar.gz" "${COMOUT_ATMOS_BUFR}/" +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 ######################################## @@ -185,7 +185,6 @@ chmod +x cmdfile ${APRUN_POSTSNDCFP} cmdfile - ######################################## # Read BUFR output and transfer into # GEMPAK surface and sounding data files From c8bc24ca8f2e32f3659bc78a354e301f19a24f1a Mon Sep 17 00:00:00 2001 From: David Huber Date: Mon, 1 Dec 2025 14:18:35 +0000 Subject: [PATCH 17/35] Correct atmos product dependencies --- dev/workflow/rocoto/gefs_tasks.py | 2 +- dev/workflow/rocoto/sfs_tasks.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/workflow/rocoto/gefs_tasks.py b/dev/workflow/rocoto/gefs_tasks.py index 61438252e58..d42c0963ba6 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 9113a5d9bb4..20a99af11ee 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'}, From 30395abbf5522c1407caccba7c70240b6f22398c Mon Sep 17 00:00:00 2001 From: David Huber Date: Mon, 1 Dec 2025 18:30:36 +0000 Subject: [PATCH 18/35] Replace tabs with spaces --- dev/parm/config/gfs/config.cleanup | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/parm/config/gfs/config.cleanup b/dev/parm/config/gfs/config.cleanup index 62b4aca2efd..2933a3bd010 100644 --- a/dev/parm/config/gfs/config.cleanup +++ b/dev/parm/config/gfs/config.cleanup @@ -28,11 +28,11 @@ 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 exclude_string="" +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 echo "END: config.cleanup" From a88f475768ee6f93ebb24cff4828db22945955a8 Mon Sep 17 00:00:00 2001 From: David Huber Date: Mon, 1 Dec 2025 18:31:13 +0000 Subject: [PATCH 19/35] Increase memory for gempak jobs (needed for meta task) --- dev/parm/config/gfs/config.resources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/parm/config/gfs/config.resources b/dev/parm/config/gfs/config.resources index 1c8ca9d24a1..d966237b0f1 100644 --- a/dev/parm/config/gfs/config.resources +++ b/dev/parm/config/gfs/config.resources @@ -1380,7 +1380,7 @@ case ${step} in elif [[ "${RUN}" = *gfs ]]; then ntasks=28 tasks_per_node=28 - memory="4GB" + memory="6GB" fi ;; From 159dc6823b68fa35eb3917038f84892f9a9ef3e4 Mon Sep 17 00:00:00 2001 From: David Huber Date: Mon, 1 Dec 2025 18:32:36 +0000 Subject: [PATCH 20/35] Make cleanup script smarter Do selective cleanup by determining date ranges for files to keep. Only keep files based on the dates selected. --- scripts/exglobal_cleanup.sh | 79 +++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index 13dbc5beb32..2ecadbfb0f5 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -28,19 +28,39 @@ GEMPAK_CLEANUP_MAX=${GEMPAK_CLEANUP_MAX:-240} # for successful cycles (defaults from 24h to 120h). # Retain files needed by Fit2Obs 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") last_rtofs_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RTOFS_CLEANUP_MAX} hours") -last_gempak_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${GEMPAK_CLEANUP_MAX} hours") -exclude_string="${exclude_string:-}" +first_gempak_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${GEMPAK_CLEANUP_MAX} hours") +# Selective exclude list +selective_exclude_string="${selective_exclude_string:-}" +# Gempak exclude list +gempak_exclude_string+=", *gfs_1p00_*" -# Find the last date among all cleanup targets +# Find the first and last date among all cleanup targets max_cleanup_max="${SELECTIVE_CLEANUP_MAX:-120}" -for cleanup_max in "${RTOFS_CLEANUP_MAX}" "${GEMPAK_CLEANUP_MAX}"; do +max_list="${RTOFS_CLEANUP_MAX}" +if [[ "${RUN}" == "gfs" && "${DO_GEMPAK}" == "YES" ]]; then + max_list+=" ${GEMPAK_CLEANUP_MAX}}" +fi + +for cleanup_max in ${max_list}; do if [[ ${cleanup_max} -gt ${max_cleanup_max} ]]; then max_cleanup_max=${cleanup_max} fi done -last_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${max_cleanup_max} hours") +max_cleanup_min=${max_cleanup_max} +for cleanup_max in ${max_list}; do + if [[ ${cleanup_max} -lt ${max_cleanup_min} ]]; then + max_cleanup_min=${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") + +last_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${max_cleanup_min} hours") function remove_files() { local directory=$1 @@ -49,44 +69,45 @@ function remove_files() { echo "No directory ${directory} to remove files from, skiping" return fi - # Find all files and links in the directory and store as an arry - # Run find only once for efficiency - flist=() - mapfile -t flist < <(find "${directory}" -type f -or -type l) || true - - # Now remove those files that match the exclude patterns - for exclude_pattern in "$@"; do - # Use a temporary array to hold files that do not match the exclude pattern - temp_flist=() - for file in "${flist[@]}"; do - # shellcheck disable=SC2053 - if [[ ! $(basename "${file}") == ${exclude_pattern} ]]; then - temp_flist+=("${file}") - fi - done - flist=("${temp_flist[@]}") - done - - # Delete all files in flist. - for file in "${flist[@]}"; do - rm -f "${file}" + local find_exclude_string="" + for exclude in "$@"; do + 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 and symlinks that do not match + # shellcheck disable=SC2086 + if [[ -n "${find_exclude_string}" ]]; then + # String is non-empty → use exclusion + find "${directory}" \( -type f -o -type l \) -not \( ${find_exclude_string} \) -ignore_readdir_race -delete + else + # String is empty → no exclusion + 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_selective_date; current_date <= last_date; \ +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}" 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} -lt ${last_gempak_date} && "${DO_GEMPAK}" == "YES" ]]; then + if [[ "${RUN}" == "gfs" && ${current_date} -ge ${first_gempak_date} && "${DO_GEMPAK}" == "YES" ]]; then # Provide the gempak exclude pattern(s) - exclude_string+=", *gfs_1p00_*" + exclude_string+="${gempak_exclude_string}" fi # Check if the cycle completed successfully by looking at the rocoto log From 73f4bcc3058acf89d33bc4797b1ce839230a28d3 Mon Sep 17 00:00:00 2001 From: David Huber Date: Mon, 1 Dec 2025 18:55:16 +0000 Subject: [PATCH 21/35] Reduce RTOFS retention to 24 hours --- dev/parm/config/gfs/config.cleanup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/parm/config/gfs/config.cleanup b/dev/parm/config/gfs/config.cleanup index 2933a3bd010..f7be6eed83b 100644 --- a/dev/parm/config/gfs/config.cleanup +++ b/dev/parm/config/gfs/config.cleanup @@ -18,7 +18,7 @@ export CLEANUP_COM="YES" # NO=retain ROTDIR. YES default in cleanup.sh export SELECTIVE_CLEANUP_MAX=144 export SELECTIVE_CLEANUP_MIN=24 export GEMPAK_CLEANUP_MAX=240 -export RTOFS_CLEANUP_MAX=48 +export RTOFS_CLEANUP_MAX=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}" From a8d5f41c8092e30cde603fff548a799bf345674f Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 2 Dec 2025 16:38:57 +0000 Subject: [PATCH 22/35] Remove extra } --- scripts/exglobal_cleanup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index ddb1e1117c0..ee881962a1d 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -40,7 +40,7 @@ gempak_exclude_string+=", *gfs_1p00_*" max_cleanup_max="${SELECTIVE_CLEANUP_MAX:-120}" max_list="${RTOFS_CLEANUP_MAX}" if [[ "${RUN}" == "gfs" && "${DO_GEMPAK}" == "YES" ]]; then - max_list+=" ${GEMPAK_CLEANUP_MAX}}" + max_list+=" ${GEMPAK_CLEANUP_MAX}" fi for cleanup_max in ${max_list}; do From cd59c0fc8ca1efc417cc7dd5284bd8feedd4f775 Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 2 Dec 2025 16:58:18 +0000 Subject: [PATCH 23/35] Rename RTOFS and GEMPAK variables --- dev/parm/config/gfs/config.cleanup | 17 +++++++++-------- scripts/exglobal_cleanup.sh | 28 ++++++++++++++++------------ 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/dev/parm/config/gfs/config.cleanup b/dev/parm/config/gfs/config.cleanup index f7be6eed83b..61de1edb056 100644 --- a/dev/parm/config/gfs/config.cleanup +++ b/dev/parm/config/gfs/config.cleanup @@ -8,17 +8,18 @@ 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 -# Selectively remove files between SELECTIVE_RM_MIN and SELECTIVE_RM_MIN hours old, based on exclude_string -# Remove all RTOFS files older than RTOFS_CLEANUP_MAX hours -# Remove all files, except GEMPAK files, older than SELECTIVE_RM_MAX hours, based on gempak_exclude_string -# Remove all files older than the max of all SELECTIVE_RM* variables -# Retain all files newer than SELECTIVE_RM_MIN hours +#--starting and ending hours of previous cycles to be removed from rotating directory based on RUN +# 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) + +# Keep all files newer than SELECTIVE_CLEANUP_MIN hours (except RTOFS) +# Remove all RTOFS files older than RTOFS_CLEANUP hours export SELECTIVE_CLEANUP_MAX=144 export SELECTIVE_CLEANUP_MIN=24 -export GEMPAK_CLEANUP_MAX=240 -export RTOFS_CLEANUP_MAX=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}" diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index ee881962a1d..751e0db2fb6 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -6,8 +6,8 @@ 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}"; +if [[ -d "${DATAfcst}" ]]; then + rm -rf "${DATAfcst}" fi #DATAefcs="${DATAROOT}/${RUN}efcs???${PDY:-}${cyc}" rm -rf "${DATAROOT}/${RUN}efcs"*"${PDY:-}${cyc}" @@ -19,8 +19,8 @@ fi SELECTIVE_CLEANUP_MIN=${SELECTIVE_CLEANUP_MIN:-24} SELECTIVE_CLEANUP_MAX=${SELECTIVE_CLEANUP_MAX:-120} -RTOFS_CLEANUP_MAX=${RTOFS_CLEANUP_MAX:-48} -GEMPAK_CLEANUP_MAX=${GEMPAK_CLEANUP_MAX:-240} +RTOFS_CLEANUP=${RTOFS_CLEANUP:-24} +GEMPAK_CLEANUP=${GEMPAK_CLEANUP:-240} ############################################################### # Clean up previous cycles; various depths @@ -29,8 +29,8 @@ GEMPAK_CLEANUP_MAX=${GEMPAK_CLEANUP_MAX:-240} # Retain files needed by Fit2Obs 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") -last_rtofs_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RTOFS_CLEANUP_MAX} hours") -first_gempak_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${GEMPAK_CLEANUP_MAX} hours") +last_rtofs_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RTOFS_CLEANUP} hours") +first_gempak_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 @@ -38,9 +38,9 @@ gempak_exclude_string+=", *gfs_1p00_*" # Find the first and last date among all cleanup targets max_cleanup_max="${SELECTIVE_CLEANUP_MAX:-120}" -max_list="${RTOFS_CLEANUP_MAX}" +max_list="${RTOFS_CLEANUP}" if [[ "${RUN}" == "gfs" && "${DO_GEMPAK}" == "YES" ]]; then - max_list+=" ${GEMPAK_CLEANUP_MAX}" + max_list+=" ${GEMPAK_CLEANUP}" fi for cleanup_max in ${max_list}; do @@ -76,7 +76,7 @@ function remove_files() { fi done # Chop off any trailing or - find_exclude_string="${find_exclude_string[*]/%-or}" + find_exclude_string="${find_exclude_string[*]/%-or/}" # Remove all regular files and symlinks that do not match # shellcheck disable=SC2086 if [[ -n "${find_exclude_string}" ]]; then @@ -92,7 +92,7 @@ function remove_files() { } # Now start removing old COM files/directories -for ((current_date=first_date; current_date <= last_date; \ +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}" @@ -124,8 +124,12 @@ current_date = $(date --utc +%Y%m%d%H -d "${current_date:0:8} ${current_date:8:2 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 < last_rtofs_date)); then rm -rf "${rtofs_dir}" ; fi - if [[ -d "${rtofs_dir}" ]] && ((current_date < last_rtofs)); then rm -rf "${rtofs_dir}"; fi + if [[ -d "${rtofs_dir}" && ${current_date} -lt ${last_rtofs_date} ]]; then + rm -rf "${rtofs_dir}" + fi + if [[ -d "${rtofs_dir}" && ${current_date} -lt ${last_rtofs} ]]; then + rm -rf "${rtofs_dir}" + fi fi fi done From d2ebe7faae5eb1010be4781fb9487ee3fab0f2cf Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 2 Dec 2025 17:00:07 +0000 Subject: [PATCH 24/35] Clarify RTOFS cleanup language --- dev/parm/config/gfs/config.cleanup | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dev/parm/config/gfs/config.cleanup b/dev/parm/config/gfs/config.cleanup index 61de1edb056..856a1a09413 100644 --- a/dev/parm/config/gfs/config.cleanup +++ b/dev/parm/config/gfs/config.cleanup @@ -8,12 +8,14 @@ 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 based on RUN +#--starting and ending hours of previous cycles to be removed from rotating directory +# 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) -# Keep all files newer than SELECTIVE_CLEANUP_MIN hours (except RTOFS) +# RTOFS-specific variables (runs every RUN) # Remove all RTOFS files older than RTOFS_CLEANUP hours export SELECTIVE_CLEANUP_MAX=144 From 93314097e122f8b607b1ec027a913e8f3322b3b5 Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 2 Dec 2025 17:05:46 +0000 Subject: [PATCH 25/35] Add DO_BUFRSND dependency on gempak/bufr sounding outputs --- parm/archive/gfs_downstream.yaml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 %} From 19e44a1fadf2bc070e424739a47bddc1940c9e6c Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 2 Dec 2025 17:10:07 +0000 Subject: [PATCH 26/35] Linter cleanup --- scripts/exglobal_cleanup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index 751e0db2fb6..279b7a514dc 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -57,7 +57,7 @@ for cleanup_max in ${max_list}; do done # Start 4 cycles before the earliest exclusion target so we actually remove older files -max_cleanup_max=$(( max_cleanup_max + 4 * assim_freq )) +max_cleanup_max=$((max_cleanup_max + 4 * assim_freq)) first_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${max_cleanup_max} hours") last_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${max_cleanup_min} hours") @@ -92,7 +92,7 @@ function remove_files() { } # Now start removing old COM files/directories -for ((current_date = first_date; current_date <= last_date; \ +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}" From 844d5280d98267bf7a252c268655675222e4028e Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 2 Dec 2025 18:53:22 +0000 Subject: [PATCH 27/35] Rename variables to more meaningful names --- scripts/exglobal_cleanup.sh | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index 279b7a514dc..9c6d5d09331 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -29,16 +29,18 @@ GEMPAK_CLEANUP=${GEMPAK_CLEANUP:-240} # Retain files needed by Fit2Obs 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") -last_rtofs_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${RTOFS_CLEANUP} hours") -first_gempak_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${GEMPAK_CLEANUP} 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="${RTOFS_CLEANUP}" +max_list="${SELECTIVE_CLEANUP_MAX}" if [[ "${RUN}" == "gfs" && "${DO_GEMPAK}" == "YES" ]]; then max_list+=" ${GEMPAK_CLEANUP}" fi @@ -105,7 +107,7 @@ current_date = $(date --utc +%Y%m%d%H -d "${current_date:0:8} ${current_date:8:2 fi # Extend the exclude list for gempak files if needed - if [[ "${RUN}" == "gfs" && ${current_date} -ge ${first_gempak_date} && "${DO_GEMPAK}" == "YES" ]]; then + 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 @@ -124,10 +126,7 @@ current_date = $(date --utc +%Y%m%d%H -d "${current_date:0:8} ${current_date:8:2 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 ${last_rtofs_date} ]]; then - rm -rf "${rtofs_dir}" - fi - if [[ -d "${rtofs_dir}" && ${current_date} -lt ${last_rtofs} ]]; then + if [[ -d "${rtofs_dir}" && ${current_date} -lt ${rtofs_cutoff_date} ]]; then rm -rf "${rtofs_dir}" fi fi From 28659b91a5f06e937e23a3868622237e4530c903 Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 2 Dec 2025 19:51:08 +0000 Subject: [PATCH 28/35] Only delete empty RUN.PDY directories --- scripts/exglobal_cleanup.sh | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/scripts/exglobal_cleanup.sh b/scripts/exglobal_cleanup.sh index 9c6d5d09331..1e5d51f8c78 100755 --- a/scripts/exglobal_cleanup.sh +++ b/scripts/exglobal_cleanup.sh @@ -33,7 +33,7 @@ gempak_cutoff_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${GEMPAK_CLEANUP} h # Selective exclude list selective_exclude_string="${selective_exclude_string:-}" # Gempak exclude list -gempak_exclude_string+=", *gfs_1p00_*" +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") @@ -51,19 +51,14 @@ for cleanup_max in ${max_list}; do fi done -max_cleanup_min=${max_cleanup_max} -for cleanup_max in ${max_list}; do - if [[ ${cleanup_max} -lt ${max_cleanup_min} ]]; then - max_cleanup_min=${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") -last_date=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} -${max_cleanup_min} 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 @@ -158,7 +153,7 @@ if [[ "${RUN}" == "gfs" ]]; then done fi -# Remove $RUN.$rPDY for the older of GDATE or RDATE +# 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 @@ -167,7 +162,7 @@ fi deletion_target="${ROTDIR}/${RUN}.${RDATE:0:8}" if [[ -d "${deletion_target}" ]]; then - rm -rf "${deletion_target}" + find "${deletion_target}" -maxdepth 0 -type d -empty -delete fi # sync and wait to avoid filesystem synchronization issues From 38793d2610d500124fb523a3fd1c6a2df99e7492 Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 2 Dec 2025 19:51:39 +0000 Subject: [PATCH 29/35] Add check for invalid GEMPAK retention --- dev/parm/config/gfs/config.cleanup | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dev/parm/config/gfs/config.cleanup b/dev/parm/config/gfs/config.cleanup index 856a1a09413..53c4a0192f4 100644 --- a/dev/parm/config/gfs/config.cleanup +++ b/dev/parm/config/gfs/config.cleanup @@ -28,6 +28,13 @@ if [[ ${SELECTIVE_CLEANUP_MIN} -gt ${SELECTIVE_CLEANUP_MAX} ]]; then 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 ${GEMPAK_CLEANUP} ]]; 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. From bb7a31a655278a22d094862c285f40fb1871990e Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 9 Dec 2025 18:29:46 +0000 Subject: [PATCH 30/35] Re-disable HPSS archiving on WCOSS2 by default --- dev/workflow/hosts/wcoss2.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/workflow/hosts/wcoss2.yaml b/dev/workflow/hosts/wcoss2.yaml index 2e619ce76f2..9f82d8e9e81 100644 --- a/dev/workflow/hosts/wcoss2.yaml +++ b/dev/workflow/hosts/wcoss2.yaml @@ -26,4 +26,4 @@ CHGRP_RSTPROD: 'YES' CHGRP_CMD: 'chgrp rstprod' # Features SUPPORTED_RESOLUTIONS: ['C1152', 'C768', 'C384', 'C192', 'C96', 'C48'] -DO_ARCHCOM: 'YES' +DO_ARCHCOM: 'NO' From 4a8bb34ac7e8e6ac9c19911f2c0fa55e23736d2d Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 9 Dec 2025 18:30:33 +0000 Subject: [PATCH 31/35] Disable C48_S2SW on WCOSS2 This test is covered by C48_S2SW_extended --- dev/ci/cases/pr/C48_S2SW.yaml | 3 +++ 1 file changed, 3 insertions(+) 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: From 8382dea4ca18982bf6bb488e153ef02fc347228e Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 9 Dec 2025 18:31:03 +0000 Subject: [PATCH 32/35] Turn on HPSS archiving for extended tests --- dev/ci/cases/yamls/gfs_extended_ci.yaml | 1 + 1 file changed, 1 insertion(+) 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" From fb0f7448fe45b65b400e87b242d85e97bb6c166f Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 9 Dec 2025 19:00:28 +0000 Subject: [PATCH 33/35] Revert the use of 'bufr_target' --- ush/gfs_sndp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ush/gfs_sndp.sh b/ush/gfs_sndp.sh index 98738f10c64..47de659c37a 100755 --- a/ush/gfs_sndp.sh +++ b/ush/gfs_sndp.sh @@ -31,7 +31,7 @@ cd $DATA/$m for stn in $(cat $file_list) do bufr_target="bufr.${stn}.${PDY}${cyc}" - cpreq "${COMIN_ATMOS_BUFR}/${bufr_target}" "${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 From 246487ca68f9d2496963fc01d0a38f8b10be9edf Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 9 Dec 2025 19:01:29 +0000 Subject: [PATCH 34/35] Remove now-unused variable --- ush/gfs_sndp.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/ush/gfs_sndp.sh b/ush/gfs_sndp.sh index 47de659c37a..af09e175dd7 100755 --- a/ush/gfs_sndp.sh +++ b/ush/gfs_sndp.sh @@ -30,7 +30,6 @@ cd $DATA/$m for stn in $(cat $file_list) do - bufr_target="bufr.${stn}.${PDY}${cyc}" cpreq "${COMIN_ATMOS_BUFR}/bufr.${stn}.${PDY}${cyc}" "${DATA}/${m}/bufrin" export pgm=tocsbufr.x #. prep_step From 865a53d2e134f74232f82e6d0e98f9637714c8d9 Mon Sep 17 00:00:00 2001 From: David Huber Date: Tue, 9 Dec 2025 19:21:37 +0000 Subject: [PATCH 35/35] Correct GEMPAK_CLEANUP check --- dev/parm/config/gfs/config.cleanup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/parm/config/gfs/config.cleanup b/dev/parm/config/gfs/config.cleanup index 53c4a0192f4..a4af66b493d 100644 --- a/dev/parm/config/gfs/config.cleanup +++ b/dev/parm/config/gfs/config.cleanup @@ -29,7 +29,7 @@ if [[ ${SELECTIVE_CLEANUP_MIN} -gt ${SELECTIVE_CLEANUP_MAX} ]]; then 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 ${GEMPAK_CLEANUP} ]]; then +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