From 973d3372eaaa6e68aa0946069dd7a6b9c5acee63 Mon Sep 17 00:00:00 2001 From: CoryMartin-NOAA Date: Mon, 17 Mar 2025 19:56:16 +0000 Subject: [PATCH 01/17] add a bunch of stuff --- jobs/JOBSFORGE_GLOBAL_AOD_DUMP | 45 +++++++++ scripts/exobsforge_global_aod_dump.py | 4 + ush/bash_utils.sh | 126 ++++++++++++++++++++++++++ ush/cron_driver.sh | 3 + ush/jjob_header.sh | 114 +++++++++++++++++++++++ ush/preamble.sh | 114 +++++++++++++++++++++++ 6 files changed, 406 insertions(+) create mode 100755 jobs/JOBSFORGE_GLOBAL_AOD_DUMP create mode 100755 scripts/exobsforge_global_aod_dump.py create mode 100755 ush/bash_utils.sh create mode 100755 ush/cron_driver.sh create mode 100755 ush/jjob_header.sh create mode 100755 ush/preamble.sh diff --git a/jobs/JOBSFORGE_GLOBAL_AOD_DUMP b/jobs/JOBSFORGE_GLOBAL_AOD_DUMP new file mode 100755 index 00000000..21a73789 --- /dev/null +++ b/jobs/JOBSFORGE_GLOBAL_AOD_DUMP @@ -0,0 +1,45 @@ +#! /usr/bin/env bash + +source "${HOMEobsforge}/ush/preamble.sh" +#source "${HOMEobsforge}/ush/jjob_header.sh" + +############################################## +# Set variables used in the script +############################################## + + +############################################## +# Begin JOB SPECIFIC work +############################################## + +############################################################### +# Run relevant script + +EXSCRIPT=${DUMPAODPY:-${SCRobsforge}/exobsforge_global_aod_dump.py} +${EXSCRIPT} +status=$? +if [[ ${status} -ne 0 ]]; then + exit "${status}" +fi + + +############################################## +# End JOB SPECIFIC work +############################################## + +############################################## +# Final processing +############################################## +if [[ -e "${pgmout}" ]] ; then + cat "${pgmout}" +fi + +########################################## +# Remove the Temporary working directory +########################################## +cd "${DATAROOT}" || exit +if [[ "${KEEPDATA}" == "NO" ]]; then + rm -rf "${DATA}" +fi + +exit 0 \ No newline at end of file diff --git a/scripts/exobsforge_global_aod_dump.py b/scripts/exobsforge_global_aod_dump.py new file mode 100755 index 00000000..f82b26ec --- /dev/null +++ b/scripts/exobsforge_global_aod_dump.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 + +if __name__ == '__main__': + print('hello') \ No newline at end of file diff --git a/ush/bash_utils.sh b/ush/bash_utils.sh new file mode 100755 index 00000000..b8ce729c --- /dev/null +++ b/ush/bash_utils.sh @@ -0,0 +1,126 @@ +#! /usr/bin/env bash + +function declare_from_tmpl() { + # + # Define variables from corresponding templates by substituting in env variables. + # + # Each template must already be defined. Any variables in the template are replaced + # with their values. Undefined variables are just removed WITHOUT raising an error. + # + # Accepts as options `-r` and `-x`, which do the same thing as the same options in + # `declare`. Variables are automatically marked as `-g` so the variable is visible + # in the calling script. + # + # Syntax: + # declare_from_tmpl [-rx] $var1[:$tmpl1] [$var2[:$tmpl2]] [...]] + # + # options: + # -r: Make variable read-only (same as `declare -r`) + # -x: Mark variable for export (same as `declare -x`) + # var1, var2, etc: Variable names whose values will be generated from a template + # and declared + # tmpl1, tmpl2, etc: Specify the template to use (default is "${var}_TMPL") + # + # Examples: + # # Current cycle and RUN, implicitly using template COM_ATMOS_ANALYSIS_TMPL + # YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COM_ATMOS_ANALYSIS + # + # # Previous cycle and gdas using an explicit template + # RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ + # COM_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL + # + # # Current cycle and COM for first member + # MEMDIR='mem001' YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COM_ATMOS_HISTORY + # + if [[ ${DEBUG_WORKFLOW:-"NO"} == "NO" ]]; then set +x; fi + local opts="-g" + local OPTIND=1 + while getopts "rx" option; do + opts="${opts}${option}" + done + shift $((OPTIND-1)) + + for input in "$@"; do + IFS=':' read -ra args <<< "${input}" + local com_var="${args[0]}" + local template + local value + if (( ${#args[@]} > 1 )); then + template="${args[1]}" + else + template="${com_var}_TMPL" + fi + if [[ ! -v "${template}" ]]; then + echo "FATAL ERROR in declare_from_tmpl: Requested template ${template} not defined!" + exit 2 + fi + value=$(echo "${!template}" | envsubst) + # shellcheck disable=SC2086 + declare ${opts} "${com_var}"="${value}" + # shellcheck disable= + echo "declare_from_tmpl :: ${com_var}=${value}" + done + set_trace +} + +function wait_for_file() { + # + # Wait for a file to exist and return the status. + # + # Checks if a file exists periodically up to a maximum number of attempts. When the file + # exists or the limit is reached, the status is returned (0 if the file exists,1 if it + # does not). This allows it to be used as a conditional to handle missing files. + # + # Syntax: + # wait_for_file file_name [sleep_interval [max_tries]] + # + # file_name: File to check the existence of (must be readable) + # sleep_interval: Time to wait between each check (in seconds) [default: 60] + # max_tries: The maximum number of checks to make [default: 100] + # + # Example: + # ``` + # file_name=/path/to/foo + # sleep_interval=60 + # max_tries=30 + # if wait_for_file; then + # echo "FATAL ERROR: ${file_name} still does not exist after waiting one-half hour." + # exit 1 + # fi + # # Code that depends on file existing + # ``` + # + set +x + local file_name=${1:?"wait_for_file() requires a file name"} + local sleep_interval=${2:-60} + local max_tries=${3:-100} + + for (( iter=0; iter 0 )); then + id="(${1})" +else + id="" +fi + +# Record the start time so we can calculate the elapsed time later +start_time=$(date +%s) + +# Get the base name of the calling script +_calling_script=$(basename "${BASH_SOURCE[1]}") + +# Announce the script has begun +start_time_human=$(date -d"@${start_time}" -u) +echo "Begin ${_calling_script} at ${start_time_human}" + +declare -rx PS4='+ $(basename ${BASH_SOURCE[0]:-${FUNCNAME[0]:-"Unknown"}})[${LINENO}]'"${id}: " + +set_strict() { + if [[ ${STRICT:-"YES"} == "YES" ]]; then + # Exit on error and undefined variable + set -eu + fi +} + +set_trace() { + # Print the script name and line number of each command as it is + # executed when using trace. + if [[ ${TRACE:-"YES"} == "YES" ]]; then + set -x + fi +} + +postamble() { + # + # Commands to execute when a script ends. + # + # Syntax: + # postamble script start_time rc + # + # Arguments: + # script: name of the script ending + # start_time: start time of script (in seconds) + # rc: the exit code of the script + # + + set +x + script="${1}" + start_time="${2}" + rc="${3}" + + # Execute postamble command + # + # Commands can be added to the postamble by appending them to $POSTAMBLE_CMD: + # POSTAMBLE_CMD="new_thing; ${POSTAMBLE_CMD:-}" # (before existing commands) + # POSTAMBLE_CMD="${POSTAMBLE_CMD:-}; new_thing" # (after existing commands) + # + # Always use this form so previous POSTAMBLE_CMD are not overwritten. This should + # only be used for commands that execute conditionally (i.e. on certain machines + # or jobs). Global changes should just be added to this function. + # These commands will be called when EACH SCRIPT terminates, so be mindful. Please + # consult with global-workflow CMs about permanent changes to $POSTAMBLE_CMD or + # this postamble function. + # + + if [[ -v 'POSTAMBLE_CMD' ]]; then + ${POSTAMBLE_CMD} + fi + + # Calculate the elapsed time + end_time=$(date +%s) + end_time_human=$(date -d@"${end_time}" -u +%H:%M:%S) + elapsed_sec=$((end_time - start_time)) + elapsed=$(date -d@"${elapsed_sec}" -u +%H:%M:%S) + + # Announce the script has ended, then pass the error code up + echo "End ${script} at ${end_time_human} with error code ${rc:-0} (time elapsed: ${elapsed})" + exit "${rc}" +} + +# Place the postamble in a trap so it is always called no matter how the script exits +# Shellcheck: Turn off warning about substitions at runtime instead of signal time +# shellcheck disable=SC2064 +trap "postamble ${_calling_script} ${start_time} \$?" EXIT +# shellcheck disable= + +source "${HOMEobsforge}/ush/bash_utils.sh" + +# Turn on our settings +set_strict +set_trace From 8a7fc32105edcf9db1acdc1c7a04bed4aaf5869f Mon Sep 17 00:00:00 2001 From: CoryMartin-NOAA Date: Mon, 17 Mar 2025 20:36:25 +0000 Subject: [PATCH 02/17] add sample XML --- parm/obsforge_test_hera.xml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 parm/obsforge_test_hera.xml diff --git a/parm/obsforge_test_hera.xml b/parm/obsforge_test_hera.xml new file mode 100644 index 00000000..68764ff5 --- /dev/null +++ b/parm/obsforge_test_hera.xml @@ -0,0 +1,23 @@ + + + + + + +]> + + + + /scratch2/NCEPDEV/stmp1/Cory.R.Martin/mar2025/stat_workflow//EXPDIR/stat_wcda/logs/@Y@m@d@H.log + + + 202103250000 202103250000 06:00:00 + 202103250000 202103250000 06:00:00 + + From 731413b3d741149decf8e0b7eba408db435911a3 Mon Sep 17 00:00:00 2001 From: CoryMartin-NOAA Date: Tue, 18 Mar 2025 16:38:47 +0000 Subject: [PATCH 03/17] save before some testing --- jobs/rocoto/aoddump.sh | 20 ++++++++++ parm/obsforge_test_hera.xml | 76 +++++++++++++++++++++++++++++++++--- ush/load_obsforge_modules.sh | 56 ++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 jobs/rocoto/aoddump.sh create mode 100644 ush/load_obsforge_modules.sh diff --git a/jobs/rocoto/aoddump.sh b/jobs/rocoto/aoddump.sh new file mode 100644 index 00000000..2ca29702 --- /dev/null +++ b/jobs/rocoto/aoddump.sh @@ -0,0 +1,20 @@ +#! /usr/bin/env bash + +source "${HOMEobsforge}/ush/preamble.sh" + +############################################################### +# Source UFSDA workflow modules +. "${HOMEobsforge}/ush/load_obsforge_modules.sh" +status=$? +if [[ ${status} -ne 0 ]]; then + exit "${status}" +fi + +export job="aoddump" +export jobid="${job}.$$" + +############################################################### +# Execute the JJOB +"${HOMEobsforge}/jobs/JOBSFORGE_GLOBAL_AOD_DUMP" +status=$? +exit "${status}" \ No newline at end of file diff --git a/parm/obsforge_test_hera.xml b/parm/obsforge_test_hera.xml index 68764ff5..0c4c3a73 100644 --- a/parm/obsforge_test_hera.xml +++ b/parm/obsforge_test_hera.xml @@ -6,18 +6,82 @@ Main workflow manager for ObsForge --> - - - + + + ]> - /scratch2/NCEPDEV/stmp1/Cory.R.Martin/mar2025/stat_workflow//EXPDIR/stat_wcda/logs/@Y@m@d@H.log + /scratch2/NCEPDEV/stmp1/Cory.R.Martin/obsforge/COMROOT/obsforge/logs/@Y@m@d@H.log - 202103250000 202103250000 06:00:00 - 202103250000 202103250000 06:00:00 + 202503160000 202503170000 06:00:00 + 202503160000 202503170000 06:00:00 + + + + /scratch2/NCEPDEV/stmp1/Cory.R.Martin/mar2025/obsforge/jobs/rocoto/aoddump.sh + + obsforge_gfs_aod_dump_@H + da-cpu + batch + hera + 00:30:00 + 1:ppn=1:tpp=1 + 96GB + --export=NONE + + /scratch2/NCEPDEV/stmp1/Cory.R.Martin/obsforge/COMROOT/obsforge/logs/@Y@m@d@H/gfs_aod_dump_prep.log + + RUN_ENVIRemc + HOMEobsforge/scratch2/NCEPDEV/stmp1/Cory.R.Martin/mar2025/obsforge/ + NETgfs + RUNgfs + CDATE@Y@m@d@H + PDY@Y@m@d + cyc@H + COMROOT/scratch2/NCEPDEV/stmp1/Cory.R.Martin/obsforge/COMROOT/obsforge/ + DATAROOT/scratch1/NCEPDEV/stmp2/Cory.R.Martin/RUNDIRS/obsforge/gfs.@Y@m@d@H + + + + + + + + /scratch2/NCEPDEV/stmp1/Cory.R.Martin/mar2025/obsforge/jobs/rocoto/aoddump.sh + + obsforge_gdas_aod_dump_@H + da-cpu + batch + hera + 00:30:00 + 1:ppn=1:tpp=1 + 96GB + --export=NONE + + /scratch2/NCEPDEV/stmp1/Cory.R.Martin/obsforge/COMROOT/obsforge/logs/@Y@m@d@H/gdas_aod_dump_prep.log + + RUN_ENVIRemc + HOMEobsforge/scratch2/NCEPDEV/stmp1/Cory.R.Martin/mar2025/obsforge/ + NETgfs + RUNgdas + CDATE@Y@m@d@H + PDY@Y@m@d + cyc@H + COMROOT/scratch2/NCEPDEV/stmp1/Cory.R.Martin/obsforge/COMROOT/obsforge/ + DATAROOT/scratch1/NCEPDEV/stmp2/Cory.R.Martin/RUNDIRS/obsforge/gdas.@Y@m@d@H + + + + diff --git a/ush/load_obsforge_modules.sh b/ush/load_obsforge_modules.sh new file mode 100644 index 00000000..41a0d9b2 --- /dev/null +++ b/ush/load_obsforge_modules.sh @@ -0,0 +1,56 @@ +#! /usr/bin/env bash + +############################################################### +if [[ "${DEBUG_WORKFLOW:-NO}" == "NO" ]]; then + echo "Loading modules quietly..." + set +x +fi + +MODS="obsforge" + +# Setup runtime environment by loading modules +ulimit_s=$( ulimit -S -s ) + +# Find module command and purge: +source "${HOMEobsforge}/ush/detect_machine.sh" +source "${HOMEobsforge}/ush/module-setup.sh" + +# Load our modules: +module use "${HOMEobsforge}/modulefiles" + +case "${MACHINE_ID}" in + ("hera" | "orion" | "hercules" | "wcoss2" | "gaeac5" | "gaeac6") + #TODO: Remove LMOD_TMOD_FIND_FIRST line when spack-stack on WCOSS2 + if [[ "${MACHINE_ID}" == "wcoss2" ]]; then + export LMOD_TMOD_FIND_FIRST=yes + # TODO: Add path to ObsForge libraries and cray-mpich as temporary patches + # TODO: Remove LD_LIBRARY_PATH lines as soon as permanent solutions are available + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${HOMEobsforge}/build/lib" + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/cray/pe/mpich/8.1.19/ofi/intel/19.0/lib" + fi + module load "${MODS}/${MACHINE_ID}" + ncdump=$( command -v ncdump ) + NETCDF=$( echo "${ncdump}" | cut -d " " -f 3 ) + export NETCDF + ;; + ("jet" | "s4" | "acorn") + echo WARNING: OBSFORGE NOT SUPPORTED ON THIS PLATFORM + ;; + *) + echo "WARNING: UNKNOWN PLATFORM" + ;; +esac + +module list +pip list + +# Add wxflow to PYTHONPATH +wxflowPATH="${HOMEobsforge}/ush/python" +PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${HOMEobsforge}/ush:${wxflowPATH}" +export PYTHONPATH + +# Restore stack soft limit: +ulimit -S -s "${ulimit_s}" +unset ulimit_s + +set_trace \ No newline at end of file From f7fa5dde29d83531c760abf4aad5f60acf23ba0b Mon Sep 17 00:00:00 2001 From: CoryMartin-NOAA Date: Tue, 18 Mar 2025 17:00:50 +0000 Subject: [PATCH 04/17] working with dummy hello script --- .gitignore | 3 +++ jobs/JOBSFORGE_GLOBAL_AOD_DUMP | 4 ++-- jobs/rocoto/aoddump.sh | 0 parm/obsforge_test_hera.xml | 4 +++- 4 files changed, 8 insertions(+), 3 deletions(-) mode change 100644 => 100755 jobs/rocoto/aoddump.sh diff --git a/.gitignore b/.gitignore index 595f5168..df6c6f2c 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,6 @@ install*/ /sorc/obsforge-utils !/bundle/CMakeLists.txt /bundle/* + +# rocoto +*.db diff --git a/jobs/JOBSFORGE_GLOBAL_AOD_DUMP b/jobs/JOBSFORGE_GLOBAL_AOD_DUMP index 21a73789..c66713f8 100755 --- a/jobs/JOBSFORGE_GLOBAL_AOD_DUMP +++ b/jobs/JOBSFORGE_GLOBAL_AOD_DUMP @@ -1,7 +1,7 @@ #! /usr/bin/env bash source "${HOMEobsforge}/ush/preamble.sh" -#source "${HOMEobsforge}/ush/jjob_header.sh" +source "${HOMEobsforge}/ush/jjob_header.sh" ############################################## # Set variables used in the script @@ -15,7 +15,7 @@ source "${HOMEobsforge}/ush/preamble.sh" ############################################################### # Run relevant script -EXSCRIPT=${DUMPAODPY:-${SCRobsforge}/exobsforge_global_aod_dump.py} +EXSCRIPT=${DUMPAODPY:-${HOMEobsforge}/scripts/exobsforge_global_aod_dump.py} ${EXSCRIPT} status=$? if [[ ${status} -ne 0 ]]; then diff --git a/jobs/rocoto/aoddump.sh b/jobs/rocoto/aoddump.sh old mode 100644 new mode 100755 diff --git a/parm/obsforge_test_hera.xml b/parm/obsforge_test_hera.xml index 0c4c3a73..3ed02f74 100644 --- a/parm/obsforge_test_hera.xml +++ b/parm/obsforge_test_hera.xml @@ -12,7 +12,7 @@ ]> - + /scratch2/NCEPDEV/stmp1/Cory.R.Martin/obsforge/COMROOT/obsforge/logs/@Y@m@d@H.log @@ -42,6 +42,7 @@ CDATE@Y@m@d@H PDY@Y@m@d cyc@H + KEEPDATANO COMROOT/scratch2/NCEPDEV/stmp1/Cory.R.Martin/obsforge/COMROOT/obsforge/ DATAROOT/scratch1/NCEPDEV/stmp2/Cory.R.Martin/RUNDIRS/obsforge/gfs.@Y@m@d@H @@ -74,6 +75,7 @@ CDATE@Y@m@d@H PDY@Y@m@d cyc@H + KEEPDATANO COMROOT/scratch2/NCEPDEV/stmp1/Cory.R.Martin/obsforge/COMROOT/obsforge/ DATAROOT/scratch1/NCEPDEV/stmp2/Cory.R.Martin/RUNDIRS/obsforge/gdas.@Y@m@d@H From b4b51856eb0eca98adbff7043c19a7af6cbce91f Mon Sep 17 00:00:00 2001 From: CoryMartin-NOAA Date: Tue, 18 Mar 2025 18:26:42 +0000 Subject: [PATCH 05/17] move COMROOT --- parm/obsforge_test_hera.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/parm/obsforge_test_hera.xml b/parm/obsforge_test_hera.xml index 3ed02f74..dc59281f 100644 --- a/parm/obsforge_test_hera.xml +++ b/parm/obsforge_test_hera.xml @@ -43,7 +43,8 @@ PDY@Y@m@d cyc@H KEEPDATANO - COMROOT/scratch2/NCEPDEV/stmp1/Cory.R.Martin/obsforge/COMROOT/obsforge/ + COMROOT/scratch2/NCEPDEV/stmp1/Cory.R.Martin/com + DCOMROOT/scratch2/NCEPDEV/stmp1/Cory.R.Martin/dcom DATAROOT/scratch1/NCEPDEV/stmp2/Cory.R.Martin/RUNDIRS/obsforge/gfs.@Y@m@d@H