From 61f825329284527ca1dec8859df2d9b28756aaaf Mon Sep 17 00:00:00 2001 From: danielabdi-noaa <52012304+danielabdi-noaa@users.noreply.github.com> Date: Fri, 21 Oct 2022 13:03:50 -0600 Subject: [PATCH 01/45] [develop] Replace TCL modulefiles with Lua counterparts (#413) * Convert modulefiles to Lua. * Fix for orion build. * Fix for cheyenne, but issue with load_any remains. * Bug fix for jet data locations. * Hack for Cheyenne: Emulate load_any with try_load + isloaded combo * Fix NCO mode non-ensemble run dependency issue. * Wcoss2 bug fix thanks to @chan-hoo * Remove conda activation message from wcoss2 modulefile. --- devbuild.sh | 2 +- modulefiles/build_cheyenne_gnu | 39 -------- modulefiles/build_cheyenne_gnu.lua | 38 ++++++++ modulefiles/build_cheyenne_intel | 37 ------- modulefiles/build_cheyenne_intel.lua | 36 +++++++ modulefiles/build_gaea_intel | 27 ------ modulefiles/build_gaea_intel.lua | 27 ++++++ modulefiles/build_hera_intel | 31 ------ modulefiles/build_hera_intel.lua | 27 ++++++ modulefiles/build_jet_intel | 31 ------ modulefiles/build_jet_intel.lua | 28 ++++++ modulefiles/build_linux_gnu | 91 ----------------- modulefiles/build_linux_gnu.lua | 87 +++++++++++++++++ modulefiles/build_macos_gnu | 90 ----------------- modulefiles/build_macos_gnu.lua | 97 +++++++++++++++++++ modulefiles/build_noaacloud_intel | 14 --- modulefiles/build_noaacloud_intel.lua | 18 ++++ modulefiles/build_odin_intel | 54 ----------- modulefiles/build_odin_intel.lua | 52 ++++++++++ modulefiles/build_orion_intel | 28 ------ modulefiles/build_orion_intel.lua | 28 ++++++ modulefiles/build_singularity_gnu | 43 -------- modulefiles/build_singularity_gnu.lua | 40 ++++++++ modulefiles/build_wcoss2_intel | 51 ---------- modulefiles/build_wcoss2_intel.lua | 49 ++++++++++ modulefiles/srw_common | 33 ------- modulefiles/srw_common.lua | 41 ++++++++ .../tasks/cheyenne/conda_regional_workflow | 5 - .../cheyenne/conda_regional_workflow.lua | 3 + .../tasks/cheyenne/get_extrn_ics.local | 4 - .../tasks/cheyenne/get_extrn_ics.local.lua | 1 + .../tasks/cheyenne/get_extrn_lbcs.local | 4 - .../tasks/cheyenne/get_extrn_lbcs.local.lua | 1 + modulefiles/tasks/cheyenne/make_grid.local | 2 - .../tasks/cheyenne/make_grid.local.lua | 1 + modulefiles/tasks/cheyenne/make_ics.local | 2 - modulefiles/tasks/cheyenne/make_ics.local.lua | 1 + modulefiles/tasks/cheyenne/make_lbcs.local | 2 - .../tasks/cheyenne/make_lbcs.local.lua | 1 + .../tasks/cheyenne/make_orog.hardcoded | 9 -- .../tasks/cheyenne/make_orog.hardcoded.lua | 4 + modulefiles/tasks/cheyenne/run_fcst.local | 2 - modulefiles/tasks/cheyenne/run_fcst.local.lua | 1 + modulefiles/tasks/cheyenne/run_vx.local | 2 - modulefiles/tasks/cheyenne/run_vx.local.lua | 1 + modulefiles/tasks/gaea/get_extrn_ics.local | 3 - .../tasks/gaea/get_extrn_ics.local.lua | 1 + modulefiles/tasks/gaea/get_extrn_lbcs.local | 3 - .../tasks/gaea/get_extrn_lbcs.local.lua | 1 + modulefiles/tasks/gaea/make_grid.local | 3 - modulefiles/tasks/gaea/make_grid.local.lua | 1 + modulefiles/tasks/gaea/make_ics.local | 3 - modulefiles/tasks/gaea/make_ics.local.lua | 1 + modulefiles/tasks/gaea/make_lbcs.local | 3 - modulefiles/tasks/gaea/make_lbcs.local.lua | 1 + modulefiles/tasks/gaea/make_orog.local | 3 - modulefiles/tasks/gaea/make_orog.local.lua | 1 + .../tasks/gaea/miniconda_regional_workflow | 6 -- .../gaea/miniconda_regional_workflow.lua | 4 + modulefiles/tasks/gaea/run_fcst.local | 3 - modulefiles/tasks/gaea/run_fcst.local.lua | 1 + modulefiles/tasks/gaea/run_vx.local | 5 - modulefiles/tasks/gaea/run_vx.local.lua | 2 + modulefiles/tasks/hera/get_extrn_ics.local | 7 -- .../tasks/hera/get_extrn_ics.local.lua | 2 + modulefiles/tasks/hera/get_extrn_lbcs.local | 7 -- .../tasks/hera/get_extrn_lbcs.local.lua | 2 + modulefiles/tasks/hera/get_obs.local | 11 --- modulefiles/tasks/hera/get_obs.local.lua | 5 + modulefiles/tasks/hera/make_grid.local | 3 - modulefiles/tasks/hera/make_grid.local.lua | 1 + modulefiles/tasks/hera/make_ics.local | 3 - modulefiles/tasks/hera/make_ics.local.lua | 1 + modulefiles/tasks/hera/make_lbcs.local | 2 - modulefiles/tasks/hera/make_lbcs.local.lua | 1 + .../tasks/hera/miniconda_regional_workflow | 5 - .../hera/miniconda_regional_workflow.lua | 4 + modulefiles/tasks/hera/run_fcst.local | 2 - modulefiles/tasks/hera/run_fcst.local.lua | 1 + modulefiles/tasks/hera/run_vx.local | 5 - modulefiles/tasks/hera/run_vx.local.lua | 3 + modulefiles/tasks/jet/get_extrn_ics.local | 9 -- modulefiles/tasks/jet/get_extrn_ics.local.lua | 2 + modulefiles/tasks/jet/get_extrn_lbcs.local | 9 -- .../tasks/jet/get_extrn_lbcs.local.lua | 2 + modulefiles/tasks/jet/make_grid.local | 3 - modulefiles/tasks/jet/make_grid.local.lua | 1 + modulefiles/tasks/jet/make_ics.local | 2 - modulefiles/tasks/jet/make_ics.local.lua | 1 + modulefiles/tasks/jet/make_lbcs.local | 2 - modulefiles/tasks/jet/make_lbcs.local.lua | 1 + .../tasks/jet/miniconda_regional_workflow | 5 - .../tasks/jet/miniconda_regional_workflow.lua | 4 + modulefiles/tasks/jet/run_fcst.local | 2 - modulefiles/tasks/jet/run_fcst.local.lua | 1 + modulefiles/tasks/jet/run_vx.local | 5 - modulefiles/tasks/jet/run_vx.local.lua | 3 + .../tasks/noaacloud/get_extrn_ics.local | 6 -- .../tasks/noaacloud/get_extrn_ics.local.lua | 1 + .../tasks/noaacloud/get_extrn_lbcs.local | 5 - .../tasks/noaacloud/get_extrn_lbcs.local.lua | 1 + modulefiles/tasks/noaacloud/make_grid.local | 11 --- .../tasks/noaacloud/make_grid.local.lua | 1 + modulefiles/tasks/noaacloud/make_ics.local | 13 --- .../tasks/noaacloud/make_ics.local.lua | 1 + modulefiles/tasks/noaacloud/make_lbcs.local | 13 --- .../tasks/noaacloud/make_lbcs.local.lua | 1 + modulefiles/tasks/noaacloud/make_orog.local | 11 --- .../tasks/noaacloud/make_orog.local.lua | 1 + .../tasks/noaacloud/make_sfc_climo.local | 11 --- .../tasks/noaacloud/make_sfc_climo.local.lua | 1 + .../noaacloud/miniconda_regional_workflow | 5 - .../noaacloud/miniconda_regional_workflow.lua | 4 + modulefiles/tasks/noaacloud/run_fcst.local | 13 --- .../tasks/noaacloud/run_fcst.local.lua | 1 + modulefiles/tasks/noaacloud/run_post.local | 13 --- .../tasks/noaacloud/run_post.local.lua | 1 + modulefiles/tasks/odin/get_extrn_ics.local | 8 -- .../tasks/odin/get_extrn_ics.local.lua | 0 modulefiles/tasks/odin/get_extrn_lbcs.local | 8 -- .../tasks/odin/get_extrn_lbcs.local.lua | 0 modulefiles/tasks/orion/get_extrn_ics.local | 6 -- .../tasks/orion/get_extrn_ics.local.lua | 1 + modulefiles/tasks/orion/get_extrn_lbcs.local | 5 - .../tasks/orion/get_extrn_lbcs.local.lua | 1 + modulefiles/tasks/orion/make_grid.local | 3 - modulefiles/tasks/orion/make_grid.local.lua | 1 + modulefiles/tasks/orion/make_ics.local | 2 - modulefiles/tasks/orion/make_ics.local.lua | 1 + modulefiles/tasks/orion/make_lbcs.local | 2 - modulefiles/tasks/orion/make_lbcs.local.lua | 1 + .../tasks/orion/miniconda_regional_workflow | 5 - .../orion/miniconda_regional_workflow.lua | 4 + modulefiles/tasks/orion/run_fcst.local | 2 - modulefiles/tasks/orion/run_fcst.local.lua | 1 + .../tasks/stampede/get_extrn_ics.local | 8 -- .../tasks/stampede/get_extrn_ics.local.lua | 0 .../tasks/stampede/get_extrn_lbcs.local | 8 -- .../tasks/stampede/get_extrn_lbcs.local.lua | 0 modulefiles/tasks/wcoss2/get_extrn_ics.local | 4 - .../tasks/wcoss2/get_extrn_ics.local.lua | 2 + modulefiles/tasks/wcoss2/get_extrn_lbcs.local | 4 - .../tasks/wcoss2/get_extrn_lbcs.local.lua | 2 + modulefiles/tasks/wcoss2/get_obs.local | 4 - modulefiles/tasks/wcoss2/get_obs.local.lua | 2 + modulefiles/tasks/wcoss2/make_grid.local | 4 - modulefiles/tasks/wcoss2/make_grid.local.lua | 2 + modulefiles/tasks/wcoss2/make_ics.local | 4 - modulefiles/tasks/wcoss2/make_ics.local.lua | 2 + modulefiles/tasks/wcoss2/make_lbcs.local | 4 - modulefiles/tasks/wcoss2/make_lbcs.local.lua | 2 + modulefiles/tasks/wcoss2/run_fcst.local | 4 - modulefiles/tasks/wcoss2/run_fcst.local.lua | 2 + modulefiles/tasks/wcoss2/run_vx.local | 4 - modulefiles/tasks/wcoss2/run_vx.local.lua | 2 + modulefiles/wflow_cheyenne | 20 ---- modulefiles/wflow_cheyenne.lua | 20 ++++ modulefiles/wflow_gaea | 21 ---- modulefiles/wflow_gaea.lua | 19 ++++ modulefiles/wflow_hera | 19 ---- modulefiles/wflow_hera.lua | 17 ++++ modulefiles/wflow_jet | 19 ---- modulefiles/wflow_jet.lua | 17 ++++ modulefiles/wflow_linux | 29 ------ modulefiles/wflow_linux.lua | 26 +++++ modulefiles/wflow_macos | 31 ------ modulefiles/wflow_macos.lua | 26 +++++ modulefiles/wflow_noaacloud | 23 ----- modulefiles/wflow_noaacloud.lua | 22 +++++ modulefiles/wflow_odin | 42 -------- modulefiles/wflow_odin.lua | 33 +++++++ modulefiles/wflow_orion | 19 ---- modulefiles/wflow_orion.lua | 19 ++++ modulefiles/wflow_singularity | 16 --- modulefiles/wflow_singularity.lua | 13 +++ modulefiles/wflow_wcoss2 | 14 --- modulefiles/wflow_wcoss2.lua | 13 +++ parm/FV3LAM_wflow.xml | 5 + ush/load_modules_run_task.sh | 2 +- ush/load_modules_wflow.sh | 3 +- ush/machine/jet.yaml | 6 +- ush/python_utils/environment.py | 2 +- ush/setup.py | 14 ++- 183 files changed, 913 insertions(+), 1173 deletions(-) delete mode 100644 modulefiles/build_cheyenne_gnu create mode 100644 modulefiles/build_cheyenne_gnu.lua delete mode 100644 modulefiles/build_cheyenne_intel create mode 100644 modulefiles/build_cheyenne_intel.lua delete mode 100644 modulefiles/build_gaea_intel create mode 100644 modulefiles/build_gaea_intel.lua delete mode 100644 modulefiles/build_hera_intel create mode 100644 modulefiles/build_hera_intel.lua delete mode 100644 modulefiles/build_jet_intel create mode 100644 modulefiles/build_jet_intel.lua delete mode 100644 modulefiles/build_linux_gnu create mode 100644 modulefiles/build_linux_gnu.lua delete mode 100644 modulefiles/build_macos_gnu create mode 100644 modulefiles/build_macos_gnu.lua delete mode 100644 modulefiles/build_noaacloud_intel create mode 100644 modulefiles/build_noaacloud_intel.lua delete mode 100644 modulefiles/build_odin_intel create mode 100644 modulefiles/build_odin_intel.lua delete mode 100644 modulefiles/build_orion_intel create mode 100644 modulefiles/build_orion_intel.lua delete mode 100644 modulefiles/build_singularity_gnu create mode 100644 modulefiles/build_singularity_gnu.lua delete mode 100644 modulefiles/build_wcoss2_intel create mode 100644 modulefiles/build_wcoss2_intel.lua delete mode 100644 modulefiles/srw_common create mode 100644 modulefiles/srw_common.lua delete mode 100644 modulefiles/tasks/cheyenne/conda_regional_workflow create mode 100644 modulefiles/tasks/cheyenne/conda_regional_workflow.lua delete mode 100644 modulefiles/tasks/cheyenne/get_extrn_ics.local create mode 100644 modulefiles/tasks/cheyenne/get_extrn_ics.local.lua delete mode 100644 modulefiles/tasks/cheyenne/get_extrn_lbcs.local create mode 100644 modulefiles/tasks/cheyenne/get_extrn_lbcs.local.lua delete mode 100644 modulefiles/tasks/cheyenne/make_grid.local create mode 100644 modulefiles/tasks/cheyenne/make_grid.local.lua delete mode 100644 modulefiles/tasks/cheyenne/make_ics.local create mode 100644 modulefiles/tasks/cheyenne/make_ics.local.lua delete mode 100644 modulefiles/tasks/cheyenne/make_lbcs.local create mode 100644 modulefiles/tasks/cheyenne/make_lbcs.local.lua delete mode 100644 modulefiles/tasks/cheyenne/make_orog.hardcoded create mode 100644 modulefiles/tasks/cheyenne/make_orog.hardcoded.lua delete mode 100644 modulefiles/tasks/cheyenne/run_fcst.local create mode 100644 modulefiles/tasks/cheyenne/run_fcst.local.lua delete mode 100644 modulefiles/tasks/cheyenne/run_vx.local create mode 100644 modulefiles/tasks/cheyenne/run_vx.local.lua delete mode 100644 modulefiles/tasks/gaea/get_extrn_ics.local create mode 100644 modulefiles/tasks/gaea/get_extrn_ics.local.lua delete mode 100644 modulefiles/tasks/gaea/get_extrn_lbcs.local create mode 100644 modulefiles/tasks/gaea/get_extrn_lbcs.local.lua delete mode 100644 modulefiles/tasks/gaea/make_grid.local create mode 100644 modulefiles/tasks/gaea/make_grid.local.lua delete mode 100644 modulefiles/tasks/gaea/make_ics.local create mode 100644 modulefiles/tasks/gaea/make_ics.local.lua delete mode 100644 modulefiles/tasks/gaea/make_lbcs.local create mode 100644 modulefiles/tasks/gaea/make_lbcs.local.lua delete mode 100644 modulefiles/tasks/gaea/make_orog.local create mode 100644 modulefiles/tasks/gaea/make_orog.local.lua delete mode 100644 modulefiles/tasks/gaea/miniconda_regional_workflow create mode 100644 modulefiles/tasks/gaea/miniconda_regional_workflow.lua delete mode 100644 modulefiles/tasks/gaea/run_fcst.local create mode 100644 modulefiles/tasks/gaea/run_fcst.local.lua delete mode 100644 modulefiles/tasks/gaea/run_vx.local create mode 100644 modulefiles/tasks/gaea/run_vx.local.lua delete mode 100644 modulefiles/tasks/hera/get_extrn_ics.local create mode 100644 modulefiles/tasks/hera/get_extrn_ics.local.lua delete mode 100644 modulefiles/tasks/hera/get_extrn_lbcs.local create mode 100644 modulefiles/tasks/hera/get_extrn_lbcs.local.lua delete mode 100644 modulefiles/tasks/hera/get_obs.local create mode 100644 modulefiles/tasks/hera/get_obs.local.lua delete mode 100644 modulefiles/tasks/hera/make_grid.local create mode 100644 modulefiles/tasks/hera/make_grid.local.lua delete mode 100644 modulefiles/tasks/hera/make_ics.local create mode 100644 modulefiles/tasks/hera/make_ics.local.lua delete mode 100644 modulefiles/tasks/hera/make_lbcs.local create mode 100644 modulefiles/tasks/hera/make_lbcs.local.lua delete mode 100644 modulefiles/tasks/hera/miniconda_regional_workflow create mode 100644 modulefiles/tasks/hera/miniconda_regional_workflow.lua delete mode 100644 modulefiles/tasks/hera/run_fcst.local create mode 100644 modulefiles/tasks/hera/run_fcst.local.lua delete mode 100644 modulefiles/tasks/hera/run_vx.local create mode 100644 modulefiles/tasks/hera/run_vx.local.lua delete mode 100644 modulefiles/tasks/jet/get_extrn_ics.local create mode 100644 modulefiles/tasks/jet/get_extrn_ics.local.lua delete mode 100644 modulefiles/tasks/jet/get_extrn_lbcs.local create mode 100644 modulefiles/tasks/jet/get_extrn_lbcs.local.lua delete mode 100644 modulefiles/tasks/jet/make_grid.local create mode 100644 modulefiles/tasks/jet/make_grid.local.lua delete mode 100644 modulefiles/tasks/jet/make_ics.local create mode 100644 modulefiles/tasks/jet/make_ics.local.lua delete mode 100644 modulefiles/tasks/jet/make_lbcs.local create mode 100644 modulefiles/tasks/jet/make_lbcs.local.lua delete mode 100644 modulefiles/tasks/jet/miniconda_regional_workflow create mode 100644 modulefiles/tasks/jet/miniconda_regional_workflow.lua delete mode 100644 modulefiles/tasks/jet/run_fcst.local create mode 100644 modulefiles/tasks/jet/run_fcst.local.lua delete mode 100644 modulefiles/tasks/jet/run_vx.local create mode 100644 modulefiles/tasks/jet/run_vx.local.lua delete mode 100644 modulefiles/tasks/noaacloud/get_extrn_ics.local create mode 100644 modulefiles/tasks/noaacloud/get_extrn_ics.local.lua delete mode 100644 modulefiles/tasks/noaacloud/get_extrn_lbcs.local create mode 100644 modulefiles/tasks/noaacloud/get_extrn_lbcs.local.lua delete mode 100644 modulefiles/tasks/noaacloud/make_grid.local create mode 100644 modulefiles/tasks/noaacloud/make_grid.local.lua delete mode 100644 modulefiles/tasks/noaacloud/make_ics.local create mode 100644 modulefiles/tasks/noaacloud/make_ics.local.lua delete mode 100644 modulefiles/tasks/noaacloud/make_lbcs.local create mode 100644 modulefiles/tasks/noaacloud/make_lbcs.local.lua delete mode 100644 modulefiles/tasks/noaacloud/make_orog.local create mode 100644 modulefiles/tasks/noaacloud/make_orog.local.lua delete mode 100644 modulefiles/tasks/noaacloud/make_sfc_climo.local create mode 100644 modulefiles/tasks/noaacloud/make_sfc_climo.local.lua delete mode 100644 modulefiles/tasks/noaacloud/miniconda_regional_workflow create mode 100644 modulefiles/tasks/noaacloud/miniconda_regional_workflow.lua delete mode 100644 modulefiles/tasks/noaacloud/run_fcst.local create mode 100644 modulefiles/tasks/noaacloud/run_fcst.local.lua delete mode 100644 modulefiles/tasks/noaacloud/run_post.local create mode 100644 modulefiles/tasks/noaacloud/run_post.local.lua delete mode 100644 modulefiles/tasks/odin/get_extrn_ics.local create mode 100644 modulefiles/tasks/odin/get_extrn_ics.local.lua delete mode 100644 modulefiles/tasks/odin/get_extrn_lbcs.local create mode 100644 modulefiles/tasks/odin/get_extrn_lbcs.local.lua delete mode 100644 modulefiles/tasks/orion/get_extrn_ics.local create mode 100644 modulefiles/tasks/orion/get_extrn_ics.local.lua delete mode 100644 modulefiles/tasks/orion/get_extrn_lbcs.local create mode 100644 modulefiles/tasks/orion/get_extrn_lbcs.local.lua delete mode 100644 modulefiles/tasks/orion/make_grid.local create mode 100644 modulefiles/tasks/orion/make_grid.local.lua delete mode 100644 modulefiles/tasks/orion/make_ics.local create mode 100644 modulefiles/tasks/orion/make_ics.local.lua delete mode 100644 modulefiles/tasks/orion/make_lbcs.local create mode 100644 modulefiles/tasks/orion/make_lbcs.local.lua delete mode 100644 modulefiles/tasks/orion/miniconda_regional_workflow create mode 100644 modulefiles/tasks/orion/miniconda_regional_workflow.lua delete mode 100644 modulefiles/tasks/orion/run_fcst.local create mode 100644 modulefiles/tasks/orion/run_fcst.local.lua delete mode 100644 modulefiles/tasks/stampede/get_extrn_ics.local create mode 100644 modulefiles/tasks/stampede/get_extrn_ics.local.lua delete mode 100644 modulefiles/tasks/stampede/get_extrn_lbcs.local create mode 100644 modulefiles/tasks/stampede/get_extrn_lbcs.local.lua delete mode 100644 modulefiles/tasks/wcoss2/get_extrn_ics.local create mode 100644 modulefiles/tasks/wcoss2/get_extrn_ics.local.lua delete mode 100644 modulefiles/tasks/wcoss2/get_extrn_lbcs.local create mode 100644 modulefiles/tasks/wcoss2/get_extrn_lbcs.local.lua delete mode 100644 modulefiles/tasks/wcoss2/get_obs.local create mode 100644 modulefiles/tasks/wcoss2/get_obs.local.lua delete mode 100644 modulefiles/tasks/wcoss2/make_grid.local create mode 100644 modulefiles/tasks/wcoss2/make_grid.local.lua delete mode 100644 modulefiles/tasks/wcoss2/make_ics.local create mode 100644 modulefiles/tasks/wcoss2/make_ics.local.lua delete mode 100644 modulefiles/tasks/wcoss2/make_lbcs.local create mode 100644 modulefiles/tasks/wcoss2/make_lbcs.local.lua delete mode 100644 modulefiles/tasks/wcoss2/run_fcst.local create mode 100644 modulefiles/tasks/wcoss2/run_fcst.local.lua delete mode 100644 modulefiles/tasks/wcoss2/run_vx.local create mode 100644 modulefiles/tasks/wcoss2/run_vx.local.lua delete mode 100644 modulefiles/wflow_cheyenne create mode 100644 modulefiles/wflow_cheyenne.lua delete mode 100644 modulefiles/wflow_gaea create mode 100644 modulefiles/wflow_gaea.lua delete mode 100644 modulefiles/wflow_hera create mode 100644 modulefiles/wflow_hera.lua delete mode 100644 modulefiles/wflow_jet create mode 100644 modulefiles/wflow_jet.lua delete mode 100644 modulefiles/wflow_linux create mode 100644 modulefiles/wflow_linux.lua delete mode 100644 modulefiles/wflow_macos create mode 100644 modulefiles/wflow_macos.lua delete mode 100644 modulefiles/wflow_noaacloud create mode 100644 modulefiles/wflow_noaacloud.lua delete mode 100644 modulefiles/wflow_odin create mode 100644 modulefiles/wflow_odin.lua delete mode 100644 modulefiles/wflow_orion create mode 100644 modulefiles/wflow_orion.lua delete mode 100644 modulefiles/wflow_singularity create mode 100644 modulefiles/wflow_singularity.lua delete mode 100644 modulefiles/wflow_wcoss2 create mode 100644 modulefiles/wflow_wcoss2.lua diff --git a/devbuild.sh b/devbuild.sh index 045611d17d..218a0eeb81 100755 --- a/devbuild.sh +++ b/devbuild.sh @@ -245,7 +245,7 @@ fi # set MODULE_FILE for this platform/compiler combination MODULE_FILE="build_${PLATFORM}_${COMPILER}" -if [ ! -f "${SRW_DIR}/modulefiles/${MODULE_FILE}" ]; then +if [ ! -f "${SRW_DIR}/modulefiles/${MODULE_FILE}.lua" ]; then printf "ERROR: module file does not exist for platform/compiler\n" >&2 printf " MODULE_FILE=${MODULE_FILE}\n" >&2 printf " PLATFORM=${PLATFORM}\n" >&2 diff --git a/modulefiles/build_cheyenne_gnu b/modulefiles/build_cheyenne_gnu deleted file mode 100644 index 0fc0d2b8ad..0000000000 --- a/modulefiles/build_cheyenne_gnu +++ /dev/null @@ -1,39 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW on" - puts stderr "the CISL Cheyenne machine using GNU" -} - -module-whatis "Loads libraries needed for building SRW on Cheyenne" - -module load cmake/3.22.0 -module load python/3.7.9 -module load ncarenv/1.3 -module load gnu/11.2.0 -module load mpt/2.25 -setenv MKLROOT /glade/u/apps/opt/intel/2022.1/mkl/latest -module load ncarcompilers/0.5.0 -module unload netcdf - -module use /glade/work/epicufsrt/GMTB/tools/gnu/11.2.0/hpc-stack-v1.2.0/modulefiles/stack -module load hpc/1.2.0 -module load hpc-gnu/11.2.0 -module load hpc-mpt/2.25 - -module load srw_common - -module load g2/3.4.5 -module load esmf/8.3.0b09 -module load netcdf/4.7.4 -module load libpng/1.6.37 -module load pio/2.5.3 -module load fms/2022.01 - -setenv CMAKE_C_COMPILER mpicc -setenv CMAKE_CXX_COMPILER mpicxx -setenv CMAKE_Fortran_COMPILER mpif90 -setenv CMAKE_Platform cheyenne.gnu -setenv CC mpicc -setenv CXX mpicxx -setenv FC mpif90 diff --git a/modulefiles/build_cheyenne_gnu.lua b/modulefiles/build_cheyenne_gnu.lua new file mode 100644 index 0000000000..6f1dc5d75e --- /dev/null +++ b/modulefiles/build_cheyenne_gnu.lua @@ -0,0 +1,38 @@ +help([[ +This module loads libraries for building the UFS SRW App on +the CISL machine Cheyenne using GNU +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on Cheyenne ]===]) + +load(pathJoin("cmake", os.getenv("cmake_ver") or "3.22.0")) +load(pathJoin("python", os.getenv("python_ver") or "3.7.9")) +load(pathJoin("ncarenv", os.getenv("ncarenv_ver") or "1.3")) +load(pathJoin("gnu", os.getenv("gnu_ver") or "11.2.0")) +load(pathJoin("mpt", os.getenv("mpt_ver") or "2.25")) +setenv("MKLROOT", "/glade/u/apps/opt/intel/2022.1/mkl/latest") +load(pathJoin("ncarcompilers", os.getenv("ncarcompilers_ver") or "0.5.0")) +unload("netcdf") + +prepend_path("MODULEPATH","/glade/work/epicufsrt/GMTB/tools/gnu/11.2.0/hpc-stack-v1.2.0/modulefiles/stack") +load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) +load(pathJoin("hpc-gnu", os.getenv("hpc_gnu_ver") or "11.2.0")) +load(pathJoin("hpc-mpt", os.getenv("hpc_mpt_ver") or "2.25")) + +load("srw_common") + +load(pathJoin("g2", os.getenv("g2_ver") or "3.4.5")) +load(pathJoin("esmf", os.getenv("esmf_ver") or "8.3.0b09")) +load(pathJoin("netcdf", os.getenv("netcdf_ver") or "4.7.4")) +load(pathJoin("libpng", os.getenv("libpng_ver") or "1.6.37")) +load(pathJoin("pio", os.getenv("pio_ver") or "2.5.3")) +load(pathJoin("fms", os.getenv("fms_ver") or "2022.01")) + +setenv("CMAKE_C_COMPILER","mpicc") +setenv("CMAKE_CXX_COMPILER","mpicxx") +setenv("CMAKE_Fortran_COMPILER","mpif90") +setenv("CMAKE_Platform","cheyenne.gnu") +setenv("CC", "mpicc") +setenv("CXX", "mpicxx") +setenv("FC", "mpif90") + diff --git a/modulefiles/build_cheyenne_intel b/modulefiles/build_cheyenne_intel deleted file mode 100644 index 1e1e865542..0000000000 --- a/modulefiles/build_cheyenne_intel +++ /dev/null @@ -1,37 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW on" - puts stderr "the CISL Cheyenne machine using Intel-2022.1" -} - -module-whatis "Loads libraries needed for building SRW on Cheyenne" - -module load cmake/3.22.0 -module load python/3.7.9 -module load ncarenv/1.3 -module load intel/2022.1 -module load mpt/2.25 -module load mkl/2022.1 -module load ncarcompilers/0.5.0 -module unload netcdf - -module use /glade/work/epicufsrt/GMTB/tools/intel/2022.1/hpc-stack-v1.2.0_6eb6/modulefiles/stack -module load hpc/1.2.0 -module load hpc-intel/2022.1 -module load hpc-mpt/2.25 - -module load srw_common - -module load g2/3.4.5 -module load esmf/8.3.0b09 -module load mapl/2.11.0-esmf-8.3.0b09 -module load netcdf/4.7.4 -module load libpng/1.6.37 -module load pio/2.5.3 -module load fms/2022.01 - -setenv CMAKE_C_COMPILER mpicc -setenv CMAKE_CXX_COMPILER mpicxx -setenv CMAKE_Fortran_COMPILER mpif90 -setenv CMAKE_Platform cheyenne.intel diff --git a/modulefiles/build_cheyenne_intel.lua b/modulefiles/build_cheyenne_intel.lua new file mode 100644 index 0000000000..b1ae5b7bc1 --- /dev/null +++ b/modulefiles/build_cheyenne_intel.lua @@ -0,0 +1,36 @@ +help([[ +This module loads libraries for building the UFS SRW App on +the CISL machine Cheyenne using Intel-2022.1 +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on Cheyenne ]===]) + +load(pathJoin("cmake", os.getenv("cmake_ver") or "3.22.0")) +load(pathJoin("python", os.getenv("python_ver") or "3.7.9")) +load(pathJoin("ncarenv", os.getenv("ncarenv_ver") or "1.3")) +load(pathJoin("intel", os.getenv("intel_ver") or "2022.1")) +load(pathJoin("mpt", os.getenv("mpt_ver") or "2.25")) +load(pathJoin("mkl", os.getenv("mkl_ver") or "2022.1")) +load(pathJoin("ncarcompilers", os.getenv("ncarcompilers_ver") or "0.5.0")) +unload("netcdf") + +prepend_path("MODULEPATH","/glade/work/epicufsrt/GMTB/tools/intel/2022.1/hpc-stack-v1.2.0_6eb6/modulefiles/stack") +load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) +load(pathJoin("hpc-intel", os.getenv("hpc_intel_ver") or "2022.1")) +load(pathJoin("hpc-mpt", os.getenv("hpc_mpt_ver") or "2.25")) + +load("srw_common") + +load(pathJoin("g2", os.getenv("g2_ver") or "3.4.5")) +load(pathJoin("esmf", os.getenv("esmf_ver") or "8.3.0b09")) +load(pathJoin("mapl", os.getenv("mapl_ver") or "2.11.0-esmf-8.3.0b09")) +load(pathJoin("netcdf", os.getenv("netcdf_ver") or "4.7.4")) +load(pathJoin("libpng", os.getenv("libpng_ver") or "1.6.37")) +load(pathJoin("pio", os.getenv("pio_ver") or "2.5.3")) +load(pathJoin("fms", os.getenv("fms_ver") or "2022.01")) + +setenv("CMAKE_C_COMPILER","mpicc") +setenv("CMAKE_CXX_COMPILER","mpicpc") +setenv("CMAKE_Fortran_COMPILER","mpif90") +setenv("CMAKE_Platform","cheyenne.intel") + diff --git a/modulefiles/build_gaea_intel b/modulefiles/build_gaea_intel deleted file mode 100644 index 6b2ef13a17..0000000000 --- a/modulefiles/build_gaea_intel +++ /dev/null @@ -1,27 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW on" - puts stderr "the NOAA RDHPC machine Gaea using Intel-2021.3.0" -} - -module use /lustre/f2/dev/role.epic/contrib/hpc-stack/intel-2021.3.0/modulefiles/stack -module load hpc/1.2.0 -module load intel/2021.3.0 -module load hpc-intel/2021.3.0 -module load hpc-cray-mpich/7.7.11 -#needed for WW3 build -module load gcc/8.3.0 - -module load srw_common -module load libpng/1.6.37 - -module load cmake/3.20.1 - -setenv CC cc -setenv FC ftn -setenv CXX CC -setenv CMAKE_C_COMPILER cc -setenv CMAKE_CXX_COMPILER CC -setenv CMAKE_Fortran_COMPILER ftn -setenv CMAKE_Platform gaea.intel diff --git a/modulefiles/build_gaea_intel.lua b/modulefiles/build_gaea_intel.lua new file mode 100644 index 0000000000..63105d0ab8 --- /dev/null +++ b/modulefiles/build_gaea_intel.lua @@ -0,0 +1,27 @@ +help([[ +This module loads libraries for building the UFS SRW App on +the NOAA RDHPC machine Gaea using Intel-2022.1.2 +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on Gaea ]===]) + +load(pathJoin("cmake", os.getenv("cmake_ver") or "3.20.1")) + +prepend_path("MODULEPATH","/lustre/f2/dev/role.epic/contrib/hpc-stack/intel-2021.3.0/modulefiles/stack") +load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) +load(pathJoin("intel", os.getenv("intel_ver") or "2021.3.0")) +load(pathJoin("hpc-intel", os.getenv("hpc_intel_ver") or "2021.3.0")) +load(pathJoin("hpc-cray-mpich", os.getenv("hpc_cray_mpich_ver") or "7.7.11")) +load(pathJoin("gcc", os.getenv("gcc_ver") or "8.3.0")) +load(pathJoin("libpng", os.getenv("libpng_ver") or "1.6.37")) + +load("srw_common") + +setenv("CC","cc") +setenv("FC","ftn") +setenv("CXX","CC") +setenv("CMAKE_C_COMPILER","cc") +setenv("CMAKE_CXX_COMPILER","CC") +setenv("CMAKE_Fortran_COMPILER","ftn") +setenv("CMAKE_Platform","gaea.intel") + diff --git a/modulefiles/build_hera_intel b/modulefiles/build_hera_intel deleted file mode 100644 index 275ef2fe32..0000000000 --- a/modulefiles/build_hera_intel +++ /dev/null @@ -1,31 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW on" - puts stderr "the NOAA RDHPC machine Hera using Intel-2022.1.2" -} - -module-whatis "Loads libraries needed for building SRW on Hera" - -module use /contrib/miniconda3/modulefiles -module load miniconda3/4.5.12 - -module use /contrib/sutils/modulefiles -module load sutils - -module load cmake/3.20.1 - -module use /scratch2/NCEPDEV/nwprod/hpc-stack/libs/hpc-stack/modulefiles/stack -module load hpc/1.2.0 -module load hpc-intel/2022.1.2 -module load hpc-impi/2022.1.2 - -module load srw_common - -module load nccmp/1.8.9.0 -module load nco/4.9.3 - -setenv CMAKE_C_COMPILER mpiicc -setenv CMAKE_CXX_COMPILER mpiicpc -setenv CMAKE_Fortran_COMPILER mpiifort -setenv CMAKE_Platform hera.intel diff --git a/modulefiles/build_hera_intel.lua b/modulefiles/build_hera_intel.lua new file mode 100644 index 0000000000..69d74a0dd6 --- /dev/null +++ b/modulefiles/build_hera_intel.lua @@ -0,0 +1,27 @@ +help([[ +This module loads libraries for building the UFS SRW App on +the NOAA RDHPC machine Hera using Intel-2022.1.2 +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on Hera ]===]) + +prepend_path("MODULEPATH","/contrib/sutils/modulefiles") +load("sutils") + +load(pathJoin("cmake", os.getenv("cmake_ver") or "3.20.1")) + +prepend_path("MODULEPATH","/scratch2/NCEPDEV/nwprod/hpc-stack/libs/hpc-stack/modulefiles/stack") +load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) +load(pathJoin("hpc-intel", os.getenv("hpc_intel_ver") or "2022.1.2")) +load(pathJoin("hpc-impi", os.getenv("hpc_impi_ver") or "2022.1.2")) + +load("srw_common") + +load(pathJoin("nccmp", os.getenv("nccmp_ver") or "1.8.9.0")) +load(pathJoin("nco", os.getenv("nco_ver") or "4.9.3")) + +setenv("CMAKE_C_COMPILER","mpiicc") +setenv("CMAKE_CXX_COMPILER","mpiicpc") +setenv("CMAKE_Fortran_COMPILER","mpiifort") +setenv("CMAKE_Platform","hera.intel") + diff --git a/modulefiles/build_jet_intel b/modulefiles/build_jet_intel deleted file mode 100644 index 7a4da30519..0000000000 --- a/modulefiles/build_jet_intel +++ /dev/null @@ -1,31 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW on" - puts stderr "the NOAA RDHPC machine JET using Intel-2022.1.2" -} - -module-whatis "Loads libraries needed for building SRW on JET" - -module use /contrib/sutils/modulefiles -module load sutils - -module load cmake/3.20.1 - -module use /lfs4/HFIP/hfv3gfs/nwprod/hpc-stack/libs/modulefiles/stack - -module load hpc/1.2.0 -module load hpc-intel/2022.1.2 -module load hpc-impi/2022.1.2 - -module load srw_common - -module load nccmp/1.8.9.0 -module load prod_util/1.2.2 -module load nco/4.9.3 - -setenv CMAKE_C_COMPILER mpiicc -setenv CMAKE_CXX_COMPILER mpiicpc -setenv CMAKE_Fortran_COMPILER mpiifort -setenv CMAKE_Platform jet.intel - diff --git a/modulefiles/build_jet_intel.lua b/modulefiles/build_jet_intel.lua new file mode 100644 index 0000000000..a2fbeadf60 --- /dev/null +++ b/modulefiles/build_jet_intel.lua @@ -0,0 +1,28 @@ +help([[ +This module loads libraries for building the UFS SRW App on +the NOAA RDHPC machine Jet using Intel-2022.1.2 +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on Jet ]===]) + +prepend_path("MODULEPATH","/contrib/sutils/modulefiles") +load("sutils") + +load(pathJoin("cmake", os.getenv("cmake_ver") or "3.20.1")) + +prepend_path("MODULEPATH","/lfs4/HFIP/hfv3gfs/nwprod/hpc-stack/libs/modulefiles/stack") +load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) +load(pathJoin("hpc-intel", os.getenv("hpc_intel_ver") or "2022.1.2")) +load(pathJoin("hpc-impi", os.getenv("hpc_impi_ver") or "2022.1.2")) + +load("srw_common") + +load(pathJoin("prod_util", os.getenv("prod_util_ver") or "1.2.2")) +load(pathJoin("nccmp", os.getenv("nccmp_ver") or "1.8.9.0")) +load(pathJoin("nco", os.getenv("nco_ver") or "4.9.3")) + +setenv("CMAKE_C_COMPILER","mpiicc") +setenv("CMAKE_CXX_COMPILER","mpiicpc") +setenv("CMAKE_Fortran_COMPILER","mpiifort") +setenv("CMAKE_Platform","jet.intel") + diff --git a/modulefiles/build_linux_gnu b/modulefiles/build_linux_gnu deleted file mode 100644 index 0845311fd3..0000000000 --- a/modulefiles/build_linux_gnu +++ /dev/null @@ -1,91 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module needs to be customized for the user's Linux environment:" - puts stderr "specify compilers, path for HPC-stack, load the modules, set compiler and linker flags" -} - -module-whatis "Loads libraries needed for building SRW on Linux" - -# This path should point to your HPCstack installation directory -setenv HPCstack "/home/username/hpc-stack/install" - -# Load HPC stack -module use $env(HPCstack)/modulefiles/stack -module load hpc -module load hpc-python -# -module load hpc-gnu -module load openmpi -module load hpc-openmpi - -module load jasper/2.0.25 -module load zlib/1.2.11 - -module load hdf5/1.10.6 -module load netcdf/4.7.4 -module load pio/2.5.3 -module load esmf/8.3.0b09 -module load fms/2022.01 - -module load bacio/2.4.1 -module load crtm/2.3.0 -module load g2/3.4.3 -module load g2tmpl/1.10.0 -module load ip/3.3.3 -module load sp/2.3.3 -module load w3nco/2.4.1 -module load upp/10.0.10 - -module load gftl-shared/1.3.3 -module load yafyaml/0.5.1 -module load mapl/2.11.0-esmf-8.3.0b09 -module load gfsio/1.4.1 -module load landsfcutil/2.4.1 -module load nemsio/2.5.2 -module load nemsiogfs/2.5.3 -module load sfcio/1.4.1 -module load sigio/2.3.2 -module load w3emc/2.7.3 -module load wgrib2/2.0.8 - -# Set the env. variables for the serial compilers (CC, FC, CXX), if not present -setenv CC "/usr/local/bin/gcc" -setenv FC "/usr/local/bin/gfortran" -setenv CXX "/usr/local/bin/g++" - -# Set MPI compilers depending on the MPI libraries built: -setenv MPI_CC mpicc -setenv MPI_CXX mpicxx -setenv MPI_FC mpif90 - -# Set compilers and platform names for CMake: -setenv CMAKE_C_COMPILER $env(MPI_CC) -setenv CMAKE_CXX_COMPILER $env(MPI_CXX) -setenv CMAKE_Fortran_COMPILER $env(MPI_FC) - -setenv CMAKE_Platform linux.gnu -#setenv CMAKE_Platform linux.intel - -setenv CMAKE_Fortran_COMPILER_ID "GNU" -#setenv CMAKE_Fortran_COMPILER_ID "Intel" - -# Set compiler and linker flags if needed: -setenv FFLAGS " -fallow-argument-mismatch" - -if { [module-info mode load] } { - puts stderr "This module needs to be customized for the user's Linux environment:" - puts stderr "load the environment modules if present, hpc-stack modules," - puts stderr "specify compilers, path for HPC-stack and SRW directory on Linux systems" - puts stderr "1) env. variable HPCstack is the hpc-stack installation directory" - puts stderr "2) Load the modules build with the hpc-stack on your system" - puts stderr "3) Specify compilers, compiler and linker flags, and a platform name" - puts stderr " The example below is for the GNU compilers built with OpenMPI libraries" - puts stderr " " - puts stderr "NB: After the module is customized, comment out the this line and the `puts stderr` lines above" - puts stderr " " - puts stderr "Please export env. variable LDFLAGS after the module is successfully loaded: - > export LDFLAGS=\"-L\$MPI_ROOT/lib \" " -} - - diff --git a/modulefiles/build_linux_gnu.lua b/modulefiles/build_linux_gnu.lua new file mode 100644 index 0000000000..5ad0561ed7 --- /dev/null +++ b/modulefiles/build_linux_gnu.lua @@ -0,0 +1,87 @@ +help([[ +This module needs to be customized for the user's Linux environment: +specify compilers, path for HPC-stack, load the modules, set compiler and linker flags +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on Linux ]===]) + +-- This path should point to your HPCstack installation directory +local HPCstack="/home/username/hpc-stack/install" + +-- Load HPC stack +prepend_path("MODULEPATH", pathJoin(HPCstack, "modulefiles/stack")) +load("hpc") +load("hpc-python") + +load("hpc-gnu") +load("openmpi") +load("hpc-openmpi") + +load("jasper/2.0.25") +load("zlib/1.2.11") + +load("hdf5/1.10.6") +load("netcdf/4.7.4") +load("pio/2.5.3") +load("esmf/8.3.0b09") +load("fms/2022.01") + +load("bacio/2.4.1") +load("crtm/2.3.0") +load("g2/3.4.3") +load("g2tmpl/1.10.0") +load("ip/3.3.3") +load("sp/2.3.3") +load("w3nco/2.4.1") +load("upp/10.0.10") + +load("gftl-shared/1.3.3") +load("yafyaml/0.5.1") +load("mapl/2.11.0-esmf-8.3.0b09") +load("gfsio/1.4.1") +load("landsfcutil/2.4.1") +load("nemsio/2.5.2") +load("nemsiogfs/2.5.3") +load("sfcio/1.4.1") +load("sigio/2.3.2") +load("w3emc/2.7.3") +load("wgrib2/2.0.8") + +-- Set the env. variables for the serial compilers (CC, FC, CXX), if not present +setenv("CC", "/usr/local/bin/gcc") +setenv("FC", "/usr/local/bin/gfortran") +setenv("CXX", "/usr/local/bin/g++") + +-- Set MPI compilers depending on the MPI libraries built: +local MPI_CC="mpicc" +local MPI_CXX="mpicxx" +local MPI_FC="mpif90" + +-- Set compilers and platform names for CMake: +setenv("CMAKE_C_COMPILER", MPI_CC) +setenv("CMAKE_CXX_COMPILER", MPI_CXX) +setenv("CMAKE_Fortran_COMPILER", MPI_FC) + +setenv("CMAKE_Platform", "linux.gnu") +--setenv("CMAKE_Platform", "linux.intel") + +setenv("CMAKE_Fortran_COMPILER_ID", "GNU") +--setenv("CMAKE_Fortran_COMPILER_ID", "Intel") + +-- Set compiler and linker flags if needed: +setenv("FFLAGS", " -fallow-argument-mismatch") + +if mode() == "load" then + LmodMsgRaw([===[ + This module needs to be customized for the user's Linux environment: + load the environment modules if present, hpc-stack modules, + specify compilers, path for HPC-stack and SRW directory on Linux systems + 1) env. variable HPCstack is the hpc-stack installation directory + 2) Load the modules build with the hpc-stack on your system + 3) Specify compilers, compiler and linker flags, and a platform name + The example below is for the GNU compilers built with OpenMPI libraries + NB: After the module is customized, comment out the this line and lines above + Please export env. variable LDFLAGS after the module is successfully loaded: + > export LDFLAGS=\"-L\$MPI_ROOT/lib \" + ]===]) +end diff --git a/modulefiles/build_macos_gnu b/modulefiles/build_macos_gnu deleted file mode 100644 index 613d361aae..0000000000 --- a/modulefiles/build_macos_gnu +++ /dev/null @@ -1,90 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module needs to be customized for the user's MacOS environment:" - puts stderr "specify compilers, path for HPC-stack, load the modules, set compiler and linker flags" - puts stderr "Option 1: M1/arm64 platform, OS BigSur, Monterey (Darwin 20,21) " - puts stderr "Option 2: Intel/x86_64 platform, OS Catalina (Darwin 19) " - puts stderr " " -} - -module-whatis "Loads libraries needed for building SRW on Hera" - -if { [module-info mode load] } { - puts "ulimit -S -s unlimited;" -} - -# This path should point to your HPCstack installation directory -setenv HPCstack "/Users/username/hpc-stack/install" - -# Load HPC stack -module use $env(HPCstack)/modulefiles/stack -module load hpc -module load hpc-python -# -module load hpc-gnu -module load openmpi -module load hpc-openmpi - -module load jasper/2.0.25 -module load zlib/1.2.11 - -module load hdf5/1.10.6 -module load netcdf/4.7.4 -module load pio/2.5.3 -module load esmf/8.3.0b09 -module load fms/2022.01 - -module load bacio/2.4.1 -module load crtm/2.3.0 -module load g2/3.4.3 -module load g2tmpl/1.10.0 -module load ip/3.3.3 -module load sp/2.3.3 -module load w3nco/2.4.1 -module load upp/10.0.10 - -module load gftl-shared/1.3.3 -module load yafyaml/0.5.1 -module load mapl/2.12.2-esmf-8.3.0b09 -module load gfsio/1.4.1 -module load landsfcutil/2.4.1 -module load nemsio/2.5.4 -module load nemsiogfs/2.5.3 -module load sfcio/1.4.1 -module load sigio/2.3.2 -module load w3emc/2.9.2 -module load wgrib2/2.0.8 -module list - -# Option 1 compiler paths: -setenv CC "/opt/homebrew/bin/gcc" -setenv FC "/opt/homebrew/bin/gfortran" -setenv CXX "/opt/homebrew/bin/g++" - -# Option 2 compiler paths: -#setenv CC "/usr/local/bin/gcc" -#setenv FC "/usr/local/bin/gfortran" -#setenv CXX "/usr/local/bin/g++" - -setenv MPI_CC mpicc -setenv MPI_CXX mpicxx -setenv MPI_FC mpif90 - -setenv CMAKE_C_COMPILER $env(MPI_CC) -setenv CMAKE_CXX_COMPILER $env(MPI_CXX) -setenv CMAKE_Fortran_COMPILER $env(MPI_FC) -setenv CMAKE_Platform macos.gnu - -setenv CMAKE_Fortran_COMPILER_ID "GNU" -setenv FFLAGS "-DNO_QUAD_PRECISION -fallow-argument-mismatch " - -# export the env. variable LDFLAGS after loading the current module -# export LDFLAGS="-L$MPI_ROOT/lib" -if { [module-info mode load] } { - puts stderr " " - puts stderr "Please export env. variable LDFLAGS after the module is successfully loaded: - > export LDFLAGS=\"-L\$MPI_ROOT/lib \" " -} - - diff --git a/modulefiles/build_macos_gnu.lua b/modulefiles/build_macos_gnu.lua new file mode 100644 index 0000000000..e964a26099 --- /dev/null +++ b/modulefiles/build_macos_gnu.lua @@ -0,0 +1,97 @@ +help([[ +This module needs to be customized for the user's Linux environment: +specify compilers, path for HPC-stack, load the modules, set compiler and linker flags + Option 1: M1/arm64 platform, OS BigSur, Monterey (Darwin 20,21) + Option 2: Intel/x86_64 platform, OS Catalina (Darwin 19) +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on macos ]===]) + +if mode() == "load" then + execute{cmd="ulimit -S -s unlimited", modeA={"load"}} +end + +-- This path should point to your HPCstack installation directory +local HPCstack="/Users/username/hpc-stack/install" + +-- Load HPC stack +prepend_path("MODULEPATH", pathJoin(HPCstack, "modulefiles/stack")) +load("hpc") +load("hpc-python") + +load("hpc-gnu") +load("openmpi") +load("hpc-openmpi") + +load("jasper/2.0.25") +load("zlib/1.2.11") + +load("hdf5/1.10.6") +load("netcdf/4.7.4") +load("pio/2.5.3") +load("esmf/8.3.0b09") +load("fms/2022.01") + +load("bacio/2.4.1") +load("crtm/2.3.0") +load("g2/3.4.3") +load("g2tmpl/1.10.0") +load("ip/3.3.3") +load("sp/2.3.3") +load("w3nco/2.4.1") +load("upp/10.0.10") + +load("gftl-shared/1.3.3") +load("yafyaml/0.5.1") +load("mapl/2.12.2-esmf-8.3.0b09") +load("gfsio/1.4.1") +load("landsfcutil/2.4.1") +load("nemsio/2.5.4") +load("nemsiogfs/2.5.3") +load("sfcio/1.4.1") +load("sigio/2.3.2") +load("w3emc/2.9.2") +load("wgrib2/2.0.8") + +-- Option 1 compiler paths: +setenv("CC", "/opt/homebrew/bin/gcc") +setenv("FC", "/opt/homebrew/bin/gfortran") +setenv("CXX", "/opt/homebrew/bin/g++") + +-- Option 2 compiler paths: +--[[ +setenv("CC", "/usr/local/bin/gcc") +setenv("FC", "/usr/local/bin/gfortran") +setenv("CXX", "/usr/local/bin/g++") +--]] +-- +-- Set MPI compilers depending on the MPI libraries built: +local MPI_CC="mpicc" +local MPI_CXX="mpicxx" +local MPI_FC="mpif90" + + +-- Set compilers and platform names for CMake: +setenv("CMAKE_C_COMPILER", MPI_CC) +setenv("CMAKE_CXX_COMPILER", MPI_CXX) +setenv("CMAKE_Fortran_COMPILER", MPI_FC) + +setenv("CMAKE_Platform", "macos.gnu") +--setenv("CMAKE_Platform", "macos.intel") + +setenv("CMAKE_Fortran_COMPILER_ID", "GNU") +--setenv("CMAKE_Fortran_COMPILER_ID", "Intel") + +-- Set compiler and linker flags if needed: +setenv("FFLAGS", " -DNO_QUAD_PRECISION -fallow-argument-mismatch ") + +-- export the env. variable LDFLAGS after loading the current module +-- export LDFLAGS="-L$MPI_ROOT/lib" +if mode() == "load" then + LmodMsgRaw([===[ + Please export env. variable LDFLAGS after the module is successfully loaded: + > export LDFLAGS=\"-L\$MPI_ROOT/lib \" " + ]===]) +end + + diff --git a/modulefiles/build_noaacloud_intel b/modulefiles/build_noaacloud_intel deleted file mode 100644 index ccf2c4bb67..0000000000 --- a/modulefiles/build_noaacloud_intel +++ /dev/null @@ -1,14 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW on" - puts stderr "the NOAA cloud using Intel-oneapi" -} - -module use /contrib/spack-stack/apps/srw-app-test/modulefiles/Core -module load stack-intel -module load stack-intel-oneapi-mpi -module load cmake/3.22.1 - -module load srw_common -module load esmf/8.2.0 diff --git a/modulefiles/build_noaacloud_intel.lua b/modulefiles/build_noaacloud_intel.lua new file mode 100644 index 0000000000..cb1205a42b --- /dev/null +++ b/modulefiles/build_noaacloud_intel.lua @@ -0,0 +1,18 @@ +help([[ +This load("s libraries for building the UFS SRW App on +the NOAA cloud using Intel-oneapi +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on NOAA cloud ]===]) + +prepend_path("MODULEPATH", "/contrib/spack-stack/apps/srw-app-test/modulefiles/Core") +load("stack-intel") +load("stack-intel-oneapi-mpi") +load("cmake/3.22.1") + +load("srw_common") +load("esmf/8.2.0") +load("netcdf-c") +load("netcdf-fortran") +load("libpng") +load("jasper") diff --git a/modulefiles/build_odin_intel b/modulefiles/build_odin_intel deleted file mode 100644 index 25120a2af4..0000000000 --- a/modulefiles/build_odin_intel +++ /dev/null @@ -1,54 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW on" - puts stderr "the NSSL machine odin using Intel" -} - -module-whatis "Loads libraries needed for building SRW on odin" - -prepend-path PATH "/home/yunheng.wang/tools/cmake-3.23.0-rc2/bin" -setenv CMAKE "/home/yunheng.wang/tools/cmake-3.23.0-rc2/bin/cmake" - -module load hpc/1.2.0 -module load hpc-intel -module load hpc-cray-mpich - -#module load srw_common - -module load jasper -module load zlib -module load png - -#module load cray-hdf5 -#module load cray-netcdf -module load esmf -module load fms - -module load bacio -module load crtm -module load g2 -module load g2tmpl -module load ip -module load sp -module load w3nco -module load upp - -module load gftl-shared -module load yafyaml -module load mapl - -module load gfsio -module load landsfcutil -module load nemsio -module load nemsiogfs -module load sfcio -module load sigio -module load w3emc -module load wgrib2 - -setenv CMAKE_C_COMPILER cc -setenv CMAKE_CXX_COMPILER CC -setenv CMAKE_Fortran_COMPILER ftn -setenv CMAKE_Platform odin.intel - diff --git a/modulefiles/build_odin_intel.lua b/modulefiles/build_odin_intel.lua new file mode 100644 index 0000000000..f4059a868a --- /dev/null +++ b/modulefiles/build_odin_intel.lua @@ -0,0 +1,52 @@ +help([[ +This module loads libraries for building the UFS SRW App on +the NSSL machine Odin using Intel +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on Odin ]===]) + +prepend_path("PATH","/home/yunheng.wang/tools/cmake-3.23.0-rc2/bin") +setenv("CMAKE","/home/yunheng.wang/tools/cmake-3.23.0-rc2/bin/cmake") + +load("hpc/1.2.0") +load("hpc-intel") +load("hpc-cray-mpich") + +--load("srw_common") + +load("jasper") +load("zlib") +load("png") + +--load("cray-hdf5") +--load("cray-netcdf") +load("esmf") +load("fms") + +load("bacio") +load("crtm") +load("g2") +load("g2tmpl") +load("ip") +load("sp") +load("w3nco") +load("upp") + +load("gftl-shared") +load("yafyaml") +load("mapl") + +load("gfsio") +load("landsfcutil") +load("nemsio") +load("nemsiogfs") +load("sfcio") +load("sigio") +load("w3emc") +load("wgrib2") + +setenv("CMAKE_C_COMPILER","cc") +setenv("CMAKE_CXX_COMPILER","CC") +setenv("CMAKE_Fortran_COMPILER","ftn") +setenv("CMAKE_Platform","odin.intel") + diff --git a/modulefiles/build_orion_intel b/modulefiles/build_orion_intel deleted file mode 100644 index f2171a4a53..0000000000 --- a/modulefiles/build_orion_intel +++ /dev/null @@ -1,28 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW on" - puts stderr "the MSU machineOrion using Intel-2022.1.2" -} - -module-whatis "Loads libraries needed for building SRW on Orion" - -module load contrib noaatools - -module load cmake/3.22.1 -module load python/3.9.2 - -module use /apps/contrib/NCEP/libs/hpc-stack/modulefiles/stack -module load hpc/1.2.0 -module load hpc-intel/2022.1.2 -module load hpc-impi/2022.1.2 - -module load srw_common - -module load nccmp/1.8.9.0 -module load nco/4.9.3 - -setenv CMAKE_C_COMPILER mpiicc -setenv CMAKE_CXX_COMPILER mpiicpc -setenv CMAKE_Fortran_COMPILER mpiifort -setenv CMAKE_Platform orion.intel diff --git a/modulefiles/build_orion_intel.lua b/modulefiles/build_orion_intel.lua new file mode 100644 index 0000000000..92795c6f8c --- /dev/null +++ b/modulefiles/build_orion_intel.lua @@ -0,0 +1,28 @@ +help([[ +This module loads libraries for building the UFS SRW App on +the MSU machine Orion using Intel-2022.1.2 +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on Orion ]===]) + +load("contrib") +load("noaatools") + +load(pathJoin("cmake", os.getenv("cmake_ver") or "3.22.1")) +load(pathJoin("python", os.getenv("python_ver") or "3.9.2")) + +prepend_path("MODULEPATH","/apps/contrib/NCEP/libs/hpc-stack/modulefiles/stack") +load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) +load(pathJoin("hpc-intel", os.getenv("hpc_intel_ver") or "2022.1.2")) +load(pathJoin("hpc-impi", os.getenv("hpc_impi_ver") or "2022.1.2")) + +load("srw_common") + +load(pathJoin("nccmp", os.getenv("nccmp_ver") or "1.8.9.0")) +load(pathJoin("nco", os.getenv("nco_ver") or "4.9.3")) + +setenv("CMAKE_C_COMPILER","mpiicc") +setenv("CMAKE_CXX_COMPILER","mpiicpc") +setenv("CMAKE_Fortran_COMPILER","mpiifort") +setenv("CMAKE_Platform","orion.intel") + diff --git a/modulefiles/build_singularity_gnu b/modulefiles/build_singularity_gnu deleted file mode 100644 index 9a28fc1ab1..0000000000 --- a/modulefiles/build_singularity_gnu +++ /dev/null @@ -1,43 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW in a singularity container" - puts stderr "using Gnu 9.3.0 built from this docker image:" - puts stderr " docker://noaaepic/ubuntu20.04-epic-srwapp:1.0" - puts stderr "https://hub.docker.com/r/noaaepic/ubuntu20.04-epic-srwapp" -} - -module-whatis "Loads libraries needed for building SRW in a singularity container" - -module use /opt/hpc-modules/modulefiles/stack - -module load hpc -module load hpc-gnu -module load hpc-openmpi - -module load netcdf -module load hdf5 -module load bacio -module load sfcio -module load sigio -module load nemsio -module load w3emc -module load esmf -module load fms -module load crtm -module load g2 -module load png -module load zlib -module load g2tmpl -module load ip -module load sp -module load w3nco -module load cmake -module load gfsio -module load wgrib2 -module load upp - -setenv CMAKE_C_COMPILER mpicc -setenv CMAKE_CXX_COMPILER mpicxx -setenv CMAKE_Fortran_COMPILER mpif90 -setenv CMAKE_Platform singularity.gnu diff --git a/modulefiles/build_singularity_gnu.lua b/modulefiles/build_singularity_gnu.lua new file mode 100644 index 0000000000..434ac448d4 --- /dev/null +++ b/modulefiles/build_singularity_gnu.lua @@ -0,0 +1,40 @@ +help([[ +This module loads libraries for building the UFS SRW App in +a singularity container +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App in singularity container ]===]) + +prepend_path("MODULEPATH","/opt/hpc-modules/modulefiles/stack") + +load("hpc") +load("hpc-gnu") +load("hpc-openmpi") + +load("netcdf") +load("hdf5") +load("bacio") +load("sfcio") +load("sigio") +load("nemsio") +load("w3emc") +load("esmf") +load("fms") +load("crtm") +load("g2") +load("png") +load("zlib") +load("g2tmpl") +load("ip") +load("sp") +load("w3nco") +load("cmake") +load("gfsio") +load("wgrib2") +load("upp") + +setenv("CMAKE_C_COMPILER","mpiicc") +setenv("CMAKE_CXX_COMPILER","mpicxx") +setenv("CMAKE_Fortran_COMPILER","mpif90") +setenv("CMAKE_Platform","singularity.gnu") + diff --git a/modulefiles/build_wcoss2_intel b/modulefiles/build_wcoss2_intel deleted file mode 100644 index 8e771b6a80..0000000000 --- a/modulefiles/build_wcoss2_intel +++ /dev/null @@ -1,51 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module loads libraries for building SRW on" - puts stderr "the NOAA WCOSS2 machine using Intel-19.1.3.304" -} - -module-whatis "Loads libraries needed for building SRW on WCOSS2 (Cactus/Dogwood)" - -module load envvar/$::env(envvar_ver) - -module load PrgEnv-intel/$::env(PrgEnv_intel_ver) -module load intel/$::env(intel_ver) -module load craype/$::env(craype_ver) -module load cray-mpich/$::env(cray_mpich_ver) - -module load cmake/$::env(cmake_ver) - -setenv HPC_OPT /apps/ops/para/libs -module use /apps/ops/para/libs/modulefiles/compiler/intel/$::env(intel_ver) -module use /apps/ops/para/libs/modulefiles/mpi/intel/$::env(intel_ver)/cray-mpich/$::env(cray_mpich_ver) - -module load jasper/$::env(jasper_ver) -module load zlib/$::env(zlib_ver) -module load libpng/$::env(libpng_ver) -module load hdf5/$::env(hdf5_ver) -module load netcdf/$::env(netcdf_ver) -module load pio/$::env(pio_ver) -module load esmf/$::env(esmf_ver) -module load fms/$::env(fms_ver) -module load bacio/$::env(bacio_ver) -module load crtm/$::env(crtm_ver) -module load g2/$::env(g2_ver) -module load g2tmpl/$::env(g2tmpl_ver) -module load ip/$::env(ip_ver) -module load sp/$::env(sp_ver) -module load w3nco/$::env(w3nco_ver) - -module load libjpeg/$::env(libjpeg_ver) -module load cray-pals/$::env(cray_pals_ver) - -module load w3emc/$::env(w3emc_ver) -module load nemsio/$::env(nemsio_ver) -module load sigio/$::env(sigio_ver) -module load sfcio/$::env(sfcio_ver) -module load wrf_io/$::env(wrf_io_ver) - -setenv CMAKE_C_COMPILER cc -setenv CMAKE_CXX_COMPILER CC -setenv CMAKE_Fortran_COMPILER ftn -setenv CMAKE_Platform wcoss2 diff --git a/modulefiles/build_wcoss2_intel.lua b/modulefiles/build_wcoss2_intel.lua new file mode 100644 index 0000000000..c8956142ee --- /dev/null +++ b/modulefiles/build_wcoss2_intel.lua @@ -0,0 +1,49 @@ +help([[ +This loads libraries for building the UFS SRW App on +the NOAA operational machine WCOSS2 using Intel-19.1.3.304 +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on WCOSS2 ]===]) + +load(pathJoin("envvar", os.getenv("envvar_ver"))) + +load(pathJoin("PrgEnv-intel", os.getenv("PrgEnv_intel_ver"))) +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("craype", os.getenv("craype_ver"))) +load(pathJoin("cray-mpich", os.getenv("cray_mpich_ver"))) + +load(pathJoin("cmake", os.getenv("cmake_ver"))) + +setenv("HPC_OPT","/apps/ops/para/libs") +prepend_path("MODULEPATH", pathJoin("/apps/ops/para/libs/modulefiles/compiler/intel", os.getenv("intel_ver"))) +prepend_path("MODULEPATH", pathJoin("/apps/ops/para/libs/modulefiles/mpi/intel", os.getenv("intel_ver"), "cray-mpich", os.getenv("cray_mpich_ver"))) + +load(pathJoin("jasper", os.getenv("jasper_ver"))) +load(pathJoin("zlib", os.getenv("zlib_ver"))) +load(pathJoin("libpng", os.getenv("libpng_ver"))) +load(pathJoin("hdf5", os.getenv("hdf5_ver"))) +load(pathJoin("netcdf", os.getenv("netcdf_ver"))) +load(pathJoin("pio", os.getenv("pio_ver"))) +load(pathJoin("esmf", os.getenv("esmf_ver"))) +load(pathJoin("fms", os.getenv("fms_ver"))) +load(pathJoin("bacio", os.getenv("bacio_ver"))) +load(pathJoin("crtm", os.getenv("crtm_ver"))) +load(pathJoin("g2", os.getenv("g2_ver"))) +load(pathJoin("g2tmpl", os.getenv("g2tmpl_ver"))) +load(pathJoin("ip", os.getenv("ip_ver"))) +load(pathJoin("sp", os.getenv("sp_ver"))) +load(pathJoin("w3nco", os.getenv("w3nco_ver"))) + +load(pathJoin("libjpeg", os.getenv("libjpeg_ver"))) +load(pathJoin("cray-pals", os.getenv("cray_pals_ver"))) + +load(pathJoin("w3emc", os.getenv("w3emc_ver"))) +load(pathJoin("nemsio", os.getenv("nemsio_ver"))) +load(pathJoin("sigio", os.getenv("sigio_ver"))) +load(pathJoin("sfcio", os.getenv("sfcio_ver"))) +load(pathJoin("wrf_io", os.getenv("wrf_io_ver"))) + +setenv("CMAKE_C_COMPILER","cc") +setenv("CMAKE_CXX_COMPILER","CC") +setenv("CMAKE_Fortran_COMPILER","ftn") +setenv("CMAKE_Platform","wcoss2") diff --git a/modulefiles/srw_common b/modulefiles/srw_common deleted file mode 100644 index 9c3ece42fc..0000000000 --- a/modulefiles/srw_common +++ /dev/null @@ -1,33 +0,0 @@ -#%Module - -module load jasper/2.0.25 -module load zlib/1.2.11 -module load-any png/1.6.35 libpng/1.6.37 - -module load-any netcdf/4.7.4 netcdf-c/4.7.4 -module load-any netcdf/4.7.4 netcdf-fortran/4.5.4 -module load-any pio/2.5.3 parallelio/2.5.2 -module load-any esmf/8.3.0b09 esmf/8.2.0 -module load fms/2022.01 - -module load bufr/11.7.0 -module load bacio/2.4.1 -module load crtm/2.3.0 -module load g2/3.4.5 -module load g2tmpl/1.10.0 -module load ip/3.3.3 -module load sp/2.3.3 -module load w3emc/2.9.2 - -module load-any gftl-shared/v1.5.0 gftl-shared/1.5.0 -module load-any yafyaml/v0.5.1 yafyaml/0.5.1 -module load-any mapl/2.22.0-esmf-8.3.0b09 mapl/2.11.0-esmf-8.2.0 - -module load nemsio/2.5.4 -module load sfcio/1.4.1 -module load sigio/2.3.2 -module load w3nco/2.4.1 -module load wrf_io/1.2.0 - -module load ncio/1.1.2 -module load wgrib2/2.0.8 diff --git a/modulefiles/srw_common.lua b/modulefiles/srw_common.lua new file mode 100644 index 0000000000..13337d8cff --- /dev/null +++ b/modulefiles/srw_common.lua @@ -0,0 +1,41 @@ + +-- Until Cheyenne updates Lmod version to >=8.3.7 +-- emulate load_any with try_load + isloaded() combo +function my_load_any(pkg1, pkg2) + try_load(pkg1) + if not isloaded(pkg1) then + load(pkg2) + end +end + +load("jasper/2.0.25") +load("zlib/1.2.11") +my_load_any("png/1.6.35", "libpng/1.6.37") + +my_load_any("netcdf/4.7.4", "netcdf-c/4.7.4") +my_load_any("netcdf/4.7.4", "netcdf-fortran/4.5.4") +my_load_any("pio/2.5.3", "parallelio/2.5.2") +my_load_any("esmf/8.3.0b09", "esmf/8.2.0") +load("fms/2022.01") + +load("bufr/11.7.0") +load("bacio/2.4.1") +load("crtm/2.3.0") +load("g2/3.4.5") +load("g2tmpl/1.10.0") +load("ip/3.3.3") +load("sp/2.3.3") +load("w3emc/2.9.2") + +my_load_any("gftl-shared/v1.5.0", "gftl-shared/1.5.0") +my_load_any("yafyaml/v0.5.1", "yafyaml/0.5.1") +my_load_any("mapl/2.22.0-esmf-8.3.0b09", "mapl/2.11.0-esmf-8.2.0") + +load("nemsio/2.5.4") +load("sfcio/1.4.1") +load("sigio/2.3.2") +load("w3nco/2.4.1") +load("wrf_io/1.2.0") + +load("ncio/1.1.2") +load("wgrib2/2.0.8") diff --git a/modulefiles/tasks/cheyenne/conda_regional_workflow b/modulefiles/tasks/cheyenne/conda_regional_workflow deleted file mode 100644 index e490af9091..0000000000 --- a/modulefiles/tasks/cheyenne/conda_regional_workflow +++ /dev/null @@ -1,5 +0,0 @@ -#%Module -module unload python -module load conda -setenv SRW_ENV /glade/p/ral/jntp/UFS_SRW_app/conda/regional_workflow - diff --git a/modulefiles/tasks/cheyenne/conda_regional_workflow.lua b/modulefiles/tasks/cheyenne/conda_regional_workflow.lua new file mode 100644 index 0000000000..53ba3f6936 --- /dev/null +++ b/modulefiles/tasks/cheyenne/conda_regional_workflow.lua @@ -0,0 +1,3 @@ +unload("python") +load("conda") +setenv("SRW_ENV", "/glade/p/ral/jntp/UFS_SRW_app/conda/regional_workflow") diff --git a/modulefiles/tasks/cheyenne/get_extrn_ics.local b/modulefiles/tasks/cheyenne/get_extrn_ics.local deleted file mode 100644 index 7f0ed16e4f..0000000000 --- a/modulefiles/tasks/cheyenne/get_extrn_ics.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load conda_regional_workflow - diff --git a/modulefiles/tasks/cheyenne/get_extrn_ics.local.lua b/modulefiles/tasks/cheyenne/get_extrn_ics.local.lua new file mode 100644 index 0000000000..494c85136d --- /dev/null +++ b/modulefiles/tasks/cheyenne/get_extrn_ics.local.lua @@ -0,0 +1 @@ +load("conda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/get_extrn_lbcs.local b/modulefiles/tasks/cheyenne/get_extrn_lbcs.local deleted file mode 100644 index 7f0ed16e4f..0000000000 --- a/modulefiles/tasks/cheyenne/get_extrn_lbcs.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load conda_regional_workflow - diff --git a/modulefiles/tasks/cheyenne/get_extrn_lbcs.local.lua b/modulefiles/tasks/cheyenne/get_extrn_lbcs.local.lua new file mode 100644 index 0000000000..494c85136d --- /dev/null +++ b/modulefiles/tasks/cheyenne/get_extrn_lbcs.local.lua @@ -0,0 +1 @@ +load("conda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/make_grid.local b/modulefiles/tasks/cheyenne/make_grid.local deleted file mode 100644 index e708b857cc..0000000000 --- a/modulefiles/tasks/cheyenne/make_grid.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load conda_regional_workflow diff --git a/modulefiles/tasks/cheyenne/make_grid.local.lua b/modulefiles/tasks/cheyenne/make_grid.local.lua new file mode 100644 index 0000000000..494c85136d --- /dev/null +++ b/modulefiles/tasks/cheyenne/make_grid.local.lua @@ -0,0 +1 @@ +load("conda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/make_ics.local b/modulefiles/tasks/cheyenne/make_ics.local deleted file mode 100644 index e708b857cc..0000000000 --- a/modulefiles/tasks/cheyenne/make_ics.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load conda_regional_workflow diff --git a/modulefiles/tasks/cheyenne/make_ics.local.lua b/modulefiles/tasks/cheyenne/make_ics.local.lua new file mode 100644 index 0000000000..494c85136d --- /dev/null +++ b/modulefiles/tasks/cheyenne/make_ics.local.lua @@ -0,0 +1 @@ +load("conda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/make_lbcs.local b/modulefiles/tasks/cheyenne/make_lbcs.local deleted file mode 100644 index e708b857cc..0000000000 --- a/modulefiles/tasks/cheyenne/make_lbcs.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load conda_regional_workflow diff --git a/modulefiles/tasks/cheyenne/make_lbcs.local.lua b/modulefiles/tasks/cheyenne/make_lbcs.local.lua new file mode 100644 index 0000000000..494c85136d --- /dev/null +++ b/modulefiles/tasks/cheyenne/make_lbcs.local.lua @@ -0,0 +1 @@ +load("conda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/make_orog.hardcoded b/modulefiles/tasks/cheyenne/make_orog.hardcoded deleted file mode 100644 index 51c59c5ee4..0000000000 --- a/modulefiles/tasks/cheyenne/make_orog.hardcoded +++ /dev/null @@ -1,9 +0,0 @@ -#%Module##################################################### - -module purge - -module load ncarenv/1.3 -module load intel/19.0.2 -module load ncarcompilers/0.5.0 -module load netcdf/4.6.3 - diff --git a/modulefiles/tasks/cheyenne/make_orog.hardcoded.lua b/modulefiles/tasks/cheyenne/make_orog.hardcoded.lua new file mode 100644 index 0000000000..2395a81c8e --- /dev/null +++ b/modulefiles/tasks/cheyenne/make_orog.hardcoded.lua @@ -0,0 +1,4 @@ +load("ncarenv/1.3") +load("intel/19.0.2") +load("ncarcompilers/0.5.0") +load("netcdf/4.6.3") diff --git a/modulefiles/tasks/cheyenne/run_fcst.local b/modulefiles/tasks/cheyenne/run_fcst.local deleted file mode 100644 index e708b857cc..0000000000 --- a/modulefiles/tasks/cheyenne/run_fcst.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load conda_regional_workflow diff --git a/modulefiles/tasks/cheyenne/run_fcst.local.lua b/modulefiles/tasks/cheyenne/run_fcst.local.lua new file mode 100644 index 0000000000..494c85136d --- /dev/null +++ b/modulefiles/tasks/cheyenne/run_fcst.local.lua @@ -0,0 +1 @@ +load("conda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/run_vx.local b/modulefiles/tasks/cheyenne/run_vx.local deleted file mode 100644 index e708b857cc..0000000000 --- a/modulefiles/tasks/cheyenne/run_vx.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load conda_regional_workflow diff --git a/modulefiles/tasks/cheyenne/run_vx.local.lua b/modulefiles/tasks/cheyenne/run_vx.local.lua new file mode 100644 index 0000000000..494c85136d --- /dev/null +++ b/modulefiles/tasks/cheyenne/run_vx.local.lua @@ -0,0 +1 @@ +load("conda_regional_workflow") diff --git a/modulefiles/tasks/gaea/get_extrn_ics.local b/modulefiles/tasks/gaea/get_extrn_ics.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/gaea/get_extrn_ics.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/gaea/get_extrn_ics.local.lua b/modulefiles/tasks/gaea/get_extrn_ics.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/get_extrn_ics.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/get_extrn_lbcs.local b/modulefiles/tasks/gaea/get_extrn_lbcs.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/gaea/get_extrn_lbcs.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/gaea/get_extrn_lbcs.local.lua b/modulefiles/tasks/gaea/get_extrn_lbcs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/get_extrn_lbcs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/make_grid.local b/modulefiles/tasks/gaea/make_grid.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/gaea/make_grid.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/gaea/make_grid.local.lua b/modulefiles/tasks/gaea/make_grid.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/make_grid.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/make_ics.local b/modulefiles/tasks/gaea/make_ics.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/gaea/make_ics.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/gaea/make_ics.local.lua b/modulefiles/tasks/gaea/make_ics.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/make_ics.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/make_lbcs.local b/modulefiles/tasks/gaea/make_lbcs.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/gaea/make_lbcs.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/gaea/make_lbcs.local.lua b/modulefiles/tasks/gaea/make_lbcs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/make_lbcs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/make_orog.local b/modulefiles/tasks/gaea/make_orog.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/gaea/make_orog.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/gaea/make_orog.local.lua b/modulefiles/tasks/gaea/make_orog.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/make_orog.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/miniconda_regional_workflow b/modulefiles/tasks/gaea/miniconda_regional_workflow deleted file mode 100644 index 4d5cea16df..0000000000 --- a/modulefiles/tasks/gaea/miniconda_regional_workflow +++ /dev/null @@ -1,6 +0,0 @@ -#%Module - -module use /lustre/f2/dev/role.epic/contrib/modulefiles -module load miniconda3/4.12.0 - -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/gaea/miniconda_regional_workflow.lua b/modulefiles/tasks/gaea/miniconda_regional_workflow.lua new file mode 100644 index 0000000000..dd8ec8f7e4 --- /dev/null +++ b/modulefiles/tasks/gaea/miniconda_regional_workflow.lua @@ -0,0 +1,4 @@ +prepend_path("MODULEPATH", "/lustre/f2/dev/role.epic/contrib/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) + +setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/tasks/gaea/run_fcst.local b/modulefiles/tasks/gaea/run_fcst.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/gaea/run_fcst.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/gaea/run_fcst.local.lua b/modulefiles/tasks/gaea/run_fcst.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/run_fcst.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/run_vx.local b/modulefiles/tasks/gaea/run_vx.local deleted file mode 100644 index f9a59c8e78..0000000000 --- a/modulefiles/tasks/gaea/run_vx.local +++ /dev/null @@ -1,5 +0,0 @@ -#%Module - -module load miniconda_regional_workflow - -prepend-path LD_LIBRARY_PATH /ncrc/sw/gaea-cle7/python/3.9/anaconda-base/envs/noaa_py3.9/lib diff --git a/modulefiles/tasks/gaea/run_vx.local.lua b/modulefiles/tasks/gaea/run_vx.local.lua new file mode 100644 index 0000000000..85e2bc2053 --- /dev/null +++ b/modulefiles/tasks/gaea/run_vx.local.lua @@ -0,0 +1,2 @@ +load("miniconda_regional_workflow") +prepend_path("LD_LIBRARY_PATH", "/ncrc/sw/gaea-cle7/python/3.9/anaconda-base/envs/noaa_py3.9/lib") diff --git a/modulefiles/tasks/hera/get_extrn_ics.local b/modulefiles/tasks/hera/get_extrn_ics.local deleted file mode 100644 index dc099871e1..0000000000 --- a/modulefiles/tasks/hera/get_extrn_ics.local +++ /dev/null @@ -1,7 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_ics task. -############################################################# - -module load hpss - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/hera/get_extrn_ics.local.lua b/modulefiles/tasks/hera/get_extrn_ics.local.lua new file mode 100644 index 0000000000..d1afe2451e --- /dev/null +++ b/modulefiles/tasks/hera/get_extrn_ics.local.lua @@ -0,0 +1,2 @@ +load("hpss") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/get_extrn_lbcs.local b/modulefiles/tasks/hera/get_extrn_lbcs.local deleted file mode 100644 index 1b420d33bc..0000000000 --- a/modulefiles/tasks/hera/get_extrn_lbcs.local +++ /dev/null @@ -1,7 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_lbcs task. -############################################################# - -module load hpss - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/hera/get_extrn_lbcs.local.lua b/modulefiles/tasks/hera/get_extrn_lbcs.local.lua new file mode 100644 index 0000000000..d1afe2451e --- /dev/null +++ b/modulefiles/tasks/hera/get_extrn_lbcs.local.lua @@ -0,0 +1,2 @@ +load("hpss") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/get_obs.local b/modulefiles/tasks/hera/get_obs.local deleted file mode 100644 index 9ed022a5a1..0000000000 --- a/modulefiles/tasks/hera/get_obs.local +++ /dev/null @@ -1,11 +0,0 @@ -#%Module##################################################### -## Module file for get_obs_ccpa, get_obs_mrms, and -## get_obs_ndas task. -############################################################# - -module load hpss - -module use /contrib/miniconda3/modulefiles -module load miniconda3/4.5.12 - -setenv SRW_ENV pygraf diff --git a/modulefiles/tasks/hera/get_obs.local.lua b/modulefiles/tasks/hera/get_obs.local.lua new file mode 100644 index 0000000000..c53d3ff3de --- /dev/null +++ b/modulefiles/tasks/hera/get_obs.local.lua @@ -0,0 +1,5 @@ +load("hpss") +prepend_path("MODULEPATH", "/contrib/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12") + +setenv("SRW_ENV", "pygraf") diff --git a/modulefiles/tasks/hera/make_grid.local b/modulefiles/tasks/hera/make_grid.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/hera/make_grid.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/hera/make_grid.local.lua b/modulefiles/tasks/hera/make_grid.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/hera/make_grid.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/make_ics.local b/modulefiles/tasks/hera/make_ics.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/hera/make_ics.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/hera/make_ics.local.lua b/modulefiles/tasks/hera/make_ics.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/hera/make_ics.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/make_lbcs.local b/modulefiles/tasks/hera/make_lbcs.local deleted file mode 100644 index 61a3a77250..0000000000 --- a/modulefiles/tasks/hera/make_lbcs.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/hera/make_lbcs.local.lua b/modulefiles/tasks/hera/make_lbcs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/hera/make_lbcs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/miniconda_regional_workflow b/modulefiles/tasks/hera/miniconda_regional_workflow deleted file mode 100644 index 48de7a99bb..0000000000 --- a/modulefiles/tasks/hera/miniconda_regional_workflow +++ /dev/null @@ -1,5 +0,0 @@ -#%Module -module use /contrib/miniconda3/modulefiles -module load miniconda3/4.5.12 - -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/hera/miniconda_regional_workflow.lua b/modulefiles/tasks/hera/miniconda_regional_workflow.lua new file mode 100644 index 0000000000..0443b7d948 --- /dev/null +++ b/modulefiles/tasks/hera/miniconda_regional_workflow.lua @@ -0,0 +1,4 @@ +prepend_path("MODULEPATH", "/contrib/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12")) + +setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/tasks/hera/run_fcst.local b/modulefiles/tasks/hera/run_fcst.local deleted file mode 100644 index 61a3a77250..0000000000 --- a/modulefiles/tasks/hera/run_fcst.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/hera/run_fcst.local.lua b/modulefiles/tasks/hera/run_fcst.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/hera/run_fcst.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/run_vx.local b/modulefiles/tasks/hera/run_vx.local deleted file mode 100644 index 51416ff471..0000000000 --- a/modulefiles/tasks/hera/run_vx.local +++ /dev/null @@ -1,5 +0,0 @@ -#%Module - -module use -a /contrib/anaconda/modulefiles -module load intel/18.0.5.274 -module load anaconda/latest diff --git a/modulefiles/tasks/hera/run_vx.local.lua b/modulefiles/tasks/hera/run_vx.local.lua new file mode 100644 index 0000000000..4fc605bc83 --- /dev/null +++ b/modulefiles/tasks/hera/run_vx.local.lua @@ -0,0 +1,3 @@ +append_path("MODULEPATH", "/contrib/anaconda/modulefiles") +load(pathJoin("intel", os.gentenv("intel_ver") or "18.0.5.274")) +load(pathJoin("anaconda", os.getenv("anaconda_ver") or "latest")) diff --git a/modulefiles/tasks/jet/get_extrn_ics.local b/modulefiles/tasks/jet/get_extrn_ics.local deleted file mode 100644 index 4b0b48cc00..0000000000 --- a/modulefiles/tasks/jet/get_extrn_ics.local +++ /dev/null @@ -1,9 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_ics task. -############################################################# - -module purge - -module load hpss - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/jet/get_extrn_ics.local.lua b/modulefiles/tasks/jet/get_extrn_ics.local.lua new file mode 100644 index 0000000000..d1afe2451e --- /dev/null +++ b/modulefiles/tasks/jet/get_extrn_ics.local.lua @@ -0,0 +1,2 @@ +load("hpss") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/get_extrn_lbcs.local b/modulefiles/tasks/jet/get_extrn_lbcs.local deleted file mode 100644 index 477dfb2e40..0000000000 --- a/modulefiles/tasks/jet/get_extrn_lbcs.local +++ /dev/null @@ -1,9 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_lbcs task. -############################################################# - -module purge - -module load hpss - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/jet/get_extrn_lbcs.local.lua b/modulefiles/tasks/jet/get_extrn_lbcs.local.lua new file mode 100644 index 0000000000..d1afe2451e --- /dev/null +++ b/modulefiles/tasks/jet/get_extrn_lbcs.local.lua @@ -0,0 +1,2 @@ +load("hpss") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/make_grid.local b/modulefiles/tasks/jet/make_grid.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/jet/make_grid.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/jet/make_grid.local.lua b/modulefiles/tasks/jet/make_grid.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/jet/make_grid.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/make_ics.local b/modulefiles/tasks/jet/make_ics.local deleted file mode 100644 index 61a3a77250..0000000000 --- a/modulefiles/tasks/jet/make_ics.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/jet/make_ics.local.lua b/modulefiles/tasks/jet/make_ics.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/jet/make_ics.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/make_lbcs.local b/modulefiles/tasks/jet/make_lbcs.local deleted file mode 100644 index 61a3a77250..0000000000 --- a/modulefiles/tasks/jet/make_lbcs.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/jet/make_lbcs.local.lua b/modulefiles/tasks/jet/make_lbcs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/jet/make_lbcs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/miniconda_regional_workflow b/modulefiles/tasks/jet/miniconda_regional_workflow deleted file mode 100644 index 48de7a99bb..0000000000 --- a/modulefiles/tasks/jet/miniconda_regional_workflow +++ /dev/null @@ -1,5 +0,0 @@ -#%Module -module use /contrib/miniconda3/modulefiles -module load miniconda3/4.5.12 - -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/jet/miniconda_regional_workflow.lua b/modulefiles/tasks/jet/miniconda_regional_workflow.lua new file mode 100644 index 0000000000..0443b7d948 --- /dev/null +++ b/modulefiles/tasks/jet/miniconda_regional_workflow.lua @@ -0,0 +1,4 @@ +prepend_path("MODULEPATH", "/contrib/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12")) + +setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/tasks/jet/run_fcst.local b/modulefiles/tasks/jet/run_fcst.local deleted file mode 100644 index 61a3a77250..0000000000 --- a/modulefiles/tasks/jet/run_fcst.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/jet/run_fcst.local.lua b/modulefiles/tasks/jet/run_fcst.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/jet/run_fcst.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/run_vx.local b/modulefiles/tasks/jet/run_vx.local deleted file mode 100644 index 9be1ed3c79..0000000000 --- a/modulefiles/tasks/jet/run_vx.local +++ /dev/null @@ -1,5 +0,0 @@ -#%Module - -module use -a /contrib/anaconda/modulefiles -module load intel/18.0.5.274 -module load anaconda/5.3.1 diff --git a/modulefiles/tasks/jet/run_vx.local.lua b/modulefiles/tasks/jet/run_vx.local.lua new file mode 100644 index 0000000000..26cbb9088c --- /dev/null +++ b/modulefiles/tasks/jet/run_vx.local.lua @@ -0,0 +1,3 @@ +append_path("MODULEPATH", "/contrib/anaconda/modulefiles") +load(pathJoin("intel", os.gentenv("intel_ver") or "18.0.5.274")) +load(pathJoin("anaconda", os.getenv("anaconda_ver") or "5.3.1")) diff --git a/modulefiles/tasks/noaacloud/get_extrn_ics.local b/modulefiles/tasks/noaacloud/get_extrn_ics.local deleted file mode 100644 index 5d5eb22d2f..0000000000 --- a/modulefiles/tasks/noaacloud/get_extrn_ics.local +++ /dev/null @@ -1,6 +0,0 @@ -#%Module - -module load miniconda_regional_workflow -prepend-path PATH /contrib/GST/miniconda/envs/regional_workflow/bin -setenv SRW_ENV regional_workflow - diff --git a/modulefiles/tasks/noaacloud/get_extrn_ics.local.lua b/modulefiles/tasks/noaacloud/get_extrn_ics.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/get_extrn_ics.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/get_extrn_lbcs.local b/modulefiles/tasks/noaacloud/get_extrn_lbcs.local deleted file mode 100644 index 7c9bd15b53..0000000000 --- a/modulefiles/tasks/noaacloud/get_extrn_lbcs.local +++ /dev/null @@ -1,5 +0,0 @@ -#%Module - -module load miniconda_regional_workflow -prepend-path PATH /contrib/GST/miniconda/envs/regional_workflow/bin -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/noaacloud/get_extrn_lbcs.local.lua b/modulefiles/tasks/noaacloud/get_extrn_lbcs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/get_extrn_lbcs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/make_grid.local b/modulefiles/tasks/noaacloud/make_grid.local deleted file mode 100644 index 6799120ead..0000000000 --- a/modulefiles/tasks/noaacloud/make_grid.local +++ /dev/null @@ -1,11 +0,0 @@ -#%Module - -module use /contrib/spack-stack/apps/srw-app-test/modulefiles/Core -module load stack-intel -module load stack-intel-oneapi-mpi -module load netcdf-c -module load netcdf-fortran - -module load miniconda_regional_workflow -prepend-path PATH /contrib/GST/miniconda/envs/regional_workflow/bin -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/noaacloud/make_grid.local.lua b/modulefiles/tasks/noaacloud/make_grid.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/make_grid.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/make_ics.local b/modulefiles/tasks/noaacloud/make_ics.local deleted file mode 100644 index 39c0f90851..0000000000 --- a/modulefiles/tasks/noaacloud/make_ics.local +++ /dev/null @@ -1,13 +0,0 @@ -#%Module - -module use /contrib/spack-stack/apps/srw-app-test/modulefiles/Core -module load stack-intel -module load stack-intel-oneapi-mpi -module load netcdf-c -module load netcdf-fortran -module load libpng -module load jasper - -module load miniconda_regional_workflow -prepend-path PATH /contrib/GST/miniconda/envs/regional_workflow/bin -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/noaacloud/make_ics.local.lua b/modulefiles/tasks/noaacloud/make_ics.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/make_ics.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/make_lbcs.local b/modulefiles/tasks/noaacloud/make_lbcs.local deleted file mode 100644 index 39c0f90851..0000000000 --- a/modulefiles/tasks/noaacloud/make_lbcs.local +++ /dev/null @@ -1,13 +0,0 @@ -#%Module - -module use /contrib/spack-stack/apps/srw-app-test/modulefiles/Core -module load stack-intel -module load stack-intel-oneapi-mpi -module load netcdf-c -module load netcdf-fortran -module load libpng -module load jasper - -module load miniconda_regional_workflow -prepend-path PATH /contrib/GST/miniconda/envs/regional_workflow/bin -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/noaacloud/make_lbcs.local.lua b/modulefiles/tasks/noaacloud/make_lbcs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/make_lbcs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/make_orog.local b/modulefiles/tasks/noaacloud/make_orog.local deleted file mode 100644 index 6799120ead..0000000000 --- a/modulefiles/tasks/noaacloud/make_orog.local +++ /dev/null @@ -1,11 +0,0 @@ -#%Module - -module use /contrib/spack-stack/apps/srw-app-test/modulefiles/Core -module load stack-intel -module load stack-intel-oneapi-mpi -module load netcdf-c -module load netcdf-fortran - -module load miniconda_regional_workflow -prepend-path PATH /contrib/GST/miniconda/envs/regional_workflow/bin -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/noaacloud/make_orog.local.lua b/modulefiles/tasks/noaacloud/make_orog.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/make_orog.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/make_sfc_climo.local b/modulefiles/tasks/noaacloud/make_sfc_climo.local deleted file mode 100644 index 6799120ead..0000000000 --- a/modulefiles/tasks/noaacloud/make_sfc_climo.local +++ /dev/null @@ -1,11 +0,0 @@ -#%Module - -module use /contrib/spack-stack/apps/srw-app-test/modulefiles/Core -module load stack-intel -module load stack-intel-oneapi-mpi -module load netcdf-c -module load netcdf-fortran - -module load miniconda_regional_workflow -prepend-path PATH /contrib/GST/miniconda/envs/regional_workflow/bin -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/noaacloud/make_sfc_climo.local.lua b/modulefiles/tasks/noaacloud/make_sfc_climo.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/make_sfc_climo.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/miniconda_regional_workflow b/modulefiles/tasks/noaacloud/miniconda_regional_workflow deleted file mode 100644 index 936a9d4c84..0000000000 --- a/modulefiles/tasks/noaacloud/miniconda_regional_workflow +++ /dev/null @@ -1,5 +0,0 @@ -#%Module -module use -a /contrib/GST/miniconda3/modulefiles -module load miniconda3/4.10.3 - -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/noaacloud/miniconda_regional_workflow.lua b/modulefiles/tasks/noaacloud/miniconda_regional_workflow.lua new file mode 100644 index 0000000000..74486df795 --- /dev/null +++ b/modulefiles/tasks/noaacloud/miniconda_regional_workflow.lua @@ -0,0 +1,4 @@ +prepend_path("MODULEPATH", "/contrib/GST/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.10.3")) + +setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/tasks/noaacloud/run_fcst.local b/modulefiles/tasks/noaacloud/run_fcst.local deleted file mode 100644 index 39c0f90851..0000000000 --- a/modulefiles/tasks/noaacloud/run_fcst.local +++ /dev/null @@ -1,13 +0,0 @@ -#%Module - -module use /contrib/spack-stack/apps/srw-app-test/modulefiles/Core -module load stack-intel -module load stack-intel-oneapi-mpi -module load netcdf-c -module load netcdf-fortran -module load libpng -module load jasper - -module load miniconda_regional_workflow -prepend-path PATH /contrib/GST/miniconda/envs/regional_workflow/bin -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/noaacloud/run_fcst.local.lua b/modulefiles/tasks/noaacloud/run_fcst.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/run_fcst.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/run_post.local b/modulefiles/tasks/noaacloud/run_post.local deleted file mode 100644 index 39c0f90851..0000000000 --- a/modulefiles/tasks/noaacloud/run_post.local +++ /dev/null @@ -1,13 +0,0 @@ -#%Module - -module use /contrib/spack-stack/apps/srw-app-test/modulefiles/Core -module load stack-intel -module load stack-intel-oneapi-mpi -module load netcdf-c -module load netcdf-fortran -module load libpng -module load jasper - -module load miniconda_regional_workflow -prepend-path PATH /contrib/GST/miniconda/envs/regional_workflow/bin -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/noaacloud/run_post.local.lua b/modulefiles/tasks/noaacloud/run_post.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/run_post.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/odin/get_extrn_ics.local b/modulefiles/tasks/odin/get_extrn_ics.local deleted file mode 100644 index 77e8616036..0000000000 --- a/modulefiles/tasks/odin/get_extrn_ics.local +++ /dev/null @@ -1,8 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_ics task. -############################################################# - -#module purge - -#module load hpss - diff --git a/modulefiles/tasks/odin/get_extrn_ics.local.lua b/modulefiles/tasks/odin/get_extrn_ics.local.lua new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modulefiles/tasks/odin/get_extrn_lbcs.local b/modulefiles/tasks/odin/get_extrn_lbcs.local deleted file mode 100644 index e0b1eb8abd..0000000000 --- a/modulefiles/tasks/odin/get_extrn_lbcs.local +++ /dev/null @@ -1,8 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_lbcs task. -############################################################# - -#module purge - -#module load hpss - diff --git a/modulefiles/tasks/odin/get_extrn_lbcs.local.lua b/modulefiles/tasks/odin/get_extrn_lbcs.local.lua new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modulefiles/tasks/orion/get_extrn_ics.local b/modulefiles/tasks/orion/get_extrn_ics.local deleted file mode 100644 index 73f80e7b10..0000000000 --- a/modulefiles/tasks/orion/get_extrn_ics.local +++ /dev/null @@ -1,6 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_ics task. -############################################################# - -module load miniconda_regional_workflow - diff --git a/modulefiles/tasks/orion/get_extrn_ics.local.lua b/modulefiles/tasks/orion/get_extrn_ics.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/get_extrn_ics.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/orion/get_extrn_lbcs.local b/modulefiles/tasks/orion/get_extrn_lbcs.local deleted file mode 100644 index 5612f95a22..0000000000 --- a/modulefiles/tasks/orion/get_extrn_lbcs.local +++ /dev/null @@ -1,5 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_lbcs task. -############################################################# - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/orion/get_extrn_lbcs.local.lua b/modulefiles/tasks/orion/get_extrn_lbcs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/get_extrn_lbcs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/orion/make_grid.local b/modulefiles/tasks/orion/make_grid.local deleted file mode 100644 index 92505cf09c..0000000000 --- a/modulefiles/tasks/orion/make_grid.local +++ /dev/null @@ -1,3 +0,0 @@ -#%Module - -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/orion/make_grid.local.lua b/modulefiles/tasks/orion/make_grid.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/make_grid.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/orion/make_ics.local b/modulefiles/tasks/orion/make_ics.local deleted file mode 100644 index 61a3a77250..0000000000 --- a/modulefiles/tasks/orion/make_ics.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/orion/make_ics.local.lua b/modulefiles/tasks/orion/make_ics.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/make_ics.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/orion/make_lbcs.local b/modulefiles/tasks/orion/make_lbcs.local deleted file mode 100644 index 61a3a77250..0000000000 --- a/modulefiles/tasks/orion/make_lbcs.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/orion/make_lbcs.local.lua b/modulefiles/tasks/orion/make_lbcs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/make_lbcs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/orion/miniconda_regional_workflow b/modulefiles/tasks/orion/miniconda_regional_workflow deleted file mode 100644 index 3703a9ba17..0000000000 --- a/modulefiles/tasks/orion/miniconda_regional_workflow +++ /dev/null @@ -1,5 +0,0 @@ -#%Module -module use -a /apps/contrib/miniconda3-noaa-gsl/modulefiles -module load miniconda3/3.8 - -setenv SRW_ENV regional_workflow diff --git a/modulefiles/tasks/orion/miniconda_regional_workflow.lua b/modulefiles/tasks/orion/miniconda_regional_workflow.lua new file mode 100644 index 0000000000..22b0f4a5ce --- /dev/null +++ b/modulefiles/tasks/orion/miniconda_regional_workflow.lua @@ -0,0 +1,4 @@ +append_path("MODULEPATH", "/apps/contrib/miniconda3-noaa-gsl/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "3.8")) + +setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/tasks/orion/run_fcst.local b/modulefiles/tasks/orion/run_fcst.local deleted file mode 100644 index 61a3a77250..0000000000 --- a/modulefiles/tasks/orion/run_fcst.local +++ /dev/null @@ -1,2 +0,0 @@ -#%Module -module load miniconda_regional_workflow diff --git a/modulefiles/tasks/orion/run_fcst.local.lua b/modulefiles/tasks/orion/run_fcst.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/run_fcst.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/stampede/get_extrn_ics.local b/modulefiles/tasks/stampede/get_extrn_ics.local deleted file mode 100644 index 77e8616036..0000000000 --- a/modulefiles/tasks/stampede/get_extrn_ics.local +++ /dev/null @@ -1,8 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_ics task. -############################################################# - -#module purge - -#module load hpss - diff --git a/modulefiles/tasks/stampede/get_extrn_ics.local.lua b/modulefiles/tasks/stampede/get_extrn_ics.local.lua new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modulefiles/tasks/stampede/get_extrn_lbcs.local b/modulefiles/tasks/stampede/get_extrn_lbcs.local deleted file mode 100644 index e0b1eb8abd..0000000000 --- a/modulefiles/tasks/stampede/get_extrn_lbcs.local +++ /dev/null @@ -1,8 +0,0 @@ -#%Module##################################################### -## Module file for get_extrn_lbcs task. -############################################################# - -#module purge - -#module load hpss - diff --git a/modulefiles/tasks/stampede/get_extrn_lbcs.local.lua b/modulefiles/tasks/stampede/get_extrn_lbcs.local.lua new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modulefiles/tasks/wcoss2/get_extrn_ics.local b/modulefiles/tasks/wcoss2/get_extrn_ics.local deleted file mode 100644 index c96547a641..0000000000 --- a/modulefiles/tasks/wcoss2/get_extrn_ics.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load intel/$::env(intel_ver) -module load python/$::env(python_ver) diff --git a/modulefiles/tasks/wcoss2/get_extrn_ics.local.lua b/modulefiles/tasks/wcoss2/get_extrn_ics.local.lua new file mode 100644 index 0000000000..16559474cd --- /dev/null +++ b/modulefiles/tasks/wcoss2/get_extrn_ics.local.lua @@ -0,0 +1,2 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) diff --git a/modulefiles/tasks/wcoss2/get_extrn_lbcs.local b/modulefiles/tasks/wcoss2/get_extrn_lbcs.local deleted file mode 100644 index c96547a641..0000000000 --- a/modulefiles/tasks/wcoss2/get_extrn_lbcs.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load intel/$::env(intel_ver) -module load python/$::env(python_ver) diff --git a/modulefiles/tasks/wcoss2/get_extrn_lbcs.local.lua b/modulefiles/tasks/wcoss2/get_extrn_lbcs.local.lua new file mode 100644 index 0000000000..16559474cd --- /dev/null +++ b/modulefiles/tasks/wcoss2/get_extrn_lbcs.local.lua @@ -0,0 +1,2 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) diff --git a/modulefiles/tasks/wcoss2/get_obs.local b/modulefiles/tasks/wcoss2/get_obs.local deleted file mode 100644 index c96547a641..0000000000 --- a/modulefiles/tasks/wcoss2/get_obs.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load intel/$::env(intel_ver) -module load python/$::env(python_ver) diff --git a/modulefiles/tasks/wcoss2/get_obs.local.lua b/modulefiles/tasks/wcoss2/get_obs.local.lua new file mode 100644 index 0000000000..16559474cd --- /dev/null +++ b/modulefiles/tasks/wcoss2/get_obs.local.lua @@ -0,0 +1,2 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) diff --git a/modulefiles/tasks/wcoss2/make_grid.local b/modulefiles/tasks/wcoss2/make_grid.local deleted file mode 100644 index c96547a641..0000000000 --- a/modulefiles/tasks/wcoss2/make_grid.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load intel/$::env(intel_ver) -module load python/$::env(python_ver) diff --git a/modulefiles/tasks/wcoss2/make_grid.local.lua b/modulefiles/tasks/wcoss2/make_grid.local.lua new file mode 100644 index 0000000000..16559474cd --- /dev/null +++ b/modulefiles/tasks/wcoss2/make_grid.local.lua @@ -0,0 +1,2 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) diff --git a/modulefiles/tasks/wcoss2/make_ics.local b/modulefiles/tasks/wcoss2/make_ics.local deleted file mode 100644 index c96547a641..0000000000 --- a/modulefiles/tasks/wcoss2/make_ics.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load intel/$::env(intel_ver) -module load python/$::env(python_ver) diff --git a/modulefiles/tasks/wcoss2/make_ics.local.lua b/modulefiles/tasks/wcoss2/make_ics.local.lua new file mode 100644 index 0000000000..16559474cd --- /dev/null +++ b/modulefiles/tasks/wcoss2/make_ics.local.lua @@ -0,0 +1,2 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) diff --git a/modulefiles/tasks/wcoss2/make_lbcs.local b/modulefiles/tasks/wcoss2/make_lbcs.local deleted file mode 100644 index c96547a641..0000000000 --- a/modulefiles/tasks/wcoss2/make_lbcs.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load intel/$::env(intel_ver) -module load python/$::env(python_ver) diff --git a/modulefiles/tasks/wcoss2/make_lbcs.local.lua b/modulefiles/tasks/wcoss2/make_lbcs.local.lua new file mode 100644 index 0000000000..16559474cd --- /dev/null +++ b/modulefiles/tasks/wcoss2/make_lbcs.local.lua @@ -0,0 +1,2 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) diff --git a/modulefiles/tasks/wcoss2/run_fcst.local b/modulefiles/tasks/wcoss2/run_fcst.local deleted file mode 100644 index c96547a641..0000000000 --- a/modulefiles/tasks/wcoss2/run_fcst.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load intel/$::env(intel_ver) -module load python/$::env(python_ver) diff --git a/modulefiles/tasks/wcoss2/run_fcst.local.lua b/modulefiles/tasks/wcoss2/run_fcst.local.lua new file mode 100644 index 0000000000..16559474cd --- /dev/null +++ b/modulefiles/tasks/wcoss2/run_fcst.local.lua @@ -0,0 +1,2 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) diff --git a/modulefiles/tasks/wcoss2/run_vx.local b/modulefiles/tasks/wcoss2/run_vx.local deleted file mode 100644 index c96547a641..0000000000 --- a/modulefiles/tasks/wcoss2/run_vx.local +++ /dev/null @@ -1,4 +0,0 @@ -#%Module - -module load intel/$::env(intel_ver) -module load python/$::env(python_ver) diff --git a/modulefiles/tasks/wcoss2/run_vx.local.lua b/modulefiles/tasks/wcoss2/run_vx.local.lua new file mode 100644 index 0000000000..16559474cd --- /dev/null +++ b/modulefiles/tasks/wcoss2/run_vx.local.lua @@ -0,0 +1,2 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) diff --git a/modulefiles/wflow_cheyenne b/modulefiles/wflow_cheyenne deleted file mode 100644 index 7041823915..0000000000 --- a/modulefiles/wflow_cheyenne +++ /dev/null @@ -1,20 +0,0 @@ -#%Module - -proc ModulesHelp { } { - put stderr "This module loads rocoto and the python environment" - put stderr "for running the UFS SRW App on the CISL machine Cheyenne" -} - -module-whatis "Loads libraries and utilities needed for running SRW on Cheyenne" - -module load ncarenv -module use -a /glade/p/ral/jntp/UFS_SRW_app/modules/ -module load rocoto -module load conda/latest - -if { [module-info mode load] } { - puts stderr "Please do the following to activate conda: - > conda activate /glade/p/ral/jntp/UFS_SRW_app/conda/regional_workflow" -} - - diff --git a/modulefiles/wflow_cheyenne.lua b/modulefiles/wflow_cheyenne.lua new file mode 100644 index 0000000000..7a7473b639 --- /dev/null +++ b/modulefiles/wflow_cheyenne.lua @@ -0,0 +1,20 @@ +help([[ +This module loads python environement for running the UFS SRW App on +on the CISL machine Cheyenne +]]) + +whatis([===[Loads libraries needed for running the UFS SRW App on Cheyenne ]===]) + +load("ncarenv") + +append_path("MODULEPATH","/glade/p/ral/jntp/UFS_SRW_app/modules") +load("rocoto") + +load(pathJoin("conda", os.getenv("conda_ver") or "latest")) + +if mode() == "load" then + LmodMsgRaw([===[Please do the following to activate conda: + > conda activate regional_workflow +]===]) +end + diff --git a/modulefiles/wflow_gaea b/modulefiles/wflow_gaea deleted file mode 100644 index 18568f7fcf..0000000000 --- a/modulefiles/wflow_gaea +++ /dev/null @@ -1,21 +0,0 @@ -#%Module - -proc ModulesHelp { } { - put stderr "This module loads python environement for running SRW on" - put stderr "the NOAA RDHPC machine Gaea" -} - -module-whatis "Loads libraries needed for running SRW on Gaea" - -module use /lustre/f2/dev/role.epic/contrib/modulefiles -module load miniconda3/4.12.0 -module load rocoto -module load alps - -setenv CONDA_DEFAULT_ENV "regional_workflow" -setenv PROJ_LIB /lustre/f2/dev/role.epic/contrib/miniconda3/4.12.0/envs/regional_workflow/share/proj - -if { [module-info mode load] } { - puts stderr "Please do the following to activate conda: - > conda activate regional_workflow" -} diff --git a/modulefiles/wflow_gaea.lua b/modulefiles/wflow_gaea.lua new file mode 100644 index 0000000000..e4b726aac1 --- /dev/null +++ b/modulefiles/wflow_gaea.lua @@ -0,0 +1,19 @@ +help([[ +This module loads python environement for running the UFS SRW App on +the NOAA RDHPC machine Gaea +]]) + +whatis([===[Loads libraries needed for running the UFS SRW App on gaea ]===]) + +prepend_path("MODULEPATH","/lustre/f2/dev/role.epic/contrib/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) +load("rocoto") +load("alps") + +setenv("PROJ_LIB", "/lustre/f2/dev/role.epic/contrib/miniconda3/4.12.0/envs/regional_workflow/share/proj") + +if mode() == "load" then + LmodMsgRaw([===[Please do the following to activate conda: + > conda activate regional_workflow +]===]) +end diff --git a/modulefiles/wflow_hera b/modulefiles/wflow_hera deleted file mode 100644 index 71641a3d11..0000000000 --- a/modulefiles/wflow_hera +++ /dev/null @@ -1,19 +0,0 @@ -#%Module - -proc ModulesHelp { } { - put stderr "This module loads python environement for running SRW on" - put stderr "the NOAA RDHPC machine Hera" -} - -module-whatis "Loads libraries needed for running SRW on Hera" - -module load rocoto - -module use /contrib/miniconda3/modulefiles -module load miniconda3/4.5.12 - -if { [module-info mode load] } { - puts stderr "Please do the following to activate conda: - > conda activate regional_workflow" -} - diff --git a/modulefiles/wflow_hera.lua b/modulefiles/wflow_hera.lua new file mode 100644 index 0000000000..58bc83d0c4 --- /dev/null +++ b/modulefiles/wflow_hera.lua @@ -0,0 +1,17 @@ +help([[ +This module loads python environement for running the UFS SRW App on +the NOAA RDHPC machine Hera +]]) + +whatis([===[Loads libraries needed for running the UFS SRW App on Hera ]===]) + +load("rocoto") + +prepend_path("MODULEPATH","/contrib/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12")) + +if mode() == "load" then + LmodMsgRaw([===[Please do the following to activate conda: + > conda activate regional_workflow +]===]) +end diff --git a/modulefiles/wflow_jet b/modulefiles/wflow_jet deleted file mode 100644 index 7aa7d0e67a..0000000000 --- a/modulefiles/wflow_jet +++ /dev/null @@ -1,19 +0,0 @@ -#%Module - -proc ModulesHelp { } { - put stderr "This module loads python environement for running SRW on" - put stderr "the NOAA RDHPC machine Jet" -} - -module-whatis "Loads libraries needed for running SRW on Jet" - -module load rocoto - -module use /contrib/miniconda3/modulefiles -module load miniconda3/4.5.12 - -if { [module-info mode load] } { - puts stderr "Please do the following to activate conda: - > conda activate regional_workflow" -} - diff --git a/modulefiles/wflow_jet.lua b/modulefiles/wflow_jet.lua new file mode 100644 index 0000000000..3c651ae788 --- /dev/null +++ b/modulefiles/wflow_jet.lua @@ -0,0 +1,17 @@ +help([[ +This module loads python environement for running the UFS SRW App on +the NOAA RDHPC machine Jet +]]) + +whatis([===[Loads libraries needed for running the UFS SRW App on Jet ]===]) + +load("rocoto") + +prepend_path("MODULEPATH","/contrib/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12")) + +if mode() == "load" then + LmodMsgRaw([===[Please do the following to activate conda: + > conda activate regional_workflow +]===]) +end diff --git a/modulefiles/wflow_linux b/modulefiles/wflow_linux deleted file mode 100644 index 2d4a4e33e9..0000000000 --- a/modulefiles/wflow_linux +++ /dev/null @@ -1,29 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module activates python environement for running SRW on general Linux" -} - -module-whatis "This module activates python environment for running SRW on general Linux" - -setenv CMAKE_Platform linux - -# This path should point to your python virtual environment directory, -# `regional_workflow`, created earlier for -# -setenv VENV "$env(HOME)/venv/regional_workflow" -if { [module-info mode load] } { - puts stderr "Verify the Python virtual environment path \$VENV shown below is correct, " - puts stderr "set to the correct path otherwise: " - puts stderr "VENV=$env(VENV) " - puts stderr "Please do the following to activate python virtual environment: - > source \$VENV/bin/activate " -} - -# Uncomment if Rocoto workflow manager is used -# This path should point to your Rocoto module location -# setenv ROCOTOmod "/Users/username/modules" -# module use $env(ROCOTOmod) -# module load rocoto - - diff --git a/modulefiles/wflow_linux.lua b/modulefiles/wflow_linux.lua new file mode 100644 index 0000000000..edfafa727d --- /dev/null +++ b/modulefiles/wflow_linux.lua @@ -0,0 +1,26 @@ +help([[ +This module activates python environement for running the UFS SRW App on Linux +]]) + +whatis([===[This module activates python environment for running the UFS SRW App on Linux]===]) + +setenv("CMAKE_Platform", "linux") +setenv("VENV", pathJoin(os.getenv("HOME"), "venv/regional_workflow")) + +--[[ +local ROCOTOmod="/Users/username/modules" +prepend_path("MODULEPATH", ROCOTOmod) +load(rocoto) +--]] + +if mode() == "load" then + LmodMsgRaw([===[Verify the Python virtual environment path \$VENV shown below is correct, +set to the correct path otherwise: +VENV=$env(VENV) " +Please do the following to activate python virtual environment: + > source \$VENV/bin/activate +]===]) +end +if mode() == "unload" then + execute{cmd="deactivate", modeA={"unload"}} +end diff --git a/modulefiles/wflow_macos b/modulefiles/wflow_macos deleted file mode 100644 index 9b8e27b2d7..0000000000 --- a/modulefiles/wflow_macos +++ /dev/null @@ -1,31 +0,0 @@ -#%Module - -proc ModulesHelp { } { - puts stderr "This module activates python environement for running SRW on macOS" -} - -module-whatis "Loads libraries needed for running SRW on macOS" - -setenv CMAKE_Platform macos - -# This path should point to your python virtual environment directory, -# `regional_workflow`, created earlier for -# -setenv VENV "$env(HOME)/venv/regional_workflow" -if { [module-info mode load] } { - puts stderr "Verify the Python virtual environment path \$VENV shown below is correct, " - puts stderr "set to the correct path otherwise: " - puts stderr "VENV=$env(VENV) " - puts stderr "Please do the following to activate python virtual environment: - > source \$VENV/bin/activate " -} -if { [module-info mode remove] } { - puts "deactivate;" -} - -# Uncomment if Rocoto workflow manager is used -# This path should point to your Rocoto module location -# setenv ROCOTOmod "/Users/username/modules" -# module use $env(ROCOTOmod) -# module load rocoto - diff --git a/modulefiles/wflow_macos.lua b/modulefiles/wflow_macos.lua new file mode 100644 index 0000000000..d1425197ad --- /dev/null +++ b/modulefiles/wflow_macos.lua @@ -0,0 +1,26 @@ +help([[ +This module activates python environement for running the UFS SRW App on general macOS +]]) + +whatis([===[This module activates python environment for running the UFS SRW App on macOS]===]) + +setenv("CMAKE_Platform", "macos") +setenv("VENV", pathJoin(os.getenv("HOME"), "venv/regional_workflow")) + +--[[ +local ROCOTOmod="/Users/username/modules" +prepend_path("MODULEPATH", ROCOTOmod) +load(rocoto) +--]] + +if mode() == "load" then + LmodMsgRaw([===[Verify the Python virtual environment path \$VENV shown below is correct, " +set to the correct path otherwise: " +VENV=$env(VENV) " +Please do the following to activate python virtual environment: + > source \$VENV/bin/activate " +]===]) +end +if mode() == "unload" then + execute{cmd="deactivate", modeA={"unload"}} +end diff --git a/modulefiles/wflow_noaacloud b/modulefiles/wflow_noaacloud deleted file mode 100644 index 2344974d90..0000000000 --- a/modulefiles/wflow_noaacloud +++ /dev/null @@ -1,23 +0,0 @@ -#%Module - -proc ModulesHelp { } { - put stderr "This module loads python environement for running SRW on" - put stderr "the NOAA cloud" -} - -module-whatis "Loads libraries needed for running SRW on NOAA cloud" - -module use /apps/modules/modulefiles -module load rocoto -module use /contrib/GST/miniconda3/modulefiles -module load miniconda3/4.10.3 - -setenv PROJ_LIB "/contrib/GST/miniconda/envs/regional_workflow/share/proj" -setenv OPT "/contrib/EPIC/hpc-modules" -append-path PATH "/contrib/GST/miniconda/envs/regional_workflow/bin" - -if { [module-info mode load] } { - puts stderr "Please do the following to activate conda: - > conda activate regional_workflow" -} - diff --git a/modulefiles/wflow_noaacloud.lua b/modulefiles/wflow_noaacloud.lua new file mode 100644 index 0000000000..23746052a0 --- /dev/null +++ b/modulefiles/wflow_noaacloud.lua @@ -0,0 +1,22 @@ +help([[ +This module loads python environement for running the UFS SRW App on +the NOAA cloud +]]) + +whatis([===[Loads libraries needed for running the UFS SRW App on NOAA cloud ]===]) + +prepend_path("MODULEPATH","/apps/modules/modulefiles") +load("rocoto") + +prepend_path("MODULEPATH","/contrib/GST/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.10.3")) + +setenv("PROJ_LIB","/contrib/GST/miniconda/envs/regional_workflow/share/proj") +setenv("OPT","/contrib/EPIC/hpc-modules") +append_path("PATH","/contrib/GST/miniconda/envs/regional_workflow/bin") + +if mode() == "load" then + LmodMsgRaw([===[Please do the following to activate conda: + > conda activate regional_workflow +]===]) +end diff --git a/modulefiles/wflow_odin b/modulefiles/wflow_odin deleted file mode 100644 index ca240f84e1..0000000000 --- a/modulefiles/wflow_odin +++ /dev/null @@ -1,42 +0,0 @@ -#%Module - -proc ModulesHelp { } { - put stderr "This module loads python environement for running SRW on" - put stderr "NSSL machine Odin" -} - -module-whatis "Loads libraries needed for running SRW on Odin" - -if { [module-info mode load] } { - # >>> conda initialize >>> - # !! Contents within this block are managed by 'conda init' !! - set shell [module-info shelltype] - set conda_path "/scratch/software/Odin/python/anaconda2" - if {$shell == "csh"} { - set conda_file "$conda_path/conda.csh" - } else { - set conda_file "$conda_path/conda.sh" - } - - if {[ file exists "$conda_file" ]} { - system "source $conda_file;" - } else { - prepend-path PATH "$conda_path/bin" - } - # <<< conda initialize <<< - - # To make "regional_workflow" avaiable, - # you should uncomment the following lines, which create file ".condarc" - # or install the environment yourself. - # -# set cmd {cat > $HOME/.condarc < conda config --set changeps1 False - > conda activate regional_workflow" -} - diff --git a/modulefiles/wflow_odin.lua b/modulefiles/wflow_odin.lua new file mode 100644 index 0000000000..7b1b5d8203 --- /dev/null +++ b/modulefiles/wflow_odin.lua @@ -0,0 +1,33 @@ +help([[ +This module loads python environement for running the UFS SRW App on +the NSSL machine Odin +]]) + +whatis([===[Loads libraries needed for running the UFS SRW App on Odin ]===]) + +if mode() == "load" then + -- >>> conda initialize >>> + -- !! Contents within this block are managed by 'conda init' !! + local shell=myShellType() + local conda_path="/scratch/software/Odin/python/anaconda2" + local conda_file + if shell == "csh" then + conda_file=pathJoin(conda_path,"conda.csh") + else + conda_file=pathJoin(conda_path,"conda.sh") + end + + local exit_code = os.execute('test -f'..conda_file) + if exit_code == 0 then + local mcmd="source " .. conda_file + execute{cmd=mcmd, modeA={"load"}} + else + prepend_path("PATH", pathJoin(conda_path,"bin")) + end + -- <<< conda initialize <<< + + LmodMsgRaw([===[Please do the following to activate conda: + > conda config --set changeps1 False + > conda activate regional_workflow + ]===]) +end diff --git a/modulefiles/wflow_orion b/modulefiles/wflow_orion deleted file mode 100644 index fb3439b0b9..0000000000 --- a/modulefiles/wflow_orion +++ /dev/null @@ -1,19 +0,0 @@ -#%Module - -proc ModulesHelp { } { - put stderr "This module loads python environement for running SRW on" - put stderr "the MSU machine Orion" -} - -module-whatis "Loads libraries needed for running SRW on Orion" - -module load contrib rocoto - -module use -a /apps/contrib/miniconda3-noaa-gsl/modulefiles -module load miniconda3/3.8 - -if { [module-info mode load] } { - puts stderr "Please do the following to activate conda: - > conda activate regional_workflow" -} - diff --git a/modulefiles/wflow_orion.lua b/modulefiles/wflow_orion.lua new file mode 100644 index 0000000000..29518b70a9 --- /dev/null +++ b/modulefiles/wflow_orion.lua @@ -0,0 +1,19 @@ +help([[ +This module loads python environement for running SRW on +the MSU machine Orion +]]) + +whatis([===[Loads libraries needed for running SRW on Orion ]===]) + +load("contrib") +load("rocoto") + +append_path("MODULEPATH","/apps/contrib/miniconda3-noaa-gsl/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "3.8")) + +if mode() == "load" then + LmodMsgRaw([===[Please do the following to activate conda: + > conda activate regional_workflow +]===]) +end + diff --git a/modulefiles/wflow_singularity b/modulefiles/wflow_singularity deleted file mode 100644 index af765e015b..0000000000 --- a/modulefiles/wflow_singularity +++ /dev/null @@ -1,16 +0,0 @@ -#%Module - -proc ModulesHelp { } { - put stderr "This module loads python environement for running SRW in" - put stderr "a singularity container" -} - -module-whatis "Loads libraries needed for running SRW in a singularity container" - -module use -a /opt/hpc-modules/modulefiles/core -module load miniconda3 - -if { [module-info mode load] } { - system "conda activate regional_workflow;" -} - diff --git a/modulefiles/wflow_singularity.lua b/modulefiles/wflow_singularity.lua new file mode 100644 index 0000000000..3c16a93570 --- /dev/null +++ b/modulefiles/wflow_singularity.lua @@ -0,0 +1,13 @@ +help([[ +This module loads python environement for running the UFS SRW App in +a singularity container +]]) + +whatis([===[Loads libraries needed for running the UFS SRW App in a singularity container]===]) + +append_path("MODULEPATH","/opt/hpc-modules/modulefiles/core") +load("miniconda3") + +if mode() == "load" then + execute{cmd="conda activate regional_workflow", modeA={"load"}} +end diff --git a/modulefiles/wflow_wcoss2 b/modulefiles/wflow_wcoss2 deleted file mode 100644 index c6b78f2dcb..0000000000 --- a/modulefiles/wflow_wcoss2 +++ /dev/null @@ -1,14 +0,0 @@ -#%Module - -proc ModulesHelp { } { - put stderr "This module loads python environement for running SRW on" - put stderr "the NOAA operational machine WCOSS2 (Cactus/Dogwood)" -} - -module-whatis "Loads libraries needed for running SRW on WCOSS2 (Cactus/Dogwood)" - -module load intel/$::env(intel_ver) -module load python/$::env(python_ver) - -module use /apps/ops/test/nco/modulefiles -module load core/rocoto/$::env(rocoto_ver) diff --git a/modulefiles/wflow_wcoss2.lua b/modulefiles/wflow_wcoss2.lua new file mode 100644 index 0000000000..a061b93323 --- /dev/null +++ b/modulefiles/wflow_wcoss2.lua @@ -0,0 +1,13 @@ +help([[ +This module loads python environement for running the UFS SRW App on +the NOAA operational machine WCOSS2 (Cactus/Dogwood)" +]]) + +whatis([===[Loads libraries needed for running the UFS SRW App on WCOSS2 ]===]) + +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) + +prepend_path("MODULEPATH","/apps/ops/test/nco/modulefiles") +load(pathJoin("core/rocoto", os.getenv("rocoto_ver"))) + diff --git a/parm/FV3LAM_wflow.xml b/parm/FV3LAM_wflow.xml index 08cb4e45a2..1a7593a751 100644 --- a/parm/FV3LAM_wflow.xml +++ b/parm/FV3LAM_wflow.xml @@ -95,9 +95,14 @@ Directories and files. {%- if run_envir == "nco" %} +{%- if do_ensemble %} {{ run }}.@Y@m@d/{{ net }}.t@Hz.{{ ensmem_indx_name }}#{{ ensmem_indx_name }}#.dyn"> {{ run }}.@Y@m@d/{{ net }}.t@Hz.{{ ensmem_indx_name }}#{{ ensmem_indx_name }}#.phy"> {%- else %} +{{ run }}.@Y@m@d/{{ net }}.t@Hz.dyn"> +{{ run }}.@Y@m@d/{{ net }}.t@Hz.phy"> +{%- endif %} +{%- else %} @Y@m@d@H{{ slash_ensmem_subdir }}/dyn"> @Y@m@d@H{{ slash_ensmem_subdir }}/phy"> {%- endif %} diff --git a/ush/load_modules_run_task.sh b/ush/load_modules_run_task.sh index 708541c5a3..efd14c88ab 100755 --- a/ush/load_modules_run_task.sh +++ b/ush/load_modules_run_task.sh @@ -164,7 +164,7 @@ fi # Load the .local module file if available for the given task # modulefile_local="${task_name}.local" -if [ -f ${modules_dir}/${modulefile_local} ]; then +if [ -f ${modules_dir}/${modulefile_local}.lua ]; then module load "${modulefile_local}" || print_err_msg_exit "\ Loading .local module file (in directory specified by mod- ules_dir) for the specified task (task_name) failed: diff --git a/ush/load_modules_wflow.sh b/ush/load_modules_wflow.sh index 51a85de46c..6049805a62 100755 --- a/ush/load_modules_wflow.sh +++ b/ush/load_modules_wflow.sh @@ -41,7 +41,7 @@ scrfunc_dir=$( dirname "${scrfunc_fp}" ) HOMEdir=$( dirname "${scrfunc_dir}" ) # source version file (run) only if it is specified in versions directory -RUN_VER_FN="run_ver.${machine}" +RUN_VER_FN="run.ver.${machine}" VERSION_FILE="${HOMEdir}/versions/${RUN_VER_FN}" if [ -f ${VERSION_FILE} ]; then . ${VERSION_FILE} @@ -70,5 +70,6 @@ fi $has_mu && set -u # List loaded modulefiles +module --version module list diff --git a/ush/machine/jet.yaml b/ush/machine/jet.yaml index c5aa0ca398..cf8545de75 100644 --- a/ush/machine/jet.yaml +++ b/ush/machine/jet.yaml @@ -38,8 +38,8 @@ task_run_fcst: FIXlut: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/fix/fix_lut data: FV3GFS: - - nemsio: /public/data/grids/gfs/nemsio - - grib2: /public/data/grids/gfs/0p25deg/grib2 - - netcdf: /public/data/grids/gfs/anl/netcdf + nemsio: /public/data/grids/gfs/nemsio + grib2: /public/data/grids/gfs/0p25deg/grib2 + netcdf: /public/data/grids/gfs/anl/netcdf RAP: /public/data/grids/rap/full/wrfprs/grib2 HRRR: /public/data/grids/hrrr/conus/wrfprs/grib2 diff --git a/ush/python_utils/environment.py b/ush/python_utils/environment.py index 1655150649..f327a74f40 100644 --- a/ush/python_utils/environment.py +++ b/ush/python_utils/environment.py @@ -224,7 +224,7 @@ def import_vars(dictionary=None, target_dict=None, env_vars=None): for k, v in env_vars.items(): # Don't replace variable with empty value - if not ((k in target_dict) and (v == "")): + if not ((k in target_dict) and (v is None or v == "")): target_dict[k] = str_to_list(v) diff --git a/ush/setup.py b/ush/setup.py index 187304f81e..4d6841be54 100644 --- a/ush/setup.py +++ b/ush/setup.py @@ -75,23 +75,21 @@ def setup(): # # Step-1 of config # ================ - # Set the name of the configuration file containing default values for - # the experiment/workflow variables. Then load its content. + # Load the configuration file containing default values for the experiment. # # ----------------------------------------------------------------------- # EXPT_DEFAULT_CONFIG_FN = "config_defaults.yaml" cfg_d = load_config_file(os.path.join(USHdir, EXPT_DEFAULT_CONFIG_FN)) - EXPT_CONFIG_FN = cfg_d["workflow"]["EXPT_CONFIG_FN"] + import_vars(dictionary=flatten_dict(cfg_d), + env_vars=["EXPT_CONFIG_FN", + "EXTRN_MDL_NAME_ICS", "EXTRN_MDL_NAME_LBCS", + "FV3GFS_FILE_FMT_ICS", "FV3GFS_FILE_FMT_LBCS"]) # # ----------------------------------------------------------------------- # - # Load the user config file but don't source it yet. This file - # contains user-specified values for a subset of the experiment/workflow - # variables that override their default values. Note that the user- - # specified configuration file is not tracked by the repository, whereas - # the default configuration file is tracked. + # Load the user config file but don't source it yet. # # ----------------------------------------------------------------------- # From e08e5c5c9a7ce4cee475fc253ca286284eed2c35 Mon Sep 17 00:00:00 2001 From: Michael Kavulich Date: Fri, 21 Oct 2022 15:17:41 -0700 Subject: [PATCH 02/45] [develop] Improve error messaging and logging for generate_FV3LAM_wflow.py (#414) The error messaging in the generate_FV3LAM_wflow.py has been overhauled to be more pythonic and more user-friendly. The old bash-like print_err_msg_exit() calls are replaced with proper exception handling, and print_info_msg() calls are replaced with the use of Python's built-in logging module. The latter has the added benefit of giving the same "tee"-like functionality--where messages are printed to screen and written to a log file simultaneously--without the need for messy subprocesses and the confusing error messages that come with them. Errors are now handled in a consistent way, with the errors clearly highlighted both on screen and in the log file, as well as an easy-to-follow exception traceback for those wanting that information. In addition, several error conditions that were previously not caught at the generate step now cause the script to fail with helpful error messages. From the user perspective, functionality will not change, aside from differences when error conditions are present. Successful runs will remain the same, except that some log messaging has been clarified, and the log file contains additional information for each message, as well as some indentation changes for ease of reading. --- tests/WE2E/run_WE2E_tests.sh | 57 ++ ush/config_defaults.yaml | 2 +- ush/generate_FV3LAM_wflow.py | 302 +++----- ush/get_crontab_contents.py | 8 +- ush/python_utils/__init__.py | 2 +- .../check_for_preexist_dir_file.py | 19 +- ush/python_utils/check_var_valid_value.py | 14 +- ush/python_utils/config_parser.py | 26 +- ush/python_utils/print_msg.py | 25 +- ush/set_ozone_param.py | 29 +- ush/set_predef_grid_params.py | 10 +- ush/set_thompson_mp_fix_files.py | 13 +- ush/setup.py | 705 +++++++----------- 13 files changed, 519 insertions(+), 693 deletions(-) diff --git a/tests/WE2E/run_WE2E_tests.sh b/tests/WE2E/run_WE2E_tests.sh index bddf87ca83..ec06a88150 100755 --- a/tests/WE2E/run_WE2E_tests.sh +++ b/tests/WE2E/run_WE2E_tests.sh @@ -65,6 +65,63 @@ WE2Edir="$TESTSdir/WE2E" # #----------------------------------------------------------------------- # +# Run python checks +# +#----------------------------------------------------------------------- +# + +# This line will return two numbers: the python major and minor versions +pyversion=($(/usr/bin/env python3 -c 'import platform; major, minor, patch = platform.python_version_tuple(); print(major); print(minor)')) + +#Now, set an error check variable so that we can print all python errors rather than just the first +pyerrors=0 + +# Check that the call to python3 returned no errors, then check if the +# python3 minor version is 6 or higher +if [[ -z "$pyversion" ]];then + print_info_msg "\ + + Error: python3 not found" + pyerrors=$((pyerrors+1)) +else + if [[ ${#pyversion[@]} -lt 2 ]]; then + print_info_msg "\ + + Error retrieving python3 version" + pyerrors=$((pyerrors+1)) + elif [[ ${pyversion[1]} -lt 6 ]]; then + print_info_msg "\ + + Error: python version must be 3.6 or higher + python version: ${pyversion[*]}" + pyerrors=$((pyerrors+1)) + fi +fi + +#Next, check for the non-standard python packages: jinja2, yaml, and f90nml +pkgs=(jinja2 yaml f90nml) +for pkg in ${pkgs[@]} ; do + if ! /usr/bin/env python3 -c "import ${pkg}" &> /dev/null; then + print_info_msg "\ + + Error: python module ${pkg} not available" + pyerrors=$((pyerrors+1)) + fi +done + +#Finally, check if the number of errors is >0, and if so exit with helpful message +if [ $pyerrors -gt 0 ];then + print_err_msg_exit "\ + Errors found: check your python environment + + Instructions for setting up python environments can be found on the web: + https://github.com/ufs-community/ufs-srweather-app/wiki/Getting-Started + +" +fi +# +#----------------------------------------------------------------------- +# # Save current shell options (in a global array). Then set new options # for this script or function. # diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 96bca2e66f..2c5831a4df 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -54,7 +54,7 @@ user: # #----------------------------------------------------------------------- MACHINE: "BIG_COMPUTER" - ACCOUNT: "project_name" + ACCOUNT: "" #---------------------------- # PLATFORM config parameters diff --git a/ush/generate_FV3LAM_wflow.py b/ush/generate_FV3LAM_wflow.py index 63be16bd50..11a86c9aaa 100755 --- a/ush/generate_FV3LAM_wflow.py +++ b/ush/generate_FV3LAM_wflow.py @@ -5,6 +5,7 @@ import platform import subprocess import unittest +import logging from multiprocessing import Process from textwrap import dedent from datetime import datetime, timedelta @@ -12,6 +13,7 @@ from python_utils import ( print_info_msg, print_err_msg_exit, + log_info, import_vars, cp_vrfy, cd_vrfy, @@ -61,57 +63,43 @@ def python_error_handler(): python_error_handler() -def generate_FV3LAM_wflow(): +def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> None: """Function to setup a forecast experiment and create a workflow - (according to the parameters specified in the config file + (according to the parameters specified in the config file) Args: - None + USHdir (str): The full path of the ush/ directory where this script is located + logfile (str): The name of the file where logging is written Returns: None """ - print( - dedent( + # Set up logging to write to screen and logfile + setup_logging(logfile) + + log_info( """ ======================================================================== - ======================================================================== - Starting experiment generation... - - ======================================================================== ========================================================================""" - ) ) - # set USHdir - USHdir = os.path.dirname(os.path.abspath(__file__)) - # check python version major, minor, patch = platform.python_version_tuple() if int(major) < 3 or int(minor) < 6: - print_info_msg( + logging.error( f""" Error: python version must be 3.6 or higher python version: {major}.{minor}""" ) + raise - # define macros + # define utilities define_macos_utilities() - # - # ----------------------------------------------------------------------- - # - # Source the file that defines and then calls the setup function. The - # setup function in turn first sources the default configuration file - # (which contains default values for the experiment/workflow parameters) - # and then sources the user-specified configuration file (which contains - # user-specified values for a subset of the experiment/workflow parame- - # ters that override their default values). - # - # ----------------------------------------------------------------------- - # + # The setup function reads the user configuration file and fills in + # non-user-specified values from config_defaults.yaml setup() # import all environment variables @@ -134,8 +122,8 @@ def generate_FV3LAM_wflow(): # Create a multiline variable that consists of a yaml-compliant string # specifying the values that the jinja variables in the template rocoto # XML should be set to. These values are set either in the user-specified - # workflow configuration file (EXPT_CONFIG_FN) or in the setup.sh script - # sourced above. Then call the python script that generates the XML. + # workflow configuration file (EXPT_CONFIG_FN) or in the setup() function + # called above. Then call the python script that generates the XML. # # ----------------------------------------------------------------------- # @@ -143,7 +131,7 @@ def generate_FV3LAM_wflow(): template_xml_fp = os.path.join(PARMdir, WFLOW_XML_FN) - print_info_msg( + log_info( f''' Creating rocoto workflow XML file (WFLOW_XML_FP) from jinja template XML file (template_xml_fp): @@ -438,17 +426,15 @@ def generate_FV3LAM_wflow(): # End of "settings" variable. settings_str = cfg_to_yaml_str(settings) - print_info_msg( - dedent( + log_info( f""" The variable \"settings\" specifying values of the rococo XML variables has been set as follows: #----------------------------------------------------------------------- - settings =\n\n""" + settings =\n\n""", + verbose=VERBOSE, ) - + settings_str, - verbose=VERBOSE, - ) + log_info(settings_str, verbose=VERBOSE) # # Call the python script to generate the experiment's actual XML file @@ -459,7 +445,7 @@ def generate_FV3LAM_wflow(): ["-q", "-u", settings_str, "-t", template_xml_fp, "-o", WFLOW_XML_FP] ) except: - print_err_msg_exit( + logging.exception( dedent( f""" Call to python script fill_jinja_template.py to create a rocoto workflow @@ -482,7 +468,7 @@ def generate_FV3LAM_wflow(): # # ----------------------------------------------------------------------- # - print_info_msg( + log_info( f''' Creating symlink in the experiment directory (EXPTDIR) that points to the workflow launch script (WFLOW_LAUNCH_SCRIPT_FP): @@ -505,23 +491,13 @@ def generate_FV3LAM_wflow(): # if USE_CRON_TO_RELAUNCH: add_crontab_line() - # - # ----------------------------------------------------------------------- - # - # Create the FIXam directory under the experiment directory. In NCO mode, - # this will be a symlink to the directory specified in FIXgsm, while in - # community mode, it will be an actual directory with files copied into - # it from FIXgsm. - # - # ----------------------------------------------------------------------- - # # - # Symlink fix files + # Copy or symlink fix files # if SYMLINK_FIX_FILES: - print_info_msg( + log_info( f''' Symlinking fixed files from system directory (FIXgsm) to a subdirectory (FIXam): FIXgsm = \"{FIXgsm}\" @@ -530,12 +506,9 @@ def generate_FV3LAM_wflow(): ) ln_vrfy(f'''-fsn "{FIXgsm}" "{FIXam}"''') - # - # Copy relevant fix files. - # else: - print_info_msg( + log_info( f''' Copying fixed files from system directory (FIXgsm) to a subdirectory (FIXam): FIXgsm = \"{FIXgsm}\" @@ -559,7 +532,7 @@ def generate_FV3LAM_wflow(): # ----------------------------------------------------------------------- # if USE_MERRA_CLIMO: - print_info_msg( + log_info( f''' Copying MERRA2 aerosol climatology data files from system directory (FIXaer/FIXlut) to a subdirectory (FIXclim) in the experiment directory: @@ -585,27 +558,27 @@ def generate_FV3LAM_wflow(): # # ----------------------------------------------------------------------- # - print_info_msg( + log_info( f""" Copying templates of various input files to the experiment directory...""", verbose=VERBOSE, ) - print_info_msg( + log_info( f""" Copying the template data table file to the experiment directory...""", verbose=VERBOSE, ) cp_vrfy(DATA_TABLE_TMPL_FP, DATA_TABLE_FP) - print_info_msg( + log_info( f""" Copying the template field table file to the experiment directory...""", verbose=VERBOSE, ) cp_vrfy(FIELD_TABLE_TMPL_FP, FIELD_TABLE_FP) - print_info_msg( + log_info( f""" Copying the template NEMS configuration file to the experiment directory...""", verbose=VERBOSE, @@ -616,7 +589,7 @@ def generate_FV3LAM_wflow(): # clone of the FV3 code repository to the experiment directory (EXPT- # DIR). # - print_info_msg( + log_info( f""" Copying the CCPP physics suite definition XML file from its location in the forecast model directory sturcture to the experiment directory...""", @@ -628,7 +601,7 @@ def generate_FV3LAM_wflow(): # clone of the FV3 code repository to the experiment directory (EXPT- # DIR). # - print_info_msg( + log_info( f""" Copying the field dictionary file from its location in the forecast model directory sturcture to the experiment directory...""", @@ -642,7 +615,7 @@ def generate_FV3LAM_wflow(): # # ----------------------------------------------------------------------- # - print_info_msg( + log_info( f''' Setting parameters in weather model's namelist file (FV3_NML_FP): FV3_NML_FP = \"{FV3_NML_FP}\"''' @@ -660,9 +633,6 @@ def generate_FV3LAM_wflow(): # Otherwise, leave it unspecified (which means it gets set to the default # value in the forecast model). # - # NOTE: - # May want to remove kice from FV3.input.yml (and maybe input.nml.FV3). - # kice = None if SDF_USES_RUC_LSM: kice = 9 @@ -877,17 +847,13 @@ def generate_FV3LAM_wflow(): settings_str = cfg_to_yaml_str(settings) - print_info_msg( - dedent( + log_info( f""" The variable \"settings\" specifying values of the weather model's - namelist variables has been set as follows: - - settings =\n\n""" - ) - + settings_str, + namelist variables has been set as follows:\n""", verbose=VERBOSE, ) + log_info("\nsettings =\n\n" + settings_str, verbose=VERBOSE) # # ----------------------------------------------------------------------- # @@ -917,7 +883,7 @@ def generate_FV3LAM_wflow(): ] ) except: - print_err_msg_exit( + logging.exception( dedent( f""" Call to python script set_namelist.py to generate an FV3 namelist file @@ -950,6 +916,13 @@ def generate_FV3LAM_wflow(): if not RUN_TASK_MAKE_GRID: set_FV3nml_sfc_climo_filenames() + + # Call function to get NOMADS data + if NOMADS: + raise Exception("Nomads script does not work!") + + # get_nomads_data(NOMADS_file_type,EXPTDIR,USHdir,DATE_FIRST_CYCL,CYCL_HRS,FCST_LEN_HRS,LBC_SPEC_INTVL_HRS) + # # ----------------------------------------------------------------------- # @@ -975,7 +948,7 @@ def generate_FV3LAM_wflow(): rocotorun_cmd = f"rocotorun -w {WFLOW_XML_FN} -d {wflow_db_fn} -v 10" rocotostat_cmd = f"rocotostat -w {WFLOW_XML_FN} -d {wflow_db_fn} -v 10" - print_info_msg( + log_info( f""" ======================================================================== ======================================================================== @@ -988,33 +961,16 @@ def generate_FV3LAM_wflow(): ======================================================================== """ ) - # # ----------------------------------------------------------------------- # - # If rocoto is required, print instructions on how to load and use it + # If rocoto is required, print instructions on how to use it # # ----------------------------------------------------------------------- # if WORKFLOW_MANAGER == "rocoto": - print_info_msg( + log_info( f""" - To launch the workflow, first ensure that you have a compatible version - of rocoto available. For most pre-configured platforms, rocoto can be - loaded via a module: - - > module load rocoto - - For more details on rocoto, see the User's Guide. - - To launch the workflow, first ensure that you have a compatible version - of rocoto loaded. For example, to load version 1.3.1 of rocoto, use - - > module load rocoto/1.3.1 - - (This version has been tested on hera; later versions may also work but - have not been tested.) - To launch the workflow, change location to the experiment directory (EXPTDIR) and issue the rocotrun command, as follows: @@ -1043,127 +999,60 @@ def generate_FV3LAM_wflow(): */{CRON_RELAUNCH_INTVL_MNTS} * * * * cd {EXPTDIR} && ./launch_FV3LAM_wflow.sh called_from_cron=\"TRUE\" """ ) - # - # If necessary, run the NOMADS script to source external model data. - # - if NOMADS: - print("Getting NOMADS online data") - print(f"NOMADS_file_type= {NOMADS_file_type}") - cd_vrfy(EXPTDIR) - NOMADS_script = os.path.join(USHdir, "NOMADS_get_extrn_mdl_files.h") - run_command( - f"""{NOMADS_script} {date_to_str(DATE_FIRST_CYCL,format="%Y%m%d")} \ - {date_to_str(DATE_FIRST_CYCL,format="%H")} {NOMADS_file_type} {FCST_LEN_HRS} {LBC_SPEC_INTVL_HRS}""" - ) + # If we got to this point everything was successful: move the log file to the experiment directory. + mv_vrfy(logfile, EXPTDIR) + +def get_nomads_data(NOMADS_file_type,EXPTDIR,USHdir,DATE_FIRST_CYCL,CYCL_HRS,FCST_LEN_HRS,LBC_SPEC_INTVL_HRS): + print("Getting NOMADS online data") + print(f"NOMADS_file_type= {NOMADS_file_type}") + cd_vrfy(EXPTDIR) + NOMADS_script = os.path.join(USHdir, "NOMADS_get_extrn_mdl_files.sh") + run_command(f"""{NOMADS_script} {date_to_str(DATE_FIRST_CYCL,format="%Y%m%d")} \ + {date_to_str(DATE_FIRST_CYCL,format="%H")} {NOMADS_file_type} {FCST_LEN_HRS} {LBC_SPEC_INTVL_HRS}""") + +def setup_logging(logfile: str = 'log.generate_FV3LAM_wflow') -> None: + """ + Sets up logging, printing high-priority (INFO and higher) messages to screen, and printing all + messages with detailed timing and routine info in the specified text file. + """ + logging.basicConfig(level=logging.DEBUG, + format='%(name)-22s %(levelname)-8s %(message)s', + filename=logfile, + filemode='w') + logging.debug(f'Finished setting up debug file logging in {logfile}') + console = logging.StreamHandler() + console.setLevel(logging.INFO) + logging.getLogger().addHandler(console) + logging.debug('Logging set up successfully') -# -# ----------------------------------------------------------------------- -# -# Start of the script that will call the experiment/workflow generation -# function defined above. -# -# ----------------------------------------------------------------------- -# if __name__ == "__main__": - # - # ----------------------------------------------------------------------- - # - # Set directories. - # - # ----------------------------------------------------------------------- - # + USHdir = os.path.dirname(os.path.abspath(__file__)) - # - # Set the name of and full path to the temporary file in which we will - # save some experiment/workflow variables. The need for this temporary - # file is explained below. - # - tmp_fn = "tmp" - tmp_fp = os.path.join(USHdir, tmp_fn) - rm_vrfy("-f", tmp_fp) - # - # Set the name of and full path to the log file in which the output from - # the experiment/workflow generation function will be saved. - # - log_fn = "log.generate_FV3LAM_wflow" - log_fp = os.path.join(USHdir, log_fn) - rm_vrfy("-f", log_fp) - # + logfile=f'{USHdir}/log.generate_FV3LAM_wflow' + # Call the generate_FV3LAM_wflow function defined above to generate the - # experiment/workflow. Note that we pipe the output of the function - # (and possibly other commands) to the "tee" command in order to be able - # to both save it to a file and print it out to the screen (stdout). - # The piping causes the call to the function (and the other commands - # grouped with it using the curly braces, { ... }) to be executed in a - # subshell. As a result, the experiment/workflow variables that the - # function sets are not available outside of the grouping, i.e. they are - # not available at and after the call to "tee". Since some of these va- - # riables are needed after the call to "tee" below, we save them in a - # temporary file and read them in outside the subshell later below. - # - def workflow_func(): - retval = 1 - generate_FV3LAM_wflow() - retval = 0 - run_command(f'''echo "{EXPTDIR}" >> "{tmp_fp}"''') - run_command(f'''echo "{retval}" >> "{tmp_fp}"''') - - # create tee functionality - tee = subprocess.Popen(["tee", log_fp], stdin=subprocess.PIPE) - os.dup2(tee.stdin.fileno(), sys.stdout.fileno()) - os.dup2(tee.stdin.fileno(), sys.stderr.fileno()) - - # create workflow process - p = Process(target=workflow_func) - p.start() - p.join() - - # - # Read in experiment/workflow variables needed later below from the tem- - # porary file created in the subshell above containing the call to the - # generate_FV3LAM_wflow function. These variables are not directly - # available here because the call to generate_FV3LAM_wflow above takes - # place in a subshell (due to the fact that we are then piping its out- - # put to the "tee" command). Then remove the temporary file. - # - (_, exptdir, _) = run_command(f'''sed "1q;d" "{tmp_fp}"''') - (_, retval, _) = run_command(f''' sed "2q;d" "{tmp_fp}"''') - if retval: - retval = int(retval) - else: - retval = 1 - rm_vrfy(tmp_fp) - # - # If the call to the generate_FV3LAM_wflow function above was success- - # ful, move the log file in which the "tee" command saved the output of - # the function to the experiment directory. - # - if retval == 0: - mv_vrfy(log_fp, exptdir) - # - # If the call to the generate_FV3LAM_wflow function above was not suc- - # cessful, print out an error message and exit with a nonzero return - # code. - # - else: - print_err_msg_exit( + # experiment/workflow. + try: + generate_FV3LAM_wflow(USHdir, logfile) + except: + logging.exception(dedent( f""" - Experiment generation failed. Check the log file from the ex- - periment/workflow generation script in the file specified by log_fp: - log_fp = \"{log_fp}\" - Stopping.""" - ) + ********************************************************************* + FATAL ERROR: + Experiment generation failed. See the error message(s) printed below. + For more detailed information, check the log file from the workflow + generation script: {logfile} + *********************************************************************\n + """ + )) class Testing(unittest.TestCase): def test_generate_FV3LAM_wflow(self): - # run workflows in separate process to avoid conflict - def workflow_func(): - generate_FV3LAM_wflow() - - def run_workflow(): - p = Process(target=workflow_func) + # run workflows in separate process to avoid conflict between community and nco settings + def run_workflow(USHdir,logfile): + p = Process(target=generate_FV3LAM_wflow,args=(USHdir,logfile)) p.start() p.join() exit_code = p.exitcode @@ -1171,18 +1060,19 @@ def run_workflow(): sys.exit(exit_code) USHdir = os.path.dirname(os.path.abspath(__file__)) + logfile='log.generate_FV3LAM_wflow' SED = get_env_var("SED") # community test case cp_vrfy(f"{USHdir}/config.community.yaml", f"{USHdir}/config.yaml") run_command(f"""{SED} -i 's/MACHINE: hera/MACHINE: linux/g' {USHdir}/config.yaml""") - run_workflow() + run_workflow(USHdir, logfile) # nco test case set_env_var("OPSROOT", f"{USHdir}/../../nco_dirs") cp_vrfy(f"{USHdir}/config.nco.yaml", f"{USHdir}/config.yaml") run_command(f"""{SED} -i 's/MACHINE: hera/MACHINE: linux/g' {USHdir}/config.yaml""") - run_workflow() + run_workflow(USHdir, logfile) def setUp(self): define_macos_utilities() diff --git a/ush/get_crontab_contents.py b/ush/get_crontab_contents.py index b0950f5c6f..c6c8d41ee0 100644 --- a/ush/get_crontab_contents.py +++ b/ush/get_crontab_contents.py @@ -5,8 +5,10 @@ import unittest import argparse from datetime import datetime +from textwrap import dedent from python_utils import ( + log_info, import_vars, set_env_var, print_input_args, @@ -99,7 +101,7 @@ def add_crontab_line(): # time_stamp = datetime.now().strftime("%F_%T") crontab_backup_fp = os.path.join(EXPTDIR, f"crontab.bak.{time_stamp}") - print_info_msg( + log_info( f''' Copying contents of user cron table to backup file: crontab_backup_fp = \"{crontab_backup_fp}\"''', @@ -123,7 +125,7 @@ def add_crontab_line(): # Add crontab line if CRONTAB_LINE in crontab_contents: - print_info_msg( + log_info( f''' The following line already exists in the cron table and thus will not be added: @@ -132,7 +134,7 @@ def add_crontab_line(): else: - print_info_msg( + log_info( f''' Adding the following line to the user's cron table in order to automatically resubmit SRW workflow: diff --git a/ush/python_utils/__init__.py b/ush/python_utils/__init__.py index 8a74a595d0..add96ee981 100644 --- a/ush/python_utils/__init__.py +++ b/ush/python_utils/__init__.py @@ -28,7 +28,7 @@ from .get_elem_inds import get_elem_inds from .interpol_to_arbit_CRES import interpol_to_arbit_CRES from .print_input_args import print_input_args -from .print_msg import print_info_msg, print_err_msg_exit +from .print_msg import print_info_msg, print_err_msg_exit, log_info from .run_command import run_command from .get_charvar_from_netcdf import get_charvar_from_netcdf from .xml_parser import load_xml_file, has_tag_with_value diff --git a/ush/python_utils/check_for_preexist_dir_file.py b/ush/python_utils/check_for_preexist_dir_file.py index fc67447fb5..cfd4d50f43 100644 --- a/ush/python_utils/check_for_preexist_dir_file.py +++ b/ush/python_utils/check_for_preexist_dir_file.py @@ -2,10 +2,10 @@ import os from datetime import datetime -from .print_msg import print_info_msg, print_err_msg_exit +from textwrap import dedent from .check_var_valid_value import check_var_valid_value from .filesys_cmds_vrfy import rm_vrfy, mv_vrfy - +from .print_msg import log_info def check_for_preexist_dir_file(path, method): """Check for a preexisting directory or file and, if present, deal with it @@ -18,7 +18,14 @@ def check_for_preexist_dir_file(path, method): None """ - check_var_valid_value(method, ["delete", "rename", "quit"]) + try: + check_var_valid_value(method, ["delete", "rename", "quit"]) + except ValueError: + errmsg = dedent(f''' + Invalid method for dealing with pre-existing directory specified + method = {method} + ''') + raise ValueError(errmsg) from None if os.path.exists(path): if method == "delete": @@ -27,7 +34,7 @@ def check_for_preexist_dir_file(path, method): now = datetime.now() d = now.strftime("_old_%Y%m%d_%H%M%S") new_path = path + d - print_info_msg( + log_info( f""" Specified directory or file already exists: {path} @@ -36,8 +43,8 @@ def check_for_preexist_dir_file(path, method): ) mv_vrfy(path, new_path) else: - print_err_msg_exit( + raise FileExistsError(dedent( f""" Specified directory or file already exists {path}""" - ) + )) diff --git a/ush/python_utils/check_var_valid_value.py b/ush/python_utils/check_var_valid_value.py index 10d8365cb6..a8b88e17a6 100644 --- a/ush/python_utils/check_var_valid_value.py +++ b/ush/python_utils/check_var_valid_value.py @@ -1,23 +1,17 @@ #!/usr/bin/env python3 -from .print_msg import print_err_msg_exit - - -def check_var_valid_value(var, values, err_msg=None): +def check_var_valid_value(var, values): """Check if specified variable has a valid value Args: var: the variable values: list of valid values - err_msg: additional error message to print Returns: True: if var has valid value, exit(1) otherwise """ + if not var: + var = "" if var not in values: - if err_msg is not None: - err_msg = f"The value specified in var = {var} is not supported." - print_err_msg_exit( - err_msg + f"{var} must be set to one of the following:\n {values}" - ) + raise ValueError(f"Got '{var}', expected one of the following:\n {values}") return True diff --git a/ush/python_utils/config_parser.py b/ush/python_utils/config_parser.py index b89ab2b5a7..c1b69db5ff 100644 --- a/ush/python_utils/config_parser.py +++ b/ush/python_utils/config_parser.py @@ -36,7 +36,6 @@ from xml.dom import minidom from .environment import list_to_str, str_to_list -from .print_msg import print_err_msg_exit from .run_command import run_command ########## @@ -45,11 +44,8 @@ def load_yaml_config(config_file): """Safe load a yaml file""" - try: - with open(config_file, "r") as f: - cfg = yaml.safe_load(f) - except yaml.YAMLError as e: - print_err_msg_exit(str(e)) + with open(config_file, "r") as f: + cfg = yaml.safe_load(f) return cfg @@ -102,7 +98,7 @@ def load_json_config(config_file): with open(config_file, "r") as f: cfg = json.load(f) except json.JSONDecodeError as e: - print_err_msg_exit(str(e)) + raise Exception(f"Unable to load json file {config_file}") return cfg @@ -218,11 +214,10 @@ def load_ini_config(config_file, return_string=0): """Load a config file with a format similar to Microsoft's INI files""" if not os.path.exists(config_file): - print_err_msg_exit( - f''' - The specified configuration file does not exist: - \"{config_file}\"''' - ) + raise FileNotFoundError(dedent(f''' + The specified configuration file does not exist: + "{config_file}"''' + )) config = configparser.RawConfigParser() config.optionxform = str @@ -238,12 +233,7 @@ def get_ini_value(config, section, key): """Finds the value of a property in a given section""" if not section in config: - print_err_msg_exit( - f''' - Section not found: - section = \"{section}\" - valid sections = \"{config.keys()}\"''' - ) + raise KeyError(f'Section not found: {section}') else: return config[section][key] diff --git a/ush/python_utils/print_msg.py b/ush/python_utils/print_msg.py index 606284e140..8db0f06b03 100644 --- a/ush/python_utils/print_msg.py +++ b/ush/python_utils/print_msg.py @@ -2,7 +2,8 @@ import traceback import sys -from textwrap import dedent +from textwrap import dedent, indent +from logging import getLogger def print_err_msg_exit(error_msg="", stack_trace=True): @@ -39,3 +40,25 @@ def print_info_msg(info_msg, verbose=True): print(dedent(info_msg)) return True return False + +def log_info(info_msg, verbose=True, dedent_=True): + """Function to print information message using the logging module. This function + should not be used if python logging has not been initialized. + + Args: + info_msg : info message to print + verbose : set to False to silence printing + dedent_ : set to False to disable "dedenting" (print string as-is) + Returns: + None + """ + + # "sys._getframe().f_back.f_code.co_name" returns the name of the calling function + logger=getLogger(sys._getframe().f_back.f_code.co_name) + + if verbose: + if dedent_: + logger.info(indent(dedent(info_msg), ' ')) + else: + logger.info(info_msg) + diff --git a/ush/set_ozone_param.py b/ush/set_ozone_param.py index e371791452..5ed4449fe1 100644 --- a/ush/set_ozone_param.py +++ b/ush/set_ozone_param.py @@ -5,20 +5,18 @@ from textwrap import dedent from python_utils import ( + log_info, import_vars, export_vars, set_env_var, list_to_str, print_input_args, - print_info_msg, - print_err_msg_exit, define_macos_utilities, load_xml_file, has_tag_with_value, find_pattern_in_str, ) - def set_ozone_param(ccpp_phys_suite_fp): """Function that does the following: (1) Determines the ozone parameterization being used by checking in the @@ -92,13 +90,8 @@ def set_ozone_param(ccpp_phys_suite_fp): fixgsm_ozone_fn = "global_o3prdlos.f77" ozone_param = "ozphys" else: - print_err_msg_exit( - f''' - Unknown or no ozone parameterization - specified in the CCPP physics suite file (ccpp_phys_suite_fp): - ccpp_phys_suite_fp = \"{ccpp_phys_suite_fp}\" - ozone_param = \"{ozone_param}\"''' - ) + raise KeyError(f'Unknown or no ozone parameterization specified in the ' + 'CCPP physics suite file "{ccpp_phys_suite_fp}"') # # ----------------------------------------------------------------------- # @@ -151,27 +144,21 @@ def set_ozone_param(ccpp_phys_suite_fp): # ----------------------------------------------------------------------- # if fixgsm_ozone_fn_is_set: - - msg = dedent( + log_info( f""" After setting the file name of the ozone production/loss file in the FIXgsm directory (based on the ozone parameterization specified in the CCPP suite definition file), the array specifying the mapping between the symlinks that need to be created in the cycle directories and the files in the FIXam directory is: - - """ - ) - msg += dedent( - f""" + """, verbose=VERBOSE) + log_info(f""" CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING = {list_to_str(CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING)} - """ - ) - print_info_msg(msg, verbose=VERBOSE) + """, verbose=VERBOSE, dedent_=False) else: - print_err_msg_exit( + raise Exception( f''' Unable to set name of the ozone production/loss file in the FIXgsm directory in the array that specifies the mapping between the symlinks that need to diff --git a/ush/set_predef_grid_params.py b/ush/set_predef_grid_params.py index 2e48e5b4a8..6b432b8f03 100644 --- a/ush/set_predef_grid_params.py +++ b/ush/set_predef_grid_params.py @@ -2,6 +2,7 @@ import unittest import os +from textwrap import dedent from python_utils import ( import_vars, @@ -37,7 +38,14 @@ def set_predef_grid_params(): USHdir = os.path.dirname(os.path.abspath(__file__)) params_dict = load_config_file(os.path.join(USHdir, "predef_grid_params.yaml")) - params_dict = params_dict[PREDEF_GRID_NAME] + try: + params_dict = params_dict[PREDEF_GRID_NAME] + except KeyError: + errmsg = dedent(f''' + PREDEF_GRID_NAME = {PREDEF_GRID_NAME} not found in predef_grid_params.yaml + Check your config file settings.''') + raise Exception(errmsg) from None + # if QUILTING = False, remove key if not QUILTING: diff --git a/ush/set_thompson_mp_fix_files.py b/ush/set_thompson_mp_fix_files.py index 0d7a454ad4..93dc3c5de6 100644 --- a/ush/set_thompson_mp_fix_files.py +++ b/ush/set_thompson_mp_fix_files.py @@ -5,13 +5,12 @@ from textwrap import dedent from python_utils import ( + log_info, import_vars, export_vars, set_env_var, list_to_str, print_input_args, - print_info_msg, - print_err_msg_exit, define_macos_utilities, load_xml_file, has_tag_with_value, @@ -90,7 +89,7 @@ def set_thompson_mp_fix_files(ccpp_phys_suite_fp, thompson_mp_climo_fn): mapping = f"{fix_file} | {fix_file}" CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING.append(mapping) - msg = dedent( + log_info( f""" Since the Thompson microphysics parameterization is being used by this physics suite (CCPP_PHYS_SUITE), the names of the fixed files needed by @@ -100,21 +99,19 @@ def set_thompson_mp_fix_files(ccpp_phys_suite_fp, thompson_mp_climo_fn): CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING. After these modifications, the values of these parameters are as follows: + CCPP_PHYS_SUITE = \"{CCPP_PHYS_SUITE}\" """ ) - msg += dedent( + log_info( f""" - CCPP_PHYS_SUITE = \"{CCPP_PHYS_SUITE}\" - FIXgsm_FILES_TO_COPY_TO_FIXam = {list_to_str(FIXgsm_FILES_TO_COPY_TO_FIXam)} """ ) - msg += dedent( + log_info( f""" CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING = {list_to_str(CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING)} """ ) - print_info_msg(msg) EXPORTS = [ "CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING", diff --git a/ush/setup.py b/ush/setup.py index 4d6841be54..3fa7313727 100644 --- a/ush/setup.py +++ b/ush/setup.py @@ -3,9 +3,12 @@ import os import sys import datetime +import traceback from textwrap import dedent +from logging import getLogger from python_utils import ( + log_info, cd_vrfy, mkdir_vrfy, rm_vrfy, @@ -18,8 +21,6 @@ import_vars, export_vars, get_env_var, - print_info_msg, - print_err_msg_exit, load_config_file, cfg_to_shell_str, cfg_to_yaml_str, @@ -56,6 +57,7 @@ def setup(): None """ + logger = getLogger(__name__) global USHdir USHdir = os.path.dirname(os.path.abspath(__file__)) cd_vrfy(USHdir) @@ -64,7 +66,7 @@ def setup(): import_vars() # print message - print_info_msg( + log_info( f""" ======================================================================== Starting function setup() in \"{os.path.basename(__file__)}\"... @@ -86,26 +88,37 @@ def setup(): "EXTRN_MDL_NAME_ICS", "EXTRN_MDL_NAME_LBCS", "FV3GFS_FILE_FMT_ICS", "FV3GFS_FILE_FMT_LBCS"]) - # - # ----------------------------------------------------------------------- - # - # Load the user config file but don't source it yet. - # - # ----------------------------------------------------------------------- - # - if os.path.exists(EXPT_CONFIG_FN): + + # Load the user config file, then ensure all user-specified + # variables correspond to a default value. + if not os.path.exists(EXPT_CONFIG_FN): + raise FileNotFoundError(f'User config file not found: EXPT_CONFIG_FN = {EXPT_CONFIG_FN}') + + try: cfg_u = load_config_file(os.path.join(USHdir, EXPT_CONFIG_FN)) - cfg_u = flatten_dict(cfg_u) - import_vars(dictionary=cfg_u, - env_vars=["MACHINE", - "EXTRN_MDL_NAME_ICS", "EXTRN_MDL_NAME_LBCS", - "FV3GFS_FILE_FMT_ICS", "FV3GFS_FILE_FMT_LBCS"]) - else: - print_err_msg_exit( - f''' - User config file not found - EXPT_CONFIG_FN = \"{EXPT_CONFIG_FN}\"''' - ) + except: + errmsg = dedent(f'''\n + Could not load YAML config file: {EXPT_CONFIG_FN} + Reference the above traceback for more information. + ''') + raise Exception(errmsg) + + cfg_u = flatten_dict(cfg_u) + for key in cfg_u: + if key not in flatten_dict(cfg_d): + raise Exception(dedent(f''' + User-specified variable "{key}" in {EXPT_CONFIG_FN} is not valid. + Check {EXPT_DEFAULT_CONFIG_FN} for allowed user-specified variables.\n''')) + + # Mandatory variables *must* be set in the user's config; the default value is invalid + mandatory = ['MACHINE'] + for val in mandatory: + if val not in cfg_u: + raise Exception(f'Mandatory variable "{val}" not found in user config file {EXPT_CONFIG_FN}') + + import_vars(dictionary=cfg_u, env_vars=["MACHINE", + "EXTRN_MDL_NAME_ICS", "EXTRN_MDL_NAME_LBCS", + "FV3GFS_FILE_FMT_ICS", "FV3GFS_FILE_FMT_LBCS"]) # # ----------------------------------------------------------------------- # @@ -117,6 +130,12 @@ def setup(): # global MACHINE, EXTRN_MDL_SYSBASEDIR_ICS, EXTRN_MDL_SYSBASEDIR_LBCS MACHINE_FILE = os.path.join(USHdir, "machine", f"{lowercase(MACHINE)}.yaml") + if not os.path.exists(MACHINE_FILE): + raise FileNotFoundError(dedent( + f""" + The machine file {MACHINE_FILE} does not exist. + Check that you have specified the correct machine ({MACHINE}) in your config file {EXPT_CONFIG_FN}""" + )) machine_cfg = load_config_file(MACHINE_FILE) # ics and lbcs @@ -161,27 +180,21 @@ def get_location(xcs,fmt): # make machine name uppercase MACHINE = uppercase(MACHINE) - # - # ----------------------------------------------------------------------- - # - # Source constants.sh and save its contents to a variable for later - # - # ----------------------------------------------------------------------- - # + # Load constants file and save its contents to a variable for later cfg_c = load_config_file(os.path.join(USHdir, CONSTANTS_FN)) import_vars(dictionary=flatten_dict(cfg_c)) # # ----------------------------------------------------------------------- # - # Generate a unique number for this workflow run. This maybe used to + # Generate a unique number for this workflow run. This may be used to # get unique log file names for example # # ----------------------------------------------------------------------- # global WORKFLOW_ID WORKFLOW_ID = "id_" + str(int(datetime.datetime.now().timestamp())) - print_info_msg(f"""WORKFLOW ID = {WORKFLOW_ID}""") + log_info(f"""WORKFLOW ID = {WORKFLOW_ID}""") # # ----------------------------------------------------------------------- @@ -208,7 +221,7 @@ def get_location(xcs,fmt): # global VERBOSE if DEBUG and not VERBOSE: - print_info_msg( + log_info( """ Resetting VERBOSE to \"TRUE\" because DEBUG has been set to \"TRUE\"...""" ) @@ -289,12 +302,20 @@ def get_location(xcs,fmt): or (len(SPP_STDDEV_CUTOFF) != N_VAR_SPP) or (len(ISEED_SPP) != N_VAR_SPP) ): - print_err_msg_exit( + raise Exception( f''' All MYNN PBL, MYNN SFC, GSL GWD, Thompson MP, or RRTMG SPP-related namelist - variables set in {CONFIG_FN} must be equal in number of entries to what is + variables set in {EXPT_CONFIG_FN} must be equal in number of entries to what is found in SPP_VAR_LIST: - Number of entries in SPP_VAR_LIST = \"{len(SPP_VAR_LIST)}\"''' + SPP_VAR_LIST (length {len(SPP_VAR_LIST)}) + SPP_MAG_LIST (length {len(SPP_MAG_LIST)}) + SPP_LSCALE (length {len(SPP_LSCALE)}) + SPP_TSCALE (length {len(SPP_TSCALE)}) + SPP_SIGTOP1 (length {len(SPP_SIGTOP1)}) + SPP_SIGTOP2 (length {len(SPP_SIGTOP2)}) + SPP_STDDEV_CUTOFF (length {len(SPP_STDDEV_CUTOFF)}) + ISEED_SPP (length {len(ISEED_SPP)}) + ''' ) # # ----------------------------------------------------------------------- @@ -311,12 +332,16 @@ def get_location(xcs,fmt): or (len(LSM_SPP_LSCALE) != N_VAR_LNDP) or (len(LSM_SPP_TSCALE) != N_VAR_LNDP) ): - print_err_msg_exit( + raise Exception( f''' All Noah or RUC-LSM SPP-related namelist variables (except ISEED_LSM_SPP) - set in {CONFIG_FN} must be equal in number of entries to what is found in + set in {EXPT_CONFIG_FN} must be equal in number of entries to what is found in SPP_VAR_LIST: - Number of entries in SPP_VAR_LIST = \"{len(LSM_SPP_VAR_LIST)}\"''' + LSM_SPP_VAR_LIST (length {len(LSM_SPP_VAR_LIST)}) + LSM_SPP_MAG_LIST (length {len(LSM_SPP_MAG_LIST)}) + LSM_SPP_LSCALE (length {len(LSM_SPP_LSCALE)}) + LSM_SPP_TSCALE (length {len(LSM_SPP_TSCALE)}) + ''' ) # # The current script should be located in the ush subdirectory of the @@ -345,37 +370,39 @@ def get_location(xcs,fmt): mng_extrns_cfg_fn = os.readlink(mng_extrns_cfg_fn) except: pass - property_name = "local_path" cfg = load_ini_config(mng_extrns_cfg_fn) + # # Get the base directory of the FV3 forecast model code. # external_name = FCST_MODEL - UFS_WTHR_MDL_DIR = get_ini_value(cfg, external_name, property_name) + property_name = "local_path" - if not UFS_WTHR_MDL_DIR: - print_err_msg_exit( - f""" - Externals.cfg does not contain "{external_name}".""" - ) + try: + UFS_WTHR_MDL_DIR = get_ini_value(cfg, external_name, property_name) + except KeyError: + errmsg = dedent(f''' + Externals configuration file {mng_extrns_cfg_fn} + does not contain "{external_name}".''') + raise Exception(errmsg) from None + UFS_WTHR_MDL_DIR = os.path.join(HOMEdir, UFS_WTHR_MDL_DIR) if not os.path.exists(UFS_WTHR_MDL_DIR): - print_err_msg_exit( + raise FileNotFoundError(dedent( f""" The base directory in which the FV3 source code should be located (UFS_WTHR_MDL_DIR) does not exist: UFS_WTHR_MDL_DIR = \"{UFS_WTHR_MDL_DIR}\" Please clone the external repository containing the code in this directory, build the executable, and then rerun the workflow.""" - ) + )) # # Define some other useful paths # global SCRIPTSdir, JOBSdir, SORCdir, PARMdir, MODULESdir global EXECdir, PARMdir, FIXdir, VX_CONFIG_DIR, METPLUS_CONF, MET_CONFIG - USHdir = os.path.join(HOMEdir, "ush") SCRIPTSdir = os.path.join(HOMEdir, "scripts") JOBSdir = os.path.join(HOMEdir, "jobs") SORCdir = os.path.join(HOMEdir, "sorc") @@ -400,26 +427,18 @@ def get_location(xcs,fmt): RELATIVE_LINK_FLAG = "--relative" - if not NCORES_PER_NODE: - print_err_msg_exit( - f""" - NCORES_PER_NODE has not been specified in the file {MACHINE_FILE} - Please ensure this value has been set for your desired platform. """ - ) - - if not (FIXgsm and FIXaer and FIXlut and TOPO_DIR and SFC_CLIMO_INPUT_DIR): - print_err_msg_exit( - f""" - One or more fix file directories have not been specified for this machine: - MACHINE = \"{MACHINE}\" - FIXgsm = \"{FIXgsm or ""} - FIXaer = \"{FIXaer or ""} - FIXlut = \"{FIXlut or ""} - TOPO_DIR = \"{TOPO_DIR or ""} - SFC_CLIMO_INPUT_DIR = \"{SFC_CLIMO_INPUT_DIR or ""} - DOMAIN_PREGEN_BASEDIR = \"{DOMAIN_PREGEN_BASEDIR or ""} - You can specify the missing location(s) in config.sh""" - ) + # Mandatory variables *must* be set in the user's config or the machine file; the default value is invalid + mandatory = ['NCORES_PER_NODE', 'FIXgsm', 'FIXaer', 'FIXlut', 'TOPO_DIR', 'SFC_CLIMO_INPUT_DIR'] + globalvars = globals() + for val in mandatory: + # globals() returns dictionary of global variables + if not globalvars[val]: + raise Exception(dedent(f''' + Mandatory variable "{val}" not found in: + user config file {EXPT_CONFIG_FN} + OR + machine file {MACHINE_FILE} + ''')) # # ----------------------------------------------------------------------- @@ -459,12 +478,10 @@ def get_location(xcs,fmt): # if WORKFLOW_MANAGER is not None: if not ACCOUNT: - print_err_msg_exit( - f''' - The variable ACCOUNT cannot be empty if you are using a workflow manager: - ACCOUNT = \"ACCOUNT\" - WORKFLOW_MANAGER = \"WORKFLOW_MANAGER\"''' - ) + raise Exception(dedent(f''' + ACCOUNT must be specified in config or machine file if using a workflow manager. + WORKFLOW_MANAGER = {WORKFLOW_MANAGER}\n''' + )) # # ----------------------------------------------------------------------- # @@ -481,12 +498,7 @@ def get_location(xcs,fmt): GTYPE = "regional" TILE_RGNL = "7" - # ----------------------------------------------------------------------- - # - # Set USE_MERRA_CLIMO to either "TRUE" or "FALSE" so we don't - # have to consider other valid values later on. - # - # ----------------------------------------------------------------------- + # USE_MERRA_CLIMO must be True for the physics suite FV3_GFS_v15_thompson_mynn_lam3km" global USE_MERRA_CLIMO if CCPP_PHYS_SUITE == "FV3_GFS_v15_thompson_mynn_lam3km": USE_MERRA_CLIMO = True @@ -503,123 +515,64 @@ def get_location(xcs,fmt): elif FCST_MODEL == "fv3gfs_aqm": CPL = True else: - print_err_msg_exit( + raise Exception( f''' The coupling flag CPL has not been specified for this value of FCST_MODEL: FCST_MODEL = \"{FCST_MODEL}\"''' ) - # - # ----------------------------------------------------------------------- - # - # Make sure RESTART_INTERVAL is set to an integer value if present - # - # ----------------------------------------------------------------------- - # + + # Make sure RESTART_INTERVAL is set to an integer value if not isinstance(RESTART_INTERVAL, int): - print_err_msg_exit( - f''' - RESTART_INTERVAL must be set to an integer number of hours. - RESTART_INTERVAL = \"{RESTART_INTERVAL}\"''' - ) - # - # ----------------------------------------------------------------------- - # - # Check that DATE_FIRST_CYCL and DATE_LAST_CYCL are strings consisting - # of exactly 10 digits. - # - # ----------------------------------------------------------------------- - # - if not isinstance(DATE_FIRST_CYCL, datetime.date): - print_err_msg_exit( - f''' - DATE_FIRST_CYCL must be a string consisting of exactly 10 digits of the - form \"YYYYMMDDHH\", where YYYY is the 4-digit year, MM is the 2-digit - month, DD is the 2-digit day-of-month, and HH is the 2-digit - cycle hour. - DATE_FIRST_CYCL = \"{DATE_FIRST_CYCL}\"''' - ) + raise Exception(f"\nRESTART_INTERVAL = {RESTART_INTERVAL}, must be an integer value\n") - if not isinstance(DATE_LAST_CYCL, datetime.date): - print_err_msg_exit( - f''' - DATE_LAST_CYCL must be a string consisting of exactly 10 digits of the - form \"YYYYMMDDHH\", where YYYY is the 4-digit year, MM is the 2-digit - month, DD is the 2-digit day-of-month, and HH is the 2-digit - cycle hour. - DATE_LAST_CYCL = \"{DATE_LAST_CYCL}\"''' - ) - # - # ----------------------------------------------------------------------- - # - # Call a function to generate the array ALL_CDATES containing the cycle - # dates/hours for which to run forecasts. The elements of this array - # will have the form YYYYMMDDHH. They are the starting dates/times of - # the forecasts that will be run in the experiment. Then set NUM_CYCLES - # to the number of elements in this array. - # - # ----------------------------------------------------------------------- - # + # Check that input dates are in a date format - ALL_CDATES = set_cycle_dates( - date_start=DATE_FIRST_CYCL, - date_end=DATE_LAST_CYCL, - incr_cycl_freq=INCR_CYCL_FREQ, - ) + # get dictionary of all variables + allvars = dict(globals()) + allvars.update(locals()) + dates = ['DATE_FIRST_CYCL', 'DATE_LAST_CYCL'] + for val in dates: + if not isinstance(allvars[val], datetime.date): + raise Exception(dedent(f''' + Date variable {val}={allvars[val]} is not in a valid date format - NUM_CYCLES = len(ALL_CDATES) + For examples of valid formats, see the users guide. + ''')) - # Completely arbitrary cutoff of 90 cycles. - if NUM_CYCLES > 90: - ALL_CDATES = None - print_info_msg( - f""" - Too many cycles in ALL_CDATES to list, redefining in abbreviated form." - ALL_CDATES="{DATE_FIRST_CYCL}...{DATE_LAST_CYCL}""" - ) - # - # ----------------------------------------------------------------------- - # # If using a custom post configuration file, make sure that it exists. - # - # ----------------------------------------------------------------------- - # if USE_CUSTOM_POST_CONFIG_FILE: - if not os.path.exists(CUSTOM_POST_CONFIG_FP): - print_err_msg_exit( + try: + #os.path.exists returns exception if passed an empty string or None, so use "try/except" as a 2-for-1 error catch + if not os.path.exists(CUSTOM_POST_CONFIG_FP): + raise + except: + raise FileNotFoundError(dedent( f''' - The custom post configuration specified by CUSTOM_POST_CONFIG_FP does not - exist: - CUSTOM_POST_CONFIG_FP = \"{CUSTOM_POST_CONFIG_FP}\"''' - ) - # - # ----------------------------------------------------------------------- - # + USE_CUSTOM_POST_CONFIG_FILE has been set, but the custom post configuration file + CUSTOM_POST_CONFIG_FP = {CUSTOM_POST_CONFIG_FP} + could not be found.''' + )) from None + # If using external CRTM fix files to allow post-processing of synthetic - # satellite products from the UPP, then make sure the fix file directory - # exists. - # - # ----------------------------------------------------------------------- - # + # satellite products from the UPP, make sure the CRTM fix file directory exists. if USE_CRTM: - if not os.path.exists(CRTM_DIR): - print_err_msg_exit( + try: + #os.path.exists returns exception if passed an empty string or None, so use "try/except" as a 2-for-1 error catch + if not os.path.exists(CRTM_DIR): + raise + except: + raise FileNotFoundError(dedent( f''' - The external CRTM fix file directory specified by CRTM_DIR does not exist: - CRTM_DIR = \"{CRTM_DIR}\"''' - ) - # - # ----------------------------------------------------------------------- - # - # The forecast length (in integer hours) cannot contain more than 3 cha- - # racters. Thus, its maximum value is 999. Check whether the specified - # forecast length exceeds this maximum value. If so, print out a warn- - # ing and exit this script. - # - # ----------------------------------------------------------------------- - # + USE_CRTM has been set, but the external CRTM fix file directory: + CRTM_DIR = {CRTM_DIR} + could not be found.''' + )) from None + + # The forecast length (in integer hours) cannot contain more than 3 characters. + # Thus, its maximum value is 999. fcst_len_hrs_max = 999 if FCST_LEN_HRS > fcst_len_hrs_max: - print_err_msg_exit( + raise ValueError( f""" Forecast length is greater than maximum allowed length: FCST_LEN_HRS = {FCST_LEN_HRS} @@ -629,16 +582,15 @@ def get_location(xcs,fmt): # ----------------------------------------------------------------------- # # Check whether the forecast length (FCST_LEN_HRS) is evenly divisible - # by the BC update interval (LBC_SPEC_INTVL_HRS). If not, print out a - # warning and exit this script. If so, generate an array of forecast - # hours at which the boundary values will be updated. + # by the BC update interval (LBC_SPEC_INTVL_HRS). If so, generate an + # array of forecast hours at which the boundary values will be updated. # # ----------------------------------------------------------------------- # rem = FCST_LEN_HRS % LBC_SPEC_INTVL_HRS if rem != 0: - print_err_msg_exit( + raise Exception( f""" The forecast length (FCST_LEN_HRS) is not evenly divisible by the lateral boundary conditions update interval (LBC_SPEC_INTVL_HRS): @@ -672,48 +624,18 @@ def get_location(xcs,fmt): # # ----------------------------------------------------------------------- # - if not DT_ATMOS: - print_err_msg_exit( - f''' - The forecast model main time step (DT_ATMOS) is set to a null string: - DT_ATMOS = {DT_ATMOS} - Please set this to a valid numerical value in the user-specified experiment - configuration file (EXPT_CONFIG_FP) and rerun: - EXPT_CONFIG_FP = \"{EXPT_CONFIG_FP}\"''' - ) - - if not LAYOUT_X: - print_err_msg_exit( - f''' - The number of MPI processes to be used in the x direction (LAYOUT_X) by - the forecast job is set to a null string: - LAYOUT_X = {LAYOUT_X} - Please set this to a valid numerical value in the user-specified experiment - configuration file (EXPT_CONFIG_FP) and rerun: - EXPT_CONFIG_FP = \"{EXPT_CONFIG_FP}\"''' - ) + # get dictionary of all variables + allvars = dict(globals()) + allvars.update(locals()) + vlist = ['DT_ATMOS', + 'LAYOUT_X', + 'LAYOUT_Y', + 'BLOCKSIZE', + 'EXPT_SUBDIR'] + for val in vlist: + if not allvars[val]: + raise Exception(f"\nMandatory variable '{val}' has not been set\n") - if not LAYOUT_Y: - print_err_msg_exit( - f''' - The number of MPI processes to be used in the y direction (LAYOUT_Y) by - the forecast job is set to a null string: - LAYOUT_Y = {LAYOUT_Y} - Please set this to a valid numerical value in the user-specified experiment - configuration file (EXPT_CONFIG_FP) and rerun: - EXPT_CONFIG_FP = \"{EXPT_CONFIG_FP}\"''' - ) - - if not BLOCKSIZE: - print_err_msg_exit( - f''' - The cache size to use for each MPI task of the forecast (BLOCKSIZE) is - set to a null string: - BLOCKSIZE = {BLOCKSIZE} - Please set this to a valid numerical value in the user-specified experiment - configuration file (EXPT_CONFIG_FP) and rerun: - EXPT_CONFIG_FP = \"{EXPT_CONFIG_FP}\"''' - ) # # ----------------------------------------------------------------------- # @@ -730,7 +652,7 @@ def get_location(xcs,fmt): # Check that DT_SUBHOURLY_POST_MNTS is between 0 and 59, inclusive. # if DT_SUBHOURLY_POST_MNTS < 0 or DT_SUBHOURLY_POST_MNTS > 59: - print_err_msg_exit( + raise ValueError( f''' When performing sub-hourly post (i.e. SUB_HOURLY_POST set to \"TRUE\"), DT_SUBHOURLY_POST_MNTS must be set to an integer between 0 and 59, @@ -744,7 +666,7 @@ def get_location(xcs,fmt): # rem = DT_SUBHOURLY_POST_MNTS * 60 % DT_ATMOS if rem != 0: - print_err_msg_exit( + raise ValueError( f""" When performing sub-hourly post (i.e. SUB_HOURLY_POST set to \"TRUE\"), the time interval specified by DT_SUBHOURLY_POST_MNTS (after converting @@ -765,7 +687,7 @@ def get_location(xcs,fmt): # informational message that such a change was made. # if DT_SUBHOURLY_POST_MNTS == 0: - print_info_msg( + logger.warning( f""" When performing sub-hourly post (i.e. SUB_HOURLY_POST set to \"TRUE\"), DT_SUBHOURLY_POST_MNTS must be set to a value greater than 0; otherwise, @@ -804,20 +726,7 @@ def get_location(xcs,fmt): EXPT_BASEDIR = os.path.abspath(EXPT_BASEDIR) mkdir_vrfy(f' -p "{EXPT_BASEDIR}"') - # - # ----------------------------------------------------------------------- - # - # If the experiment subdirectory name (EXPT_SUBDIR) is set to an empty - # string, print out an error message and exit. - # - # ----------------------------------------------------------------------- - # - if not EXPT_SUBDIR: - print_err_msg_exit( - f''' - The name of the experiment subdirectory (EXPT_SUBDIR) cannot be empty: - EXPT_SUBDIR = \"{EXPT_SUBDIR}\"''' - ) + # # ----------------------------------------------------------------------- # @@ -828,7 +737,25 @@ def get_location(xcs,fmt): # global EXPTDIR EXPTDIR = os.path.join(EXPT_BASEDIR, EXPT_SUBDIR) - check_for_preexist_dir_file(EXPTDIR, PREEXISTING_DIR_METHOD) + try: + check_for_preexist_dir_file(EXPTDIR, PREEXISTING_DIR_METHOD) + except ValueError: + logger.exception(f''' + Check that the following values are valid: + EXPTDIR {EXPTDIR} + PREEXISTING_DIR_METHOD {PREEXISTING_DIR_METHOD} + ''') + raise + except FileExistsError: + errmsg = dedent(f''' + EXPTDIR ({EXPTDIR}) already exists, and PREEXISTING_DIR_METHOD = {PREEXISTING_DIR_METHOD} + + To ignore this error, delete the directory, or set + PREEXISTING_DIR_METHOD = delete, or + PREEXISTING_DIR_METHOD = rename + in your config file. + ''') + raise FileExistsError(errmsg) from None # # ----------------------------------------------------------------------- # @@ -945,7 +872,7 @@ def get_location(xcs,fmt): if POST_OUTPUT_DOMAIN_NAME is None: if PREDEF_GRID_NAME is None: - print_err_msg_exit( + raise Exception( f""" The domain name used in naming the run_post output files (POST_OUTPUT_DOMAIN_NAME) has not been set: @@ -966,9 +893,6 @@ def get_location(xcs,fmt): # (4) The FV3 namelist file # (5) The model configuration file # (6) The NEMS configuration file - # - # If using CCPP, it also needs: - # # (7) The CCPP physics suite definition file # # The workflow contains templates for the first six of these files. @@ -1056,7 +980,7 @@ def get_location(xcs,fmt): ) CCPP_PHYS_SUITE_FP = os.path.join(EXPTDIR, CCPP_PHYS_SUITE_FN) if not os.path.exists(CCPP_PHYS_SUITE_IN_CCPP_FP): - print_err_msg_exit( + raise FileNotFoundError( f''' The CCPP suite definition file (CCPP_PHYS_SUITE_IN_CCPP_FP) does not exist in the local clone of the ufs-weather-model: @@ -1083,7 +1007,7 @@ def get_location(xcs,fmt): ) FIELD_DICT_FP = os.path.join(EXPTDIR, FIELD_DICT_FN) if not os.path.exists(FIELD_DICT_IN_UWM_FP): - print_err_msg_exit( + raise FileNotFoundError( f''' The field dictionary file (FIELD_DICT_IN_UWM_FP) does not exist in the local clone of the ufs-weather-model: @@ -1101,7 +1025,7 @@ def get_location(xcs,fmt): # export env vars before calling another module export_vars() - OZONE_PARAM = set_ozone_param(ccpp_phys_suite_fp=CCPP_PHYS_SUITE_IN_CCPP_FP) + OZONE_PARAM = set_ozone_param(CCPP_PHYS_SUITE_IN_CCPP_FP) IMPORTS = ["CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING", "FIXgsm_FILES_TO_COPY_TO_FIXam"] import_vars(env_vars=IMPORTS) @@ -1159,7 +1083,7 @@ def get_location(xcs,fmt): idx = len(EXTRN_MDL_SOURCE_BASEDIR_ICS) if not os.path.exists(EXTRN_MDL_SOURCE_BASEDIR_ICS[:idx]): - print_err_msg_exit( + raise FileNotFoundError( f''' The directory (EXTRN_MDL_SOURCE_BASEDIR_ICS) in which the user-staged external model files for generating ICs should be located does not exist: @@ -1171,7 +1095,7 @@ def get_location(xcs,fmt): idx = len(EXTRN_MDL_SOURCE_BASEDIR_LBCS) if not os.path.exists(EXTRN_MDL_SOURCE_BASEDIR_LBCS[:idx]): - print_err_msg_exit( + raise FileNotFoundError( f''' The directory (EXTRN_MDL_SOURCE_BASEDIR_LBCS) in which the user-staged external model files for generating LBCs should be located does not exist: @@ -1180,10 +1104,9 @@ def get_location(xcs,fmt): # # ----------------------------------------------------------------------- # - # Make sure that DO_ENSEMBLE is set to a valid value. Then set the names - # of the ensemble members. These will be used to set the ensemble member - # directories. Also, set the full path to the FV3 namelist file corresponding - # to each ensemble member. + # If DO_ENSEMBLE, set the names of the ensemble members; these will be + # used to set the ensemble member directories. Also, set the full path + # to the FV3 namelist file corresponding to each ensemble member. # # ----------------------------------------------------------------------- # @@ -1199,13 +1122,8 @@ def get_location(xcs,fmt): FV3_NML_ENSMEM_FPS.append( os.path.join(EXPTDIR, f"{FV3_NML_FN}_{ENSMEM_NAMES[i]}") ) - # - # ----------------------------------------------------------------------- - # + # Set the full path to the forecast model executable. - # - # ----------------------------------------------------------------------- - # global FV3_EXEC_FP FV3_EXEC_FP = os.path.join(EXECdir, FV3_EXEC_FN) # @@ -1240,13 +1158,6 @@ def get_location(xcs,fmt): global LOAD_MODULES_RUN_TASK_FP LOAD_MODULES_RUN_TASK_FP = os.path.join(USHdir, "load_modules_run_task.sh") - # - # ----------------------------------------------------------------------- - # - # Turn off some tasks that can not be run in NCO mode - # - # ----------------------------------------------------------------------- - # global RUN_TASK_MAKE_GRID, RUN_TASK_MAKE_OROG, RUN_TASK_MAKE_SFC_CLIMO global RUN_TASK_VX_GRIDSTAT, RUN_TASK_VX_POINTSTAT, RUN_TASK_VX_ENSGRID, RUN_TASK_VX_ENSPOINT @@ -1260,15 +1171,9 @@ def get_location(xcs,fmt): FIXclim = os.path.join(FIXdir, "fix_clim") FIXlam = os.path.join(FIXdir, "fix_lam") - # - # ----------------------------------------------------------------------- - # - # Make sure that DO_ENSEMBLE is set to TRUE when running ensemble vx. - # - # ----------------------------------------------------------------------- - # + # Ensemble verification can only be run in ensemble mode if (not DO_ENSEMBLE) and (RUN_TASK_VX_ENSGRID or RUN_TASK_VX_ENSPOINT): - print_err_msg_exit( + raise Exception( f''' Ensemble verification can not be run unless running in ensemble mode: DO_ENSEMBLE = \"{DO_ENSEMBLE}\" @@ -1314,21 +1219,22 @@ def get_location(xcs,fmt): # experiment directory (EXPTDIR). # if not RUN_TASK_MAKE_GRID: - if (GRID_DIR is None) or (not os.path.exists(GRID_DIR)): + if (GRID_DIR is None): GRID_DIR = os.path.join(DOMAIN_PREGEN_BASEDIR, PREDEF_GRID_NAME) - msg = f"""Setting GRID_DIR to: - GRID_DIR = \"{GRID_DIR}\" - """ - print_info_msg(msg) - - if not os.path.exists(GRID_DIR): - print_err_msg_exit( - f''' - The directory (GRID_DIR) that should contain the pregenerated grid files - does not exist: - GRID_DIR = \"{GRID_DIR}\"''' - ) + msg = dedent(f""" + GRID_DIR not specified! + Setting GRID_DIR = {GRID_DIR} + """) + logger.warning(msg) + + if not os.path.exists(GRID_DIR): + raise FileNotFoundError( + f''' + The directory (GRID_DIR) that should contain the pregenerated grid files + does not exist: + GRID_DIR = \"{GRID_DIR}\"''' + ) else: GRID_DIR = os.path.join(EXPTDIR, "grid") # @@ -1338,21 +1244,22 @@ def get_location(xcs,fmt): # the experiment directory (EXPTDIR). # if not RUN_TASK_MAKE_OROG: - if (OROG_DIR is None) or (not os.path.exists(OROG_DIR)): + if (OROG_DIR is None): OROG_DIR = os.path.join(DOMAIN_PREGEN_BASEDIR, PREDEF_GRID_NAME) - msg = f"""Setting OROG_DIR to: - OROG_DIR = \"{OROG_DIR}\" - """ - print_info_msg(msg) - - if not os.path.exists(OROG_DIR): - print_err_msg_exit( - f''' - The directory (OROG_DIR) that should contain the pregenerated orography - files does not exist: - OROG_DIR = \"{OROG_DIR}\"''' - ) + msg = dedent(f""" + OROG_DIR not specified! + Setting OROG_DIR = {OROG_DIR} + """) + logger.warning(msg) + + if not os.path.exists(OROG_DIR): + raise FileNotFoundError( + f''' + The directory (OROG_DIR) that should contain the pregenerated orography + files does not exist: + OROG_DIR = \"{OROG_DIR}\"''' + ) else: OROG_DIR = os.path.join(EXPTDIR, "orog") # @@ -1362,21 +1269,22 @@ def get_location(xcs,fmt): # a predefined location under the experiment directory (EXPTDIR). # if not RUN_TASK_MAKE_SFC_CLIMO: - if (SFC_CLIMO_DIR is None) or (not os.path.exists(SFC_CLIMO_DIR)): + if (SFC_CLIMO_DIR is None): SFC_CLIMO_DIR = os.path.join(DOMAIN_PREGEN_BASEDIR, PREDEF_GRID_NAME) - msg = f"""Setting SFC_CLIMO_DIR to: - SFC_CLIMO_DIR = \"{SFC_CLIMO_DIR}\" - """ - print_info_msg(msg) - - if not os.path.exists(SFC_CLIMO_DIR): - print_err_msg_exit( - f''' - The directory (SFC_CLIMO_DIR) that should contain the pregenerated surface - climatology files does not exist: - SFC_CLIMO_DIR = \"{SFC_CLIMO_DIR}\"''' - ) + msg = dedent(f""" + SFC_CLIMO_DIR not specified! + Setting SFC_CLIMO_DIR ={SFC_CLIMO_DIR} + """) + logger.warning(msg) + + if not os.path.exists(SFC_CLIMO_DIR): + raise FileNotFoundError( + f''' + The directory (SFC_CLIMO_DIR) that should contain the pregenerated surface + climatology files does not exist: + SFC_CLIMO_DIR = \"{SFC_CLIMO_DIR}\"''' + ) else: SFC_CLIMO_DIR = os.path.join(EXPTDIR, "sfc_climo") @@ -1462,10 +1370,9 @@ def get_location(xcs,fmt): # # ----------------------------------------------------------------------- # - # Create a new experiment directory. Note that at this point we are - # guaranteed that there is no preexisting experiment directory. For - # platforms with no workflow manager, we need to create LOGDIR as well, - # since it won't be created later at runtime. + # Create a new experiment directory. For platforms with no workflow + # manager we need to create LOGDIR as well, since it won't be created + # later at runtime. # # ----------------------------------------------------------------------- # @@ -1473,7 +1380,7 @@ def get_location(xcs,fmt): mkdir_vrfy(f' -p "{LOGDIR}"') # # ----------------------------------------------------------------------- - # + # NOTE: currently this is executed no matter what, should it be dependent on the logic described below?? # If not running the MAKE_GRID_TN, MAKE_OROG_TN, and/or MAKE_SFC_CLIMO # tasks, create symlinks under the FIXlam directory to pregenerated grid, # orography, and surface climatology files. In the process, also set @@ -1520,7 +1427,7 @@ def get_location(xcs,fmt): res_in_orog_fns = link_fix(verbose=VERBOSE, file_group="orog") if not RES_IN_FIXLAM_FILENAMES and (res_in_orog_fns != RES_IN_FIXLAM_FILENAMES): - print_err_msg_exit( + raise Exception( f""" The resolution extracted from the orography file names (res_in_orog_fns) does not match the resolution in other groups of files already consi- @@ -1546,7 +1453,7 @@ def get_location(xcs,fmt): res_in_sfc_climo_fns = link_fix(verbose=VERBOSE, file_group="sfc_climo") if RES_IN_FIXLAM_FILENAMES and res_in_sfc_climo_fns != RES_IN_FIXLAM_FILENAMES: - print_err_msg_exit( + raise Exception( f""" The resolution extracted from the surface climatology file names (res_- in_sfc_climo_fns) does not match the resolution in other groups of files @@ -1569,21 +1476,20 @@ def get_location(xcs,fmt): CRES = "" if not RUN_TASK_MAKE_GRID: CRES = f"C{RES_IN_FIXLAM_FILENAMES}" - # - # ----------------------------------------------------------------------- - # - # Make sure that WRITE_DOPOST is set to a valid value. - # - # ----------------------------------------------------------------------- - # + global RUN_TASK_RUN_POST if WRITE_DOPOST: # Turn off run_post - RUN_TASK_RUN_POST = False + if RUN_TASK_RUN_POST: + logger.warning(dedent(f""" + Inline post is turned on, deactivating post-processing tasks: + RUN_TASK_RUN_POST = False + """)) + RUN_TASK_RUN_POST = False # Check if SUB_HOURLY_POST is on if SUB_HOURLY_POST: - print_err_msg_exit( + raise Exception( f""" SUB_HOURLY_POST is NOT available with Inline Post yet.""" ) @@ -1601,7 +1507,8 @@ def get_location(xcs,fmt): if QUILTING: PE_MEMBER01 = PE_MEMBER01 + WRTCMP_write_groups * WRTCMP_write_tasks_per_group - print_info_msg( + if VERBOSE: + log_info( f""" The number of MPI tasks for the forecast (including those for the write component if it is being used) are: @@ -1857,72 +1764,50 @@ def get_location(xcs,fmt): # the make_grid task is complete. # "CRES": CRES, + # + # ----------------------------------------------------------------------- + # + # Flag in the \"{MODEL_CONFIG_FN}\" file for coupling the ocean model to + # the weather model. + # + # ----------------------------------------------------------------------- + # + "CPL": CPL, + # + # ----------------------------------------------------------------------- + # + # Name of the ozone parameterization. The value this gets set to depends + # on the CCPP physics suite being used. + # + # ----------------------------------------------------------------------- + # + "OZONE_PARAM": OZONE_PARAM, + # + # ----------------------------------------------------------------------- + # + # Computational parameters. + # + # ----------------------------------------------------------------------- + # + "PE_MEMBER01": PE_MEMBER01, + # + # ----------------------------------------------------------------------- + # + # IF DO_SPP is set to "TRUE", N_VAR_SPP specifies the number of physics + # parameterizations that are perturbed with SPP. If DO_LSM_SPP is set to + # "TRUE", N_VAR_LNDP specifies the number of LSM parameters that are + # perturbed. LNDP_TYPE determines the way LSM perturbations are employed + # and FHCYC_LSM_SPP_OR_NOT sets FHCYC based on whether LSM perturbations + # are turned on or not. + # + # ----------------------------------------------------------------------- + # + "N_VAR_SPP": N_VAR_SPP, + "N_VAR_LNDP": N_VAR_LNDP, + "LNDP_TYPE": LNDP_TYPE, + "LNDP_MODEL_TYPE": LNDP_MODEL_TYPE, + "FHCYC_LSM_SPP_OR_NOT": FHCYC_LSM_SPP_OR_NOT, } - # - # ----------------------------------------------------------------------- - # - # Continue appending variable definitions to the variable definitions - # file. - # - # ----------------------------------------------------------------------- - # - settings.update( - { - # - # ----------------------------------------------------------------------- - # - # Flag in the \"{MODEL_CONFIG_FN}\" file for coupling the ocean model to - # the weather model. - # - # ----------------------------------------------------------------------- - # - "CPL": CPL, - # - # ----------------------------------------------------------------------- - # - # Name of the ozone parameterization. The value this gets set to depends - # on the CCPP physics suite being used. - # - # ----------------------------------------------------------------------- - # - "OZONE_PARAM": OZONE_PARAM, - # - # ----------------------------------------------------------------------- - # - # The number of cycles for which to make forecasts and the list of - # starting dates/hours of these cycles. - # - # ----------------------------------------------------------------------- - # - "NUM_CYCLES": NUM_CYCLES, - "ALL_CDATES": ALL_CDATES, - # - # ----------------------------------------------------------------------- - # - # Computational parameters. - # - # ----------------------------------------------------------------------- - # - "PE_MEMBER01": PE_MEMBER01, - # - # ----------------------------------------------------------------------- - # - # IF DO_SPP is set to "TRUE", N_VAR_SPP specifies the number of physics - # parameterizations that are perturbed with SPP. If DO_LSM_SPP is set to - # "TRUE", N_VAR_LNDP specifies the number of LSM parameters that are - # perturbed. LNDP_TYPE determines the way LSM perturbations are employed - # and FHCYC_LSM_SPP_OR_NOT sets FHCYC based on whether LSM perturbations - # are turned on or not. - # - # ----------------------------------------------------------------------- - # - "N_VAR_SPP": N_VAR_SPP, - "N_VAR_LNDP": N_VAR_LNDP, - "LNDP_TYPE": LNDP_TYPE, - "LNDP_MODEL_TYPE": LNDP_MODEL_TYPE, - "FHCYC_LSM_SPP_OR_NOT": FHCYC_LSM_SPP_OR_NOT, - } - ) # write derived settings cfg_d["derived"] = settings @@ -1964,10 +1849,10 @@ def get_location(xcs,fmt): # print content of var_defns if DEBUG=True all_lines = cfg_to_yaml_str(cfg_d) - print_info_msg(all_lines, verbose=DEBUG) + log_info(all_lines, verbose=DEBUG) # print info message - print_info_msg( + log_info( f""" Generating the global experiment variable definitions file specified by GLOBAL_VAR_DEFNS_FN: @@ -2000,27 +1885,13 @@ def get_location(xcs,fmt): continue vkey = "valid_vals_" + k if (vkey in cfg_v) and not (v in cfg_v[vkey]): - print_err_msg_exit( + raise Exception( f""" - The variable {k}={v} in {EXPT_DEFAULT_CONFIG_FN} or {EXPT_CONFIG_FN} does not have - a valid value. Possible values are: + The variable {k}={v} in {EXPT_DEFAULT_CONFIG_FN} or {EXPT_CONFIG_FN} + does not have a valid value. Possible values are: {k} = {cfg_v[vkey]}""" ) - # - # ----------------------------------------------------------------------- - # - # Print message indicating successful completion of script. - # - # ----------------------------------------------------------------------- - # - print_info_msg( - f""" - ======================================================================== - Function setup() in \"{os.path.basename(__file__)}\" completed successfully!!! - ========================================================================""" - ) - # # ----------------------------------------------------------------------- From 9cd91d3a1165941f87c96b2aff9ae55f790aa733 Mon Sep 17 00:00:00 2001 From: Michael Kavulich Date: Mon, 24 Oct 2022 13:12:32 -0700 Subject: [PATCH 03/45] Update wflow_cheyenne.lua (#424) Restore correct `conda activate` message for Cheyenne --- modulefiles/wflow_cheyenne.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modulefiles/wflow_cheyenne.lua b/modulefiles/wflow_cheyenne.lua index 7a7473b639..aa44485679 100644 --- a/modulefiles/wflow_cheyenne.lua +++ b/modulefiles/wflow_cheyenne.lua @@ -14,7 +14,7 @@ load(pathJoin("conda", os.getenv("conda_ver") or "latest")) if mode() == "load" then LmodMsgRaw([===[Please do the following to activate conda: - > conda activate regional_workflow + > conda activate /glade/p/ral/jntp/UFS_SRW_app/conda/regional_workflow ]===]) end From 0ce31b453928665a1596c5eabdea0a72a329bdba Mon Sep 17 00:00:00 2001 From: Michael Kavulich Date: Wed, 26 Oct 2022 09:42:29 -0700 Subject: [PATCH 04/45] Post merge cleanup: remove old script, consolidate test directories (#430) * Remove old, deprecated "update_fork.pl" script * Move contents of test/ to tests/ to consolidate testing directories * Update tests/README.md for new path * Fixed one more new script location * Changes for CI tests from Daniel --- .cicd/scripts/srw_build.sh | 2 +- {test => tests}/README.md | 4 +- tests/WE2E/setup_WE2E_tests.sh | 2 +- {test => tests}/build.sh | 0 update_fork.pl | 77 ---------------------------------- 5 files changed, 4 insertions(+), 81 deletions(-) rename {test => tests}/README.md (94%) rename {test => tests}/build.sh (100%) delete mode 100755 update_fork.pl diff --git a/.cicd/scripts/srw_build.sh b/.cicd/scripts/srw_build.sh index e55c3f2fc5..c8a4943238 100755 --- a/.cicd/scripts/srw_build.sh +++ b/.cicd/scripts/srw_build.sh @@ -25,7 +25,7 @@ else fi # Build and install -cd ${workspace}/test +cd ${workspace}/tests ./build.sh ${platform} ${SRW_COMPILER} cd - diff --git a/test/README.md b/tests/README.md similarity index 94% rename from test/README.md rename to tests/README.md index da1f0fb648..f48c78523e 100644 --- a/test/README.md +++ b/tests/README.md @@ -32,8 +32,8 @@ To run the tests, specify the machine name on the command line, for example: On cheyenne: ``` -cd test +cd tests ./build.sh cheyenne >& build.out & ``` -Check the ``${HOMEdir}/test/build_test$PID.out`` file for PASS/FAIL. +Check the ``${HOMEdir}/tests/build_test$PID.out`` file for PASS/FAIL. diff --git a/tests/WE2E/setup_WE2E_tests.sh b/tests/WE2E/setup_WE2E_tests.sh index 1a154d54cf..cf2b4ec1dc 100755 --- a/tests/WE2E/setup_WE2E_tests.sh +++ b/tests/WE2E/setup_WE2E_tests.sh @@ -9,7 +9,7 @@ # run_WE2E_tests.sh. # # The script is dependent on a successful build of this repo using the -# test/build.sh script in the ufs-srweather-app repository. The UFS +# tests/build.sh script in the ufs-srweather-app repository. The UFS # build must be completed in a particular manner for this script to # function properly, notably the location of the build and install # directories: diff --git a/test/build.sh b/tests/build.sh similarity index 100% rename from test/build.sh rename to tests/build.sh diff --git a/update_fork.pl b/update_fork.pl deleted file mode 100755 index 17cb67dc16..0000000000 --- a/update_fork.pl +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/perl -w - -# Script for easily updating your fork of the main regional_workflow repository -# -# Author: Michael Kavulich, September 2016 -# Updated for regional_workflow repository, July 2019 -# No rights reserved, this script may be used, copied, or modified for any purpose -# -# Instructions: -# 1. Clone your fork of the repository (if you already have a local clone of your fork this is optional) -# git clone https://your_username@github.com/your_username/regional_workflow.git -# 2. Enter the directory of the local clone of your fork -# cd regional_workflow -# 3. Run this script from within the directory structure of your local clone of your fork -# ./update_fork.pl -# You will be asked to enter your Github username: enter it and hit "return". -# 4. If all went well, you should see one of two different messages at the end: -# - If your fork is already up-to-date, you should see "Already up-to-date." -# - If your fork is not up-to-date, this script initiates a fast-forward merge to bring your fork -# up to date with the develop of the main repository (https://github.com/ufs-community/regional_workflow). -# Near the end git will print a line of statistics describing what changed, which will look -# something like this: -# -# 19 files changed, 27 insertions(+), 27 deletions(-) -# -# followed by a few more lines and this final message: -# -# Branch develop set up to track remote branch develop from origin. - -# Notes: -# - This is a preliminary version of what will hopefully be a more detailed script in the future. -# This one only performs fast-forward merges. - -use strict; - -my $username; -my $go_on = ""; - -# First off: check if we are on develop, and quit if we are not. We want the branch switch to be transparent to users -my $curr_branch = `git rev-parse --abbrev-ref HEAD`; -chomp $curr_branch; -die "\nERROR ERROR ERROR:\nYou are currently on the branch $curr_branch\n\nThis script must be run from the develop branch.\n\nCheck out the develop branch, then run this script, then check out your working branch $curr_branch when the update is finished\n\n" unless $curr_branch eq "develop"; - - -# Prompt user for their username -print "Please enter your Github username:\n"; - while ($go_on eq "") { - $go_on = ; - chop($go_on); - if ($go_on eq "") { - print "Please enter your Github username:\n"; - } else { - $username = $go_on; - } - } - -print "Username = $username\n"; -my $main_repo = "https://$username\@github.com/ufs-community/regional_workflow.git"; -my $fork = "https://$username\@github.com/$username/regional_workflow.git"; - -# Set main repository as a remote repository named "upstream", per standard git conventions -print "\nStep 1: Setting main repository as a remote repository named 'upstream'\n\n"; -! system("git", "remote", "rm", "upstream") or warn "If you see \"error: Could not remove config section 'remote.upstream'\" this is normal! Don't panic!\n"; -! system("git", "remote", "add", "upstream", $main_repo) or die "Can not add main repository '$main_repo' for merging: $!\n"; - -# Set the "push" url for "upstream" to be the user's fork, to avoid accidentally pushing to the main repository -print "\nStep 2: Setting the 'push' url for 'upstream' to the user's fork, to avoid accidentally pushing to the main repository\n\n"; -! system("git", "remote", "set-url", "--push", "upstream", $fork) or die "Can not add set push repository '$fork': $!\n"; - -# Checkout develop, fetch "upstream" commits, and perform a fastforward merge -print "\nStep 3: Fetching 'upstream' commits, and performing fastforward merge\n\n"; -! system("git", "fetch", "upstream", "develop") or die "Can not fetch upstream changes from : $!\nSomething has gone seriously wrong! Perhaps you don't have internet access?\n"; -! system("git", "merge", "--ff-only", "upstream/develop") or die "\nCan not perform fastforward merge from upstream/develop: $!\n\nTroubleshooting info:\n\n 1. If you receive a message 'fatal: 'upstream/develop' does not point to a commit', your git version may be too old. On yellowstone, try `module load git`\n 2. If you receive a message' fatal: Not possible to fast-forward, aborting.', you have likely made local changes to the develop branch of your fork. All work should be done on branches of your fork, not the develop!\n"; - -# Finally, push updated develop to the Github copy of your fork: -print "\nStep 4: Pushing updated develop to fork\n\n"; -! system("git", "push", "-u", "origin", "develop") or die "\nCan not push updates to origin/develop : $!\n"; From 666887347d5c5b202c505a347751e3013c9d901a Mon Sep 17 00:00:00 2001 From: danielabdi-noaa <52012304+danielabdi-noaa@users.noreply.github.com> Date: Wed, 26 Oct 2022 17:05:32 -0600 Subject: [PATCH 05/45] Move fixed-file mapping variables out of `config_defaults.yaml`. (#421) * Move fixed-file mapping variables out of config_defaults. Also, move other variables that are unlikely/never changed by user. * Minor bug fix. * Use python script to check python version and packages. * Minor fixes. * Format python files with black. * Add pipefail in strict error checking mode. * Remove debugging comments from UFS_plot * More formatting changes. * Removed unused python utilities. --- parm/fixed_files_mapping.yaml | 208 ++++++ scripts/exregional_run_fcst.sh | 2 +- tests/WE2E/run_WE2E_tests.sh | 51 +- ush/UFS_plot_domains.py | 4 - ush/check_python_version.py | 57 ++ ush/check_ruc_lsm.py | 4 +- ush/config_defaults.yaml | 201 +----- ush/create_diag_table_file.py | 37 +- ush/create_model_configure_file.py | 24 +- ush/generate_FV3LAM_wflow.py | 269 ++++---- ush/get_crontab_contents.py | 30 +- ush/link_fix.py | 6 +- ush/machine/odin.yaml | 2 +- ush/preamble.sh | 2 +- ush/python_utils/__init__.py | 4 - .../check_for_preexist_dir_file.py | 19 +- ush/python_utils/check_var_valid_value.py | 1 + ush/python_utils/config_parser.py | 17 +- ush/python_utils/count_files.py | 16 - ush/python_utils/create_symlink_to_file.py | 16 +- ush/python_utils/filesys_cmds_vrfy.py | 2 +- ush/python_utils/get_charvar_from_netcdf.py | 48 -- ush/python_utils/get_elem_inds.py | 28 - ush/python_utils/interpol_to_arbit_CRES.py | 43 -- ush/python_utils/print_input_args.py | 8 +- ush/python_utils/print_msg.py | 6 +- ush/python_utils/test_python_utils.py | 23 - ush/retrieve_data.py | 3 +- ush/set_FV3nml_ens_stoch_seeds.py | 30 +- ush/set_FV3nml_sfc_climo_filenames.py | 60 +- ush/set_cycle_dates.py | 11 +- ush/set_extrn_mdl_params.py | 49 -- ush/set_gridparams_ESGgrid.py | 12 +- ush/set_gridparams_GFDLgrid.py | 2 +- ush/set_ozone_param.py | 55 +- ush/set_predef_grid_params.py | 9 +- ush/set_thompson_mp_fix_files.py | 39 +- ush/setup.py | 607 ++++++++++-------- ush/test_retrieve_data.py | 97 ++- 39 files changed, 1001 insertions(+), 1101 deletions(-) create mode 100644 parm/fixed_files_mapping.yaml create mode 100755 ush/check_python_version.py delete mode 100644 ush/python_utils/count_files.py delete mode 100644 ush/python_utils/get_charvar_from_netcdf.py delete mode 100644 ush/python_utils/get_elem_inds.py delete mode 100644 ush/python_utils/interpol_to_arbit_CRES.py delete mode 100644 ush/set_extrn_mdl_params.py diff --git a/parm/fixed_files_mapping.yaml b/parm/fixed_files_mapping.yaml new file mode 100644 index 0000000000..2439e535a0 --- /dev/null +++ b/parm/fixed_files_mapping.yaml @@ -0,0 +1,208 @@ +fixed_files: + # + #----------------------------------------------------------------------- + # + # FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING: + # This array is used to set some of the namelist variables in the forecast + # model's namelist file that represent the relative or absolute paths of + # various fixed files (the first column of the array, where columns are + # delineated by the pipe symbol "|") to the full paths to surface climatology + # files (on the native FV3-LAM grid) in the FIXlam directory derived from + # the corresponding surface climatology fields (the second column of the + # array). + # + #----------------------------------------------------------------------- + # + FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING: [ + "FNALBC | snowfree_albedo", + "FNALBC2 | facsf", + "FNTG3C | substrate_temperature", + "FNVEGC | vegetation_greenness", + "FNVETC | vegetation_type", + "FNSOTC | soil_type", + "FNVMNC | vegetation_greenness", + "FNVMXC | vegetation_greenness", + "FNSLPC | slope_type", + "FNABSC | maximum_snow_albedo" + ] + + # + #----------------------------------------------------------------------- + # + # Set the array parameter containing the names of all the fields that the + # MAKE_SFC_CLIMO_TN task generates on the native FV3-LAM grid. + # + #----------------------------------------------------------------------- + # + SFC_CLIMO_FIELDS: [ + "facsf", + "maximum_snow_albedo", + "slope_type", + "snowfree_albedo", + "soil_type", + "substrate_temperature", + "vegetation_greenness", + "vegetation_type", + ] + + # + #----------------------------------------------------------------------- + # + # FNGLAC, ..., FNMSKH: + # Names of (some of the) global data files that are assumed to exist in + # a system directory specified (this directory is machine-dependent; + # the experiment generation scripts will set it and store it in the + # variable FIXgsm). These file names also appear directly in the forecast + # model's input namelist file. + # + #----------------------------------------------------------------------- + # + FNGLAC: &FNGLAC "global_glacier.2x2.grb" + FNMXIC: &FNMXIC "global_maxice.2x2.grb" + FNTSFC: &FNTSFC "RTGSST.1982.2012.monthly.clim.grb" + FNSNOC: &FNSNOC "global_snoclim.1.875.grb" + FNZORC: &FNZORC "igbp" + FNAISC: &FNAISC "CFSR.SEAICE.1982.2012.monthly.clim.grb" + FNSMCC: &FNSMCC "global_soilmgldas.t126.384.190.grb" + FNMSKH: &FNMSKH "seaice_newland.grb" + # + #----------------------------------------------------------------------- + # + # FIXgsm_FILES_TO_COPY_TO_FIXam: + # If not running in NCO mode, this array contains the names of the files + # to copy from the FIXgsm system directory to the FIXam directory under + # the experiment directory. Note that the last element has a dummy value. + # This last element will get reset by the workflow generation scripts to + # the name of the ozone production/loss file to copy from FIXgsm. The + # name of this file depends on the ozone parameterization being used, + # and that in turn depends on the CCPP physics suite specified for the + # experiment. Thus, the CCPP physics suite XML must first be read in to + # determine the ozone parameterizaton and then the name of the ozone + # production/loss file. These steps are carried out elsewhere (in one + # of the workflow generation scripts/functions). + # + #----------------------------------------------------------------------- + # + FIXgsm_FILES_TO_COPY_TO_FIXam: [ + *FNGLAC, + *FNMXIC, + *FNTSFC, + *FNSNOC, + *FNAISC, + *FNSMCC, + *FNMSKH, + "global_climaeropac_global.txt", + "fix_co2_proj/global_co2historicaldata_2010.txt", + "fix_co2_proj/global_co2historicaldata_2011.txt", + "fix_co2_proj/global_co2historicaldata_2012.txt", + "fix_co2_proj/global_co2historicaldata_2013.txt", + "fix_co2_proj/global_co2historicaldata_2014.txt", + "fix_co2_proj/global_co2historicaldata_2015.txt", + "fix_co2_proj/global_co2historicaldata_2016.txt", + "fix_co2_proj/global_co2historicaldata_2017.txt", + "fix_co2_proj/global_co2historicaldata_2018.txt", + "fix_co2_proj/global_co2historicaldata_2019.txt", + "fix_co2_proj/global_co2historicaldata_2020.txt", + "fix_co2_proj/global_co2historicaldata_2021.txt", + "global_co2historicaldata_glob.txt", + "co2monthlycyc.txt", + "global_h2o_pltc.f77", + "global_hyblev.l65.txt", + "global_zorclim.1x1.grb", + "global_sfc_emissivity_idx.txt", + "global_tg3clim.2.6x1.5.grb", + "global_solarconstant_noaa_an.txt", + "global_albedo4.1x1.grb", + "geo_em.d01.lat-lon.2.5m.HGT_M.nc", + "HGT.Beljaars_filtered.lat-lon.30s_res.nc", + "replace_with_FIXgsm_ozone_prodloss_filename" + ] + # + #----------------------------------------------------------------------- + # + # FV3_NML_VARNAME_TO_FIXam_FILES_MAPPING: + # This array is used to set some of the namelist variables in the forecast + # model's namelist file that represent the relative or absolute paths of + # various fixed files (the first column of the array, where columns are + # delineated by the pipe symbol "|") to the full paths to these files in + # the FIXam directory derived from the corresponding workflow variables + # containing file names (the second column of the array). + # + #----------------------------------------------------------------------- + # + FV3_NML_VARNAME_TO_FIXam_FILES_MAPPING: [ + !join_str ["FNGLAC | ",*FNGLAC], + !join_str ["FNMXIC | ",*FNMXIC], + !join_str ["FNTSFC | ",*FNTSFC], + !join_str ["FNSNOC | ",*FNSNOC], + !join_str ["FNAISC | ",*FNAISC], + !join_str ["FNSMCC | ",*FNSMCC], + !join_str ["FNMSKH | ",*FNMSKH] + ] + #"FNZORC | $FNZORC", + + # + #----------------------------------------------------------------------- + # + # FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING: + # This array is used to set some of the namelist variables in the forecast + # model's namelist file that represent the relative or absolute paths of + # various fixed files (the first column of the array, where columns are + # delineated by the pipe symbol "|") to the full paths to surface climatology + # files (on the native FV3-LAM grid) in the FIXlam directory derived from + # the corresponding surface climatology fields (the second column of the + # array). + # + #----------------------------------------------------------------------- + # + FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING: [ + "FNALBC | snowfree_albedo", + "FNALBC2 | facsf", + "FNTG3C | substrate_temperature", + "FNVEGC | vegetation_greenness", + "FNVETC | vegetation_type", + "FNSOTC | soil_type", + "FNVMNC | vegetation_greenness", + "FNVMXC | vegetation_greenness", + "FNSLPC | slope_type", + "FNABSC | maximum_snow_albedo" + ] + + + # + #----------------------------------------------------------------------- + # + # CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING: + # This array specifies the mapping to use between the symlinks that need + # to be created in each cycle directory (these are the "files" that FV3 + # looks for) and their targets in the FIXam directory. The first column + # of the array specifies the symlink to be created, and the second column + # specifies its target file in FIXam (where columns are delineated by the + # pipe symbol "|"). + # + #----------------------------------------------------------------------- + # + CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING: [ + "aerosol.dat | global_climaeropac_global.txt", + "co2historicaldata_2010.txt | fix_co2_proj/global_co2historicaldata_2010.txt", + "co2historicaldata_2011.txt | fix_co2_proj/global_co2historicaldata_2011.txt", + "co2historicaldata_2012.txt | fix_co2_proj/global_co2historicaldata_2012.txt", + "co2historicaldata_2013.txt | fix_co2_proj/global_co2historicaldata_2013.txt", + "co2historicaldata_2014.txt | fix_co2_proj/global_co2historicaldata_2014.txt", + "co2historicaldata_2015.txt | fix_co2_proj/global_co2historicaldata_2015.txt", + "co2historicaldata_2016.txt | fix_co2_proj/global_co2historicaldata_2016.txt", + "co2historicaldata_2017.txt | fix_co2_proj/global_co2historicaldata_2017.txt", + "co2historicaldata_2018.txt | fix_co2_proj/global_co2historicaldata_2018.txt", + "co2historicaldata_2019.txt | fix_co2_proj/global_co2historicaldata_2019.txt", + "co2historicaldata_2020.txt | fix_co2_proj/global_co2historicaldata_2020.txt", + "co2historicaldata_2021.txt | fix_co2_proj/global_co2historicaldata_2021.txt", + "co2historicaldata_glob.txt | global_co2historicaldata_glob.txt", + "co2monthlycyc.txt | co2monthlycyc.txt", + "global_h2oprdlos.f77 | global_h2o_pltc.f77", + "global_albedo4.1x1.grb | global_albedo4.1x1.grb", + "global_zorclim.1x1.grb | global_zorclim.1x1.grb", + "global_tg3clim.2.6x1.5.grb | global_tg3clim.2.6x1.5.grb", + "sfc_emissivity_idx.txt | global_sfc_emissivity_idx.txt", + "solarconstant_noaa_an.txt | global_solarconstant_noaa_an.txt", + "global_o3prdlos.f77 | " + ] diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 008cfbd063..626a855ba5 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -290,7 +290,7 @@ static) files in the FIXam directory: # isn't really an advantage to using relative symlinks, so we use symlinks # with absolute paths. # -if [ "${RUN_ENVIR}" != "nco" ]; then +if [ "${SYMLINK_FIX_FILES}" == "FALSE" ]; then relative_link_flag="TRUE" else relative_link_flag="FALSE" diff --git a/tests/WE2E/run_WE2E_tests.sh b/tests/WE2E/run_WE2E_tests.sh index ec06a88150..53edf57fde 100755 --- a/tests/WE2E/run_WE2E_tests.sh +++ b/tests/WE2E/run_WE2E_tests.sh @@ -69,56 +69,11 @@ WE2Edir="$TESTSdir/WE2E" # #----------------------------------------------------------------------- # - -# This line will return two numbers: the python major and minor versions -pyversion=($(/usr/bin/env python3 -c 'import platform; major, minor, patch = platform.python_version_tuple(); print(major); print(minor)')) - -#Now, set an error check variable so that we can print all python errors rather than just the first -pyerrors=0 - -# Check that the call to python3 returned no errors, then check if the -# python3 minor version is 6 or higher -if [[ -z "$pyversion" ]];then - print_info_msg "\ - - Error: python3 not found" - pyerrors=$((pyerrors+1)) -else - if [[ ${#pyversion[@]} -lt 2 ]]; then - print_info_msg "\ - - Error retrieving python3 version" - pyerrors=$((pyerrors+1)) - elif [[ ${pyversion[1]} -lt 6 ]]; then - print_info_msg "\ - - Error: python version must be 3.6 or higher - python version: ${pyversion[*]}" - pyerrors=$((pyerrors+1)) - fi +python3 $USHdir/check_python_version.py +if [[ $? -ne 0 ]]; then + exit 1 fi -#Next, check for the non-standard python packages: jinja2, yaml, and f90nml -pkgs=(jinja2 yaml f90nml) -for pkg in ${pkgs[@]} ; do - if ! /usr/bin/env python3 -c "import ${pkg}" &> /dev/null; then - print_info_msg "\ - - Error: python module ${pkg} not available" - pyerrors=$((pyerrors+1)) - fi -done - -#Finally, check if the number of errors is >0, and if so exit with helpful message -if [ $pyerrors -gt 0 ];then - print_err_msg_exit "\ - Errors found: check your python environment - - Instructions for setting up python environments can be found on the web: - https://github.com/ufs-community/ufs-srweather-app/wiki/Getting-Started - -" -fi # #----------------------------------------------------------------------- # diff --git a/ush/UFS_plot_domains.py b/ush/UFS_plot_domains.py index d752c2696b..847cd96725 100755 --- a/ush/UFS_plot_domains.py +++ b/ush/UFS_plot_domains.py @@ -128,7 +128,6 @@ def get_lambert_points(gnomonic_map, lambert_map, pps): - #print("Hello from a function") # This function takes the lambert domain we have defined, lambert_map, as well as # pps (the number of points to interpolate and draw for each side of the lambert "rectangle"), @@ -187,9 +186,6 @@ def get_lambert_points(gnomonic_map, lambert_map, pps): # Need to replace final instruction with Path.CLOSEPOLY instructions[-1] = Path.CLOSEPOLY - #print("vertices=", vertices) - #print("instructions=", instructions) - return vertices, instructions diff --git a/ush/check_python_version.py b/ush/check_python_version.py new file mode 100755 index 0000000000..afc3dac62f --- /dev/null +++ b/ush/check_python_version.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +import sys +import logging +import platform +from textwrap import dedent + + +def check_python_version(): + """Check if python version >= 3.6 and presence of some + non-standard packages currently jinja2, yaml, f90nml""" + + # Check for non-standard python packages + try: + import jinja2 + import yaml + import f90nml + except ImportError as error: + logging.error( + dedent( + """ + Error: Missing python package required by the SRW app + """ + ) + ) + raise + + # check python version + major, minor, patch = platform.python_version_tuple() + if int(major) < 3 or int(minor) < 6: + logging.error( + dedent( + f""" + Error: python version must be 3.6 or higher + Your python version is: {major}.{minor}""" + ) + ) + raise Exception("Python version below 3.6") + + +if __name__ == "__main__": + try: + check_python_version() + except: + logging.exception( + dedent( + f""" + ************************************************************************* + FATAL ERROR: + The system does not meet minimum requirements for running the SRW app. + Instructions for setting up python environments can be found on the web: + https://github.com/ufs-community/ufs-srweather-app/wiki/Getting-Started + *************************************************************************\n + """ + ) + ) + sys.exit(1) diff --git a/ush/check_ruc_lsm.py b/ush/check_ruc_lsm.py index 8d6e287df9..3afe1f8264 100644 --- a/ush/check_ruc_lsm.py +++ b/ush/check_ruc_lsm.py @@ -32,7 +32,9 @@ class Testing(unittest.TestCase): def test_check_ruc_lsm(self): USHdir = os.path.dirname(os.path.abspath(__file__)) self.assertTrue( - check_ruc_lsm(ccpp_phys_suite_fp=f"{USHdir}{os.sep}test_data{os.sep}suite_FV3_GSD_SAR.xml") + check_ruc_lsm( + ccpp_phys_suite_fp=f"{USHdir}{os.sep}test_data{os.sep}suite_FV3_GSD_SAR.xml" + ) ) def setUp(self): diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 2c5831a4df..43d29abe2f 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -38,7 +38,6 @@ user: # #----------------------------------------------------------------------- # - # mach_doc_start # Set machine and queue parameters. Definitions: # # MACHINE: @@ -46,7 +45,7 @@ user: # supported platform, and you want to use the Rocoto workflow manager, # you will need set MACHINE: "linux" and WORKFLOW_MANAGER: "rocoto". This # combination will assume a Slurm batch manager when generating the XML. - # Please see ush/valid_param_vals.sh for a full list of supported + # Please see ush/valid_param_vals.yaml for a full list of supported # platforms. # # ACCOUNT: @@ -72,13 +71,8 @@ platform: # the XML. Valid options: "rocoto" or "none" # # NCORES_PER_NODE: - # The number of cores available per node on the compute platform. Set - # for supported platforms in setup.sh, but is now also configurable for - # all platforms. - # - # LMOD_PATH: - # Path to the LMOD sh file on your Linux system. Is set automatically - # for supported machines. + # The number of cores available per node on the compute platform, now + # configurable for all platforms. # # BUILD_MOD_FN: # Name of alternative build module file to use if using an @@ -147,13 +141,10 @@ platform: # If this is not set or set to an empty string, it will be (re)set to a # machine-dependent value. # - # mach_doc_end - # #----------------------------------------------------------------------- # WORKFLOW_MANAGER: "" NCORES_PER_NODE: "" - LMOD_PATH: "" BUILD_MOD_FN: "" WFLOW_MOD_FN: "" BUILD_VER_FN: "" @@ -177,14 +168,15 @@ platform: # will run without MPI. # # RUN_CMD_FCST: - # The run command for the model forecast step. This will be appended to - # the end of the variable definitions file, so it can reference other - # variables. + # The run command for the model forecast step. # # RUN_CMD_POST: # The run command for post-processing (UPP). Can be left blank for smaller # domains, in which case UPP will run without MPI. # + # RUN_CMD_SERIAL: + # The run command for some serial jobs + # #----------------------------------------------------------------------- # RUN_CMD_SERIAL: "" @@ -211,6 +203,9 @@ platform: # MET_INSTALL_DIR: # Location to top-level directory of MET installation. # + # MET_BIN_EXEC: + # Subdirectory containing MET binaries e.g. "bin" + # # METPLUS_PATH: # Location to top-level directory of METplus installation. # @@ -328,7 +323,7 @@ platform: PRE_TASK_CMDS: "" # #----------------------------------------------------------------------- - # Test directories + # Test directories used in run_WE2E script #----------------------------------------------------------------------- # TEST_EXTRN_MDL_SOURCE_BASEDIR: "" @@ -340,14 +335,6 @@ platform: # WORKFLOW config parameters #----------------------------- workflow: - # - #----------------------------------------------------------------------- - # - # Unique ID for workflow run that will be set in setup.py - # - #----------------------------------------------------------------------- - # - WORKFLOW_ID: "" # #----------------------------------------------------------------------- # @@ -370,7 +357,6 @@ workflow: # #----------------------------------------------------------------------- # - # dir_doc_start # Set directories. Definitions: # # EXPT_BASEDIR: @@ -388,8 +374,6 @@ workflow: # This cannot be empty. If set to a null string here, it must be set to # a (non-empty) value in the user-defined experiment configuration file. # - # dir_doc_end - # # EXEC_SUBDIR: # The name of the subdirectory of ufs-srweather-app where executables are # installed. @@ -1042,7 +1026,7 @@ task_make_grid: # in generating the files with 0-cell-, 3-cell-, and 4-cell-wide halos; # they are not needed by the forecast model. # NOTE: Probably don't need to make ESGgrid_WIDE_HALO_WIDTH a user-specified - # variable. Just set it in the function set_gridparams_ESGgrid.sh. + # variable. Just set it in the function set_gridparams_ESGgrid.py. # # Note that: # @@ -1263,8 +1247,7 @@ task_get_extrn_lbcs: # should start. For example, the forecast should use lateral boundary # conditions from the GFS started 6 hours earlier, then # EXTRN_MDL_LBCS_OFFSET_HRS=6. - # Note: the default value is model-dependent and set in - # set_extrn_mdl_params.sh + # Note: the default value is model-dependent and set in setup.py # # FV3GFS_FILE_FMT_LBCS: # If using the FV3GFS model as the source of the LBCs (i.e. if @@ -1379,7 +1362,6 @@ task_make_lbcs: KMP_AFFINITY_MAKE_LBCS: "scatter" OMP_NUM_THREADS_MAKE_LBCS: 1 OMP_STACKSIZE_MAKE_LBCS: "1024m" - LBC_SPEC_FCST_HRS: [] #---------------------------- # FORECAST config parameters @@ -1387,7 +1369,7 @@ task_make_lbcs: task_run_fcst: RUN_FCST_TN: "run_fcst" NNODES_RUN_FCST: "" # This is calculated in the workflow generation scripts, so no need to set here. - PPN_RUN_FCST: "" # will be calculated from NCORES_PER_NODE and OMP_NUM_THREADS in setup.sh + PPN_RUN_FCST: "" # will be calculated from NCORES_PER_NODE and OMP_NUM_THREADS in setup.py WTIME_RUN_FCST: 04:30:00 MAXTRIES_RUN_FCST: 1 # @@ -1576,7 +1558,7 @@ task_run_fcst: # commonly used set of grid-dependent parameters. The predefined grid # parameters are specified in the script # - # $HOMEdir/ush/set_predef_grid_params.sh + # $HOMEdir/ush/set_predef_grid_params.py # #----------------------------------------------------------------------- # @@ -1613,6 +1595,9 @@ task_run_fcst: # # Set parameters associated with the fixed (i.e. static) files. Definitions: # + # SYMLINK_FIX_FILES: + # Symlink fix files to experiment directory if true, otherwise copy the files + # # FIXgsm: # System directory in which the majority of fixed (i.e. time-independent) # files that are needed to run the FV3-LAM model are located @@ -1623,158 +1608,12 @@ task_run_fcst: # FIXlut: # System directory where the lookup tables for optics properties are located # - # FNGLAC, ..., FNMSKH: - # Names of (some of the) global data files that are assumed to exist in - # a system directory specified (this directory is machine-dependent; - # the experiment generation scripts will set it and store it in the - # variable FIXgsm). These file names also appear directly in the forecast - # model's input namelist file. - # - # FIXgsm_FILES_TO_COPY_TO_FIXam: - # If not running in NCO mode, this array contains the names of the files - # to copy from the FIXgsm system directory to the FIXam directory under - # the experiment directory. Note that the last element has a dummy value. - # This last element will get reset by the workflow generation scripts to - # the name of the ozone production/loss file to copy from FIXgsm. The - # name of this file depends on the ozone parameterization being used, - # and that in turn depends on the CCPP physics suite specified for the - # experiment. Thus, the CCPP physics suite XML must first be read in to - # determine the ozone parameterizaton and then the name of the ozone - # production/loss file. These steps are carried out elsewhere (in one - # of the workflow generation scripts/functions). - # - # FV3_NML_VARNAME_TO_FIXam_FILES_MAPPING: - # This array is used to set some of the namelist variables in the forecast - # model's namelist file that represent the relative or absolute paths of - # various fixed files (the first column of the array, where columns are - # delineated by the pipe symbol "|") to the full paths to these files in - # the FIXam directory derived from the corresponding workflow variables - # containing file names (the second column of the array). - # - # FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING: - # This array is used to set some of the namelist variables in the forecast - # model's namelist file that represent the relative or absolute paths of - # various fixed files (the first column of the array, where columns are - # delineated by the pipe symbol "|") to the full paths to surface climatology - # files (on the native FV3-LAM grid) in the FIXlam directory derived from - # the corresponding surface climatology fields (the second column of the - # array). - # - # CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING: - # This array specifies the mapping to use between the symlinks that need - # to be created in each cycle directory (these are the "files" that FV3 - # looks for) and their targets in the FIXam directory. The first column - # of the array specifies the symlink to be created, and the second column - # specifies its target file in FIXam (where columns are delineated by the - # pipe symbol "|"). - # - #----------------------------------------------------------------------- - # - # Because the default values are dependent on the platform, we set these - # to a null string which will then be overwritten in setup.sh unless the - # user has specified a different value in config.sh + #----------------------------------------------------------------------- # SYMLINK_FIX_FILES: true FIXgsm: "" FIXaer: "" FIXlut: "" - - FNGLAC: &FNGLAC "global_glacier.2x2.grb" - FNMXIC: &FNMXIC "global_maxice.2x2.grb" - FNTSFC: &FNTSFC "RTGSST.1982.2012.monthly.clim.grb" - FNSNOC: &FNSNOC "global_snoclim.1.875.grb" - FNZORC: &FNZORC "igbp" - FNAISC: &FNAISC "CFSR.SEAICE.1982.2012.monthly.clim.grb" - FNSMCC: &FNSMCC "global_soilmgldas.t126.384.190.grb" - FNMSKH: &FNMSKH "seaice_newland.grb" - - FIXgsm_FILES_TO_COPY_TO_FIXam: [ - *FNGLAC, - *FNMXIC, - *FNTSFC, - *FNSNOC, - *FNAISC, - *FNSMCC, - *FNMSKH, - "global_climaeropac_global.txt", - "fix_co2_proj/global_co2historicaldata_2010.txt", - "fix_co2_proj/global_co2historicaldata_2011.txt", - "fix_co2_proj/global_co2historicaldata_2012.txt", - "fix_co2_proj/global_co2historicaldata_2013.txt", - "fix_co2_proj/global_co2historicaldata_2014.txt", - "fix_co2_proj/global_co2historicaldata_2015.txt", - "fix_co2_proj/global_co2historicaldata_2016.txt", - "fix_co2_proj/global_co2historicaldata_2017.txt", - "fix_co2_proj/global_co2historicaldata_2018.txt", - "fix_co2_proj/global_co2historicaldata_2019.txt", - "fix_co2_proj/global_co2historicaldata_2020.txt", - "fix_co2_proj/global_co2historicaldata_2021.txt", - "global_co2historicaldata_glob.txt", - "co2monthlycyc.txt", - "global_h2o_pltc.f77", - "global_hyblev.l65.txt", - "global_zorclim.1x1.grb", - "global_sfc_emissivity_idx.txt", - "global_tg3clim.2.6x1.5.grb", - "global_solarconstant_noaa_an.txt", - "global_albedo4.1x1.grb", - "geo_em.d01.lat-lon.2.5m.HGT_M.nc", - "HGT.Beljaars_filtered.lat-lon.30s_res.nc", - "replace_with_FIXgsm_ozone_prodloss_filename" - ] - - # - # It is possible to remove this as a workflow variable and make it only - # a local one since it is used in only one script. - # - FV3_NML_VARNAME_TO_FIXam_FILES_MAPPING: [ - !join_str ["FNGLAC | ",*FNGLAC], - !join_str ["FNMXIC | ",*FNMXIC], - !join_str ["FNTSFC | ",*FNTSFC], - !join_str ["FNSNOC | ",*FNSNOC], - !join_str ["FNAISC | ",*FNAISC], - !join_str ["FNSMCC | ",*FNSMCC], - !join_str ["FNMSKH | ",*FNMSKH] - ] - #"FNZORC | $FNZORC", - - FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING: [ - "FNALBC | snowfree_albedo", - "FNALBC2 | facsf", - "FNTG3C | substrate_temperature", - "FNVEGC | vegetation_greenness", - "FNVETC | vegetation_type", - "FNSOTC | soil_type", - "FNVMNC | vegetation_greenness", - "FNVMXC | vegetation_greenness", - "FNSLPC | slope_type", - "FNABSC | maximum_snow_albedo" - ] - - CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING: [ - "aerosol.dat | global_climaeropac_global.txt", - "co2historicaldata_2010.txt | fix_co2_proj/global_co2historicaldata_2010.txt", - "co2historicaldata_2011.txt | fix_co2_proj/global_co2historicaldata_2011.txt", - "co2historicaldata_2012.txt | fix_co2_proj/global_co2historicaldata_2012.txt", - "co2historicaldata_2013.txt | fix_co2_proj/global_co2historicaldata_2013.txt", - "co2historicaldata_2014.txt | fix_co2_proj/global_co2historicaldata_2014.txt", - "co2historicaldata_2015.txt | fix_co2_proj/global_co2historicaldata_2015.txt", - "co2historicaldata_2016.txt | fix_co2_proj/global_co2historicaldata_2016.txt", - "co2historicaldata_2017.txt | fix_co2_proj/global_co2historicaldata_2017.txt", - "co2historicaldata_2018.txt | fix_co2_proj/global_co2historicaldata_2018.txt", - "co2historicaldata_2019.txt | fix_co2_proj/global_co2historicaldata_2019.txt", - "co2historicaldata_2020.txt | fix_co2_proj/global_co2historicaldata_2020.txt", - "co2historicaldata_2021.txt | fix_co2_proj/global_co2historicaldata_2021.txt", - "co2historicaldata_glob.txt | global_co2historicaldata_glob.txt", - "co2monthlycyc.txt | co2monthlycyc.txt", - "global_h2oprdlos.f77 | global_h2o_pltc.f77", - "global_albedo4.1x1.grb | global_albedo4.1x1.grb", - "global_zorclim.1x1.grb | global_zorclim.1x1.grb", - "global_tg3clim.2.6x1.5.grb | global_tg3clim.2.6x1.5.grb", - "sfc_emissivity_idx.txt | global_sfc_emissivity_idx.txt", - "solarconstant_noaa_an.txt | global_solarconstant_noaa_an.txt", - "global_o3prdlos.f77 | " - ] #---------------------------- # POST config parameters @@ -2184,7 +2023,7 @@ global: # # Set default SPP stochastic physics options. Each SPP option is an array, # applicable (in order) to the scheme/parameter listed in SPP_VAR_LIST. - # Enter each value of the array in config.sh as shown below without commas + # Enter each value of the array in config.yaml as shown below without commas # or single quotes (e.g., SPP_VAR_LIST=( "pbl" "sfc" "mp" "rad" "gwd" ). # Both commas and single quotes will be added by Jinja when creating the # namelist. diff --git a/ush/create_diag_table_file.py b/ush/create_diag_table_file.py index cd1943ef77..15a42729f4 100644 --- a/ush/create_diag_table_file.py +++ b/ush/create_diag_table_file.py @@ -36,26 +36,25 @@ def create_diag_table_file(run_dir): # create a diagnostic table file within the specified run directory print_info_msg( - f''' - Creating a diagnostics table file (\"{DIAG_TABLE_FN}\") in the specified + f""" + Creating a diagnostics table file ('{DIAG_TABLE_FN}') in the specified run directory... - run_dir = \"{run_dir}\"''', + run_dir = '{run_dir}'""", verbose=VERBOSE, ) diag_table_fp = os.path.join(run_dir, DIAG_TABLE_FN) print_info_msg( - f''' - + f""" Using the template diagnostics table file: diag_table_tmpl_fp = {DIAG_TABLE_TMPL_FP} to create: - diag_table_fp = \"{diag_table_fp}\"''', + diag_table_fp = '{diag_table_fp}'""", verbose=VERBOSE, ) @@ -65,9 +64,9 @@ def create_diag_table_file(run_dir): print_info_msg( dedent( f""" - The variable \"settings\" specifying values to be used in the \"{DIAG_TABLE_FN}\" - file has been set as follows:\n - settings =\n\n""" + The variable 'settings' specifying values to be used in the '{DIAG_TABLE_FN}' + file has been set as follows:\n + settings =\n\n""" ) + settings_str, verbose=VERBOSE, @@ -82,14 +81,14 @@ def create_diag_table_file(run_dir): print_err_msg_exit( dedent( f""" - Call to python script fill_jinja_template.py to create a \"{DIAG_TABLE_FN}\" - file from a jinja2 template failed. Parameters passed to this script are: - Full path to template diag table file: - DIAG_TABLE_TMPL_FP = \"{DIAG_TABLE_TMPL_FP}\" - Full path to output diag table file: - diag_table_fp = \"{diag_table_fp}\" - Namelist settings specified on command line:\n - settings =\n\n""" + Call to python script fill_jinja_template.py to create a '{DIAG_TABLE_FN}' + file from a jinja2 template failed. Parameters passed to this script are: + Full path to template diag table file: + DIAG_TABLE_TMPL_FP = '{DIAG_TABLE_TMPL_FP}' + Full path to output diag table file: + diag_table_fp = '{diag_table_fp}' + Namelist settings specified on command line:\n + settings =\n\n""" ) + settings_str ) @@ -133,9 +132,7 @@ def setUp(self): USHdir = os.path.dirname(os.path.abspath(__file__)) PARMdir = os.path.join(USHdir, "..", "parm") DIAG_TABLE_FN = "diag_table" - DIAG_TABLE_TMPL_FP = os.path.join( - PARMdir, f"{DIAG_TABLE_FN}.FV3_GFS_v15p2" - ) + DIAG_TABLE_TMPL_FP = os.path.join(PARMdir, f"{DIAG_TABLE_FN}.FV3_GFS_v15p2") set_env_var("DEBUG", True) set_env_var("VERBOSE", True) set_env_var("USHdir", USHdir) diff --git a/ush/create_model_configure_file.py b/ush/create_model_configure_file.py index 1cd445a3e9..7015e59729 100644 --- a/ush/create_model_configure_file.py +++ b/ush/create_model_configure_file.py @@ -52,10 +52,10 @@ def create_model_configure_file( # ----------------------------------------------------------------------- # print_info_msg( - f''' - Creating a model configuration file (\"{MODEL_CONFIG_FN}\") in the specified + f""" + Creating a model configuration file ('{MODEL_CONFIG_FN}') in the specified run directory (run_dir): - run_dir = \"{run_dir}\"''', + run_dir = '{run_dir}'""", verbose=VERBOSE, ) # @@ -190,7 +190,7 @@ def create_model_configure_file( print_info_msg( dedent( f""" - The variable \"settings\" specifying values to be used in the \"{MODEL_CONFIG_FN}\" + The variable 'settings' specifying values to be used in the '{MODEL_CONFIG_FN}' file has been set as follows:\n settings =\n\n""" ) @@ -223,14 +223,14 @@ def create_model_configure_file( print_err_msg_exit( dedent( f""" - Call to python script fill_jinja_template.py to create a \"{MODEL_CONFIG_FN}\" - file from a jinja2 template failed. Parameters passed to this script are: - Full path to template model config file: - MODEL_CONFIG_TMPL_FP = \"{MODEL_CONFIG_TMPL_FP}\" - Full path to output model config file: - model_config_fp = \"{model_config_fp}\" - Namelist settings specified on command line:\n - settings =\n\n""" + Call to python script fill_jinja_template.py to create a '{MODEL_CONFIG_FN}' + file from a jinja2 template failed. Parameters passed to this script are: + Full path to template model config file: + MODEL_CONFIG_TMPL_FP = '{MODEL_CONFIG_TMPL_FP}' + Full path to output model config file: + model_config_fp = '{model_config_fp}' + Namelist settings specified on command line:\n + settings =\n\n""" ) + settings_str ) diff --git a/ush/generate_FV3LAM_wflow.py b/ush/generate_FV3LAM_wflow.py index 11a86c9aaa..969485fce0 100755 --- a/ush/generate_FV3LAM_wflow.py +++ b/ush/generate_FV3LAM_wflow.py @@ -2,7 +2,6 @@ import os import sys -import platform import subprocess import unittest import logging @@ -37,33 +36,10 @@ from get_crontab_contents import add_crontab_line from fill_jinja_template import fill_jinja_template from set_namelist import set_namelist +from check_python_version import check_python_version -def python_error_handler(): - """Error handler for missing packages""" - - print_err_msg_exit( - """ - Errors found: check your python environment - - Instructions for setting up python environments can be found on the web: - https://github.com/ufs-community/ufs-srweather-app/wiki/Getting-Started - """, - stack_trace=False, - ) - - -# Check for non-standard python packages -try: - import jinja2 - import yaml - import f90nml -except ImportError as error: - print_info_msg(error.__class__.__name__ + ": " + str(error)) - python_error_handler() - - -def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> None: +def generate_FV3LAM_wflow(USHdir, logfile: str = "log.generate_FV3LAM_wflow") -> None: """Function to setup a forecast experiment and create a workflow (according to the parameters specified in the config file) @@ -77,28 +53,21 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> # Set up logging to write to screen and logfile setup_logging(logfile) + # Check python version and presence of some non-standard packages + check_python_version() + + # Note start of workflow generation log_info( - """ + """ ======================================================================== Starting experiment generation... ========================================================================""" ) - # check python version - major, minor, patch = platform.python_version_tuple() - if int(major) < 3 or int(minor) < 6: - logging.error( - f""" - - Error: python version must be 3.6 or higher - python version: {major}.{minor}""" - ) - raise - - # define utilities + # define utilities define_macos_utilities() - # The setup function reads the user configuration file and fills in + # The setup function reads the user configuration file and fills in # non-user-specified values from config_defaults.yaml setup() @@ -132,11 +101,11 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> template_xml_fp = os.path.join(PARMdir, WFLOW_XML_FN) log_info( - f''' + f""" Creating rocoto workflow XML file (WFLOW_XML_FP) from jinja template XML file (template_xml_fp): - template_xml_fp = \"{template_xml_fp}\" - WFLOW_XML_FP = \"{WFLOW_XML_FP}\"''' + template_xml_fp = '{template_xml_fp}' + WFLOW_XML_FP = '{WFLOW_XML_FP}'""" ) ensmem_indx_name = "" @@ -427,13 +396,13 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> settings_str = cfg_to_yaml_str(settings) log_info( - f""" - The variable \"settings\" specifying values of the rococo XML variables - has been set as follows: - #----------------------------------------------------------------------- - settings =\n\n""", - verbose=VERBOSE, - ) + f""" + The variable 'settings' specifying values of the rococo XML variables + has been set as follows: + #----------------------------------------------------------------------- + settings =\n\n""", + verbose=VERBOSE, + ) log_info(settings_str, verbose=VERBOSE) # @@ -448,15 +417,15 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> logging.exception( dedent( f""" - Call to python script fill_jinja_template.py to create a rocoto workflow - XML file from a template file failed. Parameters passed to this script - are: - Full path to template rocoto XML file: - template_xml_fp = \"{template_xml_fp}\" - Full path to output rocoto XML file: - WFLOW_XML_FP = \"{WFLOW_XML_FP}\" - Namelist settings specified on command line:\n - settings =\n\n""" + Call to python script fill_jinja_template.py to create a rocoto workflow + XML file from a template file failed. Parameters passed to this script + are: + Full path to template rocoto XML file: + template_xml_fp = '{template_xml_fp}' + Full path to output rocoto XML file: + WFLOW_XML_FP = '{WFLOW_XML_FP}' + Namelist settings specified on command line:\n + settings =\n\n""" ) + settings_str ) @@ -469,11 +438,11 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> # ----------------------------------------------------------------------- # log_info( - f''' + f""" Creating symlink in the experiment directory (EXPTDIR) that points to the workflow launch script (WFLOW_LAUNCH_SCRIPT_FP): - EXPTDIR = \"{EXPTDIR}\" - WFLOW_LAUNCH_SCRIPT_FP = \"{WFLOW_LAUNCH_SCRIPT_FP}\"''', + EXPTDIR = '{EXPTDIR}' + WFLOW_LAUNCH_SCRIPT_FP = '{WFLOW_LAUNCH_SCRIPT_FP}'""", verbose=VERBOSE, ) @@ -498,21 +467,21 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> if SYMLINK_FIX_FILES: log_info( - f''' + f""" Symlinking fixed files from system directory (FIXgsm) to a subdirectory (FIXam): - FIXgsm = \"{FIXgsm}\" - FIXam = \"{FIXam}\"''', + FIXgsm = '{FIXgsm}' + FIXam = '{FIXam}'""", verbose=VERBOSE, ) - ln_vrfy(f'''-fsn "{FIXgsm}" "{FIXam}"''') + ln_vrfy(f"""-fsn '{FIXgsm}' '{FIXam}'""") else: log_info( - f''' + f""" Copying fixed files from system directory (FIXgsm) to a subdirectory (FIXam): - FIXgsm = \"{FIXgsm}\" - FIXam = \"{FIXam}\"''', + FIXgsm = '{FIXgsm}' + FIXam = '{FIXam}'""", verbose=VERBOSE, ) @@ -533,12 +502,12 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> # if USE_MERRA_CLIMO: log_info( - f''' + f""" Copying MERRA2 aerosol climatology data files from system directory (FIXaer/FIXlut) to a subdirectory (FIXclim) in the experiment directory: - FIXaer = \"{FIXaer}\" - FIXlut = \"{FIXlut}\" - FIXclim = \"{FIXclim}\"''', + FIXaer = '{FIXaer}' + FIXlut = '{FIXlut}' + FIXclim = '{FIXclim}'""", verbose=VERBOSE, ) @@ -616,9 +585,9 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> # ----------------------------------------------------------------------- # log_info( - f''' + f""" Setting parameters in weather model's namelist file (FV3_NML_FP): - FV3_NML_FP = \"{FV3_NML_FP}\"''' + FV3_NML_FP = '{FV3_NML_FP}'""" ) # # Set npx and npy, which are just NX plus 1 and NY plus 1, respectively. @@ -848,9 +817,9 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> settings_str = cfg_to_yaml_str(settings) log_info( - f""" - The variable \"settings\" specifying values of the weather model's - namelist variables has been set as follows:\n""", + f""" + The variable 'settings' specifying values of the weather model's + namelist variables has been set as follows:\n""", verbose=VERBOSE, ) log_info("\nsettings =\n\n" + settings_str, verbose=VERBOSE) @@ -886,18 +855,18 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> logging.exception( dedent( f""" - Call to python script set_namelist.py to generate an FV3 namelist file - failed. Parameters passed to this script are: - Full path to base namelist file: - FV3_NML_BASE_SUITE_FP = \"{FV3_NML_BASE_SUITE_FP}\" - Full path to yaml configuration file for various physics suites: - FV3_NML_YAML_CONFIG_FP = \"{FV3_NML_YAML_CONFIG_FP}\" - Physics suite to extract from yaml configuration file: - CCPP_PHYS_SUITE = \"{CCPP_PHYS_SUITE}\" - Full path to output namelist file: - FV3_NML_FP = \"{FV3_NML_FP}\" - Namelist settings specified on command line:\n - settings =\n\n""" + Call to python script set_namelist.py to generate an FV3 namelist file + failed. Parameters passed to this script are: + Full path to base namelist file: + FV3_NML_BASE_SUITE_FP = '{FV3_NML_BASE_SUITE_FP}' + Full path to yaml configuration file for various physics suites: + FV3_NML_YAML_CONFIG_FP = '{FV3_NML_YAML_CONFIG_FP}' + Physics suite to extract from yaml configuration file: + CCPP_PHYS_SUITE = '{CCPP_PHYS_SUITE}' + Full path to output namelist file: + FV3_NML_FP = '{FV3_NML_FP}' + Namelist settings specified on command line:\n + settings =\n\n""" ) + settings_str ) @@ -921,7 +890,15 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> if NOMADS: raise Exception("Nomads script does not work!") - # get_nomads_data(NOMADS_file_type,EXPTDIR,USHdir,DATE_FIRST_CYCL,CYCL_HRS,FCST_LEN_HRS,LBC_SPEC_INTVL_HRS) + # get_nomads_data( + # NOMADS_file_type, + # EXPTDIR, + # USHdir, + # DATE_FIRST_CYCL, + # CYCL_HRS, + # FCST_LEN_HRS, + # LBC_SPEC_INTVL_HRS, + # ) # # ----------------------------------------------------------------------- @@ -933,21 +910,8 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> # ----------------------------------------------------------------------- # cp_vrfy(os.path.join(USHdir, EXPT_CONFIG_FN), EXPTDIR) - # - # ----------------------------------------------------------------------- - # - # For convenience, print out the commands that need to be issued on the - # command line in order to launch the workflow and to check its status. - # Also, print out the line that should be placed in the user's cron table - # in order for the workflow to be continually resubmitted. - # - # ----------------------------------------------------------------------- - # - if WORKFLOW_MANAGER == "rocoto": - wflow_db_fn = f"{os.path.splitext(WFLOW_XML_FN)[0]}.db" - rocotorun_cmd = f"rocotorun -w {WFLOW_XML_FN} -d {wflow_db_fn} -v 10" - rocotostat_cmd = f"rocotostat -w {WFLOW_XML_FN} -d {wflow_db_fn} -v 10" + # Note workflow generation completion log_info( f""" ======================================================================== @@ -955,19 +919,26 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> Experiment generation completed. The experiment directory is: - EXPTDIR=\"{EXPTDIR}\" + EXPTDIR='{EXPTDIR}' ======================================================================== ======================================================================== """ ) + # # ----------------------------------------------------------------------- # - # If rocoto is required, print instructions on how to use it + # For convenience, print out the commands that need to be issued on the + # command line in order to launch the workflow and to check its status. + # Also, print out the line that should be placed in the user's cron table + # in order for the workflow to be continually resubmitted. # # ----------------------------------------------------------------------- # if WORKFLOW_MANAGER == "rocoto": + wflow_db_fn = f"{os.path.splitext(WFLOW_XML_FN)[0]}.db" + rocotorun_cmd = f"rocotorun -w {WFLOW_XML_FN} -d {wflow_db_fn} -v 10" + rocotostat_cmd = f"rocotostat -w {WFLOW_XML_FN} -d {wflow_db_fn} -v 10" log_info( f""" @@ -992,67 +963,89 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = 'log.generate_FV3LAM_wflow') -> the rocotorun command must be issued immediately before issuing the rocotostat command. - For automatic resubmission of the workflow (say every 3 minutes), the - following line can be added to the user's crontab (use \"crontab -e\" to + For automatic resubmission of the workflow (say every {CRON_RELAUNCH_INTVL_MNTS} minutes), the + following line can be added to the user's crontab (use 'crontab -e' to edit the cron table): - */{CRON_RELAUNCH_INTVL_MNTS} * * * * cd {EXPTDIR} && ./launch_FV3LAM_wflow.sh called_from_cron=\"TRUE\" + */{CRON_RELAUNCH_INTVL_MNTS} * * * * cd {EXPTDIR} && ./launch_FV3LAM_wflow.sh called_from_cron="TRUE" """ ) # If we got to this point everything was successful: move the log file to the experiment directory. mv_vrfy(logfile, EXPTDIR) -def get_nomads_data(NOMADS_file_type,EXPTDIR,USHdir,DATE_FIRST_CYCL,CYCL_HRS,FCST_LEN_HRS,LBC_SPEC_INTVL_HRS): + +def get_nomads_data( + NOMADS_file_type, + EXPTDIR, + USHdir, + DATE_FIRST_CYCL, + CYCL_HRS, + FCST_LEN_HRS, + LBC_SPEC_INTVL_HRS, +): print("Getting NOMADS online data") print(f"NOMADS_file_type= {NOMADS_file_type}") cd_vrfy(EXPTDIR) NOMADS_script = os.path.join(USHdir, "NOMADS_get_extrn_mdl_files.sh") - run_command(f"""{NOMADS_script} {date_to_str(DATE_FIRST_CYCL,format="%Y%m%d")} \ - {date_to_str(DATE_FIRST_CYCL,format="%H")} {NOMADS_file_type} {FCST_LEN_HRS} {LBC_SPEC_INTVL_HRS}""") + run_command( + f"""{NOMADS_script} \ + {date_to_str(DATE_FIRST_CYCL,format='%Y%m%d')} \ + {date_to_str(DATE_FIRST_CYCL,format='%H')} \ + {NOMADS_file_type} \ + {FCST_LEN_HRS} \ + {LBC_SPEC_INTVL_HRS}""" + ) + -def setup_logging(logfile: str = 'log.generate_FV3LAM_wflow') -> None: +def setup_logging(logfile: str = "log.generate_FV3LAM_wflow") -> None: """ Sets up logging, printing high-priority (INFO and higher) messages to screen, and printing all messages with detailed timing and routine info in the specified text file. """ - logging.basicConfig(level=logging.DEBUG, - format='%(name)-22s %(levelname)-8s %(message)s', - filename=logfile, - filemode='w') - logging.debug(f'Finished setting up debug file logging in {logfile}') + logging.basicConfig( + level=logging.DEBUG, + format="%(name)-22s %(levelname)-8s %(message)s", + filename=logfile, + filemode="w", + ) + logging.debug(f"Finished setting up debug file logging in {logfile}") console = logging.StreamHandler() console.setLevel(logging.INFO) logging.getLogger().addHandler(console) - logging.debug('Logging set up successfully') + logging.debug("Logging set up successfully") + if __name__ == "__main__": USHdir = os.path.dirname(os.path.abspath(__file__)) - logfile=f'{USHdir}/log.generate_FV3LAM_wflow' + logfile = f"{USHdir}/log.generate_FV3LAM_wflow" # Call the generate_FV3LAM_wflow function defined above to generate the # experiment/workflow. try: generate_FV3LAM_wflow(USHdir, logfile) except: - logging.exception(dedent( - f""" - ********************************************************************* - FATAL ERROR: - Experiment generation failed. See the error message(s) printed below. - For more detailed information, check the log file from the workflow - generation script: {logfile} - *********************************************************************\n - """ - )) + logging.exception( + dedent( + f""" + ********************************************************************* + FATAL ERROR: + Experiment generation failed. See the error message(s) printed below. + For more detailed information, check the log file from the workflow + generation script: {logfile} + *********************************************************************\n + """ + ) + ) + class Testing(unittest.TestCase): def test_generate_FV3LAM_wflow(self): # run workflows in separate process to avoid conflict between community and nco settings - def run_workflow(USHdir,logfile): - p = Process(target=generate_FV3LAM_wflow,args=(USHdir,logfile)) + def run_workflow(USHdir, logfile): + p = Process(target=generate_FV3LAM_wflow, args=(USHdir, logfile)) p.start() p.join() exit_code = p.exitcode @@ -1060,18 +1053,22 @@ def run_workflow(USHdir,logfile): sys.exit(exit_code) USHdir = os.path.dirname(os.path.abspath(__file__)) - logfile='log.generate_FV3LAM_wflow' + logfile = "log.generate_FV3LAM_wflow" SED = get_env_var("SED") # community test case cp_vrfy(f"{USHdir}/config.community.yaml", f"{USHdir}/config.yaml") - run_command(f"""{SED} -i 's/MACHINE: hera/MACHINE: linux/g' {USHdir}/config.yaml""") + run_command( + f"""{SED} -i 's/MACHINE: hera/MACHINE: linux/g' {USHdir}/config.yaml""" + ) run_workflow(USHdir, logfile) # nco test case set_env_var("OPSROOT", f"{USHdir}/../../nco_dirs") cp_vrfy(f"{USHdir}/config.nco.yaml", f"{USHdir}/config.yaml") - run_command(f"""{SED} -i 's/MACHINE: hera/MACHINE: linux/g' {USHdir}/config.yaml""") + run_command( + f"""{SED} -i 's/MACHINE: hera/MACHINE: linux/g' {USHdir}/config.yaml""" + ) run_workflow(USHdir, logfile) def setUp(self): diff --git a/ush/get_crontab_contents.py b/ush/get_crontab_contents.py index c6c8d41ee0..a1e7863a43 100644 --- a/ush/get_crontab_contents.py +++ b/ush/get_crontab_contents.py @@ -64,22 +64,22 @@ def get_crontab_contents(called_from_cron): __crontab_cmd__ = "/usr/bin/crontab" print_info_msg( - f''' + f""" Getting crontab content with command: ========================================================= {__crontab_cmd__} -l - =========================================================''', + =========================================================""", verbose=DEBUG, ) (_, __crontab_contents__, _) = run_command(f"""{__crontab_cmd__} -l""") print_info_msg( - f''' + f""" Crontab contents: ========================================================= {__crontab_contents__} - =========================================================''', + =========================================================""", verbose=DEBUG, ) @@ -102,9 +102,9 @@ def add_crontab_line(): time_stamp = datetime.now().strftime("%F_%T") crontab_backup_fp = os.path.join(EXPTDIR, f"crontab.bak.{time_stamp}") log_info( - f''' + f""" Copying contents of user cron table to backup file: - crontab_backup_fp = \"{crontab_backup_fp}\"''', + crontab_backup_fp = '{crontab_backup_fp}'""", verbose=VERBOSE, ) @@ -120,25 +120,25 @@ def add_crontab_line(): ) # Create backup - run_command(f'''printf "%s" '{crontab_contents}' > "{crontab_backup_fp}"''') + run_command(f"""printf "%s" '{crontab_contents}' > '{crontab_backup_fp}'""") # Add crontab line if CRONTAB_LINE in crontab_contents: log_info( - f''' + f""" The following line already exists in the cron table and thus will not be added: - CRONTAB_LINE = \"{CRONTAB_LINE}\"''' + CRONTAB_LINE = '{CRONTAB_LINE}'""" ) else: log_info( - f''' + f""" Adding the following line to the user's cron table in order to automatically resubmit SRW workflow: - CRONTAB_LINE = \"{CRONTAB_LINE}\"''', + CRONTAB_LINE = '{CRONTAB_LINE}'""", verbose=VERBOSE, ) @@ -173,11 +173,11 @@ def delete_crontab_line(called_from_cron): # Then record the results back into the user's cron table. # print_info_msg( - f''' + f""" Crontab contents before delete: ========================================================= {crontab_contents} - =========================================================''', + =========================================================""", verbose=True, ) @@ -189,11 +189,11 @@ def delete_crontab_line(called_from_cron): run_command(f"""echo '{crontab_contents}' | {crontab_cmd}""") print_info_msg( - f''' + f""" Crontab contents after delete: ========================================================= {crontab_contents} - =========================================================''', + =========================================================""", verbose=True, ) diff --git a/ush/link_fix.py b/ush/link_fix.py index 752fb7743f..5602d5170f 100755 --- a/ush/link_fix.py +++ b/ush/link_fix.py @@ -230,7 +230,7 @@ def link_fix(verbose, file_group): f""" The resolution could not be extracted from the current file's name. The full path to the file (fp) is: - fp = \"{fp}\" + fp = '{fp}' This may be because fp contains the * globbing character, which would imply that no files were found that match the globbing pattern specified in fp.""" @@ -243,8 +243,8 @@ def link_fix(verbose, file_group): f""" The resolutions (as obtained from the file names) of the previous and current file (fp_prev and fp, respectively) are different: - fp_prev = \"{fp_prev}\" - fp = \"{fp}\" + fp_prev = '{fp_prev}' + fp = '{fp}' Please ensure that all files have the same resolution.""" ) diff --git a/ush/machine/odin.yaml b/ush/machine/odin.yaml index 67a2fb49f1..38caa4bfc1 100644 --- a/ush/machine/odin.yaml +++ b/ush/machine/odin.yaml @@ -2,7 +2,7 @@ platform: WORKFLOW_MANAGER: rocoto NCORES_PER_NODE: 24 SCHED: slurm - DOMAIN_PREGEN_BASEDIR: /FV3LAM_pregen + DOMAIN_PREGEN_BASEDIR: /scratch/ywang/UFS_SRW_App/develop/FV3LAM_pregen PARTITION_DEFAULT: workq QUEUE_DEFAULT: workq PARTITION_FCST: workq diff --git a/ush/preamble.sh b/ush/preamble.sh index 0357ace76f..4c75665ed6 100644 --- a/ush/preamble.sh +++ b/ush/preamble.sh @@ -91,7 +91,7 @@ TRACE=${DEBUG:-"FALSE"} if [[ $STRICT == "TRUE" ]]; then # Exit on error and undefined variable - set -eu + set -euo pipefail fi if [[ $TRACE == "TRUE" ]]; then # Turn on debugging diff --git a/ush/python_utils/__init__.py b/ush/python_utils/__init__.py index add96ee981..02e2b83b77 100644 --- a/ush/python_utils/__init__.py +++ b/ush/python_utils/__init__.py @@ -1,7 +1,6 @@ from .misc import uppercase, lowercase, find_pattern_in_str, find_pattern_in_file from .check_for_preexist_dir_file import check_for_preexist_dir_file from .check_var_valid_value import check_var_valid_value -from .count_files import count_files from .create_symlink_to_file import create_symlink_to_file from .define_macos_utilities import define_macos_utilities from .environment import ( @@ -25,12 +24,9 @@ mkdir_vrfy, cd_vrfy, ) -from .get_elem_inds import get_elem_inds -from .interpol_to_arbit_CRES import interpol_to_arbit_CRES from .print_input_args import print_input_args from .print_msg import print_info_msg, print_err_msg_exit, log_info from .run_command import run_command -from .get_charvar_from_netcdf import get_charvar_from_netcdf from .xml_parser import load_xml_file, has_tag_with_value from .config_parser import ( load_json_config, diff --git a/ush/python_utils/check_for_preexist_dir_file.py b/ush/python_utils/check_for_preexist_dir_file.py index cfd4d50f43..39ad7f1706 100644 --- a/ush/python_utils/check_for_preexist_dir_file.py +++ b/ush/python_utils/check_for_preexist_dir_file.py @@ -7,6 +7,7 @@ from .filesys_cmds_vrfy import rm_vrfy, mv_vrfy from .print_msg import log_info + def check_for_preexist_dir_file(path, method): """Check for a preexisting directory or file and, if present, deal with it according to the specified method @@ -21,10 +22,12 @@ def check_for_preexist_dir_file(path, method): try: check_var_valid_value(method, ["delete", "rename", "quit"]) except ValueError: - errmsg = dedent(f''' - Invalid method for dealing with pre-existing directory specified - method = {method} - ''') + errmsg = dedent( + f""" + Invalid method for dealing with pre-existing directory specified + method = {method} + """ + ) raise ValueError(errmsg) from None if os.path.exists(path): @@ -43,8 +46,10 @@ def check_for_preexist_dir_file(path, method): ) mv_vrfy(path, new_path) else: - raise FileExistsError(dedent( - f""" + raise FileExistsError( + dedent( + f""" Specified directory or file already exists {path}""" - )) + ) + ) diff --git a/ush/python_utils/check_var_valid_value.py b/ush/python_utils/check_var_valid_value.py index a8b88e17a6..0c9bcc49c6 100644 --- a/ush/python_utils/check_var_valid_value.py +++ b/ush/python_utils/check_var_valid_value.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 + def check_var_valid_value(var, values): """Check if specified variable has a valid value diff --git a/ush/python_utils/config_parser.py b/ush/python_utils/config_parser.py index c1b69db5ff..e53b8cec1f 100644 --- a/ush/python_utils/config_parser.py +++ b/ush/python_utils/config_parser.py @@ -60,8 +60,8 @@ def increase_indent(self, flow=False, indentless=False): def str_presenter(dumper, data): if len(data.splitlines()) > 1: - return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|') - return dumper.represent_scalar('tag:yaml.org,2002:str', data) + return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|") + return dumper.represent_scalar("tag:yaml.org,2002:str", data) yaml.add_representer(str, str_presenter) @@ -214,10 +214,13 @@ def load_ini_config(config_file, return_string=0): """Load a config file with a format similar to Microsoft's INI files""" if not os.path.exists(config_file): - raise FileNotFoundError(dedent(f''' - The specified configuration file does not exist: - "{config_file}"''' - )) + raise FileNotFoundError( + dedent( + f""" + The specified configuration file does not exist: + '{config_file}'""" + ) + ) config = configparser.RawConfigParser() config.optionxform = str @@ -233,7 +236,7 @@ def get_ini_value(config, section, key): """Finds the value of a property in a given section""" if not section in config: - raise KeyError(f'Section not found: {section}') + raise KeyError(f"Section not found: {section}") else: return config[section][key] diff --git a/ush/python_utils/count_files.py b/ush/python_utils/count_files.py deleted file mode 100644 index 36862895b7..0000000000 --- a/ush/python_utils/count_files.py +++ /dev/null @@ -1,16 +0,0 @@ -import glob - - -def count_files(ext, dirct="."): - """Function that returns the number of files in the specified directory - ending with the specified file extension - - Args: - ext: File extension string - dir: Directory to parse (default is current directory) - Returns: - int: Number of files - """ - - files = glob.glob(dirct + "/*." + ext) - return len(files) diff --git a/ush/python_utils/create_symlink_to_file.py b/ush/python_utils/create_symlink_to_file.py index 3a3fddb08b..363a49fa40 100644 --- a/ush/python_utils/create_symlink_to_file.py +++ b/ush/python_utils/create_symlink_to_file.py @@ -22,26 +22,26 @@ def create_symlink_to_file(target, symlink, relative=True): if target is None: print_err_msg_exit( - f''' - The argument \"target\" specifying the target of the symbolic link that + f""" + The argument 'target' specifying the target of the symbolic link that this function will create was not specified in the call to this function: - target = \"{target}\"''' + target = '{target}'""" ) if symlink is None: print_err_msg_exit( - f''' - The argument \"symlink\" specifying the target of the symbolic link that + f""" + The argument 'symlink' specifying the target of the symbolic link that this function will create was not specified in the call to this function: - symlink = \"{symlink}\"''' + symlink = '{symlink}'""" ) if not os.path.exists(target): print_err_msg_exit( - f''' + f""" Cannot create symlink to specified target file because the latter does not exist or is not a file: - target = \"{target}\"''' + target = '{target}'""" ) relative_flag = "" diff --git a/ush/python_utils/filesys_cmds_vrfy.py b/ush/python_utils/filesys_cmds_vrfy.py index 7cae27b7d5..d99b97c7f2 100644 --- a/ush/python_utils/filesys_cmds_vrfy.py +++ b/ush/python_utils/filesys_cmds_vrfy.py @@ -17,7 +17,7 @@ def cmd_vrfy(cmd, *args): cmd += " " + " ".join([str(a) for a in args]) ret = os.system(cmd) if ret != 0: - print_err_msg_exit(f'System call "{cmd}" failed.') + print_err_msg_exit(f"System call '{cmd}' failed.") return ret diff --git a/ush/python_utils/get_charvar_from_netcdf.py b/ush/python_utils/get_charvar_from_netcdf.py deleted file mode 100644 index c5f642b03a..0000000000 --- a/ush/python_utils/get_charvar_from_netcdf.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 - -import os -from .print_msg import print_err_msg_exit -from .run_command import run_command - - -def get_charvar_from_netcdf(nc_file, nc_var_name): - """Searches NetCDF file and extract a scalar variable - - Args: - nc_file: Path to netCDF file - nc_var_name: name of the scalar variable - Returns: - value of the variable - """ - - SED = os.getenv("SED") - - cmd = f"ncdump -v {nc_var_name} {nc_file} | \ - {SED} -r -e '1,/data:/d' \ - -e '/^[ ]*'{nc_var_name}'/d' \ - -e '/^}}$/d' \ - -e 's/.*\"(.*)\".*/\\1/' \ - -e '/^$/d' \ - " - (ret, nc_var_value, _) = run_command(cmd) - - if ret != 0: - print_err_msg_exit( - f''' - Attempt to extract the value of the NetCDF variable spcecified by nc_var_name - from the file specified by nc_file failed: - nc_file = \"{nc_file}\" - nc_var_name = \"{nc_var_name}\"''' - ) - - if nc_var_value is None: - print_err_msg_exit( - f''' - In the specified NetCDF file (nc_file), the specified variable (nc_var_name) - was not found: - nc_file = \"{nc_file}\" - nc_var_name = \"{nc_var_name}\" - nc_var_value = \"{nc_var_value}\"''' - ) - - return nc_var_value diff --git a/ush/python_utils/get_elem_inds.py b/ush/python_utils/get_elem_inds.py deleted file mode 100644 index 20ac2e8967..0000000000 --- a/ush/python_utils/get_elem_inds.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -from .misc import lowercase -from .check_var_valid_value import check_var_valid_value - - -def get_elem_inds(arr, match, ret_type): - """Function that returns indices of elements of array - that match a given string - - Args: - arr: the list - match: element to match (case insenensitive) - ret_type: the return type can be any of [ 'first', 'last', 'all' ] - Returns: - A list of indices - """ - ret_type = lowercase(ret_type) - check_var_valid_value(ret_type, ["first", "last", "all"]) - - if ret_type == "first": - return arr.index(match) - if ret_type == "last": - for i in range(len(arr) - 1, -1, -1): - if arr[i] == match: - return i - return None - return [i for i, e in enumerate(arr) if e == match] diff --git a/ush/python_utils/interpol_to_arbit_CRES.py b/ush/python_utils/interpol_to_arbit_CRES.py deleted file mode 100644 index d87e258000..0000000000 --- a/ush/python_utils/interpol_to_arbit_CRES.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 - - -def interpol_to_arbit_CRES(RES, RES_array, prop_array): - """Function to interpolate (or extrapolate) a grid cell size-dependent property - to an arbitrary cubed-sphere resolution using arrays that specify a set of property - values for a corresponding set of resolutions - - Args: - RES: The cubed-sphere resolution at which to find the value of a property. - This is in units of number of cells (in either of the two horizontal - directions) on any one of the tiles of a cubed-sphere grid. - - RES_array: The name of the array containing the cubed-sphere resolutions for - which corresponding property values are given (in prop_array). These - are assumed to be given from smallest to largest. - - prop_array: The name of the array containing the values of the property corres- - ponding to the cubed-sphere resolutions in RES_array. - Returns: - Interpolated (extrapolated) property value - """ - - num_valid_RESes = len(RES_array) - i_min = 0 - i_max = num_valid_RESes - 1 - - if RES <= RES_array[i_min]: - prop = prop_array[i_min] - elif RES > RES_array[i_max]: - prop = prop_array[i_max] - else: - for i in range(0, num_valid_RESes - 1): - if RES_array[i] < RES <= RES_array[i + 1]: - RES1 = RES_array[i] - RES2 = RES_array[i + 1] - prop1 = prop_array[i] - prop2 = prop_array[i + 1] - m_slope = (prop2 - prop1) / (RES2 - RES1) - y_intcpt = (RES2 * prop1 - RES1 * prop2) / (RES2 - RES1) - prop = m_slope * RES + y_intcpt - - return prop diff --git a/ush/python_utils/print_input_args.py b/ush/python_utils/print_input_args.py index 3edcef3428..6d2a6ec2f1 100644 --- a/ush/python_utils/print_input_args.py +++ b/ush/python_utils/print_input_args.py @@ -33,23 +33,23 @@ def print_input_args(valid_args): if num_valid_args == 0: msg = dedent( - f''' + f""" No arguments have been passed to function {function} in script {filename_base} located - \"{filename}\"''' + '{filename}'""" ) else: msg = dedent( f""" The arguments to function {function} in script {filename_base} located - \"{filename}\" + '{filename}' have been set as follows:\n\n""" ) for k, v in valid_arg_names.items(): - msg = msg + f' {k}="{v}"\n' + msg = msg + f" {k}='{v}'\n" print_info_msg(msg, verbose=DEBUG) return num_valid_args diff --git a/ush/python_utils/print_msg.py b/ush/python_utils/print_msg.py index 8db0f06b03..078d708ba9 100644 --- a/ush/python_utils/print_msg.py +++ b/ush/python_utils/print_msg.py @@ -41,6 +41,7 @@ def print_info_msg(info_msg, verbose=True): return True return False + def log_info(info_msg, verbose=True, dedent_=True): """Function to print information message using the logging module. This function should not be used if python logging has not been initialized. @@ -54,11 +55,10 @@ def log_info(info_msg, verbose=True, dedent_=True): """ # "sys._getframe().f_back.f_code.co_name" returns the name of the calling function - logger=getLogger(sys._getframe().f_back.f_code.co_name) + logger = getLogger(sys._getframe().f_back.f_code.co_name) if verbose: if dedent_: - logger.info(indent(dedent(info_msg), ' ')) + logger.info(indent(dedent(info_msg), " ")) else: logger.info(info_msg) - diff --git a/ush/python_utils/test_python_utils.py b/ush/python_utils/test_python_utils.py index 7e25fdaf5b..69b6daf1a2 100644 --- a/ush/python_utils/test_python_utils.py +++ b/ush/python_utils/test_python_utils.py @@ -49,11 +49,6 @@ def test_check_for_preexist_dir_file(self): def test_check_var_valid_value(self): self.assertTrue(check_var_valid_value("rice", ["egg", "spam", "rice"])) - def test_count_files(self): - (_, target_cnt, _) = run_command("ls -l *.py | wc -l") - cnt = count_files("py") - self.assertEqual(cnt, int(target_cnt)) - def test_filesys_cmds(self): dPATH = f"{self.PATH}/test_data/dir" mkdir_vrfy(dPATH) @@ -63,27 +58,9 @@ def test_filesys_cmds(self): cmd_vrfy(f"rm -rf {dPATH}") self.assertFalse(os.path.exists("tt.py")) - def test_get_charvar_from_netcdf(self): - FILE = f"{self.PATH}/test_data/sample.nc" - val = get_charvar_from_netcdf(FILE, "pressure") - self.assertTrue(val and (val.split()[0], "955.5,")) - def test_run_command(self): self.assertEqual(run_command("echo hello"), (0, "hello", "")) - def test_get_elem_inds(self): - arr = ["egg", "spam", "egg", "rice", "egg"] - self.assertEqual(get_elem_inds(arr, "egg", "first"), 0) - self.assertEqual(get_elem_inds(arr, "egg", "last"), 4) - self.assertEqual(get_elem_inds(arr, "egg", "all"), [0, 2, 4]) - - def test_interpol_to_arbit_CRES(self): - RES = 800 - RES_array = [5, 25, 40, 60, 80, 100, 400, 700, 1000, 1500, 2800, 3000] - prop_array = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.65, 0.7, 1.0, 1.1, 1.2, 1.3] - prop = interpol_to_arbit_CRES(RES, RES_array, prop_array) - self.assertAlmostEqual(prop, 0.8) - def test_create_symlink_to_file(self): TARGET = f"{self.PATH}/test_python_utils.py" SYMLINK = f"{self.PATH}/test_data/test_python_utils.py" diff --git a/ush/retrieve_data.py b/ush/retrieve_data.py index 52f217bb85..2d7bcefa17 100755 --- a/ush/retrieve_data.py +++ b/ush/retrieve_data.py @@ -47,7 +47,7 @@ def clean_up_output_dir(expected_subdir, local_archive, output_path, source_path unavailable = {} # Check to make sure the files exist on disk for file_path in source_paths: - local_file_path = os.path.join( os.getcwd(), file_path.lstrip("/") ) + local_file_path = os.path.join(os.getcwd(), file_path.lstrip("/")) if not os.path.exists(local_file_path): logging.info(f"File does not exist: {local_file_path}") unavailable["hpss"] = source_paths @@ -493,7 +493,6 @@ def hpss_requested_files(cla, file_names, store_specs, members=-1, ens_group=-1) if isinstance(archive_internal_dirs, dict): archive_internal_dirs = archive_internal_dirs.get(cla.anl_or_fcst, [""]) - # which_archive matters for choosing the correct file names within, # but we can safely just try all options for the # archive_internal_dir diff --git a/ush/set_FV3nml_ens_stoch_seeds.py b/ush/set_FV3nml_ens_stoch_seeds.py index e285fc92ed..098aadc37f 100644 --- a/ush/set_FV3nml_ens_stoch_seeds.py +++ b/ush/set_FV3nml_ens_stoch_seeds.py @@ -101,10 +101,10 @@ def set_FV3nml_ens_stoch_seeds(cdate): print_info_msg( dedent( f""" - The variable \"settings\" specifying seeds in \"{FV3_NML_FP}\" - has been set as follows: + The variable 'settings' specifying seeds in '{FV3_NML_FP}' + has been set as follows: - settings =\n\n""" + settings =\n\n""" ) + settings_str, verbose=VERBOSE, @@ -118,15 +118,15 @@ def set_FV3nml_ens_stoch_seeds(cdate): print_err_msg_exit( dedent( f""" - Call to python script set_namelist.py to set the variables in the FV3 - namelist file that specify the paths to the surface climatology files - failed. Parameters passed to this script are: - Full path to base namelist file: - FV3_NML_FP = \"{FV3_NML_FP}\" - Full path to output namelist file: - fv3_nml_ensmem_fp = \"{fv3_nml_ensmem_fp}\" - Namelist settings specified on command line (these have highest precedence):\n - settings =\n\n""" + Call to python script set_namelist.py to set the variables in the FV3 + namelist file that specify the paths to the surface climatology files + failed. Parameters passed to this script are: + Full path to base namelist file: + FV3_NML_FP = '{FV3_NML_FP}' + Full path to output namelist file: + fv3_nml_ensmem_fp = '{fv3_nml_ensmem_fp}' + Namelist settings specified on command line (these have highest precedence):\n + settings =\n\n""" ) + settings_str ) @@ -181,11 +181,13 @@ def setUp(self): "-p", os.path.join( EXPTDIR, - f'{date_to_str(self.cdate,format="%Y%m%d%H")}{os.sep}mem{i+1}', + f"{date_to_str(self.cdate,format='%Y%m%d%H')}{os.sep}mem{i+1}", ), ) - cd_vrfy(f'{EXPTDIR}{os.sep}{date_to_str(self.cdate,format="%Y%m%d%H")}{os.sep}mem2') + cd_vrfy( + f"{EXPTDIR}{os.sep}{date_to_str(self.cdate,format='%Y%m%d%H')}{os.sep}mem2" + ) set_env_var("USHdir", USHdir) set_env_var("ENSMEM_INDX", 2) diff --git a/ush/set_FV3nml_sfc_climo_filenames.py b/ush/set_FV3nml_sfc_climo_filenames.py index e94ad5b183..4cad4dfff9 100644 --- a/ush/set_FV3nml_sfc_climo_filenames.py +++ b/ush/set_FV3nml_sfc_climo_filenames.py @@ -17,6 +17,7 @@ rm_vrfy, import_vars, set_env_var, + load_config_file, load_shell_config, flatten_dict, define_macos_utilities, @@ -46,6 +47,11 @@ def set_FV3nml_sfc_climo_filenames(): # import all environment variables import_vars() + # fixed file mapping variables + fixed_cfg = load_config_file(os.path.join(PARMdir, "fixed_files_mapping.yaml")) + IMPORTS = ["SFC_CLIMO_FIELDS", "FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING"] + import_vars(dictionary=flatten_dict(fixed_cfg), env_vars=IMPORTS) + # The regular expression regex_search set below will be used to extract # from the elements of the array FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING # the name of the namelist variable to set and the corresponding surface @@ -82,9 +88,9 @@ def set_FV3nml_sfc_climo_filenames(): print_info_msg( dedent( f""" - The variable \"settings\" specifying values of the namelist variables - has been set as follows:\n - settings =\n\n""" + The variable 'settings' specifying values of the namelist variables + has been set as follows:\n + settings =\n\n""" ) + settings_str, verbose=VERBOSE, @@ -102,15 +108,15 @@ def set_FV3nml_sfc_climo_filenames(): print_err_msg_exit( dedent( f""" - Call to python script set_namelist.py to set the variables in the FV3 - namelist file that specify the paths to the surface climatology files - failed. Parameters passed to this script are: - Full path to base namelist file: - fv3_nml_base_fp = \"{fv3_nml_base_fp}\" - Full path to output namelist file: - FV3_NML_FP = \"{FV3_NML_FP}\" - Namelist settings specified on command line (these have highest precedence):\n - settings =\n\n""" + Call to python script set_namelist.py to set the variables in the FV3 + namelist file that specify the paths to the surface climatology files + failed. Parameters passed to this script are: + Full path to base namelist file: + fv3_nml_base_fp = '{fv3_nml_base_fp}' + Full path to output namelist file: + FV3_NML_FP = '{FV3_NML_FP}' + Namelist settings specified on command line (these have highest precedence):\n + settings =\n\n""" ) + settings_str ) @@ -159,38 +165,10 @@ def setUp(self): os.path.join(PARMdir, "input.nml.FV3"), os.path.join(EXPTDIR, "input.nml"), ) - set_env_var("USHdir", USHdir) + set_env_var("PARMdir", PARMdir) set_env_var("EXPTDIR", EXPTDIR) set_env_var("FIXlam", FIXlam) set_env_var("DO_ENSEMBLE", False) set_env_var("CRES", "C3357") set_env_var("RUN_ENVIR", "nco") set_env_var("FV3_NML_FP", os.path.join(EXPTDIR, "input.nml")) - - FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING = [ - "FNALBC | snowfree_albedo", - "FNALBC2 | facsf", - "FNTG3C | substrate_temperature", - "FNVEGC | vegetation_greenness", - "FNVETC | vegetation_type", - "FNSOTC | soil_type", - "FNVMNC | vegetation_greenness", - "FNVMXC | vegetation_greenness", - "FNSLPC | slope_type", - "FNABSC | maximum_snow_albedo", - ] - SFC_CLIMO_FIELDS = [ - "facsf", - "maximum_snow_albedo", - "slope_type", - "snowfree_albedo", - "soil_type", - "substrate_temperature", - "vegetation_greenness", - "vegetation_type", - ] - set_env_var( - "FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING", - FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING, - ) - set_env_var("SFC_CLIMO_FIELDS", SFC_CLIMO_FIELDS) diff --git a/ush/set_cycle_dates.py b/ush/set_cycle_dates.py index 09adf55e88..069a3891b1 100644 --- a/ush/set_cycle_dates.py +++ b/ush/set_cycle_dates.py @@ -43,6 +43,13 @@ def test_set_cycle_dates(self): incr_cycl_freq=6, ) self.assertEqual( - cdates, ["2022010106", "2022010112", "2022010118", - "2022010200", "2022010206", "2022010212"] + cdates, + [ + "2022010106", + "2022010112", + "2022010118", + "2022010200", + "2022010206", + "2022010212", + ], ) diff --git a/ush/set_extrn_mdl_params.py b/ush/set_extrn_mdl_params.py deleted file mode 100644 index 7d52055031..0000000000 --- a/ush/set_extrn_mdl_params.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python3 - -import unittest - -from python_utils import import_vars, export_vars, set_env_var, get_env_var - - -def set_extrn_mdl_params(): - """Sets parameters associated with the external model used for initial - conditions (ICs) and lateral boundary conditions (LBCs). - Args: - None - Returns: - None - """ - - # import all env variables - import_vars() - - global EXTRN_MDL_LBCS_OFFSET_HRS - - # - # ----------------------------------------------------------------------- - # - # Set EXTRN_MDL_LBCS_OFFSET_HRS, which is the number of hours to shift - # the starting time of the external model that provides lateral boundary - # conditions. - # - # ----------------------------------------------------------------------- - # - if EXTRN_MDL_NAME_LBCS == "RAP": - EXTRN_MDL_LBCS_OFFSET_HRS = EXTRN_MDL_LBCS_OFFSET_HRS or "3" - else: - EXTRN_MDL_LBCS_OFFSET_HRS = EXTRN_MDL_LBCS_OFFSET_HRS or "0" - - # export values we set above - env_vars = ["EXTRN_MDL_LBCS_OFFSET_HRS"] - export_vars(env_vars=env_vars) - - -class Testing(unittest.TestCase): - def test_extrn_mdl_params(self): - set_extrn_mdl_params() - EXTRN_MDL_LBCS_OFFSET_HRS = get_env_var("EXTRN_MDL_LBCS_OFFSET_HRS") - self.assertEqual(EXTRN_MDL_LBCS_OFFSET_HRS, 3) - - def setUp(self): - set_env_var("EXTRN_MDL_NAME_LBCS", "RAP") - set_env_var("EXTRN_MDL_LBCS_OFFSET_HRS", None) diff --git a/ush/set_gridparams_ESGgrid.py b/ush/set_gridparams_ESGgrid.py index ce8cd02ffe..dc2269b2ce 100644 --- a/ush/set_gridparams_ESGgrid.py +++ b/ush/set_gridparams_ESGgrid.py @@ -5,11 +5,11 @@ from datetime import datetime, timedelta from python_utils import ( - import_vars, - set_env_var, - print_input_args, - load_config_file, - flatten_dict, + import_vars, + set_env_var, + print_input_args, + load_config_file, + flatten_dict, ) @@ -35,7 +35,7 @@ def set_gridparams_ESGgrid(lon_ctr, lat_ctr, nx, ny, halo_width, delx, dely, paz # get constants IMPORTS = ["RADIUS_EARTH", "DEGS_PER_RADIAN"] USHdir = os.path.dirname(os.path.abspath(__file__)) - constants_cfg = load_config_file(os.path.join(USHdir,"constants.yaml")) + constants_cfg = load_config_file(os.path.join(USHdir, "constants.yaml")) import_vars(dictionary=flatten_dict(constants_cfg), env_vars=IMPORTS) # diff --git a/ush/set_gridparams_GFDLgrid.py b/ush/set_gridparams_GFDLgrid.py index 47253a1c73..70a309c3fd 100644 --- a/ush/set_gridparams_GFDLgrid.py +++ b/ush/set_gridparams_GFDLgrid.py @@ -63,7 +63,7 @@ def set_gridparams_GFDLgrid( import_vars(env_vars=IMPORTS) IMPORTS = ["NH4"] USHdir = os.path.dirname(os.path.abspath(__file__)) - constants_cfg = load_config_file(os.path.join(USHdir,"constants.yaml")) + constants_cfg = load_config_file(os.path.join(USHdir, "constants.yaml")) import_vars(dictionary=flatten_dict(constants_cfg), env_vars=IMPORTS) # diff --git a/ush/set_ozone_param.py b/ush/set_ozone_param.py index 5ed4449fe1..28f6e1ef68 100644 --- a/ush/set_ozone_param.py +++ b/ush/set_ozone_param.py @@ -17,7 +17,13 @@ find_pattern_in_str, ) -def set_ozone_param(ccpp_phys_suite_fp): + +def set_ozone_param( + ccpp_phys_suite_fp, + CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, + FIXgsm_FILES_TO_COPY_TO_FIXam, + VERBOSE, +): """Function that does the following: (1) Determines the ozone parameterization being used by checking in the CCPP physics suite XML. @@ -41,15 +47,14 @@ def set_ozone_param(ccpp_phys_suite_fp): Args: ccpp_phys_suite_fp: full path to CCPP physics suite + CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING + FIXgsm_FILES_TO_COPY_TO_FIXam Returns: ozone_param: a string """ print_input_args(locals()) - # import all environment variables - import_vars() - # # ----------------------------------------------------------------------- # @@ -90,8 +95,10 @@ def set_ozone_param(ccpp_phys_suite_fp): fixgsm_ozone_fn = "global_o3prdlos.f77" ozone_param = "ozphys" else: - raise KeyError(f'Unknown or no ozone parameterization specified in the ' - 'CCPP physics suite file "{ccpp_phys_suite_fp}"') + raise KeyError( + f"Unknown or no ozone parameterization specified in the " + "CCPP physics suite file '{ccpp_phys_suite_fp}'" + ) # # ----------------------------------------------------------------------- # @@ -151,24 +158,27 @@ def set_ozone_param(ccpp_phys_suite_fp): CCPP suite definition file), the array specifying the mapping between the symlinks that need to be created in the cycle directories and the files in the FIXam directory is: - """, verbose=VERBOSE) - log_info(f""" + """, + verbose=VERBOSE, + ) + log_info( + f""" CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING = {list_to_str(CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING)} - """, verbose=VERBOSE, dedent_=False) + """, + verbose=VERBOSE, + dedent_=False, + ) else: raise Exception( - f''' + f""" Unable to set name of the ozone production/loss file in the FIXgsm directory in the array that specifies the mapping between the symlinks that need to be created in the cycle directories and the files in the FIXgsm directory: - fixgsm_ozone_fn_is_set = \"{fixgsm_ozone_fn_is_set}\"''' + fixgsm_ozone_fn_is_set = '{fixgsm_ozone_fn_is_set}'""" ) - EXPORTS = ["CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING", "FIXgsm_FILES_TO_COPY_TO_FIXam"] - export_vars(env_vars=EXPORTS) - return ozone_param @@ -178,15 +188,15 @@ def test_set_ozone_param(self): self.assertEqual( "ozphys_2015", set_ozone_param( - ccpp_phys_suite_fp=f"{USHdir}{os.sep}test_data{os.sep}suite_FV3_GSD_SAR.xml" + f"{USHdir}{os.sep}test_data{os.sep}suite_FV3_GSD_SAR.xml", + CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, + FIXgsm_FILES_TO_COPY_TO_FIXam, + VERBOSE=True, ), ) def setUp(self): - define_macos_utilities() - set_env_var("DEBUG", True) - set_env_var("VERBOSE", True) - + global CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING = [ "aerosol.dat | global_climaeropac_global.txt", "co2historicaldata_2010.txt | fix_co2_proj/global_co2historicaldata_2010.txt", @@ -209,6 +219,7 @@ def setUp(self): "solarconstant_noaa_an.txt | global_solarconstant_noaa_an.txt", "global_o3prdlos.f77 | ozprdlos_2015_new_sbuvO3_tclm15_nuchem.f77", ] + global FIXgsm_FILES_TO_COPY_TO_FIXam FIXgsm_FILES_TO_COPY_TO_FIXam = [ "global_glacier.2x2.grb", "global_maxice.2x2.grb", @@ -241,9 +252,3 @@ def setUp(self): "HGT.Beljaars_filtered.lat-lon.30s_res.nc", "ozprdlos_2015_new_sbuvO3_tclm15_nuchem.f77", ] - - set_env_var( - "CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING", - CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, - ) - set_env_var("FIXgsm_FILES_TO_COPY_TO_FIXam", FIXgsm_FILES_TO_COPY_TO_FIXam) diff --git a/ush/set_predef_grid_params.py b/ush/set_predef_grid_params.py index 6b432b8f03..faf8c75c58 100644 --- a/ush/set_predef_grid_params.py +++ b/ush/set_predef_grid_params.py @@ -41,12 +41,13 @@ def set_predef_grid_params(): try: params_dict = params_dict[PREDEF_GRID_NAME] except KeyError: - errmsg = dedent(f''' - PREDEF_GRID_NAME = {PREDEF_GRID_NAME} not found in predef_grid_params.yaml - Check your config file settings.''') + errmsg = dedent( + f""" + PREDEF_GRID_NAME = {PREDEF_GRID_NAME} not found in predef_grid_params.yaml + Check your config file settings.""" + ) raise Exception(errmsg) from None - # if QUILTING = False, remove key if not QUILTING: params_dict.pop("QUILTING") diff --git a/ush/set_thompson_mp_fix_files.py b/ush/set_thompson_mp_fix_files.py index 93dc3c5de6..df69c2b232 100644 --- a/ush/set_thompson_mp_fix_files.py +++ b/ush/set_thompson_mp_fix_files.py @@ -17,7 +17,12 @@ ) -def set_thompson_mp_fix_files(ccpp_phys_suite_fp, thompson_mp_climo_fn): +def set_thompson_mp_fix_files( + ccpp_phys_suite_fp, + thompson_mp_climo_fn, + CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, + FIXgsm_FILES_TO_COPY_TO_FIXam, +): """Function that first checks whether the Thompson microphysics parameterization is being called by the selected physics suite. If not, it sets the output variable whose name is specified by @@ -31,14 +36,17 @@ def set_thompson_mp_fix_files(ccpp_phys_suite_fp, thompson_mp_climo_fn): Args: ccpp_phys_suite_fp: full path to CCPP physics suite thompson_mp_climo_fn: netcdf file for thompson microphysics + CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING + FIXgsm_FILES_TO_COPY_TO_FIXam Returns: boolean: sdf_uses_thompson_mp """ print_input_args(locals()) - # import all environment variables - import_vars() + # import some environment variables + IMPORTS = ["EXTRN_MDL_NAME_ICS", "EXTRN_MDL_NAME_LBCS", "CCPP_PHYS_SUITE"] + import_vars(env_vars=IMPORTS) # # ----------------------------------------------------------------------- @@ -99,7 +107,7 @@ def set_thompson_mp_fix_files(ccpp_phys_suite_fp, thompson_mp_climo_fn): CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING. After these modifications, the values of these parameters are as follows: - CCPP_PHYS_SUITE = \"{CCPP_PHYS_SUITE}\" + CCPP_PHYS_SUITE = '{CCPP_PHYS_SUITE}' """ ) log_info( @@ -113,12 +121,6 @@ def set_thompson_mp_fix_files(ccpp_phys_suite_fp, thompson_mp_climo_fn): """ ) - EXPORTS = [ - "CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING", - "FIXgsm_FILES_TO_COPY_TO_FIXam", - ] - export_vars(env_vars=EXPORTS) - return sdf_uses_thompson_mp @@ -128,19 +130,19 @@ def test_set_thompson_mp_fix_files(self): self.assertEqual( True, set_thompson_mp_fix_files( - ccpp_phys_suite_fp=f"{USHdir}{os.sep}test_data{os.sep}suite_FV3_GSD_SAR.xml", - thompson_mp_climo_fn="Thompson_MP_MONTHLY_CLIMO.nc", + f"{USHdir}{os.sep}test_data{os.sep}suite_FV3_GSD_SAR.xml", + "Thompson_MP_MONTHLY_CLIMO.nc", + CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, + FIXgsm_FILES_TO_COPY_TO_FIXam, ), ) def setUp(self): - define_macos_utilities() - set_env_var("DEBUG", True) - set_env_var("VERBOSE", True) set_env_var("EXTRN_MDL_NAME_ICS", "FV3GFS") set_env_var("EXTRN_MDL_NAME_LBCS", "FV3GFS") set_env_var("CCPP_PHYS_SUITE", "FV3_GSD_SAR") + global CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING = [ "aerosol.dat | global_climaeropac_global.txt", "co2historicaldata_2010.txt | fix_co2_proj/global_co2historicaldata_2010.txt", @@ -164,6 +166,7 @@ def setUp(self): "global_o3prdlos.f77 | ozprdlos_2015_new_sbuvO3_tclm15_nuchem.f77", ] + global FIXgsm_FILES_TO_COPY_TO_FIXam FIXgsm_FILES_TO_COPY_TO_FIXam = [ "global_glacier.2x2.grb", "global_maxice.2x2.grb", @@ -196,9 +199,3 @@ def setUp(self): "HGT.Beljaars_filtered.lat-lon.30s_res.nc", "ozprdlos_2015_new_sbuvO3_tclm15_nuchem.f77", ] - - set_env_var( - "CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING", - CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, - ) - set_env_var("FIXgsm_FILES_TO_COPY_TO_FIXam", FIXgsm_FILES_TO_COPY_TO_FIXam) diff --git a/ush/setup.py b/ush/setup.py index 3fa7313727..1bdf2453a8 100644 --- a/ush/setup.py +++ b/ush/setup.py @@ -32,7 +32,6 @@ from set_cycle_dates import set_cycle_dates from set_predef_grid_params import set_predef_grid_params from set_ozone_param import set_ozone_param -from set_extrn_mdl_params import set_extrn_mdl_params from set_gridparams_ESGgrid import set_gridparams_ESGgrid from set_gridparams_GFDLgrid import set_gridparams_GFDLgrid from link_fix import link_fix @@ -69,7 +68,7 @@ def setup(): log_info( f""" ======================================================================== - Starting function setup() in \"{os.path.basename(__file__)}\"... + Starting function setup() in '{os.path.basename(__file__)}'... ========================================================================""" ) # @@ -83,42 +82,64 @@ def setup(): # EXPT_DEFAULT_CONFIG_FN = "config_defaults.yaml" cfg_d = load_config_file(os.path.join(USHdir, EXPT_DEFAULT_CONFIG_FN)) - import_vars(dictionary=flatten_dict(cfg_d), - env_vars=["EXPT_CONFIG_FN", - "EXTRN_MDL_NAME_ICS", "EXTRN_MDL_NAME_LBCS", - "FV3GFS_FILE_FMT_ICS", "FV3GFS_FILE_FMT_LBCS"]) - + import_vars( + dictionary=flatten_dict(cfg_d), + env_vars=[ + "EXPT_CONFIG_FN", + "EXTRN_MDL_NAME_ICS", + "EXTRN_MDL_NAME_LBCS", + "FV3GFS_FILE_FMT_ICS", + "FV3GFS_FILE_FMT_LBCS", + ], + ) # Load the user config file, then ensure all user-specified - # variables correspond to a default value. + # variables correspond to a default value. if not os.path.exists(EXPT_CONFIG_FN): - raise FileNotFoundError(f'User config file not found: EXPT_CONFIG_FN = {EXPT_CONFIG_FN}') + raise FileNotFoundError( + f"User config file not found: EXPT_CONFIG_FN = {EXPT_CONFIG_FN}" + ) try: cfg_u = load_config_file(os.path.join(USHdir, EXPT_CONFIG_FN)) except: - errmsg = dedent(f'''\n - Could not load YAML config file: {EXPT_CONFIG_FN} - Reference the above traceback for more information. - ''') + errmsg = dedent( + f"""\n + Could not load YAML config file: {EXPT_CONFIG_FN} + Reference the above traceback for more information. + """ + ) raise Exception(errmsg) cfg_u = flatten_dict(cfg_u) for key in cfg_u: if key not in flatten_dict(cfg_d): - raise Exception(dedent(f''' - User-specified variable "{key}" in {EXPT_CONFIG_FN} is not valid. - Check {EXPT_DEFAULT_CONFIG_FN} for allowed user-specified variables.\n''')) + raise Exception( + dedent( + f""" + User-specified variable "{key}" in {EXPT_CONFIG_FN} is not valid. + Check {EXPT_DEFAULT_CONFIG_FN} for allowed user-specified variables.\n""" + ) + ) # Mandatory variables *must* be set in the user's config; the default value is invalid - mandatory = ['MACHINE'] + mandatory = ["MACHINE"] for val in mandatory: if val not in cfg_u: - raise Exception(f'Mandatory variable "{val}" not found in user config file {EXPT_CONFIG_FN}') + raise Exception( + f"Mandatory variable '{val}' not found in user config file {EXPT_CONFIG_FN}" + ) - import_vars(dictionary=cfg_u, env_vars=["MACHINE", - "EXTRN_MDL_NAME_ICS", "EXTRN_MDL_NAME_LBCS", - "FV3GFS_FILE_FMT_ICS", "FV3GFS_FILE_FMT_LBCS"]) + import_vars( + dictionary=cfg_u, + env_vars=[ + "MACHINE", + "EXTRN_MDL_NAME_ICS", + "EXTRN_MDL_NAME_LBCS", + "FV3GFS_FILE_FMT_ICS", + "FV3GFS_FILE_FMT_LBCS", + ], + ) # # ----------------------------------------------------------------------- # @@ -131,23 +152,25 @@ def setup(): global MACHINE, EXTRN_MDL_SYSBASEDIR_ICS, EXTRN_MDL_SYSBASEDIR_LBCS MACHINE_FILE = os.path.join(USHdir, "machine", f"{lowercase(MACHINE)}.yaml") if not os.path.exists(MACHINE_FILE): - raise FileNotFoundError(dedent( - f""" - The machine file {MACHINE_FILE} does not exist. - Check that you have specified the correct machine ({MACHINE}) in your config file {EXPT_CONFIG_FN}""" - )) + raise FileNotFoundError( + dedent( + f""" + The machine file {MACHINE_FILE} does not exist. + Check that you have specified the correct machine ({MACHINE}) in your config file {EXPT_CONFIG_FN}""" + ) + ) machine_cfg = load_config_file(MACHINE_FILE) # ics and lbcs - def get_location(xcs,fmt): - if ("data" in machine_cfg) and (xcs in machine_cfg["data"]): - v = machine_cfg["data"][xcs] - if not isinstance(v,dict): - return v - else: - return v[fmt] - else: - return "" + def get_location(xcs, fmt): + if ("data" in machine_cfg) and (xcs in machine_cfg["data"]): + v = machine_cfg["data"][xcs] + if not isinstance(v, dict): + return v + else: + return v[fmt] + else: + return "" EXTRN_MDL_SYSBASEDIR_ICS = get_location(EXTRN_MDL_NAME_ICS, FV3GFS_FILE_FMT_ICS) EXTRN_MDL_SYSBASEDIR_LBCS = get_location(EXTRN_MDL_NAME_LBCS, FV3GFS_FILE_FMT_LBCS) @@ -155,10 +178,12 @@ def get_location(xcs,fmt): # remove the data key and provide machine specific default values for cfg_d if "data" in machine_cfg: machine_cfg.pop("data") - machine_cfg.update({ - "EXTRN_MDL_SYSBASEDIR_ICS": EXTRN_MDL_SYSBASEDIR_ICS, - "EXTRN_MDL_SYSBASEDIR_LBCS": EXTRN_MDL_SYSBASEDIR_LBCS, - }) + machine_cfg.update( + { + "EXTRN_MDL_SYSBASEDIR_ICS": EXTRN_MDL_SYSBASEDIR_ICS, + "EXTRN_MDL_SYSBASEDIR_LBCS": EXTRN_MDL_SYSBASEDIR_LBCS, + } + ) machine_cfg = flatten_dict(machine_cfg) update_dict(machine_cfg, cfg_d) @@ -180,6 +205,12 @@ def get_location(xcs,fmt): # make machine name uppercase MACHINE = uppercase(MACHINE) + # Load fixed-files mapping file + cfg_f = load_config_file( + os.path.join(USHdir, os.pardir, "parm", "fixed_files_mapping.yaml") + ) + import_vars(dictionary=flatten_dict(cfg_f)) + # Load constants file and save its contents to a variable for later cfg_c = load_config_file(os.path.join(USHdir, CONSTANTS_FN)) import_vars(dictionary=flatten_dict(cfg_c)) @@ -194,6 +225,7 @@ def get_location(xcs,fmt): # global WORKFLOW_ID WORKFLOW_ID = "id_" + str(int(datetime.datetime.now().timestamp())) + cfg_d["workflow"]["WORKFLOW_ID"] = WORKFLOW_ID log_info(f"""WORKFLOW ID = {WORKFLOW_ID}""") # @@ -223,7 +255,7 @@ def get_location(xcs,fmt): if DEBUG and not VERBOSE: log_info( """ - Resetting VERBOSE to \"TRUE\" because DEBUG has been set to \"TRUE\"...""" + Resetting VERBOSE to 'TRUE' because DEBUG has been set to 'TRUE'...""" ) VERBOSE = True @@ -303,7 +335,7 @@ def get_location(xcs,fmt): or (len(ISEED_SPP) != N_VAR_SPP) ): raise Exception( - f''' + f""" All MYNN PBL, MYNN SFC, GSL GWD, Thompson MP, or RRTMG SPP-related namelist variables set in {EXPT_CONFIG_FN} must be equal in number of entries to what is found in SPP_VAR_LIST: @@ -315,7 +347,7 @@ def get_location(xcs,fmt): SPP_SIGTOP2 (length {len(SPP_SIGTOP2)}) SPP_STDDEV_CUTOFF (length {len(SPP_STDDEV_CUTOFF)}) ISEED_SPP (length {len(ISEED_SPP)}) - ''' + """ ) # # ----------------------------------------------------------------------- @@ -333,7 +365,7 @@ def get_location(xcs,fmt): or (len(LSM_SPP_TSCALE) != N_VAR_LNDP) ): raise Exception( - f''' + f""" All Noah or RUC-LSM SPP-related namelist variables (except ISEED_LSM_SPP) set in {EXPT_CONFIG_FN} must be equal in number of entries to what is found in SPP_VAR_LIST: @@ -341,16 +373,14 @@ def get_location(xcs,fmt): LSM_SPP_MAG_LIST (length {len(LSM_SPP_MAG_LIST)}) LSM_SPP_LSCALE (length {len(LSM_SPP_LSCALE)}) LSM_SPP_TSCALE (length {len(LSM_SPP_TSCALE)}) - ''' + """ ) # # The current script should be located in the ush subdirectory of the # workflow directory. Thus, the workflow directory is the one above the # directory of the current script. # - HOMEdir = os.path.abspath( - os.path.dirname(__file__) + os.sep + os.pardir - ) + HOMEdir = os.path.abspath(os.path.dirname(__file__) + os.sep + os.pardir) # # ----------------------------------------------------------------------- @@ -381,22 +411,25 @@ def get_location(xcs,fmt): try: UFS_WTHR_MDL_DIR = get_ini_value(cfg, external_name, property_name) except KeyError: - errmsg = dedent(f''' - Externals configuration file {mng_extrns_cfg_fn} - does not contain "{external_name}".''') + errmsg = dedent( + f""" + Externals configuration file {mng_extrns_cfg_fn} + does not contain '{external_name}'.""" + ) raise Exception(errmsg) from None - UFS_WTHR_MDL_DIR = os.path.join(HOMEdir, UFS_WTHR_MDL_DIR) if not os.path.exists(UFS_WTHR_MDL_DIR): - raise FileNotFoundError(dedent( - f""" - The base directory in which the FV3 source code should be located - (UFS_WTHR_MDL_DIR) does not exist: - UFS_WTHR_MDL_DIR = \"{UFS_WTHR_MDL_DIR}\" - Please clone the external repository containing the code in this directory, - build the executable, and then rerun the workflow.""" - )) + raise FileNotFoundError( + dedent( + f""" + The base directory in which the FV3 source code should be located + (UFS_WTHR_MDL_DIR) does not exist: + UFS_WTHR_MDL_DIR = '{UFS_WTHR_MDL_DIR}' + Please clone the external repository containing the code in this directory, + build the executable, and then rerun the workflow.""" + ) + ) # # Define some other useful paths # @@ -428,17 +461,28 @@ def get_location(xcs,fmt): RELATIVE_LINK_FLAG = "--relative" # Mandatory variables *must* be set in the user's config or the machine file; the default value is invalid - mandatory = ['NCORES_PER_NODE', 'FIXgsm', 'FIXaer', 'FIXlut', 'TOPO_DIR', 'SFC_CLIMO_INPUT_DIR'] + mandatory = [ + "NCORES_PER_NODE", + "FIXgsm", + "FIXaer", + "FIXlut", + "TOPO_DIR", + "SFC_CLIMO_INPUT_DIR", + ] globalvars = globals() for val in mandatory: # globals() returns dictionary of global variables if not globalvars[val]: - raise Exception(dedent(f''' - Mandatory variable "{val}" not found in: - user config file {EXPT_CONFIG_FN} - OR - machine file {MACHINE_FILE} - ''')) + raise Exception( + dedent( + f""" + Mandatory variable '{val}' not found in: + user config file {EXPT_CONFIG_FN} + OR + machine file {MACHINE_FILE} + """ + ) + ) # # ----------------------------------------------------------------------- @@ -478,10 +522,13 @@ def get_location(xcs,fmt): # if WORKFLOW_MANAGER is not None: if not ACCOUNT: - raise Exception(dedent(f''' - ACCOUNT must be specified in config or machine file if using a workflow manager. - WORKFLOW_MANAGER = {WORKFLOW_MANAGER}\n''' - )) + raise Exception( + dedent( + f""" + ACCOUNT must be specified in config or machine file if using a workflow manager. + WORKFLOW_MANAGER = {WORKFLOW_MANAGER}\n""" + ) + ) # # ----------------------------------------------------------------------- # @@ -516,57 +563,67 @@ def get_location(xcs,fmt): CPL = True else: raise Exception( - f''' + f""" The coupling flag CPL has not been specified for this value of FCST_MODEL: - FCST_MODEL = \"{FCST_MODEL}\"''' + FCST_MODEL = '{FCST_MODEL}'""" ) # Make sure RESTART_INTERVAL is set to an integer value if not isinstance(RESTART_INTERVAL, int): - raise Exception(f"\nRESTART_INTERVAL = {RESTART_INTERVAL}, must be an integer value\n") + raise Exception( + f"\nRESTART_INTERVAL = {RESTART_INTERVAL}, must be an integer value\n" + ) # Check that input dates are in a date format # get dictionary of all variables allvars = dict(globals()) allvars.update(locals()) - dates = ['DATE_FIRST_CYCL', 'DATE_LAST_CYCL'] + dates = ["DATE_FIRST_CYCL", "DATE_LAST_CYCL"] for val in dates: if not isinstance(allvars[val], datetime.date): - raise Exception(dedent(f''' - Date variable {val}={allvars[val]} is not in a valid date format + raise Exception( + dedent( + f""" + Date variable {val}={allvars[val]} is not in a valid date format - For examples of valid formats, see the users guide. - ''')) + For examples of valid formats, see the users guide. + """ + ) + ) # If using a custom post configuration file, make sure that it exists. if USE_CUSTOM_POST_CONFIG_FILE: try: - #os.path.exists returns exception if passed an empty string or None, so use "try/except" as a 2-for-1 error catch + # os.path.exists returns exception if passed an empty string or None, so use "try/except" as a 2-for-1 error catch if not os.path.exists(CUSTOM_POST_CONFIG_FP): raise except: - raise FileNotFoundError(dedent( - f''' - USE_CUSTOM_POST_CONFIG_FILE has been set, but the custom post configuration file - CUSTOM_POST_CONFIG_FP = {CUSTOM_POST_CONFIG_FP} - could not be found.''' - )) from None + raise FileNotFoundError( + dedent( + f""" + USE_CUSTOM_POST_CONFIG_FILE has been set, but the custom post configuration file + CUSTOM_POST_CONFIG_FP = {CUSTOM_POST_CONFIG_FP} + could not be found.""" + ) + ) from None # If using external CRTM fix files to allow post-processing of synthetic # satellite products from the UPP, make sure the CRTM fix file directory exists. if USE_CRTM: try: - #os.path.exists returns exception if passed an empty string or None, so use "try/except" as a 2-for-1 error catch + # os.path.exists returns exception if passed an empty string or None, so use "try/except" as a 2-for-1 error catch if not os.path.exists(CRTM_DIR): raise except: - raise FileNotFoundError(dedent( - f''' - USE_CRTM has been set, but the external CRTM fix file directory: - CRTM_DIR = {CRTM_DIR} - could not be found.''' - )) from None + raise FileNotFoundError( + dedent( + f""" + USE_CRTM has been set, but the external CRTM fix file directory: + CRTM_DIR = {CRTM_DIR} + could not be found.""" + ) + ) from None # The forecast length (in integer hours) cannot contain more than 3 characters. # Thus, its maximum value is 999. @@ -582,7 +639,7 @@ def get_location(xcs,fmt): # ----------------------------------------------------------------------- # # Check whether the forecast length (FCST_LEN_HRS) is evenly divisible - # by the BC update interval (LBC_SPEC_INTVL_HRS). If so, generate an + # by the BC update interval (LBC_SPEC_INTVL_HRS). If so, generate an # array of forecast hours at which the boundary values will be updated. # # ----------------------------------------------------------------------- @@ -614,6 +671,7 @@ def get_location(xcs,fmt): LBC_SPEC_INTVL_HRS, LBC_SPEC_INTVL_HRS + FCST_LEN_HRS, LBC_SPEC_INTVL_HRS ) ] + cfg_d["task_make_lbcs"]["LBC_SPEC_FCST_HRS"] = LBC_SPEC_FCST_HRS # # ----------------------------------------------------------------------- # @@ -627,11 +685,7 @@ def get_location(xcs,fmt): # get dictionary of all variables allvars = dict(globals()) allvars.update(locals()) - vlist = ['DT_ATMOS', - 'LAYOUT_X', - 'LAYOUT_Y', - 'BLOCKSIZE', - 'EXPT_SUBDIR'] + vlist = ["DT_ATMOS", "LAYOUT_X", "LAYOUT_Y", "BLOCKSIZE", "EXPT_SUBDIR"] for val in vlist: if not allvars[val]: raise Exception(f"\nMandatory variable '{val}' has not been set\n") @@ -653,12 +707,12 @@ def get_location(xcs,fmt): # if DT_SUBHOURLY_POST_MNTS < 0 or DT_SUBHOURLY_POST_MNTS > 59: raise ValueError( - f''' - When performing sub-hourly post (i.e. SUB_HOURLY_POST set to \"TRUE\"), + f""" + When performing sub-hourly post (i.e. SUB_HOURLY_POST set to 'TRUE'), DT_SUBHOURLY_POST_MNTS must be set to an integer between 0 and 59, inclusive but in this case is not: - SUB_HOURLY_POST = \"{SUB_HOURLY_POST}\" - DT_SUBHOURLY_POST_MNTS = \"{DT_SUBHOURLY_POST_MNTS}\"''' + SUB_HOURLY_POST = '{SUB_HOURLY_POST}' + DT_SUBHOURLY_POST_MNTS = '{DT_SUBHOURLY_POST_MNTS}'""" ) # # Check that DT_SUBHOURLY_POST_MNTS (after converting to seconds) is @@ -668,14 +722,14 @@ def get_location(xcs,fmt): if rem != 0: raise ValueError( f""" - When performing sub-hourly post (i.e. SUB_HOURLY_POST set to \"TRUE\"), + When performing sub-hourly post (i.e. SUB_HOURLY_POST set to 'TRUE'), the time interval specified by DT_SUBHOURLY_POST_MNTS (after converting to seconds) must be evenly divisible by the time step DT_ATMOS used in the forecast model, i.e. the remainder (rem) must be zero. In this case, it is not: - SUB_HOURLY_POST = \"{SUB_HOURLY_POST}\" - DT_SUBHOURLY_POST_MNTS = \"{DT_SUBHOURLY_POST_MNTS}\" - DT_ATMOS = \"{DT_ATMOS}\" + SUB_HOURLY_POST = '{SUB_HOURLY_POST}' + DT_SUBHOURLY_POST_MNTS = '{DT_SUBHOURLY_POST_MNTS}' + DT_ATMOS = '{DT_ATMOS}' rem = (DT_SUBHOURLY_POST_MNTS*60) %% DT_ATMOS = {rem} Please reset DT_SUBHOURLY_POST_MNTS and/or DT_ATMOS so that this remainder is zero.""" @@ -689,12 +743,12 @@ def get_location(xcs,fmt): if DT_SUBHOURLY_POST_MNTS == 0: logger.warning( f""" - When performing sub-hourly post (i.e. SUB_HOURLY_POST set to \"TRUE\"), + When performing sub-hourly post (i.e. SUB_HOURLY_POST set to 'TRUE'), DT_SUBHOURLY_POST_MNTS must be set to a value greater than 0; otherwise, sub-hourly output is not really being performed: - SUB_HOURLY_POST = \"{SUB_HOURLY_POST}\" - DT_SUBHOURLY_POST_MNTS = \"{DT_SUBHOURLY_POST_MNTS}\" - Resetting SUB_HOURLY_POST to \"FALSE\". If you do not want this, you + SUB_HOURLY_POST = '{SUB_HOURLY_POST}' + DT_SUBHOURLY_POST_MNTS = '{DT_SUBHOURLY_POST_MNTS}' + Resetting SUB_HOURLY_POST to 'FALSE'. If you do not want this, you must set DT_SUBHOURLY_POST_MNTS to something other than zero.""" ) SUB_HOURLY_POST = False @@ -725,7 +779,7 @@ def get_location(xcs,fmt): pass EXPT_BASEDIR = os.path.abspath(EXPT_BASEDIR) - mkdir_vrfy(f' -p "{EXPT_BASEDIR}"') + mkdir_vrfy(f" -p '{EXPT_BASEDIR}'") # # ----------------------------------------------------------------------- @@ -740,21 +794,25 @@ def get_location(xcs,fmt): try: check_for_preexist_dir_file(EXPTDIR, PREEXISTING_DIR_METHOD) except ValueError: - logger.exception(f''' - Check that the following values are valid: - EXPTDIR {EXPTDIR} - PREEXISTING_DIR_METHOD {PREEXISTING_DIR_METHOD} - ''') + logger.exception( + f""" + Check that the following values are valid: + EXPTDIR {EXPTDIR} + PREEXISTING_DIR_METHOD {PREEXISTING_DIR_METHOD} + """ + ) raise except FileExistsError: - errmsg = dedent(f''' - EXPTDIR ({EXPTDIR}) already exists, and PREEXISTING_DIR_METHOD = {PREEXISTING_DIR_METHOD} - - To ignore this error, delete the directory, or set - PREEXISTING_DIR_METHOD = delete, or - PREEXISTING_DIR_METHOD = rename - in your config file. - ''') + errmsg = dedent( + f""" + EXPTDIR ({EXPTDIR}) already exists, and PREEXISTING_DIR_METHOD = {PREEXISTING_DIR_METHOD} + + To ignore this error, delete the directory, or set + PREEXISTING_DIR_METHOD = delete, or + PREEXISTING_DIR_METHOD = rename + in your config file. + """ + ) raise FileExistsError(errmsg) from None # # ----------------------------------------------------------------------- @@ -796,22 +854,35 @@ def get_location(xcs,fmt): # Main directory locations if RUN_ENVIR == "nco": - try: OPSROOT = os.path.abspath(f"{EXPT_BASEDIR}{os.sep}..{os.sep}nco_dirs") \ - if OPSROOT is None else OPSROOT - except NameError: OPSROOT = EXPTDIR - try: COMROOT - except NameError: COMROOT = os.path.join(OPSROOT, "com") - try: PACKAGEROOT - except NameError: PACKAGEROOT = os.path.join(OPSROOT, "packages") - try: DATAROOT - except NameError: DATAROOT = os.path.join(OPSROOT, "tmp") - try: DCOMROOT - except NameError: DCOMROOT = os.path.join(OPSROOT, "dcom") + try: + OPSROOT = ( + os.path.abspath(f"{EXPT_BASEDIR}{os.sep}..{os.sep}nco_dirs") + if OPSROOT is None + else OPSROOT + ) + except NameError: + OPSROOT = EXPTDIR + try: + COMROOT + except NameError: + COMROOT = os.path.join(OPSROOT, "com") + try: + PACKAGEROOT + except NameError: + PACKAGEROOT = os.path.join(OPSROOT, "packages") + try: + DATAROOT + except NameError: + DATAROOT = os.path.join(OPSROOT, "tmp") + try: + DCOMROOT + except NameError: + DCOMROOT = os.path.join(OPSROOT, "dcom") COMIN_BASEDIR = os.path.join(COMROOT, NET, model_ver) COMOUT_BASEDIR = os.path.join(COMROOT, NET, model_ver) - LOGDIR = os.path.join(OPSROOT,"output") + LOGDIR = os.path.join(OPSROOT, "output") else: @@ -825,34 +896,52 @@ def get_location(xcs,fmt): LOGDIR = os.path.join(EXPTDIR, "log") - try: DBNROOT - except NameError: DBNROOT = None - try: SENDECF - except NameError: SENDECF = False - try: SENDDBN - except NameError: SENDDBN = False - try: SENDDBN_NTC - except NameError: SENDDBN_NTC = False - try: SENDCOM - except NameError: SENDCOM = False - try: SENDWEB - except NameError: SENDWEB = False - try: KEEPDATA - except NameError: KEEPDATA = True - try: MAILTO - except NameError: MAILTO = None - try: MAILCC - except NameError: MAILCC = None + try: + DBNROOT + except NameError: + DBNROOT = None + try: + SENDECF + except NameError: + SENDECF = False + try: + SENDDBN + except NameError: + SENDDBN = False + try: + SENDDBN_NTC + except NameError: + SENDDBN_NTC = False + try: + SENDCOM + except NameError: + SENDCOM = False + try: + SENDWEB + except NameError: + SENDWEB = False + try: + KEEPDATA + except NameError: + KEEPDATA = True + try: + MAILTO + except NameError: + MAILTO = None + try: + MAILCC + except NameError: + MAILCC = None # create NCO directories if RUN_ENVIR == "nco": - mkdir_vrfy(f' -p "{OPSROOT}"') - mkdir_vrfy(f' -p "{COMROOT}"') - mkdir_vrfy(f' -p "{PACKAGEROOT}"') - mkdir_vrfy(f' -p "{DATAROOT}"') - mkdir_vrfy(f' -p "{DCOMROOT}"') + mkdir_vrfy(f" -p '{OPSROOT}'") + mkdir_vrfy(f" -p '{COMROOT}'") + mkdir_vrfy(f" -p '{PACKAGEROOT}'") + mkdir_vrfy(f" -p '{DATAROOT}'") + mkdir_vrfy(f" -p '{DCOMROOT}'") if DBNROOT is not None: - mkdir_vrfy(f' -p "{DBNROOT}"') + mkdir_vrfy(f" -p '{DBNROOT}'") # # ----------------------------------------------------------------------- @@ -868,7 +957,7 @@ def get_location(xcs,fmt): POST_OUTPUT_DOMAIN_NAME = POST_OUTPUT_DOMAIN_NAME or PREDEF_GRID_NAME if type(POST_OUTPUT_DOMAIN_NAME) != int: - POST_OUTPUT_DOMAIN_NAME = lowercase(POST_OUTPUT_DOMAIN_NAME) + POST_OUTPUT_DOMAIN_NAME = lowercase(POST_OUTPUT_DOMAIN_NAME) if POST_OUTPUT_DOMAIN_NAME is None: if PREDEF_GRID_NAME is None: @@ -876,10 +965,10 @@ def get_location(xcs,fmt): f""" The domain name used in naming the run_post output files (POST_OUTPUT_DOMAIN_NAME) has not been set: - POST_OUTPUT_DOMAIN_NAME = \"{POST_OUTPUT_DOMAIN_NAME}\" + POST_OUTPUT_DOMAIN_NAME = '{POST_OUTPUT_DOMAIN_NAME}' If this experiment is not using a predefined grid (i.e. if PREDEF_GRID_NAME is set to a null string), POST_OUTPUT_DOMAIN_NAME - must be set in the configuration file (\"{EXPT_CONFIG_FN}\"). """ + must be set in the configuration file ('{EXPT_CONFIG_FN}'). """ ) # # ----------------------------------------------------------------------- @@ -981,10 +1070,10 @@ def get_location(xcs,fmt): CCPP_PHYS_SUITE_FP = os.path.join(EXPTDIR, CCPP_PHYS_SUITE_FN) if not os.path.exists(CCPP_PHYS_SUITE_IN_CCPP_FP): raise FileNotFoundError( - f''' + f""" The CCPP suite definition file (CCPP_PHYS_SUITE_IN_CCPP_FP) does not exist in the local clone of the ufs-weather-model: - CCPP_PHYS_SUITE_IN_CCPP_FP = \"{CCPP_PHYS_SUITE_IN_CCPP_FP}\"''' + CCPP_PHYS_SUITE_IN_CCPP_FP = '{CCPP_PHYS_SUITE_IN_CCPP_FP}'""" ) # # ----------------------------------------------------------------------- @@ -1008,10 +1097,10 @@ def get_location(xcs,fmt): FIELD_DICT_FP = os.path.join(EXPTDIR, FIELD_DICT_FN) if not os.path.exists(FIELD_DICT_IN_UWM_FP): raise FileNotFoundError( - f''' + f""" The field dictionary file (FIELD_DICT_IN_UWM_FP) does not exist in the local clone of the ufs-weather-model: - FIELD_DICT_IN_UWM_FP = \"{FIELD_DICT_IN_UWM_FP}\"''' + FIELD_DICT_IN_UWM_FP = '{FIELD_DICT_IN_UWM_FP}'""" ) # # ----------------------------------------------------------------------- @@ -1022,13 +1111,13 @@ def get_location(xcs,fmt): # ----------------------------------------------------------------------- # - # export env vars before calling another module - export_vars() - - OZONE_PARAM = set_ozone_param(CCPP_PHYS_SUITE_IN_CCPP_FP) + OZONE_PARAM = set_ozone_param( + CCPP_PHYS_SUITE_IN_CCPP_FP, + CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, + FIXgsm_FILES_TO_COPY_TO_FIXam, + VERBOSE=VERBOSE, + ) - IMPORTS = ["CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING", "FIXgsm_FILES_TO_COPY_TO_FIXam"] - import_vars(env_vars=IMPORTS) # # ----------------------------------------------------------------------- # @@ -1084,10 +1173,10 @@ def get_location(xcs,fmt): if not os.path.exists(EXTRN_MDL_SOURCE_BASEDIR_ICS[:idx]): raise FileNotFoundError( - f''' + f""" The directory (EXTRN_MDL_SOURCE_BASEDIR_ICS) in which the user-staged external model files for generating ICs should be located does not exist: - EXTRN_MDL_SOURCE_BASEDIR_ICS = \"{EXTRN_MDL_SOURCE_BASEDIR_ICS}\"''' + EXTRN_MDL_SOURCE_BASEDIR_ICS = '{EXTRN_MDL_SOURCE_BASEDIR_ICS}'""" ) idx = EXTRN_MDL_SOURCE_BASEDIR_LBCS.find("$") @@ -1096,10 +1185,10 @@ def get_location(xcs,fmt): if not os.path.exists(EXTRN_MDL_SOURCE_BASEDIR_LBCS[:idx]): raise FileNotFoundError( - f''' + f""" The directory (EXTRN_MDL_SOURCE_BASEDIR_LBCS) in which the user-staged external model files for generating LBCs should be located does not exist: - EXTRN_MDL_SOURCE_BASEDIR_LBCS = \"{EXTRN_MDL_SOURCE_BASEDIR_LBCS}\"''' + EXTRN_MDL_SOURCE_BASEDIR_LBCS = '{EXTRN_MDL_SOURCE_BASEDIR_LBCS}'""" ) # # ----------------------------------------------------------------------- @@ -1174,11 +1263,11 @@ def get_location(xcs,fmt): # Ensemble verification can only be run in ensemble mode if (not DO_ENSEMBLE) and (RUN_TASK_VX_ENSGRID or RUN_TASK_VX_ENSPOINT): raise Exception( - f''' + f""" Ensemble verification can not be run unless running in ensemble mode: - DO_ENSEMBLE = \"{DO_ENSEMBLE}\" - RUN_TASK_VX_ENSGRID = \"{RUN_TASK_VX_ENSGRID}\" - RUN_TASK_VX_ENSPOINT = \"{RUN_TASK_VX_ENSPOINT}\"''' + DO_ENSEMBLE = '{DO_ENSEMBLE}' + RUN_TASK_VX_ENSGRID = '{RUN_TASK_VX_ENSGRID}' + RUN_TASK_VX_ENSPOINT = '{RUN_TASK_VX_ENSPOINT}'""" ) # @@ -1219,21 +1308,23 @@ def get_location(xcs,fmt): # experiment directory (EXPTDIR). # if not RUN_TASK_MAKE_GRID: - if (GRID_DIR is None): + if GRID_DIR is None: GRID_DIR = os.path.join(DOMAIN_PREGEN_BASEDIR, PREDEF_GRID_NAME) - msg = dedent(f""" - GRID_DIR not specified! - Setting GRID_DIR = {GRID_DIR} - """) + msg = dedent( + f""" + GRID_DIR not specified! + Setting GRID_DIR = {GRID_DIR} + """ + ) logger.warning(msg) - if not os.path.exists(GRID_DIR): + if not os.path.exists(GRID_DIR): raise FileNotFoundError( - f''' + f""" The directory (GRID_DIR) that should contain the pregenerated grid files does not exist: - GRID_DIR = \"{GRID_DIR}\"''' + GRID_DIR = '{GRID_DIR}'""" ) else: GRID_DIR = os.path.join(EXPTDIR, "grid") @@ -1244,21 +1335,23 @@ def get_location(xcs,fmt): # the experiment directory (EXPTDIR). # if not RUN_TASK_MAKE_OROG: - if (OROG_DIR is None): + if OROG_DIR is None: OROG_DIR = os.path.join(DOMAIN_PREGEN_BASEDIR, PREDEF_GRID_NAME) - msg = dedent(f""" - OROG_DIR not specified! - Setting OROG_DIR = {OROG_DIR} - """) + msg = dedent( + f""" + OROG_DIR not specified! + Setting OROG_DIR = {OROG_DIR} + """ + ) logger.warning(msg) if not os.path.exists(OROG_DIR): raise FileNotFoundError( - f''' + f""" The directory (OROG_DIR) that should contain the pregenerated orography files does not exist: - OROG_DIR = \"{OROG_DIR}\"''' + OROG_DIR = '{OROG_DIR}'""" ) else: OROG_DIR = os.path.join(EXPTDIR, "orog") @@ -1269,40 +1362,42 @@ def get_location(xcs,fmt): # a predefined location under the experiment directory (EXPTDIR). # if not RUN_TASK_MAKE_SFC_CLIMO: - if (SFC_CLIMO_DIR is None): + if SFC_CLIMO_DIR is None: SFC_CLIMO_DIR = os.path.join(DOMAIN_PREGEN_BASEDIR, PREDEF_GRID_NAME) - msg = dedent(f""" - SFC_CLIMO_DIR not specified! - Setting SFC_CLIMO_DIR ={SFC_CLIMO_DIR} - """) + msg = dedent( + f""" + SFC_CLIMO_DIR not specified! + Setting SFC_CLIMO_DIR ={SFC_CLIMO_DIR} + """ + ) logger.warning(msg) if not os.path.exists(SFC_CLIMO_DIR): raise FileNotFoundError( - f''' + f""" The directory (SFC_CLIMO_DIR) that should contain the pregenerated surface climatology files does not exist: - SFC_CLIMO_DIR = \"{SFC_CLIMO_DIR}\"''' + SFC_CLIMO_DIR = '{SFC_CLIMO_DIR}'""" ) else: SFC_CLIMO_DIR = os.path.join(EXPTDIR, "sfc_climo") + # # ----------------------------------------------------------------------- # - # Set cycle-independent parameters associated with the external models - # from which we will obtain the ICs and LBCs. + # Set EXTRN_MDL_LBCS_OFFSET_HRS, which is the number of hours to shift + # the starting time of the external model that provides lateral boundary + # conditions. # # ----------------------------------------------------------------------- # + global EXTRN_MDL_LBCS_OFFSET_HRS + if EXTRN_MDL_NAME_LBCS == "RAP": + EXTRN_MDL_LBCS_OFFSET_HRS = EXTRN_MDL_LBCS_OFFSET_HRS or "3" + else: + EXTRN_MDL_LBCS_OFFSET_HRS = EXTRN_MDL_LBCS_OFFSET_HRS or "0" - # export env vars before calling another module - export_vars() - - set_extrn_mdl_params() - - IMPORTS = ["EXTRN_MDL_LBCS_OFFSET_HRS"] - import_vars(env_vars=IMPORTS) # # ----------------------------------------------------------------------- # @@ -1361,7 +1456,6 @@ def get_location(xcs,fmt): "STRETCH_FAC": STRETCH_FAC, } - # Extract the basic grid params from the dictionary (LON_CTR, LAT_CTR, NX, NY, NHW, STRETCH_FAC) = ( grid_params[k] for k in ["LON_CTR", "LAT_CTR", "NX", "NY", "NHW", "STRETCH_FAC"] @@ -1370,14 +1464,14 @@ def get_location(xcs,fmt): # # ----------------------------------------------------------------------- # - # Create a new experiment directory. For platforms with no workflow + # Create a new experiment directory. For platforms with no workflow # manager we need to create LOGDIR as well, since it won't be created # later at runtime. # # ----------------------------------------------------------------------- # - mkdir_vrfy(f' -p "{EXPTDIR}"') - mkdir_vrfy(f' -p "{LOGDIR}"') + mkdir_vrfy(f" -p '{EXPTDIR}'") + mkdir_vrfy(f" -p '{LOGDIR}'") # # ----------------------------------------------------------------------- # NOTE: currently this is executed no matter what, should it be dependent on the logic described below?? @@ -1390,7 +1484,7 @@ def get_location(xcs,fmt): # # ----------------------------------------------------------------------- # - mkdir_vrfy(f' -p "{FIXlam}"') + mkdir_vrfy(f" -p '{FIXlam}'") RES_IN_FIXLAM_FILENAMES = "" # # ----------------------------------------------------------------------- @@ -1481,10 +1575,14 @@ def get_location(xcs,fmt): if WRITE_DOPOST: # Turn off run_post if RUN_TASK_RUN_POST: - logger.warning(dedent(f""" - Inline post is turned on, deactivating post-processing tasks: - RUN_TASK_RUN_POST = False - """)) + logger.warning( + dedent( + f""" + Inline post is turned on, deactivating post-processing tasks: + RUN_TASK_RUN_POST = False + """ + ) + ) RUN_TASK_RUN_POST = False # Check if SUB_HOURLY_POST is on @@ -1509,12 +1607,12 @@ def get_location(xcs,fmt): if VERBOSE: log_info( - f""" - The number of MPI tasks for the forecast (including those for the write - component if it is being used) are: - PE_MEMBER01 = {PE_MEMBER01}""", - verbose=VERBOSE, - ) + f""" + The number of MPI tasks for the forecast (including those for the write + component if it is being used) are: + PE_MEMBER01 = {PE_MEMBER01}""", + verbose=VERBOSE, + ) # # ----------------------------------------------------------------------- # @@ -1579,48 +1677,19 @@ def get_location(xcs,fmt): # ----------------------------------------------------------------------- # SDF_USES_THOMPSON_MP = set_thompson_mp_fix_files( - ccpp_phys_suite_fp=CCPP_PHYS_SUITE_IN_CCPP_FP, - thompson_mp_climo_fn=THOMPSON_MP_CLIMO_FN, + CCPP_PHYS_SUITE_IN_CCPP_FP, + THOMPSON_MP_CLIMO_FN, + CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, + FIXgsm_FILES_TO_COPY_TO_FIXam, ) - IMPORTS = ["CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING", "FIXgsm_FILES_TO_COPY_TO_FIXam"] - import_vars(env_vars=IMPORTS) - - # - # ----------------------------------------------------------------------- - # - # Generate the shell script that will appear in the experiment directory - # (EXPTDIR) and will contain definitions of variables needed by the va- - # rious scripts in the workflow. We refer to this as the experiment/ - # workflow global variable definitions file. We will create this file - # by: - # - # 1) Copying the default workflow/experiment configuration file (speci- - # fied by EXPT_DEFAULT_CONFIG_FN and located in the shell script di- - # rectory specified by USHdir) to the experiment directory and rena- - # ming it to the name specified by GLOBAL_VAR_DEFNS_FN. - # - # 2) Resetting the default variable values in this file to their current - # values. This is necessary because these variables may have been - # reset by the user-specified configuration file (if one exists in - # USHdir) and/or by this setup script, e.g. because predef_domain is - # set to a valid non-empty value. - # - # 3) Appending to the variable definitions file any new variables intro- - # duced in this setup script that may be needed by the scripts that - # perform the various tasks in the workflow (and which source the va- - # riable defintions file). - # - # First, set the full path to the variable definitions file and copy the - # default configuration script into it. - # - # ----------------------------------------------------------------------- - # - # global variable definition file path global GLOBAL_VAR_DEFNS_FP GLOBAL_VAR_DEFNS_FP = os.path.join(EXPTDIR, GLOBAL_VAR_DEFNS_FN) + # fixed files section + cfg_d.update(cfg_f) + # update dictionary with globals() values update_dict(globals(), cfg_d) @@ -1646,7 +1715,7 @@ def get_location(xcs,fmt): # # Full path to workflow (re)launch script, its log file, and the line # that gets added to the cron table to launch this script if the flag - # USE_CRON_TO_RELAUNCH is set to \"TRUE\". + # USE_CRON_TO_RELAUNCH is set to 'TRUE'. # # ----------------------------------------------------------------------- # @@ -1767,7 +1836,7 @@ def get_location(xcs,fmt): # # ----------------------------------------------------------------------- # - # Flag in the \"{MODEL_CONFIG_FN}\" file for coupling the ocean model to + # Flag in the '{MODEL_CONFIG_FN}' file for coupling the ocean model to # the weather model. # # ----------------------------------------------------------------------- @@ -1856,11 +1925,11 @@ def get_location(xcs,fmt): f""" Generating the global experiment variable definitions file specified by GLOBAL_VAR_DEFNS_FN: - GLOBAL_VAR_DEFNS_FN = \"{GLOBAL_VAR_DEFNS_FN}\" + GLOBAL_VAR_DEFNS_FN = '{GLOBAL_VAR_DEFNS_FN}' Full path to this file is: - GLOBAL_VAR_DEFNS_FP = \"{GLOBAL_VAR_DEFNS_FP}\" - For more detailed information, set DEBUG to \"TRUE\" in the experiment - configuration file (\"{EXPT_CONFIG_FN}\").""" + GLOBAL_VAR_DEFNS_FP = '{GLOBAL_VAR_DEFNS_FP}' + For more detailed information, set DEBUG to 'TRUE' in the experiment + configuration file ('{EXPT_CONFIG_FN}').""" ) with open(GLOBAL_VAR_DEFNS_FP, "a") as f: diff --git a/ush/test_retrieve_data.py b/ush/test_retrieve_data.py index 3ffdf4744c..dc7a775f05 100644 --- a/ush/test_retrieve_data.py +++ b/ush/test_retrieve_data.py @@ -1,4 +1,4 @@ -''' +""" Functional test suite for gathering data using retreve_data.py. The tests reflect some use cases of gathering various model input data @@ -14,7 +14,7 @@ To run a single test: python -m unittest -b test_retrieve_data.FunctionalTesting.test_rap_lbcs_from_aws -''' +""" import glob import os import tempfile @@ -22,22 +22,21 @@ import retrieve_data + class FunctionalTesting(unittest.TestCase): - ''' Test class for retrieve data ''' + """Test class for retrieve data""" def setUp(self): self.path = os.path.dirname(__file__) - self.config = f'{self.path}/../parm/data_locations.yml' + self.config = f"{self.path}/../parm/data_locations.yml" - @unittest.skipIf(os.environ.get('CI') == "true", "Skipping HPSS tests") + @unittest.skipIf(os.environ.get("CI") == "true", "Skipping HPSS tests") def test_fv3gfs_grib2_lbcs_from_hpss(self): - ''' Get FV3GFS grib2 files from HPSS for LBCS, offset by 6 hours - - ''' + """Get FV3GFS grib2 files from HPSS for LBCS, offset by 6 hours""" - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) args = [ @@ -56,18 +55,18 @@ def test_fv3gfs_grib2_lbcs_from_hpss(self): # Verify files exist in temp dir - path = os.path.join(tmp_dir, '*') + path = os.path.join(tmp_dir, "*") files_on_disk = glob.glob(path) self.assertEqual(len(files_on_disk), 3) - @unittest.skipIf(os.environ.get('CI') == "true", "Skipping HPSS tests") + @unittest.skipIf(os.environ.get("CI") == "true", "Skipping HPSS tests") def test_fv3gfs_netcdf_lbcs_from_hpss(self): - ''' Get FV3GFS netcdf files from HPSS for LBCS. Tests fcst lead + """Get FV3GFS netcdf files from HPSS for LBCS. Tests fcst lead times > 40 hours, since they come from a different archive file. - ''' + """ - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) args = [ @@ -86,20 +85,19 @@ def test_fv3gfs_netcdf_lbcs_from_hpss(self): # Verify files exist in temp dir - path = os.path.join(tmp_dir, '*') + path = os.path.join(tmp_dir, "*") files_on_disk = glob.glob(path) self.assertEqual(len(files_on_disk), 2) # GDAS Tests def test_gdas_ics_from_aws(self): - ''' In real time, GDAS is used for LBCS with a 6 hour offset. - ''' + """In real time, GDAS is used for LBCS with a 6 hour offset.""" - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) - out_path_tmpl = f'mem{{mem:03d}}' + out_path_tmpl = f"mem{{mem:03d}}" args = [ '--anl_or_fcst', 'anl', @@ -120,22 +118,19 @@ def test_gdas_ics_from_aws(self): for mem in [9, 10]: files_on_disk = glob.glob( - os.path.join(out_path_tmpl.format(mem=mem), '*') - ) + os.path.join(out_path_tmpl.format(mem=mem), "*") + ) self.assertEqual(len(files_on_disk), 2) - # GEFS Tests def test_gefs_grib2_ics_from_aws(self): - ''' Get GEFS grib2 a & b files for ICS offset by 6 hours. + """Get GEFS grib2 a & b files for ICS offset by 6 hours.""" - ''' - - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) - out_path_tmpl = f'mem{{mem:03d}}' + out_path_tmpl = f"mem{{mem:03d}}" args = [ '--anl_or_fcst', 'anl', @@ -155,19 +150,17 @@ def test_gefs_grib2_ics_from_aws(self): # Verify files exist in temp dir for mem in [1, 2]: files_on_disk = glob.glob( - os.path.join(out_path_tmpl.format(mem=mem), '*') - ) + os.path.join(out_path_tmpl.format(mem=mem), "*") + ) self.assertEqual(len(files_on_disk), 2) - - # HRRR Tests - @unittest.skipIf(os.environ.get('CI') == "true", "Skipping HPSS tests") + @unittest.skipIf(os.environ.get("CI") == "true", "Skipping HPSS tests") def test_hrrr_ics_from_hpss(self): - ''' Get HRRR ICS from hpss ''' + """Get HRRR ICS from hpss""" - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) args = [ @@ -185,16 +178,16 @@ def test_hrrr_ics_from_hpss(self): # Verify files exist in temp dir - path = os.path.join(tmp_dir, '*') + path = os.path.join(tmp_dir, "*") files_on_disk = glob.glob(path) self.assertEqual(len(files_on_disk), 1) - @unittest.skipIf(os.environ.get('CI') == "true", "Skipping HPSS tests") + @unittest.skipIf(os.environ.get("CI") == "true", "Skipping HPSS tests") def test_hrrr_lbcs_from_hpss(self): - ''' Get HRRR LBCS from hpss for 3 hour boundary conditions ''' + """Get HRRR LBCS from hpss for 3 hour boundary conditions""" - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) args = [ @@ -212,15 +205,15 @@ def test_hrrr_lbcs_from_hpss(self): # Verify files exist in temp dir - path = os.path.join(tmp_dir, '*') + path = os.path.join(tmp_dir, "*") files_on_disk = glob.glob(path) self.assertEqual(len(files_on_disk), 8) def test_hrrr_ics_from_aws(self): - ''' Get HRRR ICS from aws ''' + """Get HRRR ICS from aws""" - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) args = [ @@ -238,15 +231,15 @@ def test_hrrr_ics_from_aws(self): # Verify files exist in temp dir - path = os.path.join(tmp_dir, '*') + path = os.path.join(tmp_dir, "*") files_on_disk = glob.glob(path) self.assertEqual(len(files_on_disk), 1) def test_hrrr_lbcs_from_aws(self): - ''' Get HRRR LBCS from aws for 3 hour boundary conditions ''' + """Get HRRR LBCS from aws for 3 hour boundary conditions""" - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) args = [ @@ -264,16 +257,16 @@ def test_hrrr_lbcs_from_aws(self): # Verify files exist in temp dir - path = os.path.join(tmp_dir, '*') + path = os.path.join(tmp_dir, "*") files_on_disk = glob.glob(path) self.assertEqual(len(files_on_disk), 8) # RAP tests def test_rap_ics_from_aws(self): - ''' Get RAP ICS from aws offset by 3 hours ''' + """Get RAP ICS from aws offset by 3 hours""" - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) args = [ @@ -291,16 +284,16 @@ def test_rap_ics_from_aws(self): # Verify files exist in temp dir - path = os.path.join(tmp_dir, '*') + path = os.path.join(tmp_dir, "*") files_on_disk = glob.glob(path) self.assertEqual(len(files_on_disk), 1) def test_rap_lbcs_from_aws(self): - ''' Get RAP LBCS from aws for 6 hour boundary conditions offset - by 3 hours. Use 09Z start time for longer LBCS.''' + """Get RAP LBCS from aws for 6 hour boundary conditions offset + by 3 hours. Use 09Z start time for longer LBCS.""" - with tempfile.TemporaryDirectory(dir='.') as tmp_dir: + with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) args = [ @@ -318,6 +311,6 @@ def test_rap_lbcs_from_aws(self): # Verify files exist in temp dir - path = os.path.join(tmp_dir, '*') + path = os.path.join(tmp_dir, "*") files_on_disk = glob.glob(path) self.assertEqual(len(files_on_disk), 5) From 4daf3b8371caa6748718a13cfefff049462b52ac Mon Sep 17 00:00:00 2001 From: Natalie Perlin <68030316+natalie-perlin@users.noreply.github.com> Date: Fri, 28 Oct 2022 14:28:22 -0400 Subject: [PATCH 06/45] created devclean.sh (#415) * created devclean.sh a script to clean all the SRW builds in subdirectories, bin/exec directory * updated devclean.sh Co-authored-by: Natalie Perlin --- devclean.sh | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100755 devclean.sh diff --git a/devclean.sh b/devclean.sh new file mode 100755 index 0000000000..d3c316514e --- /dev/null +++ b/devclean.sh @@ -0,0 +1,146 @@ +#!/bin/bash + +# usage instructions +usage () { +cat << EOF_USAGE + +Clean the UFS-SRW Application build +Usage: $0 [OPTIONS] ... + +OPTIONS + -h, --help + show this help guide + -a, --all + removes "bin", "build" directories, and other build artifacts + --remove + removes the "build" directory, keeps the "bin", "lib" and other build artifacts intact + --clean + removes "bin", "build" directories, and other build artifacts (same as "-a", "--all") + --install-dir=INSTALL_DIR + installation directory name (\${SRW_DIR} by default) + --build-dir=BUILD_DIR + main build directory, absolute path (\${SRW_DIR}/build/ by default) + --bin-dir=BIN_DIR + binary directory name ("exec" by default); full path is \${INSTALL_DIR}/\${BIN_DIR}) + --sub-modules + remove sub-module directories. They will need to be checked out again by sourcing "\${SRW_DIR}/manage_externals/checkout_externals" before attempting subsequent builds + -v, --verbose + provide more verbose output + +EOF_USAGE +} + +# print settings +settings () { +cat << EOF_SETTINGS +Settings: + + INSTALL_DIR=${INSTALL_DIR} + BUILD_DIR=${BUILD_DIR} + BIN_DIR=${BIN_DIR} + REMOVE=${REMOVE} + VERBOSE=${VERBOSE} + +Default cleaning options: (if no arguments provided, then nothing is cleaned) + REMOVE=${REMOVE} + CLEAN=${CLEAN} + INCLUDE_SUB_MODULES=${INCLUDE_SUB_MODULES} + +EOF_SETTINGS +} + +# print usage error and exit +usage_error () { + printf "ERROR: $1\n" >&2 + usage >&2 + exit 1 +} + +# default settings +SRW_DIR=$(cd "$(dirname "$(readlink -f -n "${BASH_SOURCE[0]}" )" )" && pwd -P) +INSTALL_DIR=${INSTALL_DIR:-${SRW_DIR}} +BUILD_DIR=${BUILD_DIR:-"${SRW_DIR}/build"} +BIN_DIR="exec" +REMOVE=false +VERBOSE=false + +# default clean options +REMOVE=false +CLEAN=false +INCLUDE_SUB_MODULES=false #changes to true if '--sub-modules' option is provided + +# process requires arguments +if [[ ("$1" == "--help") || ("$1" == "-h") ]]; then + usage + exit 0 +fi +# process optional arguments +while :; do + case $1 in + --help|-h) usage; exit 0 ;; + --all|-a) ALL_CLEAN=true ;; + --remove) REMOVE=true ;; + --remove=?*|--remove=) usage_error "$1 argument ignored." ;; + --clean) CLEAN=true ;; + --install-dir=?*) INSTALL_DIR=${1#*=} ;; + --install-dir|--install-dir=) usage_error "$1 requires argument." ;; + --build-dir=?*) BUILD_DIR=${1#*=} ;; + --build-dir|--build-dir=) usage_error "$1 requires argument." ;; + --bin-dir=?*) BIN_DIR=${1#*=} ;; + --bin-dir|--bin-dir=) usage_error "$1 requires argument." ;; + --sub-modules) INCLUDE_SUB_MODULES=true ;; + --verbose|-v) VERBOSE=true ;; + --verbose=?*|--verbose=) usage_error "$1 argument ignored." ;; + # targets + default) ALL_CLEAN=false ;; + # unknown + -?*|?*) usage_error "Unknown option $1" ;; + *) usage; break ;; + esac + shift +done + +# choose defaults to clean +if [ "${ALL_CLEAN}" = true ]; then + CLEAN=true +fi + +# print settings +if [ "${VERBOSE}" = true ] ; then + settings +fi + +# clean if build directory already exists +if [ "${REMOVE}" = true ] && [ "${CLEAN}" = false ] ; then + printf '%s\n' "Remove the \"build\" directory only, BUILD_DIR = $BUILD_DIR " + [[ -d ${BUILD_DIR} ]] && rm -rf ${BUILD_DIR} && printf '%s\n' "rm -rf ${BUILD_DIR}" +elif [ "${CLEAN}" = true ]; then + printf '%s\n' "Remove build directory, bin directory, and other build artifacts " + printf '%s\n' " from the installation directory = ${INSTALL_DIR} " + [[ -d "${BUILD_DIR}" ]] && rm -rf ${BUILD_DIR} && printf '%s\n' "rm -rf ${BUILD_DIR}" + [[ -d "${INSTALL_DIR}/${BIN_DIR}" ]] && ( rm -rf ${INSTALL_DIR}/${BIN_DIR} && printf '%s\n' "rm -rf ${INSTALL_DIR}/${BIN_DIR}" ) + [[ -d "${INSTALL_DIR}/lib" ]] && ( rm -rf ${INSTALL_DIR}/share && printf '%s\n' "rm -rf ${INSTALL_DIR}/share" ) + [[ -d "${INSTALL_DIR}/include" ]] && ( rm -rf ${INSTALL_DIR}/include && printf '%s\n' "rm -rf ${INSTALL_DIR}/include" ) + [[ -d "${INSTALL_DIR}/lib" ]] && rm -rf ${INSTALL_DIR}/lib && printf '%s\n' "rm -rf ${INSTALL_DIR}/lib" + [[ -d "${SRW_DIR}/manage_externals/manic" ]] && rm -f ${SRW_DIR}/manage_externals/manic/*.pyc && printf '%s\n' "rm -f ${SRW_DIR}/manage_externals/manic/*.pyc" + echo " " +fi +# Clean all the submodules if requested. NB: Need to check out them again before attempting subsequent builds, by sourcing ${SRW_DIR}/manage_externals/checkout_externals +if [ ${INCLUDE_SUB_MODULES} == true ]; then + printf '%s\n' "Removing submodules ..." + declare -a submodules='()' + submodules=(${SRW_DIR}/sorc/*) +# echo " submodules are: ${submodules[@]} (total of ${#submodules[@]}) " + if [ ${#submodules[@]} -ge 1 ]; then + for sub in ${submodules[@]}; do [[ -d "${sub}" ]] && ( rm -rf ${sub} && printf '%s\n' "rm -rf ${sub}" ); done + fi + printf '%s\n' "NB: Need to check out submodules again for any subsequent builds, " \ + " by sourcing ${SRW_DIR}/manage_externals/checkout_externals " +fi +# +echo " " +echo "All the requested cleaning tasks have been completed" +echo " " + +exit 0 + From 16ad699d8be265973b5401d53589ba6ebf8e52a9 Mon Sep 17 00:00:00 2001 From: Michael Lueken <63728921+MichaelLueken@users.noreply.github.com> Date: Fri, 28 Oct 2022 14:54:53 -0400 Subject: [PATCH 07/45] [develop] Remove my_load_any from modulefiles/srw_common.lua and use load_any --- modulefiles/build_cheyenne_intel.lua | 1 - modulefiles/srw_common.lua | 26 ++++++++------------------ 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/modulefiles/build_cheyenne_intel.lua b/modulefiles/build_cheyenne_intel.lua index b1ae5b7bc1..2c5f2a332f 100644 --- a/modulefiles/build_cheyenne_intel.lua +++ b/modulefiles/build_cheyenne_intel.lua @@ -23,7 +23,6 @@ load("srw_common") load(pathJoin("g2", os.getenv("g2_ver") or "3.4.5")) load(pathJoin("esmf", os.getenv("esmf_ver") or "8.3.0b09")) -load(pathJoin("mapl", os.getenv("mapl_ver") or "2.11.0-esmf-8.3.0b09")) load(pathJoin("netcdf", os.getenv("netcdf_ver") or "4.7.4")) load(pathJoin("libpng", os.getenv("libpng_ver") or "1.6.37")) load(pathJoin("pio", os.getenv("pio_ver") or "2.5.3")) diff --git a/modulefiles/srw_common.lua b/modulefiles/srw_common.lua index 13337d8cff..622f497342 100644 --- a/modulefiles/srw_common.lua +++ b/modulefiles/srw_common.lua @@ -1,21 +1,11 @@ - --- Until Cheyenne updates Lmod version to >=8.3.7 --- emulate load_any with try_load + isloaded() combo -function my_load_any(pkg1, pkg2) - try_load(pkg1) - if not isloaded(pkg1) then - load(pkg2) - end -end - load("jasper/2.0.25") load("zlib/1.2.11") -my_load_any("png/1.6.35", "libpng/1.6.37") +load_any("png/1.6.35", "libpng/1.6.37") -my_load_any("netcdf/4.7.4", "netcdf-c/4.7.4") -my_load_any("netcdf/4.7.4", "netcdf-fortran/4.5.4") -my_load_any("pio/2.5.3", "parallelio/2.5.2") -my_load_any("esmf/8.3.0b09", "esmf/8.2.0") +load_any("netcdf/4.7.4", "netcdf-c/4.7.4") +load_any("netcdf/4.7.4", "netcdf-fortran/4.5.4") +load_any("pio/2.5.3", "parallelio/2.5.2") +load_any("esmf/8.3.0b09", "esmf/8.2.0") load("fms/2022.01") load("bufr/11.7.0") @@ -27,9 +17,9 @@ load("ip/3.3.3") load("sp/2.3.3") load("w3emc/2.9.2") -my_load_any("gftl-shared/v1.5.0", "gftl-shared/1.5.0") -my_load_any("yafyaml/v0.5.1", "yafyaml/0.5.1") -my_load_any("mapl/2.22.0-esmf-8.3.0b09", "mapl/2.11.0-esmf-8.2.0") +load_any("gftl-shared/v1.5.0", "gftl-shared/1.5.0") +load_any("yafyaml/v0.5.1", "yafyaml/0.5.1") +load_any("mapl/2.22.0-esmf-8.3.0b09", "mapl/2.11.0-esmf-8.2.0") load("nemsio/2.5.4") load("sfcio/1.4.1") From a1782a2ae77a0b25d2f0a78947e0076ecef407f7 Mon Sep 17 00:00:00 2001 From: "Chan-Hoo.Jeon-NOAA" <60152248+chan-hoo@users.noreply.github.com> Date: Fri, 28 Oct 2022 15:10:53 -0400 Subject: [PATCH 08/45] Structure and components of COMIN directory in NCO mode are modified (#440) * set for_IC/LBCS dir for nco mode * add missing -rf to rm_vrfy in make_ic/lbcs * add directory empty check for restart * add intermediate symlink to RESTART for cycled runs * update rocoto ver to 1.3.5 on wcoss2 Co-authored-by: chan-hoo Co-authored-by: chan-hoo Co-authored-by: chan-hoo --- jobs/JREGIONAL_GET_EXTRN_MDL_FILES | 2 +- scripts/exregional_make_ics.sh | 12 +++++++++++- scripts/exregional_make_lbcs.sh | 12 +++++++++++- scripts/exregional_run_fcst.sh | 18 ++++++++++++++++++ ush/job_preamble.sh | 4 ++-- versions/run.ver.wcoss2 | 2 +- 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/jobs/JREGIONAL_GET_EXTRN_MDL_FILES b/jobs/JREGIONAL_GET_EXTRN_MDL_FILES index a6b1902a14..8975a3e678 100755 --- a/jobs/JREGIONAL_GET_EXTRN_MDL_FILES +++ b/jobs/JREGIONAL_GET_EXTRN_MDL_FILES @@ -209,7 +209,7 @@ esac #----------------------------------------------------------------------- # if [ $RUN_ENVIR = "nco" ]; then - export EXTRN_MDL_STAGING_DIR="${COMIN}" + export EXTRN_MDL_STAGING_DIR="${COMIN}/for_${ICS_OR_LBCS}" mkdir_vrfy -p "${EXTRN_MDL_STAGING_DIR}" else export EXTRN_MDL_STAGING_DIR="${COMIN}/${EXTRN_MDL_NAME}/for_${ICS_OR_LBCS}" diff --git a/scripts/exregional_make_ics.sh b/scripts/exregional_make_ics.sh index 5c2d6c393a..e8f84f4136 100755 --- a/scripts/exregional_make_ics.sh +++ b/scripts/exregional_make_ics.sh @@ -86,7 +86,7 @@ fi #----------------------------------------------------------------------- # if [ $RUN_ENVIR = "nco" ]; then - extrn_mdl_staging_dir="${COMIN}" + extrn_mdl_staging_dir="${COMIN}/for_ICS" extrn_mdl_var_defns_fp="${extrn_mdl_staging_dir}/${NET}.${cycle}.${EXTRN_MDL_NAME_ICS}.ICS.${EXTRN_MDL_VAR_DEFNS_FN}.sh" else extrn_mdl_staging_dir="${COMIN}/${EXTRN_MDL_NAME_ICS}/for_ICS" @@ -592,6 +592,16 @@ mv_vrfy gfs.bndy.nc ${INPUT_DATA}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile${TI # #----------------------------------------------------------------------- # +# Clean up the external model data files in NCO mode +# +#----------------------------------------------------------------------- +# +if [ "${RUN_ENVIR}" = "nco" ]; then + rm_vrfy -rf ${extrn_mdl_staging_dir} +fi +# +#----------------------------------------------------------------------- +# # Process FVCOM Data # #----------------------------------------------------------------------- diff --git a/scripts/exregional_make_lbcs.sh b/scripts/exregional_make_lbcs.sh index 581ba76b5f..123350e886 100755 --- a/scripts/exregional_make_lbcs.sh +++ b/scripts/exregional_make_lbcs.sh @@ -84,7 +84,7 @@ fi #----------------------------------------------------------------------- # if [ $RUN_ENVIR = "nco" ]; then - extrn_mdl_staging_dir="${COMIN}" + extrn_mdl_staging_dir="${COMIN}/for_LBCS" extrn_mdl_var_defns_fp="${extrn_mdl_staging_dir}/${NET}.${cycle}.${EXTRN_MDL_NAME_LBCS}.LBCS.${EXTRN_MDL_VAR_DEFNS_FN}.sh" else extrn_mdl_staging_dir="${COMIN}/${EXTRN_MDL_NAME_LBCS}/for_LBCS" @@ -499,6 +499,16 @@ done # #----------------------------------------------------------------------- # +# Clean up the external model data files in NCO mode +# +#----------------------------------------------------------------------- +# +if [ "${RUN_ENVIR}" = "nco" ]; then + rm_vrfy -rf ${extrn_mdl_staging_dir} +fi +# +#----------------------------------------------------------------------- +# # Print message indicating successful completion of script. # #----------------------------------------------------------------------- diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 626a855ba5..2bf946a9f6 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -492,6 +492,9 @@ if [ "${RUN_ENVIR}" = "nco" ]; then ln_vrfy -sf "${DATA_SHARED}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr}${mnts_secs_str}.nc" "dynf${fhr}${mnts_secs_str}.nc" ln_vrfy -sf "${DATA_SHARED}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr}${mnts_secs_str}.nc" "phyf${fhr}${mnts_secs_str}.nc" done + + # create an intermediate symlink to RESTART + ln_vrfy -sf "${DATA}/RESTART" "${COMIN}/RESTART" fi # #----------------------------------------------------------------------- @@ -512,6 +515,21 @@ POST_STEP # #----------------------------------------------------------------------- # +# Move RESTART directory to COMIN and create symlink in DATA only for +# NCO mode and when it is not empty. +# +#----------------------------------------------------------------------- +# +if [ "${RUN_ENVIR}" = "nco" ]; then + rm_vrfy -rf "${COMIN}/RESTART" + if [ "$(ls -A RESTART)" ]; then + mv_vrfy RESTART ${COMIN} + ln_vrfy -sf ${COMIN}/RESTART ${DATA}/RESTART + fi +fi +# +#----------------------------------------------------------------------- +# # If doing inline post, create the directory in which the post-processing # output will be stored (postprd_dir). # diff --git a/ush/job_preamble.sh b/ush/job_preamble.sh index 4e90c58dfd..52667a112d 100644 --- a/ush/job_preamble.sh +++ b/ush/job_preamble.sh @@ -102,8 +102,8 @@ export -f POST_STEP #----------------------------------------------------------------------- # if [ "${RUN_ENVIR}" = "nco" ]; then - export COMIN="${COMIN_BASEDIR}/${RUN}.${PDY}" - export COMOUT="${COMOUT_BASEDIR}/${RUN}.${PDY}" + export COMIN="${COMIN_BASEDIR}/${RUN}.${PDY}/${cyc}" + export COMOUT="${COMOUT_BASEDIR}/${RUN}.${PDY}/${cyc}" else export COMIN="${COMIN_BASEDIR}/${PDY}${cyc}" export COMOUT="${COMOUT_BASEDIR}/${PDY}${cyc}" diff --git a/versions/run.ver.wcoss2 b/versions/run.ver.wcoss2 index db7dc8c6ea..acdfffdf6d 100644 --- a/versions/run.ver.wcoss2 +++ b/versions/run.ver.wcoss2 @@ -2,4 +2,4 @@ export intel_ver=19.1.3.304 export python_ver=3.8.6 -export rocoto_ver=1.3.4 +export rocoto_ver=1.3.5 From 3f4cfcf7f08bc350d33ef6f144deaa651d8e2096 Mon Sep 17 00:00:00 2001 From: danielabdi-noaa <52012304+danielabdi-noaa@users.noreply.github.com> Date: Fri, 28 Oct 2022 17:40:01 -0600 Subject: [PATCH 09/45] Avoid the effect of external environment on tasks (#436) * Enable SCHED_NATIVE_CMD on all systems. * Don't export variables for those that use SLURM. * Add some missing task specific modulefiles. * Try with an empty native line on cheyenne --- .../tasks/cheyenne/make_sfc_climo.local.lua | 1 + .../tasks/gaea/make_sfc_climo.local.lua | 1 + .../tasks/hera/make_sfc_climo.local.lua | 1 + .../tasks/jet/make_sfc_climo.local.lua | 1 + .../tasks/wcoss2/make_sfc_climo.local.lua | 2 + parm/FV3LAM_wflow.xml | 86 +------------------ ush/load_modules_run_task.sh | 4 - ush/machine/gaea.yaml | 8 +- ush/machine/hera.yaml | 7 +- ush/machine/jet.yaml | 7 +- ush/machine/noaacloud.yaml | 2 +- ush/machine/odin.yaml | 9 +- ush/machine/orion.yaml | 7 +- ush/machine/singularity.yaml | 1 + ush/machine/stampede.yaml | 1 + 15 files changed, 34 insertions(+), 104 deletions(-) create mode 100644 modulefiles/tasks/cheyenne/make_sfc_climo.local.lua create mode 100644 modulefiles/tasks/gaea/make_sfc_climo.local.lua create mode 100644 modulefiles/tasks/hera/make_sfc_climo.local.lua create mode 100644 modulefiles/tasks/jet/make_sfc_climo.local.lua create mode 100644 modulefiles/tasks/wcoss2/make_sfc_climo.local.lua diff --git a/modulefiles/tasks/cheyenne/make_sfc_climo.local.lua b/modulefiles/tasks/cheyenne/make_sfc_climo.local.lua new file mode 100644 index 0000000000..494c85136d --- /dev/null +++ b/modulefiles/tasks/cheyenne/make_sfc_climo.local.lua @@ -0,0 +1 @@ +load("conda_regional_workflow") diff --git a/modulefiles/tasks/gaea/make_sfc_climo.local.lua b/modulefiles/tasks/gaea/make_sfc_climo.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/make_sfc_climo.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/make_sfc_climo.local.lua b/modulefiles/tasks/hera/make_sfc_climo.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/hera/make_sfc_climo.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/make_sfc_climo.local.lua b/modulefiles/tasks/jet/make_sfc_climo.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/jet/make_sfc_climo.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/make_sfc_climo.local.lua b/modulefiles/tasks/wcoss2/make_sfc_climo.local.lua new file mode 100644 index 0000000000..16559474cd --- /dev/null +++ b/modulefiles/tasks/wcoss2/make_sfc_climo.local.lua @@ -0,0 +1,2 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) diff --git a/parm/FV3LAM_wflow.xml b/parm/FV3LAM_wflow.xml index 1a7593a751..a0be3cc87f 100644 --- a/parm/FV3LAM_wflow.xml +++ b/parm/FV3LAM_wflow.xml @@ -22,7 +22,11 @@ Parameters needed by the job scheduler. +{%- if sched_native_cmd %} +{%- else %} + +{%- endif %} @@ -204,9 +208,7 @@ MODULES_RUN_TASK_FP script. {{ nnodes_make_grid }}:ppn={{ ppn_make_grid }} {{ wtime_make_grid }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &MAKE_GRID_TN; &LOGDIR;/&MAKE_GRID_TN;&LOGEXT; @@ -230,9 +232,7 @@ MODULES_RUN_TASK_FP script. {{ nnodes_make_orog }}:ppn={{ ppn_make_orog }} {{ wtime_make_orog }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &MAKE_OROG_TN; &LOGDIR;/&MAKE_OROG_TN;&LOGEXT; @@ -264,9 +264,7 @@ MODULES_RUN_TASK_FP script. {{ nnodes_make_sfc_climo }}:ppn={{ ppn_make_sfc_climo }} {{ wtime_make_sfc_climo }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &MAKE_SFC_CLIMO_TN; &LOGDIR;/&MAKE_SFC_CLIMO_TN;&LOGEXT; @@ -305,9 +303,7 @@ MODULES_RUN_TASK_FP script. {{ nnodes_get_extrn_ics }}:ppn={{ ppn_get_extrn_ics }} {{ wtime_get_extrn_ics }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &GET_EXTRN_ICS_TN; &LOGDIR;/&GET_EXTRN_ICS_TN;_@Y@m@d@H&LOGEXT; @@ -332,9 +328,7 @@ MODULES_RUN_TASK_FP script. {{ nnodes_get_extrn_lbcs }}:ppn={{ ppn_get_extrn_lbcs }} {{ wtime_get_extrn_lbcs }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &GET_EXTRN_LBCS_TN; &LOGDIR;/&GET_EXTRN_LBCS_TN;_@Y@m@d@H&LOGEXT; @@ -369,9 +363,7 @@ MODULES_RUN_TASK_FP script. {{ nnodes_make_ics }}:ppn={{ ppn_make_ics }} {{ wtime_make_ics }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &MAKE_ICS_TN;{{ uscore_ensmem_name }} &LOGDIR;/&MAKE_ICS_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -418,9 +410,7 @@ MODULES_RUN_TASK_FP script. {{ nnodes_make_lbcs }}:ppn={{ ppn_make_lbcs }} {{ wtime_make_lbcs }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &MAKE_LBCS_TN;{{ uscore_ensmem_name }} &LOGDIR;/&MAKE_LBCS_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -475,9 +465,7 @@ MODULES_RUN_TASK_FP script. {{ nnodes_run_fcst }}:ppn={{ ppn_run_fcst }} &NCORES_PER_NODE; {%- endif %} - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} {{ wtime_run_fcst }} &RUN_FCST_TN;{{ uscore_ensmem_name }} &LOGDIR;/&RUN_FCST_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -530,9 +518,7 @@ later below for other output times. {{ nnodes_run_post }}:ppn={{ ppn_run_post }} {{ wtime_run_post }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn# &LOGDIR;/&RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn#_@Y@m@d@H&LOGEXT; @@ -588,9 +574,7 @@ for other output times. {{ nnodes_run_post }}:ppn={{ ppn_run_post }} {{ wtime_run_post }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn# &LOGDIR;/&RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn#_@Y@m@d@H&LOGEXT; @@ -651,9 +635,7 @@ always zero). {{ nnodes_run_post }}:ppn={{ ppn_run_post }} {{ wtime_run_post }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} {%- if sub_hourly_post %} &RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn# &LOGDIR;/&RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn#_@Y@m@d@H&LOGEXT; @@ -723,9 +705,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_run_post }}:ppn={{ ppn_run_post }} {{ wtime_run_post }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn# &LOGDIR;/&RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn#_@Y@m@d@H&LOGEXT; @@ -767,9 +747,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_get_obs_ccpa }}:ppn={{ ppn_get_obs_ccpa }} {{ wtime_get_obs_ccpa }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &GET_OBS_CCPA_TN; &LOGDIR;/&GET_OBS_CCPA_TN;_@Y@m@d@H&LOGEXT; @@ -797,9 +775,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_get_obs_mrms }}:ppn={{ ppn_get_obs_mrms }} {{ wtime_get_obs_mrms }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &GET_OBS_MRMS_TN; &LOGDIR;/&GET_OBS_MRMS_TN;_@Y@m@d@H&LOGEXT; @@ -828,9 +804,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_get_obs_ndas }}:ppn={{ ppn_get_obs_ndas }} {{ wtime_get_obs_ndas }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &GET_OBS_NDAS_TN; &LOGDIR;/&GET_OBS_NDAS_TN;_@Y@m@d@H&LOGEXT; @@ -857,9 +831,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_GRIDSTAT_TN; &LOGDIR;/&VX_GRIDSTAT_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -911,9 +883,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_GRIDSTAT_REFC_TN; &LOGDIR;/&VX_GRIDSTAT_REFC_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -964,9 +934,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_GRIDSTAT_RETOP_TN; &LOGDIR;/&VX_GRIDSTAT_RETOP_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -1017,9 +985,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_GRIDSTAT_03h_TN; &LOGDIR;/&VX_GRIDSTAT_03h_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -1056,9 +1022,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_GRIDSTAT_06h_TN; &LOGDIR;/&VX_GRIDSTAT_06h_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -1095,9 +1059,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_GRIDSTAT_24h_TN; &LOGDIR;/&VX_GRIDSTAT_24h_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -1134,9 +1096,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_pointstat }}:ppn={{ ppn_vx_pointstat }} {{ wtime_vx_pointstat }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_POINTSTAT_TN; &LOGDIR;/&VX_POINTSTAT_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; @@ -1190,9 +1150,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_TN; &LOGDIR;/&VX_ENSGRID_TN;_@Y@m@d@H&LOGEXT; @@ -1225,9 +1183,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_03h_TN; &LOGDIR;/&VX_ENSGRID_03h_TN;_@Y@m@d@H&LOGEXT; @@ -1260,9 +1216,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_06h_TN; &LOGDIR;/&VX_ENSGRID_06h_TN;_@Y@m@d@H&LOGEXT; @@ -1295,9 +1249,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_24h_TN; &LOGDIR;/&VX_ENSGRID_24h_TN;_@Y@m@d@H&LOGEXT; @@ -1329,9 +1281,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_REFC_TN; &LOGDIR;/&VX_ENSGRID_REFC_TN;_@Y@m@d@H&LOGEXT; @@ -1362,9 +1312,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_RETOP_TN; &LOGDIR;/&VX_ENSGRID_RETOP_TN;_@Y@m@d@H&LOGEXT; @@ -1394,9 +1342,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_mean }}:ppn={{ ppn_vx_ensgrid_mean }} {{ wtime_vx_ensgrid_mean }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_MEAN_TN; &LOGDIR;/&VX_ENSGRID_MEAN_TN;_@Y@m@d@H&LOGEXT; @@ -1428,9 +1374,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_PROB_TN; &LOGDIR;/&VX_ENSGRID_PROB_TN;_@Y@m@d@H&LOGEXT; @@ -1462,9 +1406,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_mean }}:ppn={{ ppn_vx_ensgrid_mean }} {{ wtime_vx_ensgrid_mean }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_MEAN_03h_TN; &LOGDIR;/&VX_ENSGRID_MEAN_03h_TN;_@Y@m@d@H&LOGEXT; @@ -1496,9 +1438,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_PROB_03h_TN; &LOGDIR;/&VX_ENSGRID_PROB_03h_TN;_@Y@m@d@H&LOGEXT; @@ -1531,9 +1471,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_mean }}:ppn={{ ppn_vx_ensgrid_mean }} {{ wtime_vx_ensgrid_mean }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_MEAN_06h_TN; &LOGDIR;/&VX_ENSGRID_MEAN_06h_TN;_@Y@m@d@H&LOGEXT; @@ -1565,9 +1503,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_PROB_06h_TN; &LOGDIR;/&VX_ENSGRID_PROB_06h_TN;_@Y@m@d@H&LOGEXT; @@ -1600,9 +1536,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_mean }}:ppn={{ ppn_vx_ensgrid_mean }} {{ wtime_vx_ensgrid_mean }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_MEAN_24h_TN; &LOGDIR;/&VX_ENSGRID_MEAN_24h_TN;_@Y@m@d@H&LOGEXT; @@ -1634,9 +1568,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_PROB_24h_TN; &LOGDIR;/&VX_ENSGRID_PROB_24h_TN;_@Y@m@d@H&LOGEXT; @@ -1668,9 +1600,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_PROB_REFC_TN; &LOGDIR;/&VX_ENSGRID_PROB_REFC_TN;_@Y@m@d@H&LOGEXT; @@ -1701,9 +1631,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSGRID_PROB_RETOP_TN; &LOGDIR;/&VX_ENSGRID_PROB_RETOP_TN;_@Y@m@d@H&LOGEXT; @@ -1735,9 +1663,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_enspoint }}:ppn={{ ppn_vx_enspoint }} {{ wtime_vx_enspoint }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSPOINT_TN; &LOGDIR;/&VX_ENSPOINT_TN;_@Y@m@d@H&LOGEXT; @@ -1766,9 +1692,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_enspoint_mean }}:ppn={{ ppn_vx_enspoint_mean }} {{ wtime_vx_enspoint_mean }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSPOINT_MEAN_TN; &LOGDIR;/&VX_ENSPOINT_MEAN_TN;_@Y@m@d@H&LOGEXT; @@ -1797,9 +1721,7 @@ the tag to be identical to the ones above for other output times. {{ nnodes_vx_enspoint_prob }}:ppn={{ ppn_vx_enspoint_prob }} {{ wtime_vx_enspoint_prob }} &NCORES_PER_NODE; - {%- if machine in ["GAEA"] %} &SCHED_NATIVE_CMD; - {%- endif %} &VX_ENSPOINT_PROB_TN; &LOGDIR;/&VX_ENSPOINT_PROB_TN;_@Y@m@d@H&LOGEXT; diff --git a/ush/load_modules_run_task.sh b/ush/load_modules_run_task.sh index efd14c88ab..6d5f8cde50 100755 --- a/ush/load_modules_run_task.sh +++ b/ush/load_modules_run_task.sh @@ -184,10 +184,6 @@ module list if [ -n "${SRW_ENV:-}" ] ; then set +u conda activate ${SRW_ENV} - if [ $machine = "gaea" ]; then - conda deactivate - conda activate ${SRW_ENV} - fi set -u fi diff --git a/ush/machine/gaea.yaml b/ush/machine/gaea.yaml index aa16540124..a2a2b47090 100644 --- a/ush/machine/gaea.yaml +++ b/ush/machine/gaea.yaml @@ -11,11 +11,11 @@ platform: QUEUE_DEFAULT: normal QUEUE_FCST: normal QUEUE_HPSS: normal - RUN_CMD_FCST: srun --mpi=pmi2 -n ${PE_MEMBER01} - RUN_CMD_POST: srun --mpi=pmi2 -n $nprocs + RUN_CMD_FCST: srun --export=ALL --mpi=pmi2 -n ${PE_MEMBER01} + RUN_CMD_POST: srun --export=ALL --mpi=pmi2 -n $nprocs RUN_CMD_SERIAL: time - RUN_CMD_UTILS: srun --mpi=pmi2 -n $nprocs - SCHED_NATIVE_CMD: -M c3 + RUN_CMD_UTILS: srun --export=ALL --mpi=pmi2 -n $nprocs + SCHED_NATIVE_CMD: -M c3 --export=NONE PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' TEST_EXTRN_MDL_SOURCE_BASEDIR: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/input_model_data TEST_PREGEN_BASEDIR: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/FV3LAM_pregen diff --git a/ush/machine/hera.yaml b/ush/machine/hera.yaml index e2f2ac12f7..21617c8d0d 100644 --- a/ush/machine/hera.yaml +++ b/ush/machine/hera.yaml @@ -15,10 +15,11 @@ platform: QUEUE_FCST: batch PARTITION_HPSS: service QUEUE_HPSS: batch - RUN_CMD_FCST: srun - RUN_CMD_POST: srun + RUN_CMD_FCST: srun --export=ALL + RUN_CMD_POST: srun --export=ALL RUN_CMD_SERIAL: time - RUN_CMD_UTILS: srun + RUN_CMD_UTILS: srun --export=ALL + SCHED_NATIVE_CMD: --export=NONE PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' TEST_EXTRN_MDL_SOURCE_BASEDIR: /scratch2/BMC/det/UFS_SRW_App/develop/input_model_data TEST_PREGEN_BASEDIR: /scratch2/BMC/det/UFS_SRW_App/develop/FV3LAM_pregen diff --git a/ush/machine/jet.yaml b/ush/machine/jet.yaml index cf8545de75..37dd70ea85 100644 --- a/ush/machine/jet.yaml +++ b/ush/machine/jet.yaml @@ -15,10 +15,11 @@ platform: QUEUE_FCST: batch PARTITION_HPSS: service QUEUE_HPSS: batch - RUN_CMD_FCST: srun - RUN_CMD_POST: srun + RUN_CMD_FCST: srun --export=ALL + RUN_CMD_POST: srun --export=ALL RUN_CMD_SERIAL: time - RUN_CMD_UTILS: srun + RUN_CMD_UTILS: srun --export=ALL + SCHED_NATIVE_CMD: --export=NONE PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' TEST_EXTRN_MDL_SOURCE_BASEDIR: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/input_model_data TEST_PREGEN_BASEDIR: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/FV3LAM_pregen diff --git a/ush/machine/noaacloud.yaml b/ush/machine/noaacloud.yaml index ffa371ba2d..32246aae54 100644 --- a/ush/machine/noaacloud.yaml +++ b/ush/machine/noaacloud.yaml @@ -12,8 +12,8 @@ platform: RUN_CMD_POST: mpiexec -np $nprocs RUN_CMD_SERIAL: time RUN_CMD_UTILS: mpiexec -np $nprocs + SCHED_NATIVE_CMD: --export=NONE PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' - BUILD_MOD_FN: wflow_noaacloud TEST_EXTRN_MDL_SOURCE_BASEDIR: /contrib/EPIC/UFS_SRW_App/develop/input_model_data TEST_PREGEN_BASEDIR: /contrib/EPIC/UFS_SRW_App/develop/FV3LAM_pregen TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS: /contrib/EPIC/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir diff --git a/ush/machine/odin.yaml b/ush/machine/odin.yaml index 38caa4bfc1..dbf9bb2a8b 100644 --- a/ush/machine/odin.yaml +++ b/ush/machine/odin.yaml @@ -9,10 +9,11 @@ platform: QUEUE_FCST: workq PARTITION_HPSS: workq QUEUE_HPSS: workq - RUN_CMD_FCST: srun -n ${PE_MEMBER01} - RUN_CMD_POST: srun -n 1 - RUN_CMD_SERIAL: srun -n 1 - RUN_CMD_UTILS: srun -n $nprocs + RUN_CMD_FCST: srun --export=ALL -n ${PE_MEMBER01} + RUN_CMD_POST: srun --export=ALL -n 1 + RUN_CMD_SERIAL: srun --export=ALL -n 1 + RUN_CMD_UTILS: srun --export=ALL -n $nprocs + SCHED_NATIVE_CMD: --export=NONE PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' TEST_EXTRN_MDL_SOURCE_BASEDIR: /scratch/ywang/UFS_SRW_App/develop/input_model_data TEST_PREGEN_BASEDIR: /scratch/ywang/UFS_SRW_App/develop/FV3LAM_pregen diff --git a/ush/machine/orion.yaml b/ush/machine/orion.yaml index b57a563cd2..00aba1a85b 100644 --- a/ush/machine/orion.yaml +++ b/ush/machine/orion.yaml @@ -15,10 +15,11 @@ platform: QUEUE_FCST: batch PARTITION_HPSS: service QUEUE_HPSS: batch - RUN_CMD_FCST: srun -n ${PE_MEMBER01} - RUN_CMD_POST: srun + RUN_CMD_FCST: srun --export=ALL -n ${PE_MEMBER01} + RUN_CMD_POST: srun --export=ALL RUN_CMD_SERIAL: time - RUN_CMD_UTILS: srun + RUN_CMD_UTILS: srun --export=ALL + SCHED_NATIVE_CMD: --export=NONE PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' TEST_EXTRN_MDL_SOURCE_BASEDIR: /work/noaa/fv3-cam/UFS_SRW_App/develop/input_model_data TEST_PREGEN_BASEDIR: /work/noaa/fv3-cam/UFS_SRW_App/develop/FV3LAM_pregen diff --git a/ush/machine/singularity.yaml b/ush/machine/singularity.yaml index 40f3a3915a..3fbea67c69 100644 --- a/ush/machine/singularity.yaml +++ b/ush/machine/singularity.yaml @@ -13,6 +13,7 @@ platform: RUN_CMD_POST: mpirun -np $nprocs --oversubscribe RUN_CMD_SERIAL: time RUN_CMD_UTILS: mpirun -np $nprocs --oversubscribe + SCHED_NATIVE_CMD: --export=NONE PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' task_make_orog: TOPO_DIR: /contrib/global/glopara/fix/fix_orog diff --git a/ush/machine/stampede.yaml b/ush/machine/stampede.yaml index 64ed089377..4dbb1ccdb6 100644 --- a/ush/machine/stampede.yaml +++ b/ush/machine/stampede.yaml @@ -13,6 +13,7 @@ platform: RUN_CMD_POST: ibrun -np $nprocs RUN_CMD_SERIAL: time RUN_CMD_UTILS: ibrun -np $nprocs + SCHED_NATIVE_CMD: --export=NONE PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' TEST_EXTRN_MDL_SOURCE_BASEDIR: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/input_model_data TEST_PREGEN_BASEDIR: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/FV3LAM_pregen From 2f8bd2693751760100a1d378a7b3e9f995ac0386 Mon Sep 17 00:00:00 2001 From: danielabdi-noaa <52012304+danielabdi-noaa@users.noreply.github.com> Date: Fri, 28 Oct 2022 21:05:09 -0600 Subject: [PATCH 10/45] Bug fix on hera/jet run_vx.local modulefile. (#438) * Bug fix on hera/jet run_vx.local modulefile. * Turn off formatting for some blocks of code. --- modulefiles/tasks/hera/run_vx.local.lua | 2 +- modulefiles/tasks/jet/run_vx.local.lua | 2 +- ush/config_defaults.yaml | 18 ------------------ ush/test_retrieve_data.py | 20 ++++++++++++++++++++ 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/modulefiles/tasks/hera/run_vx.local.lua b/modulefiles/tasks/hera/run_vx.local.lua index 4fc605bc83..ce3212dfe9 100644 --- a/modulefiles/tasks/hera/run_vx.local.lua +++ b/modulefiles/tasks/hera/run_vx.local.lua @@ -1,3 +1,3 @@ append_path("MODULEPATH", "/contrib/anaconda/modulefiles") -load(pathJoin("intel", os.gentenv("intel_ver") or "18.0.5.274")) +load(pathJoin("intel", os.getenv("intel_ver") or "18.0.5.274")) load(pathJoin("anaconda", os.getenv("anaconda_ver") or "latest")) diff --git a/modulefiles/tasks/jet/run_vx.local.lua b/modulefiles/tasks/jet/run_vx.local.lua index 26cbb9088c..13b6b4b954 100644 --- a/modulefiles/tasks/jet/run_vx.local.lua +++ b/modulefiles/tasks/jet/run_vx.local.lua @@ -1,3 +1,3 @@ append_path("MODULEPATH", "/contrib/anaconda/modulefiles") -load(pathJoin("intel", os.gentenv("intel_ver") or "18.0.5.274")) +load(pathJoin("intel", os.getenv("intel_ver") or "18.0.5.274")) load(pathJoin("anaconda", os.getenv("anaconda_ver") or "5.3.1")) diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 43d29abe2f..1a25bee535 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -1575,24 +1575,6 @@ task_run_fcst: # #----------------------------------------------------------------------- # - # Set the array parameter containing the names of all the fields that the - # MAKE_SFC_CLIMO_TN task generates on the native FV3-LAM grid. - # - #----------------------------------------------------------------------- - # - SFC_CLIMO_FIELDS: [ - "facsf", - "maximum_snow_albedo", - "slope_type", - "snowfree_albedo", - "soil_type", - "substrate_temperature", - "vegetation_greenness", - "vegetation_type" - ] - # - #----------------------------------------------------------------------- - # # Set parameters associated with the fixed (i.e. static) files. Definitions: # # SYMLINK_FIX_FILES: diff --git a/ush/test_retrieve_data.py b/ush/test_retrieve_data.py index dc7a775f05..dffa638562 100644 --- a/ush/test_retrieve_data.py +++ b/ush/test_retrieve_data.py @@ -39,6 +39,7 @@ def test_fv3gfs_grib2_lbcs_from_hpss(self): with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) + # fmt: off args = [ '--anl_or_fcst', 'fcst', '--config', self.config, @@ -50,6 +51,7 @@ def test_fv3gfs_grib2_lbcs_from_hpss(self): '--debug', '--file_type', 'grib2', ] + # fmt: on retrieve_data.main(args) @@ -69,6 +71,7 @@ def test_fv3gfs_netcdf_lbcs_from_hpss(self): with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) + # fmt: off args = [ '--anl_or_fcst', 'fcst', '--config', self.config, @@ -80,6 +83,7 @@ def test_fv3gfs_netcdf_lbcs_from_hpss(self): '--debug', '--file_type', 'netcdf', ] + # fmt: on retrieve_data.main(args) @@ -99,6 +103,7 @@ def test_gdas_ics_from_aws(self): out_path_tmpl = f"mem{{mem:03d}}" + # fmt: off args = [ '--anl_or_fcst', 'anl', '--config', self.config, @@ -111,6 +116,7 @@ def test_gdas_ics_from_aws(self): '--file_type', 'netcdf', '--members', '9', '10', ] + # fmt: on retrieve_data.main(args) @@ -132,6 +138,7 @@ def test_gefs_grib2_ics_from_aws(self): out_path_tmpl = f"mem{{mem:03d}}" + # fmt: off args = [ '--anl_or_fcst', 'anl', '--config', self.config, @@ -144,6 +151,7 @@ def test_gefs_grib2_ics_from_aws(self): '--file_type', 'netcdf', '--members', '1', '2', ] + # fmt: on retrieve_data.main(args) @@ -163,6 +171,7 @@ def test_hrrr_ics_from_hpss(self): with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) + # fmt: off args = [ '--anl_or_fcst', 'anl', '--config', self.config, @@ -173,6 +182,7 @@ def test_hrrr_ics_from_hpss(self): '--output_path', tmp_dir, '--debug', ] + # fmt: on retrieve_data.main(args) @@ -190,6 +200,7 @@ def test_hrrr_lbcs_from_hpss(self): with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) + # fmt: off args = [ '--anl_or_fcst', 'fcst', '--config', self.config, @@ -200,6 +211,7 @@ def test_hrrr_lbcs_from_hpss(self): '--output_path', tmp_dir, '--debug', ] + # fmt: on retrieve_data.main(args) @@ -216,6 +228,7 @@ def test_hrrr_ics_from_aws(self): with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) + # fmt: off args = [ '--anl_or_fcst', 'anl', '--config', self.config, @@ -226,6 +239,7 @@ def test_hrrr_ics_from_aws(self): '--output_path', tmp_dir, '--debug', ] + # fmt: on retrieve_data.main(args) @@ -242,6 +256,7 @@ def test_hrrr_lbcs_from_aws(self): with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) + # fmt: off args = [ '--anl_or_fcst', 'fcst', '--config', self.config, @@ -252,6 +267,7 @@ def test_hrrr_lbcs_from_aws(self): '--output_path', tmp_dir, '--debug', ] + # fmt: on retrieve_data.main(args) @@ -269,6 +285,7 @@ def test_rap_ics_from_aws(self): with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) + # fmt: off args = [ '--anl_or_fcst', 'anl', '--config', self.config, @@ -279,6 +296,7 @@ def test_rap_ics_from_aws(self): '--output_path', tmp_dir, '--debug', ] + # fmt: on retrieve_data.main(args) @@ -296,6 +314,7 @@ def test_rap_lbcs_from_aws(self): with tempfile.TemporaryDirectory(dir=".") as tmp_dir: os.chdir(tmp_dir) + # fmt: off args = [ '--anl_or_fcst', 'fcst', '--config', self.config, @@ -306,6 +325,7 @@ def test_rap_lbcs_from_aws(self): '--output_path', tmp_dir, '--debug', ] + # fmt: on retrieve_data.main(args) From b213ccc714e206ff7fdc4dcd15bd894b8338a97f Mon Sep 17 00:00:00 2001 From: danielabdi-noaa <52012304+danielabdi-noaa@users.noreply.github.com> Date: Sat, 29 Oct 2022 18:20:09 -0600 Subject: [PATCH 11/45] Make CIs test NCO mode properly. (#418) --- .cicd/scripts/srw_test.sh | 3 ++- parm/FV3LAM_wflow.xml | 2 +- tests/WE2E/setup_WE2E_tests.sh | 10 ++++++++-- ush/job_preamble.sh | 9 +++++++++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/.cicd/scripts/srw_test.sh b/.cicd/scripts/srw_test.sh index e884a66aad..d6b6134993 100755 --- a/.cicd/scripts/srw_test.sh +++ b/.cicd/scripts/srw_test.sh @@ -28,6 +28,7 @@ fi # Test directories we2e_experiment_base_dir="${workspace}/expt_dirs" we2e_test_dir="${workspace}/tests/WE2E" +nco_dir="${workspace}/nco_dirs" # Run the end-to-end tests. if "${SRW_WE2E_COMPREHENSIVE_TESTS}"; then @@ -37,7 +38,7 @@ else fi cd ${we2e_test_dir} -./setup_WE2E_tests.sh ${platform} ${SRW_PROJECT} ${SRW_COMPILER} ${test_type} ${we2e_experiment_base_dir} +./setup_WE2E_tests.sh ${platform} ${SRW_PROJECT} ${SRW_COMPILER} ${test_type} ${we2e_experiment_base_dir} ${nco_dir} # Allow the tests to start before checking for status. # TODO: Create a parameter that sets the initial start delay. diff --git a/parm/FV3LAM_wflow.xml b/parm/FV3LAM_wflow.xml index a0be3cc87f..e1696ae5a8 100644 --- a/parm/FV3LAM_wflow.xml +++ b/parm/FV3LAM_wflow.xml @@ -163,7 +163,7 @@ tasks; and the "FCST" type is used for the RUN_FCST_TN task. {%- if run_envir == "nco" %} - &LOGDIR;/FV3LAM_wflow_{{ workflow_id }}.log + &LOGDIR;/FV3LAM_wflow.{{ workflow_id }}.log {%- else %} &LOGDIR;/FV3LAM_wflow.log {%- endif %} diff --git a/tests/WE2E/setup_WE2E_tests.sh b/tests/WE2E/setup_WE2E_tests.sh index cf2b4ec1dc..823829304d 100755 --- a/tests/WE2E/setup_WE2E_tests.sh +++ b/tests/WE2E/setup_WE2E_tests.sh @@ -25,13 +25,15 @@ function usage { echo - echo "Usage: $0 machine slurm_account [compiler] [test_type] [expt_dirs] | -h" + echo "Usage: $0 machine slurm_account [compiler] [test_type] [expts_dir] [nco_dirs] [run_envir] | -h" echo echo " machine [required] is one of: ${machines[@]}" echo " slurm_account [required] case sensitive name of the user-specific slurm account" echo " compiler [optional] compiler used for build" echo " test_type [optional] test type: fundamental or comprehensive or all or any other name" echo " expts_dir [optional] Experiment base directory" + echo " nco_dirs [optional] NCO operations root directory" + echo " run_envir [optional] either 'community' or 'nco' " echo " -h display this help" echo exit 1 @@ -61,6 +63,9 @@ SRW_APP_DIR=$( dirname "${TESTS_DIR}" ) TOP_DIR=$( dirname "${SRW_APP_DIR}" ) EXPTS_DIR=${5:-"${TOP_DIR}/expt_dirs"} +NCO_DIR=${6:-"${TOP_DIR}/nco_dirs"} + +RUN_ENVIR=${7:-""} #---------------------------------------------------------------------- # Use exec_subdir consistent with the automated build. @@ -83,8 +88,9 @@ source ${SRW_APP_DIR}/ush/load_modules_wflow.sh ${machine} exec_subdir=${exec_subdir} \ compiler=${compiler} \ expt_basedir=${EXPTS_DIR} \ + opsroot=${NCO_DIR} \ debug="TRUE" \ verbose="TRUE" \ cron_relaunch_intvl_mnts=4 \ - run_envir="community" + run_envir=${RUN_ENVIR} diff --git a/ush/job_preamble.sh b/ush/job_preamble.sh index 52667a112d..63ffb1bbeb 100644 --- a/ush/job_preamble.sh +++ b/ush/job_preamble.sh @@ -118,9 +118,18 @@ fi function job_postamble() { if [ "${RUN_ENVIR}" = "nco" ]; then + # Remove temp directory cd ${DATAROOT} [[ $KEEPDATA = "FALSE" ]] && rm -rf $DATA $DATA_SHARED + + # Create symlinks to log files + local EXPTLOG=${EXPTDIR}/log + mkdir_vrfy -p ${EXPTLOG} + for i in ${LOGDIR}/*.${WORKFLOW_ID}.log; do + local LOGB=$(basename $i .${WORKFLOW_ID}.log) + ln_vrfy -sf $i ${EXPTLOG}/${LOGB}.log + done fi # Print exit message From ce024c4582e203ee400759fa2cf7d6879f76d2c3 Mon Sep 17 00:00:00 2001 From: danielabdi-noaa <52012304+danielabdi-noaa@users.noreply.github.com> Date: Sat, 29 Oct 2022 18:20:30 -0600 Subject: [PATCH 12/45] Make CIs test NCO mode properly. (#418) From 0e11b9d4ec37885f09399c8938c7106e72d8877c Mon Sep 17 00:00:00 2001 From: Gillian Petro <96886803+gspetro-NOAA@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:36:20 -0400 Subject: [PATCH 13/45] [develop] Update Build/Run and ConfigWorkflow Chapters (#425) * update stochastic physics link * add HPC-Stack Intersphinx links * remove hpc-stack submodule in favor of intersphinx links * move tables to 'tables' directory * remove duplicate Glossary terms; update links * update Quickstart * add M. Leukin to mgmt team list; change expt gen command * fix typo * fix typo * add stochastic physics link & troubleshooting tips * separate Build & Run chapters; update crosslinks * minor fix * update file exts in Config Params chapter * update user/platform sections of Config Params Chapter * update file name params * grid_gen, verbose, compiler, etc. params * ConfigWorkflow 1st draft revision * add met docs to intersphinx * fix minor errors * updated table 4.1 * add default values to ConfigWorkflow, other minor fixes * add RRFS and GSI to Glossary * update tables & file exts * add L1 data locations * address comments in ConfigWorkflow * fix table * minor fixes * minor updates * rm reg_wflow references, update tables, minor updates * switch order of steps so python env is loaded first * edit and rearrange pyenv and config BR sections * edit mac/linux/VX config sections * 1st draft of RunSRW * add parameter definitions that were accidentally deleted in .sh --> .yaml switch * remove comments * fix typo * fix link * add info from Mike L. * update build & workflow images * update workflow generation image * update image * update image * fix reviewer comments * update expt gen image * rm reg_wflow refs, switch config.sh to .yaml, update directory structure in intro * rm reg_wflow refs, switch config.sh to .yaml * change templates dir to parm * update GSI glossary entry * fixes based on PR review * remove fixed file mapping params * remove SFC_CLIMO_FIELDS from config_defaults.yaml/ConfigWorkflow.rst * update info on data: section of machine file * minor wording fix * minor wording fix * add note about converting ols .sh file to .yaml * update intro forum link, minor wording/details * update pngs, RRFS note, minor intro fixes * update wflow gen img Co-authored-by: gspetro --- docs/UsersGuide/source/BuildRunSRW.rst | 1632 ----------- docs/UsersGuide/source/BuildSRW.rst | 496 ++++ docs/UsersGuide/source/Components.rst | 2 +- docs/UsersGuide/source/ConfigWorkflow.rst | 2465 ++++++++++------- .../UsersGuide/source/ContainerQuickstart.rst | 12 +- docs/UsersGuide/source/ContributorsGuide.rst | 34 +- docs/UsersGuide/source/FAQ.rst | 4 +- docs/UsersGuide/source/Glossary.rst | 18 + docs/UsersGuide/source/Graphics.rst | 16 +- docs/UsersGuide/source/InputOutputFiles.rst | 34 +- docs/UsersGuide/source/Introduction.rst | 83 +- docs/UsersGuide/source/LAMGrids.rst | 18 +- docs/UsersGuide/source/Quickstart.rst | 40 +- docs/UsersGuide/source/RocotoInfo.rst | 6 +- docs/UsersGuide/source/RunSRW.rst | 1259 +++++++++ docs/UsersGuide/source/WE2Etests.rst | 20 +- .../source/_static/SRW_build_process.png | Bin 0 -> 59669 bytes .../_static/SRW_overall_workflow_run.png | Bin 0 -> 84193 bytes .../_static/SRW_regional_workflow_gen.png | Bin 0 -> 163031 bytes .../source/_static/SRW_wflow_flowchart.png | Bin 0 -> 145622 bytes docs/UsersGuide/source/conf.py | 1 + docs/UsersGuide/source/index.rst | 3 +- docs/UsersGuide/source/tables/Tests.rst | 2 +- ush/config_defaults.yaml | 313 ++- 24 files changed, 3637 insertions(+), 2821 deletions(-) delete mode 100644 docs/UsersGuide/source/BuildRunSRW.rst create mode 100644 docs/UsersGuide/source/BuildSRW.rst create mode 100644 docs/UsersGuide/source/RunSRW.rst create mode 100644 docs/UsersGuide/source/_static/SRW_build_process.png create mode 100644 docs/UsersGuide/source/_static/SRW_overall_workflow_run.png create mode 100644 docs/UsersGuide/source/_static/SRW_regional_workflow_gen.png create mode 100644 docs/UsersGuide/source/_static/SRW_wflow_flowchart.png diff --git a/docs/UsersGuide/source/BuildRunSRW.rst b/docs/UsersGuide/source/BuildRunSRW.rst deleted file mode 100644 index 9e0da6016a..0000000000 --- a/docs/UsersGuide/source/BuildRunSRW.rst +++ /dev/null @@ -1,1632 +0,0 @@ -.. _BuildRunSRW: - -===================================== -Building and Running the SRW App -===================================== - -The Unified Forecast System (:term:`UFS`) Short-Range Weather (SRW) Application is an :term:`umbrella repository` consisting of a number of different :ref:`components ` housed in external repositories. Once the SRW App is built, users can configure an experiment and generate predictions of atmospheric behavior over a limited spatial area and on time scales ranging from minutes out to several days. - -This chapter walks users through how to build and run the "out-of-the-box" case for the SRW App. However, the steps are relevant to any SRW Application experiment and can be modified to suit user goals. The out-of-the-box SRW App case builds a weather forecast for June 15-16, 2019. Multiple convective weather events during these two days produced over 200 filtered storm reports. Severe weather was clustered in two areas: the Upper Midwest through the Ohio Valley and the Southern Great Plains. This forecast uses a predefined 25-km Continental United States (:term:`CONUS`) domain (RRFS_CONUS_25km), the Global Forecast System (:term:`GFS`) version 16 physics suite (FV3_GFS_v16 :term:`CCPP`), and :term:`FV3`-based GFS raw external model data for initialization. - -.. attention:: - - The SRW Application has `four levels of support `__. The steps described in this chapter will work most smoothly on preconfigured (Level 1) systems. This chapter can also serve as a starting point for running the SRW App on other systems (including generic Linux/Mac systems), but the user may need to perform additional troubleshooting. - -.. note:: - The :ref:`container approach ` is recommended for a smoother first-time build and run experience. Building without a container may allow for more customization. However, the non-container approach requires more in-depth system-based knowledge, especially on Level 3 and 4 systems, so it is less appropriate for beginners. - -The overall procedure for generating an experiment is shown in :numref:`Figure %s `, with the scripts to generate and run the workflow shown in red. The steps are as follows: - - #. :ref:`Install prerequisites ` - #. :ref:`Clone the SRW App from GitHub ` - #. :ref:`Check out the external repositories ` - #. :ref:`Set up the build environment and build the executables ` - #. :ref:`Download and stage data ` - #. :ref:`Optional: Configure a new grid ` - #. :ref:`Generate a regional workflow experiment ` - - * :ref:`Configure the experiment parameters ` - * :ref:`Load the python environment for the regional workflow ` - - #. :ref:`Run the regional workflow ` - #. :ref:`Optional: Plot the output ` - -.. _AppOverallProc: - -.. figure:: _static/FV3LAM_wflow_overall.png - :alt: Flowchart describing the SRW App workflow steps. - - *Overall layout of the SRW App Workflow* - - -.. _HPCstackInfo: - -Install the HPC-Stack -======================== - -.. Attention:: - Skip the HPC-Stack installation if working on a `Level 1 system `_ (e.g., Cheyenne, Hera, Orion, NOAA Cloud). - -**Definition:** :term:`HPC-Stack` is a repository that provides a unified, shell script-based build system to build the software stack required for `UFS `_ applications such as the SRW App. - -Background ----------------- - -The UFS Weather Model draws on over 50 code libraries to run its applications. These libraries range from libraries developed in-house at NOAA (e.g., NCEPLIBS, FMS) to libraries developed by NOAA's partners (e.g., PIO, ESMF) to truly third party libraries (e.g., NETCDF). Individual installation of these libraries is not practical, so the `HPC-Stack `__ was developed as a central installation system to ensure that the infrastructure environment across multiple platforms is as similar as possible. Installation of the HPC-Stack is required to run the SRW App. - -Instructions -------------------------- -Users working on systems that fall under `Support Levels 2-4 `__ will need to install the HPC-Stack the first time they try to build applications (such as the SRW App) that depend on it. Users can either build the HPC-Stack on their local system or use the centrally maintained stacks on each HPC platform if they are working on a Level 1 system. Before installing the HPC-Stack, users on both Linux and MacOS systems should set the stack size to "unlimited" (if allowed) or to the largest possible value: - -.. code-block:: console - - # Linux, if allowed - ulimit -s unlimited - - # MacOS, this corresponds to 65MB - ulimit -S -s unlimited - -For a detailed description of installation options, see :ref:`Installing the HPC-Stack `. - -After completing installation, continue to the next section (:numref:`Section %s: Download the UFS SRW Application Code `). - -.. _DownloadSRWApp: - -Download the UFS SRW Application Code -====================================== -The SRW Application source code is publicly available on GitHub. To download the SRW App code, clone the ``develop`` branch of the repository: - -.. code-block:: console - - git clone -b develop https://github.com/ufs-community/ufs-srweather-app.git - -The cloned repository contains the configuration files and sub-directories shown in -:numref:`Table %s `. The user may set an ``$SRW`` environment variable to point to the location of the new ``ufs-srweather-app`` repository. For example, if ``ufs-srweather-app`` was cloned into the ``$HOME`` directory, the following commands will set an ``$SRW`` environment variable in a bash or csh shell, respectively: - -.. code-block:: console - - export SRW=$HOME/ufs-srweather-app - setenv SRW $HOME/ufs-srweather-app - -.. _FilesAndSubDirs: - -.. table:: Files and sub-directories of the ufs-srweather-app repository - - +--------------------------------+--------------------------------------------------------+ - | **File/Directory Name** | **Description** | - +================================+========================================================+ - | CMakeLists.txt | Main CMake file for SRW App | - +--------------------------------+--------------------------------------------------------+ - | Externals.cfg | Includes tags pointing to the correct version of the | - | | external GitHub repositories/branches used in the SRW | - | | App. | - +--------------------------------+--------------------------------------------------------+ - | LICENSE.md | CC0 license information | - +--------------------------------+--------------------------------------------------------+ - | README.md | Getting Started Guide | - +--------------------------------+--------------------------------------------------------+ - | ufs_srweather_app_meta.h.in | Meta information for SRW App which can be used by | - | | other packages | - +--------------------------------+--------------------------------------------------------+ - | ufs_srweather_app.settings.in | SRW App configuration summary | - +--------------------------------+--------------------------------------------------------+ - | modulefiles | Contains build and workflow modulefiles | - +--------------------------------+--------------------------------------------------------+ - | etc | Contains Lmod startup scripts | - +--------------------------------+--------------------------------------------------------+ - | docs | Contains release notes, documentation, and User's Guide| - +--------------------------------+--------------------------------------------------------+ - | manage_externals | Utility for checking out external repositories | - +--------------------------------+--------------------------------------------------------+ - | src | Contains CMakeLists.txt; external repositories | - | | will be cloned into this directory. | - +--------------------------------+--------------------------------------------------------+ - - -.. _CheckoutExternals: - -Check Out External Components -================================ - -The SRW App relies on a variety of components (e.g., regional_workflow, UFS_UTILS, ufs-weather-model, and UPP) detailed in :numref:`Chapter %s ` of this User's Guide. Each component has its own repository. Users must run the ``checkout_externals`` script to collect the individual components of the SRW App from their respective Git repositories. The ``checkout_externals`` script uses the configuration file ``Externals.cfg`` in the top level directory of the SRW App to clone the correct tags (code versions) of the external repositories listed in :numref:`Section %s ` into the appropriate directories under the ``regional_workflow`` and ``src`` directories. - -Run the executable that pulls in SRW App components from external repositories: - -.. code-block:: console - - cd $SRW - ./manage_externals/checkout_externals - -The script should output dialogue indicating that it is retrieving different code repositories. It may take several minutes to download these repositories. - - -.. _BuildExecutables: - -Set Up the Environment and Build the Executables -=================================================== - -.. _DevBuild: - -``devbuild.sh`` Approach ------------------------------ - -On Level 1 systems for which a modulefile is provided under the ``modulefiles`` directory, users can build the SRW App binaries with: - -.. code-block:: console - - ./devbuild.sh --platform= - -where ```` is replaced with the name of the platform the user is working on. Valid values are: ``cheyenne`` | ``gaea`` | ``hera`` | ``jet`` | ``linux`` | ``macos`` | ``noaacloud`` | ``odin`` | ``orion`` | ``singularity`` | ``wcoss2`` - -.. note:: - Although build modulefiles exist for generic Linux and MacOS machines, users will need to alter these according to the instructions in Sections :numref:`%s ` & :numref:`%s `. It is recommended that users on these systems build the SRW App with the :ref:`CMake Approach ` instead. - -If compiler auto-detection fails for some reason, specify it using the ``--compiler`` argument. For example: - -.. code-block:: console - - ./devbuild.sh --platform=hera --compiler=intel - -where valid values are ``intel`` or ``gnu``. - -If users want to build the optional ``GSI`` and ``rrfs_utl`` components for RRFS (NOTE: These components are not currently available for use at runtime), they can add the ``--rrfs`` argument. For example: - -.. code-block:: console - - ./devbuild.sh --platform=hera --rrfs - -The last line of the console output should be ``[100%] Built target ufs-weather-model``, indicating that the UFS Weather Model executable has been built successfully. - -The executables listed in :numref:`Table %s ` should appear in the ``ufs-srweather-app/bin`` directory. If users choose to build the ``GSI`` and ``rrfs_utl`` components, the executables listed in :numref:`Table %s ` will also appear there. If this build method does not work, or if users are not on a supported machine, they will have to manually setup the environment and build the SRW App binaries with CMake as described in :numref:`Section %s `. - - -.. _ExecDescription: - -.. table:: Names and descriptions of the executables produced by the build step and used by the SRW App - - +------------------------+---------------------------------------------------------------------------------+ - | **Executable Name** | **Description** | - +========================+=================================================================================+ - | chgres_cube | Reads in raw external model (global or regional) and surface climatology data | - | | to create initial and lateral boundary conditions | - +------------------------+---------------------------------------------------------------------------------+ - | emcsfc_ice_blend | Blends National Ice Center sea ice cover and EMC sea ice concentration data to | - | | create a global sea ice analysis used to update the GFS once per day | - +------------------------+---------------------------------------------------------------------------------+ - | emcsfc_snow2mdl | Blends National Ice Center snow cover and Air Force snow depth data to create a | - | | global depth analysis used to update the GFS snow field once per day | - +------------------------+---------------------------------------------------------------------------------+ - | filter_topo | Filters topography based on resolution | - +------------------------+---------------------------------------------------------------------------------+ - | fregrid | Remaps data from the input mosaic grid to the output mosaic grid | - +------------------------+---------------------------------------------------------------------------------+ - | fvcom_to_FV3 | Determines lake surface conditions for the Great Lakes | - +------------------------+---------------------------------------------------------------------------------+ - | global_cycle | Updates the GFS surface conditions using external snow and sea ice analyses | - +------------------------+---------------------------------------------------------------------------------+ - | global_equiv_resol | Calculates a global, uniform, cubed-sphere equivalent resolution for the | - | | regional Extended Schmidt Gnomonic (ESG) grid | - +------------------------+---------------------------------------------------------------------------------+ - | inland | Creates an inland land mask by determining in-land (i.e. non-coastal) points | - | | and assigning a value of 1. Default value is 0. | - +------------------------+---------------------------------------------------------------------------------+ - | lakefrac | Calculates the ratio of the lake area to the grid cell area at each atmospheric | - | | grid point. | - +------------------------+---------------------------------------------------------------------------------+ - | make_hgrid | Computes geo-referencing parameters (e.g., latitude, longitude, grid cell area) | - | | for global uniform grids | - +------------------------+---------------------------------------------------------------------------------+ - | make_solo_mosaic | Creates mosaic files with halos | - +------------------------+---------------------------------------------------------------------------------+ - | orog | Generates orography, land mask, and gravity wave drag files from fixed files | - +------------------------+---------------------------------------------------------------------------------+ - | orog_gsl | Ceates orographic statistics fields required for the orographic drag suite | - | | developed by NOAA's Global Systems Laboratory (GSL) | - +------------------------+---------------------------------------------------------------------------------+ - | regional_esg_grid | Generates an ESG regional grid based on a user-defined namelist | - +------------------------+---------------------------------------------------------------------------------+ - | sfc_climo_gen | Creates surface climatology fields from fixed files for use in ``chgres_cube`` | - +------------------------+---------------------------------------------------------------------------------+ - | shave | Shaves the excess halo rows down to what is required for the lateral boundary | - | | conditions (LBC's) in the orography and grid files | - +------------------------+---------------------------------------------------------------------------------+ - | upp.x | Post-processor for the model output | - +------------------------+---------------------------------------------------------------------------------+ - | ufs_model | UFS Weather Model executable | - +------------------------+---------------------------------------------------------------------------------+ - | vcoord_gen | Generates hybrid coordinate interface profiles | - +------------------------+---------------------------------------------------------------------------------+ - -.. _RRFSexec: - -.. table:: Names and descriptions of the executables produced when the RRFS option is enabled - - +----------------------------+-----------------------------------------------------------------------------+ - | **Executable Name** | **Description** | - +============================+=============================================================================+ - | gsi.x | Runs the Gridpoint Statistical Interpolation (GSI). | - +----------------------------+-----------------------------------------------------------------------------+ - | enkf.x | Runs the Ensemble Kalman Filter. | - +----------------------------+-----------------------------------------------------------------------------+ - | gen_annual_maxmin_GVF.exe | Generate maximum and minimum GVF files based on yearly long GVF | - | | observations for update_GVF process. | - +----------------------------+-----------------------------------------------------------------------------+ - | update_GVF.exe | Update the greenness vegetation fraction (GVF) in the surface file based on | - | | the real-time observations files. | - +----------------------------+-----------------------------------------------------------------------------+ - | ref2tten.exe | Calculate temperature tendency based on the radar reflectivity observation | - | | at each grid point. This temperature tendency can be used by the model | - | | during integration as latent heating initialization for ongoing | - | | precipitation systems, especially convection. | - +----------------------------+-----------------------------------------------------------------------------+ - | update_ice.exe | Replace ice fields in warm start surface files based on the forecast from | - | | cold start forecast using the GFS as the initial file. | - +----------------------------+-----------------------------------------------------------------------------+ - | process_updatesst.exe | Update SST field based on the SST analysis from NCEP. | - +----------------------------+-----------------------------------------------------------------------------+ - | check_imssnow_fv3lam.exe | This is a tool used to read snow and ice fields from surface files and | - | | check that field. | - +----------------------------+-----------------------------------------------------------------------------+ - | gen_cs.exe | NCL scripts to do cross section plotting. | - +----------------------------+-----------------------------------------------------------------------------+ - | lakesurgery.exe | Replace the existing lake depth with the GLOBathy bathymetry. It is | - | | designed to work with the HRRR model. | - +----------------------------+-----------------------------------------------------------------------------+ - | process_imssnow_fv3lam.exe | Use FV3LAM snow and ice fields based on the snow and ice information from | - | | imssnow. | - +----------------------------+-----------------------------------------------------------------------------+ - | gen_ensmean_recenter.exe | Runs the ensemble mean/recentering calculation for FV3LAM ensemble files. | - +----------------------------+-----------------------------------------------------------------------------+ - | update_bc.exe | Adjust 0-h boundary conditions based on the analysis results during data | - | | assimilation cycling. | - +----------------------------+-----------------------------------------------------------------------------+ - | adjust_soiltq.exe | Use the lowest level temperature and moisture analysis increments to adjust | - | | the soil moisture and soil temperature after analysis. | - +----------------------------+-----------------------------------------------------------------------------+ - | process_NSSL_mosaic.exe | Process NSSL MRMS radar reflectivity mosaic observations: read 33 level | - | | NSSL MRMS radar reflectivity grib2 files and then interpolate the | - | | reflectivity horizontally to the ESG grid. | - +----------------------------+-----------------------------------------------------------------------------+ - | use_raphrrr_sfc.exe | Use RAP and HRRR surface fields to replace the surface fields in FV3LAM. | - | | This is only used for starting the RRFS surface cycling. | - +----------------------------+-----------------------------------------------------------------------------+ - | process_Lightning.exe | Processes lightning data: read NLDN NetCDF observation files and map the | - | | lightning observations into FV3LAM ESG grid. | - +----------------------------+-----------------------------------------------------------------------------+ - | process_larccld.exe | Process NASA Langley cloud top product: reads the cloud top pressure, | - | | temperature, etc and maps them to the ESG grid. | - +----------------------------+-----------------------------------------------------------------------------+ - | process_metarcld.exe | Process METAR ceilometers cloud observations: reads the cloud base and | - | | coverage observations from PrepBUFR and distributes the cloud | - | | observations/weather/visibility observations to the ESG grid. | - +----------------------------+-----------------------------------------------------------------------------+ - | fv3lam_nonvarcldana.exe | Runs the non-variational cloud and precipitable hydrometeor analysis based | - | | on the METAR cloud observations, satellite retrieved cloud top products, | - | | and radar reflectivity. | - +----------------------------+-----------------------------------------------------------------------------+ - - - -.. _CMakeApproach: - -CMake Approach ------------------ - -Set Up the Build Environment -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. attention:: - * If users successfully built the executables in :numref:`Table %s `, they should skip to step :numref:`Step %s `. - * Users who want to build the SRW App on a generic MacOS should skip to :numref:`Section %s ` and follow the approach there. - -If the ``devbuild.sh`` approach failed, users need to set up their environment to run a workflow on their specific platform. First, users should make sure ``Lmod`` is the app used for loading modulefiles. This is the case on most Level 1 systems; however, on systems such as Gaea/Odin, the default modulefile loader is from Cray and must be switched to Lmod. For example, on Gaea, users can run one of the following two commands depending on whether they have a bash or csh shell, respectively: - -.. code-block:: console - - source etc/lmod-setup.sh gaea - source etc/lmod-setup.csh gaea - -If users execute one of the above commands on systems that don't need it, it will not cause any problems (it will simply do a ``module purge``). - -From here on, ``Lmod`` is ready to load the modulefiles needed by the SRW App. These modulefiles are located in the ``modulefiles`` directory. To load the necessary modulefile for a specific ```` using a given ````, run: - -.. code-block:: console - - module use - module load build__ - -where ```` is the full path to the ``modulefiles`` directory. - -This will work on Level 1 systems, where a modulefile is available in the ``modulefiles`` directory. On Level 2-4 systems (including generic Linux/MacOS systems), users will need to modify certain environment variables, such as the path to HPC-Stack, so that the SRW App can find and load the appropriate modules. For systems with Lmod installed, one of the current ``build__`` modulefiles can be copied and used as a template. To check whether Lmod is installed, run ``echo $LMOD_PKG``, and see if it outputs a path to the Lmod package. On systems without Lmod, users can modify or set the required environment variables with the ``export`` or ``setenv`` commands, depending on whether they are using a bash or csh/tcsh shell, respectively: - -.. code-block:: - - export = - setenv - -Note that building the SRW App without Lmod is not supported at this time. It should be possible to do so, but it has not been tested. Users are encouraged to install Lmod on their system. - -.. _BuildCMake: - -Build the Executables Using CMake -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -After setting up the build environment in the preceding section (by loading the ``build__`` modulefile), users need to build the executables required to run the SRW App. In the ``ufs-srweather-app`` directory, create a subdirectory to hold the build's executables: - -.. code-block:: console - - mkdir build - cd build - -From the build directory, run the following commands to build the pre-processing utilities, forecast model, and post-processor: - -.. code-block:: console - - cmake .. -DCMAKE_INSTALL_PREFIX=.. - make -j 4 >& build.out & - -``-DCMAKE_INSTALL_PREFIX`` specifies the location in which the ``bin``, ``include``, ``lib``, and ``share`` directories will be created. These directories will contain various components of the SRW App. Its recommended value ``..`` denotes one directory up from the build directory. In the next line, the ``make`` call argument ``-j 4`` indicates that the build will run in parallel with 4 threads. Although users can specify a larger or smaller number of threads (e.g., ``-j8``, ``-j2``), it is highly recommended to use at least 4 parallel threads to prevent overly long installation times. - -If users want to build the optional ``GSI`` and ``rrfs_utl`` components for RRFS (NOTE: These components are not currently available for use at runtime), they can add ``ENABLE_RRFS=on`` to the original cmake command. For example: - -.. code-block:: console - - cmake .. -DCMAKE_INSTALL_PREFIX=.. ENABLE_RRFS=on - make -j 4 >& build.out & - -The build will take a few minutes to complete. When it starts, a random number is printed to the console, and when it is done, a ``[1]+ Done`` message is printed to the console. ``[1]+ Exit`` indicates an error. Output from the build will be in the ``ufs-srweather-app/build/build.out`` file. When the build completes, users should see the forecast model executable ``ufs_model`` and several pre- and post-processing executables in the ``ufs-srweather-app/bin`` directory. These executables are described in :numref:`Table %s `. - -.. hint:: - - If you see the ``build.out`` file, but there is no ``ufs-srweather-app/bin`` directory, wait a few more minutes for the build to complete. - -.. _MacDetails: - -Additional Details for Building on MacOS ------------------------------------------- - -.. note:: - Users who are **not** building the SRW App on a MacOS machine may skip to the :ref:`next section `. - -The SRW App can be built on MacOS machines, presuming HPC-Stack has already been installed successfully. The following two options have been tested: - -* **Option 1:** MacBookAir 2020, M1 chip (arm64, running natively), 4+4 cores, Big Sur 11.6.4, GNU compiler suite v.11.2.0_3 (gcc, gfortran, g++); no MPI pre-installed - -* **Option 2:** MacBook Pro 2015, 2.8 GHz Quad-Core Intel Core i7 (x86_64), Catalina OS X 10.15.7, GNU compiler suite v.11.2.0_3 (gcc, gfortran, g++); no MPI pre-installed - -The ``build_macos_gnu`` modulefile initializes the module environment, lists the location of HPC-Stack modules, loads the meta-modules and modules, and sets compilers, additional flags, and environment variables needed for building the SRW App. The modulefile must be modified to include the absolute path to the user's HPC-Stack installation and ``ufs-srweather-app`` directories. In particular, the following section must be modified: - -.. code-block:: console - - # This path should point to your HPCstack installation directory - setenv HPCstack "/Users/username/hpc-stack/install" - - # This path should point to your SRW Application directory - setenv SRW "/Users/username/ufs-srweather-app" - -An excerpt of the ``build_macos_gnu`` contents appears below for Option 1. To use Option 2, the user will need to comment out the lines specific to Option 1 and uncomment the lines specific to Option 2 in the ``build_macos_gnu`` modulefile. Additionally, users need to verify that all file paths reflect their system's configuration and that the correct version numbers for software libraries appear in the modulefile. - -.. code-block:: console - - # Option 1 compiler paths: - setenv CC "/opt/homebrew/bin/gcc" - setenv FC "/opt/homebrew/bin/gfortran" - setenv CXX "/opt/homebrew/bin/g++" - - # Option 2 compiler paths: - #setenv CC "/usr/local/bin/gcc" - #setenv FC "/usr/local/bin/gfortran" - #setenv CXX "/usr/local/bin/g++" - -Then, users must source the Lmod setup file, just as they would on other systems, and load the modulefiles needed for building and running the SRW App: - -.. code-block:: console - - source etc/lmod-setup.sh macos - module use - module load build_macos_gnu - export LDFLAGS="-L${MPI_ROOT}/lib" - -In a csh/tcsh shell, users would run ``source etc/lmod-setup.csh macos`` in place of the first line in the code block above. - -Additionally, for Option 1 systems, set the variable ``ENABLE_QUAD_PRECISION`` to ``OFF`` in the ``$SRW/src/ufs-weather-model/FV3/atmos_cubed_sphere/CMakeLists.txt`` file. This change is optional if using Option 2 to build the SRW App. To make this change using a streamline editor (`sed`), run: - -.. code-block:: console - - sed -i .bak 's/QUAD_PRECISION\" ON)/QUAD_PRECISION\" OFF)/' $SRW/src/ufs-weather-model/FV3/atmos_cubed_sphere/CMakeLists.txt - -Proceed to building the executables using the process outlined in :numref:`Step %s `. - - -.. _Data: - -Download and Stage the Data -============================ - -The SRW App requires input files to run. These include static datasets, initial and boundary conditions files, and model configuration files. On Level 1 systems, the data required to run SRW App tests are already available. For Level 2-4 systems, the data must be added. Detailed instructions on how to add the data can be found in :numref:`Section %s `. Sections :numref:`%s ` and :numref:`%s ` contain useful background information on the input and output files used in the SRW App. - -.. _GridSpecificConfig: - -Grid Configuration -======================= - -The SRW App officially supports four different predefined grids as shown in :numref:`Table %s `. The out-of-the-box SRW App case uses the ``RRFS_CONUS_25km`` predefined grid option. More information on the predefined and user-generated grid options can be found in :numref:`Chapter %s ` for those who are curious. Users who plan to utilize one of the four predefined domain (grid) options may continue to :numref:`Step %s `. Users who plan to create a new domain should refer to :numref:`Section %s ` for details on how to do so. At a minimum, these users will need to add the new grid name to the ``valid_param_vals.sh`` script and add the corresponding grid-specific parameters in the ``set_predef_grid_params.sh`` script. - -.. _PredefinedGrids: - -.. table:: Predefined grids in the SRW App - - +----------------------+-------------------+--------------------------------+ - | **Grid Name** | **Grid Type** | **Quilting (write component)** | - +======================+===================+================================+ - | RRFS_CONUS_25km | ESG grid | lambert_conformal | - +----------------------+-------------------+--------------------------------+ - | RRFS_CONUS_13km | ESG grid | lambert_conformal | - +----------------------+-------------------+--------------------------------+ - | RRFS_CONUS_3km | ESG grid | lambert_conformal | - +----------------------+-------------------+--------------------------------+ - | SUBCONUS_Ind_3km | ESG grid | lambert_conformal | - +----------------------+-------------------+--------------------------------+ - - -.. _GenerateForecast: - -Generate the Forecast Experiment -================================= -Generating the forecast experiment requires three steps: - -#. :ref:`Set experiment parameters ` -#. :ref:`Set Python and other environment parameters ` -#. :ref:`Run a script to generate the experiment workflow ` - -The first two steps depend on the platform being used and are described here for each Level 1 platform. Users will need to adjust the instructions to reflect their machine configuration if they are working on a Level 2-4 platform. Information in :numref:`Chapter %s: Configuring the Workflow ` can help with this. - -.. _ExptConfig: - -Set Experiment Parameters ----------------------------- - -Each experiment requires certain basic information to run (e.g., date, grid, physics suite). This information is specified in ``config_defaults.sh`` and in the user-specified ``config.sh`` file. When generating a new experiment, the SRW App first reads and assigns default values from the ``config_defaults.sh`` file. Then, it reads and (re)assigns variables from the user's custom ``config.sh`` file. - -For background info on ``config_defaults.sh``, read :numref:`Section %s `, or jump to :numref:`Section %s ` to continue configuring the experiment. - -.. _DefaultConfigSection: - -Default configuration: ``config_defaults.sh`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. note:: - This section provides background information on how the SRW App uses the ``config_defaults.sh`` file. It is informative, but users do not need to modify ``config_defaults.sh`` to run the out-of-the-box case for the SRW App. Therefore, users may skip to :numref:`Step %s ` to continue configuring their experiment. - -Configuration variables in the ``config_defaults.sh`` file appear in :numref:`Table %s `. Some of these default values are intentionally invalid in order to ensure that the user assigns valid values in the user-specified ``config.sh`` file. Any settings provided in ``config.sh`` will override the ``config_defaults.sh`` -settings. There is usually no need for a user to modify the default configuration file. Additional information on the default settings can be found in the file itself and in :numref:`Chapter %s `. - -.. _ConfigVarsDefault: - -.. table:: Configuration variables specified in the config_defaults.sh script. - - +----------------------+--------------------------------------------------------------+ - | **Group Name** | **Configuration variables** | - +======================+==============================================================+ - | Experiment mode | RUN_ENVIR | - +----------------------+--------------------------------------------------------------+ - | Machine and queue | MACHINE, MACHINE_FILE, ACCOUNT, COMPILER, SCHED, | - | | LMOD_PATH, NCORES_PER_NODE, BUILD_MOD_FN, WFLOW_MOD_FN, | - | | PARTITION_DEFAULT, CLUSTERS_DEFAULT, QUEUE_DEFAULT, | - | | PARTITION_HPSS, CLUSTERS_HPSS, QUEUE_HPSS, PARTITION_FCST, | - | | CLUSTERS_FCST, QUEUE_FCST | - +----------------------+--------------------------------------------------------------+ - | Workflow management | WORKFLOW_MANAGER, RUN_CMD_UTILS, RUN_CMD_FCST, RUN_CMD_POST | - +----------------------+--------------------------------------------------------------+ - | Cron | USE_CRON_TO_RELAUNCH, CRON_RELAUNCH_INTVL_MNTS | - +----------------------+--------------------------------------------------------------+ - | Directory parameters | EXPT_BASEDIR, EXPT_SUBDIR, EXEC_SUBDIR | - +----------------------+--------------------------------------------------------------+ - | NCO mode | COMINgfs, FIXLAM_NCO_BASEDIR, STMP, NET, envir, RUN, PTMP | - +----------------------+--------------------------------------------------------------+ - | Separator | DOT_OR_USCORE | - +----------------------+--------------------------------------------------------------+ - | File name | EXPT_CONFIG_FN, RGNL_GRID_NML_FN, DATA_TABLE_FN, | - | | DIAG_TABLE_FN, FIELD_TABLE_FN, FV3_NML_BASE_SUITE_FN, | - | | FV3_NML_YAML_CONFIG_FN, FV3_NML_BASE_ENS_FN, | - | | MODEL_CONFIG_FN, NEMS_CONFIG_FN, FV3_EXEC_FN, | - | | FCST_MODEL, WFLOW_XML_FN, GLOBAL_VAR_DEFNS_FN, | - | | EXTRN_MDL_ICS_VAR_DEFNS_FN, EXTRN_MDL_LBCS_VAR_DEFNS_FN, | - | | WFLOW_LAUNCH_SCRIPT_FN, WFLOW_LAUNCH_LOG_FN | - +----------------------+--------------------------------------------------------------+ - | Forecast | DATE_FIRST_CYCL, DATE_LAST_CYCL, INCR_CYCL_FREQ, | - | | FCST_LEN_HRS | - +----------------------+--------------------------------------------------------------+ - | IC/LBC | EXTRN_MDL_NAME_ICS, EXTRN_MDL_NAME_LBCS, | - | | LBC_SPEC_INTVL_HRS, EXTRN_MDL_ICS_OFFSET_HRS, | - | | EXTRN_MDL_LBCS_OFFSET_HRS, FV3GFS_FILE_FMT_ICS, | - | | FV3GFS_FILE_FMT_LBCS | - +----------------------+--------------------------------------------------------------+ - | NOMADS | NOMADS, NOMADS_file_type | - +----------------------+--------------------------------------------------------------+ - | External model | EXTRN_MDL_SYSBASEDIR_ICS, EXTRN_MDL_SYSBASEDIR_LBCS, | - | | USE_USER_STAGED_EXTRN_FILES, EXTRN_MDL_SOURCE_BASEDIR_ICS, | - | | EXTRN_MDL_FILES_ICS, EXTRN_MDL_SOURCE_BASEDIR_LBCS, | - | | EXTRN_MDL_FILES_LBCS | - +----------------------+--------------------------------------------------------------+ - | CCPP | CCPP_PHYS_SUITE | - +----------------------+--------------------------------------------------------------+ - | Stochastic physics | NEW_LSCALE, DO_SHUM, DO_SPPT, DO_SKEB, DO_SPP, DO_LSM_SPP, | - | | ISEED_SHUM, SHUM_MAG, SHUM_LSCALE, SHUM_TSCALE, SHUM_INT, | - | | ISEED_SPPT, SPPT_MAG, SPPT_LOGIT, SPPT_LSCALE, SPPT_TSCALE, | - | | SPPT_INT, SPPT_SFCLIMIT, USE_ZMTNBLCK, ISEED_SKEB, | - | | SKEB_MAG, SKEB_LSCALE, SKEP_TSCALE, SKEB_INT, SKEBNORM, | - | | SKEB_VDOF, ISEED_SPP, SPP_MAG_LIST, SPP_LSCALE, SPP_TSCALE, | - | | SPP_SIGTOP1, SPP_SIGTOP2, SPP_STDDEV_CUTOFF, SPP_VAR_LIST, | - | | LSM_SPP_TSCALE, LSM_SPP_LSCALE, ISEED_LSM_SPP, | - | | LSM_SPP_VAR_LIST, LSM_SPP_MAG_LIST, LSM_SPP_EACH_STEP | - +----------------------+--------------------------------------------------------------+ - | GRID | GRID_GEN_METHOD, PREDEF_GRID_NAME | - +----------------------+--------------------------------------------------------------+ - | ESG grid | ESGgrid_LON_CTR, ESGgrid_LAT_CTR, ESGgrid_DELX, | - | | ESGgrid_DELY, ESGgrid_NX, ESGgrid_NY, ESGgrid_PAZI | - | | ESGgrid_WIDE_HALO_WIDTH | - +----------------------+--------------------------------------------------------------+ - | GFDL grid | GFDLgrid_LON_T6_CTR, GFDLgrid_LAT_T6_CTR, GFDLgrid_RES, | - | | GFDLgrid_STRETCH_FAC, GFDLgrid_REFINE_RATIO, | - | | GFDLgrid_ISTART_OF_RGNL_DOM_ON_T6G, | - | | GFDLgrid_IEND_OF_RGNL_DOM_ON_T6G, | - | | GFDLgrid_JSTART_OF_RGNL_DOM_ON_T6G, | - | | GFDLgrid_JEND_OF_RGNL_DOM_ON_T6G, | - | | GFDLgrid_USE_GFDLgrid_RES_IN_FILENAMES | - +----------------------+--------------------------------------------------------------+ - | Input configuration | DT_ATMOS, RESTART_INTERVAL, WRITE_DOPOST, LAYOUT_X, | - | | LAYOUT_Y, BLOCKSIZE, QUILTING, | - | | PRINT_ESMF, WRTCMP_write_groups, | - | | WRTCMP_write_tasks_per_group, WRTCMP_output_grid, | - | | WRTCMP_cen_lon, WRTCMP_cen_lat, WRTCMP_lon_lwr_left, | - | | WRTCMP_lat_lwr_left, WRTCMP_lon_upr_rght, | - | | WRTCMP_lat_upr_rght, WRTCMP_dlon, WRTCMP_dlat, | - | | WRTCMP_stdlat1, WRTCMP_stdlat2, WRTCMP_nx, WRTCMP_ny, | - | | WRTCMP_dx, WRTCMP_dy | - +----------------------+--------------------------------------------------------------+ - | Experiment generation| PREEXISTING_DIR_METHOD, VERBOSE, DEBUG | - +----------------------+--------------------------------------------------------------+ - | Cycle-independent | RUN_TASK_MAKE_GRID, GRID_DIR, RUN_TASK_MAKE_OROG, | - | | OROG_DIR, RUN_TASK_MAKE_SFC_CLIMO, SFC_CLIMO_DIR | - +----------------------+--------------------------------------------------------------+ - | Cycle dependent | RUN_TASK_GET_EXTRN_ICS, RUN_TASK_GET_EXTRN_LBCS, | - | | RUN_TASK_MAKE_ICS, RUN_TASK_MAKE_LBCS, RUN_TASK_RUN_FCST, | - | | RUN_TASK_RUN_POST | - +----------------------+--------------------------------------------------------------+ - | VX run tasks | RUN_TASK_GET_OBS_CCPA, RUN_TASK_GET_OBS_MRMS, | - | | RUN_TASK_GET_OBS_NDAS, RUN_TASK_VX_GRIDSTAT, | - | | RUN_TASK_VX_POINTSTAT, RUN_TASK_VX_ENSGRID, | - | | RUN_TASK_VX_ENSPOINT | - +----------------------+--------------------------------------------------------------+ - | Fixed File Parameters| FIXgsm, FIXaer, FIXlut, TOPO_DIR, SFC_CLIMO_INPUT_DIR, | - | | FNGLAC, FNMXIC, FNTSFC, FNSNOC, FNZORC, | - | | FNAISC, FNSMCC, FNMSKH, FIXgsm_FILES_TO_COPY_TO_FIXam, | - | | FV3_NML_VARNAME_TO_FIXam_FILES_MAPPING, | - | | FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING, | - | | CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING | - +----------------------+--------------------------------------------------------------+ - | Workflow tasks | MAKE_GRID_TN, MAKE_OROG_TN, MAKE_SFC_CLIMO_TN, | - | | GET_EXTRN_ICS_TN, GET_EXTRN_LBCS_TN, MAKE_ICS_TN, | - | | MAKE_LBCS_TN, RUN_FCST_TN, RUN_POST_TN | - +----------------------+--------------------------------------------------------------+ - | Verification tasks | GET_OBS, GET_OBS_CCPA_TN, GET_OBS_MRMS_TN, GET_OBS_NDAS_TN, | - | | VX_TN, VX_GRIDSTAT_TN, VX_GRIDSTAT_REFC_TN, | - | | VX_GRIDSTAT_RETOP_TN, VX_GRIDSTAT_##h_TN, VX_POINTSTAT_TN, | - | | VX_ENSGRID_TN, VX_ENSGRID_##h_TN, VX_ENSGRID_REFC_TN, | - | | VX_ENSGRID_RETOP_TN, VX_ENSGRID_MEAN_TN, VX_ENSGRID_PROB_TN, | - | | VX_ENSGRID_MEAN_##h_TN, VX_ENSGRID_PROB_03h_TN, | - | | VX_ENSGRID_PROB_REFC_TN, VX_ENSGRID_PROB_RETOP_TN, | - | | VX_ENSPOINT_TN, VX_ENSPOINT_MEAN_TN, VX_ENSPOINT_PROB_TN | - +----------------------+--------------------------------------------------------------+ - | NODE | NNODES_MAKE_GRID, NNODES_MAKE_OROG, NNODES_MAKE_SFC_CLIMO, | - | | NNODES_GET_EXTRN_ICS, NNODES_GET_EXTRN_LBCS, | - | | NNODES_MAKE_ICS, NNODES_MAKE_LBCS, NNODES_RUN_FCST, | - | | NNODES_RUN_POST, NNODES_GET_OBS_CCPA, NNODES_GET_OBS_MRMS, | - | | NNODES_GET_OBS_NDAS, NNODES_VX_GRIDSTAT, | - | | NNODES_VX_POINTSTAT, NNODES_VX_ENSGRID, | - | | NNODES_VX_ENSGRID_MEAN, NNODES_VX_ENSGRID_PROB, | - | | NNODES_VX_ENSPOINT, NNODES_VX_ENSPOINT_MEAN, | - | | NNODES_VX_ENSPOINT_PROB | - +----------------------+--------------------------------------------------------------+ - | MPI processes | PPN_MAKE_GRID, PPN_MAKE_OROG, PPN_MAKE_SFC_CLIMO, | - | | PPN_GET_EXTRN_ICS, PPN_GET_EXTRN_LBCS, PPN_MAKE_ICS, | - | | PPN_MAKE_LBCS, PPN_RUN_FCST, PPN_RUN_POST, | - | | PPN_GET_OBS_CCPA, PPN_GET_OBS_MRMS, PPN_GET_OBS_NDAS, | - | | PPN_VX_GRIDSTAT, PPN_VX_POINTSTAT, PPN_VX_ENSGRID, | - | | PPN_VX_ENSGRID_MEAN, PPN_VX_ENSGRID_PROB, PPN_VX_ENSPOINT, | - | | PPN_VX_ENSPOINT_MEAN, PPN_VX_ENSPOINT_PROB | - +----------------------+--------------------------------------------------------------+ - | Walltime | WTIME_MAKE_GRID, WTIME_MAKE_OROG, WTIME_MAKE_SFC_CLIMO, | - | | WTIME_GET_EXTRN_ICS, WTIME_GET_EXTRN_LBCS, WTIME_MAKE_ICS, | - | | WTIME_MAKE_LBCS, WTIME_RUN_FCST, WTIME_RUN_POST, | - | | WTIME_GET_OBS_CCPA, WTIME_GET_OBS_MRMS, WTIME_GET_OBS_NDAS, | - | | WTIME_VX_GRIDSTAT, WTIME_VX_POINTSTAT, WTIME_VX_ENSGRID, | - | | WTIME_VX_ENSGRID_MEAN, WTIME_VX_ENSGRID_PROB, | - | | WTIME_VX_ENSPOINT, WTIME_VX_ENSPOINT_MEAN, | - | | WTIME_VX_ENSPOINT_PROB | - +----------------------+--------------------------------------------------------------+ - | Maximum attempt | MAXTRIES_MAKE_GRID, MAXTRIES_MAKE_OROG, | - | | MAXTRIES_MAKE_SFC_CLIMO, MAXTRIES_GET_EXTRN_ICS, | - | | MAXTRIES_GET_EXTRN_LBCS, MAXTRIES_MAKE_ICS, | - | | MAXTRIES_MAKE_LBCS, MAXTRIES_RUN_FCST, MAXTRIES_RUN_POST, | - | | MAXTRIES_GET_OBS_CCPA, MAXTRIES_GET_OBS_MRMS, | - | | MAXTRIES_GET_OBS_NDAS, MAXTRIES_VX_GRIDSTAT, | - | | MAXTRIES_VX_GRIDSTAT_REFC, MAXTRIES_VX_GRIDSTAT_RETOP, | - | | MAXTRIES_VX_GRIDSTAT_##h, MAXTRIES_VX_POINTSTAT, | - | | MAXTRIES_VX_ENSGRID, MAXTRIES_VX_ENSGRID_REFC, | - | | MAXTRIES_VX_ENSGRID_RETOP, MAXTRIES_VX_ENSGRID_##h, | - | | MAXTRIES_VX_ENSGRID_MEAN, MAXTRIES_VX_ENSGRID_PROB, | - | | MAXTRIES_VX_ENSGRID_MEAN_##h, MAXTRIES_VX_ENSGRID_PROB_##h, | - | | MAXTRIES_VX_ENSGRID_PROB_REFC, | - | | MAXTRIES_VX_ENSGRID_PROB_RETOP, MAXTRIES_VX_ENSPOINT, | - | | MAXTRIES_VX_ENSPOINT_MEAN, MAXTRIES_VX_ENSPOINT_PROB | - +----------------------+--------------------------------------------------------------+ - | Climatology | SFC_CLIMO_FIELDS, USE_MERRA_CLIMO | - +----------------------+--------------------------------------------------------------+ - | CRTM | USE_CRTM, CRTM_DIR | - +----------------------+--------------------------------------------------------------+ - | Post configuration | USE_CUSTOM_POST_CONFIG_FILE, CUSTOM_POST_CONFIG_FP, | - | | SUB_HOURLY_POST, DT_SUB_HOURLY_POST_MNTS | - +----------------------+--------------------------------------------------------------+ - | METplus | MODEL, MET_INSTALL_DIR, MET_BIN_EXEC, METPLUS_PATH, | - | | CCPA_OBS_DIR, MRMS_OBS_DIR, NDAS_OBS_DIR | - +----------------------+--------------------------------------------------------------+ - | Running ensembles | DO_ENSEMBLE, NUM_ENS_MEMBERS | - +----------------------+--------------------------------------------------------------+ - | Boundary blending | HALO_BLEND | - +----------------------+--------------------------------------------------------------+ - | FVCOM | USE_FVCOM, FVCOM_WCSTART, FVCOM_DIR, FVCOM_FILE | - +----------------------+--------------------------------------------------------------+ - | Thread Affinity | KMP_AFFINITY_*, OMP_NUM_THREADS_*, OMP_STACKSIZE_* | - +----------------------+--------------------------------------------------------------+ - - -.. _UserSpecificConfig: - -User-specific configuration: ``config.sh`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The user must specify certain basic information about the experiment in a ``config.sh`` file located in the ``ufs-srweather-app/regional_workflow/ush`` directory. Two example templates are provided in that directory: ``config.community.sh`` and ``config.nco.sh``. The first file is a minimal example for creating and running an experiment in the *community* mode (with ``RUN_ENVIR`` set to ``community``). The second is an example for creating and running an experiment in the *NCO* (operational) mode (with ``RUN_ENVIR`` set to ``nco``). The *community* mode is recommended in most cases and is fully supported for this release. The operational/NCO mode is typically used by those at the NOAA/NCEP/Environmental Modeling Center (EMC) and the NOAA/Global Systems Laboratory (GSL) working on pre-implementation testing for the Rapid Refresh Forecast System (RRFS). :numref:`Table %s ` shows the configuration variables that appear in the ``config.community.sh``, along with their default values in ``config_default.sh`` and the values defined in ``config.community.sh``. - -.. _ConfigCommunity: - -.. table:: Configuration variables specified in the config.community.sh script - - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | **Parameter** | **Default Value** | **config.community.sh Value** | - +================================+===================+==================================================================================+ - | MACHINE | "BIG_COMPUTER" | "hera" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | ACCOUNT | "project_name" | "an_account" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | EXPT_SUBDIR | "" | "test_CONUS_25km_GFSv16" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | COMPILER | "intel" | "intel" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | VERBOSE | "TRUE" | "TRUE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_ENVIR | "nco" | "community" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | PREEXISTING_DIR_METHOD | "delete" | "rename" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | PREDEF_GRID_NAME | "" | "RRFS_CONUS_25km" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | DO_ENSEMBLE | "FALSE" | "FALSE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | NUM_ENS_MEMBERS | "1" | "2" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | QUILTING | "TRUE" | "TRUE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | CCPP_PHYS_SUITE | "FV3_GFS_v16" | "FV3_GFS_v16" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | FCST_LEN_HRS | "24" | "12" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | LBC_SPEC_INTVL_HRS | "6" | "6" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | DATE_FIRST_CYCL | "YYYYMMDDHH" | "2019061518" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | DATE_LAST_CYCL | "YYYYMMDDHH" | "2019061518" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | EXTRN_MDL_NAME_ICS | "FV3GFS" | "FV3GFS" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | EXTRN_MDL_NAME_LBCS | "FV3GFS" | "FV3GFS" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | FV3GFS_FILE_FMT_ICS | "nemsio" | "grib2" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | FV3GFS_FILE_FMT_LBCS | "nemsio" | "grib2" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | WTIME_RUN_FCST | "04:30:00" | "02:00:00" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | USE_USER_STAGED_EXTRN_FILES | "FALSE" | "TRUE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | EXTRN_MDL_SOURCE_BASEDIR_ICS | "" | "/scratch2/BMC/det/UFS_SRW_App/develop/input_model_data/FV3GFS/grib2/2019061518" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | EXTRN_MDL_FILES_ICS | "" | "gfs.pgrb2.0p25.f000" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | EXTRN_MDL_SOURCE_BASEDIR_LBCS | "" | "/scratch2/BMC/det/UFS_SRW_App/develop/input_model_data/FV3GFS/grib2/2019061518" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | EXTRN_MDL_FILES_LBCS | "" | "gfs.pgrb2.0p25.f006" "gfs.pgrb2.0p25.f012" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | MODEL | "" | FV3_GFS_v16_CONUS_25km" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | METPLUS_PATH | "" | "/path/to/METPlus" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | MET_INSTALL_DIR | "" | "/path/to/MET" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | CCPA_OBS_DIR | "" | "/path/to/processed/CCPA/data" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | MRMS_OBS_DIR | "" | "/path/to/processed/MRMS/data" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | NDAS_OBS_DIR | "" | "/path/to/processed/NDAS/data" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_MAKE_GRID | "TRUE" | "TRUE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_MAKE_OROG | "TRUE" | "TRUE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_MAKE_SFC_CLIMO | "TRUE" | "TRUE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_GET_OBS_CCPA | "FALSE" | "FALSE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_GET_OBS_MRMS | "FALSE" | "FALSE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_GET_OBS_NDAS | "FALSE" | "FALSE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_VX_GRIDSTAT | "FALSE" | "FALSE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_VX_POINTSTAT | "FALSE" | "FALSE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_VX_ENSGRID | "FALSE" | "FALSE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - | RUN_TASK_VX_ENSPOINT | "FALSE" | "FALSE" | - +--------------------------------+-------------------+----------------------------------------------------------------------------------+ - - -To get started, make a copy of ``config.community.sh``. From the ``ufs-srweather-app`` directory, run: - -.. code-block:: console - - cd $SRW/regional_workflow/ush - cp config.community.sh config.sh - -The default settings in this file include a predefined 25-km :term:`CONUS` grid (RRFS_CONUS_25km), the :term:`GFS` v16 physics suite (FV3_GFS_v16 :term:`CCPP`), and :term:`FV3`-based GFS raw external model data for initialization. - -Next, edit the new ``config.sh`` file to customize it for your machine. At a minimum, change the ``MACHINE`` and ``ACCOUNT`` variables; then choose a name for the experiment directory by setting ``EXPT_SUBDIR``. If you have pre-staged initialization data for the experiment, set ``USE_USER_STAGED_EXTRN_FILES="TRUE"``, and set the paths to the data for ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_SOURCE_BASEDIR_LBCS``. If the modulefile used to set up the build environment in :numref:`Section %s ` uses a GNU compiler, check that the line ``COMPILER="gnu"`` appears in the ``config.sh`` file. On platforms where Rocoto and :term:`cron` are available, users can automate resubmission of their experiment workflow by adding the following lines to the ``config.sh`` file: - -.. code-block:: console - - USE_CRON_TO_RELAUNCH="TRUE" - CRON_RELAUNCH_INTVL_MNTS="03" - -.. note:: - - Generic Linux and MacOS users should refer to :numref:`Section %s ` for additional details on configuring an experiment and python environment. - -Sample ``config.sh`` settings are indicated below for Level 1 platforms. Detailed guidance applicable to all systems can be found in :numref:`Chapter %s: Configuring the Workflow `, which discusses each variable and the options available. Additionally, information about the four predefined Limited Area Model (LAM) Grid options can be found in :numref:`Chapter %s: Limited Area Model (LAM) Grids `. - -.. hint:: - - To determine an appropriate ACCOUNT field for Level 1 systems, run ``groups``, and it will return a list of projects you have permissions for. Not all of the listed projects/groups have an HPC allocation, but those that do are potentially valid account names. - -Minimum parameter settings for running the out-of-the-box SRW App case on Level 1 machines: - -.. _SystemData: - -**Cheyenne:** - -.. code-block:: console - - MACHINE="cheyenne" - ACCOUNT="" - EXPT_SUBDIR="" - USE_USER_STAGED_EXTRN_FILES="TRUE" - EXTRN_MDL_SOURCE_BASEDIR_ICS="/glade/p/ral/jntp/UFS_SRW_App/develop/input_model_data///" - EXTRN_MDL_SOURCE_BASEDIR_LBCS="/glade/p/ral/jntp/UFS_SRW_App/develop/input_model_data///" - -where: - * ```` refers to a valid account name. - * ```` is an experiment name of the user's choice. - * ```` refers to a subdirectory, such as "FV3GFS" or "HRRR", containing the experiment data. - * ```` refers to one of 3 possible data formats: ``grib2``, ``nemsio``, or ``netcdf``. - * ```` refers to a subdirectory containing data for the :term:`cycle` date (in YYYYMMDDHH format). - - -**Hera, Jet, Orion, Gaea:** - -The ``MACHINE``, ``ACCOUNT``, and ``EXPT_SUBDIR`` settings are the same as for Cheyenne, except that ``"cheyenne"`` should be switched to ``"hera"``, ``"jet"``, ``"orion"``, or ``"gaea"``, respectively. Set ``USE_USER_STAGED_EXTRN_FILES="TRUE"``, but replace the file paths to Cheyenne's data with the file paths for the correct machine. ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_SOURCE_BASEDIR_LBCS`` use the same base file path. - -On Hera: - -.. code-block:: console - - "/scratch2/BMC/det/UFS_SRW_App/develop/input_model_data////" - -On Jet: - -.. code-block:: console - - "/mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/input_model_data////" - -On Orion: - -.. code-block:: console - - "/work/noaa/fv3-cam/UFS_SRW_App/develop/input_model_data////" - -On Gaea: - -.. code-block:: console - - "/lustre/f2/pdata/ncep/UFS_SRW_App/develop/input_model_data////" - -On **WCOSS** systems, edit ``config.sh`` with these WCOSS-specific parameters, and use a valid WCOSS project code for the account parameter: - -.. code-block:: console - - MACHINE="wcoss2" - ACCOUNT="valid_wcoss_project_code" - EXPT_SUBDIR="my_expt_name" - USE_USER_STAGED_EXTRN_FILES="TRUE" - -On WCOSS2: - -.. code-block:: console - - EXTRN_MDL_SOURCE_BASEDIR_ICS="/lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/input_model_data///YYYYMMDDHH/ICS" - EXTRN_MDL_SOURCE_BASEDIR_LBCS="/lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/input_model_data///YYYYMMDDHH/LBCS" - -On NOAA Cloud Systems: - -.. code-block:: console - - MACHINE="NOAACLOUD" - ACCOUNT="none" - EXPT_SUBDIR="" - USE_USER_STAGED_EXTRN_FILES="TRUE" - EXTRN_MDL_SOURCE_BASEDIR_ICS="/contrib/EPIC/UFS_SRW_App/develop/input_model_data////" - EXTRN_MDL_FILES_ICS=( "gfs.t18z.pgrb2.0p25.f000" ) - EXTRN_MDL_SOURCE_BASEDIR_LBCS="/contrib/EPIC/UFS_SRW_App/develop/input_model_data////" - EXTRN_MDL_FILES_LBCS=( "gfs.t18z.pgrb2.0p25.f006" "gfs.t18z.pgrb2.0p25.f012" ) - -.. note:: - - The values of the configuration variables should be consistent with those in the - ``valid_param_vals.sh`` script. In addition, various sample configuration files can be found in the ``regional_workflow/tests/baseline_configs`` directory. - - -To configure an experiment and python environment for a general Linux or Mac system, see the :ref:`next section `. To configure an experiment to run METplus verification tasks, see :numref:`Section %s `. Otherwise, skip to :numref:`Section %s `. - -.. _LinuxMacEnvConfig: - -User-specific Configuration on a General Linux/MacOS System -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The configuration process for Linux and MacOS systems is similar to the process for other systems, but it requires a few extra steps. - -.. note:: - Examples in this subsection presume that the user is running Terminal.app with a bash shell environment. If this is not the case, users will need to adjust the commands to fit their command line application and shell environment. - -.. _MacMorePackages: - -Install/Upgrade Mac-Specific Packages -```````````````````````````````````````` -MacOS requires the installation of a few additional packages and, possibly, an upgrade to bash. Users running on MacOS should execute the following commands: - -.. code-block:: console - - bash --version - brew upgrade bash - brew install coreutils - brew gsed - -.. _LinuxMacVEnv: - -Creating a Virtual Environment on Linux and Mac -`````````````````````````````````````````````````` - -Users should ensure that the following packages are installed and up-to-date: - -.. code-block:: console - - python3 -m pip --version - python3 -m pip install --upgrade pip - python3 -m ensurepip --default-pip - python3 -m pip install ruby OR(on MacOS only): brew install ruby - -Users must create a virtual environment (``regional_workflow``), store it in their ``$HOME/venv/`` directory, and install additional python packages: - -.. code-block:: console - - [[ -d $HOME/venv ]] | mkdir -p $HOME/venv - python3 -m venv $HOME/venv/regional_workflow - source $HOME/venv/regional_workflow/bin/activate - python3 -m pip install jinja2 - python3 -m pip install pyyaml - python3 -m pip install f90nml - -The virtual environment can be deactivated by running the ``deactivate`` command. The virtual environment built here will be reactivated in :numref:`Step %s ` and needs to be used to generate the workflow and run the experiment. - -.. _LinuxMacExptConfig: - -Configuring an Experiment on General Linux and MacOS Systems -`````````````````````````````````````````````````````````````` - -**Optional: Install Rocoto** - -.. note:: - Users may `install Rocoto `__ if they want to make use of a workflow manager to run their experiments. However, this option has not been tested yet on MacOS and has had limited testing on general Linux plaforms. - - -**Configure the SRW App:** - -Configure an experiment using a template. Copy the contents of ``config.community.sh`` into ``config.sh``: - -.. code-block:: console - - cd $SRW/regional_workflow/ush - cp config.community.sh config.sh - -In the ``config.sh`` file, set ``MACHINE="macos"`` or ``MACHINE="linux"``, and modify the account and experiment info. For example: - -.. code-block:: console - - MACHINE="macos" - ACCOUNT="user" - EXPT_SUBDIR="" - COMPILER="gnu" - VERBOSE="TRUE" - RUN_ENVIR="community" - PREEXISTING_DIR_METHOD="rename" - - PREDEF_GRID_NAME="RRFS_CONUS_25km" - QUILTING="TRUE" - -Due to the limited number of processors on MacOS systems, users must also configure the domain decomposition defaults (usually, there are only 8 CPUs in M1-family chips and 4 CPUs for x86_64). - -For :ref:`Option 1 `, add the following information to ``config.sh``: - -.. code-block:: console - - LAYOUT_X="${LAYOUT_X:-3}" - LAYOUT_Y="${LAYOUT_Y:-2}" - WRTCMP_write_groups="1" - WRTCMP_write_tasks_per_group="2" - -For :ref:`Option 2 `, add the following information to ``config.sh``: - -.. code-block:: console - - LAYOUT_X="${LAYOUT_X:-3}" - LAYOUT_Y="${LAYOUT_Y:-1}" - WRTCMP_write_groups="1" - WRTCMP_write_tasks_per_group="1" - -.. note:: - The number of MPI processes required by the forecast will be equal to ``LAYOUT_X`` * ``LAYOUT_Y`` + ``WRTCMP_write_tasks_per_group``. - -**Configure the Machine File** - -Configure a ``macos.sh`` or ``linux.sh`` machine file in ``$SRW/regional_workflow/ush/machine/`` based on the number of CPUs (````) in the system (usually 8 or 4 in MacOS; varies on Linux systems). Job scheduler (``SCHED``) options can be viewed :ref:`here `. Users must also set the path to the fix file directories. - -.. code-block:: console - - # Commands to run at the start of each workflow task. - PRE_TASK_CMDS='{ ulimit -a; }' - - # Architecture information - WORKFLOW_MANAGER="none" - NCORES_PER_NODE=${NCORES_PER_NODE:-} - SCHED=${SCHED:-""} - - # UFS SRW App specific paths - FIXgsm="path/to/FIXgsm/files" - FIXaer="path/to/FIXaer/files" - FIXlut="path/to/FIXlut/files" - TOPO_DIR="path/to/FIXgsm/files" # (path to location of static input files used by the - make_orog task) - SFC_CLIMO_INPUT_DIR="path/to/FIXgsm/files" # (path to location of static surface climatology - input fields used by sfc_climo_gen) - - # Run commands for executables - RUN_CMD_SERIAL="time" - RUN_CMD_UTILS="mpirun -np 4" - RUN_CMD_FCST='mpirun -np ${PE_MEMBER01}' - RUN_CMD_POST="mpirun -np 4" - - -.. _VXConfig: - -Configure METplus Verification Suite (Optional) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Users who want to use the METplus verification suite to evaluate their forecasts need to add additional information to their ``config.sh`` file. Other users may skip to the :ref:`next section `. - -.. attention:: - METplus *installation* is not included as part of the build process for this release of the SRW App. However, METplus is preinstalled on many `Level 1 & 2 `__ systems. For the v2.0.0 release, METplus *use* is supported on systems with a functioning METplus installation, although installation itself is not supported. For more information about METplus, see :numref:`Section %s `. - -.. note:: - If METplus users update their METplus installation, they must update the module load statements in ``ufs-srweather-app/regional_workflow/modulefiles/tasks//run_vx.local`` file to correspond to their system's updated installation: - - .. code-block:: console - - module use -a - module load met/ - -To use METplus verification, the path to the MET and METplus directories must be added to ``config.sh``: - -.. code-block:: console - - METPLUS_PATH="" - MET_INSTALL_DIR="" - -Users who have already staged the observation data needed for METplus (i.e., the :term:`CCPA`, :term:`MRMS`, and :term:`NDAS` data) on their system should set the path to this data and set the corresponding ``RUN_TASK_GET_OBS_*`` parameters to "FALSE" in ``config.sh``. - -.. code-block:: console - - CCPA_OBS_DIR="/path/to/UFS_SRW_App/develop/obs_data/ccpa/proc" - MRMS_OBS_DIR="/path/to/UFS_SRW_App/develop/obs_data/mrms/proc" - NDAS_OBS_DIR="/path/to/UFS_SRW_App/develop/obs_data/ndas/proc" - RUN_TASK_GET_OBS_CCPA="FALSE" - RUN_TASK_GET_OBS_MRMS="FALSE" - RUN_TASK_GET_OBS_NDAS="FALSE" - -If users have access to NOAA :term:`HPSS` but have not pre-staged the data, they can simply set the ``RUN_TASK_GET_OBS_*`` tasks to "TRUE", and the machine will attempt to download the appropriate data from NOAA HPSS. The ``*_OBS_DIR`` paths must be set to the location where users want the downloaded data to reside. - -Users who do not have access to NOAA HPSS and do not have the data on their system will need to download :term:`CCPA`, :term:`MRMS`, and :term:`NDAS` data manually from collections of publicly available data, such as the ones listed `here `__. - -Next, the verification tasks must be turned on according to the user's needs. Users should add some or all of the following tasks to ``config.sh``, depending on the verification procedure(s) they have in mind: - -.. code-block:: console - - RUN_TASK_VX_GRIDSTAT="TRUE" - RUN_TASK_VX_POINTSTAT="TRUE" - RUN_TASK_VX_ENSGRID="TRUE" - RUN_TASK_VX_ENSPOINT="TRUE" - -These tasks are independent, so users may set some values to "TRUE" and others to "FALSE" depending on the needs of their experiment. Note that the ENSGRID and ENSPOINT tasks apply only to ensemble model verification. Additional verification tasks appear in :numref:`Table %s `. More details on all of the parameters in this section are available in :numref:`Section %s `. - -.. _SetUpPythonEnv: - -Set Up the Python and Other Environment Parameters ----------------------------------------------------- - -The workflow requires Python 3 with the packages ``PyYAML``, ``Jinja2``, and ``f90nml`` available. This Python environment has already been set up on Level 1 platforms, and it can be activated in the following way: - -.. code-block:: console - - module use - module load wflow_ - -The ``wflow_`` modulefile will then output instructions to activate the regional workflow. The user should run the commands specified in the modulefile output. For example, if the output says: - -.. code-block:: console - - Please do the following to activate conda: - > conda activate regional_workflow - -then the user should run ``conda activate regional_workflow``. This will activate the ``regional_workflow`` conda environment. However, the command(s) will vary from system to system. Regardless, the user should see ``(regional_workflow)`` in front of the Terminal prompt at this point. If this is not the case, activate the regional workflow from the ``ush`` directory by running: - -.. code-block:: console - - conda init - source ~/.bashrc - conda activate regional_workflow - -.. _LinuxMacActivateWFenv: - -Activating the Workflow Environment on Non-Level 1 Systems -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Users on non-Level 1 systems can copy one of the provided ``wflow_`` files and use it as a template to create a ``wflow_`` file that works for their system. ``wflow_macos`` and ``wflow_linux`` template files are provided with the release. After making appropriate modifications to a ``wflow_`` file, users can run the commands from :numref:`Step %s ` above to activate the regional workflow. - -On generic Linux or MacOS systems, loading the designated ``wflow_`` file will output instructions similar to the following: - -.. code-block:: console - - Please do the following to activate conda: - > source $VENV/bin/activate - -If that does not work, users can also try: - -.. code-block:: console - - source $HOME/venv/regional_workflow/bin/activate - -However, it may instead be necessary to make additional adjustments to the ``wflow_`` file. - -.. _GenerateWorkflow: - -Generate the Regional Workflow -------------------------------------------- - -Run the following command from the ``ufs-srweather-app/regional_workflow/ush`` directory to generate the workflow: - -.. code-block:: console - - ./generate_FV3LAM_wflow.sh - -The last line of output from this script, starting with ``*/1 * * * *`` or ``*/3 * * * *``, can be saved and :ref:`used later ` to automatically run portions of the workflow if users have the Rocoto workflow manager installed on their system. - -This workflow generation script creates an experiment directory and populates it with all the data needed to run through the workflow. The flowchart in :numref:`Figure %s ` describes the experiment generation process. First, ``generate_FV3LAM_wflow.sh`` runs the ``setup.sh`` script to set the configuration parameters. Second, it copies the time-independent (fix) files and other necessary data input files from their location in the ufs-weather-model directory to the experiment directory (``$EXPTDIR``). Third, it copies the weather model executable (``ufs_model``) from the ``bin`` directory to ``$EXPTDIR`` and creates the input namelist file ``input.nml`` based on the ``input.nml.FV3`` file in the regional_workflow/ush/templates directory. Lastly, it creates the workflow XML file ``FV3LAM_wflow.xml`` that is executed when running the experiment with the Rocoto workflow manager. - -The ``setup.sh`` script reads three other configuration scripts in order: (1) ``config_default.sh`` (:numref:`Section %s `), (2) ``config.sh`` (:numref:`Section %s `), and (3) ``set_predef_grid_params.sh``. If a parameter is specified differently in these scripts, the file containing the last defined value will be used. - -The generated workflow will appear in ``$EXPTDIR``, where ``EXPTDIR=${EXPT_BASEDIR}/${EXPT_SUBDIR}``. These variables were specified in the ``config.sh`` file in :numref:`Step %s `. The settings for these paths can also be viewed in the console output from the ``./generate_FV3LAM_wflow.sh`` script or in the ``log.generate_FV3LAM_wflow`` file, which can be found in ``$EXPTDIR``. - -.. _WorkflowGeneration: - -.. figure:: _static/FV3regional_workflow_gen_v2.png - :alt: Flowchart of the workflow generation process. Scripts are called in the following order: source_util_funcs.sh (which calls bash_utils), then set_FV3nml_sfc_climo_filenames.sh, set_FV3nml_stock_params.sh, create_diag_table_files.sh, and setup.sh. setup.sh calls several scripts: set_cycle_dates.sh, set_grid_params_GFDLgrid.sh, set_grid_params_ESGgrid.sh, link_fix.sh, set_ozone_param.sh, set_Thompson_mp_fix_files.sh, config_defaults.sh, config.sh, and valid_param_vals.sh. Then, it sets a number of variables, including FIXgsm, TOPO_DIR, and SFC_CLIMO_INPUT_DIR variables. Next, set_predef_grid_params.sh is called, and the FIXam and FIXLAM directories are set, along with the forecast input files. The setup script also calls set_extrn_mdl_params.sh, sets the GRID_GEN_METHOD with HALO, checks various parameters, and generates shell scripts. Then, the workflow generation script sets up YAML-compliant strings and generates the actual Rocoto workflow XML file from the template file (fill_jinja_template.py). The workflow generation script checks the crontab file and, if applicable, copies certain fix files to the experiment directory. Then, it copies templates of various input files to the experiment directory and sets parameters for the input.nml file. Finally, it generates the workflow. Additional information on each step appears in comments within each script. - - *Experiment generation description* - - -.. _WorkflowTaskDescription: - -Description of Workflow Tasks --------------------------------- - -.. note:: - This section gives a general overview of workflow tasks. To begin running the workflow, skip to :numref:`Step %s ` - -:numref:`Figure %s ` illustrates the overall workflow. Individual tasks that make up the workflow are specified in the ``FV3LAM_wflow.xml`` file. :numref:`Table %s ` describes the function of each baseline task. The first three pre-processing tasks; ``MAKE_GRID``, ``MAKE_OROG``, and ``MAKE_SFC_CLIMO`` are optional. If the user stages pre-generated grid, orography, and surface climatology fix files, these three tasks can be skipped by adding the following lines to the ``config.sh`` file before running the ``generate_FV3LAM_wflow.sh`` script: - -.. code-block:: console - - RUN_TASK_MAKE_GRID="FALSE" - RUN_TASK_MAKE_OROG="FALSE" - RUN_TASK_MAKE_SFC_CLIMO="FALSE" - - -.. _WorkflowTasksFig: - -.. figure:: _static/FV3LAM_wflow_flowchart_v2.png - :alt: Flowchart of the workflow tasks. If the make_grid, make_orog, and make_sfc_climo tasks are toggled off, they will not be run. If toggled on, make_grid, make_orog, and make_sfc_climo will run consecutively by calling the corresponding exregional script in the regional_workflow/scripts directory. The get_ics, get_lbcs, make_ics, make_lbcs, and run_fcst tasks call their respective exregional scripts. The run_post task will run, and if METplus verification tasks have been configured, those will run during post-processing by calling their exregional scripts. - - *Flowchart of the workflow tasks* - - -The ``FV3LAM_wflow.xml`` file runs the specific j-job scripts (``regional_workflow/jobs/JREGIONAL_[task name]``) in the prescribed order when the experiment is launched via the ``launch_FV3LAM_wflow.sh`` script or the ``rocotorun`` command. Each j-job task has its own source script (or "ex-script") named ``exregional_[task name].sh`` in the ``regional_workflow/scripts`` directory. Two database files named ``FV3LAM_wflow.db`` and ``FV3LAM_wflow_lock.db`` are generated and updated by the Rocoto calls. There is usually no need for users to modify these files. To relaunch the workflow from scratch, delete these two ``*.db`` files and then call the launch script repeatedly for each task. - - -.. _WorkflowTasksTable: - -.. table:: Baseline workflow tasks in the SRW App - - +----------------------+------------------------------------------------------------+ - | **Workflow Task** | **Task Description** | - +======================+============================================================+ - | make_grid | Pre-processing task to generate regional grid files. Only | - | | needs to be run once per experiment. | - +----------------------+------------------------------------------------------------+ - | make_orog | Pre-processing task to generate orography files. Only | - | | needs to be run once per experiment. | - +----------------------+------------------------------------------------------------+ - | make_sfc_climo | Pre-processing task to generate surface climatology files. | - | | Only needs to be run, at most, once per experiment. | - +----------------------+------------------------------------------------------------+ - | get_extrn_ics | Cycle-specific task to obtain external data for the | - | | initial conditions | - +----------------------+------------------------------------------------------------+ - | get_extrn_lbcs | Cycle-specific task to obtain external data for the | - | | lateral boundary conditions (LBCs) | - +----------------------+------------------------------------------------------------+ - | make_ics | Generate initial conditions from the external data | - +----------------------+------------------------------------------------------------+ - | make_lbcs | Generate LBCs from the external data | - +----------------------+------------------------------------------------------------+ - | run_fcst | Run the forecast model (UFS weather model) | - +----------------------+------------------------------------------------------------+ - | run_post | Run the post-processing tool (UPP) | - +----------------------+------------------------------------------------------------+ - -In addition to the baseline tasks described in :numref:`Table %s ` above, users may choose to run some or all of the METplus verification tasks. These tasks are described in :numref:`Table %s ` below. - -.. _VXWorkflowTasksTable: - -.. table:: Verification (VX) workflow tasks in the SRW App - - +-----------------------+------------------------------------------------------------+ - | **Workflow Task** | **Task Description** | - +=======================+============================================================+ - | GET_OBS_CCPA | Retrieves and organizes hourly :term:`CCPA` data from NOAA | - | | HPSS. Can only be run if ``RUN_TASK_GET_OBS_CCPA="TRUE"`` | - | | *and* user has access to NOAA :term:`HPSS` data. | - +-----------------------+------------------------------------------------------------+ - | GET_OBS_NDAS | Retrieves and organizes hourly :term:`NDAS` data from NOAA | - | | HPSS. Can only be run if ``RUN_TASK_GET_OBS_NDAS="TRUE"`` | - | | *and* user has access to NOAA HPSS data. | - +-----------------------+------------------------------------------------------------+ - | GET_OBS_MRMS | Retrieves and organizes hourly :term:`MRMS` composite | - | | reflectivity and :term:`echo top` data from NOAA HPSS. Can | - | | only be run if ``RUN_TASK_GET_OBS_MRMS="TRUE"`` *and* user | - | | has access to NOAA HPSS data. | - +-----------------------+------------------------------------------------------------+ - | VX_GRIDSTAT | Runs METplus grid-to-grid verification for 1-h accumulated | - | | precipitation | - +-----------------------+------------------------------------------------------------+ - | VX_GRIDSTAT_REFC | Runs METplus grid-to-grid verification for composite | - | | reflectivity | - +-----------------------+------------------------------------------------------------+ - | VX_GRIDSTAT_RETOP | Runs METplus grid-to-grid verification for :term:`echo top`| - +-----------------------+------------------------------------------------------------+ - | VX_GRIDSTAT_##h | Runs METplus grid-to-grid verification for 3-h, 6-h, and | - | | 24-h (i.e., daily) accumulated precipitation. Valid values | - | | for ``##`` are ``03``, ``06``, and ``24``. | - +-----------------------+------------------------------------------------------------+ - | VX_POINTSTAT | Runs METplus grid-to-point verification for surface and | - | | upper-air variables | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID | Runs METplus grid-to-grid ensemble verification for 1-h | - | | accumulated precipitation. Can only be run if | - | | ``DO_ENSEMBLE="TRUE"`` and ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID_REFC | Runs METplus grid-to-grid ensemble verification for | - | | composite reflectivity. Can only be run if | - | | ``DO_ENSEMBLE="TRUE"`` and | - | | ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID_RETOP | Runs METplus grid-to-grid ensemble verification for | - | | :term:`echo top`. Can only be run if ``DO_ENSEMBLE="TRUE"``| - | | and ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID_##h | Runs METplus grid-to-grid ensemble verification for 3-h, | - | | 6-h, and 24-h (i.e., daily) accumulated precipitation. | - | | Valid values for ``##`` are ``03``, ``06``, and ``24``. | - | | Can only be run if ``DO_ENSEMBLE="TRUE"`` and | - | | ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID_MEAN | Runs METplus grid-to-grid verification for ensemble mean | - | | 1-h accumulated precipitation. Can only be run if | - | | ``DO_ENSEMBLE="TRUE"`` and ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID_PROB | Runs METplus grid-to-grid verification for 1-h accumulated | - | | precipitation probabilistic output. Can only be run if | - | | ``DO_ENSEMBLE="TRUE"`` and ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID_MEAN_##h | Runs METplus grid-to-grid verification for ensemble mean | - | | 3-h, 6-h, and 24h (i.e., daily) accumulated precipitation. | - | | Valid values for ``##`` are ``03``, ``06``, and ``24``. | - | | Can only be run if ``DO_ENSEMBLE="TRUE"`` and | - | | ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID_PROB_##h | Runs METplus grid-to-grid verification for 3-h, 6-h, and | - | | 24h (i.e., daily) accumulated precipitation probabilistic | - | | output. Valid values for ``##`` are ``03``, ``06``, and | - | | ``24``. Can only be run if ``DO_ENSEMBLE="TRUE"`` and | - | | ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID_PROB_REFC | Runs METplus grid-to-grid verification for ensemble | - | | probabilities for composite reflectivity. Can only be run | - | | if ``DO_ENSEMBLE="TRUE"`` and | - | | ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSGRID_PROB_RETOP | Runs METplus grid-to-grid verification for ensemble | - | | probabilities for :term:`echo top`. Can only be run if | - | | ``DO_ENSEMBLE="TRUE"`` and ``RUN_TASK_VX_ENSGRID="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - | VX_ENSPOINT | Runs METplus grid-to-point ensemble verification for | - | | surface and upper-air variables. Can only be run if | - | | ``DO_ENSEMBLE="TRUE"`` and ``RUN_TASK_VX_ENSPOINT="TRUE"``.| - +-----------------------+------------------------------------------------------------+ - | VX_ENSPOINT_MEAN | Runs METplus grid-to-point verification for ensemble mean | - | | surface and upper-air variables. Can only be run if | - | | ``DO_ENSEMBLE="TRUE"`` and ``RUN_TASK_VX_ENSPOINT="TRUE"``.| - +-----------------------+------------------------------------------------------------+ - | VX_ENSPOINT_PROB | Runs METplus grid-to-point verification for ensemble | - | | probabilities for surface and upper-air variables. Can | - | | only be run if ``DO_ENSEMBLE="TRUE"`` and | - | | ``RUN_TASK_VX_ENSPOINT="TRUE"``. | - +-----------------------+------------------------------------------------------------+ - - -.. _Run: - -Run the Workflow -======================= - -The workflow can be run using the Rocoto workflow manager (see :numref:`Section %s `) or using standalone wrapper scripts (see :numref:`Section %s `). - -.. attention:: - - If users are running the SRW App on a system that does not have Rocoto installed (e.g., `Level 3 & 4 `__ systems, such as MacOS or generic Linux systems), they should follow the process outlined in :numref:`Section %s ` instead of the instructions in this section. - - -.. _UseRocoto: - -Run the Workflow Using Rocoto --------------------------------- - -The information in this section assumes that Rocoto is available on the desired platform. All official HPC platforms for the UFS SRW App release make use of the Rocoto workflow management software for running experiments. However, Rocoto cannot be used when running the workflow within a container. If Rocoto is not available, it is still possible to run the workflow using stand-alone scripts according to the process outlined in :numref:`Section %s `. - -There are two main ways to run the workflow with Rocoto: (1) with the ``launch_FV3LAM_wflow.sh`` script, and (2) by manually calling the ``rocotorun`` command. Users can also automate the workflow using a crontab. - -.. note:: - Users may find it helpful to review :numref:`Chapter %s ` to gain a better understanding of Rocoto commands and workflow management before continuing, but this is not required to run the experiment. - -Optionally, an environment variable can be set to navigate to the ``$EXPTDIR`` more easily. If the login shell is bash, it can be set as follows: - -.. code-block:: console - - export EXPTDIR=// - -If the login shell is csh/tcsh, it can be set using: - -.. code-block:: console - - setenv EXPTDIR // - - -.. _Automate: - -Automated Option -^^^^^^^^^^^^^^^^^^^ - -The simplest way to run the Rocoto workflow is to automate the process using a job scheduler such as :term:`Cron`. For automatic resubmission of the workflow at regular intervals (e.g., every minute), the user can add the following commands to their ``config.sh`` file *before* generating the experiment: - -.. code-block:: console - - USE_CRON_TO_RELAUNCH="TRUE" - CRON_RELAUNCH_INTVL_MNTS="02" - -This will automatically add an appropriate entry to the user's :term:`cron table` and launch the workflow. Alternatively, the user can add a crontab entry using the ``crontab -e`` command. As mentioned in :numref:`Section %s `, the last line of output from ``./generate_FV3LAM_wflow.sh`` (starting with ``*/1 * * * *`` or ``*/3 * * * *``), can be pasted into the crontab file. It can also be found in the ``$EXPTDIR/log.generate_FV3LAM_wflow`` file. The crontab entry should resemble the following: - -.. code-block:: console - - */3 * * * * cd && ./launch_FV3LAM_wflow.sh called_from_cron="TRUE" - -where ```` is changed to correspond to the user's ``$EXPTDIR``. The number ``3`` can be changed to a different positive integer and simply means that the workflow will be resubmitted every three minutes. - -.. hint:: - - * On NOAA Cloud instances, ``*/1 * * * *`` is the preferred option for cron jobs because compute nodes will shut down if they remain idle too long. If the compute node shuts down, it can take 15-20 minutes to start up a new one. - * On other NOAA HPC systems, admins discourage the ``*/1 * * * *`` due to load problems. ``*/3 * * * *`` is the preferred option for cron jobs on non-NOAA Cloud systems. - -To check the experiment progress: - -.. code-block:: console - - cd $EXPTDIR - rocotostat -w FV3LAM_wflow.xml -d FV3LAM_wflow.db -v 10 - - - -After finishing the experiment, open the crontab using ``crontab -e`` and delete the crontab entry. - -.. note:: - - On Orion, *cron* is only available on the orion-login-1 node, so users will need to work on that node when running *cron* jobs on Orion. - -.. _Success: - -The workflow run is complete when all tasks have "SUCCEEDED". If everything goes smoothly, users will eventually see a workflow status table similar to the following: - -.. code-block:: console - - CYCLE TASK JOBID STATE EXIT STATUS TRIES DURATION - ========================================================================================================== - 201906150000 make_grid 4953154 SUCCEEDED 0 1 5.0 - 201906150000 make_orog 4953176 SUCCEEDED 0 1 26.0 - 201906150000 make_sfc_climo 4953179 SUCCEEDED 0 1 33.0 - 201906150000 get_extrn_ics 4953155 SUCCEEDED 0 1 2.0 - 201906150000 get_extrn_lbcs 4953156 SUCCEEDED 0 1 2.0 - 201906150000 make_ics 4953184 SUCCEEDED 0 1 16.0 - 201906150000 make_lbcs 4953185 SUCCEEDED 0 1 71.0 - 201906150000 run_fcst 4953196 SUCCEEDED 0 1 1035.0 - 201906150000 run_post_f000 4953244 SUCCEEDED 0 1 5.0 - 201906150000 run_post_f001 4953245 SUCCEEDED 0 1 4.0 - ... - 201906150000 run_post_f012 4953381 SUCCEEDED 0 1 7.0 - -If users choose to run METplus verification tasks as part of their experiment, the output above will include additional lines after ``run_post_f012``. The output will resemble the following but may be significantly longer when using ensemble verification: - -.. code-block:: console - - CYCLE TASK JOBID STATE EXIT STATUS TRIES DURATION - ========================================================================================================== - 201906150000 make_grid 30466134 SUCCEEDED 0 1 5.0 - ... - 201906150000 run_post_f012 30468271 SUCCEEDED 0 1 7.0 - 201906150000 run_gridstatvx 30468420 SUCCEEDED 0 1 53.0 - 201906150000 run_gridstatvx_refc 30468421 SUCCEEDED 0 1 934.0 - 201906150000 run_gridstatvx_retop 30468422 SUCCEEDED 0 1 1002.0 - 201906150000 run_gridstatvx_03h 30468491 SUCCEEDED 0 1 43.0 - 201906150000 run_gridstatvx_06h 30468492 SUCCEEDED 0 1 29.0 - 201906150000 run_gridstatvx_24h 30468493 SUCCEEDED 0 1 20.0 - 201906150000 run_pointstatvx 30468423 SUCCEEDED 0 1 670.0 - - -Launch the Rocoto Workflow Using a Script -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Users who prefer not to automate their experiments can run the Rocoto workflow using the ``launch_FV3LAM_wflow.sh`` script provided. Simply call it without any arguments from the experiment directory: - -.. code-block:: console - - cd $EXPTDIR - ./launch_FV3LAM_wflow.sh - -This script creates a log file named ``log.launch_FV3LAM_wflow`` in ``$EXPTDIR`` or appends information to the file if it already exists. The launch script also creates the ``log/FV3LAM_wflow.log`` file, which shows Rocoto task information. Check the end of the log file periodically to see how the experiment is progressing: - -.. code-block:: console - - tail -n 40 log.launch_FV3LAM_wflow - -In order to launch additional tasks in the workflow, call the launch script again; this action will need to be repeated until all tasks in the workflow have been launched. To (re)launch the workflow and check its progress on a single line, run: - -.. code-block:: console - - ./launch_FV3LAM_wflow.sh; tail -n 40 log.launch_FV3LAM_wflow - -This will output the last 40 lines of the log file, which list the status of the workflow tasks (e.g., SUCCEEDED, DEAD, RUNNING, SUBMITTING, QUEUED). The number 40 can be changed according to the user's preferences. The output will look like this: - -.. code-block:: console - - CYCLE TASK JOBID STATE EXIT STATUS TRIES DURATION - ====================================================================================================== - 202006170000 make_grid druby://hfe01:33728 SUBMITTING - 0 0.0 - 202006170000 make_orog - - - - - - 202006170000 make_sfc_climo - - - - - - 202006170000 get_extrn_ics druby://hfe01:33728 SUBMITTING - 0 0.0 - 202006170000 get_extrn_lbcs druby://hfe01:33728 SUBMITTING - 0 0.0 - 202006170000 make_ics - - - - - - 202006170000 make_lbcs - - - - - - 202006170000 run_fcst - - - - - - 202006170000 run_post_00 - - - - - - 202006170000 run_post_01 - - - - - - 202006170000 run_post_02 - - - - - - 202006170000 run_post_03 - - - - - - 202006170000 run_post_04 - - - - - - 202006170000 run_post_05 - - - - - - 202006170000 run_post_06 - - - - - - - Summary of workflow status: - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - 0 out of 1 cycles completed. - Workflow status: IN PROGRESS - -If all the tasks complete successfully, the "Workflow status" at the bottom of the log file will change from "IN PROGRESS" to "SUCCESS". If certain tasks could not complete, the "Workflow status" will instead change to "FAILURE". Error messages for each specific task can be found in the task log files located in ``$EXPTDIR/log``. - -The workflow run is complete when all tasks have "SUCCEEDED", and the ``rocotostat`` command outputs a table similar to the one :ref:`above `. - - -.. _RocotoManualRun: - -Launch the Rocoto Workflow Manually -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -**Load Rocoto** - -Instead of running the ``./launch_FV3LAM_wflow.sh`` script, users can load Rocoto and any other required modules. This gives the user more control over the process and allows them to view experiment progress more easily. On Level 1 systems, the Rocoto modules are loaded automatically in :numref:`Step %s `. For most other systems, a variant on the following commands will be necessary to load the Rocoto module: - -.. code-block:: console - - module use - module load rocoto - -Some systems may require a version number (e.g., ``module load rocoto/1.3.3``) - -**Run the Rocoto Workflow** - -After loading Rocoto, call ``rocotorun`` from the experiment directory to launch the workflow tasks. This will start any tasks that do not have a dependency. As the workflow progresses through its stages, ``rocotostat`` will show the state of each task and allow users to monitor progress: - -.. code-block:: console - - cd $EXPTDIR - rocotorun -w FV3LAM_wflow.xml -d FV3LAM_wflow.db -v 10 - rocotostat -w FV3LAM_wflow.xml -d FV3LAM_wflow.db -v 10 - -The ``rocotorun`` and ``rocotostat`` commands above will need to be resubmitted regularly and repeatedly until the experiment is finished. In part, this is to avoid having the system time out. This also ensures that when one task ends, tasks dependent on it will run as soon as possible, and ``rocotostat`` will capture the new progress. - -If the experiment fails, the ``rocotostat`` command will indicate which task failed. Users can look at the log file in the ``log`` subdirectory for the failed task to determine what caused the failure. For example, if the ``make_grid`` task failed, users can open the ``make_grid.log`` file to see what caused the problem: - -.. code-block:: console - - cd $EXPTDIR/log - vi make_grid.log - -.. note:: - - If users have the `Slurm workload manager `__ on their system, they can run the ``squeue`` command in lieu of ``rocotostat`` to check what jobs are currently running. - - -.. _RunUsingStandaloneScripts: - -Run the Workflow Using Stand-Alone Scripts ---------------------------------------------- - -.. note:: - The Rocoto workflow manager cannot be used inside a container. - -The regional workflow can be run using standalone shell scripts in cases where the Rocoto software is not available on a given platform. If Rocoto *is* available, see :numref:`Section %s ` to run the workflow using Rocoto. - -#. ``cd`` into the experiment directory - -#. Set the environment variable ``$EXPTDIR`` for either bash or csh, respectively: - - .. code-block:: console - - export EXPTDIR=`pwd` - setenv EXPTDIR `pwd` - -#. Copy the wrapper scripts from the ``regional_workflow`` directory into the experiment directory. Each workflow task has a wrapper script that sets environment variables and runs the job script. - - .. code-block:: console - - cp /ufs-srweather-app/regional_workflow/ush/wrappers/* . - -#. Set the ``OMP_NUM_THREADS`` variable. - - .. code-block:: console - - export OMP_NUM_THREADS=1 - -#. Run each of the listed scripts in order. Scripts with the same stage number (listed in :numref:`Table %s `) may be run simultaneously. - - .. code-block:: console - - ./run_make_grid.sh - ./run_get_ics.sh - ./run_get_lbcs.sh - ./run_make_orog.sh - ./run_make_sfc_climo.sh - ./run_make_ics.sh - ./run_make_lbcs.sh - ./run_fcst.sh - ./run_post.sh - -Check the batch script output file in your experiment directory for a “SUCCESS” message near the end of the file. - -.. _RegionalWflowTasks: - -.. table:: List of tasks in the regional workflow in the order that they are executed. - Scripts with the same stage number may be run simultaneously. The number of - processors and wall clock time is a good starting point for Cheyenne or Hera - when running a 48-h forecast on the 25-km CONUS domain. For a brief description of tasks, see :numref:`Table %s `. - - +------------+------------------------+----------------+----------------------------+ - | **Stage/** | **Task Run Script** | **Number of** | **Wall clock time (H:mm)** | - | **step** | | **Processors** | | - +============+========================+================+============================+ - | 1 | run_get_ics.sh | 1 | 0:20 (depends on HPSS vs | - | | | | FTP vs staged-on-disk) | - +------------+------------------------+----------------+----------------------------+ - | 1 | run_get_lbcs.sh | 1 | 0:20 (depends on HPSS vs | - | | | | FTP vs staged-on-disk) | - +------------+------------------------+----------------+----------------------------+ - | 1 | run_make_grid.sh | 24 | 0:20 | - +------------+------------------------+----------------+----------------------------+ - | 2 | run_make_orog.sh | 24 | 0:20 | - +------------+------------------------+----------------+----------------------------+ - | 3 | run_make_sfc_climo.sh | 48 | 0:20 | - +------------+------------------------+----------------+----------------------------+ - | 4 | run_make_ics.sh | 48 | 0:30 | - +------------+------------------------+----------------+----------------------------+ - | 4 | run_make_lbcs.sh | 48 | 0:30 | - +------------+------------------------+----------------+----------------------------+ - | 5 | run_fcst.sh | 48 | 0:30 | - +------------+------------------------+----------------+----------------------------+ - | 6 | run_post.sh | 48 | 0:25 (2 min per output | - | | | | forecast hour) | - +------------+------------------------+----------------+----------------------------+ - -Users can access log files for specific tasks in the ``$EXPTDIR/log`` directory. To see how the experiment is progressing, users can also check the end of the ``log.launch_FV3LAM_wflow`` file from the command line: - -.. code-block:: console - - tail -n 40 log.launch_FV3LAM_wflow - -.. hint:: - If any of the scripts return an error that "Primary job terminated normally, but one process returned a non-zero exit code," there may not be enough space on one node to run the process. On an HPC system, the user will need to allocate a(nother) compute node. The process for doing so is system-dependent, and users should check the documentation available for their HPC system. Instructions for allocating a compute node on NOAA Cloud systems can be viewed in :numref:`Section %s ` as an example. - -.. note:: - On most HPC systems, users will need to submit a batch job to run multi-processor jobs. On some HPC systems, users may be able to run the first two jobs (serial) on a login node/command-line. Example scripts for Slurm (Hera) and PBS (Cheyenne) resource managers are provided (``sq_job.sh`` and ``qsub_job.sh``, respectively). These examples will need to be adapted to each user's system. Alternatively, some batch systems allow users to specify most of the settings on the command line (with the ``sbatch`` or ``qsub`` command, for example). - - - -.. _PlotOutput: - -Plot the Output -=============== -Two python scripts are provided to generate plots from the :term:`FV3`-LAM post-processed :term:`GRIB2` output. Information on how to generate the graphics can be found in :numref:`Chapter %s `. diff --git a/docs/UsersGuide/source/BuildSRW.rst b/docs/UsersGuide/source/BuildSRW.rst new file mode 100644 index 0000000000..85790b482c --- /dev/null +++ b/docs/UsersGuide/source/BuildSRW.rst @@ -0,0 +1,496 @@ +.. _BuildSRW: + +========================== +Building the SRW App +========================== + +The Unified Forecast System (:term:`UFS`) Short-Range Weather (SRW) Application is an :term:`umbrella repository` consisting of a number of different :ref:`components ` housed in external repositories. Once the SRW App is built, users can configure experiments and generate predictions of atmospheric behavior over a limited spatial area and on time scales ranging from minutes out to several days. + +.. attention:: + + The SRW Application has `four levels of support `__. The steps described in this chapter will work most smoothly on preconfigured (Level 1) systems. This chapter can also serve as a starting point for running the SRW App on other systems (including generic Linux/Mac systems), but the user may need to perform additional troubleshooting. + +.. note:: + The :ref:`container approach ` is recommended for a smoother first-time build and run experience. Building without a container may allow for more customization. However, the non-container approach requires more in-depth system-based knowledge, especially on Level 3 and 4 systems, so it is less appropriate for beginners. + +To build the SRW App, users will complete the following steps: + + #. :ref:`Install prerequisites ` + #. :ref:`Clone the SRW App from GitHub ` + #. :ref:`Check out the external repositories ` + #. :ref:`Set up the build environment and build the executables ` + +.. _AppBuildProc: + +.. figure:: _static/SRW_build_process.png + :alt: Flowchart describing the SRW App build process. + + *Overview of the SRW App Build Process* + + +.. _HPCstackInfo: + +Install the HPC-Stack +======================== + +.. Attention:: + Skip the HPC-Stack installation if working on a `Level 1 system `_ (e.g., Cheyenne, Hera, Orion, NOAA Cloud). + +**Definition:** :term:`HPC-Stack` is a repository that provides a unified, shell script-based build system to build the software stack required for `UFS `_ applications such as the SRW App. + +Background +---------------- + +The UFS Weather Model draws on over 50 code libraries to run its applications. These libraries range from libraries developed in-house at NOAA (e.g., NCEPLIBS, FMS) to libraries developed by NOAA's partners (e.g., PIO, ESMF) to truly third party libraries (e.g., NETCDF). Individual installation of these libraries is not practical, so the `HPC-Stack `__ was developed as a central installation system to ensure that the infrastructure environment across multiple platforms is as similar as possible. Installation of the HPC-Stack is required to run the SRW App. + +Instructions +------------------------- +Users working on systems that fall under `Support Levels 2-4 `__ will need to install the HPC-Stack the first time they try to build applications (such as the SRW App) that depend on it. Users can either build the HPC-Stack on their local system or use the centrally maintained stacks on each HPC platform if they are working on a Level 1 system. Before installing the HPC-Stack, users on both Linux and MacOS systems should set the stack size to "unlimited" (if allowed) or to the largest possible value: + +.. code-block:: console + + # Linux, if allowed + ulimit -s unlimited + + # MacOS, this corresponds to 65MB + ulimit -S -s unlimited + +For a detailed description of installation options, see :ref:`Installing the HPC-Stack `. + +After completing installation, continue to the next section (:numref:`Section %s: Download the UFS SRW Application Code `). + +.. _DownloadSRWApp: + +Download the UFS SRW Application Code +====================================== +The SRW Application source code is publicly available on GitHub. To download the SRW App code, clone the ``develop`` branch of the repository: + +.. code-block:: console + + git clone -b develop https://github.com/ufs-community/ufs-srweather-app.git + +The cloned repository contains the configuration files and sub-directories shown in +:numref:`Table %s `. The user may set an ``$SRW`` environment variable to point to the location of the new ``ufs-srweather-app`` repository. For example, if ``ufs-srweather-app`` was cloned into the ``$HOME`` directory, the following commands will set an ``$SRW`` environment variable in a bash or csh shell, respectively: + +.. code-block:: console + + export SRW=$HOME/ufs-srweather-app + setenv SRW $HOME/ufs-srweather-app + +.. _FilesAndSubDirs: + +.. table:: Files and sub-directories of the ufs-srweather-app repository + + +--------------------------------+-----------------------------------------------------------+ + | **File/Directory Name** | **Description** | + +================================+===========================================================+ + | CMakeLists.txt | Main CMake file for SRW App | + +--------------------------------+-----------------------------------------------------------+ + | devbuild.sh | SRW App build script | + +--------------------------------+-----------------------------------------------------------+ + | docs | Contains release notes, documentation, and User's Guide | + +--------------------------------+-----------------------------------------------------------+ + | environment.yml | Contains information on the package versions required for | + | | the regional workflow environment. | + +--------------------------------+-----------------------------------------------------------+ + | etc | Contains Lmod startup scripts | + +--------------------------------+-----------------------------------------------------------+ + | Externals.cfg | Includes tags pointing to the correct version of the | + | | external GitHub repositories/branches used in the SRW | + | | App. | + +--------------------------------+-----------------------------------------------------------+ + | jobs | Contains the *j-job* script for each workflow task. These | + | | scripts set up the environment variables and call an | + | | *ex-script* script located in the ``scripts`` | + | | subdirectory. | + +--------------------------------+-----------------------------------------------------------+ + | LICENSE.md | CC0 license information | + +--------------------------------+-----------------------------------------------------------+ + | manage_externals | Utility for checking out external repositories | + +--------------------------------+-----------------------------------------------------------+ + | modulefiles | Contains build and workflow modulefiles | + +--------------------------------+-----------------------------------------------------------+ + | parm | Contains parameter files. Includes UFS Weather Model | + | | configuration files such as ``model_configure``, | + | | ``diag_table``, and ``field_table``. | + +--------------------------------+-----------------------------------------------------------+ + | README.md | Getting Started Guide | + +--------------------------------+-----------------------------------------------------------+ + | rename_model.sh | Used to rename the model before it becomes NCO | + | | operational. The SRW App is a generic app that is the base| + | | for models such as :term:`AQM` and :term:`RRFS`. When | + | | these models become operational, variables like | + | | ``HOMEdir`` and ``PARMdir`` will be renamed to | + | | ``HOMEaqm``/``HOMErrfs``, ``PARMaqm``/``PARMrrfs``, etc. | + | | using this script. | + +--------------------------------+-----------------------------------------------------------+ + | scripts | Contains the *ex-script* for each workflow task. | + | | These scripts are where the script logic and executables | + | | are contained. | + +--------------------------------+-----------------------------------------------------------+ + | sorc | Contains CMakeLists.txt; external repositories | + | | will be cloned into this directory. | + +--------------------------------+-----------------------------------------------------------+ + | tests | Contains SRW App tests, including workflow end-to-end | + | | (WE2E) tests. | + +--------------------------------+-----------------------------------------------------------+ + | ufs_srweather_app_meta.h.in | Meta information for SRW App which can be used by | + | | other packages | + +--------------------------------+-----------------------------------------------------------+ + | ufs_srweather_app.settings.in | SRW App configuration summary | + +--------------------------------+-----------------------------------------------------------+ + | ush | Contains utility scripts. Includes the experiment | + | | configuration file and the experiment generation file. | + +--------------------------------+-----------------------------------------------------------+ + | versions | Contains ``run.ver`` and ``build.ver`` files, which track | + | | package versions at run time and compile time, | + | | respectively. | + +--------------------------------+-----------------------------------------------------------+ + +.. COMMENT: Is environment.yml deprecated? Remove? + +.. _CheckoutExternals: + +Check Out External Components +================================ + +The SRW App relies on a variety of components (e.g., UFS_UTILS, ufs-weather-model, and UPP) detailed in :numref:`Chapter %s ` of this User's Guide. Each component has its own repository. Users must run the ``checkout_externals`` script to collect the individual components of the SRW App from their respective GitHub repositories. The ``checkout_externals`` script uses the configuration file ``Externals.cfg`` in the top level directory of the SRW App to clone the correct tags (code versions) of the external repositories listed in :numref:`Section %s ` into the appropriate directories (e.g., ``ush``, ``sorc``). + +Run the executable that pulls in SRW App components from external repositories: + +.. code-block:: console + + cd $SRW + ./manage_externals/checkout_externals + +The script should output dialogue indicating that it is retrieving different code repositories. It may take several minutes to download these repositories. + +To see more options for the ``checkout_externals`` script, users can run ``./manage_externals/checkout_externals -h``. For example: + + * ``-S``: Outputs the status of the repositories managed by ``checkout_externals``. By default only summary information is provided. Use with the ``-v`` (verbose) option to see details. + * ``-x [EXCLUDE [EXCLUDE ...]]``: allows users to exclude components when checking out externals. + * ``-o``: By default only the required externals are checked out. This flag will also checkout the optional externals. + +Generally, users will not need to use the options and can simply run the script, but the options are available for those who are curious. + +.. _BuildExecutables: + +Set Up the Environment and Build the Executables +=================================================== + +.. _DevBuild: + +``devbuild.sh`` Approach +----------------------------- + +On Level 1 systems for which a modulefile is provided under the ``modulefiles`` directory, users can build the SRW App binaries with the following command: + +.. code-block:: console + + ./devbuild.sh --platform= + +where ```` is replaced with the name of the platform the user is working on. Valid values are: ``cheyenne`` | ``gaea`` | ``hera`` | ``jet`` | ``linux`` | ``macos`` | ``noaacloud`` | ``odin`` | ``orion`` | ``singularity`` | ``wcoss2`` + +.. note:: + Although build modulefiles exist for generic Linux and MacOS machines, users will need to alter these according to the instructions in Sections :numref:`%s ` & :numref:`%s `. Users on these systems may have more success building the SRW App with the :ref:`CMake Approach ` instead. + +If compiler auto-detection fails for some reason, specify it using the ``--compiler`` argument. For example: + +.. code-block:: console + + ./devbuild.sh --platform=hera --compiler=intel + +where valid values are ``intel`` or ``gnu``. + +The last line of the console output should be ``[100%] Built target ufs-weather-model``, indicating that the UFS Weather Model executable has been built successfully. + +If users want to build the optional ``GSI`` and ``rrfs_utl`` components for :term:`RRFS`, they can pass the ``gsi`` and ``rrfs_utils`` arguments to ``devbuild.sh``. For example: + +.. code-block:: console + + ./devbuild.sh -p=hera gsi rrfs_utils + +.. note:: + RRFS capabilities are currently build-only features. They are not yet available for use at runtime. + +The last few lines of the RRFS console output should be: + +.. code-block:: console + + [100%] Built target RRFS_UTILS + Install the project... + -- Install configuration: "RELEASE" + -- Installing: /path/to/ufs-srweather-app/exec/ufs_srweather_app.settings + +After running ``devbuild.sh``, the executables listed in :numref:`Table %s ` should appear in the ``ufs-srweather-app/exec`` directory. If users choose to build the ``GSI`` and ``rrfs_utils`` components, the executables listed in :numref:`Table %s ` will also appear there. If the ``devbuild.sh`` build method does not work, or if users are not on a supported machine, they will have to manually set up the environment and build the SRW App binaries with CMake as described in :numref:`Section %s `. + +.. _ExecDescription: + +.. table:: Names and descriptions of the executables produced by the build step and used by the SRW App + + +------------------------+---------------------------------------------------------------------------------+ + | **Executable Name** | **Description** | + +========================+=================================================================================+ + | chgres_cube | Reads in raw external model (global or regional) and surface climatology data | + | | to create initial and lateral boundary conditions | + +------------------------+---------------------------------------------------------------------------------+ + | emcsfc_ice_blend | Blends National Ice Center sea ice cover and EMC sea ice concentration data to | + | | create a global sea ice analysis used to update the GFS once per day | + +------------------------+---------------------------------------------------------------------------------+ + | emcsfc_snow2mdl | Blends National Ice Center snow cover and Air Force snow depth data to create a | + | | global depth analysis used to update the GFS snow field once per day | + +------------------------+---------------------------------------------------------------------------------+ + | filter_topo | Filters topography based on resolution | + +------------------------+---------------------------------------------------------------------------------+ + | fregrid | Remaps data from the input mosaic grid to the output mosaic grid | + +------------------------+---------------------------------------------------------------------------------+ + | fvcom_to_FV3 | Determines lake surface conditions for the Great Lakes | + +------------------------+---------------------------------------------------------------------------------+ + | global_cycle | Updates the GFS surface conditions using external snow and sea ice analyses | + +------------------------+---------------------------------------------------------------------------------+ + | global_equiv_resol | Calculates a global, uniform, cubed-sphere equivalent resolution for the | + | | regional Extended Schmidt Gnomonic (ESG) grid | + +------------------------+---------------------------------------------------------------------------------+ + | inland | Creates an inland land mask by determining inland (i.e., non-coastal) points | + | | and assigning a value of 1. Default value is 0. | + +------------------------+---------------------------------------------------------------------------------+ + | lakefrac | Calculates the ratio of the lake area to the grid cell area at each atmospheric | + | | grid point. | + +------------------------+---------------------------------------------------------------------------------+ + | make_hgrid | Computes geo-referencing parameters (e.g., latitude, longitude, grid cell area) | + | | for global uniform grids | + +------------------------+---------------------------------------------------------------------------------+ + | make_solo_mosaic | Creates mosaic files with halos | + +------------------------+---------------------------------------------------------------------------------+ + | orog | Generates orography, land mask, and gravity wave drag files from fixed files | + +------------------------+---------------------------------------------------------------------------------+ + | orog_gsl | Creates orographic statistics fields required for the orographic drag suite | + | | developed by NOAA's Global Systems Laboratory (GSL) | + +------------------------+---------------------------------------------------------------------------------+ + | regional_esg_grid | Generates an ESG regional grid based on a user-defined namelist | + +------------------------+---------------------------------------------------------------------------------+ + | sfc_climo_gen | Creates surface climatology fields from fixed files for use in ``chgres_cube`` | + +------------------------+---------------------------------------------------------------------------------+ + | shave | Shaves the excess halo rows down to what is required for the lateral boundary | + | | conditions (LBCs) in the orography and grid files | + +------------------------+---------------------------------------------------------------------------------+ + | upp.x | Post processor for the model output | + +------------------------+---------------------------------------------------------------------------------+ + | ufs_model | UFS Weather Model executable | + +------------------------+---------------------------------------------------------------------------------+ + | vcoord_gen | Generates hybrid coordinate interface profiles | + +------------------------+---------------------------------------------------------------------------------+ + +.. _RRFSexec: + +.. table:: Names and descriptions of the executables produced when the RRFS option is enabled + + +----------------------------+-----------------------------------------------------------------------------+ + | **Executable Name** | **Description** | + +============================+=============================================================================+ + | gsi.x | Runs the Gridpoint Statistical Interpolation (GSI). | + +----------------------------+-----------------------------------------------------------------------------+ + | enkf.x | Runs the Ensemble Kalman Filter. | + +----------------------------+-----------------------------------------------------------------------------+ + | adjust_soiltq.exe | Uses the lowest-level temperature and moisture analysis increments to | + | | adjust the soil moisture and soil temperature after analysis. | + +----------------------------+-----------------------------------------------------------------------------+ + | check_imssnow_fv3lam.exe | This is a tool used to read snow and ice fields from surface files and | + | | check those fields. | + +----------------------------+-----------------------------------------------------------------------------+ + | fv3lam_nonvarcldana.exe | Runs the non-variational cloud and precipitable hydrometeor analysis based | + | | on the METAR cloud observations, satellite retrieved cloud top products, | + | | and radar reflectivity. | + +----------------------------+-----------------------------------------------------------------------------+ + | gen_annual_maxmin_GVF.exe | Generates maximum and minimum greenness vegetation fraction (GVF) files | + | | based on year-long GVF observations for the ``update_GVF`` process. | + +----------------------------+-----------------------------------------------------------------------------+ + | gen_cs.exe | NCL scripts to do cross section plotting. | + +----------------------------+-----------------------------------------------------------------------------+ + | gen_ensmean_recenter.exe | Runs the ensemble mean/recentering calculation for FV3LAM ensemble files. | + +----------------------------+-----------------------------------------------------------------------------+ + | lakesurgery.exe | Replaces the existing lake depth with the GLOBathy bathymetry. It is | + | | designed to work with the HRRR model. | + +----------------------------+-----------------------------------------------------------------------------+ + | nc_diag_cat.x | Performs :term:`NetCDF` Diagnostic Concatenation. Reads metadata while | + | | allocating necessary space, defines variables with the metadata (no | + | | attributes are stored), then finally add data to the output file. | + | | This is the MPI executable. | + +----------------------------+-----------------------------------------------------------------------------+ + | process_imssnow_fv3lam.exe | Uses FV3LAM snow and ice fields based on the snow and ice information from | + | | imssnow. | + +----------------------------+-----------------------------------------------------------------------------+ + | process_larccld.exe | Processes NASA Langley cloud top product, which reads the cloud top | + | | pressure, temperature, etc. and maps them to the ESG grid. | + +----------------------------+-----------------------------------------------------------------------------+ + | process_Lightning.exe | Processes lightning data. Reads NLDN NetCDF observation files and map the | + | | lightning observations into FV3LAM ESG grid. | + +----------------------------+-----------------------------------------------------------------------------+ + | process_metarcld.exe | Processes METAR ceilometer cloud observations. Reads the cloud base and | + | | coverage observations from PrepBUFR and distributes the cloud, weather, | + | | and visibility observations to the ESG grid. | + +----------------------------+-----------------------------------------------------------------------------+ + | process_NSSL_mosaic.exe | Processes :term:`NSSL` MRMS radar reflectivity mosaic observations. Reads | + | | 33-level NSSL MRMS radar reflectivity grib2 files and then interpolates the | + | | reflectivity horizontally to the ESG grid. | + +----------------------------+-----------------------------------------------------------------------------+ + | process_updatesst.exe | Updates Sea Surface Temperature (SST) field based on the SST analysis from | + | | NCEP. | + +----------------------------+-----------------------------------------------------------------------------+ + | ref2tten.exe | Calculates temperature tendency based on the radar reflectivity observation | + | | at each grid point. This temperature tendency can be used by the model | + | | during integration as latent heating initialization for ongoing | + | | precipitation systems, especially convection. | + +----------------------------+-----------------------------------------------------------------------------+ + | test_nc_unlimdims.x | Checks to see the number of fields with unlimited dimensions in NetCDF | + | | files. | + +----------------------------+-----------------------------------------------------------------------------+ + | ufs_srweather_app.settings | | + +----------------------------+-----------------------------------------------------------------------------+ + | update_bc.exe | Adjusts 0-h boundary conditions based on the analysis results during data | + | | assimilation cycling. | + +----------------------------+-----------------------------------------------------------------------------+ + | update_GVF.exe | Updates the GVF in the surface file based on the real-time observation | + | | files. | + +----------------------------+-----------------------------------------------------------------------------+ + | update_ice.exe | Replaces ice fields in warm start surface files based on the forecast from | + | | cold start forecast using the GFS as the initial file. | + +----------------------------+-----------------------------------------------------------------------------+ + | use_raphrrr_sfc.exe | Uses RAP and HRRR surface fields to replace the surface fields in FV3LAM. | + | | This is only used for starting the RRFS surface cycling. | + +----------------------------+-----------------------------------------------------------------------------+ + +.. COMMENT: What does ufs_srweather_app.settings do? + - precipitable hydrometeor analysis? + - What does the update_ice.exe description mean? + + +.. _CMakeApproach: + +CMake Approach +----------------- + +Set Up the Build Environment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. attention:: + * If users successfully built the executables in :numref:`Table %s `, they should skip to step :numref:`Chapter %s `. + * Users who want to build the SRW App on a generic MacOS should skip to :numref:`Section %s ` and follow the approach there. + +If the ``devbuild.sh`` approach failed, users need to set up their environment to run a workflow on their specific platform. First, users should make sure ``Lmod`` is the app used for loading modulefiles. This is the case on most Level 1 systems; however, on systems such as Gaea/Odin, the default modulefile loader is from Cray and must be switched to Lmod. For example, on Gaea, users can run one of the following two commands depending on whether they have a bash or csh shell, respectively: + +.. code-block:: console + + source etc/lmod-setup.sh gaea + source etc/lmod-setup.csh gaea + +If users execute one of the above commands on systems that don't need it, it will not cause any problems (it will simply do a ``module purge``). + +From here on, ``Lmod`` is ready to load the modulefiles needed by the SRW App. These modulefiles are located in the ``modulefiles`` directory. To load the necessary modulefile for a specific ```` using a given ````, run: + +.. code-block:: console + + module use + module load build__ + +where ```` is the full path to the ``modulefiles`` directory. + +This will work on Level 1 systems, where a modulefile is available in the ``modulefiles`` directory. On Level 2-4 systems (including generic Linux/MacOS systems), users will need to modify certain environment variables, such as the path to HPC-Stack, so that the SRW App can find and load the appropriate modules. For systems with Lmod installed, one of the current ``build__`` modulefiles can be copied and used as a template. To check whether Lmod is installed, run ``echo $LMOD_PKG``, and see if it outputs a path to the Lmod package. On systems without Lmod, users can modify or set the required environment variables with the ``export`` or ``setenv`` commands, depending on whether they are using a bash or csh/tcsh shell, respectively: + +.. code-block:: + + export = + setenv + +Note that building the SRW App without Lmod is not supported at this time. It should be possible to do so, but it has not been tested. Users are encouraged to install Lmod on their system. + +.. _BuildCMake: + +Build the Executables Using CMake +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After setting up the build environment in the preceding section (by loading the ``build__`` modulefile), users need to build the executables required to run the SRW App. In the ``ufs-srweather-app`` directory, create a subdirectory to hold the build's executables: + +.. code-block:: console + + mkdir build + cd build + +From the build directory, run the following commands to build the pre-processing utilities, forecast model, and post-processor: + +.. code-block:: console + + cmake .. -DCMAKE_INSTALL_PREFIX=.. -DCMAKE_INSTALL_BINDIR=exec .. + make -j 4 >& build.out & + +``-DCMAKE_INSTALL_PREFIX`` specifies the location in which the ``exec``, ``include``, ``lib``, and ``share`` directories will be created. These directories will contain various components of the SRW App. Its recommended value ``..`` denotes one directory up from the build directory. In the next line, the ``make`` argument ``-j 4`` indicates that the build will run in parallel with 4 threads. Although users can specify a larger or smaller number of threads (e.g., ``-j 8``, ``-j 2``), it is highly recommended to use at least 4 parallel threads to prevent overly long installation times. + +The build will take a few minutes to complete. When it starts, a random number is printed to the console, and when it is done, a ``[1]+ Done`` message is printed to the console. ``[1]+ Exit`` indicates an error. Output from the build will be in the ``ufs-srweather-app/build/build.out`` file. When the build completes, users should see the forecast model executable ``ufs_model`` and several pre- and post-processing executables in the ``ufs-srweather-app/exec`` directory. These executables are described in :numref:`Table %s `. + +.. hint:: + + If you see the ``build.out`` file, but there is no ``ufs-srweather-app/exec`` directory, wait a few more minutes for the build to complete. + +.. _MacDetails: + +Additional Details for Building on MacOS +------------------------------------------ + +.. note:: + Users who are **not** building the SRW App on a MacOS machine may skip to the :numref:`Section %s ` to finish building the SRW App or continue to :numref:`Chapter %s ` to configure and run an experiment. + +The SRW App can be built on MacOS machines, presuming HPC-Stack has already been installed successfully. The following two options have been tested: + +* **Option 1:** MacBookAir 2020, M1 chip (arm64, running natively), 4+4 cores, Big Sur 11.6.4, GNU compiler suite v.11.2.0_3 (gcc, gfortran, g++); no MPI pre-installed + +* **Option 2:** MacBook Pro 2015, 2.8 GHz Quad-Core Intel Core i7 (x86_64), Catalina OS X 10.15.7, GNU compiler suite v.11.2.0_3 (gcc, gfortran, g++); no MPI pre-installed + +The ``build_macos_gnu`` modulefile initializes the module environment, lists the location of HPC-Stack modules, loads the meta-modules and modules, and sets compilers, additional flags, and environment variables needed for building the SRW App. The modulefile must be modified to include the absolute path to the user's HPC-Stack installation and ``ufs-srweather-app`` directories. In particular, the following section must be modified: + +.. code-block:: console + + # This path should point to your HPCstack installation directory + setenv HPCstack "/Users/username/hpc-stack/install" + + # This path should point to your SRW Application directory + setenv SRW "/Users/username/ufs-srweather-app" + +An excerpt of the ``build_macos_gnu`` contents appears below for Option 1. To use Option 2, the user will need to comment out the lines specific to Option 1 (using a double hyphen) and uncomment the lines specific to Option 2 in the ``build_macos_gnu`` modulefile. Additionally, users need to verify that all file paths reflect their system's configuration and that the correct version numbers for software libraries appear in the modulefile. + +.. code-block:: console + + -- Option 1 compiler paths: + setenv("CC", "/opt/homebrew/bin/gcc") + setenv("FC", "/opt/homebrew/bin/gfortran") + setenv("CXX", "/opt/homebrew/bin/g++") + + -- Option 2 compiler paths: + --[[ + setenv("CC", "/usr/local/bin/gcc") + setenv("FC", "/usr/local/bin/gfortran") + setenv("CXX", "/usr/local/bin/g++") + --]] + +Then, users must source the Lmod setup file, just as they would on other systems, and load the modulefiles needed for building and running the SRW App: + +.. code-block:: console + + source etc/lmod-setup.sh macos + module use + module load build_macos_gnu + export LDFLAGS="-L${MPI_ROOT}/lib" + +In a csh/tcsh shell, users would run ``source etc/lmod-setup.csh macos`` in place of the first line in the code block above. + +Additionally, for Option 1 systems, set the variable ``ENABLE_QUAD_PRECISION`` to ``OFF`` in the ``$SRW/src/ufs-weather-model/FV3/atmos_cubed_sphere/CMakeLists.txt`` file. This change is optional if using Option 2 to build the SRW App. To make this change using a streamline editor (`sed`), run: + +.. code-block:: console + + sed -i .bak 's/QUAD_PRECISION\" ON)/QUAD_PRECISION\" OFF)/' $SRW/src/ufs-weather-model/FV3/atmos_cubed_sphere/CMakeLists.txt + +Proceed to building the executables using the process outlined in :numref:`Step %s `. + +Run an Experiment +===================== + +To configure and run an experiment, users should proceed to :numref:`Chapter %s `. \ No newline at end of file diff --git a/docs/UsersGuide/source/Components.rst b/docs/UsersGuide/source/Components.rst index bafb4ead29..b187db6680 100644 --- a/docs/UsersGuide/source/Components.rst +++ b/docs/UsersGuide/source/Components.rst @@ -72,7 +72,7 @@ A Python script is provided to create basic visualizations of the model output. is designed to output graphics in PNG format for 14 standard meteorological variables when using the pre-defined :term:`CONUS` domain. A difference plotting script is also included to visually compare two runs for the same domain and resolution. These scripts are provided only as an example for users familiar with Python. They may be used to perform a visual check to verify that the application is producing reasonable results. -After running ``manage_externals/checkout_externals``, the visualization scripts will be available in the ``ufs-srweather-app/regional_workflow/ush/Python`` directory. Usage information and instructions are described in :numref:`Chapter %s ` and are also included at the top of the script. +After running ``manage_externals/checkout_externals``, the visualization scripts will be available in the ``ufs-srweather-app/ush/Python`` directory. Usage information and instructions are described in :numref:`Chapter %s ` and are also included at the top of the script. Build System and Workflow ========================= diff --git a/docs/UsersGuide/source/ConfigWorkflow.rst b/docs/UsersGuide/source/ConfigWorkflow.rst index 3c3d4cffac..eb0407e954 100644 --- a/docs/UsersGuide/source/ConfigWorkflow.rst +++ b/docs/UsersGuide/source/ConfigWorkflow.rst @@ -1,18 +1,24 @@ .. _ConfigWorkflow: -============================================================================================ -Workflow Parameters: Configuring the Workflow in ``config.sh`` and ``config_defaults.sh`` -============================================================================================ -To create the experiment directory and workflow when running the SRW Application, the user must create an experiment configuration file named ``config.sh``. This file contains experiment-specific information, such as dates, external model data, observation data, directories, and other relevant settings. To help the user, two sample configuration files have been included in the ``regional_workflow`` repository's ``ush`` directory: ``config.community.sh`` and ``config.nco.sh``. The first is for running experiments in community mode (``RUN_ENVIR`` set to "community"), and the second is for running experiments in "nco" mode (``RUN_ENVIR`` set to "nco"). Note that for this release, only "community" mode is supported. These files can be used as the starting point from which to generate a variety of experiment configurations for the SRW App. +================================================================================================ +Workflow Parameters: Configuring the Workflow in ``config.yaml`` and ``config_defaults.yaml`` +================================================================================================ +To create the experiment directory and workflow when running the SRW Application, the user must create an experiment configuration file (usually named ``config.yaml``). This file contains experiment-specific information, such as forecast dates, grid and physics suite choices, data directories, and other relevant settings. To help the user, two sample configuration files have been included in the ``ush`` directory: ``config.community.yaml`` and ``config.nco.yaml``. The first is for running experiments in *community* mode (``RUN_ENVIR`` set to "community"), and the second is for running experiments in *nco* mode (``RUN_ENVIR`` set to "nco"). The content of these files can be copied into ``config.yaml`` and used as the starting point from which to generate a variety of experiment configurations for the SRW App. Note that for this release, only *community* mode is supported. -There is an extensive list of experiment parameters that a user can set when configuring the experiment. Not all of these need to be explicitly set by the user in ``config.sh``. If a user does not define an entry in the ``config.sh`` script, either its value in ``config_defaults.sh`` will be used, or it will be reset depending on other parameters, such as the platform on which the experiment will be run (specified by ``MACHINE``). Note that ``config_defaults.sh`` contains the full list of experiment parameters that a user may set in ``config.sh`` (i.e., the user cannot set parameters in ``config.sh`` that are not initialized in ``config_defaults.sh``). +There is an extensive list of experiment parameters that a user can set when configuring the experiment. Not all of these parameters need to be set explicitly by the user in ``config.yaml``. If a user does not define a variable in the ``config.yaml`` script, its value in ``config_defaults.yaml`` will be used, or the value will be reset depending on other parameters, such as the platform (``MACHINE``) selected for the experiment. -The following is a list of the parameters in the ``config_defaults.sh`` file. For each parameter, the default value and a brief description is given. +.. note:: + The ``config_defaults.yaml`` file contains the full list of experiment parameters that a user may set in ``config.yaml``. The user cannot set parameters in ``config.yaml`` that are not initialized in ``config_defaults.yaml``. -.. _PlatEnv: +The following is a list of the parameters in the ``config_defaults.yaml`` file. For each parameter, the default value and a brief description is provided. + +.. _user: + +USER Configuration Parameters +================================= + +If non-default parameters are selected for the variables in this section, they should be added to the ``user:`` section of the ``config.yaml`` file. -Platform Environment -==================== ``RUN_ENVIR``: (Default: "nco") This variable determines the workflow mode. The user can choose between two options: "nco" and "community". The "nco" mode uses a directory structure that mimics what is used in operations at NOAA/NCEP Central Operations (NCO) and at the NOAA/NCEP/Environmental Modeling Center (EMC), which works with NCO on pre-implementation testing. Specifics of the conventions used in "nco" mode can be found in the following `WCOSS Implementation Standards `__ document: @@ -21,34 +27,38 @@ Platform Environment | January 19, 2022 | Version 11.0.0 - Setting ``RUN_ENVIR`` to "community" is recommended in most cases for users who are not planning to implement their code into operations at NCO. + Setting ``RUN_ENVIR`` to "community" is recommended in most cases for users who are not planning to implement their code into operations at NCO. Valid values: ``"nco"`` | ``"community"`` ``MACHINE``: (Default: "BIG_COMPUTER") - The machine (a.k.a. platform or system) on which the workflow will run. Currently supported platforms are listed on the `SRW App Wiki page `__. When running the SRW App on any ParellelWorks/NOAA Cloud system, use "NOAACLOUD" regardless of the underlying system (AWS, GCP, or Azure). When running the SRW App in a container, set ``MACHINE`` to "SINGULARITY" regardless of the underlying platform (including on NOAA Cloud systems). Valid values: ``"HERA"`` | ``"ORION"`` | ``"JET"`` | ``"CHEYENNE"`` | ``"GAEA"`` | ``"NOAACLOUD"`` | ``"STAMPEDE"`` | ``"ODIN"`` | ``"MACOS"`` | ``"LINUX"`` | ``"SINGULARITY"`` | ``"WCOSS2"`` + The machine (a.k.a. platform or system) on which the workflow will run. Currently supported platforms are listed on the `SRW App Wiki page `__. When running the SRW App on any ParellelWorks/NOAA Cloud system, use "NOAACLOUD" regardless of the underlying system (AWS, GCP, or Azure). Valid values: ``"HERA"`` | ``"ORION"`` | ``"JET"`` | ``"CHEYENNE"`` | ``"GAEA"`` | ``"NOAACLOUD"`` | ``"STAMPEDE"`` | ``"ODIN"`` | ``"MACOS"`` | ``"LINUX"`` | ``"SINGULARITY"`` | ``"WCOSS2"`` + + .. hint:: + Users who are NOT on a named, supported Level 1 or 2 platform will need to set the ``MACHINE`` variable to ``LINUX`` or ``MACOS``; to combine use of a Linux or MacOS platform with the Rocoto workflow manager, users will also need to set ``WORKFLOW_MANAGER: "rocoto"`` in the ``platform:`` section of ``config.yaml``. This combination will assume a Slurm batch manager when generating the XML. ``MACHINE_FILE``: (Default: "") - Path to a configuration file with machine-specific settings. If none is provided, ``setup.sh`` will attempt to set the path to a configuration file for a supported platform. + Path to a configuration file with machine-specific settings. If none is provided, ``setup.py`` will attempt to set the path to a configuration file for a supported platform. ``ACCOUNT``: (Default: "project_name") The account under which users submit jobs to the queue on the specified ``MACHINE``. To determine an appropriate ``ACCOUNT`` field for `Level 1 `__ systems, users may run the ``groups`` command, which will return a list of projects that the user has permissions for. Not all of the listed projects/groups have an HPC allocation, but those that do are potentially valid account names. On some systems, the ``saccount_params`` command will display additional account details. -``COMPILER``: (Default: "intel") - Type of compiler invoked during the build step. Currently, this must be set manually (i.e., it is not inherited from the build system in the ``ufs-srweather-app`` directory). Valid values: ``"intel"`` | ``"gnu"`` +.. _PlatformConfig: + +PLATFORM Configuration Parameters +===================================== + +If non-default parameters are selected for the variables in this section, they should be added to the ``platform:`` section of the ``config.yaml`` file. ``WORKFLOW_MANAGER``: (Default: "none") - The workflow manager to use (e.g., "ROCOTO"). This is set to "none" by default, but if the machine name is set to a platform that supports Rocoto, this will be overwritten and set to "ROCOTO." Valid values: ``"rocoto"`` | ``"none"`` + The workflow manager to use (e.g., "rocoto"). This is set to "none" by default, but if the machine name is set to a platform that supports Rocoto, this will be overwritten and set to "rocoto." If set explicitly to "rocoto" along with the use of the ``MACHINE: "LINUX"`` target, the configuration layer assumes a Slurm batch manager when generating the XML. Valid values: ``"rocoto"`` | ``"none"`` ``NCORES_PER_NODE``: (Default: "") - The number of cores available per node on the compute platform. Set for supported platforms in ``setup.sh``, but it is now also configurable for all platforms. - -``LMOD_PATH``: (Default: "") - Path to the LMOD shell file on the user's Linux system. It is set automatically for supported machines. + The number of cores available per node on the compute platform. Set for supported platforms in ``setup.py``, but it is now also configurable for all platforms. ``BUILD_MOD_FN``: (Default: "") - Name of alternative build module file to use if running on an unsupported platform. Is set automatically for supported machines. + Name of an alternative build module file to use if running on an unsupported platform. It is set automatically for supported machines. ``WFLOW_MOD_FN``: (Default: "") - Name of alternative workflow module file to use if running on an unsupported platform. Is set automatically for supported machines. + Name of an alternative workflow module file to use if running on an unsupported platform. It is set automatically for supported machines. ``BUILD_VER_FN``: (Default: "") File name containing the version of the modules used for building the app. Currently, WCOSS2 only uses this file. @@ -61,140 +71,180 @@ Platform Environment ``SCHED``: (Default: "") The job scheduler to use (e.g., Slurm) on the specified ``MACHINE``. Leaving this an empty string allows the experiment generation script to set it automatically depending on the machine the workflow is running on. Valid values: ``"slurm"`` | ``"pbspro"`` | ``"lsf"`` | ``"lsfcray"`` | ``"none"`` -Machine-Dependent Parameters: +``SCHED_NATIVE_CMD``: (Default: "") + Allows an extra parameter to be passed to the job scheduler (Slurm or PBSPRO) via XML Native command. + +``DOMAIN_PREGEN_BASEDIR``: (Default: "") + For use in NCO mode only (``RUN_ENVIR: "nco"``). The base directory containing pregenerated grid, orography, and surface climatology files. This is an alternative for setting ``GRID_DIR``, ``OROG_DIR``, and ``SFC_CLIMO_DIR`` individually. For the pregenerated grid specified by ``PREDEF_GRID_NAME``, these "fixed" files are located in: + + .. code-block:: console + + ${DOMAIN_PREGEN_BASEDIR}/${PREDEF_GRID_NAME} + + The workflow scripts will create a symlink in the experiment directory that will point to a subdirectory (having the same name as the experiment grid) under this directory. This variable should be set to a null string in ``config_defaults.yaml``, but it can be changed in the user-specified workflow configuration file set by ``EXPT_CONFIG_FN`` (usually ``config.yaml``). + +``PRE_TASK_CMDS``: (Default: "") + Pre-task commands such as ``ulimit`` needed by tasks. For example: ``'{ ulimit -s unlimited; ulimit -a; }'`` + +Machine-Dependent Parameters ------------------------------- -These parameters vary depending on machine. On `Level 1 and 2 `__ systems, the appropriate values for each machine can be viewed in the ``regional_workflow/ush/machine/.sh`` scripts. To specify a value other than the default, add these variables and the desired value in the ``config.sh`` file so that they override the ``config_defaults.sh`` and machine default values. +These parameters vary depending on machine. On `Level 1 and 2 `__ systems, the appropriate values for each machine can be viewed in the ``ush/machine/.sh`` scripts. To specify a value other than the default, add these variables and the desired value in the ``config.yaml`` file so that they override the ``config_defaults.yaml`` and machine default values. ``PARTITION_DEFAULT``: (Default: "") - This variable is only used with the Slurm job scheduler (i.e., if ``SCHED`` is set to "slurm"). This is the default partition to which Slurm submits workflow tasks. When a variable that designates the partition (e.g., ``PARTITION_HPSS``, ``PARTITION_FCST``; see below) is **not** specified, the task will be submitted to the default partition indicated in the ``PARTITION_DEFAULT`` variable. If this value is not set or is set to an empty string, it will be (re)set to a machine-dependent value. Valid values: ``""`` | ``"hera"`` | ``"normal"`` | ``"orion"`` | ``"sjet,vjet,kjet,xjet"`` | ``"workq"`` - -``CLUSTERS_DEFAULT``: (Default: "") - This variable is only used with the Slurm job scheduler (i.e., if ``SCHED`` is set to "slurm"). These are the default clusters to which Slurm submits workflow tasks. If ``CLUSTERS_HPSS`` or ``CLUSTERS_FCST`` (see below) are not specified, the task will be submitted to the default clusters indicated in this variable. If this value is not set or is set to an empty string, it will be (re)set to a machine-dependent value. + This variable is only used with the Slurm job scheduler (i.e., when ``SCHED: "slurm"``). This is the default partition to which Slurm submits workflow tasks. When a variable that designates the partition (e.g., ``PARTITION_HPSS``, ``PARTITION_FCST``; see below) is **not** specified, the task will be submitted to the default partition indicated in the ``PARTITION_DEFAULT`` variable. If this value is not set or is set to an empty string, it will be (re)set to a machine-dependent value. Options are machine-dependent and include: ``""`` | ``"hera"`` | ``"normal"`` | ``"orion"`` | ``"sjet"`` | ``"vjet"`` | ``"kjet"`` | ``"xjet"`` | ``"workq"`` ``QUEUE_DEFAULT``: (Default: "") - The default queue or QOS to which workflow tasks are submitted (QOS is Slurm's term for queue; it stands for "Quality of Service"). If the task's ``QUEUE_HPSS`` or ``QUEUE_FCST`` parameters (see below) are not specified, the task will be submitted to the queue indicated by this variable. If this value is not set or is set to an empty string, it will be (re)set to a machine-dependent value. Valid values: ``""`` | ``"batch"`` | ``"dev"`` | ``"normal"`` | ``"regular"`` | ``"workq"`` + The default queue or QOS to which workflow tasks are submitted (QOS is Slurm's term for queue; it stands for "Quality of Service"). If the task's ``QUEUE_HPSS`` or ``QUEUE_FCST`` parameters (see below) are not specified, the task will be submitted to the queue indicated by this variable. If this value is not set or is set to an empty string, it will be (re)set to a machine-dependent value. Options are machine-dependent and include: ``""`` | ``"batch"`` | ``"dev"`` | ``"normal"`` | ``"regular"`` | ``"workq"`` ``PARTITION_HPSS``: (Default: "") - This variable is only used with the Slurm job scheduler (i.e., if ``SCHED`` is set to "slurm"). Tasks that get or create links to external model files are submitted to the partition specified in this variable. These links are needed to generate initial conditions (:term:`ICs`) and lateral boundary conditions (:term:`LBCs`) for the experiment. If this variable is not set or is set to an empty string, it will be (re)set to the ``PARTITION_DEFAULT`` value (if set) or to a machine-dependent value. Valid values: ``""`` | ``"normal"`` | ``"service"`` | ``"workq"`` - -``CLUSTERS_HPSS``: (Default: "") - This variable is only used with the Slurm job scheduler (i.e., if ``SCHED`` is set to "slurm"). Tasks that get or create links to external model files are submitted to the clusters specified in this variable. These links are needed to generate initial conditions (ICs) and lateral boundary conditions (LBCs) for the experiment. If this variable is not set or is set to an empty string, it will be (re)set to a machine-dependent value. + This variable is only used with the Slurm job scheduler (i.e., when ``SCHED: "slurm"``). Tasks that get or create links to external model files are submitted to the partition specified in this variable. These links are needed to generate initial conditions (:term:`ICs`) and lateral boundary conditions (:term:`LBCs`) for the experiment. If this variable is not set or is set to an empty string, it will be (re)set to the ``PARTITION_DEFAULT`` value (if set) or to a machine-dependent value. Options are machine-dependent and include: ``""`` | ``"normal"`` | ``"service"`` | ``"workq"`` ``QUEUE_HPSS``: (Default: "") - Tasks that get or create links to external model files are submitted to this queue, or QOS (QOS is Slurm's term for queue; it stands for "Quality of Service"). If this value is not set or is set to an empty string, it will be (re)set to a machine-dependent value. Valid values: ``""`` | ``"batch"`` | ``"dev_transfer"`` | ``"normal"`` | ``"regular"`` | ``"workq"`` + Tasks that get or create links to external model files are submitted to this queue, or QOS (QOS is Slurm's term for queue; it stands for "Quality of Service"). These links are needed to generate initial conditions (:term:`ICs`) and lateral boundary conditions (:term:`LBCs`) for the experiment. If this value is not set or is set to an empty string, it will be (re)set to a machine-dependent value. Options are machine-dependent and include: ``""`` | ``"batch"`` | ``"dev_transfer"`` | ``"normal"`` | ``"regular"`` | ``"workq"`` ``PARTITION_FCST``: (Default: "") - This variable is only used with the Slurm job scheduler (i.e., if ``SCHED`` is set to "slurm"). The task that runs forecasts is submitted to this partition. If this variable is not set or is set to an empty string, it will be (re)set to a machine-dependent value. Valid values: ``""`` | ``"hera"`` | ``"normal"`` | ``"orion"`` | ``"sjet,vjet,kjet,xjet"`` | ``"workq"`` - -``CLUSTERS_FCST``: (Default: "") - This variable is only used with the Slurm job scheduler (i.e., if ``SCHED`` is set to "slurm"). The task that runs forecasts is submitted to this cluster. If this variable is not set or is set to an empty string, it will be (re)set to a machine-dependent value. + This variable is only used with the Slurm job scheduler (i.e., when ``SCHED: "slurm"``). The task that runs forecasts is submitted to this partition. If this variable is not set or is set to an empty string, it will be (re)set to a machine-dependent value. Options are machine-dependent and include: ``""`` | ``"hera"`` | ``"normal"`` | ``"orion"`` | ``"sjet"`` | ``"vjet"`` | ``"kjet"`` | ``"xjet"`` | ``"workq"`` ``QUEUE_FCST``: (Default: "") - The task that runs a forecast is submitted to this queue, or QOS (QOS is Slurm's term for queue; it stands for "Quality of Service"). If this variable is not set or set to an empty string, it will be (re)set to a machine-dependent value. Valid values: ``""`` | ``"batch"`` | ``"dev"`` | ``"normal"`` | ``"regular"`` | ``"workq"`` + The task that runs a forecast is submitted to this queue, or QOS (QOS is Slurm's term for queue; it stands for "Quality of Service"). If this variable is not set or set to an empty string, it will be (re)set to a machine-dependent value. Options are machine-dependent and include: ``""`` | ``"batch"`` | ``"dev"`` | ``"normal"`` | ``"regular"`` | ``"workq"`` Parameters for Running Without a Workflow Manager -================================================= -These settings control run commands for platforms without a workflow manager. Values will be ignored unless ``WORKFLOW_MANAGER="none"``. +----------------------------------------------------- +These settings set run commands for platforms without a workflow manager. Values will be ignored unless ``WORKFLOW_MANAGER: "none"``. ``RUN_CMD_UTILS``: (Default: "mpirun -np 1") The run command for MPI-enabled pre-processing utilities (e.g., shave, orog, sfc_climo_gen). This can be left blank for smaller domains, in which case the executables will run without :term:`MPI`. Users may need to use a different command for launching an MPI-enabled executable depending on their machine and MPI installation. -``RUN_CMD_FCST``: (Default: "mpirun -np \${PE_MEMBER01}") - The run command for the model forecast step. This will be appended to the end of the variable definitions file (``var_defns.sh``). Changing the ``${PE_MEMBER01}`` variable is **not** recommended; it refers to the number of MPI tasks that the Weather Model will expect to run with. Running the Weather Model with a different number of MPI tasks than the workflow has been set up for can lead to segmentation faults and other errors. It is also important to escape the ``$`` character or use single quotes here so that ``PE_MEMBER01`` is not referenced until runtime, since it is not defined at the beginning of the workflow generation script. +``RUN_CMD_FCST``: (Default: "mpirun -np ${PE_MEMBER01}") + The run command for the model forecast step. This will be appended to the end of the variable definitions file (``var_defns.sh``). Changing the ``${PE_MEMBER01}`` variable is **not** recommended; it refers to the number of MPI tasks that the Weather Model will expect to run with. Running the Weather Model with a different number of MPI tasks than the workflow has been set up for can lead to segmentation faults and other errors. ``RUN_CMD_POST``: (Default: "mpirun -np 1") The run command for post-processing (via the :term:`UPP`). Can be left blank for smaller domains, in which case UPP will run without :term:`MPI`. -.. _Cron: -Cron-Associated Parameters -========================== +METplus Parameters +---------------------- -Cron is a job scheduler accessed through the command-line on UNIX-like operating systems. It is useful for automating tasks such as the ``rocotorun`` command, which launches each workflow task in the SRW App. Cron periodically checks a cron table (aka crontab) to see if any tasks are are ready to execute. If so, it runs them. +:ref:`METplus ` is a scientific verification framework that spans a wide range of temporal and spatial scales. Many of the METplus parameters are described below, but additional documentation for the METplus components is available on the `METplus website `__. -``USE_CRON_TO_RELAUNCH``: (Default: "FALSE") - Flag that determines whether or not a line is added to the user's cron table, which calls the experiment launch script every ``CRON_RELAUNCH_INTVL_MNTS`` minutes. +``MODEL``: (Default: "") + A descriptive name of the user's choice for the model being verified. + +``MET_INSTALL_DIR``: (Default: "") + Path to top-level directory of MET installation. -``CRON_RELAUNCH_INTVL_MNTS``: (Default: "03") - The interval (in minutes) between successive calls of the experiment launch script by a cron job to (re)launch the experiment (so that the workflow for the experiment kicks off where it left off). This is used only if ``USE_CRON_TO_RELAUNCH`` is set to "TRUE". +``METPLUS_PATH``: (Default: "") + Path to top-level directory of METplus installation. -.. _DirParams: +``MET_BIN_EXEC``: (Default: "") + Name of subdirectory where METplus executables are installed. -Directory Parameters -==================== -``EXPT_BASEDIR``: (Default: "") - The full path to the base directory inside of which the experiment directory (``EXPT_SUBDIR``) will be created. If this is not specified or if it is set to an empty string, it will default to ``${HOMEdir}/../../expt_dirs``, where ``${HOMEdir}`` contains the full path to the ``regional_workflow`` directory. +.. _METParamNote: -``EXPT_SUBDIR``: (Default: "") - A descriptive name of the user's choice for the experiment directory (*not* its full path). The full path to the experiment directory, which will be contained in the variable ``EXPTDIR``, will be: +.. note:: + Where a date field is required: + * ``YYYY`` refers to the 4-digit valid year + * ``MM`` refers to the 2-digit valid month + * ``DD`` refers to the 2-digit valid day of the month + * ``HH`` refers to the 2-digit valid hour of the day + * ``mm`` refers to the 2-digit valid minutes of the hour + * ``SS`` refers to the two-digit valid seconds of the hour - .. code-block:: console +``CCPA_OBS_DIR``: (Default: "") + User-specified location of top-level directory where CCPA hourly precipitation files used by METplus are located. This parameter needs to be set for both user-provided observations and for observations that are retrieved from the NOAA :term:`HPSS` (if the user has access) via the ``get_obs_ccpa_tn`` task. (This task is activated in the workflow by setting ``RUN_TASK_GET_OBS_CCPA: true``). - EXPTDIR="${EXPT_BASEDIR}/${EXPT_SUBDIR}" + METplus configuration files require the use of a predetermined directory structure and file names. If the CCPA files are user-provided, they need to follow the anticipated naming structure: ``{YYYYMMDD}/ccpa.t{HH}z.01h.hrap.conus.gb2``, where YYYYMMDD and HH are as described in the note :ref:`above `. When pulling observations from NOAA HPSS, the data retrieved will be placed in the ``CCPA_OBS_DIR`` directory. This path must be defind as ``//ccpa/proc``. METplus is configured to verify 01-, 03-, 06-, and 24-h accumulated precipitation using hourly CCPA files. - This parameter cannot be left as a null string. + .. note:: + There is a problem with the valid time in the metadata for files valid from 19 - 00 UTC (i.e., files under the "00" directory). The script to pull the CCPA data from the NOAA HPSS (``scripts/exregional_get_obs_ccpa.sh``) has an example of how to account for this and organize the data into a more intuitive format. When a fix is provided, it will be accounted for in the ``exregional_get_obs_ccpa.sh`` script. -``EXEC_SUBDIR``: (Default: "bin") - The name of the subdirectory of ``ufs-srweather-app`` where executables are installed. +``MRMS_OBS_DIR``: (Default: "") + User-specified location of top-level directory where MRMS composite reflectivity files used by METplus are located. This parameter needs to be set for both user-provided observations and for observations that are retrieved from the NOAA :term:`HPSS` (if the user has access) via the ``get_obs_mrms_tn`` task (activated in the workflow by setting ``RUN_TASK_GET_OBS_MRMS: true``). When pulling observations directly from NOAA HPSS, the data retrieved will be placed in this directory. Please note, this path must be defind as ``//mrms/proc``. + + METplus configuration files require the use of a predetermined directory structure and file names. Therefore, if the MRMS files are user-provided, they need to follow the anticipated naming structure: ``{YYYYMMDD}/MergedReflectivityQCComposite_00.50_{YYYYMMDD}-{HH}{mm}{SS}.grib2``, where YYYYMMDD and {HH}{mm}{SS} are as described in the note :ref:`above `. -.. _NCOModeParms: +.. note:: + METplus is configured to look for a MRMS composite reflectivity file for the valid time of the forecast being verified; since MRMS composite reflectivity files do not always exactly match the valid time, a script (within the main script that retrieves MRMS data from the NOAA HPSS) is used to identify and rename the MRMS composite reflectivity file to match the valid time of the forecast. The script to pull the MRMS data from the NOAA HPSS has an example of the expected file-naming structure: ``scripts/exregional_get_obs_mrms.sh``. This script calls the script used to identify the MRMS file closest to the valid time: ``ush/mrms_pull_topofhour.py``. -NCO Mode Parameters -=================== -These variables apply only when using NCO mode (i.e., when ``RUN_ENVIR`` is set to "nco"). +``NDAS_OBS_DIR``: (Default: "") + User-specified location of the top-level directory where NDAS prepbufr files used by METplus are located. This parameter needs to be set for both user-provided observations and for observations that are retrieved from the NOAA :term:`HPSS` (if the user has access) via the ``get_obs_ndas_tn`` task (activated in the workflow by setting ``RUN_TASK_GET_OBS_NDAS: true``). When pulling observations directly from NOAA HPSS, the data retrieved will be placed in this directory. Please note, this path must be defined as ``//ndas/proc``. METplus is configured to verify near-surface variables hourly and upper-air variables at 00 and 12 UTC with NDAS prepbufr files. + + METplus configuration files require the use of predetermined file names. Therefore, if the NDAS files are user-provided, they need to follow the anticipated naming structure: ``prepbufr.ndas.{YYYYMMDDHH}``, where YYYYMMDDHH is as described in the note :ref:`above `. The script to pull the NDAS data from the NOAA HPSS (``scripts/exregional_get_obs_ndas.sh``) has an example of how to rename the NDAS data into a more intuitive format with the valid time listed in the file name. -``COMINgfs``: (Default: "/base/path/of/directory/containing/gfs/input/files") - The beginning portion of the path to the directory that contains files generated by the external model (FV3GFS). The initial and lateral boundary condition generation tasks need this path in order to create initial and boundary condition files for a given cycle on the native FV3-LAM grid. For a cycle that starts on the date specified by the variable YYYYMMDD (consisting of the 4-digit year, 2-digit month, and 2-digit day of the month) and the hour specified by the variable HH (consisting of the 2-digit hour of the day), the directory in which the workflow will look for the external model files is: +Test Directories +---------------------- - .. code-block:: console +These directories are used only by the ``run_WE2E_tests.sh`` script, so they are not used unless the user runs a Workflow End-to-End (WE2E) test. Their function corresponds to the same variables without the ``TEST_`` prefix. Users typically should not modify these variables. For any alterations, the logic in the ``run_WE2E_tests.sh`` script would need to be adjusted accordingly. - $COMINgfs/gfs.$yyyymmdd/$hh/atmos +``TEST_EXTRN_MDL_SOURCE_BASEDIR``: (Default: "") + This parameter allows testing of user-staged files in a known location on a given platform. This path contains a limited dataset and likely will not be useful for most user experiments. -``FIXLAM_NCO_BASEDIR``: (Default: "") - The base directory containing pregenerated grid, orography, and surface climatology files. For the pregenerated grid type specified in the variable ``PREDEF_GRID_NAME``, these "fixed" files are located in: +``TEST_PREGEN_BASEDIR``: (Default: "") + Similar to ``DOMAIN_PREGEN_BASEDIR``, this variable sets the base directory containing pregenerated grid, orography, and surface climatology files for WE2E tests. This is an alternative for setting ``GRID_DIR``, ``OROG_DIR``, and ``SFC_CLIMO_DIR`` individually. - .. code-block:: console +``TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS``: (Default: "") + This parameter is used to test the mechanism that allows users to point to a data stream on disk. It sets up a sandbox location that mimics the stream in a more controlled way and tests the ability to access :term:`ICS`. - ${FIXLAM_NCO_BASEDIR}/${PREDEF_GRID_NAME} +``TEST_ALT_EXTRN_MDL_SYSBASEDIR_LBCS``: (Default: "") + This parameter is used to test the mechanism that allows users to point to a data stream on disk. It sets up a sandbox location that mimics the stream in a more controlled way and tests the ability to access :term:`LBCS`. - The workflow scripts will create a symlink in the experiment directory that will point to a subdirectory (having the name of the grid being used) under this directory. This variable should be set to a null string in ``config_defaults.sh`` and specified by the user in the workflow configuration file (``config.sh``). -``STMP``: (Default: "/base/path/of/directory/containing/model/input/and/raw/output/files") - The beginning portion of the path to the directory that will contain :term:`cycle-dependent` model input files, symlinks to :term:`cycle-independent` input files, and raw (i.e., before post-processing) forecast output files for a given :term:`cycle`. The format for cycle dates (cdate) is ``cdate="${YYYYMMDD}${HH}"``, where the date is specified using YYYYMMDD format, and the hour is specified using HH format. The files for a cycle date will be located in the following directory: +.. _workflow: - .. code-block:: console +WORKFLOW Configuration Parameters +===================================== - $STMP/tmpnwprd/$RUN/$cdate +If non-default parameters are selected for the variables in this section, they should be added to the ``workflow:`` section of the ``config.yaml`` file. -``NET, envir, RUN``: - Variables used in forming the path to the directory that will contain the post-processor (:term:`UPP`) output files for a given cycle (see ``PTMP`` below). These are defined in the `WCOSS Implementation Standards `__ document (pp. 4-5, 19-20) as follows: +.. _Cron: - ``NET``: (Default: "rrfs") - Model name (first level of ``com`` directory structure) +Cron-Associated Parameters +------------------------------ - ``envir``: (Default: "para") - Set to "test" during the initial testing phase, "para" when running in parallel (on a schedule), and "prod" in production. (Second level of ``com`` directory structure.) +Cron is a job scheduler accessed through the command-line on UNIX-like operating systems. It is useful for automating tasks such as the ``rocotorun`` command, which launches each workflow task in the SRW App. Cron periodically checks a cron table (aka crontab) to see if any tasks are are ready to execute. If so, it runs them. - ``RUN``: (Default: "experiment_name") - Name of model run (third level of ``com`` directory structure). +``USE_CRON_TO_RELAUNCH``: (Default: false) + Flag that determines whether or not a line is added to the user's cron table, which calls the experiment launch script every ``CRON_RELAUNCH_INTVL_MNTS`` minutes. Valid values: ``True`` | ``False`` + +``CRON_RELAUNCH_INTVL_MNTS``: (Default: 3) + The interval (in minutes) between successive calls of the experiment launch script by a cron job to (re)launch the experiment (so that the workflow for the experiment kicks off where it left off). This is used only if ``USE_CRON_TO_RELAUNCH`` is set to true. + +.. _DirParams: + +Directory Parameters +----------------------- + +``EXPT_BASEDIR``: (Default: "") + The full path to the base directory in which the experiment directory (``EXPT_SUBDIR``) will be created. If this is not specified or if it is set to an empty string, it will default to ``${HOMEdir}/../expt_dirs``, where ``${HOMEdir}`` contains the full path to the ``ufs-srweather-app`` directory. + +``EXPT_SUBDIR``: (Default: "") + The user-designated name of the experiment directory (*not* its full path). The full path to the experiment directory, which will be contained in the variable ``EXPTDIR``, will be: -``PTMP``: (Default: "/base/path/of/directory/containing/postprocessed/output/files") - The beginning portion of the path to the directory that will contain the output files from the post-processor (:term:`UPP`) for a given cycle. For a cycle that starts on the date specified by YYYYMMDD and hour specified by HH (where YYYYMMDD and HH are as described above), the UPP output files will be placed in the following directory: - .. code-block:: console - $PTMP/com/$NET/$envir/$RUN.$yyyymmdd/$hh + EXPTDIR="${EXPT_BASEDIR}/${EXPT_SUBDIR}" + + This parameter cannot be left as a null string. It must be set to a non-null value in the user-defined experiment configuration file (i.e., ``config.yaml``). + +``EXEC_SUBDIR``: (Default: "exec") + The name of the subdirectory of ``ufs-srweather-app`` where executables are installed. Pre-Processing File Separator Parameters -======================================== +-------------------------------------------- + ``DOT_OR_USCORE``: (Default: "_") This variable sets the separator character(s) to use in the names of the grid, mosaic, and orography fixed files. Ideally, the same separator should be used in the names of these fixed files as in the surface climatology fixed files. Valid values: ``"_"`` | ``"."`` -File Name Parameters -==================== -``EXPT_CONFIG_FN``: (Default: "config.sh") + +Set File Name Parameters +---------------------------- + +``EXPT_CONFIG_FN``: (Default: "config.yaml") Name of the user-specified configuration file for the forecast experiment. +``CONSTANTS_FN``: (Default: "constants.yaml") + Name of the file containing definitions of various mathematical, physical, and SRW App contants. + ``RGNL_GRID_NML_FN``: (Default: "regional_grid.nml") Name of the file containing namelist settings for the code that generates an "ESGgrid" regional grid. @@ -207,23 +257,23 @@ File Name Parameters ``FV3_NML_BASE_ENS_FN``: (Default: "input.nml.base_ens") Name of the Fortran file containing the forecast model's base ensemble namelist (i.e., the original namelist file from which each of the ensemble members' namelist files is generated). -``DIAG_TABLE_FN``: (Default: "diag_table") - Name of the file specifying the fields that the forecast model will output. +``FV3_EXEC_FN``: (Default: "ufs_model") + Name to use for the forecast model executable. -``FIELD_TABLE_FN``: (Default: "field_table") - Name of the file specifying the :term:`tracers ` that the forecast model will read in from the :term:`IC/LBC ` files. +``DIAG_TABLE_TMPL_FN``: (Default: "") + Name of a template file that specifies the output fields of the forecast model. The selected physics suite is appended to this file name in ``setup.py``, taking the form ``{DIAG_TABLE_TMPL_FN}.{CCPP_PHYS_SUITE}``. Generally, the SRW App expects to read in the default value set in ``setup.py`` (i.e., ``diag_table.{CCPP_PHYS_SUITE}``), and users should **not** specify a value for ``DIAG_TABLE_TMPL_FN`` in their configuration file (i.e., ``config.yaml``) unless (1) the file name required by the model changes, and (2) they also change the names of the ``diag_table`` options in the ``ufs-srweather-app/parm`` directory. -``DATA_TABLE_FN``: (Default: "data_table") - Name of the file containing the data table read in by the forecast model. +``FIELD_TABLE_TMPL_FN``: (Default: "") + Name of a template file that specifies the :term:`tracers ` that the forecast model will read in from the :term:`IC/LBC ` files. The selected physics suite is appended to this file name in ``setup.py``, taking the form ``{FIELD_TABLE_TMPL_FN}.{CCPP_PHYS_SUITE}``. Generally, the SRW App expects to read in the default value set in ``setup.py`` (i.e., ``field_table.{CCPP_PHYS_SUITE}``), and users should **not** specify a different value for ``FIELD_TABLE_TMPL_FN`` in their configuration file (i.e., ``config.yaml``) unless (1) the file name required by the model changes, and (2) they also change the names of the ``field_table`` options in the ``ufs-srweather-app/parm`` directory. -``MODEL_CONFIG_FN``: (Default: "model_configure") - Name of the file containing settings and configurations for the :term:`NUOPC`/:term:`ESMF` component. +``DATA_TABLE_TMPL_FN``: (Default: "") + Name of a template file that contains the data table read in by the forecast model. Generally, the SRW App expects to read in the default value set in ``setup.py`` (i.e., ``data_table``), and users should **not** specify a different value for ``DATA_TABLE_TMPL_FN`` in their configuration file (i.e., ``config.yaml``) unless (1) the file name required by the model changes, and (2) they also change the name of ``data_table`` in the ``ufs-srweather-app/parm`` directory. -``NEMS_CONFIG_FN``: (Default: "nems.configure") - Name of the file containing information about the various :term:`NEMS` components and their run sequence. +``MODEL_CONFIG_TMPL_FN``: (Default: "") + Name of a template file that contains settings and configurations for the :term:`NUOPC`/:term:`ESMF` main component. Generally, the SRW App expects to read in the default value set in ``setup.py`` (i.e., ``model_configure``), and users should **not** specify a different value for ``MODEL_CONFIG_TMPL_FN`` in their configuration file (i.e., ``config.yaml``) unless (1) the file name required by the model changes, and (2) they also change the name of ``model_configure`` in the ``ufs-srweather-app/parm`` directory. -``FV3_EXEC_FN``: (Default: "ufs_model") - Name of the forecast model executable stored in the executables directory (``EXECDIR``; set during experiment generation). +``NEMS_CONFIG_TMPL_FN``: (Default: "") + Name of a template file that contains information about the various :term:`NEMS` components and their run sequence. Generally, the SRW App expects to read in the default value set in ``setup.py`` (i.e., ``nems.configure``), and users should **not** specify a different value for ``NEMS_CONFIG_TMPL_FN`` in their configuration file (i.e., ``config.yaml``) unless (1) the file name required by the model changes, and (2) they also change the name of ``nems.configure`` in the ``ufs-srweather-app/parm`` directory. ``FCST_MODEL``: (Default: "ufs-weather-model") Name of forecast model. Valid values: ``"ufs-weather-model"`` | ``"fv3gfs_aqm"`` @@ -232,13 +282,10 @@ File Name Parameters Name of the Rocoto workflow XML file that the experiment generation script creates. This file defines the workflow for the experiment. ``GLOBAL_VAR_DEFNS_FN``: (Default: "var_defns.sh") - Name of the file (a shell script) containing definitions of the primary and secondary experiment variables (parameters). This file is sourced by many scripts (e.g., the J-job scripts corresponding to each workflow task) in order to make all the experiment variables available in those scripts. The primary variables are defined in the default configuration script (``config_defaults.sh``) and in ``config.sh``. The secondary experiment variables are generated by the experiment generation script. + Name of the file (a shell script) containing definitions of the primary and secondary experiment variables (parameters). This file is sourced by many scripts (e.g., the J-job scripts corresponding to each workflow task) in order to make all the experiment variables available in those scripts. The primary variables are defined in the default configuration script (``config_defaults.yaml``) and in ``config.yaml``. The secondary experiment variables are generated by the experiment generation script. -``EXTRN_MDL_ICS_VAR_DEFNS_FN``: (Default: "extrn_mdl_ics_var_defns.sh") - Name of the file (a shell script) containing the definitions of variables associated with the external model from which :term:`ICs` are generated. This file is created by the ``GET_EXTRN_ICS_TN`` task because the values of the variables it contains are not known before this task runs. The file is then sourced by the ``MAKE_ICS_TN`` task. - -``EXTRN_MDL_LBCS_VAR_DEFNS_FN``: (Default: "extrn_mdl_lbcs_var_defns.sh") - Name of the file (a shell script) containing the definitions of variables associated with the external model from which :term:`LBCs` are generated. This file is created by the ``GET_EXTRN_LBCS_TN`` task because the values of the variables it contains are not known before this task runs. The file is then sourced by the ``MAKE_ICS_TN`` task. +``EXTRN_MDL_VAR_DEFNS_FN``: (Default: "extrn_mdl_var_defns") + Name of the file (a shell script) containing the definitions of variables associated with the external model from which :term:`ICs` or :term:`LBCs` are generated. This file is created by the ``GET_EXTRN_*_TN`` task because the values of the variables it contains are not known before this task runs. The file is then sourced by the ``MAKE_ICS_TN`` and ``MAKE_LBCS_TN`` tasks. ``WFLOW_LAUNCH_SCRIPT_FN``: (Default: "launch_FV3LAM_wflow.sh") Name of the script that can be used to (re)launch the experiment's Rocoto workflow. @@ -246,415 +293,255 @@ File Name Parameters ``WFLOW_LAUNCH_LOG_FN``: (Default: "log.launch_FV3LAM_wflow") Name of the log file that contains the output from successive calls to the workflow launch script (``WFLOW_LAUNCH_SCRIPT_FN``). -Forecast Parameters -=================== -``DATE_FIRST_CYCL``: (Default: "YYYYMMDDHH") - Starting date of the first forecast in the set of forecasts to run. Format is "YYYYMMDDHH". +.. _CCPP_Params: -``DATE_LAST_CYCL``: (Default: "YYYYMMDDHH") - Starting date of the last forecast in the set of forecasts to run. Format is "YYYYMMDDHH". +CCPP Parameter +------------------ -``INCR_CYCL_FREQ``: (Default: "24") - Increment in hours for cycle frequency (cycl_freq). The default is "24", which means cycl_freq=24:00:00. +``CCPP_PHYS_SUITE``: (Default: "FV3_GFS_v16") + This parameter indicates which :term:`CCPP` (Common Community Physics Package) physics suite to use for the forecast(s). The choice of physics suite determines the forecast model's namelist file, the diagnostics table file, the field table file, and the XML physics suite definition file, which are staged in the experiment directory or the :term:`cycle` directories under it. -``FCST_LEN_HRS``: (Default: "24") - The length of each forecast, in integer hours. + .. note:: + For information on *stochastic physics* parameters, see :numref:`Section %s `. + + **Current supported settings for the CCPP parameter are:** -Model Configuration Parameters -================================= + | ``"FV3_GFS_v16"`` + | ``"FV3_RRFS_v1beta"`` + | ``"FV3_HRRR"`` + | ``"FV3_WoFS_v0"`` -``DT_ATMOS``: (Default: "") - Time step for the outermost atmospheric model loop in seconds. This corresponds to the frequency at which the physics routines and the top level dynamics routine are called. (Note that one call to the top-level dynamics routine results in multiple calls to the horizontal dynamics, tracer transport, and vertical dynamics routines; see the `FV3 dycore scientific documentation `__ for details.) Must be set. Takes an integer value. In the SRW App, a default value for ``DT_ATMOS`` appears in the ``set_predef_grid_params.sh`` script, but a different value can be set in ``config.sh``. + **Other valid values include:** -``RESTART_INTERVAL``: (Default: "0") - Frequency of the output restart files in hours. Using the default interval ("0"), restart files are produced at the end of a forecast run. When ``RESTART_INTERVAL="1"``, restart files are produced every hour with the prefix "YYYYMMDD.HHmmSS." in the ``RESTART`` directory. + | ``"FV3_GFS_2017_gfdlmp"`` + | ``"FV3_GFS_2017_gfdlmp_regional"`` + | ``"FV3_GFS_v15p2"`` + | ``"FV3_GFS_v15_thompson_mynn_lam3km"`` -.. _InlinePost: -``WRITE_DOPOST``: (Default: "FALSE") - Flag that determines whether to use the INLINE POST option. If TRUE, the ``WRITE_DOPOST`` flag in the ``model_configure`` file will be set to "TRUE", and the post-processing tasks get called from within the weather model so that the post-processed files (in :term:`grib2` format) are output by the Weather Model at the same time that it outputs the ``dynf###.nc`` and ``phyf###.nc`` files. Setting ``WRITE_DOPOST="TRUE"`` turns off the separate ``run_post`` task (i.e., ``RUN_TASK_RUN_POST`` is set to "FALSE") in ``setup.sh``. +.. _GridGen: -METplus Parameters -===================== +Grid Generation Parameters +------------------------------ -:ref:`METplus ` is a scientific verification framework that spans a wide range of temporal and spatial scales. Many of the METplus parameters are described below, but additional documentation for the METplus components is available on the `METplus website `__. +``GRID_GEN_METHOD``: (Default: "") + This variable specifies which method to use to generate a regional grid in the horizontal plane. The values that it can take on are: -``MODEL``: (Default: "") - A descriptive name of the user's choice for the model being verified. - -``MET_INSTALL_DIR``: (Default: "") - Path to top-level directory of MET installation. + * ``"ESGgrid"``: The "ESGgrid" method will generate a regional version of the Extended Schmidt Gnomonic (ESG) grid using the map projection developed by Jim Purser of EMC (:cite:t:`Purser_2020`). "ESGgrid" is the preferred grid option. -``METPLUS_PATH``: (Default: "") - Path to top-level directory of METplus installation. + * ``"GFDLgrid"``: The "GFDLgrid" method first generates a "parent" global cubed-sphere grid. Then a portion from tile 6 of the global grid is used as the regional grid. This regional grid is referred to in the grid generation scripts as "tile 7," even though it does not correspond to a complete tile. The forecast is run only on the regional grid (i.e., on tile 7, not on tiles 1 through 6). Note that the "GFDLgrid" method is the legacy grid generation method. It is not supported in *all* predefined domains. -``MET_BIN_EXEC``: (Default: "bin") - Location where METplus executables are installed. +.. attention:: -.. _METParamNote: + If the experiment uses a **predefined grid** (i.e., if ``PREDEF_GRID_NAME`` is set to the name of a valid predefined grid), then ``GRID_GEN_METHOD`` will be reset to the value of ``GRID_GEN_METHOD`` for that grid. This will happen regardless of whether ``GRID_GEN_METHOD`` is assigned a value in the experiment configuration file; any value assigned will be overwritten. .. note:: - Where a date field is required: - * ``YYYY`` refers to the 4-digit valid year - * ``MM`` refers to the 2-digit valid month - * ``DD`` refers to the 2-digit valid day of the month - * ``HH`` refers to the 2-digit valid hour of the day - * ``mm`` refers to the 2-digit valid minutes of the hour - * ``SS`` refers to the two-digit valid seconds of the hour -``CCPA_OBS_DIR``: (Default: "") - User-specified location of top-level directory where CCPA hourly precipitation files used by METplus are located. This parameter needs to be set for both user-provided observations and for observations that are retrieved from the NOAA :term:`HPSS` (if the user has access) via the ``get_obs_ccpa_tn`` task. (This task is activated in the workflow by setting ``RUN_TASK_GET_OBS_CCPA="TRUE"``). + If the experiment uses a **user-defined grid** (i.e., if ``PREDEF_GRID_NAME`` is set to a null string), then ``GRID_GEN_METHOD`` must be set in the experiment configuration file. Otherwise, the experiment generation will fail because the generation scripts check to ensure that the grid name is set to a non-empty string before creating the experiment directory. - METplus configuration files require the use of a predetermined directory structure and file names. If the CCPA files are user-provided, they need to follow the anticipated naming structure: ``{YYYYMMDD}/ccpa.t{HH}z.01h.hrap.conus.gb2``, where YYYYMMDD and HH are as described in the note :ref:`above `. When pulling observations from NOAA HPSS, the data retrieved will be placed in the ``CCPA_OBS_DIR`` directory. This path must be defind as ``//ccpa/proc``. METplus is configured to verify 01-, 03-, 06-, and 24-h accumulated precipitation using hourly CCPA files. +Forecast Parameters +---------------------- +``DATE_FIRST_CYCL``: (Default: "YYYYMMDDHH") + Starting date of the first forecast in the set of forecasts to run. Format is "YYYYMMDDHH". - .. note:: - There is a problem with the valid time in the metadata for files valid from 19 - 00 UTC (i.e., files under the "00" directory). The script to pull the CCPA data from the NOAA HPSS (``regional_workflow/scripts/exregional_get_ccpa_files.sh``) has an example of how to account for this and organize the data into a more intuitive format. When a fix is provided, it will be accounted for in the ``exregional_get_ccpa_files.sh`` script. +``DATE_LAST_CYCL``: (Default: "YYYYMMDDHH") + Starting date of the last forecast in the set of forecasts to run. Format is "YYYYMMDDHH". -``MRMS_OBS_DIR``: (Default: "") - User-specified location of top-level directory where MRMS composite reflectivity files used by METplus are located. This parameter needs to be set for both user-provided observations and for observations that are retrieved from the NOAA :term:`HPSS` (if the user has access) via the ``get_obs_mrms_tn`` task (activated in the workflow by setting ``RUN_TASK_GET_OBS_MRMS="TRUE"``). When pulling observations directly from NOAA HPSS, the data retrieved will be placed in this directory. Please note, this path must be defind as ``//mrms/proc``. - - METplus configuration files require the use of a predetermined directory structure and file names. Therefore, if the MRMS files are user-provided, they need to follow the anticipated naming structure: ``{YYYYMMDD}/MergedReflectivityQCComposite_00.50_{YYYYMMDD}-{HH}{mm}{SS}.grib2``, where YYYYMMDD and {HH}{mm}{SS} are as described in the note :ref:`above `. +``INCR_CYCL_FREQ``: (Default: 24) + Increment in hours for Rocoto cycle frequency. The default is 24, which means cycl_freq=24:00:00. -.. note:: - METplus is configured to look for a MRMS composite reflectivity file for the valid time of the forecast being verified; since MRMS composite reflectivity files do not always exactly match the valid time, a script (within the main script that retrieves MRMS data from the NOAA HPSS) is used to identify and rename the MRMS composite reflectivity file to match the valid time of the forecast. The script to pull the MRMS data from the NOAA HPSS has an example of the expected file-naming structure: ``regional_workflow/scripts/exregional_get_mrms_files.sh``. This script calls the script used to identify the MRMS file closest to the valid time: ``regional_workflow/ush/mrms_pull_topofhour.py``. +``FCST_LEN_HRS``: (Default: 24) + The length of each forecast, in integer hours. +Pre-Existing Directory Parameter +------------------------------------ +``PREEXISTING_DIR_METHOD``: (Default: "delete") + This variable determines how to deal with pre-existing directories (resulting from previous calls to the experiment generation script using the same experiment name [``EXPT_SUBDIR``] as the current experiment). This variable must be set to one of three valid values: ``"delete"``, ``"rename"``, or ``"quit"``. The behavior for each of these values is as follows: -``NDAS_OBS_DIR``: (Default: "") - User-specified location of top-level directory where NDAS prepbufr files used by METplus are located. This parameter needs to be set for both user-provided observations and for observations that are retrieved from the NOAA :term:`HPSS` (if the user has access) via the ``get_obs_ndas_tn`` task (activated in the workflow by setting ``RUN_TASK_GET_OBS_NDAS="TRUE"``). When pulling observations directly from NOAA HPSS, the data retrieved will be placed in this directory. Please note, this path must be defined as ``//ndas/proc``. METplus is configured to verify near-surface variables hourly and upper-air variables at 00 and 12 UTC with NDAS prepbufr files. - - METplus configuration files require the use of predetermined file names. Therefore, if the NDAS files are user-provided, they need to follow the anticipated naming structure: ``prepbufr.ndas.{YYYYMMDDHH}``, where YYYYMMDD and HH are as described in the note :ref:`above `. The script to pull the NDAS data from the NOAA HPSS (``regional_workflow/scripts/exregional_get_ndas_files.sh``) has an example of how to rename the NDAS data into a more intuitive format with the valid time listed in the file name. + * **"delete":** The preexisting directory is deleted and a new directory (having the same name as the original preexisting directory) is created. -Initial and Lateral Boundary Condition Generation Parameters -============================================================ -``EXTRN_MDL_NAME_ICS``: (Default: "FV3GFS") - The name of the external model that will provide fields from which initial condition (IC) files, surface files, and 0-th hour boundary condition files will be generated for input into the forecast model. Valid values: ``"GSMGFS"`` | ``"FV3GFS"`` | ``"RAP"`` | ``"HRRR"`` | ``"NAM"`` + * **"rename":** The preexisting directory is renamed and a new directory (having the same name as the original pre-existing directory) is created. The new name of the preexisting directory consists of its original name and the suffix "_old###", where ``###`` is a 3-digit integer chosen to make the new name unique. -``EXTRN_MDL_NAME_LBCS``: (Default: "FV3GFS") - The name of the external model that will provide fields from which lateral boundary condition (LBC) files (except for the 0-th hour LBC file) will be generated for input into the forecast model. Valid values: ``"GSMGFS"`` | ``"FV3GFS"`` | ``"RAP"`` | ``"HRRR"`` | ``"NAM"`` + * **"quit":** The preexisting directory is left unchanged, but execution of the currently running script is terminated. In this case, the preexisting directory must be dealt with manually before rerunning the script. -``LBC_SPEC_INTVL_HRS``: (Default: "6") - The interval (in integer hours) at which LBC files will be generated. This is also referred to as the *boundary specification interval*. Note that the model selected in ``EXTRN_MDL_NAME_LBCS`` must have data available at a frequency greater than or equal to that implied by ``LBC_SPEC_INTVL_HRS``. For example, if ``LBC_SPEC_INTVL_HRS`` is set to "6", then the model must have data available at least every 6 hours. It is up to the user to ensure that this is the case. +Verbose Parameter +--------------------- +``VERBOSE``: (Default: true) + Flag that determines whether the experiment generation and workflow task scripts print out extra informational messages. Valid values: ``True`` | ``False`` -``EXTRN_MDL_ICS_OFFSET_HRS``: (Default: "0") - Users may wish to start a forecast using forecast data from a previous cycle of an external model. This variable indicates how many hours earlier the external model started than the FV3 forecast configured here. For example, if the forecast should start from a 6-hour forecast of the GFS, then ``EXTRN_MDL_ICS_OFFSET_HRS="6"``. +Debug Parameter +-------------------- +``DEBUG``: (Default: false) + Flag that determines whether to print out very detailed debugging messages. Note that if DEBUG is set to true, then VERBOSE will also be reset to true if it isn't already. Valid values: ``True`` | ``False`` -``EXTRN_MDL_LBCS_OFFSET_HRS``: (Default: "") - Users may wish to use lateral boundary conditions from a forecast that was started earlier than the start of the forecast configured here. This variable indicates how many hours earlier the external model started than the FV3 forecast configured here. For example, if the forecast should use lateral boundary conditions from the GFS started 6 hours earlier, then ``EXTRN_MDL_LBCS_OFFSET_HRS="6"``. Note: the default value is model-dependent and is set in ``set_extrn_mdl_params.sh``. +Compiler +----------- -``FV3GFS_FILE_FMT_ICS``: (Default: "nemsio") - If using the FV3GFS model as the source of the :term:`ICs` (i.e., if ``EXTRN_MDL_NAME_ICS="FV3GFS"``), this variable specifies the format of the model files to use when generating the ICs. Valid values: ``"nemsio"`` | ``"grib2"`` | ``"netcdf"`` +``COMPILER``: (Default: "intel") + Type of compiler invoked during the build step. Currently, this must be set manually; it is not inherited from the build system in the ``ufs-srweather-app`` directory. Valid values: ``"intel"`` | ``"gnu"`` -``FV3GFS_FILE_FMT_LBCS``: (Default: "nemsio") - If using the FV3GFS model as the source of the :term:`LBCs` (i.e., if ``EXTRN_MDL_NAME_ICS="FV3GFS"``), this variable specifies the format of the model files to use when generating the LBCs. Valid values: ``"nemsio"`` | ``"grib2"`` | ``"netcdf"`` +Verification Parameters +--------------------------- +``GET_OBS``: (Default: "get_obs") + Set the name of the Rocoto workflow task used to load proper module files for ``GET_OBS_*`` tasks. Users typically do not need to change this value. +``VX_TN``: (Default: "run_vx") + Set the name of the Rocoto workflow task used to load proper module files for ``VX_*`` tasks. Users typically do not need to change this value. -Base Directories for External Model Files -=========================================== +``VX_ENSGRID_TN``: (Default: "run_ensgridvx") + Set the name of the Rocoto workflow task that runs METplus grid-to-grid ensemble verification for 1-h accumulated precipitation. Users typically do not need to change this value. -.. note:: - These variables must be defined as null strings in ``config_defaults.sh`` so that if they are specified by the user in the experiment configuration file (``config.sh``), they remain set to those values, and if not, they get set to machine-dependent values. +``VX_ENSGRID_PROB_REFC_TN``: (Default: "run_ensgridvx_prob_refc") + Set the name of the Rocoto workflow task that runs METplus grid-to-grid verification for ensemble probabilities for composite reflectivity. Users typically do not need to change this value. -``EXTRN_MDL_SYSBASEDIR_ICS``: (Default: "") - Base directory on the local machine containing external model files for generating :term:`ICs` on the native grid. The way the full path containing these files is constructed depends on the user-specified external model for ICs (defined in ``EXTRN_MDL_NAME_ICS`` above). +``MAXTRIES_VX_ENSGRID_PROB_REFC``: (Default: 1) + Maximum number of times to attempt ``VX_ENSGRID_PROB_REFC_TN``. -``EXTRN_MDL_SYSBASEDIR_LBCS``: (Default: "") - Base directory on the local machine containing external model files for generating :term:`LBCs` on the native grid. The way the full path containing these files is constructed depends on the user-specified external model for LBCs (defined in ``EXTRN_MDL_NAME_LBCS`` above). +.. _NCOModeParms: -User-Staged External Model Directory and File Parameters -======================================================== -``USE_USER_STAGED_EXTRN_FILES``: (Default: "FALSE") - Flag that determines whether the workflow will look for the external model files needed for generating :term:`ICs` and :term:`LBCs` in user-specified directories (rather than fetching them from mass storage like NOAA :term:`HPSS`). +NCO-Specific Variables +========================= -``EXTRN_MDL_SOURCE_BASEDIR_ICS``: (Default: "/base/dir/containing/user/staged/extrn/mdl/files/for/ICs") - Directory containing external model files for generating ICs. If ``USE_USER_STAGED_EXTRN_FILES`` is set to "TRUE", the workflow looks within this directory for a subdirectory named "YYYYMMDDHH", which contains the external model files specified by the array ``EXTRN_MDL_FILES_ICS``. This "YYYYMMDDHH" subdirectory corresponds to the start date and cycle hour of the forecast (see :ref:`above `). These files will be used to generate the :term:`ICs` on the native FV3-LAM grid. This variable is not used if ``USE_USER_STAGED_EXTRN_FILES`` is set to "FALSE". - -``EXTRN_MDL_FILES_ICS``: (Default: "ICS_file1" "ICS_file2" "...") - Array containing the file names to search for in the ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` directory. This variable is not used if ``USE_USER_STAGED_EXTRN_FILES`` is set to "FALSE". +A standard set of environment variables has been established for *nco* mode to simplify the production workflow and improve the troubleshooting process for operational and preoperational models. These variables are only used in *nco* mode (i.e., when ``RUN_ENVIR: "nco"``). When non-default parameters are selected for the variables in this section, they should be added to the ``nco:`` section of the ``config.yaml`` file. -``EXTRN_MDL_SOURCE_BASEDIR_LBCS``: (Default: "/base/dir/containing/user/staged/extrn/mdl/files/for/ICs") - Analogous to ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` but for :term:`LBCs` instead of :term:`ICs`. - Directory containing external model files for generating LBCs. If ``USE_USER_STAGED_EXTRN_FILES`` is set to "TRUE", the workflow looks within this directory for a subdirectory named "YYYYMMDDHH", which contains the external model files specified by the array ``EXTRN_MDL_FILES_LBCS``. This "YYYYMMDDHH" subdirectory corresponds to the start date and cycle hour of the forecast (see :ref:`above `). These files will be used to generate the :term:`LBCs` on the native FV3-LAM grid. This variable is not used if ``USE_USER_STAGED_EXTRN_FILES`` is set to "FALSE". +.. note:: + Only *community* mode is fully supported for this release. *nco* mode is used by those at the Environmental Modeling Center (EMC) and Global Systems Laboratory (GSL) who are working on pre-implementation operational testing. Other users should run the SRW App in *community* mode. -``EXTRN_MDL_FILES_LBCS``: (Default: " "LBCS_file1" "LBCS_file2" "...") - Analogous to ``EXTRN_MDL_FILES_ICS`` but for :term:`LBCs` instead of :term:`ICs`. Array containing the file names to search for in the ``EXTRN_MDL_SOURCE_BASEDIR_LBCS`` directory. This variable is not used if ``USE_USER_STAGED_EXTRN_FILES`` is set to "FALSE". +``envir, NET, model_ver, RUN``: + Standard environment variables defined in the NCEP Central Operations WCOSS Implementation Standards document. These variables are used in forming the path to various directories containing input, output, and workflow files. The variables are defined in the `WCOSS Implementation Standards `__ document (pp. 4-5) as follows: + ``envir``: (Default: "para") + Set to "test" during the initial testing phase, "para" when running in parallel (on a schedule), and "prod" in production. -NOMADS Parameters -====================== + ``NET``: (Default: "rrfs") + Model name (first level of ``com`` directory structure) -Set parameters associated with NOMADS online data. + ``model_ver``: (Default: "v1.0.0") + Version number of package in three digits (second level of ``com`` directory) -``NOMADS``: (Default: "FALSE") - Flag controlling whether to use NOMADS online data. + ``RUN``: (Default: "rrfs") + Name of model run (third level of ``com`` directory structure). In general, same as ``$NET``. -``NOMADS_file_type``: (Default: "nemsio") - Flag controlling the format of the data. Valid values: ``"GRIB2"`` | ``"grib2"`` | ``"NEMSIO"`` | ``"nemsio"`` +``OPSROOT``: (Default: "") + The operations root directory in *nco* mode. -.. _CCPP_Params: +WORKFLOW SWITCHES Configuration Parameters +============================================= -CCPP Parameter -=============== -``CCPP_PHYS_SUITE``: (Default: "FV3_GFS_v16") - This parameter indicates which :term:`CCPP` (Common Community Physics Package) physics suite to use for the forecast(s). The choice of physics suite determines the forecast model's namelist file, the diagnostics table file, the field table file, and the XML physics suite definition file, which are staged in the experiment directory or the :term:`cycle` directories under it. - - **Current supported settings for this parameter are:** +These parameters set flags that determine whether various workflow tasks should be run. When non-default parameters are selected for the variables in this section, they should be added to the ``workflow_switches:`` section of the ``config.yaml`` file. Note that the ``MAKE_GRID_TN``, ``MAKE_OROG_TN``, and ``MAKE_SFC_CLIMO_TN`` are all :term:`cycle-independent` tasks, i.e., if they are run, they only run once at the beginning of the workflow before any cycles are run. - | ``"FV3_GFS_v16"`` - | ``"FV3_RRFS_v1beta"`` - | ``"FV3_HRRR"`` - | ``"FV3_WoFS_v0"`` +Baseline Workflow Tasks +-------------------------- - **Other valid values include:** +``RUN_TASK_MAKE_GRID``: (Default: true) + Flag that determines whether to run the grid file generation task (``MAKE_GRID_TN``). If this is set to true, the grid generation task is run and new grid files are generated. If it is set to false, then the scripts look for pre-generated grid files in the directory specified by ``GRID_DIR`` (see :numref:`Section %s ` below). Valid values: ``True`` | ``False`` - | ``"FV3_GFS_2017_gfdlmp"`` - | ``"FV3_GFS_2017_gfdlmp_regional"`` - | ``"FV3_GFS_v15p2"`` - | ``"FV3_GFS_v15_thompson_mynn_lam3km"`` +``RUN_TASK_MAKE_OROG``: (Default: true) + Same as ``RUN_TASK_MAKE_GRID`` but for the orography generation task (``MAKE_OROG_TN``). Flag that determines whether to run the orography file generation task (``MAKE_OROG_TN``). If this is set to true, the orography generation task is run and new orography files are generated. If it is set to false, then the scripts look for pre-generated orography files in the directory specified by ``OROG_DIR`` (see :numref:`Section %s ` below). Valid values: ``True`` | ``False`` -Stochastic Physics Parameters -================================ +``RUN_TASK_MAKE_SFC_CLIMO``: (Default: true) + Same as ``RUN_TASK_MAKE_GRID`` but for the surface climatology generation task (``MAKE_SFC_CLIMO_TN``). Flag that determines whether to run the surface climatology file generation task (``MAKE_SFC_CLIMO_TN``). If this is set to true, the surface climatology generation task is run and new surface climatology files are generated. If it is set to false, then the scripts look for pre-generated surface climatology files in the directory specified by ``SFC_CLIMO_DIR`` (see :numref:`Section %s ` below). Valid values: ``True`` | ``False`` -For the most updated and detailed documentation of these parameters, see the `UFS Stochastic Physics Documentation `__. +``RUN_TASK_GET_EXTRN_ICS``: (Default: true) + Flag that determines whether to run the ``GET_EXTRN_ICS_TN`` task. -``NEW_LSCALE``: (Default: "TRUE") - Use correct formula for converting a spatial legnth scale into spectral space. +``RUN_TASK_GET_EXTRN_LBCS``: (Default: true) + Flag that determines whether to run the ``GET_EXTRN_LBCS_TN`` task. -Specific Humidity (SHUM) Perturbation Parameters ---------------------------------------------------- +``RUN_TASK_MAKE_ICS``: (Default: true) + Flag that determines whether to run the ``MAKE_ICS_TN`` task. -``DO_SHUM``: (Default: "FALSE") - Flag to turn Specific Humidity (SHUM) perturbations on or off. SHUM perturbations multiply the low-level specific humidity by a small random number at each time-step. The SHUM scheme attempts to address missing physics phenomena (e.g., cold pools, gust fronts) most active in convective regions. +``RUN_TASK_MAKE_LBCS``: (Default: true) + Flag that determines whether to run the ``MAKE_LBCS_TN`` task. -``ISEED_SHUM``: (Default: "2") - Seed for setting the SHUM random number sequence. +``RUN_TASK_RUN_FCST``: (Default: true) + Flag that determines whether to run the ``RUN_FCST_TN`` task. -``SHUM_MAG``: (Default: "0.006") - Amplitudes of random patterns. Corresponds to the variable ``shum`` in ``input.nml``. +``RUN_TASK_RUN_POST``: (Default: true) + Flag that determines whether to run the ``RUN_POST_TN`` task. Valid values: ``True`` | ``False`` -``SHUM_LSCALE``: (Default: "150000") - Decorrelation spatial scale in meters. +.. _VXTasks: -``SHUM_TSCALE``: (Default: "21600") - Decorrelation timescale in seconds. Corresponds to the variable ``shum_tau`` in ``input.nml``. +Verification Tasks +-------------------- -``SHUM_INT``: (Default: "3600") - Interval in seconds to update random pattern (optional). Perturbations still get applied at every time-step. Corresponds to the variable ``shumint`` in ``input.nml``. +``RUN_TASK_GET_OBS_CCPA``: (Default: false) + Flag that determines whether to run the ``GET_OBS_CCPA_TN`` task, which retrieves the :term:`CCPA` hourly precipitation files used by METplus from NOAA :term:`HPSS`. See :numref:`Section %s ` for additional parameters related to this task. -.. _SPPT: +``RUN_TASK_GET_OBS_MRMS``: (Default: false) + Flag that determines whether to run the ``GET_OBS_MRMS_TN`` task, which retrieves the :term:`MRMS` composite reflectivity files used by METplus from NOAA HPSS. See :numref:`Section %s ` for additional parameters related to this task. -Stochastically Perturbed Physics Tendencies (SPPT) Parameters ------------------------------------------------------------------ +``RUN_TASK_GET_OBS_NDAS``: (Default: false) + Flag that determines whether to run the ``GET_OBS_NDAS_TN`` task, which retrieves the :term:`NDAS` PrepBufr files used by METplus from NOAA HPSS. See :numref:`Section %s ` for additional parameters related to this task. -SPPT perturbs full physics tendencies *after* the call to the physics suite, unlike :ref:`SPP ` (below), which perturbs specific tuning parameters within a physics scheme. +``RUN_TASK_VX_GRIDSTAT``: (Default: false) + Flag that determines whether to run the grid-stat verification task. The :ref:`MET Grid-Stat tool ` provides verification statistics for a matched forecast and observation grid. See :numref:`Section %s ` for additional parameters related to this task. Valid values: ``True`` | ``False`` -``DO_SPPT``: (Default: "FALSE") - Flag to turn Stochastically Perturbed Physics Tendencies (SPPT) on or off. SPPT multiplies the physics tendencies by a random number between 0 and 2 before updating the model state. This addresses error in the physics parameterizations (either missing physics or unresolved subgrid processes). It is most active in the boundary layer and convective regions. +``RUN_TASK_VX_POINTSTAT``: (Default: false) + Flag that determines whether to run the point-stat verification task. The :ref:`MET Point-Stat tool ` provides verification statistics for forecasts at observation points (as opposed to over gridded analyses). See :numref:`Section %s ` for additional parameters related to this task. Valid values: ``True`` | ``False`` -``ISEED_SPPT``: (Default: "1") - Seed for setting the SPPT random number sequence. +``RUN_TASK_VX_ENSGRID``: (Default: false) + Flag that determines whether to run the ensemble-stat verification for gridded data task. The :ref:`MET Ensemble-Stat tool ` provides verification statistics for ensemble forecasts and can be used in conjunction with the :ref:`MET Grid-Stat tool `. See :numref:`Section %s ` for additional parameters related to this task. Valid values: ``True`` | ``False`` -``SPPT_MAG``: (Default: "0.7") - Amplitude of random patterns. Corresponds to the variable ``sppt`` in ``input.nml``. +``RUN_TASK_VX_ENSPOINT``: (Default: false) + Flag that determines whether to run the ensemble point verification task. If this flag is set, both ensemble-stat point verification and point verification of ensemble-stat output is computed. The :ref:`MET Ensemble-Stat tool ` provides verification statistics for ensemble forecasts and can be used in conjunction with the :ref:`MET Point-Stat tool `. See :numref:`Section %s ` for additional parameters related to this task. Valid values: ``True`` | ``False`` -``SPPT_LOGIT``: (Default: "TRUE") - Limits the SPPT perturbations to between 0 and 2. Should be "TRUE"; otherwise the model will crash. +.. + COMMENT: Might be worth defining "ensemble-stat verification for gridded data," "ensemble point verification," "ensemble-stat point verification," and "point verification of ensemble-stat output" -``SPPT_LSCALE``: (Default: "150000") - Decorrelation spatial scale in meters. +.. _make-grid: -``SPPT_TSCALE``: (Default: "21600") - Decorrelation timescale in seconds. Corresponds to the variable ``sppt_tau`` in ``input.nml``. - -``SPPT_INT``: (Default: "3600") - Interval in seconds to update random pattern (optional parameter). Perturbations still get applied at every time-step. Corresponds to the variable ``spptint`` in ``input.nml``. +MAKE_GRID Configuration Parameters +====================================== -``SPPT_SFCLIMIT``: (Default: "TRUE") - When "TRUE", tapers the SPPT perturbations to zero at the model's lowest level, which reduces model crashes. +Non-default parameters for the ``make_grid`` task are set in the ``task_make_grid:`` section of the ``config.yaml`` file. -``USE_ZMTNBLCK``: (Default: "FALSE") - When "TRUE", do not apply perturbations below the dividing streamline that is diagnosed by the gravity wave drag, mountain blocking scheme +Basic Task Parameters +-------------------------- -Stochastic Kinetic Energy Backscatter (SKEB) Parameters ----------------------------------------------------------- +For each workflow task, certain parameter values must be passed to the job scheduler (e.g., Slurm), which submits a job for the task. Typically, users do not need to adjust the default values. -``DO_SKEB``: (Default: "FALSE") - Flag to turn Stochastic Kinetic Energy Backscatter (SKEB) on or off. SKEB adds wind perturbations to the model state. Perturbations are random in space/time, but amplitude is determined by a smoothed dissipation estimate provided by the :term:`dynamical core`. SKEB addresses errors in the dynamics more active in the mid-latitudes. + ``MAKE_GRID_TN``: (Default: "make_grid") + Set the name of this :term:`cycle-independent` Rocoto workflow task. Users typically do not need to change this value. -``ISEED_SKEB``: (Default: "3") - Seed for setting the SHUM random number sequence. + ``NNODES_MAKE_GRID``: (Default: 1) + Number of nodes to use for the job. -``SKEB_MAG``: (Default: "0.5") - Amplitude of random patterns. Corresponds to the variable ``skeb`` in ``input.nml``. + ``PPN_MAKE_GRID``: (Default: 24) + Number of :term:`MPI` processes per node. -``SKEB_LSCALE``: (Default: "150000") - Decorrelation spatial scale in meters. + ``WTIME_MAKE_GRID``: (Default: 00:20:00) + Maximum time for the task to complete. -``SKEB_TSCALE``: (Default: "21600") - Decorrelation timescale in seconds. Corresponds to the variable ``skeb_tau`` in ``input.nml``. + ``MAXTRIES_MAKE_GRID``: (Default: 2) + Maximum number of times to attempt the task. -``SKEB_INT``: (Default: "3600") - Interval in seconds to update random pattern (optional). Perturbations still get applied every time-step. Corresponds to the variable ``skebint`` in ``input.nml``. + ``GRID_DIR``: (Default: "") + The directory containing pre-generated grid files when ``RUN_TASK_MAKE_GRID`` is set to false. -``SKEBNORM``: (Default: "1") - Patterns: - * 0-random pattern is stream function - * 1-pattern is K.E. norm - * 2-pattern is vorticity +.. _ESGgrid: -``SKEB_VDOF``: (Default: "10") - The number of degrees of freedom in the vertical direction for the SKEB random pattern. +ESGgrid Settings +------------------- -.. _SPP: +The following parameters must be set if using the "ESGgrid" method to generate a regional grid (i.e., when ``GRID_GEN_METHOD: "ESGgrid"``, see :numref:`Section %s `). If a different ``GRID_GEN_METHOD`` is used, these parameters will be ignored. When using a predefined grid with ``GRID_GEN_METHOD: "ESGgrid"``, the values in this section will be set automatically to the assigned values for that grid. -Parameters for Stochastically Perturbed Parameterizations (SPP) ------------------------------------------------------------------- +``ESGgrid_LON_CTR``: (Default: "") + The longitude of the center of the grid (in degrees). -SPP perturbs specific tuning parameters within a physics :term:`parameterization ` (unlike :ref:`SPPT `, which multiplies overall physics tendencies by a random perturbation field *after* the call to the physics suite). Each SPP option is an array, applicable (in order) to the :term:`RAP`/:term:`HRRR`-based parameterization listed in ``SPP_VAR_LIST``. Enter each value of the array in ``config.sh`` as shown below without commas or single quotes (e.g., ``SPP_VAR_LIST=( "pbl" "sfc" "mp" "rad" "gwd"`` ). Both commas and single quotes will be added by Jinja when creating the namelist. +``ESGgrid_LAT_CTR``: (Default: "") + The latitude of the center of the grid (in degrees). -.. note:: - SPP is currently only available for specific physics schemes used in the RAP/HRRR physics suite. Users need to be aware of which :term:`SDF` is chosen when turning this option on. Among the supported physics suites, the full set of parameterizations can only be used with the ``FV3_HRRR`` option for ``CCPP_PHYS_SUITE``. +``ESGgrid_DELX``: (Default: "") + The cell size in the zonal direction of the regional grid (in meters). -``DO_SPP``: (Default: "false") - Flag to turn SPP on or off. SPP perturbs parameters or variables with unknown or uncertain magnitudes within the physics code based on ranges provided by physics experts. +``ESGgrid_DELY``: (Default: "") + The cell size in the meridional direction of the regional grid (in meters). -``ISEED_SPP``: (Default: ( "4" "4" "4" "4" "4" ) ) - Seed for setting the random number sequence for the perturbation pattern. - -``SPP_MAG_LIST``: (Default: ( "0.2" "0.2" "0.75" "0.2" "0.2" ) ) - SPP perturbation magnitudes used in each parameterization. Corresponds to the variable ``spp_prt_list`` in ``input.nml`` - -``SPP_LSCALE``: (Default: ( "150000.0" "150000.0" "150000.0" "150000.0" "150000.0" ) ) - Decorrelation spatial scales in meters. - -``SPP_TSCALE``: (Default: ( "21600.0" "21600.0" "21600.0" "21600.0" "21600.0" ) ) - Decorrelation timescales in seconds. Corresponds to the variable ``spp_tau`` in ``input.nml``. - -``SPP_SIGTOP1``: (Default: ( "0.1" "0.1" "0.1" "0.1" "0.1") ) - Controls vertical tapering of perturbations at the tropopause and corresponds to the lower sigma level at which to taper perturbations to zero. - -``SPP_SIGTOP2``: (Default: ( "0.025" "0.025" "0.025" "0.025" "0.025" ) ) - Controls vertical tapering of perturbations at the tropopause and corresponds to the upper sigma level at which to taper perturbations to zero. - -``SPP_STDDEV_CUTOFF``: (Default: ( "1.5" "1.5" "2.5" "1.5" "1.5" ) ) - Limit for possible perturbation values in standard deviations from the mean. - -``SPP_VAR_LIST``: (Default: ( "pbl" "sfc" "mp" "rad" "gwd" ) ) - The list of parameterizations to perturb: planetary boundary layer (PBL), surface physics (SFC), microphysics (MP), radiation (RAD), gravity wave drag (GWD). Valid values: ``"pbl"`` | ``"sfc"`` | ``"rad"`` | ``"gwd"`` | ``"mp"`` - - -Land Surface Model (LSM) SPP -------------------------------- - -Land surface perturbations can be applied to land model parameters and land model prognostic variables. The LSM scheme is intended to address errors in the land model and land-atmosphere interactions. LSM perturbations include soil moisture content (SMC) (volume fraction), vegetation fraction (VGF), albedo (ALB), salinity (SAL), emissivity (EMI), surface roughness (ZOL) (in cm), and soil temperature (STC). Perturbations to soil moisture content (SMC) are only applied at the first time step. Only five perturbations at a time can be applied currently, but all seven are shown below. In addition, only one unique *iseed* value is allowed at the moment, and it is used for each pattern. - -The parameters below turn on SPP in Noah or RUC LSM (support for Noah MP is in progress). Please be aware of the :term:`SDF` that you choose if you wish to turn on Land Surface Model (LSM) SPP. SPP in LSM schemes is handled in the ``&nam_sfcperts`` namelist block instead of in ``&nam_sppperts``, where all other SPP is implemented. The default perturbation frequency is determined by the ``fhcyc`` namelist entry. Since that parameter is set to zero in the SRW App, use ``LSM_SPP_EACH_STEP`` to perturb every time step. - -``DO_LSM_SPP``: (Default: "false") - Turns on Land Surface Model (LSM) Stochastic Physics Parameterizations (SPP). When "TRUE", sets ``lndp_type=2``, which applies land perturbations to the selected paramaters using a newer scheme designed for data assimilation (DA) ensemble spread. LSM SPP perturbs uncertain land surface fields ("smc" "vgf" "alb" "sal" "emi" "zol" "stc") based on recommendations from physics experts. - -``LSM_SPP_TSCALE``: (Default: ( ( "21600" "21600" "21600" "21600" "21600" "21600" "21600" ) ) ) - Decorrelation timescales in seconds. - -``LSM_SPP_LSCALE``: (Default: ( ( "150000" "150000" "150000" "150000" "150000" "150000" "150000" ) ) ) - Decorrelation spatial scales in meters. - -``ISEED_LSM_SPP``: (Default: ("9") ) - Seed to initialize the random perturbation pattern. - -``LSM_SPP_VAR_LIST``: (Default: ( ( "smc" "vgf" "alb" "sal" "emi" "zol" "stc" ) ) ) - Indicates which LSM variables to perturb. - -``LSM_SPP_MAG_LIST``: (Default: ( ( "0.2" "0.001" "0.001" "0.001" "0.001" "0.001" "0.2" ) ) ) - Sets the maximum random pattern amplitude for each of the LSM perturbations. - -``LSM_SPP_EACH_STEP``: (Default: "true") - When set to "TRUE", it sets ``lndp_each_step=.true.`` and perturbs each time step. - -.. _PredefGrid: - -Predefined Grid Parameters -========================== -``PREDEF_GRID_NAME``: (Default: "") - This parameter indicates which (if any) predefined regional grid to use for the experiment. Setting ``PREDEF_GRID_NAME`` provides a convenient method of specifying a commonly used set of grid-dependent parameters. The predefined grid settings can be viewed in the script ``ush/set_predef_grid_params.sh``. - - **Currently supported options:** - - | ``"RRFS_CONUS_25km"`` - | ``"RRFS_CONUS_13km"`` - | ``"RRFS_CONUS_3km"`` - | ``"SUBCONUS_Ind_3km"`` - - **Other valid values include:** - - | ``"CONUS_25km_GFDLgrid"`` - | ``"CONUS_3km_GFDLgrid"`` - | ``"EMC_AK"`` - | ``"EMC_HI"`` - | ``"EMC_PR"`` - | ``"EMC_GU"`` - | ``"GSL_HAFSV0.A_25km"`` - | ``"GSL_HAFSV0.A_13km"`` - | ``"GSL_HAFSV0.A_3km"`` - | ``"GSD_HRRR_AK_50km"`` - | ``"RRFS_AK_13km"`` - | ``"RRFS_AK_3km"`` - | ``"RRFS_CONUScompact_25km"`` - | ``"RRFS_CONUScompact_13km"`` - | ``"RRFS_CONUScompact_3km"`` - | ``"RRFS_NA_13km"`` - | ``"RRFS_NA_3km"`` - | ``"RRFS_SUBCONUS_3km"`` - | ``"WoFS_3km"`` - -.. note:: - - * If ``PREDEF_GRID_NAME`` is set to a valid predefined grid name, the grid generation method, the (native) grid parameters, and the write component grid parameters are set to predefined values for the specified grid, overwriting any settings of these parameters in the user-specified experiment configuration file (``config.sh``). In addition, if the time step ``DT_ATMOS`` and the computational parameters (``LAYOUT_X``, ``LAYOUT_Y``, and ``BLOCKSIZE``) are not specified in that configuration file, they are also set to predefined values for the specified grid. - - * If ``PREDEF_GRID_NAME`` is set to an empty string, it implies that the user will provide the native grid parameters in the user-specified experiment configuration file (``config.sh``). In this case, the grid generation method, the native grid parameters, the write component grid parameters, the main time step (``DT_ATMOS``), and the computational parameters (``LAYOUT_X``, ``LAYOUT_Y``, and ``BLOCKSIZE``) must be set in the configuration file. Otherwise, the values of the parameters in the default experiment configuration file (``config_defaults.sh``) will be used. - - -.. _ConfigParameters: - -Grid Generation Parameters -========================== -``GRID_GEN_METHOD``: (Default: "") - This variable specifies which method to use to generate a regional grid in the horizontal plane. The values that it can take on are: - - * **"ESGgrid":** The "ESGgrid" method will generate a regional version of the Extended Schmidt Gnomonic (ESG) grid using the map projection developed by Jim Purser of EMC (:cite:t:`Purser_2020`). "ESGgrid" is the preferred grid option. - - * **"GFDLgrid":** The "GFDLgrid" method first generates a "parent" global cubed-sphere grid. Then a portion from tile 6 of the global grid is used as the regional grid. This regional grid is referred to in the grid generation scripts as "tile 7," even though it does not correspond to a complete tile. The forecast is run only on the regional grid (i.e., on tile 7, not on tiles 1 through 6). Note that the "GFDLgrid" method is the legacy grid generation method. It is not supported in *all* predefined domains. - -.. attention:: - - If the experiment uses a **predefined grid** (i.e., if ``PREDEF_GRID_NAME`` is set to the name of a valid predefined grid), then ``GRID_GEN_METHOD`` will be reset to the value of ``GRID_GEN_METHOD`` for that grid. This will happen regardless of whether ``GRID_GEN_METHOD`` is assigned a value in the experiment configuration file; any value assigned will be overwritten. - -.. note:: - - If the experiment uses a **user-defined grid** (i.e., if ``PREDEF_GRID_NAME`` is set to a null string), then ``GRID_GEN_METHOD`` must be set in the experiment configuration file. Otherwise, the experiment generation will fail because the generation scripts check to ensure that the grid name is set to a non-empty string before creating the experiment directory. - -.. _ESGgrid: - -ESGgrid Settings -------------------- - -The following parameters must be set if using the "ESGgrid" method to generate a regional grid (i.e., when ``GRID_GEN_METHOD="ESGgrid"``). - -``ESGgrid_LON_CTR``: (Default: "") - The longitude of the center of the grid (in degrees). - -``ESGgrid_LAT_CTR``: (Default: "") - The latitude of the center of the grid (in degrees). - -``ESGgrid_DELX``: (Default: "") - The cell size in the zonal direction of the regional grid (in meters). - -``ESGgrid_DELY``: (Default: "") - The cell size in the meridional direction of the regional grid (in meters). - -``ESGgrid_NX``: (Default: "") - The number of cells in the zonal direction on the regional grid. +``ESGgrid_NX``: (Default: "") + The number of cells in the zonal direction on the regional grid. ``ESGgrid_NY``: (Default: "") The number of cells in the meridional direction on the regional grid. @@ -663,7 +550,7 @@ The following parameters must be set if using the "ESGgrid" method to generate a The rotational parameter for the "ESGgrid" (in degrees). ``ESGgrid_WIDE_HALO_WIDTH``: (Default: "") - The width (in number of grid cells) of the :term:`halo` to add around the regional grid before shaving the halo down to the width(s) expected by the forecast model. + The width (in number of grid cells) of the :term:`halo` to add around the regional grid before shaving the halo down to the width(s) expected by the forecast model. The user need not specify this variable since it is set automatically in ``set_gridparams_ESGgrid.py`` .. _WideHalo: @@ -673,7 +560,9 @@ The following parameters must be set if using the "ESGgrid" method to generate a GFDLgrid Settings --------------------- -The following parameters must be set if using the "GFDLgrid" method to generate a regional grid (i.e., when ``GRID_GEN_METHOD="GFDLgrid"``). Note that the regional grid is defined with respect to a "parent" global cubed-sphere grid. Thus, all the parameters for a global cubed-sphere grid must be specified even though the model equations are integrated only on the regional grid. Tile 6 has arbitrarily been chosen as the tile to use to orient the global parent grid on the sphere (Earth). For convenience, the regional grid is denoted as "tile 7" even though it is embedded within tile 6 (i.e., it doesn't extend beyond the boundary of tile 6). Its exact location within tile 6 is determined by specifying the starting and ending i- and j-indices of the regional grid on tile 6, where ``i`` is the grid index in the x direction and ``j`` is the grid index in the y direction. All of this information is set in the variables below. +The following parameters must be set if using the "GFDLgrid" method to generate a regional grid (i.e., when ``GRID_GEN_METHOD: "GFDLgrid"``, see :numref:`Section %s `). If a different ``GRID_GEN_METHOD`` is used, these parameters will be ignored. When using a predefined grid with ``GRID_GEN_METHOD: "GFDLgrid"``, the values in this section will be set automatically to the assigned values for that grid. + +Note that the regional grid is defined with respect to a "parent" global cubed-sphere grid. Thus, all the parameters for a global cubed-sphere grid must be specified even though the model equations are integrated only on the regional grid. Tile 6 has arbitrarily been chosen as the tile to use to orient the global parent grid on the sphere (Earth). For convenience, the regional grid is denoted as "tile 7" even though it is embedded within tile 6 (i.e., it doesn't extend beyond the boundary of tile 6). Its exact location within tile 6 is determined by specifying the starting and ending i- and j-indices of the regional grid on tile 6, where ``i`` is the grid index in the x direction and ``j`` is the grid index in the y direction. All of this information is set in the variables below. ``GFDLgrid_LON_T6_CTR``: (Default: "") Longitude of the center of tile 6 (in degrees). @@ -682,30 +571,29 @@ The following parameters must be set if using the "GFDLgrid" method to generate Latitude of the center of tile 6 (in degrees). ``GFDLgrid_NUM_CELLS``: (Default: "") - Number of grid cells in either of the two horizontal directions (x and y) on each of the six tiles of the parent global cubed-sphere grid. Valid values: ``"48"`` | ``"96"`` | ``"192"`` | ``"384"`` | ``"768"`` | ``"1152"`` | ``"3072"`` + Number of grid cells in either of the two horizontal directions (x and y) on each of the six tiles of the parent global cubed-sphere grid. Valid values: ``48`` | ``96`` | ``192`` | ``384`` | ``768`` | ``1152`` | ``3072`` - To give an idea of what these values translate to in terms of grid cell size in kilometers, we list below the approximate grid cell size on a uniform global grid having the specified value of ``GFDLgrid_NUM_CELLS``, where by "uniform" we mean with Schmidt stretch factor ``GFDLgrid_STRETCH_FAC="1"`` (although in regional applications ``GFDLgrid_STRETCH_FAC`` will typically be set to a value greater than ``"1"`` to obtain a smaller grid size on tile 6): + To give an idea of what these values translate to in terms of grid cell size in kilometers, we list below the approximate grid cell size on a uniform global grid having the specified value of ``GFDLgrid_NUM_CELLS``, where by "uniform" we mean with Schmidt stretch factor ``GFDLgrid_STRETCH_FAC: "1"`` (although in regional applications ``GFDLgrid_STRETCH_FAC`` will typically be set to a value greater than ``"1"`` to obtain a smaller grid size on tile 6): +---------------------+--------------------+ - | GFDLgrid_NUM_CELLS | typical cell size | + | GFDLgrid_NUM_CELLS | Typical Cell Size | +=====================+====================+ - | 48 | 208 km | + | 48 | 200 km | +---------------------+--------------------+ - | 96 | 104 km | + | 96 | 100 km | +---------------------+--------------------+ - | 192 | 52 km | + | 192 | 50 km | +---------------------+--------------------+ - | 384 | 26 km | + | 384 | 25 km | +---------------------+--------------------+ | 768 | 13 km | +---------------------+--------------------+ - | 1152 | 8.7 km | + | 1152 | 8.5 km | +---------------------+--------------------+ - | 3072 | 3.3 km | + | 3072 | 3.2 km | +---------------------+--------------------+ - Note that these are only typical cell sizes. The actual cell size on the global grid tiles varies somewhat as we move across a tile (and is dependent on ``GFDLgrid_STRETCH_FAC``). - + Note that these are only typical cell sizes. The actual cell size on the global grid tiles varies somewhat as we move across a tile and is also dependent on ``GFDLgrid_STRETCH_FAC``, which modifies the shape and size of the tile. ``GFDLgrid_STRETCH_FAC``: (Default: "") Stretching factor used in the Schmidt transformation applied to the parent cubed-sphere grid. Setting the Schmidt stretching factor to a value greater than 1 shrinks tile 6, while setting it to a value less than 1 (but still greater than 0) expands it. The remaining 5 tiles change shape as necessary to maintain global coverage of the grid. @@ -726,624 +614,1313 @@ The following parameters must be set if using the "GFDLgrid" method to generate j-index on tile 6 at which the regional grid (tile 7) ends. ``GFDLgrid_USE_NUM_CELLS_IN_FILENAMES``: (Default: "") - Flag that determines the file naming convention to use for grid, orography, and surface climatology files (or, if using pregenerated files, the naming convention that was used to name these files). These files usually start with the string ``"C${RES}_"``, where ``RES`` is an integer. In the global forecast model, ``RES`` is the number of points in each of the two horizontal directions (x and y) on each tile of the global grid (defined here as ``GFDLgrid_NUM_CELLS``). If this flag is set to "TRUE", ``RES`` will be set to ``GFDLgrid_NUM_CELLS`` just as in the global forecast model. If it is set to "FALSE", we calculate (in the grid generation task) an "equivalent global uniform cubed-sphere resolution" -- call it ``RES_EQUIV`` -- and then set ``RES`` equal to it. ``RES_EQUIV`` is the number of grid points in each of the x and y directions on each tile that a global UNIFORM (i.e., stretch factor of 1) cubed-sphere grid would need to have in order to have the same average grid size as the regional grid. This is a more useful indicator of the grid size because it takes into account the effects of ``GFDLgrid_NUM_CELLS``, ``GFDLgrid_STRETCH_FAC``, and ``GFDLgrid_REFINE_RATIO`` in determining the regional grid's typical grid size, whereas simply setting ``RES`` to ``GFDLgrid_NUM_CELLS`` doesn't take into account the effects of ``GFDLgrid_STRETCH_FAC`` and ``GFDLgrid_REFINE_RATIO`` on the regional grid's resolution. Nevertheless, some users still prefer to use ``GFDLgrid_NUM_CELLS`` in the file names, so we allow for that here by setting this flag to "TRUE". + Flag that determines the file naming convention to use for grid, orography, and surface climatology files (or, if using pregenerated files, the naming convention that was used to name these files). These files usually start with the string ``"C${RES}_"``, where ``RES`` is an integer. In the global forecast model, ``RES`` is the number of points in each of the two horizontal directions (x and y) on each tile of the global grid (defined here as ``GFDLgrid_NUM_CELLS``). If this flag is set to true, ``RES`` will be set to ``GFDLgrid_NUM_CELLS`` just as in the global forecast model. If it is set to false, we calculate (in the grid generation task) an "equivalent global uniform cubed-sphere resolution" --- call it ``RES_EQUIV`` --- and then set ``RES`` equal to it. ``RES_EQUIV`` is the number of grid points in each of the x and y directions on each tile that a global UNIFORM (i.e., stretch factor of 1) cubed-sphere grid would need to have in order to have the same average grid size as the regional grid. This is a more useful indicator of the grid size because it takes into account the effects of ``GFDLgrid_NUM_CELLS``, ``GFDLgrid_STRETCH_FAC``, and ``GFDLgrid_REFINE_RATIO`` in determining the regional grid's typical grid size, whereas simply setting ``RES`` to ``GFDLgrid_NUM_CELLS`` doesn't take into account the effects of ``GFDLgrid_STRETCH_FAC`` and ``GFDLgrid_REFINE_RATIO`` on the regional grid's resolution. Nevertheless, some users still prefer to use ``GFDLgrid_NUM_CELLS`` in the file names, so we allow for that here by setting this flag to true. -Computational Forecast Parameters -================================= +.. _make-orog: + +MAKE_OROG Configuration Parameters +===================================== -``LAYOUT_X, LAYOUT_Y``: (Default: "") - The number of :term:`MPI` tasks (processes) to use in the two horizontal directions (x and y) of the regional grid when running the forecast model. +Non-default parameters for the ``make_orog`` task are set in the ``task_make_orog:`` section of the ``config.yaml`` file. -``BLOCKSIZE``: (Default: "") - The amount of data that is passed into the cache at a time. +``MAKE_OROG_TN``: (Default: "make_orog") + Set the name of this :term:`cycle-independent` Rocoto workflow task. Users typically do not need to change this value. -.. note:: +``NNODES_MAKE_OROG``: (Default: 1) + Number of nodes to use for the job. - In ``config_defaults.sh`` these parameters are set to null strings so that: +``PPN_MAKE_OROG``: (Default: 24) + Number of :term:`MPI` processes per node. - #. If the experiment is using a predefined grid and the user sets the ``BLOCKSIZE`` parameter in the user-specified experiment configuration file (i.e., ``config.sh``), that value will be used in the forecast(s). Otherwise, the default ``BLOCKSIZE`` for that predefined grid will be used. - #. If the experiment is *not* using a predefined grid (i.e., it is using a custom grid whose parameters are specified in the experiment configuration file), then the user must specify a value for the ``BLOCKSIZE`` parameter in that configuration file. Otherwise, it will remain set to a null string, and the experiment generation will fail, because the generation scripts check to ensure that all the parameters defined in this section are set to non-empty strings before creating the experiment directory. +``WTIME_MAKE_OROG``: (Default: 00:20:00) + Maximum time for the task to complete. -.. _WriteComp: +``MAXTRIES_MAKE_OROG``: (Default: 2) + Maximum number of times to attempt the task. -Write-Component (Quilting) Parameters -====================================== +``KMP_AFFINITY_MAKE_OROG``: (Default: "disabled") + Intel Thread Affinity Interface for the ``make_orog`` task. See :ref:`this note ` for more information on thread affinity. Settings for the ``make_orog`` task is disabled because this task does not use parallelized code. -.. note:: - The :term:`UPP` (called by the ``RUN_POST_TN`` task) cannot process output on the native grid types ("GFDLgrid" and "ESGgrid"), so output fields are interpolated to a **write-component grid** before writing them to an output file. The output files written by the UFS Weather Model use an Earth System Modeling Framework (:term:`ESMF`) component, referred to as the **write component**. This model component is configured with settings in the ``model_configure`` file, as described in `Section 4.2.3 `__ of the UFS Weather Model documentation. +``OMP_NUM_THREADS_MAKE_OROG``: (Default: 6) + The number of OpenMP threads to use for parallel regions. -``QUILTING``: (Default: "TRUE") +``OMP_STACKSIZE_MAKE_OROG``: (Default: "2048m") + Controls the size of the stack for threads created by the OpenMP implementation. - .. attention:: - The regional grid requires the use of the write component, so users generally should not need to change the default value for ``QUILTING``. +``OROG_DIR``: (Default: "") + The directory containing pre-generated orography files to use when ``MAKE_OROG_TN`` is set to false. - Flag that determines whether to use the write component for writing forecast output files to disk. If set to "TRUE", the forecast model will output files named ``dynf$HHH.nc`` and ``phyf$HHH.nc`` (where ``HHH`` is the 3-digit forecast hour) containing dynamics and physics fields, respectively, on the write-component grid. For example, the output files for the 3rd hour of the forecast would be ``dynf$003.nc`` and ``phyf$003.nc``. (The regridding from the native FV3-LAM grid to the write-component grid is done by the forecast model.) If ``QUILTING`` is set to "FALSE", then the output file names are ``fv3_history.nc`` and ``fv3_history2d.nc``, and they contain fields on the native grid. Although the UFS Weather Model can run without quilting, the regional grid requires the use of the write component. Therefore, QUILTING should be set to "TRUE" when running the SRW App. If ``QUILTING`` is set to "FALSE", the ``RUN_POST_TN`` (meta)task cannot run because the :term:`UPP` code that this task calls cannot process fields on the native grid. In that case, the ``RUN_POST_TN`` (meta)task will be automatically removed from the Rocoto workflow XML. The :ref:`INLINE POST ` option also requires ``QUILTING`` to be set to "TRUE" in the SRW App. +.. _make-sfc-climo: -``PRINT_ESMF``: (Default: "FALSE") - Flag that determines whether to output extra (debugging) information from :term:`ESMF` routines. Must be "TRUE" or "FALSE". Note that the write component uses ESMF library routines to interpolate from the native forecast model grid to the user-specified output grid (which is defined in the model configuration file ``model_configure`` in the forecast run directory). +MAKE_SFC_CLIMO Configuration Parameters +=========================================== -``WRTCMP_write_groups``: (Default: "1") - The number of write groups (i.e., groups of :term:`MPI` tasks) to use in the write component. +Non-default parameters for the ``make_sfc_climo`` task are set in the ``task_make_sfc_climo:`` section of the ``config.yaml`` file. -``WRTCMP_write_tasks_per_group``: (Default: "20") - The number of MPI tasks to allocate for each write group. +``MAKE_SFC_CLIMO_TN``: "make_sfc_climo" + Set the name of this :term:`cycle-independent` Rocoto workflow task. Users typically do not need to change this value. -``WRTCMP_output_grid``: (Default: "''") - Sets the type (coordinate system) of the write component grid. The default empty string forces the user to set a valid value for ``WRTCMP_output_grid`` in ``config.sh`` if specifying a *custom* grid. When creating an experiment with a user-defined grid, this parameter must be specified or the experiment will fail. Valid values: ``"lambert_conformal"`` | ``"regional_latlon"`` | ``"rotated_latlon"`` +``NNODES_MAKE_SFC_CLIMO``: (Default: 2) + Number of nodes to use for the job. -``WRTCMP_cen_lon``: (Default: "") - Longitude (in degrees) of the center of the write component grid. Can usually be set to the corresponding value from the native grid. +``PPN_MAKE_SFC_CLIMO``: (Default: 24) + Number of :term:`MPI` processes per node. -``WRTCMP_cen_lat``: (Default: "") - Latitude (in degrees) of the center of the write component grid. Can usually be set to the corresponding value from the native grid. +``WTIME_MAKE_SFC_CLIMO``: (Default: 00:20:00) + Maximum time for the task to complete. -``WRTCMP_lon_lwr_left``: (Default: "") - Longitude (in degrees) of the center of the lower-left (southwest) cell on the write component grid. If using the "rotated_latlon" coordinate system, this is expressed in terms of the rotated longitude. Must be set manually when running an experiment with a user-defined grid. +``MAXTRIES_MAKE_SFC_CLIMO``: (Default: 2) + Maximum number of times to attempt the task. -``WRTCMP_lat_lwr_left``: (Default: "") - Latitude (in degrees) of the center of the lower-left (southwest) cell on the write component grid. If using the "rotated_latlon" coordinate system, this is expressed in terms of the rotated latitude. Must be set manually when running an experiment with a user-defined grid. +``KMP_AFFINITY_MAKE_SFC_CLIMO``: (Default: "scatter") + Intel Thread Affinity Interface for the ``make_sfc_climo`` task. See :ref:`this note ` for more information on thread affinity. -**The following parameters must be set when** ``WRTCMP_output_grid`` **is set to "rotated_latlon":** +``OMP_NUM_THREADS_MAKE_SFC_CLIMO``: (Default: 1) + The number of OpenMP threads to use for parallel regions. -``WRTCMP_lon_upr_rght``: (Default: "") - Longitude (in degrees) of the center of the upper-right (northeast) cell on the write component grid (expressed in terms of the rotated longitude). +``OMP_STACKSIZE_MAKE_SFC_CLIMO``: (Default: "1024m") + Controls the size of the stack for threads created by the OpenMP implementation. -``WRTCMP_lat_upr_rght``: (Default: "") - Latitude (in degrees) of the center of the upper-right (northeast) cell on the write component grid (expressed in terms of the rotated latitude). +``SFC_CLIMO_DIR``: (Default: "") + The directory containing pre-generated surface climatology files to use when ``MAKE_SFC_CLIMO_TN`` is set to false. -``WRTCMP_dlon``: (Default: "") - Size (in degrees) of a grid cell on the write component grid (expressed in terms of the rotated longitude). +GET_EXTRN_ICS Configuration Parameters +========================================= -``WRTCMP_dlat``: (Default: "") - Size (in degrees) of a grid cell on the write component grid (expressed in terms of the rotated latitude). +Non-default parameters for the ``get_extrn_ics`` task are set in the ``task_get_extrn_ics:`` section of the ``config.yaml`` file. -**The following parameters must be set when** ``WRTCMP_output_grid`` **is set to "lambert_conformal":** +.. _basic-get-extrn-ics: -``WRTCMP_stdlat1``: (Default: "") - First standard latitude (in degrees) in definition of Lambert conformal projection. +Basic Task Parameters +--------------------------------- -``WRTCMP_stdlat2``: (Default: "") - Second standard latitude (in degrees) in definition of Lambert conformal projection. +For each workflow task, certain parameter values must be passed to the job scheduler (e.g., Slurm), which submits a job for the task. -``WRTCMP_nx``: (Default: "") - Number of grid points in the x-coordinate of the Lambert conformal projection. +``GET_EXTRN_ICS_TN``: (Default: "get_extrn_ics") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. -``WRTCMP_ny``: (Default: "") - Number of grid points in the y-coordinate of the Lambert conformal projection. +``NNODES_GET_EXTRN_ICS``: (Default: 1) + Number of nodes to use for the job. -``WRTCMP_dx``: (Default: "") - Grid cell size (in meters) along the x-axis of the Lambert conformal projection. +``PPN_GET_EXTRN_ICS``: (Default: 1) + Number of :term:`MPI` processes per node. -``WRTCMP_dy``: (Default: "") - Grid cell size (in meters) along the y-axis of the Lambert conformal projection. +``WTIME_GET_EXTRN_ICS``: (Default: 00:45:00) + Maximum time for the task to complete. -Pre-existing Directory Parameter -================================ -``PREEXISTING_DIR_METHOD``: (Default: "delete") - This variable determines how to deal with pre-existing directories (resulting from previous calls to the experiment generation script using the same experiment name [``EXPT_SUBDIR``] as the current experiment). This variable must be set to one of three valid values: ``"delete"``, ``"rename"``, or ``"quit"``. The behavior for each of these values is as follows: +``MAXTRIES_GET_EXTRN_ICS``: (Default: 1) + Maximum number of times to attempt the task. - * **"delete":** The preexisting directory is deleted and a new directory (having the same name as the original preexisting directory) is created. +``EXTRN_MDL_NAME_ICS``: (Default: "FV3GFS") + The name of the external model that will provide fields from which initial condition (IC) files, surface files, and 0-th hour boundary condition files will be generated for input into the forecast model. Valid values: ``"GSMGFS"`` | ``"FV3GFS"`` | ``"RAP"`` | ``"HRRR"`` | ``"NAM"`` - * **"rename":** The preexisting directory is renamed and a new directory (having the same name as the original pre-existing directory) is created. The new name of the preexisting directory consists of its original name and the suffix "_old###", where ``###`` is a 3-digit integer chosen to make the new name unique. +``EXTRN_MDL_ICS_OFFSET_HRS``: (Default: 0) + Users may wish to start a forecast using forecast data from a previous cycle of an external model. This variable indicates how many hours earlier the external model started than the FV3 forecast configured here. For example, if the forecast should start from a 6-hour forecast of the GFS, then ``EXTRN_MDL_ICS_OFFSET_HRS: "6"``. - * **"quit":** The preexisting directory is left unchanged, but execution of the currently running script is terminated. In this case, the preexisting directory must be dealt with manually before rerunning the script. +``FV3GFS_FILE_FMT_ICS``: (Default: "nemsio") + If using the FV3GFS model as the source of the :term:`ICs` (i.e., if ``EXTRN_MDL_NAME_ICS: "FV3GFS"``), this variable specifies the format of the model files to use when generating the ICs. Valid values: ``"nemsio"`` | ``"grib2"`` | ``"netcdf"`` +File and Directory Parameters +-------------------------------- -Verbose Parameter -================= -``VERBOSE``: (Default: "TRUE") - Flag that determines whether the experiment generation and workflow task scripts print out extra informational messages. Valid values: ``"TRUE"`` | ``"true"`` | ``"YES"`` | ``"yes"`` | ``"FALSE"`` | ``"false"`` | ``"NO"`` | ``"no"`` +``USE_USER_STAGED_EXTRN_FILES``: (Default: false) + Flag that determines whether the workflow will look for the external model files needed for generating :term:`ICs` in user-specified directories (rather than fetching them from mass storage like NOAA :term:`HPSS`). Valid values: ``True`` | ``False`` -Debug Parameter -================= -``DEBUG``: (Default: "FALSE") - Flag that determines whether to print out very detailed debugging messages. Note that if DEBUG is set to TRUE, then VERBOSE will also be reset to TRUE if it isn't already. Valid values: ``"TRUE"`` | ``"true"`` | ``"YES"`` | ``"yes"`` | ``"FALSE"`` | ``"false"`` | ``"NO"`` | ``"no"`` - -.. _WFTasks: - -Rocoto Workflow Tasks -======================== - -Set the names of the various Rocoto workflow tasks. These names usually do not need to be changed. - -**Baseline Tasks:** - -| ``MAKE_GRID_TN``: (Default: "make_grid") -| ``MAKE_OROG_TN``: (Default: "make_orog") -| ``MAKE_SFC_CLIMO_TN``: (Default: "make_sfc_climo") -| ``GET_EXTRN_ICS_TN``: (Default: "get_extrn_ics") -| ``GET_EXTRN_LBCS_TN``: (Default: "get_extrn_lbcs") -| ``MAKE_ICS_TN``: (Default: "make_ics") -| ``MAKE_LBCS_TN``: (Default: "make_lbcs") -| ``RUN_FCST_TN``: (Default: "run_fcst") -| ``RUN_POST_TN``: (Default: "run_post") - -**METplus Verification Tasks:** When running METplus verification tasks, the following task names are also added to the Rocoto workflow: - -| ``GET_OBS``: (Default: "get_obs") -| ``GET_OBS_CCPA_TN``: (Default: "get_obs_ccpa") -| ``GET_OBS_MRMS_TN``: (Default: "get_obs_mrms") -| ``GET_OBS_NDAS_TN``: (Default: "get_obs_ndas") -| ``VX_TN``: (Default: "run_vx") -| ``VX_GRIDSTAT_TN``: (Default: "run_gridstatvx") -| ``VX_GRIDSTAT_REFC_TN``: (Default: "run_gridstatvx_refc") -| ``VX_GRIDSTAT_RETOP_TN``: (Default: "run_gridstatvx_retop") -| ``VX_GRIDSTAT_03h_TN``: (Default: "run_gridstatvx_03h") -| ``VX_GRIDSTAT_06h_TN``: (Default: "run_gridstatvx_06h") -| ``VX_GRIDSTAT_24h_TN``: (Default: "run_gridstatvx_24h") -| ``VX_POINTSTAT_TN``: (Default: "run_pointstatvx") -| ``VX_ENSGRID_TN``: (Default: "run_ensgridvx") -| ``VX_ENSGRID_03h_TN``: (Default: "run_ensgridvx_03h") -| ``VX_ENSGRID_06h_TN``: (Default: "run_ensgridvx_06h") -| ``VX_ENSGRID_24h_TN``: (Default: "run_ensgridvx_24h") -| ``VX_ENSGRID_REFC_TN``: (Default: "run_ensgridvx_refc") -| ``VX_ENSGRID_RETOP_TN``: (Default: "run_ensgridvx_retop") -| ``VX_ENSGRID_MEAN_TN``: (Default: "run_ensgridvx_mean") -| ``VX_ENSGRID_PROB_TN``: (Default: "run_ensgridvx_prob") -| ``VX_ENSGRID_MEAN_03h_TN``: (Default: "run_ensgridvx_mean_03h") -| ``VX_ENSGRID_PROB_03h_TN``: (Default: "run_ensgridvx_prob_03h") -| ``VX_ENSGRID_MEAN_06h_TN``: (Default: "run_ensgridvx_mean_06h") -| ``VX_ENSGRID_PROB_06h_TN``: (Default: "run_ensgridvx_prob_06h") -| ``VX_ENSGRID_MEAN_24h_TN``: (Default: "run_ensgridvx_mean_24h") -| ``VX_ENSGRID_PROB_24h_TN``: (Default: "run_ensgridvx_prob_24h") -| ``VX_ENSGRID_PROB_REFC_TN``: (Default: "run_ensgridvx_prob_refc") -| ``VX_ENSGRID_PROB_RETOP_TN``: (Default: "run_ensgridvx_prob_retop") -| ``VX_ENSPOINT_TN``: (Default: "run_enspointvx") -| ``VX_ENSPOINT_MEAN_TN``: (Default: "run_enspointvx_mean") -| ``VX_ENSPOINT_PROB_TN``: (Default: "run_enspointvx_prob") - - -Workflow Task Parameters -======================== -For each workflow task, additional parameters determine the values to pass to the job scheduler (e.g., Slurm), which submits a job for each task. Parameters include the number of nodes to use for the job, the number of :term:`MPI` processes per node, the maximum walltime to allow for the job to complete, and the maximum number of times to attempt each task. - -**Number of nodes:** - -| ``NNODES_MAKE_GRID``: (Default: "1") -| ``NNODES_MAKE_OROG``: (Default: "1") -| ``NNODES_MAKE_SFC_CLIMO``: (Default: "2") -| ``NNODES_GET_EXTRN_ICS``: (Default: "1") -| ``NNODES_GET_EXTRN_LBCS``: (Default: "1") -| ``NNODES_MAKE_ICS``: (Default: "4") -| ``NNODES_MAKE_LBCS``: (Default: "4") -| ``NNODES_RUN_FCST``: (Default: "") +``EXTRN_MDL_SOURCE_BASEDIR_ICS``: (Default: "") + Directory containing external model files for generating ICs. If ``USE_USER_STAGED_EXTRN_FILES`` is set to true, the workflow looks within this directory for a subdirectory named "YYYYMMDDHH", which contains the external model files specified by the array ``EXTRN_MDL_FILES_ICS``. This "YYYYMMDDHH" subdirectory corresponds to the start date and cycle hour of the forecast (see :ref:`above `). These files will be used to generate the :term:`ICs` on the native FV3-LAM grid. This variable is not used if ``USE_USER_STAGED_EXTRN_FILES`` is set to false. -.. note:: - The correct value for ``NNODES_RUN_FCST`` will be calculated in the workflow generation scripts. - -| ``NNODES_RUN_POST``: (Default: "2") -| ``NNODES_GET_OBS_CCPA``: (Default: "1") -| ``NNODES_GET_OBS_MRMS``: (Default: "1") -| ``NNODES_GET_OBS_NDAS``: (Default: "1") -| ``NNODES_VX_GRIDSTAT``: (Default: "1") -| ``NNODES_VX_POINTSTAT``: (Default: "1") -| ``NNODES_VX_ENSGRID``: (Default: "1") -| ``NNODES_VX_ENSGRID_MEAN``: (Default: "1") -| ``NNODES_VX_ENSGRID_PROB``: (Default: "1") -| ``NNODES_VX_ENSPOINT``: (Default: "1") -| ``NNODES_VX_ENSPOINT_MEAN``: (Default: "1") -| ``NNODES_VX_ENSPOINT_PROB``: (Default: "1") - -**Number of MPI processes per node:** - -| ``PPN_MAKE_GRID``: (Default: "24") -| ``PPN_MAKE_OROG``: (Default: "24") -| ``PPN_MAKE_SFC_CLIMO``: (Default: "24") -| ``PPN_GET_EXTRN_ICS``: (Default: "1") -| ``PPN_GET_EXTRN_LBCS``: (Default: "1") -| ``PPN_MAKE_ICS``: (Default: "12") -| ``PPN_MAKE_LBCS``: (Default: "12") -| ``PPN_RUN_FCST``: (Default: "") +``EXTRN_MDL_SYSBASEDIR_ICS``: (Default: '') + A known location of a real data stream on a given platform. This is typically a real-time data stream as on Hera, Jet, or WCOSS. External model files for generating :term:`ICs` on the native grid should be accessible via this data stream. The way the full path containing these files is constructed depends on the user-specified external model for ICs (defined above in :numref:`Section %s ` ``EXTRN_MDL_NAME_ICS``). -.. note:: - The correct value for ``PPN_RUN_FCST`` will be calculated from ``NCORES_PER_NODE`` and ``OMP_NUM_THREADS`` in ``setup.sh``. - -| ``PPN_RUN_POST``: (Default: "24") -| ``PPN_GET_OBS_CCPA``: (Default: "1") -| ``PPN_GET_OBS_MRMS``: (Default: "1") -| ``PPN_GET_OBS_NDAS``: (Default: "1") -| ``PPN_VX_GRIDSTAT``: (Default: "1") -| ``PPN_VX_POINTSTAT``: (Default: "1") -| ``PPN_VX_ENSGRID``: (Default: "1") -| ``PPN_VX_ENSGRID_MEAN``: (Default: "1") -| ``PPN_VX_ENSGRID_PROB``: (Default: "1") -| ``PPN_VX_ENSPOINT``: (Default: "1") -| ``PPN_VX_ENSPOINT_MEAN``: (Default: "1") -| ``PPN_VX_ENSPOINT_PROB``: (Default: "1") - - -**Wall Times:** Maximum amount of time for the task to run - -| ``WTIME_MAKE_GRID``: (Default: "00:20:00") -| ``WTIME_MAKE_OROG``: (Default: "01:00:00") -| ``WTIME_MAKE_SFC_CLIMO``: (Default: "00:20:00") -| ``WTIME_GET_EXTRN_ICS``: (Default: "00:45:00") -| ``WTIME_GET_EXTRN_LBCS``: (Default: "00:45:00") -| ``WTIME_MAKE_ICS``: (Default: "00:30:00") -| ``WTIME_MAKE_LBCS``: (Default: "00:30:00") -| ``WTIME_RUN_FCST``: (Default: "04:30:00") -| ``WTIME_RUN_POST``: (Default: "00:15:00") -| ``WTIME_GET_OBS_CCPA``: (Default: "00:45:00") -| ``WTIME_GET_OBS_MRMS``: (Default: "00:45:00") -| ``WTIME_GET_OBS_NDAS``: (Default: "02:00:00") -| ``WTIME_VX_GRIDSTAT``: (Default: "02:00:00") -| ``WTIME_VX_POINTSTAT``: (Default: "01:00:00") -| ``WTIME_VX_ENSGRID``: (Default: "01:00:00") -| ``WTIME_VX_ENSGRID_MEAN``: (Default: "01:00:00") -| ``WTIME_VX_ENSGRID_PROB``: (Default: "01:00:00") -| ``WTIME_VX_ENSPOINT``: (Default: "01:00:00") -| ``WTIME_VX_ENSPOINT_MEAN``: (Default: "01:00:00") -| ``WTIME_VX_ENSPOINT_PROB``: (Default: "01:00:00") - -**Maximum number of attempts to run a task:** - -| ``MAXTRIES_MAKE_GRID``: (Default: "2") -| ``MAXTRIES_MAKE_OROG``: (Default: "2") -| ``MAXTRIES_MAKE_SFC_CLIMO``: (Default: "2") -| ``MAXTRIES_GET_EXTRN_ICS``: (Default: "1") -| ``MAXTRIES_GET_EXTRN_LBCS``: (Default: "1") -| ``MAXTRIES_MAKE_ICS``: (Default: "1") -| ``MAXTRIES_MAKE_LBCS``: (Default: "1") -| ``MAXTRIES_RUN_FCST``: (Default: "1") -| ``MAXTRIES_RUN_POST``: (Default: "2") -| ``MAXTRIES_GET_OBS_CCPA``: (Default: "1") -| ``MAXTRIES_GET_OBS_MRMS``: (Default: "1") -| ``MAXTRIES_GET_OBS_NDAS``: (Default: "1") -| ``MAXTRIES_VX_GRIDSTAT``: (Default: "1") -| ``MAXTRIES_VX_GRIDSTAT_REFC``: (Default: "1") -| ``MAXTRIES_VX_GRIDSTAT_RETOP``: (Default: "1") -| ``MAXTRIES_VX_GRIDSTAT_03h``: (Default: "1") -| ``MAXTRIES_VX_GRIDSTAT_06h``: (Default: "1") -| ``MAXTRIES_VX_GRIDSTAT_24h``: (Default: "1") -| ``MAXTRIES_VX_POINTSTAT``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_REFC``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_RETOP``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_03h``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_06h``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_24h``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_MEAN``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_PROB``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_MEAN_03h``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_PROB_03h``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_MEAN_06h``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_PROB_06h``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_MEAN_24h``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_PROB_24h``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_PROB_REFC``: (Default: "1") -| ``MAXTRIES_VX_ENSGRID_PROB_RETOP``: (Default: "1") -| ``MAXTRIES_VX_ENSPOINT``: (Default: "1") -| ``MAXTRIES_VX_ENSPOINT_MEAN``: (Default: "1") -| ``MAXTRIES_VX_ENSPOINT_PROB``: (Default: "1") - - -Pre-Processing Parameters -========================= -These parameters set flags (and related directories) that determine whether various workflow tasks should be run. Note that the ``MAKE_GRID_TN``, ``MAKE_OROG_TN``, and ``MAKE_SFC_CLIMO_TN`` are all :term:`cycle-independent` tasks, i.e., if they are to be run, they do so only once at the beginning of the workflow before any cycles are run. + .. note:: + This variable must be defined as a null string in ``config_defaults.yaml`` so that if it is specified by the user in the experiment configuration file (``config.yaml``), it remains set to those values, and if not, it gets set to machine-dependent values. -Baseline Workflow Tasks --------------------------- +``EXTRN_MDL_FILES_ICS``: (Default: "") + Array containing templates of the file names to search for in the ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` directory. This variable is not used if ``USE_USER_STAGED_EXTRN_FILES`` is set to false. A single template should be used for each model file type that is used. Users may use any of the Python-style templates allowed in the ``ush/retrieve_data.py`` script. To see the full list of supported templates, run that script with the ``-h`` option. + + For example, to set FV3GFS nemsio input files: + + .. code-block:: console -``RUN_TASK_MAKE_GRID``: (Default: "TRUE") - Flag that determines whether to run the grid file generation task (``MAKE_GRID_TN``). If this is set to "TRUE", the grid generation task is run and new grid files are generated. If it is set to "FALSE", then the scripts look for pre-generated grid files in the directory specified by ``GRID_DIR`` (see below). + EXTRN_MDL_FILES_ICS=[ gfs.t{hh}z.atmf{fcst_hr:03d}.nemsio , + gfs.t{hh}z.sfcf{fcst_hr:03d}.nemsio ] + + To set FV3GFS grib files: -``GRID_DIR``: (Default: "/path/to/pregenerated/grid/files") - The directory containing pre-generated grid files when ``RUN_TASK_MAKE_GRID`` is set to "FALSE". + .. code-block:: console -``RUN_TASK_MAKE_OROG``: (Default: "TRUE") - Same as ``RUN_TASK_MAKE_GRID`` but for the orography generation task (``MAKE_OROG_TN``). Flag that determines whether to run the orography file generation task (``MAKE_OROG_TN``). If this is set to "TRUE", the orography generation task is run and new orography files are generated. If it is set to "FALSE", then the scripts look for pre-generated orography files in the directory specified by ``OROG_DIR`` (see below). + EXTRN_MDL_FILES_ICS=[ gfs.t{hh}z.pgrb2.0p25.f{fcst_hr:03d} ] -``OROG_DIR``: (Default: "/path/to/pregenerated/orog/files") - The directory containing pre-generated orography files to use when ``MAKE_OROG_TN`` is set to "FALSE". +``EXTRN_MDL_DATA_STORES``: (Default: "") + A list of data stores where the scripts should look to find external model data. The list is in priority order. If disk information is provided via ``USE_USER_STAGED_EXTRN_FILES`` or a known location on the platform, the disk location will receive highest priority. Valid values: ``disk`` | ``hpss`` | ``aws`` | ``nomads`` -``RUN_TASK_MAKE_SFC_CLIMO``: (Default: "TRUE") - Same as ``RUN_TASK_MAKE_GRID`` but for the surface climatology generation task (``MAKE_SFC_CLIMO_TN``). Flag that determines whether to run the surface climatology file generation task (``MAKE_SFC_CLIMO_TN``). If this is set to "TRUE", the surface climatology generation task is run and new surface climatology files are generated. If it is set to "FALSE", then the scripts look for pre-generated surface climatology files in the directory specified by ``SFC_CLIMO_DIR`` (see below). +NOMADS Parameters +--------------------- -``SFC_CLIMO_DIR``: (Default: "/path/to/pregenerated/surface/climo/files") - The directory containing pre-generated surface climatology files to use when ``MAKE_SFC_CLIMO_TN`` is set to "FALSE". +Set parameters associated with NOMADS online data. -``RUN_TASK_GET_EXTRN_ICS``: (Default: "TRUE") - Flag that determines whether to run the ``GET_EXTRN_ICS_TN`` task. +``NOMADS``: (Default: false) + Flag controlling whether to use NOMADS online data. Valid values: ``True`` | ``False`` -``RUN_TASK_GET_EXTRN_LBCS``: (Default: "TRUE") - Flag that determines whether to run the ``GET_EXTRN_LBCS_TN`` task. +``NOMADS_file_type``: (Default: "nemsio") + Flag controlling the format of the data. Valid values: ``"GRIB2"`` | ``"grib2"`` | ``"NEMSIO"`` | ``"nemsio"`` -``RUN_TASK_MAKE_ICS``: (Default: "TRUE") - Flag that determines whether to run the ``MAKE_ICS_TN`` task. -``RUN_TASK_MAKE_LBCS``: (Default: "TRUE") - Flag that determines whether to run the ``MAKE_LBCS_TN`` task. +GET_EXTRN_LBCS Configuration Parameters +========================================== -``RUN_TASK_RUN_FCST``: (Default: "TRUE") - Flag that determines whether to run the ``RUN_FCST_TN`` task. +Non-default parameters for the ``get_extrn_lbcs`` task are set in the ``task_get_extrn_lbcs:`` section of the ``config.yaml`` file. -``RUN_TASK_RUN_POST``: (Default: "TRUE") - Flag that determines whether to run the ``RUN_POST_TN`` task. +.. _basic-get-extrn-lbcs: -.. _VXTasks: +Basic Task Parameters +--------------------------------- -Verification Tasks --------------------- +For each workflow task, certain parameter values must be passed to the job scheduler (e.g., Slurm), which submits a job for the task. -``RUN_TASK_GET_OBS_CCPA``: (Default: "FALSE") - Flag that determines whether to run the ``GET_OBS_CCPA_TN`` task, which retrieves the :term:`CCPA` hourly precipitation files used by METplus from NOAA :term:`HPSS`. +``GET_EXTRN_LBCS_TN``: (Default: "get_extrn_lbcs") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. -``RUN_TASK_GET_OBS_MRMS``: (Default: "FALSE") - Flag that determines whether to run the ``GET_OBS_MRMS_TN`` task, which retrieves the :term:`MRMS` composite reflectivity files used by METplus from NOAA HPSS. +``NNODES_GET_EXTRN_LBCS``: (Default: 1) + Number of nodes to use for the job. -``RUN_TASK_GET_OBS_NDAS``: (Default: "FALSE") - Flag that determines whether to run the ``GET_OBS_NDAS_TN`` task, which retrieves the :term:`NDAS` PrepBufr files used by METplus from NOAA HPSS. +``PPN_GET_EXTRN_LBCS``: (Default: 1) + Number of :term:`MPI` processes per node. -``RUN_TASK_VX_GRIDSTAT``: (Default: "FALSE") - Flag that determines whether to run the grid-stat verification task. +``WTIME_GET_EXTRN_LBCS``: (Default: 00:45:00) + Maximum time for the task to complete. -``RUN_TASK_VX_POINTSTAT``: (Default: "FALSE") - Flag that determines whether to run the point-stat verification task. +``MAXTRIES_GET_EXTRN_LBCS``: (Default: 1) + Maximum number of times to attempt the task. -``RUN_TASK_VX_ENSGRID``: (Default: "FALSE") - Flag that determines whether to run the ensemble-stat verification for gridded data task. +``EXTRN_MDL_NAME_LBCS``: (Default: "FV3GFS") + The name of the external model that will provide fields from which lateral boundary condition (LBC) files (except for the 0-th hour LBC file) will be generated for input into the forecast model. Valid values: ``"GSMGFS"`` | ``"FV3GFS"`` | ``"RAP"`` | ``"HRRR"`` | ``"NAM"`` -``RUN_TASK_VX_ENSPOINT``: (Default: "FALSE") - Flag that determines whether to run the ensemble point verification task. If this flag is set, both ensemble-stat point verification and point verification of ensemble-stat output is computed. +``LBC_SPEC_INTVL_HRS``: (Default: "6") + The interval (in integer hours) at which LBC files will be generated. This is also referred to as the *boundary update interval*. Note that the model selected in ``EXTRN_MDL_NAME_LBCS`` must have data available at a frequency greater than or equal to that implied by ``LBC_SPEC_INTVL_HRS``. For example, if ``LBC_SPEC_INTVL_HRS`` is set to "6", then the model must have data available at least every 6 hours. It is up to the user to ensure that this is the case. -.. - COMMENT: Might be worth defining "ensemble-stat verification for gridded data," "ensemble point verification," "ensemble-stat point verification," and "point verification of ensemble-stat output" +``EXTRN_MDL_LBCS_OFFSET_HRS``: (Default: "") + Users may wish to use lateral boundary conditions from a forecast that was started earlier than the start of the forecast configured here. This variable indicates how many hours earlier the external model started than the FV3 forecast configured here. For example, if the forecast should use lateral boundary conditions from the GFS started 6 hours earlier, then ``EXTRN_MDL_LBCS_OFFSET_HRS: "6"``. Note: the default value is model-dependent and is set in ``ush/set_extrn_mdl_params.py``. -Aerosol Climatology Parameter -================================ +``FV3GFS_FILE_FMT_LBCS``: (Default: "nemsio") + If using the FV3GFS model as the source of the :term:`LBCs` (i.e., if ``EXTRN_MDL_NAME_LBCS: "FV3GFS"``), this variable specifies the format of the model files to use when generating the LBCs. Valid values: ``"nemsio"`` | ``"grib2"`` | ``"netcdf"`` -``USE_MERRA_CLIMO``: (Default: "FALSE") - Flag that determines whether :term:`MERRA2` aerosol climatology data and lookup tables for optics properties are obtained. -.. - COMMENT: When would it be appropriate to obtain these files? +File and Directory Parameters +-------------------------------- -Surface Climatology Parameter -============================= -``SFC_CLIMO_FIELDS``: (Default: "("facsf" "maximum_snow_albedo" "slope_type" "snowfree_albedo" "soil_type" "substrate_temperature" "vegetation_greenness" "vegetation_type")" ) - Array containing the names of all the fields for which ``MAKE_SFC_CLIMO_TN`` generates files on the native FV3-LAM grid. +``USE_USER_STAGED_EXTRN_FILES``: (Default: false) + Analogous to ``USE_USER_STAGED_EXTRN_FILES`` in :term:`ICs` but for :term:`LBCs`. Flag that determines whether the workflow will look for the external model files needed for generating :term:`LBCs` in user-specified directories (rather than fetching them from mass storage like NOAA :term:`HPSS`). Valid values: ``True`` | ``False`` + +``EXTRN_MDL_SOURCE_BASEDIR_LBCS``: (Default: "") + Analogous to ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` but for :term:`LBCs` instead of :term:`ICs`. + Directory containing external model files for generating LBCs. If ``USE_USER_STAGED_EXTRN_FILES`` is set to true, the workflow looks within this directory for a subdirectory named "YYYYMMDDHH", which contains the external model files specified by the array ``EXTRN_MDL_FILES_LBCS``. This "YYYYMMDDHH" subdirectory corresponds to the start date and cycle hour of the forecast (see :ref:`above `). These files will be used to generate the :term:`LBCs` on the native FV3-LAM grid. This variable is not used if ``USE_USER_STAGED_EXTRN_FILES`` is set to false. -Fixed File Parameters -===================== -These parameters are associated with the fixed (i.e., static) files. On `Level 1 & 2 `__ systems, fixed files are prestaged with paths defined in the ``setup.sh`` script. Because the default values are platform-dependent, they are set to a null string in ``config_defaults.sh``. Then these null values are overwritten in ``setup.sh`` with machine-specific values or with a user-specified value from ``config.sh``. +``EXTRN_MDL_SYSBASEDIR_LBCS``: (Default: '') + Same as ``EXTRN_MDL_SYSBASEDIR_ICS`` but for :term:`LBCs`. A known location of a real data stream on a given platform. This is typically a real-time data stream as on Hera, Jet, or WCOSS. External model files for generating :term:`LBCs` on the native grid should be accessible via this data stream. The way the full path containing these files is constructed depends on the user-specified external model for LBCs (defined above in :numref:`Section %s ` ``EXTRN_MDL_NAME_LBCS`` above). -``FIXgsm``: (Default: "") - System directory in which the majority of fixed (i.e., time-independent) files that are needed to run the FV3-LAM model are located. + .. note:: + This variable must be defined as a null string in ``config_defaults.yaml`` so that if it is specified by the user in the experiment configuration file (``config.yaml``), it remains set to those values, and if not, it gets set to machine-dependent values. -``FIXaer``: (Default: "") - System directory where :term:`MERRA2` aerosol climatology files are located. +``EXTRN_MDL_FILES_LBCS``: (Default: "") + Analogous to ``EXTRN_MDL_FILES_ICS`` but for :term:`LBCs` instead of :term:`ICs`. Array containing templates of the file names to search for in the ``EXTRN_MDL_SOURCE_BASEDIR_LBCS`` directory. This variable is not used if ``USE_USER_STAGED_EXTRN_FILES`` is set to false. A single template should be used for each model file type that is used. Users may use any of the Python-style templates allowed in the ``ush/retrieve_data.py`` script. To see the full list of supported templates, run that script with the ``-h`` option. For examples, see the ``EXTRN_MDL_FILES_ICS`` variable above. + +``EXTRN_MDL_DATA_STORES``: (Default: "") + Analogous to ``EXTRN_MDL_DATA_STORES`` in :term:`ICs` but for :term:`LBCs`. A list of data stores where the scripts should look to find external model data. The list is in priority order. If disk information is provided via ``USE_USER_STAGED_EXTRN_FILES`` or a known location on the platform, the disk location will receive highest priority. Valid values: ``disk`` | ``hpss`` | ``aws`` | ``nomads`` -``FIXlut``: (Default: "") - System directory where the lookup tables for optics properties are located. +NOMADS Parameters +--------------------- -``TOPO_DIR``: (Default: "") - The location on disk of the static input files used by the ``make_orog`` task (i.e., ``orog.x`` and ``shave.x``). Can be the same as ``FIXgsm``. +Set parameters associated with NOMADS online data. Analogus to :term:`ICs` NOMADS Parameters. -``SFC_CLIMO_INPUT_DIR``: (Default: "") - The location on disk of the static surface climatology input fields, used by ``sfc_climo_gen``. These files are only used if ``RUN_TASK_MAKE_SFC_CLIMO=TRUE``. +``NOMADS``: (Default: false) + Flag controlling whether to use NOMADS online data. -``FNGLAC, ..., FNMSKH``: (Default: see below) - .. code-block:: console +``NOMADS_file_type``: (Default: "nemsio") + Flag controlling the format of the data. Valid values: ``"GRIB2"`` | ``"grib2"`` | ``"NEMSIO"`` | ``"nemsio"`` - (FNGLAC="global_glacier.2x2.grb" - FNMXIC="global_maxice.2x2.grb" - FNTSFC="RTGSST.1982.2012.monthly.clim.grb" - FNSNOC="global_snoclim.1.875.grb" - FNZORC="igbp" - FNAISC="CFSR.SEAICE.1982.2012.monthly.clim.grb" - FNSMCC="global_soilmgldas.t126.384.190.grb" - FNMSKH="seaice_newland.grb") +MAKE_ICS Configuration Parameters +====================================== - Names and default locations of (some of the) global data files that are assumed to exist in a system directory. (This directory is machine-dependent; the experiment generation scripts will set it and store it in the variable ``FIXgsm``.) These file names also appear directly in the forecast model's input :term:`namelist` file. +Non-default parameters for the ``make_ics`` task are set in the ``task_make_ics:`` section of the ``config.yaml`` file. -``FIXgsm_FILES_TO_COPY_TO_FIXam``: (Default: see below) - .. code-block:: console +Basic Task Parameters +--------------------------------- - ("$FNGLAC" \ - "$FNMXIC" \ - "$FNTSFC" \ - "$FNSNOC" \ - "$FNAISC" \ - "$FNSMCC" \ - "$FNMSKH" \ - "global_climaeropac_global.txt" \ - "fix_co2_proj/global_co2historicaldata_2010.txt" \ - "fix_co2_proj/global_co2historicaldata_2011.txt" \ - "fix_co2_proj/global_co2historicaldata_2012.txt" \ - "fix_co2_proj/global_co2historicaldata_2013.txt" \ - "fix_co2_proj/global_co2historicaldata_2014.txt" \ - "fix_co2_proj/global_co2historicaldata_2015.txt" \ - "fix_co2_proj/global_co2historicaldata_2016.txt" \ - "fix_co2_proj/global_co2historicaldata_2017.txt" \ - "fix_co2_proj/global_co2historicaldata_2018.txt" \ - "fix_co2_proj/global_co2historicaldata_2019.txt" \ - "fix_co2_proj/global_co2historicaldata_2020.txt" \ - "fix_co2_proj/global_co2historicaldata_2021.txt" \ - "global_co2historicaldata_glob.txt" \ - "co2monthlycyc.txt" \ - "global_h2o_pltc.f77" \ - "global_hyblev.l65.txt" \ - "global_zorclim.1x1.grb" \ - "global_sfc_emissivity_idx.txt" \ - "global_tg3clim.2.6x1.5.grb" \ - "global_solarconstant_noaa_an.txt" \ - "global_albedo4.1x1.grb" \ - "geo_em.d01.lat-lon.2.5m.HGT_M.nc" \ - "HGT.Beljaars_filtered.lat-lon.30s_res.nc" \ - "replace_with_FIXgsm_ozone_prodloss_filename") - - If not running in NCO mode, this array contains the names of the files to copy from the ``FIXgsm`` system directory to the ``FIXam`` directory under the experiment directory. - - .. note:: - The last element in the list above contains a dummy value. This value will be reset by the workflow generation scripts to the name of the ozone production/loss file that needs to be copied from ``FIXgsm``. This file depends on the :term:`CCPP` physics suite specified for the experiment (and the corresponding ozone parameterization scheme used in that physics suite). +For each workflow task, certain parameter values must be passed to the job scheduler (e.g., Slurm), which submits a job for the task. -``FV3_NML_VARNAME_TO_FIXam_FILES_MAPPING``: (Default: see below) - .. code-block:: console +``MAKE_ICS_TN``: (Default: "make_ics") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. - ("FNGLAC | $FNGLAC" \ - "FNMXIC | $FNMXIC" \ - "FNTSFC | $FNTSFC" \ - "FNSNOC | $FNSNOC" \ - "FNAISC | $FNAISC" \ - "FNSMCC | $FNSMCC" \ - "FNMSKH | $FNMSKH" ) +``NNODES_MAKE_ICS``: (Default: 4) + Number of nodes to use for the job. - This array is used to set some of the :term:`namelist` variables in the forecast model's namelist file. It maps file symlinks to the actual fixed file locations in the ``FIXam`` directory. The symlink names appear in the first column (to the left of the "|" symbol), and the paths to these files (in the ``FIXam`` directory) are held in workflow variables, which appear to the right of the "|" symbol. It is possible to remove ``FV3_NML_VARNAME_TO_FIXam_FILES_MAPPING`` as a workflow variable and make it only a local one since it is used in only one script. +``PPN_MAKE_ICS``: (Default: 12) + Number of :term:`MPI` processes per node. -``FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING``: (Default: see below) - .. code-block:: console +``WTIME_MAKE_ICS``: (Default: 00:30:00) + Maximum time for the task to complete. - ("FNALBC | snowfree_albedo" \ - "FNALBC2 | facsf" \ - "FNTG3C | substrate_temperature" \ - "FNVEGC | vegetation_greenness" \ - "FNVETC | vegetation_type" \ - "FNSOTC | soil_type" \ - "FNVMNC | vegetation_greenness" \ - "FNVMXC | vegetation_greenness" \ - "FNSLPC | slope_type" \ - "FNABSC | maximum_snow_albedo" ) - - This array is used to set some of the :term:`namelist` variables in the forecast model's namelist file. The variable names appear in the first column (to the left of the "|" symbol), and the paths to these surface climatology files on the native FV3-LAM grid (in the ``FIXLAM`` directory) are derived from the corresponding surface climatology fields (the second column of the array). - -``CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING``: (Default: see below) - .. code-block:: console +``MAXTRIES_MAKE_ICS``: (Default: 1) + Maximum number of times to attempt the task. - ("aerosol.dat | global_climaeropac_global.txt" \ - "co2historicaldata_2010.txt | fix_co2_proj/global_co2historicaldata_2010.txt" \ - "co2historicaldata_2011.txt | fix_co2_proj/global_co2historicaldata_2011.txt" \ - "co2historicaldata_2012.txt | fix_co2_proj/global_co2historicaldata_2012.txt" \ - "co2historicaldata_2013.txt | fix_co2_proj/global_co2historicaldata_2013.txt" \ - "co2historicaldata_2014.txt | fix_co2_proj/global_co2historicaldata_2014.txt" \ - "co2historicaldata_2015.txt | fix_co2_proj/global_co2historicaldata_2015.txt" \ - "co2historicaldata_2016.txt | fix_co2_proj/global_co2historicaldata_2016.txt" \ - "co2historicaldata_2017.txt | fix_co2_proj/global_co2historicaldata_2017.txt" \ - "co2historicaldata_2018.txt | fix_co2_proj/global_co2historicaldata_2018.txt" \ - "co2historicaldata_2019.txt | fix_co2_proj/global_co2historicaldata_2019.txt" \ - "co2historicaldata_2020.txt | fix_co2_proj/global_co2historicaldata_2020.txt" \ - "co2historicaldata_2021.txt | fix_co2_proj/global_co2historicaldata_2021.txt" \ - "co2historicaldata_glob.txt | global_co2historicaldata_glob.txt" \ - "co2monthlycyc.txt | co2monthlycyc.txt" \ - "global_h2oprdlos.f77 | global_h2o_pltc.f77" \ - "global_albedo4.1x1.grb | global_albedo4.1x1.grb" \ - "global_zorclim.1x1.grb | global_zorclim.1x1.grb" \ - "global_tg3clim.2.6x1.5.grb | global_tg3clim.2.6x1.5.grb" \ - "sfc_emissivity_idx.txt | global_sfc_emissivity_idx.txt" \ - "solarconstant_noaa_an.txt | global_solarconstant_noaa_an.txt" \ - "global_o3prdlos.f77 | " ) - - This array specifies the mapping to use between the symlinks that need to be created in each cycle directory (these are the "files" that :term:`FV3` looks for) and their targets in the ``FIXam`` directory. The first column of the array specifies the symlink to be created, and the second column specifies its target file in ``FIXam`` (where columns are delineated by the pipe symbol "|"). - -Subhourly Forecast Parameters -================================= +``KMP_AFFINITY_MAKE_ICS``: (Default: "scatter") + Intel Thread Affinity Interface for the ``make_ics`` task. See :ref:`this note ` for more information on thread affinity. -``SUB_HOURLY_POST``: (Default: "FALSE") - Flag that indicates whether the forecast model will generate output files on a sub-hourly time interval (e.g., 10 minutes, 15 minutes). This will also cause the post-processor to process these sub-hourly files. If this variable is set to "TRUE", then ``DT_SUBHOURLY_POST_MNTS`` should be set to a valid value between "01" and "59". +``OMP_NUM_THREADS_MAKE_ICS``: (Default: 1) + The number of OpenMP threads to use for parallel regions. -``DT_SUB_HOURLY_POST_MNTS``: (Default: "00") - Time interval in minutes between the forecast model output files. If ``SUB_HOURLY_POST`` is set to "TRUE", this needs to be set to a valid two-digit integer between "01" and "59". Note that if ``SUB_HOURLY_POST`` is set to "TRUE" but ``DT_SUB_HOURLY_POST_MNTS`` is set to "00", ``SUB_HOURLY_POST`` will get reset to "FALSE" in the experiment generation scripts (there will be an informational message in the log file to emphasize this). Valid values: ``"1"`` | ``"01"`` | ``"2"`` | ``"02"`` | ``"3"`` | ``"03"`` | ``"4"`` | ``"04"`` | ``"5"`` | ``"05"`` | ``"6"`` | ``"06"`` | ``"10"`` | ``"12"`` | ``"15"`` | ``"20"`` | ``"30"`` +``OMP_STACKSIZE_MAKE_ICS``: (Default: "1024m") + Controls the size of the stack for threads created by the OpenMP implementation. -Customized Post Configuration Parameters -======================================== +FVCOM Parameter +------------------- +``USE_FVCOM``: (Default: false) + Flag that specifies whether to update surface conditions in FV3-:term:`LAM` with fields generated from the Finite Volume Community Ocean Model (:term:`FVCOM`). If set to true, lake/sea surface temperatures, ice surface temperatures, and ice placement will be overwritten using data provided by FVCOM. Setting ``USE_FVCOM`` to true causes the executable ``process_FVCOM.exe`` in the ``MAKE_ICS_TN`` task to run. This, in turn, modifies the file ``sfc_data.nc`` generated by ``chgres_cube`` during the ``make_ics`` task. Note that the FVCOM data must already be interpolated to the desired FV3-LAM grid. Valid values: ``True`` | ``False`` -``USE_CUSTOM_POST_CONFIG_FILE``: (Default: "FALSE") - Flag that determines whether a user-provided custom configuration file should be used for post-processing the model data. If this is set to "TRUE", then the workflow will use the custom post-processing (:term:`UPP`) configuration file specified in ``CUSTOM_POST_CONFIG_FP``. Otherwise, a default configuration file provided in the UPP repository will be used. +``FVCOM_WCSTART``: (Default: "cold") + Define if this is a "warm" start or a "cold" start. Setting this to "warm" will read in ``sfc_data.nc`` generated in a RESTART directory. Setting this to "cold" will read in the ``sfc_data.nc`` generated from ``chgres_cube`` in the ``make_ics`` portion of the workflow. Valid values: ``"cold"`` | ``"COLD"`` | ``"warm"`` | ``"WARM"`` -``CUSTOM_POST_CONFIG_FP``: (Default: "") - The full path to the custom flat file, including filename, to be used for post-processing. This is only used if ``CUSTOM_POST_CONFIG_FILE`` is set to "TRUE". +``FVCOM_DIR``: (Default: "") + User-defined directory where the ``fvcom.nc`` file containing :term:`FVCOM` data already interpolated to the FV3-LAM native grid is located. The file in this directory must be named ``fvcom.nc``. +``FVCOM_FILE``: (Default: "fvcom.nc") + Name of the file located in ``FVCOM_DIR`` that has :term:`FVCOM` data interpolated to the FV3-LAM grid. This file will be copied later to a new location, and the name will be changed to ``fvcom.nc`` if a name other than ``fvcom.nc`` is selected. -Community Radiative Transfer Model (CRTM) Parameters -======================================================= -These variables set parameters associated with outputting satellite fields in the :term:`UPP` :term:`grib2` files using the Community Radiative Transfer Model (:term:`CRTM`). :numref:`Section %s ` includes further instructions on how to do this. +MAKE_LBCS Configuration Parameters +====================================== -``USE_CRTM``: (Default: "FALSE") - Flag that defines whether external :term:`CRTM` coefficient files have been staged by the user in order to output synthetic satellite products available within the :term:`UPP`. If this is set to "TRUE", then the workflow will check for these files in the directory ``CRTM_DIR``. Otherwise, it is assumed that no satellite fields are being requested in the UPP configuration. +Non-default parameters for the ``make_lbcs`` task are set in the ``task_make_lbcs:`` section of the ``config.yaml`` file. -``CRTM_DIR``: (Default: "") - This is the path to the top CRTM fix file directory. This is only used if ``USE_CRTM`` is set to "TRUE". +``MAKE_LBCS_TN``: (Default: "make_lbcs") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. -Ensemble Model Parameters -============================ +``NNODES_MAKE_LBCS``: (Default: 4) + Number of nodes to use for the job. -``DO_ENSEMBLE``: (Default: "FALSE") - Flag that determines whether to run a set of ensemble forecasts (for each set of specified cycles). If this is set to "TRUE", ``NUM_ENS_MEMBERS`` forecasts are run for each cycle, each with a different set of stochastic seed values. When "FALSE", a single forecast is run for each cycle. +``PPN_MAKE_LBCS``: (Default: 12) + Number of :term:`MPI` processes per node. -``NUM_ENS_MEMBERS``: (Default: "1") - The number of ensemble members to run if ``DO_ENSEMBLE`` is set to "TRUE". This variable also controls the naming of the ensemble member directories. For example, if ``NUM_ENS_MEMBERS`` is set to "8", the member directories will be named *mem1, mem2, ..., mem8*. If it is set to "08" (with a leading zero), the member directories will be named *mem01, mem02, ..., mem08*. However, after reading in the number of characters in this string (in order to determine how many leading zeros, if any, should be placed in the names of the member directories), the workflow generation scripts strip away those leading zeros. Thus, in the variable definitions file (``GLOBAL_VAR_DEFNS_FN``), this variable appears with its leading zeros stripped. This variable is not used unless ``DO_ENSEMBLE`` is set to "TRUE". +``WTIME_MAKE_LBCS``: (Default: 00:30:00) + Maximum time for the task to complete. -.. _HaloBlend: +``MAXTRIES_MAKE_LBCS``: (Default: 1) + Maximum number of times to attempt the task. -Halo Blend Parameter -==================== -``HALO_BLEND``: (Default: "10") - Number of cells to use for "blending" the external solution (obtained from the :term:`LBCs`) with the internal solution from the FV3LAM :term:`dycore`. Specifically, it refers to the number of rows into the computational domain that should be blended with the LBCs. Cells at which blending occurs are all within the boundary of the native grid; they don't involve the 4 cells outside the boundary where the LBCs are specified (which is a different :term:`halo`). Blending is necessary to smooth out waves generated due to mismatch between the external and internal solutions. To shut :term:`halo` blending off, set this to zero. +``KMP_AFFINITY_MAKE_LBCS``: (Default: "scatter") + Intel Thread Affinity Interface for the ``make_lbcs`` task. See :ref:`this note ` for more information on thread affinity. +``OMP_NUM_THREADS_MAKE_LBCS``: (Default: 1) + The number of OpenMP threads to use for parallel regions. -FVCOM Parameter -=============== -``USE_FVCOM``: (Default: "FALSE") - Flag that specifies whether or not to update surface conditions in FV3-LAM with fields generated from the Finite Volume Community Ocean Model (:term:`FVCOM`). If set to "TRUE", lake/sea surface temperatures, ice surface temperatures, and ice placement will be overwritten using data provided by FVCOM. Setting ``USE_FVCOM`` to "TRUE" causes the executable ``process_FVCOM.exe`` in the ``MAKE_ICS_TN`` task to run. This, in turn, modifies the file ``sfc_data.nc`` generated by ``chgres_cube``. Note that the FVCOM data must already be interpolated to the desired FV3-LAM grid. +``OMP_STACKSIZE_MAKE_LBCS``: (Default: "1024m") + Controls the size of the stack for threads created by the OpenMP implementation. -``FVCOM_WCSTART``: (Default: "cold") - Define if this is a "warm" start or a "cold" start. Setting this to "warm" will read in ``sfc_data.nc`` generated in a RESTART directory. Setting this to "cold" will read in the ``sfc_data.nc`` generated from ``chgres_cube`` in the ``make_ics`` portion of the workflow. Valid values: ``"cold"`` | ``"warm"`` +FORECAST Configuration Parameters +===================================== -``FVCOM_DIR``: (Default: "/user/defined/dir/to/fvcom/data") - User-defined directory where the ``fvcom.nc`` file containing :term:`FVCOM` data on the FV3-LAM native grid is located. The file name in this directory must be ``fvcom.nc``. +Non-default parameters for the ``run_fcst`` task are set in the ``task_run_fcst`` section of the ``config.yaml`` file. -``FVCOM_FILE``: (Default: "fvcom.nc") - Name of file located in ``FVCOM_DIR`` that has :term:`FVCOM` data interpolated to the FV3-LAM grid. This file will be copied later to a new location and the name changed to ``fvcom.nc`` if a name other than ``fvcom.nc`` is selected. +Basic Task Parameters +--------------------------------- -Thread Affinity Interface -=========================== +For each workflow task, certain parameter values must be passed to the job scheduler (e.g., Slurm), which submits a job for the task. -.. note:: - Note that settings for the ``make_grid`` and ``make_orog`` tasks are disabled or not included below because they do not use parallelized code. +``RUN_FCST_TN``: (Default: "run_fcst") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. -``KMP_AFFINITY_*``: (Default: see below) +``NNODES_RUN_FCST``: (Default: "") + Number of nodes to use for the job. This is calculated in the workflow generation scripts, so there is no need to set it in the configuration file. - .. code-block:: console +``PPN_RUN_FCST``: (Default: "") + Number of :term:`MPI` processes per node. It will be calculated from ``NCORES_PER_NODE`` and ``OMP_NUM_THREADS`` in ``setup.py``. - KMP_AFFINITY_MAKE_OROG="disabled" - KMP_AFFINITY_MAKE_SFC_CLIMO="scatter" - KMP_AFFINITY_MAKE_ICS="scatter" - KMP_AFFINITY_MAKE_LBCS="scatter" - KMP_AFFINITY_RUN_FCST="scatter" - KMP_AFFINITY_RUN_POST="scatter" +``WTIME_RUN_FCST``: (Default: 04:30:00) + Maximum time for the task to complete. - "Intel's runtime library can bind OpenMP threads to physical processing units. The interface is controlled using the KMP_AFFINITY environment variable. Thread affinity restricts execution of certain threads to a subset of the physical processing units in a multiprocessor computer. Depending on the system (machine) topology, application, and operating system, thread affinity can have a dramatic effect on the application speed and on the execution speed of a program." Valid values: ``"scatter"`` | ``"disabled"`` | ``"balanced"`` | ``"compact"`` | ``"explicit"`` | ``"none"`` +``MAXTRIES_RUN_FCST``: (Default: 1) + Maximum number of times to attempt the task. - For more information, see the `Intel Development Reference Guide `__. +``KMP_AFFINITY_RUN_FCST``: (Default: "scatter") + Intel Thread Affinity Interface for the ``run_fcst`` task. -``OMP_NUM_THREADS_*``: (Default: see below) +.. _thread-affinity: - .. code-block:: console + .. note:: - OMP_NUM_THREADS_MAKE_OROG="6" - OMP_NUM_THREADS_MAKE_SFC_CLIMO="1" - OMP_NUM_THREADS_MAKE_ICS="1" - OMP_NUM_THREADS_MAKE_LBCS="1" - OMP_NUM_THREADS_RUN_FCST="2" # atmos_nthreads in model_configure - OMP_NUM_THREADS_RUN_POST="1" + **Thread Affinity Interface** - The number of OpenMP threads to use for parallel regions. + "Intel's runtime library can bind OpenMP threads to physical processing units. The interface is controlled using the ``KMP_AFFINITY`` environment variable. Thread affinity restricts execution of certain threads to a subset of the physical processing units in a multiprocessor computer. Depending on the system (machine) topology, application, and operating system, thread affinity can have a dramatic effect on the application speed and on the execution speed of a program." Valid values: ``"scatter"`` | ``"disabled"`` | ``"balanced"`` | ``"compact"`` | ``"explicit"`` | ``"none"`` -.. - COMMENT: What does the #atmos_nthreads comment mean? Can it be removed? + For more information, see the `Intel Development Reference Guide `__. + +``OMP_NUM_THREADS_RUN_FCST``: (Default: 2) + The number of OpenMP threads to use for parallel regions. Corresponds to the ``atmos_nthreads`` value in ``model_configure``. + +``OMP_STACKSIZE_RUN_FCST``: (Default: "1024m") + Controls the size of the stack for threads created by the OpenMP implementation. + +Model Configuration Parameters +---------------------------------- + +These parameters set values in the Weather Model's ``model_configure`` file. + +``DT_ATMOS``: (Default: "") + Time step for the outermost atmospheric model loop in seconds. This corresponds to the frequency at which the physics routines and the top level dynamics routine are called. (Note that one call to the top-level dynamics routine results in multiple calls to the horizontal dynamics, :term:`tracer` transport, and vertical dynamics routines; see the `FV3 dycore scientific documentation `__ for details.) Must be set. Takes an integer value. In the SRW App, a default value for ``DT_ATMOS`` appears in the ``set_predef_grid_params.yaml`` script, but a different value can be set in ``config.yaml``. + +``RESTART_INTERVAL``: (Default: 0) + Frequency of the output restart files in hours. Using the default interval (0), restart files are produced at the end of a forecast run. When ``RESTART_INTERVAL: 1``, restart files are produced every hour with the prefix "YYYYMMDD.HHmmSS." in the ``RESTART`` directory. + +.. _InlinePost: + +``WRITE_DOPOST``: (Default: false) + Flag that determines whether to use the inline post option. The default ``WRITE_DOPOST: false`` does not use the inline post functionality, and the ``run_post`` tasks are called from outside of the Weather Model. If ``WRITE_DOPOST: true``, the ``WRITE_DOPOST`` flag in the ``model_configure`` file will be set to true, and the post-processing (:term:`UPP`) tasks will be called from within the Weather Model. This means that the post-processed files (in :term:`grib2` format) are output by the Weather Model at the same time that it outputs the ``dynf###.nc`` and ``phyf###.nc`` files. Setting ``WRITE_DOPOST: true`` turns off the separate ``run_post`` task (i.e., ``RUN_TASK_RUN_POST`` is set to false) in ``setup.py`` to avoid unnecessary computations. Valid values: ``True`` | ``False`` + +Computational Parameters +---------------------------- + +``LAYOUT_X, LAYOUT_Y``: (Default: "") + The number of :term:`MPI` tasks (processes) to use in the two horizontal directions (x and y) of the regional grid when running the forecast model. + +``BLOCKSIZE``: (Default: "") + The amount of data that is passed into the cache at a time. + +.. note:: + + In ``config_defaults.yaml`` the computational parameters are set to null strings so that: + + #. If the experiment is using a predefined grid and the user sets the parameter in the user-specified experiment configuration file (i.e., ``config.yaml``), that value will be used in the forecast(s). Otherwise, the default value for that predefined grid will be used. + #. If the experiment is *not* using a predefined grid (i.e., it is using a custom grid whose parameters are specified in the experiment configuration file), then the user must specify a value for the parameter in that configuration file. Otherwise, the parameter will remain set to a null string, and the experiment generation will fail because the generation scripts check to ensure that all the parameters defined in this section are set to non-empty strings before creating the experiment directory. + +.. _WriteComp: + +Write-Component (Quilting) Parameters +----------------------------------------- + +.. note:: + The :term:`UPP` (called by the ``RUN_POST_TN`` task) cannot process output on the native grid types ("GFDLgrid" and "ESGgrid"), so output fields are interpolated to a **write component grid** before writing them to an output file. The output files written by the UFS Weather Model use an Earth System Modeling Framework (:term:`ESMF`) component, referred to as the **write component**. This model component is configured with settings in the ``model_configure`` file, as described in `Section 4.2.3 `__ of the UFS Weather Model documentation. + +``QUILTING``: (Default: true) + + .. attention:: + The regional grid requires the use of the write component, so users generally should not need to change the default value for ``QUILTING``. + + Flag that determines whether to use the write component for writing forecast output files to disk. If set to true, the forecast model will output files named ``dynf$HHH.nc`` and ``phyf$HHH.nc`` (where ``HHH`` is the 3-digit forecast hour) containing dynamics and physics fields, respectively, on the write-component grid. For example, the output files for the 3rd hour of the forecast would be ``dynf$003.nc`` and ``phyf$003.nc``. (The regridding from the native FV3-LAM grid to the write-component grid is done by the forecast model.) If ``QUILTING`` is set to false, then the output file names are ``fv3_history.nc`` and ``fv3_history2d.nc``, and they contain fields on the native grid. Although the UFS Weather Model can run without quilting, the regional grid requires the use of the write component. Therefore, QUILTING should be set to true when running the SRW App. If ``QUILTING`` is set to false, the ``RUN_POST_TN`` (meta)task cannot run because the :term:`UPP` code called by this task cannot process fields on the native grid. In that case, the ``RUN_POST_TN`` (meta)task will be automatically removed from the Rocoto workflow XML. The :ref:`INLINE POST ` option also requires ``QUILTING`` to be set to true in the SRW App. Valid values: ``True`` | ``False`` + +``PRINT_ESMF``: (Default: false) + Flag that determines whether to output extra (debugging) information from :term:`ESMF` routines. Note that the write component uses ESMF library routines to interpolate from the native forecast model grid to the user-specified output grid (which is defined in the model configuration file ``model_configure`` in the forecast run directory). Valid values: ``True`` | ``False`` + +``WRTCMP_write_groups``: (Default: 1) + The number of write groups (i.e., groups of :term:`MPI` tasks) to use in the write component. + +``WRTCMP_write_tasks_per_group``: (Default: 20) + The number of MPI tasks to allocate for each write group. + +``WRTCMP_output_grid``: (Default: "''") + Sets the type (coordinate system) of the write component grid. The default empty string forces the user to set a valid value for ``WRTCMP_output_grid`` in ``config.yaml`` if specifying a *custom* grid. When creating an experiment with a user-defined grid, this parameter must be specified or the experiment will fail. Valid values: ``"lambert_conformal"`` | ``"regional_latlon"`` | ``"rotated_latlon"`` + +``WRTCMP_cen_lon``: (Default: "") + Longitude (in degrees) of the center of the write component grid. Can usually be set to the corresponding value from the native grid. + +``WRTCMP_cen_lat``: (Default: "") + Latitude (in degrees) of the center of the write component grid. Can usually be set to the corresponding value from the native grid. + +``WRTCMP_lon_lwr_left``: (Default: "") + Longitude (in degrees) of the center of the lower-left (southwest) cell on the write component grid. If using the "rotated_latlon" coordinate system, this is expressed in terms of the rotated longitude. Must be set manually when running an experiment with a user-defined grid. + +``WRTCMP_lat_lwr_left``: (Default: "") + Latitude (in degrees) of the center of the lower-left (southwest) cell on the write component grid. If using the "rotated_latlon" coordinate system, this is expressed in terms of the rotated latitude. Must be set manually when running an experiment with a user-defined grid. + +**The following parameters must be set when** ``WRTCMP_output_grid`` **is set to "rotated_latlon":** + +``WRTCMP_lon_upr_rght``: (Default: "") + Longitude (in degrees) of the center of the upper-right (northeast) cell on the write component grid (expressed in terms of the rotated longitude). + +``WRTCMP_lat_upr_rght``: (Default: "") + Latitude (in degrees) of the center of the upper-right (northeast) cell on the write component grid (expressed in terms of the rotated latitude). + +``WRTCMP_dlon``: (Default: "") + Size (in degrees) of a grid cell on the write component grid (expressed in terms of the rotated longitude). + +``WRTCMP_dlat``: (Default: "") + Size (in degrees) of a grid cell on the write component grid (expressed in terms of the rotated latitude). + +**The following parameters must be set when** ``WRTCMP_output_grid`` **is set to "lambert_conformal":** + +``WRTCMP_stdlat1``: (Default: "") + First standard latitude (in degrees) in definition of Lambert conformal projection. + +``WRTCMP_stdlat2``: (Default: "") + Second standard latitude (in degrees) in definition of Lambert conformal projection. + +``WRTCMP_nx``: (Default: "") + Number of grid points in the x-coordinate of the Lambert conformal projection. + +``WRTCMP_ny``: (Default: "") + Number of grid points in the y-coordinate of the Lambert conformal projection. + +``WRTCMP_dx``: (Default: "") + Grid cell size (in meters) along the x-axis of the Lambert conformal projection. + +``WRTCMP_dy``: (Default: "") + Grid cell size (in meters) along the y-axis of the Lambert conformal projection. + +.. _PredefGrid: + +Predefined Grid Parameters +------------------------------ + +``PREDEF_GRID_NAME``: (Default: "") + This parameter indicates which (if any) predefined regional grid to use for the experiment. Setting ``PREDEF_GRID_NAME`` provides a convenient method of specifying a commonly used set of grid-dependent parameters. The predefined grid settings can be viewed in the script ``ush/set_predef_grid_params.yaml``. + + **Currently supported options:** + + | ``"RRFS_CONUS_25km"`` + | ``"RRFS_CONUS_13km"`` + | ``"RRFS_CONUS_3km"`` + | ``"SUBCONUS_Ind_3km"`` + **Other valid values include:** -``OMP_STACKSIZE_*``: (Default: see below) + | ``"CONUS_25km_GFDLgrid"`` + | ``"CONUS_3km_GFDLgrid"`` + | ``"EMC_AK"`` + | ``"EMC_HI"`` + | ``"EMC_PR"`` + | ``"EMC_GU"`` + | ``"GSL_HAFSV0.A_25km"`` + | ``"GSL_HAFSV0.A_13km"`` + | ``"GSL_HAFSV0.A_3km"`` + | ``"GSD_HRRR_AK_50km"`` + | ``"RRFS_AK_13km"`` + | ``"RRFS_AK_3km"`` + | ``"RRFS_CONUScompact_25km"`` + | ``"RRFS_CONUScompact_13km"`` + | ``"RRFS_CONUScompact_3km"`` + | ``"RRFS_NA_13km"`` + | ``"RRFS_NA_3km"`` + | ``"RRFS_SUBCONUS_3km"`` + | ``"WoFS_3km"`` - .. code-block:: console +.. note:: + + * If ``PREDEF_GRID_NAME`` is set to a valid predefined grid name, the grid generation method, the (native) grid parameters, and the write component grid parameters are set to predefined values for the specified grid, overwriting any settings of these parameters in the user-specified experiment configuration file (``config.yaml``). In addition, if the time step ``DT_ATMOS`` and the computational parameters (``LAYOUT_X``, ``LAYOUT_Y``, and ``BLOCKSIZE``) are not specified in that configuration file, they are also set to predefined values for the specified grid. - OMP_STACKSIZE_MAKE_OROG="2048m" - OMP_STACKSIZE_MAKE_SFC_CLIMO="1024m" - OMP_STACKSIZE_MAKE_ICS="1024m" - OMP_STACKSIZE_MAKE_LBCS="1024m" - OMP_STACKSIZE_RUN_FCST="1024m" - OMP_STACKSIZE_RUN_POST="1024m" + * If ``PREDEF_GRID_NAME`` is set to an empty string, it implies that the user will provide the native grid parameters in the user-specified experiment configuration file (``config.yaml``). In this case, the grid generation method, the native grid parameters, the write component grid parameters, the main time step (``DT_ATMOS``), and the computational parameters (``LAYOUT_X``, ``LAYOUT_Y``, and ``BLOCKSIZE``) must be set in the configuration file. Otherwise, the values of the parameters in the default experiment configuration file (``config_defaults.yaml``) will be used. +Aerosol Climatology Parameter +--------------------------------- + +``USE_MERRA_CLIMO``: (Default: false) + Flag that determines whether :term:`MERRA2` aerosol climatology data and lookup tables for optics properties are obtained. Valid values: ``True`` | ``False`` + + .. COMMENT: When would it be appropriate to obtain these files? + +Fixed File Parameters +------------------------- + +These parameters are associated with the fixed (i.e., static) files. On `Level 1 & 2 `__ systems, fixed files are pre-staged with paths defined in the ``setup.py`` script. Because the default values are platform-dependent, they are set to a null string in ``config_defaults.yaml``. Then these null values are overwritten in ``setup.py`` with machine-specific values or with a user-specified value from ``config.yaml``. + +``FIXgsm``: (Default: "") + System directory in which the majority of fixed (i.e., time-independent) files that are needed to run the FV3-LAM model are located. + +``FIXaer``: (Default: "") + System directory where :term:`MERRA2` aerosol climatology files are located. + +``FIXlut``: (Default: "") + System directory where the lookup tables for optics properties are located. + +``TOPO_DIR``: (Default: "") + The location on disk of the static input files used by the ``make_orog`` task (i.e., ``orog.x`` and ``shave.x``). Can be the same as ``FIXgsm``. + +``SFC_CLIMO_INPUT_DIR``: (Default: "") + The location on disk of the static surface climatology input fields, used by ``sfc_climo_gen``. These files are only used if ``RUN_TASK_MAKE_SFC_CLIMO: true``. + +``SYMLINK_FIX_FILES``: (Default: true) + Flag that indicates whether to symlink or copy fix files to the experiment directory. + +RUN_POST Configuration Parameters +===================================== + +Non-default parameters for the ``run_post`` task are set in the ``task_run_post:`` section of the ``config.yaml`` file. + +Basic Task Parameters +--------------------------------- + +For each workflow task, certain parameter values must be passed to the job scheduler (e.g., Slurm), which submits a job for the task. + +``RUN_POST_TN``: (Default: "run_post") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_RUN_POST``: (Default: 2) + Number of nodes to use for the job. + +``PPN_RUN_POST``: (Default: 24) + Number of :term:`MPI` processes per node. + +``WTIME_RUN_POST``: (Default: 00:15:00) + Maximum time for the task to complete. + +``MAXTRIES_RUN_POST``: (Default: 2) + Maximum number of times to attempt the task. + +``KMP_AFFINITY_RUN_POST``: (Default: "scatter") + Intel Thread Affinity Interface for the ``run_post`` task. See :ref:`this note ` for more information on thread affinity. + +``OMP_NUM_THREADS_RUN_POST``: (Default: 1) + The number of OpenMP threads to use for parallel regions. + +``OMP_STACKSIZE_RUN_POST``: (Default: "1024m") Controls the size of the stack for threads created by the OpenMP implementation. +Subhourly Post Parameters +----------------------------- +Set parameters associated with subhourly forecast model output and post-processing. + +``SUB_HOURLY_POST``: (Default: false) + Flag that indicates whether the forecast model will generate output files on a sub-hourly time interval (e.g., 10 minutes, 15 minutes). This will also cause the post-processor to process these sub-hourly files. If this variable is set to true, then ``DT_SUBHOURLY_POST_MNTS`` should be set to a valid value between 1 and 59. Valid values: ``True`` | ``False`` + +``DT_SUB_HOURLY_POST_MNTS``: (Default: 0) + Time interval in minutes between the forecast model output files (only used if ``SUB_HOURLY_POST`` is set to true). If ``SUB_HOURLY_POST`` is set to true, this needs to be set to a valid two-digit integer between 1 and 59. Note that if ``SUB_HOURLY_POST`` is set to true but ``DT_SUB_HOURLY_POST_MNTS`` is set to 0, ``SUB_HOURLY_POST`` will get reset to false in the experiment generation scripts (there will be an informational message in the log file to emphasize this). Valid values: ``0`` | ``1`` | ``2`` | ``3`` | ``4`` | ``5`` | ``6`` | ``10`` | ``12`` | ``15`` | ``20`` | ``30`` + +Customized Post Configuration Parameters +-------------------------------------------- + +Set parameters for customizing the :term:`UPP`. + +``USE_CUSTOM_POST_CONFIG_FILE``: (Default: false) + Flag that determines whether a user-provided custom configuration file should be used for post-processing the model data. If this is set to true, then the workflow will use the custom post-processing (:term:`UPP`) configuration file specified in ``CUSTOM_POST_CONFIG_FP``. Otherwise, a default configuration file provided in the UPP repository will be used. Valid values: ``True`` | ``False`` + +``CUSTOM_POST_CONFIG_FP``: (Default: "") + The full path to the custom post flat file, including filename, to be used for post-processing. This is only used if ``CUSTOM_POST_CONFIG_FILE`` is set to true. + +``POST_OUTPUT_DOMAIN_NAME``: (Default: "") + Domain name (in lowercase) used to construct the names of the output files generated by the :term:`UPP`. If using a predefined grid, ``POST_OUTPUT_DOMAIN_NAME`` defaults to ``PREDEF_GRID_NAME``. If using a custom grid, ``POST_OUTPUT_DOMAIN_NAME`` must be specified by the user. The post output files are named as follows: + + .. code-block:: console + + $NET.tHHz.[var_name].f###.${POST_OUTPUT_DOMAIN_NAME}.grib2 + + Note that this variable is first changed to lower case before being used to construct the file names. + +.. _get-obs-ccpa: + +GET_OBS_CCPA Configuration Parameters +======================================== + +Non-default parameters for the ``get_obs_ccpa`` task are set in the ``task_get_obs_ccpa:`` section of the ``config.yaml`` file. + +``GET_OBS_CCPA_TN``: (Default: "get_obs_ccpa") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. See :numref:`Section %s ` for more information about the verification tasks. + +``NNODES_GET_OBS_CCPA``: (Default: 1) + Number of nodes to use for the job. + +``PPN_GET_OBS_CCPA``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_GET_OBS_CCPA``: (Default: 00:45:00) + Maximum time for the task to complete. + +``MAXTRIES_GET_OBS_CCPA``: (Default: 1) + Maximum number of times to attempt the task. + +.. _get-obs-mrms: + +GET_OBS_MRMS Configuration Parameters +======================================== + +Non-default parameters for the ``get_obs_mrms`` task are set in the ``task_get_obs_mrms:`` section of the ``config.yaml`` file. See :numref:`Section %s ` for more information about the verification tasks. + +``GET_OBS_MRMS_TN``: (Default: "get_obs_mrms") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_GET_OBS_MRMS``: (Default: 1) + Number of nodes to use for the job. + +``PPN_GET_OBS_MRMS``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_GET_OBS_MRMS``: (Default: 00:45:00) + Maximum time for the task to complete. + +``MAXTRIES_GET_OBS_MRMS``: (Default: 1) + Maximum number of times to attempt the task. + +.. _get-obs-ndas: + +GET_OBS_NDAS Configuration Parameters +======================================== + +Non-default parameters for the ``get_obs_ndas`` task are set in the ``task_get_obs_ndas:`` section of the ``config.yaml`` file. See :numref:`Section %s ` for more information about the verification tasks. + +``GET_OBS_NDAS_TN``: (Default: "get_obs_ndas") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_GET_OBS_NDAS``: (Default: 1) + Number of nodes to use for the job. + +``PPN_GET_OBS_NDAS``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_GET_OBS_NDAS``: (Default: 02:00:00) + Maximum time for the task to complete. + +``MAXTRIES_GET_OBS_NDAS``: (Default: 1) + Maximum number of times to attempt the task. + + +.. _VX-gridstat: + +VX_GRIDSTAT Configuration Parameters +======================================== + +Non-default parameters for the ``run_gridstatvx`` task are set in the ``task_run_vx_gridstat:`` section of the ``config.yaml`` file. + +``VX_GRIDSTAT_TN``: (Default: "run_gridstatvx") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_GRIDSTAT``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_GRIDSTAT``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_GRIDSTAT``: (Default: 02:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_GRIDSTAT``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_GRIDSTAT_REFC Configuration Parameters +============================================= + +Non-default parameters for the ``run_gridstatvx_refc`` task are set in the ``task_run_vx_gridstat_refc:`` section of the ``config.yaml`` file. + +``VX_GRIDSTAT_REFC_TN``: (Default: "run_gridstatvx_refc") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_GRIDSTAT``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_GRIDSTAT``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_GRIDSTAT``: (Default: 02:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_GRIDSTAT_REFC``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_GRIDSTAT_RETOP Configuration Parameters +============================================= + +Non-default parameters for the ``run_gridstatvx_retop`` task are set in the ``task_run_vx_gridstat_retop:`` section of the ``config.yaml`` file. + +``VX_GRIDSTAT_RETOP_TN``: (Default: "run_gridstatvx_retop") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_GRIDSTAT``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_GRIDSTAT``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_GRIDSTAT``: (Default: 02:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_GRIDSTAT_RETOP``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_GRIDSTAT_03h Configuration Parameters +============================================= + +Non-default parameters for the ``run_gridstatvx_03h`` task are set in the ``task_run_vx_gridstat_03h:`` section of the ``config.yaml`` file. + +``VX_GRIDSTAT_03h_TN``: (Default: "run_gridstatvx_03h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_GRIDSTAT``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_GRIDSTAT``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_GRIDSTAT``: (Default: 02:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_GRIDSTAT_03h``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_GRIDSTAT_06h Configuration Parameters +============================================= + +Non-default parameters for the ``run_gridstatvx_06h`` task are set in the ``task_run_vx_gridstat_06h:`` section of the ``config.yaml`` file. + +``VX_GRIDSTAT_06h_TN``: (Default: "run_gridstatvx_06h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_GRIDSTAT``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_GRIDSTAT``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_GRIDSTAT``: (Default: 02:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_GRIDSTAT_06h``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_GRIDSTAT_24h Configuration Parameters +============================================= + +Non-default parameters for the ``run_gridstatvx_24h`` task are set in the ``task_run_vx_gridstat_24h:`` section of the ``config.yaml`` file. + +``VX_GRIDSTAT_24h_TN``: (Default: "run_gridstatvx_24h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_GRIDSTAT``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_GRIDSTAT``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_GRIDSTAT``: (Default: 02:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_GRIDSTAT_24h``: (Default: 1) + Maximum number of times to attempt the task. + +.. _VX-pointstat: + +VX_POINTSTAT Configuration Parameters +============================================= + +Non-default parameters for the ``run_pointstatvx`` task are set in the ``task_run_vx_pointstat:`` section of the ``config.yaml`` file. + +``VX_POINTSTAT_TN``: (Default: "run_pointstatvx") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_POINTSTAT``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_POINTSTAT``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_POINTSTAT``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_POINTSTAT``: (Default: 1) + Maximum number of times to attempt the task. + +.. _VX-ensgrid: + +VX_ENSGRID Configuration Parameters +============================================= + +Non-default parameters for the ``run_ensgridvx_*`` tasks are set in the ``task_run_vx_ensgrid:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_03h_TN``: (Default: "run_ensgridvx_03h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``MAXTRIES_VX_ENSGRID_03h``: (Default: 1) + Maximum number of times to attempt the task. + +``VX_ENSGRID_06h_TN``: (Default: "run_ensgridvx_06h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``MAXTRIES_VX_ENSGRID_06h``: (Default: 1) + Maximum number of times to attempt the task. + +``VX_ENSGRID_24h_TN``: (Default: "run_ensgridvx_24h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``MAXTRIES_VX_ENSGRID_24h``: (Default: 1) + Maximum number of times to attempt the task. + +``VX_ENSGRID_RETOP_TN``: (Default: "run_ensgridvx_retop") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``MAXTRIES_VX_ENSGRID_RETOP``: (Default: 1) + Maximum number of times to attempt the task. + +``VX_ENSGRID_PROB_RETOP_TN``: (Default: "run_ensgridvx_prob_retop") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``MAXTRIES_VX_ENSGRID_PROB_RETOP``: (Default: 1) + Maximum number of times to attempt the task. + +``NNODES_VX_ENSGRID``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSGRID_REFC Configuration Parameters +============================================= + +Non-default parameters for the ``run_ensgridvx_refc`` task are set in the ``task_run_vx_ensgrid_refc:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_REFC_TN``: (Default: "run_ensgridvx_refc") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSGRID``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID_REFC``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSGRID_MEAN Configuration Parameters +============================================= + +Non-default parameters for the ``run_ensgridvx_mean`` task are set in the ``task_run_vx_ensgrid_mean:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_MEAN_TN``: (Default: "run_ensgridvx_mean") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSGRID_MEAN``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID_MEAN``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID_MEAN``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID_MEAN``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSGRID_MEAN_03h Configuration Parameters +=============================================== + +Non-default parameters for the ``run_ensgridvx_mean_03h`` task are set in the ``task_run_vx_ensgrid_mean_03h:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_MEAN_03h_TN``: (Default: "run_ensgridvx_mean_03h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSGRID_MEAN``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID_MEAN``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID_MEAN``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID_MEAN_03h``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSGRID_MEAN_06h Configuration Parameters +=============================================== + +Non-default parameters for the ``run_ensgridvx_mean_06h`` task are set in the ``task_run_vx_ensgrid_mean_06h:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_MEAN_06h_TN``: (Default: "run_ensgridvx_mean_06h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSGRID_MEAN``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID_MEAN``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID_MEAN``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID_MEAN_06h``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSGRID_MEAN_24h Configuration Parameters +=============================================== + +Non-default parameters for the ``run_ensgridvx_mean_24h`` task are set in the ``task_run_vx_ensgrid_mean_24h:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_MEAN_24h_TN``: (Default: "run_ensgridvx_mean_24h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSGRID_MEAN``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID_MEAN``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID_MEAN``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID_MEAN_24h``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSGRID_PROB Configuration Parameters +============================================ + +Non-default parameters for the ``run_ensgridvx_prob`` task are set in the ``task_run_vx_ensgrid_prob:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_PROB_TN``: (Default: "run_ensgridvx_prob") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSGRID_PROB``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID_PROB``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID_PROB``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID_PROB``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSGRID_PROB_03h Configuration Parameters +================================================ + +Non-default parameters for the ``run_ensgridvx_prob_03h`` task are set in the ``task_run_vx_ensgrid_prob_03h:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_PROB_03h_TN``: (Default: "run_ensgridvx_prob_03h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSGRID_PROB``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID_PROB``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID_PROB``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID_PROB_03h``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSGRID_PROB_06h Configuration Parameters +================================================ + +Non-default parameters for the ``run_ensgridvx_prob_06h`` task are set in the ``task_run_vx_ensgrid_prob_06h:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_PROB_06h_TN``: (Default: "run_ensgridvx_prob_06h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSGRID_PROB``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID_PROB``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID_PROB``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID_PROB_06h``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSGRID_PROB_24h Configuration Parameters +================================================ + +Non-default parameters for the ``run_ensgridvx_prob_24h`` task are set in the ``task_run_vx_ensgrid_prob_24h:`` section of the ``config.yaml`` file. + +``VX_ENSGRID_PROB_24h_TN``: (Default: "run_ensgridvx_prob_24h") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSGRID_PROB``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSGRID_PROB``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSGRID_PROB``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSGRID_PROB_24h``: (Default: 1) + Maximum number of times to attempt the task. + +.. _VX-enspoint: + +VX_ENSPOINT Configuration Parameters +======================================== + +Non-default parameters for the ``run_enspointvx`` task are set in the ``task_run_vx_enspoint:`` section of the ``config.yaml`` file. + +``VX_ENSPOINT_TN``: (Default: "run_enspointvx") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSPOINT``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSPOINT``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSPOINT``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSPOINT``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSPOINT_MEAN Configuration Parameters +============================================== + +Non-default parameters for the ``run_enspointvx_mean`` task are set in the ``task_run_vx_enspoint_mean:`` section of the ``config.yaml`` file. + +``VX_ENSPOINT_MEAN_TN``: (Default: "run_enspointvx_mean") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSPOINT_MEAN``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSPOINT_MEAN``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSPOINT_MEAN``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSPOINT_MEAN``: (Default: 1) + Maximum number of times to attempt the task. + + +VX_ENSPOINT_PROB Configuration Parameters +============================================== + +Non-default parameters for the ``run_enspointvx_prob`` task are set in the ``task_run_vx_enspoint_prob:`` section of the ``config.yaml`` file. + +``VX_ENSPOINT_PROB_TN``: (Default: "run_enspointvx_prob") + Set the name of this Rocoto workflow task. Users typically do not need to change this value. + +``NNODES_VX_ENSPOINT_PROB``: (Default: 1) + Number of nodes to use for the job. + +``PPN_VX_ENSPOINT_PROB``: (Default: 1) + Number of :term:`MPI` processes per node. + +``WTIME_VX_ENSPOINT_PROB``: (Default: 01:00:00) + Maximum time for the task to complete. + +``MAXTRIES_VX_ENSPOINT_PROB``: (Default: 1) + Maximum number of times to attempt the task. + + +Global Configuration Parameters +=================================== + +Non-default parameters for the miscellaneous tasks are set in the ``global:`` section of the ``config.yaml`` file. + +Community Radiative Transfer Model (CRTM) Parameters +-------------------------------------------------------- + +These variables set parameters associated with outputting satellite fields in the :term:`UPP` :term:`grib2` files using the Community Radiative Transfer Model (:term:`CRTM`). :numref:`Section %s ` includes further instructions on how to do this. + +``USE_CRTM``: (Default: false) + Flag that defines whether external :term:`CRTM` coefficient files have been staged by the user in order to output synthetic satellite products available within the :term:`UPP`. If this is set to true, then the workflow will check for these files in the directory ``CRTM_DIR``. Otherwise, it is assumed that no satellite fields are being requested in the UPP configuration. Valid values: ``True`` | ``False`` + +``CRTM_DIR``: (Default: "") + This is the path to the top CRTM fix file directory. This is only used if ``USE_CRTM`` is set to true. + + +Ensemble Model Parameters +----------------------------- + +Set parameters associated with running ensembles. + +``DO_ENSEMBLE``: (Default: false) + Flag that determines whether to run a set of ensemble forecasts (for each set of specified cycles). If this is set to true, ``NUM_ENS_MEMBERS`` forecasts are run for each cycle, each with a different set of stochastic seed values. When false, a single forecast is run for each cycle. Valid values: ``True`` | ``False`` + +``NUM_ENS_MEMBERS``: (Default: 1) + The number of ensemble members to run if ``DO_ENSEMBLE`` is set to true. This variable also controls the naming of the ensemble member directories. For example, if ``NUM_ENS_MEMBERS`` is set to 8, the member directories will be named *mem1, mem2, ..., mem8*. This variable is not used unless ``DO_ENSEMBLE`` is set to true. + +.. _stochastic-physics: + +Stochastic Physics Parameters +---------------------------------- + +Set default ad-hoc stochastic physics options. For the most updated and detailed documentation of these parameters, see the `UFS Stochastic Physics Documentation `__. + +``NEW_LSCALE``: (Default: true) + Use correct formula for converting a spatial legnth scale into spectral space. + +Specific Humidity (SHUM) Perturbation Parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``DO_SHUM``: (Default: false) + Flag to turn Specific Humidity (SHUM) perturbations on or off. SHUM perturbations multiply the low-level specific humidity by a small random number at each time-step. The SHUM scheme attempts to address missing physics phenomena (e.g., cold pools, gust fronts) most active in convective regions. Valid values: ``True`` | ``False`` + +``ISEED_SHUM``: (Default: 2) + Seed for setting the SHUM random number sequence. + +``SHUM_MAG``: (Default: 0.006) + Amplitudes of random patterns. Corresponds to the variable ``shum`` in ``input.nml``. + +``SHUM_LSCALE``: (Default: 150000) + Decorrelation spatial scale in meters. + +``SHUM_TSCALE``: (Default: 21600) + Decorrelation timescale in seconds. Corresponds to the variable ``shum_tau`` in ``input.nml``. + +``SHUM_INT``: (Default: 3600) + Interval in seconds to update random pattern (optional). Perturbations still get applied at every time-step. Corresponds to the variable ``shumint`` in ``input.nml``. + +.. _SPPT: + +Stochastically Perturbed Physics Tendencies (SPPT) Parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +SPPT perturbs full physics tendencies *after* the call to the physics suite, unlike :ref:`SPP ` (below), which perturbs specific tuning parameters within a physics scheme. + +``DO_SPPT``: (Default: false) + Flag to turn Stochastically Perturbed Physics Tendencies (SPPT) on or off. SPPT multiplies the physics tendencies by a random number between 0 and 2 before updating the model state. This addresses error in the physics parameterizations (either missing physics or unresolved subgrid processes). It is most active in the boundary layer and convective regions. Valid values: ``True`` | ``False`` + +``ISEED_SPPT``: (Default: 1) + Seed for setting the SPPT random number sequence. + +``SPPT_MAG``: (Default: 0.7) + Amplitude of random patterns. Corresponds to the variable ``sppt`` in ``input.nml``. + +``SPPT_LOGIT``: (Default: true) + Limits the SPPT perturbations to between 0 and 2. Should be "TRUE"; otherwise the model will crash. + +``SPPT_LSCALE``: (Default: 150000) + Decorrelation spatial scale in meters. + +``SPPT_TSCALE``: (Default: 21600) + Decorrelation timescale in seconds. Corresponds to the variable ``sppt_tau`` in ``input.nml``. + +``SPPT_INT``: (Default: 3600) + Interval in seconds to update random pattern (optional parameter). Perturbations still get applied at every time-step. Corresponds to the variable ``spptint`` in ``input.nml``. + +``SPPT_SFCLIMIT``: (Default: true) + When true, tapers the SPPT perturbations to zero at the model's lowest level, which reduces model crashes. + +``USE_ZMTNBLCK``: (Default: false) + When true, do not apply perturbations below the dividing streamline that is diagnosed by the gravity wave drag, mountain blocking scheme. Valid values: ``True`` | ``False`` + + +Stochastic Kinetic Energy Backscatter (SKEB) Parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``DO_SKEB``: (Default: false) + Flag to turn Stochastic Kinetic Energy Backscatter (SKEB) on or off. SKEB adds wind perturbations to the model state. Perturbations are random in space/time, but amplitude is determined by a smoothed dissipation estimate provided by the :term:`dynamical core`. SKEB addresses errors in the dynamics more active in the mid-latitudes. Valid values: ``True`` | ``False`` + +``ISEED_SKEB``: (Default: 3) + Seed for setting the SHUM random number sequence. + +``SKEB_MAG``: (Default: 0.5) + Amplitude of random patterns. Corresponds to the variable ``skeb`` in ``input.nml``. + +``SKEB_LSCALE``: (Default: 150000) + Decorrelation spatial scale in meters. + +``SKEB_TSCALE``: (Default: 21600) + Decorrelation timescale in seconds. Corresponds to the variable ``skeb_tau`` in ``input.nml``. + +``SKEB_INT``: (Default: 3600) + Interval in seconds to update random pattern (optional). Perturbations still get applied every time-step. Corresponds to the variable ``skebint`` in ``input.nml``. + +``SKEBNORM``: (Default: 1) + Patterns: + * 0-random pattern is stream function + * 1-pattern is K.E. norm + * 2-pattern is vorticity + +``SKEB_VDOF``: (Default: 10) + The number of degrees of freedom in the vertical direction for the SKEB random pattern. + + +.. _SPP: + +Parameters for Stochastically Perturbed Parameterizations (SPP) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +SPP perturbs specific tuning parameters within a physics :term:`parameterization ` (unlike :ref:`SPPT `, which multiplies overall physics tendencies by a random perturbation field *after* the call to the physics suite). Patterns evolve and are applied at each time step. Each SPP option is an array, applicable (in order) to the :term:`RAP`/:term:`HRRR`-based parameterization listed in ``SPP_VAR_LIST``. Enter each value of the array in ``config.yaml`` as shown below without commas or single quotes (e.g., ``SPP_VAR_LIST: [ "pbl" "sfc" "mp" "rad" "gwd" ]`` ). Both commas and single quotes will be added by Jinja when creating the namelist. + +.. note:: + SPP is currently only available for specific physics schemes used in the RAP/HRRR physics suite. Users need to be aware of which :term:`SDF` is chosen when turning this option on. Of the four supported physics suites, the full set of parameterizations can only be used with the ``FV3_HRRR`` option for ``CCPP_PHYS_SUITE``. + +``DO_SPP``: (Default: false) + Flag to turn SPP on or off. SPP perturbs parameters or variables with unknown or uncertain magnitudes within the physics code based on ranges provided by physics experts. Valid values: ``True`` | ``False`` + +``ISEED_SPP``: (Default: [ 4, 5, 6, 7, 8 ] ) + Seed for setting the random number sequence for the perturbation pattern. + +``SPP_VAR_LIST``: (Default: [ "pbl", "sfc", "mp", "rad", "gwd" ] ) + The list of parameterizations to perturb: planetary boundary layer (PBL), surface physics (SFC), microphysics (MP), radiation (RAD), gravity wave drag (GWD). Valid values: ``"pbl"`` | ``"sfc"`` | ``"rad"`` | ``"gwd"`` | ``"mp"`` + +``SPP_MAG_LIST``: (Default: [ 0.2, 0.2, 0.75, 0.2, 0.2 ] ) + SPP perturbation magnitudes used in each parameterization. Corresponds to the variable ``spp_prt_list`` in ``input.nml`` + +``SPP_LSCALE``: (Default: [ 150000.0, 150000.0, 150000.0, 150000.0, 150000.0 ] ) + Decorrelation spatial scales in meters. + +``SPP_TSCALE``: (Default: [ 21600.0, 21600.0, 21600.0, 21600.0, 21600.0 ] ) + Decorrelation timescales in seconds. Corresponds to the variable ``spp_tau`` in ``input.nml``. + +``SPP_SIGTOP1``: (Default: [ 0.1, 0.1, 0.1, 0.1, 0.1 ] ) + Controls vertical tapering of perturbations at the tropopause and corresponds to the lower sigma level at which to taper perturbations to zero. + +``SPP_SIGTOP2``: (Default: [ 0.025, 0.025, 0.025, 0.025, 0.025 ] ) + Controls vertical tapering of perturbations at the tropopause and corresponds to the upper sigma level at which to taper perturbations to zero. + +``SPP_STDDEV_CUTOFF``: (Default: [ 1.5, 1.5, 2.5, 1.5, 1.5 ] ) + Limit for possible perturbation values in standard deviations from the mean. + + +Land Surface Model (LSM) SPP +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Land surface perturbations can be applied to land model parameters and land model prognostic variables. The LSM scheme is intended to address errors in the land model and land-atmosphere interactions. LSM perturbations include soil moisture content (SMC) (volume fraction), vegetation fraction (VGF), albedo (ALB), salinity (SAL), emissivity (EMI), surface roughness (ZOL) (in cm), and soil temperature (STC). Perturbations to soil moisture content (SMC) are only applied at the first time step. Only five perturbations at a time can be applied currently, but all seven are shown below. In addition, only one unique *iseed* value is allowed at the moment, and it is used for each pattern. + +The parameters below turn on SPP in Noah or RUC LSM (support for Noah MP is in progress). Please be aware of the :term:`SDF` that you choose if you wish to turn on Land Surface Model (LSM) SPP. SPP in LSM schemes is handled in the ``&nam_sfcperts`` namelist block instead of in ``&nam_sppperts``, where all other SPP is implemented. + +``DO_LSM_SPP``: (Default: false) + Turns on Land Surface Model (LSM) Stochastic Physics Parameterizations (SPP). When true, sets ``lndp_type=2``, which applies land perturbations to the selected paramaters using a newer scheme designed for data assimilation (DA) ensemble spread. LSM SPP perturbs uncertain land surface fields ("smc" "vgf" "alb" "sal" "emi" "zol" "stc") based on recommendations from physics experts. Valid values: ``True`` | ``False`` + +``LSM_SPP_TSCALE``: (Default: [ 21600, 21600, 21600, 21600, 21600, 21600, 21600 ] ) + Decorrelation timescales in seconds. + +``LSM_SPP_LSCALE``: (Default: [ 150000, 150000, 150000, 150000, 150000, 150000, 150000 ] ) + Decorrelation spatial scales in meters. + +``ISEED_LSM_SPP``: (Default: [ 9 ] ) + Seed to initialize the random perturbation pattern. + +``LSM_SPP_VAR_LIST``: (Default: [ "smc", "vgf", "alb", "sal", "emi", "zol", "stc" ] ) + Indicates which LSM variables to perturb. + +``LSM_SPP_MAG_LIST``: (Default: [ 0.017, 0.001, 0.001, 0.001, 0.001, 0.001, 0.2 ] ) + Sets the maximum random pattern amplitude for each of the LSM perturbations. + +.. COMMENT: This variable no longer appears and was going to be removed. See if anything has replaced it. + ``LSM_SPP_EACH_STEP``: (Default: "true") + When set to "TRUE", it sets ``lndp_each_step=.true.`` and perturbs each time step. + + +.. _HaloBlend: + +Halo Blend Parameter +------------------------ +``HALO_BLEND``: (Default: 10) + Number of cells to use for "blending" the external solution (obtained from the :term:`LBCs`) with the internal solution from the FV3LAM :term:`dycore`. Specifically, it refers to the number of rows into the computational domain that should be blended with the LBCs. Cells at which blending occurs are all within the boundary of the native grid; they don't involve the 4 cells outside the boundary where the LBCs are specified (which is a different :term:`halo`). Blending is necessary to smooth out waves generated due to mismatch between the external and internal solutions. To shut :term:`halo` blending off, set this to zero. + diff --git a/docs/UsersGuide/source/ContainerQuickstart.rst b/docs/UsersGuide/source/ContainerQuickstart.rst index 229db0a6eb..8b72c079e5 100644 --- a/docs/UsersGuide/source/ContainerQuickstart.rst +++ b/docs/UsersGuide/source/ContainerQuickstart.rst @@ -4,14 +4,14 @@ Container-Based Quick Start Guide ==================================== -This Container-Based Quick Start Guide will help users build and run the "out-of-the-box" case for the Unified Forecast System (:term:`UFS`) Short-Range Weather (SRW) Application using a `Singularity `__ container. The :term:`container` approach provides a uniform enviroment in which to build and run the SRW App. Normally, the details of building and running the SRW App vary from system to system due to the many possible combinations of operating systems, compilers, :term:`MPI`'s, and package versions available. Installation via Singularity container reduces this variability and allows for a smoother SRW App build experience. Normally, containers can only run on a single compute node and are not compatible with the `Rocoto workflow manager `__, so users must run each task in the workflow manually. However, the Singularity container described in this chapter has been adapted such that it is able to run across multiple nodes using Rocoto. This makes it an excellent starting point for beginners. The :ref:`non-container approach ` may still be more appropriate for users who desire additional customizability, particularly if they already have experience running the SRW App. +This Container-Based Quick Start Guide will help users build and run the "out-of-the-box" case for the Unified Forecast System (:term:`UFS`) Short-Range Weather (SRW) Application using a `Singularity `__ container. The :term:`container` approach provides a uniform enviroment in which to build and run the SRW App. Normally, the details of building and running the SRW App vary from system to system due to the many possible combinations of operating systems, compilers, :term:`MPI`'s, and package versions available. Installation via Singularity container reduces this variability and allows for a smoother SRW App build experience. Normally, containers can only run on a single compute node and are not compatible with the `Rocoto workflow manager `__, so users must run each task in the workflow manually. However, the Singularity container described in this chapter has been adapted such that it is able to run across multiple nodes using Rocoto. This makes it an excellent starting point for beginners. The :ref:`non-container build approach ` may still be more appropriate for users who desire additional customizability, particularly if they already have experience running the SRW App. The "out-of-the-box" SRW App case described in this User's Guide builds a weather forecast for June 15-16, 2019. Multiple convective weather events during these two days produced over 200 filtered storm reports. Severe weather was clustered in two areas: the Upper Midwest through the Ohio Valley and the Southern Great Plains. This forecast uses a predefined 25-km Continental United States (:term:`CONUS`) grid (RRFS_CONUS_25km), the Global Forecast System (:term:`GFS`) version 16 physics suite (FV3_GFS_v16 :term:`CCPP`), and :term:`FV3`-based GFS raw external model data for initialization. .. attention:: * The SRW Application has `four levels of support `__. The steps described in this chapter will work most smoothly on preconfigured (Level 1) systems. However, this guide can serve as a starting point for running the SRW App on other systems, too. - * This chapter of the User's Guide should **only** be used for container builds. For non-container builds, see :numref:`Chapter %s ` for a Quick Start Guide or :numref:`Chapter %s ` for a detailed guide to building the SRW App **without** a container. + * This chapter of the User's Guide should **only** be used for container builds. For non-container builds, see :numref:`Chapter %s ` for a Quick Start Guide or :numref:`Chapter %s ` for a detailed guide to building the SRW App **without** a container. .. _DownloadCodeC: @@ -247,7 +247,7 @@ To activate the regional workflow, run the following commands: where: * ```` is replaced with the actual path to the modulefiles on the user's system (often ``$PWD/modulefiles``), and - * ```` is a valid, lowercased machine/platform name (see the ``MACHINE`` variable in :numref:`Section %s `). + * ```` is a valid, lowercased machine/platform name (see the ``MACHINE`` variable in :numref:`Section %s `). The ``wflow_`` modulefile will then output instructions to activate the regional workflow. The user should run the commands specified in the modulefile output. For example, if the output says: @@ -273,7 +273,7 @@ where: * ``-c`` indicates the compiler on the user's local machine (e.g., ``intel/2022.1.2``) * ``-m`` indicates the :term:`MPI` on the user's local machine (e.g., ``impi/2022.1.2``) - * ```` refers to the local machine (e.g., ``hera``, ``jet``, ``noaacloud``, ``mac``). See ``MACHINE`` in :numref:`Section %s ` for a full list of options. + * ```` refers to the local machine (e.g., ``hera``, ``jet``, ``noaacloud``, ``mac``). See ``MACHINE`` in :numref:`Section %s ` for a full list of options. * ``-i`` indicates the name of the container image that was built in :numref:`Step %s ` (``ubuntu20.04-intel-srwapp`` or ``ubuntu20.04-intel-srwapp-develop.img`` by default). For example, on Hera, the command would be: @@ -299,7 +299,7 @@ From here, users can follow the steps below to configure the out-of-the-box SRW The default settings include a predefined 25-km :term:`CONUS` grid (RRFS_CONUS_25km), the :term:`GFS` v16 physics suite (FV3_GFS_v16 :term:`CCPP`), and :term:`FV3`-based GFS raw external model data for initialization. - #. Edit the ``MACHINE`` and ``ACCOUNT`` variables in the ``user:`` section of ``config.yaml``. See :numref:`Section %s ` for details on valid values. + #. Edit the ``MACHINE`` and ``ACCOUNT`` variables in the ``user:`` section of ``config.yaml``. See :numref:`Section %s ` for details on valid values. .. note:: @@ -326,7 +326,7 @@ From here, users can follow the steps below to configure the out-of-the-box SRW EXTRN_MDL_FILES_ICS: [] EXTRN_MDL_DATA_STORES: disk - On other systems, users will need to change the path for ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_FILES_LBCS`` (below) to reflect the location of the system's data. The location of the machine's global data can be viewed :ref:`here ` for Level 1 systems. Alternatively, the user can add the path to their local data if they downloaded it as described in :numref:`Section %s `. + On other systems, users will need to change the path for ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_FILES_LBCS`` (below) to reflect the location of the system's data. The location of the machine's global data can be viewed :ref:`here ` for Level 1 systems. Alternatively, the user can add the path to their local data if they downloaded it as described in :numref:`Section %s `. #. Edit the ``task_get_extrn_lbcs:`` section of the ``config.yaml`` to include the correct data paths to the lateral boundary conditions files. For example, on Hera, add: diff --git a/docs/UsersGuide/source/ContributorsGuide.rst b/docs/UsersGuide/source/ContributorsGuide.rst index f63bf3d447..efb90ca4cc 100644 --- a/docs/UsersGuide/source/ContributorsGuide.rst +++ b/docs/UsersGuide/source/ContributorsGuide.rst @@ -13,7 +13,7 @@ Background Authoritative branch ----------------------- -The ``ufs-srweather-app`` and ``regional_workflow`` repositories each maintain a main branch for development called ``develop``. The HEAD of ``develop`` reflects the latest development changes. It points to regularly updated hashes for individual sub-components. Pull requests (PRs) will be merged to ``develop``. +The ``ufs-srweather-app`` repository maintains a main branch for development called ``develop``. The HEAD of ``develop`` reflects the latest development changes. It points to regularly updated hashes for individual sub-components. Pull requests (PRs) will be merged to ``develop``. The ``develop`` branch is protected by the code management team: #. Pull requests for this branch require approval by at least two code reviewers. @@ -52,7 +52,7 @@ Scientists from across multiple labs and organizations have volunteered to revie +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ | GSL | Jeff Beck (@JeffBeck-NOAA) | SRW App configuration/workflow, code management, meteorological evaluation | | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Gerard Ketefian (@gsketefian) | ``regional_workflow`` scripts, jinja templates, and verification tasks | + | | Gerard Ketefian (@gsketefian) | regional workflow scripts, jinja templates, and verification tasks | | +------------------------------------------------+---------------------------------------------------------------------------------------------+ | | Linlin Pan (@panll) | Workflow, CCPP/physics, verification | | +------------------------------------------------+---------------------------------------------------------------------------------------------+ @@ -64,7 +64,7 @@ Scientists from across multiple labs and organizations have volunteered to revie +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ | NCAR | Mike Kavulich (@mkavulich) | CCPP/physics | | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Will Mayfield (@willmayfield) | Verification/METplus tasks, regional_workflow (esp. on Cheyenne) | + | | Will Mayfield (@willmayfield) | Verification/METplus tasks, regional workflow (esp. on Cheyenne) | +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ | NSSL | Yunheng Wang (@ywangwof) | HPC systems, code management and regional workflow especially on Stampede, Jet | | | | and NSSL computers | @@ -75,7 +75,7 @@ Scientists from across multiple labs and organizations have volunteered to revie Contribution Process ======================== -The steps below should be followed in order to make changes to the ``develop`` branch of the ``ufs-srweather-app`` or ``regional_workflow`` repositories. Communication with code managers and the code management team throughout the process is encouraged. +The steps below should be followed in order to make changes to the ``develop`` branch of the ``ufs-srweather-app`` repository. Communication with code managers and the code management team throughout the process is encouraged. #. **Issue** - Open an issue to document changes. Click `here `__ to open a new ``ufs-srweather-app`` issue or see :numref:`Step %s ` for detailed instructions. #. **GitFlow** - Follow `GitFlow `__ procedures for development. @@ -99,9 +99,9 @@ The steps below should be followed in order to make changes to the ``develop`` b Opening an Issue ------------------- -All changes should be associated with a GitHub Issue. If developers are working on a change, they should search the existing issues in the appropriate repository (``ufs-srweather-app`` and/or ``regional_workflow``). If an issue does not exist for the work they are doing, they should create one prior to opening a new pull request. +All changes should be associated with a GitHub Issue. If developers are working on a change, they should search the existing issues in the ``ufs-srweather-app`` repository. If an issue does not exist for the work they are doing, they should create one prior to opening a new pull request. -To open an issue, click on `New Issue `__ within the ``ufs-srweather-app`` GitHub repository and/or within the ``regional_workflow`` repository (depending on where the changes will be made). +To open an issue, click on `New Issue `__ within the ``ufs-srweather-app`` GitHub repository. Choose from three options: #. `Bug Report `__: Report specific problems ("bugs") in the code using the following template: @@ -217,9 +217,9 @@ Pull requests will be reviewed and approved by at least two code reviewers, at l .. note:: - * If a developer wants to make use of automated testing, any ``ufs-srweather-app`` + ``regional_workflow`` dependencies must be opened in PRs from dependent branches of forks belonging to the same user. - * The ``Externals.cfg`` file should point to any dependent branches in ``regional_workflow`` (and other components, if necessary) while those branches are under review. Once the corresponding ``regional_workflow`` PR has been merged, the developer should update the references in their ``Externals.cfg`` file to reflect the appropriate hashes in the authoritative repositories. - * Developers should mention in their ``ufs-srweather-app`` PR description that they are temporarily pointing to a branch/hash in their fork of ``regional_workflow`` and that it will be updated once the corresponding ``regional_workflow`` PR is merged. + * If a developer wants to make use of automated testing, any ``ufs-srweather-app`` dependencies must be opened in PRs from dependent branches of forks belonging to the same user. + * The ``Externals.cfg`` file should point to any dependent branches in component repositories while those branches are under review. Once the PR has been merged in the dependent repository, the developer should update the references in their ``Externals.cfg`` file to reflect the appropriate hashes in the authoritative repositories. + * Developers should mention in their ``ufs-srweather-app`` PR description that they are temporarily pointing to a branch/hash in their fork of a component repository and that it will be updated once the corresponding PR is merged. .. _Template: @@ -369,32 +369,30 @@ General * For changes to the ``scripts``, ``ush``, or ``jobs`` directories, developers should follow the `NCO Guidelines `__ for what is incorporated into each layer. * Developers should ensure that their contributions work with the most recent version of the ``ufs-srweather-app``, including all the specific up-to-date hashes of each subcomponent. * Modifications should not break any existing supported capabilities on any supported platforms. -* Update the ``.rst`` documentation files where appropriate as part of the PR. The documentation files reside in ``ufs-srweather-app``, so changes to ``regional_workflow`` that require documentation need a corresponding PR to ``ufs-srweather-app``. If necessary, contributors may update the documentation in a subsequent PR. In these cases, the contributor should open an issue reflecting the need for documentation (see :numref:`Step %s `) and include the issue number and explanation in the Documentation section of their initial PR. +* Update the ``.rst`` documentation files where appropriate as part of the PR. The documentation files reside in ``ufs-srweather-app/docs``. If necessary, contributors may update the documentation in a subsequent PR. In these cases, the contributor should open an issue reflecting the need for documentation (see :numref:`Step %s `) and include the issue number and explanation in the Documentation section of their initial PR. SRW Application ------------------ -Externals.cfg +**Externals.cfg** * All externals live in a single ``Externals.cfg`` file. * Only a single hash will be maintained for any given external code base. All externals should point to this static hash (not to the top of a branch). * All new entries in ``Externals.cfg`` must point only to authoritative repositories. In other words, entries must point to either a `UFS Community GitHub organization `__ repository or another NOAA project organization repository. - * Temporary exceptions are made for a PR into the ``develop`` branch of ``ufs-srweather-app`` that is dependent on another PR (e.g., a ``regional_workflow`` PR from the same contributor). When the component PR is merged, the contributor must update the corresponding ``ufs-srweather-app`` PR with the hash of the component's authoritative repository. + * Temporary exceptions are made for a PR into the ``develop`` branch of ``ufs-srweather-app`` that is dependent on another PR (e.g., a ``ufs-weather-model`` PR from the same contributor). When the component PR is merged, the contributor must update the corresponding ``ufs-srweather-app`` PR with the hash of the component's authoritative repository. -Build system +**Build System** * Each component must build with CMake * Each component must build with Intel compilers on official `Level 1 `__ platforms and with GNU or Intel compilers on other platforms. * Each component must have a mechanism for platform independence (i.e., no hard-coded machine-specific settings outside of established environment, configuration, and modulefiles). * Each component must build using the standard supported NCEPLIBS environment (currently `HPC-Stack `__). -Modulefiles +**Modulefiles** * Each component must build using the common modules located in the ``modulefiles/srw_common`` file. - Regional Workflow ----------------------- -If changes are made to ``regional_workflow``, a corresponding PR to ``ufs-srweather-app`` should be opened to update the ``regional_workflow`` hash. +-------------------- **General Coding Standards:** * The ``regional_workflow`` repository must not contain source code for compiled programs. Only scripts and configuration files should reside in this repository. @@ -414,7 +412,7 @@ If changes are made to ``regional_workflow``, a corresponding PR to ``ufs-srweat **Management of Template Files:** If a new configurable option is required in an existing template, it must be handled similarly to its counterparts in the scripts that fill in the template. For example, if a new type of namelist is introduced for a new application component, it should make use of the existing ``jinja`` framework for populating namelist settings. -**Namelist Management:** Namelists in ``ufs-srweather-app`` and ``regional_workflow`` are generated using a Python tool and managed by setting YAML configuration parameters. This allows for the management of multiple configuration settings with maximum flexibility and minimum duplication of information. +**Namelist Management:** Namelists in ``ufs-srweather-app`` are generated using a Python tool and managed by setting YAML configuration parameters. This allows for the management of multiple configuration settings with maximum flexibility and minimum duplication of information. .. _Testing: diff --git a/docs/UsersGuide/source/FAQ.rst b/docs/UsersGuide/source/FAQ.rst index 7d2a212dd8..69e171d69c 100644 --- a/docs/UsersGuide/source/FAQ.rst +++ b/docs/UsersGuide/source/FAQ.rst @@ -22,7 +22,7 @@ grid, orography, and surface climatology files that these tasks generate are alr available (e.g., from a previous experiment that used the same grid as the current experiment), then these tasks can be skipped, and the workflow can use those pre-generated files. This can be done by adding the following lines to the ``config.sh`` script before running -the ``generate_FV3LAM_wflow.sh`` script: +the ``generate_FV3LAM_wflow.py`` script: .. code-block:: console @@ -57,7 +57,7 @@ How do I change the Physics Suite Definition File (SDF)? ========================================================= The SDF is set in the ``config.sh`` file using the variable ``CCPP_PHYS_SUITE``. When users run the -``generate_FV3LAM_wflow.sh`` script, the SDF file is copied from its location in the forecast +``generate_FV3LAM_wflow.py`` script, the SDF file is copied from its location in the forecast model directory to the experiment directory ``EXPTDIR``. For more information on the :term:`CCPP` physics suite parameters, see :numref:`Section %s ` .. _RestartTask: diff --git a/docs/UsersGuide/source/Glossary.rst b/docs/UsersGuide/source/Glossary.rst index 0d48c55237..f7de1fe3f9 100644 --- a/docs/UsersGuide/source/Glossary.rst +++ b/docs/UsersGuide/source/Glossary.rst @@ -12,6 +12,9 @@ Glossary advection According to the American Meteorological Society (AMS) `definition `__, advection is "The process of transport of an atmospheric property solely by the mass motion (velocity field) of the atmosphere." In common parlance, advection is movement of atmospheric substances that are carried around by the wind. + AQM + The `Air Quality Model `__ (AQM) is a UFS Application that dynamically couples the Community Multiscale Air Quality (:term:`CMAQ`) model with the UFS Weather Model through the :term:`NUOPC` Layer to simulate temporal and spatial variations of atmospheric compositions (e.g., ozone and aerosol compositions). The CMAQ, treated as a column chemistry model, updates concentrations of chemical species (e.g., ozone and aerosol compositions) at each integration time step. The transport terms (e.g., :term:`advection` and diffusion) of all chemical species are handled by the UFS Weather Model as :term:`tracers`. + CAPE Convective Available Potential Energy. @@ -28,6 +31,9 @@ Glossary CIN Convective Inhibition. + CMAQ + The `Community Multiscale Air Quality Model `__ (CMAQ, pronounced "cee-mak") is a numerical air quality model that predicts the concentration of airborne gases and particles and the deposition of these pollutants back to Earth's surface. The purpose of CMAQ is to provide fast, technically sound estimates of ozone, particulates, toxics, and acid deposition. CMAQ is an active open-source development project of the U.S. Environmental Protection Agency (EPA). Code is publicly availably at https://github.com/USEPA/CMAQ. + cron crontab cron table @@ -93,6 +99,12 @@ Glossary GRIB2 The second version of the World Meterological Organization's (WMO) standard for distributing gridded data. + GSI + `Gridpoint Statistical Interpolation `__ (GSI) is a variational data assimilation system, designed to be flexible, state-of-art, and run efficiently on various parallel computing platforms. It supports :term:`RRFS` features. GSI code is publicly available `on GitHub `__, and fix file data is publicly available `here `__. + + GSL + NOAA `Global Systems Laboratory `__ is one of ten NOAA Research laboratories and is located in Boulder, Colorado. Its research improves environmental prediction models, develops state-of-the-science decision support tools and visualization systems, and uses high-performance computing technology to support a Weather-Ready Nation. + halo A strip of cells on the edge of the regional grid. The :ref:`wide halo ` surrounds the regional grid and is used to feed the lateral boundary conditions into the grid. The :ref:`HALO_BLEND ` parameter refers to a strip of cells *inside* the boundary of the native grid. This halo smooths out mismatches between the external and internal solutions. @@ -167,6 +179,9 @@ Glossary netCDF NetCDF (`Network Common Data Form `__) is a file format and community standard for storing multidimensional scientific data. It includes a set of software libraries and machine-independent data formats that support the creation, access, and sharing of array-oriented scientific data. + NSSL + The `National Severe Storms Laboratory `__. + NUOPC The `National Unified Operational Prediction Capability `__ Layer "defines conventions and a set of generic components for building coupled models using the Earth System Modeling Framework (:term:`ESMF`)." @@ -185,6 +200,9 @@ Glossary Repository A central location in which files (e.g., data, code, documentation) are stored and managed. + RRFS + The `Rapid Refresh Forecast System `__ is NOAA's next-generation convection-allowing, rapidly-updated, ensemble-based data assimilation and forecasting system currently scheduled for operational implementation in 2024. It is designed to run forecasts on a 3-km :term:`CONUS` domain. + SDF Suite Definition File. An external file containing information about the construction of a physics suite. It describes the schemes that are called, in which order they are called, whether they are subcycled, and whether they are assembled into groups to be called together. diff --git a/docs/UsersGuide/source/Graphics.rst b/docs/UsersGuide/source/Graphics.rst index 259892e73c..945ee13569 100644 --- a/docs/UsersGuide/source/Graphics.rst +++ b/docs/UsersGuide/source/Graphics.rst @@ -17,7 +17,7 @@ output over the :term:`CONUS` for a number of variables, including: * Max/Min 2-5 km updraft helicity * Sea level pressure (SLP) -The Python scripts are located under ``ufs-srweather-app/regional_workflow/ush/Python``. +The Python scripts are located under ``ufs-srweather-app/ush/Python``. The script ``plot_allvars.py`` plots the output from a single cycle within an experiment, while the script ``plot_allvars_diff.py`` plots the difference between the same cycle from two different experiments (e.g., the experiments may differ in some aspect such as the physics suite used). If @@ -126,7 +126,7 @@ scripts: .. code-block:: console - cd ufs-srweather-app/regional_workflow/ush/Python + cd ufs-srweather-app/ush/Python Plotting Output from One Experiment -------------------------------------- @@ -146,7 +146,7 @@ following command line arguments: If a forecast starts at 18h, this is considered the 0th forecast hour, so "starting forecast hour" should be 0, not 18. An example of plotting output from a cycle generated using the sample experiment/workflow -configuration in the ``config.community.sh`` script (which uses the GFSv16 suite definition file) +configuration in the ``config.community.yaml`` script (which uses the GFSv16 suite definition file) is as follows: .. code-block:: console @@ -185,7 +185,7 @@ In this case, the output ``.png`` files will be located in the directory ``$EXPT Submitting Plotting Scripts Through a Batch System ====================================================== -If users plan to create plots of multiple forecast lead times and forecast variables, then they may need to submit the Python scripts to the batch system. Sample scripts are provided for use on a platform such as Hera that uses the Slurm job scheduler: ``sq_job.sh`` and ``sq_job_diff.sh``. Equivalent sample scripts are provided for use on a platform such as Cheyenne that uses PBS as the job scheduler: ``qsub_job.sh`` and ``qsub_job_diff.sh``. Examples of these scripts are located under ``ufs-srweather-app/regional_workflow/ush/Python`` and can be used as a starting point to create a batch script for the user's specific platform/job scheduler. +If users plan to create plots of multiple forecast lead times and forecast variables, then they may need to submit the Python scripts to the batch system. Sample scripts are provided for use on a platform such as Hera that uses the Slurm job scheduler: ``sq_job.sh`` and ``sq_job_diff.sh``. Equivalent sample scripts are provided for use on a platform such as Cheyenne that uses PBS as the job scheduler: ``qsub_job.sh`` and ``qsub_job_diff.sh``. Examples of these scripts are located under ``ufs-srweather-app/ush/Python`` and can be used as a starting point to create a batch script for the user's specific platform/job scheduler. At a minimum, the account should be set appropriately prior to job submission: @@ -201,14 +201,14 @@ If the user's login shell is bash, these variables can be set as follows: .. code-block:: console - export HOMEdir=/path-to/ufs-srweather-app/regional_workflow + export HOMEdir=/path-to/ufs-srweather-app export EXPTDIR=/path-to/experiment/directory If the user's login shell is csh/tcsh, they can be set as follows: .. code-block:: console - setenv HOMEdir /path-to/ufs-srweather-app/regional_workflow + setenv HOMEdir /path-to/ufs-srweather-app setenv EXPTDIR /path-to/experiment/directory If plotting the difference between the same cycle from two different experiments, the variables @@ -217,7 +217,7 @@ is bash, these variables can be set as follows: .. code-block:: console - export HOMEdir=/path-to/ufs-srweather-app/regional_workflow + export HOMEdir=/path-to/ufs-srweather-app export EXPTDIR1=/path-to/experiment/directory1 export EXPTDIR2=/path-to/experiment/directory2 @@ -225,7 +225,7 @@ If the user's login shell is csh/tcsh, they can be set as follows: .. code-block:: console - setenv HOMEdir /path-to/ufs-srweather-app/regional_workflow + setenv HOMEdir /path-to/ufs-srweather-app setenv EXPTDIR1 /path-to/experiment/directory1 setenv EXPTDIR2 /path-to/experiment/directory2 diff --git a/docs/UsersGuide/source/InputOutputFiles.rst b/docs/UsersGuide/source/InputOutputFiles.rst index 75dec1b4b7..640a2a598a 100644 --- a/docs/UsersGuide/source/InputOutputFiles.rst +++ b/docs/UsersGuide/source/InputOutputFiles.rst @@ -44,11 +44,11 @@ Documentation for the UPP input files can be found in the `UPP User's Guide Workflow --------- The SRW Application uses a series of template files, combined with user-selected settings, -to create the required namelists and parameter files needed by the Application workflow. (See :numref:`Figure %s ` for a visual summary of the workflow generation process, including template use.) These templates can be reviewed to see which defaults are used and where configuration parameters from the ``config.sh`` file are assigned. +to create the required namelists and parameter files needed by the Application workflow. (See :numref:`Figure %s ` for a visual summary of the workflow generation process, including template use.) These templates can be reviewed to see which defaults are used and where configuration parameters from the ``config.yaml`` file are assigned. List of Template Files ^^^^^^^^^^^^^^^^^^^^^^^^ -The template files for the SRW Application are located in ``regional_workflow/ush/templates`` +The template files for the SRW Application are located in ``parm`` and are shown in :numref:`Table %s `. .. _TemplateFiles: @@ -80,7 +80,7 @@ and are shown in :numref:`Table %s `. +-----------------------------+--------------------------------------------------------------+ | FV3LAM_wflow.xml | Rocoto XML file to run the workflow. It is filled in using | | | the ``fill_template.py`` python script that is called in | - | | ``generate_FV3LAM_wflow.sh``. | + | | ``generate_FV3LAM_wflow.py``. | +-----------------------------+--------------------------------------------------------------+ | input.nml.FV3 | Namelist file for the Weather Model. | +-----------------------------+--------------------------------------------------------------+ @@ -101,7 +101,9 @@ Additional information related to ``diag_table_[CCPP]``, ``field_table_[CCPP]``, Migratory Route of the Input Files in the Workflow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:numref:`Figure %s ` shows how the input files in the template directory (``ufs-srweather-app/regional_workflow/ush/templates/``) flow to the experiment directory. First, the CCPP physics suite is specified in the configuration file. The template input files corresponding to the selected physics suite, such as ``field_table_[CCPP]`` and ``nems.configure_[CCPP]``, are copied to the experiment directory (``$EXPTDIR``). Additionally, the namelist file of the Weather Model (``input.nml``) is created from the ``input.nml.FV3`` and ``FV3.input.yml`` files by running the workflow generation script. While running the ``RUN_FCST`` task in the regional workflow as shown in :numref:`Figure %s `, the ``field_table``, ``nems.configure``, and ``input.nml`` files, located in ``$EXPTDIR``, are linked to the cycle directory (``$CYCLE_DIR``). Additionally, ``diag_table`` and ``model_configure`` are copied from the ``templates`` directory. Finally, these files are updated with the variables specified in ``var_defn.sh``. +:numref:`Figure %s ` shows how the input files in the template directory (``ufs-srweather-app/parm``) flow to the experiment directory. First, the CCPP physics suite is specified in the configuration file. The template input files corresponding to the selected physics suite, such as ``field_table_[CCPP]`` and ``nems.configure_[CCPP]``, are copied to the experiment directory (``$EXPTDIR``). Additionally, the namelist file of the Weather Model (``input.nml``) is created from the ``input.nml.FV3`` and ``FV3.input.yml`` files by running the workflow generation script. While running the ``RUN_FCST`` task in the regional workflow as shown in :numref:`Figure %s `, the ``field_table``, ``nems.configure``, and ``input.nml`` files, located in ``$EXPTDIR``, are linked to the cycle directory (``$CYCLE_DIR``). Additionally, ``diag_table`` and ``model_configure`` are copied from the ``parm`` directory. Finally, these files are updated with the variables specified in ``var_defn.sh``. + +.. COMMENT: Update image! .. _MigratoryRoute: @@ -115,7 +117,7 @@ Migratory Route of the Input Files in the Workflow Output Files ============== -Output files from each workflow task are written to a subdirectory within the experiment directory (``$EXPTDIR/YYYYMMDDHH``), named based on the settings in ``config.sh``. +Output files from each workflow task are written to a subdirectory within the experiment directory (``$EXPTDIR/YYYYMMDDHH``), named based on the settings in ``config.yaml``. Initial and boundary condition files ------------------------------------ @@ -168,7 +170,7 @@ For the SRW Application, the weather model netCDF output files are written to `` * ``NATLEV_{YY}{JJJ}{hh}{mm}f{fhr}00 -> {domain}.t{cyc}z.natlevf{fhr}.tmXX.grib2`` * ``PRSLEV_{YY}{JJJ}{hh}{mm}f{fhr}00 -> {domain}.t{cyc}z.prslevf{fhr}.tmXX.grib2`` -The default setting for the output file names uses ``rrfs`` for ``{domain}``. This may be overridden by the user in the ``config.sh`` settings. +The default setting for the output file names uses ``rrfs`` for ``{domain}``. This may be overridden by the user in the ``config.yaml`` settings. Modifying the UPP Output ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -184,7 +186,7 @@ UPP Product Output Tables for the UFS SRW LAM Grid: Use the instructions in the `UPP User's Guide `__ to make modifications to the ``fv3lam.xml`` file and to remake the flat text file, called ``postxconfig-NT-fv3lam.txt`` (default), that the UPP reads. -After creating the new flat text file to reflect the changes, users will need to modify their ``config.sh`` to point the workflow to the new text file. In ``config.sh``, set the following: +After creating the new flat text file to reflect the changes, users will need to modify their ``config.yaml`` to point the workflow to the new text file. In ``config.yaml``, set the following: .. code-block:: console @@ -210,7 +212,7 @@ Download and unpack the external files: wget https://github.com/NOAA-EMC/EMC_post/releases/download/upp_v10.1.0/fix.tar.gz tar -xzf fix.tar.gz -Modify the ``config.sh`` file to include the following lines: +Modify the ``config.yaml`` file to include the following lines: .. code-block:: console @@ -227,7 +229,7 @@ By setting ``USE_CRTM`` to "TRUE", the workflow will use the path defined in ``C Downloading and Staging Input Data ================================== -A set of input files, including static (fix) data and raw initial and lateral boundary conditions (:term:`IC/LBCs`), is required to run the SRW Application. The data required for the "out-of-the-box" SRW App case described in Chapters :numref:`%s ` and :numref:`%s ` is already preinstalled on `Level 1 & 2 `__ systems, along with data required to run the :ref:`WE2E ` test cases. Therefore, users on these systems do not need to stage the fixed files manually because they have been prestaged, and the paths are set in ``regional_workflow/ush/setup.sh``. Users on Level 3 & 4 systems can find the most recent SRW App release data in the `UFS SRW Application Data Bucket `__ by clicking on `Browse Bucket `__. +A set of input files, including static (fix) data and raw initial and lateral boundary conditions (:term:`IC/LBCs`), is required to run the SRW Application. The data required for the "out-of-the-box" SRW App case described in Chapters :numref:`%s ` and :numref:`%s ` is already preinstalled on `Level 1 & 2 `__ systems, along with data required to run the :ref:`WE2E ` test cases. Therefore, users on these systems do not need to stage the fixed files manually because they have been prestaged, and the paths are set in ``ush/setup.sh``. Users on Level 3 & 4 systems can find the most recent SRW App release data in the `UFS SRW Application Data Bucket `__ by clicking on `Browse Bucket `__. .. _StaticFixFiles: @@ -243,7 +245,7 @@ Static files are available in the `"fix" directory `__ of the SRW Data Bucket using the ``wget`` command for each required file. A list of ``wget`` commands with links is provided :ref:`here ` for the release v2.0.0 fix file data. Users will need to create an appropriate directory structure for the files when downloading them individually. The best solution is to download the files into directories that mirror the structure of the `Data Bucket `__. -The environment variables ``FIXgsm``, ``TOPO_DIR``, and ``SFC_CLIMO_INPUT_DIR`` indicate the path to the directories where the static files are located. After downloading the experiment data, users must set the paths to the files in ``config.sh``. Add the following code to the ``config.sh`` file, and alter the variable paths accordingly: +The environment variables ``FIXgsm``, ``TOPO_DIR``, and ``SFC_CLIMO_INPUT_DIR`` indicate the path to the directories where the static files are located. After downloading the experiment data, users must set the paths to the files in ``config.yaml``. Add the following code to the ``config.yaml`` file, and alter the variable paths accordingly: .. code-block:: console @@ -257,7 +259,7 @@ Initial Condition/Lateral Boundary Condition File Formats and Source ----------------------------------------------------------------------- The SRW Application currently supports raw initial and lateral boundary conditions from numerous models (i.e., FV3GFS, NAM, RAP, HRRR). The data can be provided in three formats: :term:`NEMSIO`, :term:`netCDF`, or :term:`GRIB2`. -To download the model input data for the 12-hour "out-of-the-box" experiment configuration in ``config.community.sh`` file, run: +To download the model input data for the 12-hour "out-of-the-box" experiment configuration in ``config.community.yaml`` file, run: .. code-block:: console @@ -269,7 +271,7 @@ To download data for different dates, model types, and formats, users can explor Initial and Lateral Boundary Condition Organization --------------------------------------------------- -The paths to ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_SOURCE_BASEDIR_LBCS`` must be set in the ``config.sh`` file as follows: +The paths to ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_SOURCE_BASEDIR_LBCS`` must be set in the ``config.yaml`` file as follows: .. code-block:: console @@ -277,7 +279,7 @@ The paths to ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_SOURCE_BASEDIR_LBC EXTRN_MDL_SOURCE_BASEDIR_ICS="" EXTRN_MDL_SOURCE_BASEDIR_LBCS="" -These last two variables describe where the :term:`IC ` and :term:`LBC ` file directories are located, respectively. For ease of reusing ``config.sh`` across experiments, it is recommended that users set up the raw :term:`IC/LBC ` file paths to include the model name (e.g., FV3GFS, NAM, RAP, HRRR), data format (e.g., grib2, nemsio), and date (in ``YYYYMMDDHH`` format). For example: ``/path-to/input_model_data/FV3GFS/grib2/2019061518/``. While there is flexibility to modify these settings, this structure will provide the most reusability for multiple dates when using the SRW Application workflow. +These last two variables describe where the :term:`IC ` and :term:`LBC ` file directories are located, respectively. For ease of reusing ``config.yaml`` across experiments, it is recommended that users set up the raw :term:`IC/LBC ` file paths to include the model name (e.g., FV3GFS, NAM, RAP, HRRR), data format (e.g., grib2, nemsio), and date (in ``YYYYMMDDHH`` format). For example: ``/path-to/input_model_data/FV3GFS/grib2/2019061518/``. While there is flexibility to modify these settings, this structure will provide the most reusability for multiple dates when using the SRW Application workflow. When files are pulled from NOAA :term:`HPSS` (rather than downloaded from the data bucket), the naming convention looks something like: @@ -295,7 +297,7 @@ where: * ``{cycle}`` corresponds to the 2-digit hour of the day when the forecast cycle starts, and * ``{fhr}`` corresponds to the 2- or 3-digit nth hour of the forecast (3-digits for FV3GFS data and 2 digits for RAP/HRRR data). -For example, a forecast using FV3GFS GRIB2 data that starts at 18h00 UTC would have a {cycle} value of 18, which is the 000th forecast hour. The LBCS file for 21h00 UTC would be named ``gfs.t18z.pgrb2.0p25.f003``. An example ``config.sh`` setting using HRRR and RAP data appears below: +For example, a forecast using FV3GFS GRIB2 data that starts at 18h00 UTC would have a {cycle} value of 18, which is the 000th forecast hour. The LBCS file for 21h00 UTC would be named ``gfs.t18z.pgrb2.0p25.f003``. An example ``config.yaml`` setting using HRRR and RAP data appears below: .. code-block:: console @@ -313,7 +315,7 @@ from 20190615 at 18 UTC. FV3GFS GRIB2 files are the default model and file forma Running the App for Different Dates ----------------------------------- -If users want to run the SRW Application for dates other than June 15-16, 2019, they will need to modify the ``config.sh`` settings, including the ``DATE_FIRST_CYCL`` and ``DATE_LAST_CYCL`` variables. The forecast length can be modified by changing the ``FCST_LEN_HRS``. In addition, the lateral boundary interval can be specified using the ``LBC_SPEC_INTVL_HRS`` variable. +If users want to run the SRW Application for dates other than June 15-16, 2019, they will need to modify the ``config.yaml`` settings, including the ``DATE_FIRST_CYCL`` and ``DATE_LAST_CYCL`` variables. The forecast length can be modified by changing the ``FCST_LEN_HRS``. In addition, the lateral boundary interval can be specified using the ``LBC_SPEC_INTVL_HRS`` variable. Users will need to ensure that the initial and lateral boundary condition files are available in the specified path for their new date, cycle, and forecast length. @@ -322,7 +324,7 @@ Staging Initial Conditions Manually ----------------------------------- If users want to run the SRW Application with raw model files for dates other than those that are currently available on the preconfigured platforms, they need to stage the data manually. -The data should be placed in ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_SOURCE_BASEDIR_LBCS`` (which may be the same directory). The path to these variables can be set in the ``config.sh`` file. Raw model files are available from a number of sources. A few examples are provided here for convenience. +The data should be placed in ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_SOURCE_BASEDIR_LBCS`` (which may be the same directory). The path to these variables can be set in the ``config.yaml`` file. Raw model files are available from a number of sources. A few examples are provided here for convenience. NOMADS: https://nomads.ncep.noaa.gov/pub/data/nccf/com/{model}/prod, where model may be: diff --git a/docs/UsersGuide/source/Introduction.rst b/docs/UsersGuide/source/Introduction.rst index f81766bae2..7e39ba7769 100644 --- a/docs/UsersGuide/source/Introduction.rst +++ b/docs/UsersGuide/source/Introduction.rst @@ -8,7 +8,7 @@ The Unified Forecast System (:term:`UFS`) is a community-based, coupled, compreh The UFS includes `multiple applications `__ that support different forecast durations and spatial domains. This documentation describes the UFS Short-Range Weather (SRW) Application, which targets predictions of atmospheric behavior on a limited spatial domain and on time scales from minutes to several days. The SRW Application v2.0.0 release includes a prognostic atmospheric model, pre- and post-processing, and a community workflow for running the system end-to-end. These components are documented within this User's Guide and supported through a `community forum `__. New and improved capabilities for this release include the addition of a verification package (METplus) for both deterministic and ensemble simulations and support for four stochastically perturbed physics schemes. Future work will expand the capabilities of the application to include data assimilation (DA) and a forecast restart/cycling capability. -This documentation provides a :ref:`Quick Start Guide ` designed for use on `Level 1 systems `__ or as an overview of the workflow. It also provides a :ref:`Container-Based Quick Start Guide ` for running the SRW Application in a container and a :ref:`detailed guide ` for running the SRW App on any supported platform. Additionally, this User's Guide provides an overview of the :ref:`release components ` and details on how to customize or modify different portions of the workflow. +This documentation provides a :ref:`Quick Start Guide ` designed for use on `Level 1 systems `__ or as an overview of the workflow. It also provides a :ref:`Container-Based Quick Start Guide ` for running the SRW Application in a container and detailed chapters on :ref:`building ` and :ref:`running ` the SRW App on any supported platform. Additionally, this User's Guide provides an overview of the :ref:`release components ` and details on how to customize or modify different portions of the workflow. The SRW App v2.0.0 citation is as follows and should be used when presenting results based on research conducted with the App: @@ -18,19 +18,24 @@ UFS Development Team. (2022, June 23). Unified Forecast System (UFS) Short-Range How to Use This Document ======================== -This guide instructs both novice and experienced users on downloading, building, and running the SRW Application. Please post questions in the `UFS Forum `__. +This guide instructs both novice and experienced users on downloading, building, and running the SRW Application. Please post questions in the `GitHub Discussions `__ forum. .. code-block:: console Throughout the guide, this presentation style indicates shell commands and options, code examples, etc. -Variables presented as ``AaBbCc123`` in this User's Guide typically refer to variables in scripts, names of files, and directories. +Variables presented as ``AaBbCc123`` in this User's Guide typically refer to variables in scripts, names of files, or directories. File paths or code that include angle brackets (e.g., ``build__``) indicate that users should insert options appropriate to their SRW App configuration (e.g., ``build_orion_intel``). .. hint:: - * To get started running the SRW App, users can view :numref:`Chapter %s ` for a quick overview of the workflow steps. For more detailed explanations, users can refer to the :ref:`Container-Based Quick Start Guide ` or the in-depth chapter on :ref:`Building and Running the Short-Range Weather Application `. + * To get started with the SRW App, users have a few options: + + #. View :numref:`Chapter %s ` for a quick overview of the workflow steps. + #. To build the application in a container, which provides a more uniform work environment, users can refer to the :ref:`Container-Based Quick Start Guide `. + #. For detailed instructions on building and running the SRW App, users can refer to :numref:`Chapter %s: Building the SRW App ` and :numref:`Chapter %s: Running the SRW App `. + * For background information on the SRW App code repositories and directory structure, see :numref:`Section %s ` below. * For an outline of SRW App components, see section :numref:`Section %s ` below or refer to :numref:`Chapter %s ` for a more in-depth treatment. @@ -70,11 +75,11 @@ The UFS SRW Application has been designed so that any sufficiently up-to-date ma * >82 GB disk space - * 53 GB input data for a standard collection of global database, or "fix" data (topography, climatology, observational database) for a short 12-hour test forecast on CONUS 25km domain. See data download instructions in :numref:`Section %s `. + * 53 GB input data for a standard collection of global data, or "fix" file data (topography, climatology, observational data) for a short 12-hour test forecast on the :term:`CONUS` 25km domain. See data download instructions in :numref:`Section %s `. * 8 GB for :term:`HPC-Stack` full installation * 3 GB for ``ufs-srweather-app`` installation - * 1 GB for boundary conditions for a short 12-h test forecast on the CONUS 25km domain. See data download instructions in :numref:`Section %s ` - * 17 GB for a 12-h test forecast on the CONUS 25km domain, with model output saved hourly, see :numref:`Section %s ` + * 1 GB for boundary conditions for a short 12-hour test forecast on the CONUS 25km domain. See data download instructions in :numref:`Section %s `. + * 17 GB for a 12-hour test forecast on the CONUS 25km domain, with model output saved hourly. * Fortran compiler released since 2018 @@ -107,10 +112,10 @@ The following software is also required to run the SRW Application, but the :ter * Only **MPICH** or **OpenMPI** can be built with HPC-Stack. Other implementations must be installed separately by the user (if desired). -For MacOS systems, some additional software packages are needed. When possible, it is recommended that users install and/or upgrade this software (along with software listed above) using the `Homebrew `__ package manager for MacOS. See :ref:`Chapter %s ` and :numref:`Chapter %s ` for further guidance on installing these prerequisites on MacOS. +For MacOS systems, some additional software packages are needed. When possible, it is recommended that users install and/or upgrade this software (along with software listed above) using the `Homebrew `__ package manager for MacOS. See :ref:`Chapter 3 ` and :numref:`Chapter %s ` for further guidance on installing these prerequisites on MacOS. * bash v4.x -* GNU compiler suite v.11 or higher with gfortran +* GNU compiler suite v11 or higher with gfortran * cmake * make * coreutils @@ -175,7 +180,7 @@ The SRW Application has a portable CMake-based build system that packages togeth The SRW Application allows for configuration of various elements of the workflow. For example, users can modify the parameters of the atmospheric model, such as start and end dates, duration, time step, and the physics suite used for the simulation. More information on how to do this is available in :numref:`Section %s `. -The SRW Application has been tested on a variety of platforms widely used by researchers, including NOAA High-Performance Computing (HPC) systems (e.g., Hera, Orion), cloud environments, and generic Linux and MacOS systems. Four `levels of support `__ have been defined for the SRW Application. Preconfigured (Level 1) systems already have the required external libraries available in a central location (via :term:`HPC-Stack`). The SRW Application is expected to build and run out-of-the-box on these systems, and users can :ref:`download the SRW App code ` without first installing prerequisites. On other platforms (Levels 2-4), the SRW App can be :ref:`run within a container ` that includes the HPC-Stack, or the required libraries will need to be installed as part of the :ref:`SRW Application build ` process. Once these prerequisite libraries are installed, applications and models should build and run successfully. However, users may need to perform additional troubleshooting on Level 3 or 4 systems since little or no pre-release testing has been conducted on these systems. +The SRW Application has been tested on a variety of platforms widely used by researchers, including NOAA High-Performance Computing (HPC) systems (e.g., Hera, Orion), cloud environments, and generic Linux and MacOS systems. Four `levels of support `__ have been defined for the SRW Application. Preconfigured (Level 1) systems already have the required external libraries available in a central location (via :term:`HPC-Stack`). The SRW Application is expected to build and run out-of-the-box on these systems, and users can :ref:`download the SRW App code ` without first installing prerequisites. On other platforms (Levels 2-4), the SRW App can be :ref:`run within a container ` that includes the HPC-Stack, or the required libraries will need to be installed as part of the :ref:`SRW Application build ` process. Once these prerequisite libraries are installed, applications and models should build and run successfully. However, users may need to perform additional troubleshooting on Level 3 or 4 systems since little or no pre-release testing has been conducted on these systems. @@ -203,9 +208,6 @@ The :term:`umbrella repository` for the SRW Application is named ``ufs-srweather | Repository for | https://github.com/ufs-community/ufs-weather-model | | the UFS Weather Model | | +---------------------------------+---------------------------------------------------------+ - | Repository for the regional | https://github.com/ufs-community/regional_workflow | - | workflow | | - +---------------------------------+---------------------------------------------------------+ | Repository for UFS utilities, | https://github.com/ufs-community/UFS_UTILS | | including pre-processing, | | | chgres_cube, and more | | @@ -229,33 +231,28 @@ The ``ufs-srweather-app`` :term:`umbrella repository` structure is determined by .. code-block:: console ufs-srweather-app - ├── (bin) ├── (build) ├── docs │ └── UsersGuide ├── etc + ├── (exec) ├── (include) + ├── jobs ├── (lib) ├── manage_externals ├── modulefiles - ├── regional_workflow - │ ├── (fix) - │ ├── jobs - │ ├── modulefiles - │ ├── scripts - │ ├── tests - │ └── ush - │ ├── machine - │ ├── Python - │ ├── templates - │ └── wrappers + ├── parm ├── (share) - ├── src - │ ├── UPP + ├── scripts + ├── sorc + │ ├── CMakeLists.txt + │ ├── (gsi) + │ ├── (rrfs_utl) + │ ├── (UPP) │ │ ├── parm │ │ └── sorc │ │ └── ncep_post.fd - │ ├── UFS_UTILS + │ ├── (UFS_UTILS) │ │ ├── sorc │ │ │ ├── chgres_cube.fd │ │ │ ├── fre-nctools.fd @@ -263,15 +260,23 @@ The ``ufs-srweather-app`` :term:`umbrella repository` structure is determined by │ │ │ ├── orog_mask_tools.fd │ │ │ └── sfc_climo_gen.fd │ │ └── ush - │ └── ufs-weather-model + │ └── (ufs-weather-model) │ └── FV3 │ ├── atmos_cubed_sphere │ └── ccpp - └── test - -Regional Workflow Sub-Directories + ├── tests/WE2E + ├── ush + │ ├── bash_utils + │ ├── machine + │ ├── Python + │ ├── python_utils + │ ├── test_data + │ └── wrappers + └── versions + +SRW App Sub-Directories ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -A number of sub-directories are created under the ``regional_workflow`` directory when the regional workflow is cloned (see directory diagram :ref:`above `). :numref:`Table %s ` describes the contents of these sub-directories. +:numref:`Table %s ` describes the contents of the most important sub-directories. :numref:`Table %s ` provides and in-depth explanation of the ``ufs-srweather-app`` directories. .. _Subdirectories: @@ -296,7 +301,7 @@ A number of sub-directories are created under the ``regional_workflow`` director Experiment Directory Structure -------------------------------- -When the user generates an experiment using the ``generate_FV3LAM_wflow.sh`` script (:numref:`Step %s `), a user-defined experimental directory (``$EXPTDIR``) is created based on information specified in the ``config.sh`` file. :numref:`Table %s ` shows the contents of the experiment directory before running the experiment workflow. +When the user generates an experiment using the ``generate_FV3LAM_wflow.py`` script (:numref:`Step %s `), a user-defined experimental directory (``$EXPTDIR``) is created based on information specified in the ``config.yaml`` file. :numref:`Table %s ` shows the contents of the experiment directory before running the experiment workflow. .. _ExptDirStructure: @@ -306,7 +311,7 @@ When the user generates an experiment using the ``generate_FV3LAM_wflow.sh`` scr +---------------------------+--------------------------------------------------------------------------------------------------------------+ | **File Name** | **Description** | +===========================+==============================================================================================================+ - | config.sh | User-specified configuration file, see :numref:`Section %s ` | + | config.yaml | User-specified configuration file, see :numref:`Section %s ` | +---------------------------+--------------------------------------------------------------------------------------------------------------+ | data_table | :term:`Cycle-independent` input file (empty) | +---------------------------+--------------------------------------------------------------------------------------------------------------+ @@ -319,13 +324,13 @@ When the user generates an experiment using the ``generate_FV3LAM_wflow.sh`` scr | | `__ | +---------------------------+--------------------------------------------------------------------------------------------------------------+ | launch_FV3LAM_wflow.sh | Symlink to the shell script of | - | | ``ufs-srweather-app/regional_workflow/ush/launch_FV3LAM_wflow.sh``, | + | | ``ufs-srweather-app/ush/launch_FV3LAM_wflow.sh``, | | | which can be used to (re)launch the Rocoto workflow. | | | Each time this script is called, it appends to a log | | | file named ``log.launch_FV3LAM_wflow``. | +---------------------------+--------------------------------------------------------------------------------------------------------------+ | log.generate_FV3LAM_wflow | Log of the output from the experiment generation script | - | | (``generate_FV3LAM_wflow.sh``) | + | | (``generate_FV3LAM_wflow.py``) | +---------------------------+--------------------------------------------------------------------------------------------------------------+ | nems.configure | See `NEMS configuration file | | | `__ | @@ -378,7 +383,7 @@ Once the Rocoto workflow is launched, several files and directories are generate | | simultaneously for each cycle in the experiment. Cycle directories | | | are created to contain cycle-specific files for each cycle that | | | the experiment runs. If ``DATE_FIRST_CYCL`` and ``DATE_LAST_CYCL`` | - | | are different in the ``config.sh`` file, more than one cycle | + | | are different in the ``config.yaml`` file, more than one cycle | | | directory will be created under the experiment directory. | +---------------------------+--------------------------------------------------------------------+ | grid | Directory generated by the ``make_grid`` task to store grid files | @@ -456,7 +461,7 @@ A list of available documentation is shown in :numref:`Table %s `. Contributions to the `ufs-srweather-app `__ repository or the `regional_workflow `__ repository should follow the guidelines contained in the :ref:`SRW App Contributor's Guide `. +utilities, model code, and infrastructure. Users can post issues in the related GitHub repositories to report bugs or to announce upcoming contributions to the code base. For code to be accepted in the authoritative repositories, users must follow the code management rules of each UFS component repository, which are outlined in the respective User's Guides listed in :numref:`Table %s `. Contributions to the `ufs-srweather-app `__ repository should follow the guidelines contained in the :ref:`SRW App Contributor's Guide `. Future Direction ================= diff --git a/docs/UsersGuide/source/LAMGrids.rst b/docs/UsersGuide/source/LAMGrids.rst index 92d561ded7..0706556234 100644 --- a/docs/UsersGuide/source/LAMGrids.rst +++ b/docs/UsersGuide/source/LAMGrids.rst @@ -10,7 +10,7 @@ grids supported in the v2.0.0 release, but other predefined grids are available Predefined Grids ================= -The SRW App v2.0.0 release includes four predefined limited area model (:term:`LAM`) grids. To select a supported predefined grid, the ``PREDEF_GRID_NAME`` variable within the ``config.sh`` script must be set to one of the following four options: +The SRW App v2.0.0 release includes four predefined limited area model (:term:`LAM`) grids. To select a supported predefined grid, the ``PREDEF_GRID_NAME`` variable within the ``config.yaml`` script must be set to one of the following four options: * ``RRFS_CONUS_3km`` * ``RRFS_CONUS_13km`` @@ -124,24 +124,24 @@ The steps to add such a grid to the workflow are as follows: #. Choose the name of the grid. For the purposes of this documentation, the grid will be called "NEW_GRID". -#. Add NEW_GRID to the array ``valid_vals_PREDEF_GRID_NAME`` in the ``ufs-srweather-app/regional_workflow/ush/valid_param_vals.sh`` file. +#. Add NEW_GRID to the array ``valid_vals_PREDEF_GRID_NAME`` in the ``ufs-srweather-app/ush/valid_param_vals.yaml`` file. -#. In ``ufs-srweather-app/regional_workflow/ush/set_predef_grid_params.sh``, add a stanza to +#. In ``ufs-srweather-app/ush/set_predef_grid_params.py``, add a stanza to the case statement ``case ${PREDEF_GRID_NAME} in`` for NEW_GRID. An example of such a stanza is given :ref:`below ` along with comments describing the variables that need to be set. -To run a forecast experiment on NEW_GRID, start with a workflow configuration file for a successful experiment (e.g., ``config.sh``, located in the ``ufs-srweather-app/regional_workflow/ush`` subdirectory), and change the line for ``PREDEF_GRID_NAME`` to the following: +To run a forecast experiment on NEW_GRID, start with a workflow configuration file for a successful experiment (e.g., ``config.yaml``, located in the ``ufs-srweather-app/ush`` subdirectory), and change the line for ``PREDEF_GRID_NAME`` to the following: .. code-block:: console PREDEF_GRID_NAME="NEW_GRID" -Then, generate a new experiment/workflow using the ``generate_FV3LAM_wflow.sh`` script in the :ref:`usual way `. +Then, generate a new experiment/workflow using the ``generate_FV3LAM_wflow.py`` script in the :ref:`usual way `. Code Example --------------- -The following is an example of a code stanza for "NEW_GRID" to be added to ``set_predef_grid_params.sh``: +The following is an example of a code stanza for "NEW_GRID" to be added to ``set_predef_grid_params.py``: .. _NewGridExample: @@ -200,7 +200,7 @@ The following is an example of a code stanza for "NEW_GRID" to be added to ``set # needs to be in order to avoid numerical instabilities during the # forecast. The values specified below are used only if DT_ATMOS is # not explicitly set in the user-specified experiment configuration - # file config.sh. Note that this parameter may be suite dependent. + # file config.yaml. Note that this parameter may be suite dependent. if [ "${CCPP_PHYS_SUITE}" = "FV3_GFS_v16" ]; then DT_ATMOS=${DT_ATMOS:-"300"} @@ -212,7 +212,7 @@ The following is an example of a code stanza for "NEW_GRID" to be added to ``set # Default MPI task layout (decomposition) along the x and y directions and # blocksize. The values specified below are used only if they are not explicitly - # set in the user-specified experiment configuration file config.sh. + # set in the user-specified experiment configuration file config.yaml. LAYOUT_X=${LAYOUT_X:-"5"} LAYOUT_Y=${LAYOUT_Y:-"2"} @@ -250,7 +250,7 @@ The following is an example of a code stanza for "NEW_GRID" to be added to ``set # The coordinate system for the write-component grid # See the array valid_vals_WRTCMP_output_grid (defined in - # the script valid_param_vals.sh) for the values this can take on. + # the script valid_param_vals.yaml) for the values this can take on. # The following example is specifically for the Lambert conformal # coordinate system. diff --git a/docs/UsersGuide/source/Quickstart.rst b/docs/UsersGuide/source/Quickstart.rst index c0ca4d6a0a..1046345d22 100644 --- a/docs/UsersGuide/source/Quickstart.rst +++ b/docs/UsersGuide/source/Quickstart.rst @@ -4,7 +4,7 @@ Quick Start Guide ==================== -This chapter provides a brief summary of how to build and run the SRW Application. The steps will run most smoothly on `Level 1 `__ systems. Users should expect to reference other chapters of this User's Guide, particularly :numref:`Chapter %s `, for additional explanations regarding each step. +This chapter provides a brief summary of how to build and run the SRW Application. The steps will run most smoothly on `Level 1 `__ systems. Users should expect to reference other chapters of this User's Guide, particularly :numref:`Chapter %s ` and :numref:`Chapter %s `, for additional explanations regarding each step. Install the HPC-Stack @@ -17,7 +17,7 @@ Once the HPC-Stack has been successfully installed, users can move on to buildin Building and Running the UFS SRW Application =============================================== -For a detailed explanation of how to build and run the SRW App on any supported system, see :numref:`Chapter %s `. The overall procedure for generating an experiment is shown in :numref:`Figure %s `, with the scripts to generate and run the workflow shown in red. An overview of the required steps appears below. However, users can expect to access other referenced sections of this User's Guide for more detail. +For a detailed explanation of how to build and run the SRW App on any supported system, see :numref:`Chapter %s: Building the SRW App ` and :numref:`Chapter %s: Running the SRW App `. The overall procedure for generating an experiment is shown in :numref:`Figure %s `, with the scripts to generate and run the workflow shown in red. An overview of the required steps appears below. However, users can expect to access other referenced sections of this User's Guide for more detail. #. Clone the SRW App from GitHub: @@ -68,6 +68,26 @@ For a detailed explanation of how to build and run the SRW App on any supported #. Download and stage data (both the fix files and the :term:`IC/LBC ` files) according to the instructions in :numref:`Section %s ` (if on a Level 2-4 system). + #. Load the python environment for the regional workflow. Users on Level 2-4 systems will need to use one of the existing ``wflow_`` modulefiles (e.g., ``wflow_macos``) and adapt it to their system. + + .. code-block:: console + + source + module use + module load wflow_ + + where ```` refers to a valid machine name (see :numref:`Section %s `). After loading the workflow, users should follow the instructions printed to the console. For example, if the output says: + + .. code-block:: console + + Please do the following to activate conda: + > conda activate regional_workflow + + then the user should run ``conda activate regional_workflow`` to activate the regional workflow environment. + + .. note:: + If users source the lmod-setup file on a system that doesn't need it, it will not cause any problems (it will simply do a ``module purge``). + #. Configure the experiment parameters. .. code-block:: console @@ -88,22 +108,6 @@ For a detailed explanation of how to build and run the SRW App on any supported INVALID ENTRY: EXTRN_MDL_FILES_ICS=[] FAILURE - #. Load the python environment for the regional workflow. Users on Level 2-4 systems will need to use one of the existing ``wflow_`` modulefiles (e.g., ``wflow_macos``) and adapt it to their system. - - .. code-block:: console - - module use - module load wflow_ - - After loading the workflow, users should follow the instructions printed to the console. For example, if the output says: - - .. code-block:: console - - Please do the following to activate conda: - > conda activate regional_workflow - - then the user should run ``conda activate regional_workflow`` to activate the ``regional_workflow`` environment. - #. Generate the experiment workflow. .. code-block:: console diff --git a/docs/UsersGuide/source/RocotoInfo.rst b/docs/UsersGuide/source/RocotoInfo.rst index ac49064abf..a56ea7ad28 100644 --- a/docs/UsersGuide/source/RocotoInfo.rst +++ b/docs/UsersGuide/source/RocotoInfo.rst @@ -10,7 +10,7 @@ system as the task dependencies allow and runs one instance of the workflow for :term:`cycles `. More information about Rocoto can be found on the `Rocoto Wiki `__. The SRW App workflow is defined in a Jinja-enabled Rocoto XML template called ``FV3LAM_wflow.xml``, -which resides in the ``regional_workflow/ush/templates`` directory. When the ``generate_FV3LAM_wflow.sh`` +which resides in the ``parm`` directory. When the ``generate_FV3LAM_wflow.py`` script is run, the ``fill_jinja_template.py`` script is called, and the parameters in the template file are filled in. The completed file contains the workflow task names, parameters needed by the job scheduler, and task interdependencies. The generated XML file is then copied to the experiment directory: @@ -143,7 +143,7 @@ from the ``$EXPTDIR`` directory as follows: where * ``-c`` is the cycle to query in YYYYMMDDHHmm format -* ``-t`` is the task name (see default task names in :numref:`Chapter %s `) +* ``-t`` is the task name (e.g., ``make_grid``, ``get_extrn_ics``, ``run_fcst``). See :numref:`Chapter %s ` for the default values for task name variables, which end in ``_TN``. The cycle and task names appear in the first and second columns of the table output by ``rocotostat``. @@ -160,7 +160,7 @@ Running ``rocotocheck`` will result in output similar to the following: Task: run_fcst account: gsd-fv3 - command: /scratch2/BMC/det/$USER/ufs-srweather-app/regional_workflow/ush/load_modules_run_task.sh "run_fcst" "/scratch2/BMC/det/$USER/ufs-srweather-app/regional_workflow/jobs/JREGIONAL_RUN_FCST" + command: /scratch2/BMC/det/$USER/ufs-srweather-app/ush/load_modules_run_task.sh "run_fcst" "/scratch2/BMC/det/$USER/ufs-srweather-app/jobs/JREGIONAL_RUN_FCST" cores: 24 final: false jobname: run_FV3 diff --git a/docs/UsersGuide/source/RunSRW.rst b/docs/UsersGuide/source/RunSRW.rst new file mode 100644 index 0000000000..630a1f9862 --- /dev/null +++ b/docs/UsersGuide/source/RunSRW.rst @@ -0,0 +1,1259 @@ +.. _RunSRW: + +=========================== +Running the SRW App +=========================== + +This chapter explains how to set up and run the "out-of-the-box" case for the SRW App. However, the steps are relevant to any SRW Application experiment and can be modified to suit user goals. This chapter assumes that users have already built the SRW App by following the steps in :numref:`Chapter %s `. These steps are also applicable to containerized versions of the SRW App and assume that the user has completed Steps :numref:`%s ` through :numref:`%s `. + +The out-of-the-box SRW App case builds a weather forecast for June 15-16, 2019. Multiple convective weather events during these two days produced over 200 filtered storm reports. Severe weather was clustered in two areas: the Upper Midwest through the Ohio Valley and the Southern Great Plains. This forecast uses a predefined 25-km Continental United States (:term:`CONUS`) domain (RRFS_CONUS_25km), the Global Forecast System (:term:`GFS`) version 16 physics suite (FV3_GFS_v16 :term:`CCPP`), and :term:`FV3`-based GFS raw external model data for initialization. + +.. attention:: + + The SRW Application has `four levels of support `__. The steps described in this chapter will work most smoothly on preconfigured (Level 1) systems. This chapter can also serve as a starting point for running the SRW App on other systems (including generic Linux/Mac systems), but the user may need to perform additional troubleshooting. + + +The overall procedure for generating an experiment is shown in :numref:`Figure %s `, with the scripts to generate and run the workflow shown in red. Once the SRW has been built, as described in :numref:`Chapter %s `, the steps to run a forecast are as follows: + + #. :ref:`Download and stage data ` + #. :ref:`Optional: Configure a new grid ` + #. :ref:`Generate a regional workflow experiment ` + + * :ref:`Set the experiment configuration parameters ` + * :ref:`Load the python environment for the regional workflow ` + + #. :ref:`Run the regional workflow ` + #. :ref:`Optional: Plot the output ` + +.. _AppOverallProc: + +.. figure:: _static/SRW_overall_workflow_run.png + :alt: Flowchart describing the SRW App workflow steps. + + *Overall layout of the SRW App Workflow* + +.. _Data: + +Download and Stage the Data +============================ + +The SRW App requires input files to run. These include static datasets, initial and boundary conditions files, and model configuration files. On Level 1 systems, the data required to run SRW App tests are already available in the following locations: + +.. table:: Data locations for Level 1 systems + + +--------------+-----------------------------------------------------------------+ + | Machine | File location | + +==============+=================================================================+ + | Cheyenne | /glade/p/ral/jntp/UFS_SRW_App/develop/input_model_data/ | + +--------------+-----------------------------------------------------------------+ + | Gaea | /lustre/f2/pdata/ncep/UFS_SRW_App/develop/input_model_data/ | + +--------------+-----------------------------------------------------------------+ + | Hera | /scratch2/BMC/det/UFS_SRW_App/develop/input_model_data/ | + +--------------+-----------------------------------------------------------------+ + | Jet | /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/input_model_data/ | + +--------------+-----------------------------------------------------------------+ + | NOAA Cloud | /contrib/EPIC/UFS_SRW_App/develop/input_model_data/ | + +--------------+-----------------------------------------------------------------+ + | Orion | /work/noaa/fv3-cam/UFS_SRW_App/develop/input_model_data/ | + +--------------+-----------------------------------------------------------------+ + | WCOSS2 | /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/input_model_data/ | + +--------------+-----------------------------------------------------------------+ + +For Level 2-4 systems, the data must be added to the user's system. Detailed instructions on how to add the data can be found in :numref:`Section %s `. Sections :numref:`%s ` and :numref:`%s ` contain useful background information on the input and output files used in the SRW App. + +.. _GridSpecificConfig: + +Grid Configuration +======================= + +The SRW App officially supports the four predefined grids shown in :numref:`Table %s `. The out-of-the-box SRW App case uses the ``RRFS_CONUS_25km`` predefined grid option. More information on the predefined and user-generated grid options can be found in :numref:`Chapter %s ` for those who are curious. Users who plan to utilize one of the four predefined domain (grid) options may continue to :numref:`Step %s `. Users who plan to create a new custom domain should refer to :numref:`Section %s ` for instructions. At a minimum, these users will need to add the new grid name to the ``valid_param_vals.yaml`` script and add the corresponding grid-specific parameters in the ``set_predef_grid_params.py`` script. + +.. _PredefinedGrids: + +.. table:: Predefined grids in the SRW App + + +----------------------+-------------------+--------------------------------+ + | **Grid Name** | **Grid Type** | **Quilting (write component)** | + +======================+===================+================================+ + | RRFS_CONUS_25km | ESG grid | lambert_conformal | + +----------------------+-------------------+--------------------------------+ + | RRFS_CONUS_13km | ESG grid | lambert_conformal | + +----------------------+-------------------+--------------------------------+ + | RRFS_CONUS_3km | ESG grid | lambert_conformal | + +----------------------+-------------------+--------------------------------+ + | SUBCONUS_Ind_3km | ESG grid | lambert_conformal | + +----------------------+-------------------+--------------------------------+ + + +.. _GenerateForecast: + +Generate the Forecast Experiment +================================= +Generating the forecast experiment requires three steps: + +#. :ref:`Load the python environment for the regional workflow ` +#. :ref:`Set experiment configuration parameters ` +#. :ref:`Run a script to generate the experiment workflow ` + +The first two steps depend on the platform being used and are described here for each Level 1 platform. Users will need to adjust the instructions to reflect their machine configuration if they are working on a Level 2-4 platform. Information in :numref:`Chapter %s: Configuring the Workflow ` can help with this. + +.. _SetUpPythonEnv: + +Load the Python Environment for the Regional Workflow +--------------------------------------------------------- + +The workflow requires Python 3 with the packages ``PyYAML``, ``Jinja2``, and ``f90nml`` available. This Python environment has already been set up on Level 1 platforms, and it can be activated in the following way: + +.. code-block:: console + + source + module use + module load wflow_ + +where ```` refers to a valid machine name (see :numref:`Section %s `). + +.. note:: + If users source the lmod-steup file on a system that doesn't need it, it will not cause any problems (it will simply do a ``module purge``). + +The ``wflow_`` modulefile will then output instructions to activate the regional workflow. The user should run the commands specified in the modulefile output. For example, if the output says: + +.. code-block:: console + + Please do the following to activate conda: + > conda activate regional_workflow + +then the user should run ``conda activate regional_workflow``. This will activate the ``regional_workflow`` conda environment. However, the command(s) will vary from system to system. Regardless, the user should see ``(regional_workflow)`` in front of the Terminal prompt at this point. If this is not the case, activate the regional workflow from the ``ush`` directory by running: + +.. code-block:: console + + conda init + source ~/.bashrc + conda activate regional_workflow + +.. _LinuxMacActivateWFenv: + +Activating the Workflow Environment on Non-Level 1 Systems +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Users on non-Level 1 systems can copy one of the provided ``wflow_`` files and use it as a template to create a ``wflow_`` file that works for their system. ``wflow_macos`` and ``wflow_linux`` template files are provided in the ``modulefiles`` directory. After making appropriate modifications to a ``wflow_`` file, users can run the commands from :numref:`Step %s ` above to activate the regional workflow. + +On generic Linux or MacOS systems, loading the designated ``wflow_`` file will output instructions similar to the following: + +.. code-block:: console + + Please do the following to activate conda: + > source $VENV/bin/activate + +If that does not work, users can also try: + +.. code-block:: console + + source $HOME/venv/regional_workflow/bin/activate + +However, it may instead be necessary to make additional adjustments to the ``wflow_`` file. + +.. _ExptConfig: + +Set Experiment Configuration Parameters +------------------------------------------ + +Each experiment requires certain basic information to run (e.g., date, grid, physics suite). This information is specified in ``config_defaults.yaml`` and in the user-specified ``config.yaml`` file. When generating a new experiment, the SRW App first reads and assigns default values from ``config_defaults.yaml``. Then, it reads and (re)assigns variables from the user's custom ``config.yaml`` file. + +For background info on ``config_defaults.yaml``, read :numref:`Section %s `, or jump to :numref:`Section %s ` to continue configuring the experiment. + +.. _DefaultConfigSection: + +Default configuration: ``config_defaults.yaml`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: + This section provides background information on available parameters and how the SRW App uses the ``config_defaults.yaml`` file. It is informative, but users do not need to modify ``config_defaults.yaml`` to run the out-of-the-box case for the SRW App. Therefore, users may skip to :numref:`Step %s ` to continue configuring their experiment. + +Configuration parameters in the ``config_defaults.yaml`` file appear in :numref:`Table %s `. Some of these default values are intentionally invalid in order to ensure that the user assigns valid values in the user-specified ``config.yaml`` file. Any settings provided in ``config.yaml`` will override the settings in ``config_defaults.yaml``. +settings. There is usually no need for a user to modify the default configuration file. Additional information on the default settings can be found in the ``config_defaults.yaml`` file comments and in :numref:`Chapter %s `. + +.. _ConfigVarsDefault: + +.. table:: Configuration variables specified in the config_defaults.yaml script + + +-----------------------------+-----------------------------------------------------------------------+ + | **Group Name** | **Configuration variables** | + +=============================+=======================================================================+ + | User | RUN_ENVIR, MACHINE, MACHINE_FILE, ACCOUNT | + +-----------------------------+-----------------------------------------------------------------------+ + | Platform | WORKFLOW_MANAGER, NCORES_PER_NODE, BUILD_MOD_FN, WFLOW_MOD_FN, | + | | BUILD_VER_FN, RUN_VER_FN, SCHED, DOMAIN_PREGEN_BASEDIR, | + | | ENV_INIT_SCRIPTS_FPS, PRE_TASK_CMDS, PARTITION_DEFAULT, QUEUE_DEFAULT,| + | | PARTITION_HPSS, QUEUE_HPSS, PARTITION_FCST, QUEUE_FCST, | + | | RUN_CMD_UTILS, RUN_CMD_FCST, RUN_CMD_POST, SLURM_NATIVE_CMD, | + | | MODEL, MET_INSTALL_DIR, METPLUS_PATH, MET_BIN_EXEC, CCPA_OBS_DIR, | + | | MRMS_OBS_DIR, NDAS_OBS_DIR | + +-----------------------------+-----------------------------------------------------------------------+ + | Workflow | WORKFLOW_ID, USE_CRON_TO_RELAUNCH, CRON_RELAUNCH_INTVL_MNTS, | + | | EXPT_BASEDIR, EXPT_SUBDIR, EXEC_SUBDIR, DOT_OR_USCORE, | + | | EXPT_CONFIG_FN, CONSTANTS_FN, RGNL_GRID_NML_FN, | + | | FV3_NML_BASE_SUITE_FN, FV3_NML_YAML_CONFIG_FN, FV3_NML_BASE_ENS_FN, | + | | FV3_EXEC_FN, DIAG_TABLE_TMPL_FN, FIELD_TABLE_TMPL_FN, | + | | DATA_TABLE_TMPL_FN, MODEL_CONFIG_TMPL_FN, NEMS_CONFIG_TMPL_FN, | + | | FCST_MODEL, WFLOW_XML_FN, GLOBAL_VAR_DEFNS_FN, | + | | EXTRN_MDL_VAR_DEFNS_FN, WFLOW_LAUNCH_SCRIPT_FN, WFLOW_LAUNCH_LOG_FN, | + | | CCPP_PHYS_SUITE, GRID_GEN_METHOD, DATE_FIRST_CYCL, DATE_LAST_CYCL, | + | | INCR_CYCL_FREQ, FCST_LEN_HRS, GET_OBS, VX_TN, VX_ENSGRID_TN, | + | | VX_ENSGRID_PROB_REFC_TN, MAXTRIES_VX_ENSGRID_PROB_REFC, | + | | PREEXISTING_DIR_METHOD, VERBOSE, DEBUG, COMPILER | + +-----------------------------+-----------------------------------------------------------------------+ + | NCO | envir, NET, model_ver, RUN, OPSROOT | + +-----------------------------+-----------------------------------------------------------------------+ + | Workflow Switches | RUN_TASK_MAKE_GRID, RUN_TASK_MAKE_OROG, RUN_TASK_MAKE_SFC_CLIMO, | + | | RUN_TASK_GET_EXTRN_ICS, RUN_TASK_GET_EXTRN_LBCS, RUN_TASK_MAKE_ICS, | + | | RUN_TASK_MAKE_LBCS, RUN_TASK_RUN_FCST, RUN_TASK_RUN_POST, | + | | RUN_TASK_GET_OBS_CCPA, RUN_TASK_GET_OBS_MRMS, RUN_TASK_GET_OBS_NDAS, | + | | RUN_TASK_VX_GRIDSTAT, RUN_TASK_VX_POINTSTAT, RUN_TASK_VX_ENSGRID, | + | | RUN_TASK_VX_ENSPOINT | + +-----------------------------+-----------------------------------------------------------------------+ + | task_make_grid | MAKE_GRID_TN, NNODES_MAKE_GRID, PPN_MAKE_GRID, WTIME_MAKE_GRID, | + | | MAXTRIES_MAKE_GRID, GRID_DIR, ESGgrid_LON_CTR, ESGgrid_LAT_CTR, | + | | ESGgrid_DELX, ESGgrid_DELY, ESGgrid_NX, ESGgrid_NY, ESGgrid_PAZI, | + | | ESGgrid_WIDE_HALO_WIDTH, GFDLgrid_LON_T6_CTR, GFDLgrid_LAT_T6_CTR, | + | | GFDLgrid_NUM_CELLS, GFDLgrid_STRETCH_FAC, GFDLgrid_REFINE_RATIO, | + | | GFDLgrid_ISTART_OF_RGNL_DOM_ON_T6G, GFDLgrid_IEND_OF_RGNL_DOM_ON_T6G, | + | | GFDLgrid_JSTART_OF_RGNL_DOM_ON_T6G, GFDLgrid_JEND_OF_RGNL_DOM_ON_T6G, | + | | GFDLgrid_USE_NUM_CELLS_IN_FILENAMES | + +-----------------------------+-----------------------------------------------------------------------+ + | task_make_orog | MAKE_OROG_TN, NNODES_MAKE_OROG, PPN_MAKE_OROG, WTIME_MAKE_OROG, | + | | MAXTRIES_MAKE_OROG, KMP_AFFINITY_MAKE_OROG, OMP_NUM_THREADS_MAKE_OROG | + | | OMP_STACKSIZE_MAKE_OROG, OROG_DIR | + +-----------------------------+-----------------------------------------------------------------------+ + | task_make_sfc_climo | MAKE_SFC_CLIMO_TN, NNODES_MAKE_SFC_CLIMO, PPN_MAKE_SFC_CLIMO, | + | | WTIME_MAKE_SFC_CLIMO, MAXTRIES_MAKE_SFC_CLIMO, | + | | KMP_AFFINITY_MAKE_SFC_CLIMO, OMP_NUM_THREADS_MAKE_SFC_CLIMO, | + | | OMP_STACKSIZE_MAKE_SFC_CLIMO, SFC_CLIMO_DIR | + +-----------------------------+-----------------------------------------------------------------------+ + | task_get_extrn_ics | GET_EXTRN_ICS_TN, NNODES_GET_EXTRN_ICS, PPN_GET_EXTRN_ICS, | + | | WTIME_GET_EXTRN_ICS, MAXTRIES_GET_EXTRN_ICS, EXTRN_MDL_NAME_ICS, | + | | EXTRN_MDL_ICS_OFFSET_HRS, FV3GFS_FILE_FMT_ICS, | + | | EXTRN_MDL_SYSBASEDIR_ICS, USE_USER_STAGED_EXTRN_FILES, | + | | EXTRN_MDL_SOURCE_BASEDIR_ICS, EXTRN_MDL_FILES_ICS, | + | | EXTRN_MDL_FILES_ICS, EXTRN_MDL_FILES_ICS, EXTRN_MDL_DATA_STORES, | + | | NOMADS, NOMADS_file_type | + +-----------------------------+-----------------------------------------------------------------------+ + | task_get_extrn_lbcs | GET_EXTRN_LBCS_TN, NNODES_GET_EXTRN_LBCS, PPN_GET_EXTRN_LBCS, | + | | WTIME_GET_EXTRN_LBCS, MAXTRIES_GET_EXTRN_LBCS, EXTRN_MDL_NAME_LBCS, | + | | LBC_SPEC_INTVL_HRS, EXTRN_MDL_LBCS_OFFSET_HRS, FV3GFS_FILE_FMT_LBCS, | + | | EXTRN_MDL_SYSBASEDIR_LBCS, USE_USER_STAGED_EXTRN_FILES, | + | | EXTRN_MDL_SOURCE_BASEDIR_LBCS, EXTRN_MDL_FILES_LBCS, | + | | EXTRN_MDL_DATA_STORE, NOMADS, NOMADS_file_type | + +-----------------------------+-----------------------------------------------------------------------+ + | task_make_ics | MAKE_ICS_TN, NNODES_MAKE_ICS, PPN_MAKE_ICS, WTIME_MAKE_ICS, | + | | MAXTRIES_MAKE_ICS, KMP_AFFINITY_MAKE_ICS, OMP_NUM_THREADS_MAKE_ICS, | + | | OMP_STACKSIZE_MAKE_ICS, USE_FVCOM, FVCOM_WCSTART, FVCOM_DIR, | + | | FVCOM_FILE | + +-----------------------------+-----------------------------------------------------------------------+ + | task_make_lbcs | MAKE_LBCS_TN, NNODES_MAKE_LBCS, PPN_MAKE_LBCS, WTIME_MAKE_LBCS, | + | | MAXTRIES_MAKE_LBCS, KMP_AFFINITY_MAKE_LBCS, OMP_NUM_THREADS_MAKE_LBCS,| + | | OMP_STACKSIZE_MAKE_LBCS | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_fcst | RUN_FCST_TN, NNODES_RUN_FCST, PPN_RUN_FCST, WTIME_RUN_FCST, | + | | MAXTRIES_RUN_FCST, KMP_AFFINITY_RUN_FCST, OMP_NUM_THREADS_RUN_FCST, | + | | OMP_STACKSIZE_RUN_FCST, DT_ATMOS, RESTART_INTERVAL, WRITE_DOPOST, | + | | LAYOUT_X, LAYOUT_Y, BLOCKSIZE, QUILTING, PRINT_ESMF, | + | | WRTCMP_write_groups, WRTCMP_write_tasks_per_group, | + | | WRTCMP_cen_lon, WRTCMP_cen_lat, WRTCMP_lon_lwr_left, | + | | WRTCMP_lat_lwr_left, WRTCMP_lon_upr_rght, WRTCMP_lat_upr_rght, | + | | WRTCMP_dlon, WRTCMP_dlat, WRTCMP_stdlat1, WRTCMP_stdlat2, WRTCMP_nx, | + | | WRTCMP_ny, WRTCMP_dx, WRTCMP_dy, PREDEF_GRID_NAME, USE_MERRA_CLIMO, | + | | SFC_CLIMO_FIELDS, FIXgsm, FIXaer, FIXlut, TOPO_DIR, | + | | SFC_CLIMO_INPUT_DIR, SYMLINK_FIX_FILES, FNGLAC, FNMXIC, FNTSFC, | + | | FNSNOC, FNZORC, FNAISC, FNSMCC, FNMSKH, FIXgsm_FILES_TO_COPY_TO_FIXam,| + | | FV3_NML_VARNAME_TO_FIXam_FILES_MAPPING, | + | | FV3_NML_VARNAME_TO_SFC_CLIMO_FIELD_MAPPING, | + | | CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_post | RUN_POST_TN, NNODES_RUN_POST, PPN_RUN_POST, WTIME_RUN_POST, | + | | MAXTRIES_RUN_POST, KMP_AFFINITY_RUN_POST, OMP_NUM_THREADS_RUN_POST, | + | | OMP_STACKSIZE_RUN_POST, SUB_HOURLY_POST, DT_SUB_HOURLY_POST_MNTS, | + | | USE_CUSTOM_POST_CONFIG_FILE, CUSTOM_POST_CONFIG_FP, | + | | POST_OUTPUT_DOMAIN_NAME | + +-----------------------------+-----------------------------------------------------------------------+ + | Global | USE_CRTM, CRTM_DIR, DO_ENSEMBLE, NUM_ENS_MEMBERS, | + | | NEW_LSCALE, DO_SHUM, ISEED_SHUM, SHUM_MAG, SHUM_LSCALE, SHUM_TSCALE, | + | | SHUM_INT, DO_SPPT, ISEED_SPPT, SPPT_MAG, SPPT_LOGIT, SPPT_LSCALE, | + | | SPPT_TSCALE, SPPT_INT, SPPT_SFCLIMIT, USE_ZMTNBLCK, DO_SKEB, | + | | ISEED_SKEB, SKEB_MAG, SKEB_LSCALE, SKEP_TSCALE, SKEB_INT, SKEBNORM, | + | | SKEB_VDOF, DO_SPP, ISEED_SPP, SPP_VAR_LIST, SPP_MAG_LIST, SPP_LSCALE, | + | | SPP_TSCALE, SPP_SIGTOP1, SPP_SIGTOP2, SPP_STDDEV_CUTOFF, DO_LSM_SPP, | + | | LSM_SPP_TSCALE, LSM_SPP_LSCALE, ISEED_LSM_SPP, LSM_SPP_VAR_LIST, | + | | LSM_SPP_MAG_LIST, HALO_BLEND | + +-----------------------------+-----------------------------------------------------------------------+ + | task_get_obs_ccpa | GET_OBS_CCPA_TN, NNODES_GET_OBS_CCPA, PPN_GET_OBS_CCPA, | + | | WTIME_GET_OBS_CCPA, MAXTRIES_GET_OBS_CCPA | + +-----------------------------+-----------------------------------------------------------------------+ + | task_get_obs_mrms | GET_OBS_MRMS_TN, NNODES_GET_OBS_MRMS, PPN_GET_OBS_MRMS, | + | | WTIME_GET_OBS_MRMS, MAXTRIES_GET_OBS_MRMS | + +-----------------------------+-----------------------------------------------------------------------+ + | task_get_obs_ndas | GET_OBS_NDAS_TN, NNODES_GET_OBS_NDAS, PPN_GET_OBS_NDAS, | + | | WTIME_GET_OBS_NDAS, MAXTRIES_GET_OBS_NDAS | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_gridstat | VX_GRIDSTAT_TN, NNODES_VX_GRIDSTAT, PPN_VX_GRIDSTAT, | + | | WTIME_VX_GRIDSTAT, MAXTRIES_VX_GRIDSTAT | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_gridstat_refc | VX_GRIDSTAT_REFC_TN, NNODES_VX_GRIDSTAT, PPN_VX_GRIDSTAT, | + | | WTIME_VX_GRIDSTAT, MAXTRIES_VX_GRIDSTAT_REFC | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_gridstat_retop | VX_GRIDSTAT_RETOP_TN, NNODES_VX_GRIDSTAT, PPN_VX_GRIDSTAT, | + | | WTIME_VX_GRIDSTAT, MAXTRIES_VX_GRIDSTAT_RETOP | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_gridstat_03h | VX_GRIDSTAT_03h_TN, NNODES_VX_GRIDSTAT, PPN_VX_GRIDSTAT, | + | | WTIME_VX_GRIDSTAT, MAXTRIES_VX_GRIDSTAT_03h | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_gridstat_06h | VX_GRIDSTAT_06h_TN, NNODES_VX_GRIDSTAT, PPN_VX_GRIDSTAT, | + | | WTIME_VX_GRIDSTAT, MAXTRIES_VX_GRIDSTAT_06h | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_gridstat_24h | VX_GRIDSTAT_24h_TN, NNODES_VX_GRIDSTAT, PPN_VX_GRIDSTAT, | + | | WTIME_VX_GRIDSTAT, MAXTRIES_VX_GRIDSTAT_24h | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_pointstat | VX_POINTSTAT_TN, NNODES_VX_POINTSTAT, PPN_VX_POINTSTAT, | + | | WTIME_VX_POINTSTAT, MAXTRIES_VX_POINTSTAT | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid | VX_ENSGRID_03h_TN, MAXTRIES_VX_ENSGRID_03h, VX_ENSGRID_06h_TN, | + | | MAXTRIES_VX_ENSGRID_06h, VX_ENSGRID_24h_TN, MAXTRIES_VX_ENSGRID_24h, | + | | VX_ENSGRID_RETOP_TN, MAXTRIES_VX_ENSGRID_RETOP, | + | | VX_ENSGRID_PROB_RETOP_TN, MAXTRIES_VX_ENSGRID_PROB_RETOP, | + | | NNODES_VX_ENSGRID, PPN_VX_ENSGRID, WTIME_VX_ENSGRID, | + | | MAXTRIES_VX_ENSGRID | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid_refc | VX_ENSGRID_REFC_TN, NNODES_VX_ENSGRID, PPN_VX_ENSGRID, | + | | WTIME_VX_ENSGRID, MAXTRIES_VX_ENSGRID_REFC | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid_mean | VX_ENSGRID_MEAN_TN, NNODES_VX_ENSGRID_MEAN, PPN_VX_ENSGRID_MEAN, | + | | WTIME_VX_ENSGRID_MEAN, MAXTRIES_VX_ENSGRID_MEAN | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid_mean_03h| VX_ENSGRID_MEAN_03h_TN, NNODES_VX_ENSGRID_MEAN, PPN_VX_ENSGRID_MEAN, | + | | WTIME_VX_ENSGRID_MEAN, MAXTRIES_VX_ENSGRID_MEAN_03h | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid_mean_06h| VX_ENSGRID_MEAN_06h_TN, NNODES_VX_ENSGRID_MEAN, PPN_VX_ENSGRID_MEAN, | + | | WTIME_VX_ENSGRID_MEAN, MAXTRIES_VX_ENSGRID_MEAN_06h | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid_mean_24h| VX_ENSGRID_MEAN_24h_TN, NNODES_VX_ENSGRID_MEAN, PPN_VX_ENSGRID_MEAN, | + | | WTIME_VX_ENSGRID_MEAN, MAXTRIES_VX_ENSGRID_MEAN_24h | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid_prob | VX_ENSGRID_PROB_TN, NNODES_VX_ENSGRID_PROB, PPN_VX_ENSGRID_PROB, | + | | WTIME_VX_ENSGRID_PROB, MAXTRIES_VX_ENSGRID_PROB | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid_prob_03h| VX_ENSGRID_PROB_03h_TN, NNODES_VX_ENSGRID_PROB, PPN_VX_ENSGRID_PROB, | + | | WTIME_VX_ENSGRID_PROB, MAXTRIES_VX_ENSGRID_PROB_03h | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid_prob_06h| VX_ENSGRID_PROB_06h_TN, NNODES_VX_ENSGRID_PROB, PPN_VX_ENSGRID_PROB, | + | | WTIME_VX_ENSGRID_PROB, MAXTRIES_VX_ENSGRID_PROB_06h | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_ensgrid_prob_24h| VX_ENSGRID_PROB_24h_TN, NNODES_VX_ENSGRID_PROB, PPN_VX_ENSGRID_PROB, | + | | WTIME_VX_ENSGRID_PROB, MAXTRIES_VX_ENSGRID_PROB_24h | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_enspoint | VX_ENSPOINT_TN, NNODES_VX_ENSPOINT, PPN_VX_ENSPOINT, | + | | WTIME_VX_ENSPOINT, MAXTRIES_VX_ENSPOINT | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_enspoint_mean | VX_ENSPOINT_MEAN_TN, NNODES_VX_ENSPOINT_MEAN, PPN_VX_ENSPOINT_MEAN, | + | | WTIME_VX_ENSPOINT_MEAN, MAXTRIES_VX_ENSPOINT_MEAN | + +-----------------------------+-----------------------------------------------------------------------+ + | task_run_vx_enspoint_prob | VX_ENSPOINT_PROB_TN, NNODES_VX_ENSPOINT_PROB, PPN_VX_ENSPOINT_PROB, | + | | WTIME_VX_ENSPOINT_PROB, MAXTRIES_VX_ENSPOINT_PROB | + +-----------------------------+-----------------------------------------------------------------------+ + +.. _UserSpecificConfig: + +User-specific configuration: ``config.yaml`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The user must specify certain basic experiment configuration information in a ``config.yaml`` file located in the ``ufs-srweather-app/ush`` directory. Two example templates are provided in that directory: ``config.community.yaml`` and ``config.nco.yaml``. The first file is a minimal example for creating and running an experiment in *community* mode (with ``RUN_ENVIR`` set to ``community``). The second is an example for creating and running an experiment in the *NCO* (operational) mode (with ``RUN_ENVIR`` set to ``nco``). The *community* mode is recommended in most cases and is fully supported for this release. The operational/NCO mode is typically used by developers at the Environmental Modeling Center (:term:`EMC`) and at the Global Systems Laboratory (:term:`GSL`) working on pre-implementation testing for the Rapid Refresh Forecast System (RRFS). :numref:`Table %s ` compares the configuration variables that appear in the ``config.community.yaml`` with their default values in ``config_default.yaml``. + +.. _ConfigCommunity: + +.. table:: Configuration variables specified in the config.community.yaml script + + +--------------------------------+-------------------+------------------------------------+ + | **Parameter** | **Default Value** | **config.community.yaml Value** | + +================================+===================+====================================+ + | RUN_ENVIR | "nco" | "community" | + +--------------------------------+-------------------+------------------------------------+ + | MACHINE | "BIG_COMPUTER" | "hera" | + +--------------------------------+-------------------+------------------------------------+ + | ACCOUNT | "project_name" | "an_account" | + +--------------------------------+-------------------+------------------------------------+ + | MODEL | "" | "FV3_GFS_v16_CONUS_25km" | + +--------------------------------+-------------------+------------------------------------+ + | METPLUS_PATH | "" | "" | + +--------------------------------+-------------------+------------------------------------+ + | MET_INSTALL_DIR | "" | "" | + +--------------------------------+-------------------+------------------------------------+ + | CCPA_OBS_DIR | "" | "" | + +--------------------------------+-------------------+------------------------------------+ + | MRMS_OBS_DIR | "" | "" | + +--------------------------------+-------------------+------------------------------------+ + | NDAS_OBS_DIR | "" | "" | + +--------------------------------+-------------------+------------------------------------+ + | EXPT_SUBDIR | "" | "test_community" | + +--------------------------------+-------------------+------------------------------------+ + | CCPP_PHYS_SUITE | "FV3_GFS_v16" | "FV3_GFS_v16" | + +--------------------------------+-------------------+------------------------------------+ + | DATE_FIRST_CYCL | "YYYYMMDDHH" | '2019061518' | + +--------------------------------+-------------------+------------------------------------+ + | DATE_LAST_CYCL | "YYYYMMDDHH" | '2019061518' | + +--------------------------------+-------------------+------------------------------------+ + | FCST_LEN_HRS | 24 | 12 | + +--------------------------------+-------------------+------------------------------------+ + | PREEXISTING_DIR_METHOD | "delete" | "rename" | + +--------------------------------+-------------------+------------------------------------+ + | VERBOSE | true | true | + +--------------------------------+-------------------+------------------------------------+ + | COMPILER | "intel" | "intel" | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_MAKE_GRID | true | true | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_MAKE_OROG | true | true | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_MAKE_SFC_CLIMO | true | true | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_GET_OBS_CCPA | false | false | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_GET_OBS_MRMS | false | false | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_GET_OBS_NDAS | false | false | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_VX_GRIDSTAT | false | false | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_VX_POINTSTAT | false | false | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_VX_ENSGRID | false | false | + +--------------------------------+-------------------+------------------------------------+ + | RUN_TASK_VX_ENSPOINT | false | false | + +--------------------------------+-------------------+------------------------------------+ + | EXTRN_MDL_NAME_ICS | "FV3GFS" | "FV3GFS" | + +--------------------------------+-------------------+------------------------------------+ + | FV3GFS_FILE_FMT_ICS | "nemsio" | "grib2" | + +--------------------------------+-------------------+------------------------------------+ + | EXTRN_MDL_NAME_LBCS | "FV3GFS" | "FV3GFS" | + +--------------------------------+-------------------+------------------------------------+ + | FV3GFS_FILE_FMT_LBCS | "nemsio" | "grib2" | + +--------------------------------+-------------------+------------------------------------+ + | LBC_SPEC_INTVL_HRS | 6 | 6 | + +--------------------------------+-------------------+------------------------------------+ + | WTIME_RUN_FCST | "04:30:00" | "02:00:00" | + +--------------------------------+-------------------+------------------------------------+ + | QUILTING | true | true | + +--------------------------------+-------------------+------------------------------------+ + | PREDEF_GRID_NAME | "" | "RRFS_CONUS_25km" | + +--------------------------------+-------------------+------------------------------------+ + | DO_ENSEMBLE | false | false | + +--------------------------------+-------------------+------------------------------------+ + | NUM_ENS_MEMBERS | 1 | 2 | + +--------------------------------+-------------------+------------------------------------+ + + +To get started, make a copy of ``config.community.yaml``. From the ``ufs-srweather-app`` directory, run: + +.. code-block:: console + + cd $SRW/ush + cp config.community.yaml config.yaml + +The default settings in this file include a predefined 25-km :term:`CONUS` grid (RRFS_CONUS_25km), the :term:`GFS` v16 physics suite (FV3_GFS_v16 :term:`CCPP`), and :term:`FV3`-based GFS raw external model data for initialization. + +.. note:: + + Users who are accustomed to the former shell script workflow can reuse and old ``config.sh`` file by setting ``EXPT_CONFIG_FN: "config.sh"`` in ``config_defaults.yaml``. Alternatively, users can convert their ``config.sh`` file to a ``config.yaml`` file by running: + + .. code-block:: console + + ./config_utils.py -c $PWD/config.sh -t $PWD/config_defaults.yaml -o yaml >config.yaml + +Next, users should edit the new ``config.yaml`` file to customize it for their machine. At a minimum, users must change the ``MACHINE`` and ``ACCOUNT`` variables. Then, they can choose a name for the experiment directory by setting ``EXPT_SUBDIR``. If users have pre-staged initialization data for the experiment, they can set ``USE_USER_STAGED_EXTRN_FILES: true``, and set the paths to the data for ``EXTRN_MDL_SOURCE_BASEDIR_ICS`` and ``EXTRN_MDL_SOURCE_BASEDIR_LBCS``. If the modulefile used to set up the build environment in :numref:`Section %s ` uses a GNU compiler, check that the line ``COMPILER: "gnu"`` appears in the ``config.yaml`` file. On platforms where Rocoto and :term:`cron` are available, users can automate resubmission of their experiment workflow by adding the following lines to the ``workflow:`` section of the ``config.yaml`` file: + +.. code-block:: console + + USE_CRON_TO_RELAUNCH: true + CRON_RELAUNCH_INTVL_MNTS: 3 + +.. note:: + + Generic Linux and MacOS users should refer to :numref:`Section %s ` for additional details on configuring an experiment and python environment. + +Sample ``config.yaml`` settings are indicated below for Level 1 platforms. Detailed guidance applicable to all systems can be found in :numref:`Chapter %s: Configuring the Workflow `, which discusses each variable and the options available. Additionally, information about the four predefined Limited Area Model (LAM) Grid options can be found in :numref:`Chapter %s: Limited Area Model (LAM) Grids `. + +On Level 1 systems, the following fields will need to be updated or added to the appropriate section of the ``config.yaml`` file in order to run the out-of-the-box SRW App case: + +.. code-block:: console + + user: + MACHINE: hera + ACCOUNT: an_account + workflow: + EXPT_SUBDIR: test_community + task_get_extrn_ics: + USE_USER_STAGED_EXTRN_FILES: true + EXTRN_MDL_SOURCE_BASEDIR_ICS: "/path/to/UFS_SRW_App/develop/input_model_data///" + task_get_extrn_lbcs: + USE_USER_STAGED_EXTRN_FILES: true + EXTRN_MDL_SOURCE_BASEDIR_LBCS: "/path/to/UFS_SRW_App/develop/input_model_data///" + +where: + * ``MACHINE`` refers to a valid machine name (see :numref:`Section %s ` for options). + * ``ACCOUNT`` refers to a valid account name. Not all systems require a valid account name, but most do. + + .. hint:: + + To determine an appropriate ACCOUNT field for Level 1 systems, run ``groups``, and it will return a list of projects you have permissions for. Not all of the listed projects/groups have an HPC allocation, but those that do are potentially valid account names. + + * ``EXPT_SUBDIR`` is changed to an experiment name of the user's choice. + * ```` is the path to the SRW App data on the user's machine (see :numref:`Section %s `). + * ```` refers to a subdirectory containing the experiment data from a particular model. Valid values on Level 1 systems correspond to the valid values for ``EXTRN_MDL_NAME_ICS`` and ``EXTRN_MDL_NAME_LBCS`` (see :numref:`Chapter %s ` for options). + * ```` refers to one of 3 possible data formats: ``grib2``, ``nemsio``, or ``netcdf``. + * ```` refers to a subdirectory containing data for the :term:`cycle` date (in YYYYMMDDHH format). + +For example, to run the out-of-the-box experiment on Gaea, add or modify variables in the ``user``, ``workflow``, ``task_get_extrn_ics``, and ``task_get_extrn_lbcs`` sections of ``config.yaml`` (unmodified variables are not shown in this example): + + .. code-block:: + + user: + MACHINE: gaea + ACCOUNT: hfv3gfs + workflow: + EXPT_SUBDIR: run_basic_srw + task_get_extrn_ics: + USE_USER_STAGED_EXTRN_FILES: true + EXTRN_MDL_SOURCE_BASEDIR_ICS: /lustre/f2/pdata/ncep/UFS_SRW_App/develop/input_model_data/FV3GFS/grib2/2019061518 + task_get_extrn_lbcs: + USE_USER_STAGED_EXTRN_FILES: true + EXTRN_MDL_SOURCE_BASEDIR_LBCS: /lustre/f2/pdata/ncep/UFS_SRW_App/develop/input_model_data/FV3GFS/grib2/2019061518 + +To determine whether the ``config.yaml`` file adjustments are valid, users can run the following script from the ``ush`` directory: + +.. code-block:: console + + ./config_utils.py -c $PWD/config.yaml -v $PWD/config_defaults.yaml + +A correct ``config.yaml`` file will output a ``SUCCESS`` message. A ``config.yaml`` file with problems will output a ``FAILURE`` message describing the problem. For example: + +.. code-block:: console + + INVALID ENTRY: EXTRN_MDL_FILES_ICS=[] + FAILURE + +.. note:: + + The regional workflow must be loaded for the ``config_utils.py`` script to validate the ``config.yaml`` file. + +Valid values for configuration variables should be consistent with those in the ``ush/valid_param_vals.yaml`` script. In addition, various sample configuration files can be found within the subdirectories of ``tests/WE2E/test_configs``. + +To configure an experiment and python environment for a general Linux or Mac system, see the :ref:`next section `. To configure an experiment to run METplus verification tasks, see :numref:`Section %s `. Otherwise, skip to :numref:`Section %s `. + +.. _LinuxMacEnvConfig: + +User-specific Configuration on a General Linux/MacOS System +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The configuration process for Linux and MacOS systems is similar to the process for other systems, but it requires a few extra steps. + +.. note:: + Examples in this subsection presume that the user is running in the Terminal with a bash shell environment. If this is not the case, users will need to adjust the commands to fit their command line application and shell environment. + +.. _MacMorePackages: + +Install/Upgrade Mac-Specific Packages +```````````````````````````````````````` +MacOS requires the installation of a few additional packages and, possibly, an upgrade to bash. Users running on MacOS should execute the following commands: + +.. code-block:: console + + bash --version + brew upgrade bash + brew install coreutils + brew gsed + +.. _LinuxMacVEnv: + +Creating a Virtual Environment on Linux and Mac +`````````````````````````````````````````````````` + +Users should ensure that the following packages are installed and up-to-date: + +.. code-block:: console + + python3 -m pip --version + python3 -m pip install --upgrade pip + python3 -m ensurepip --default-pip + python3 -m pip install ruby OR (on MacOS only): brew install ruby + +Users must create a virtual regional workflow environment, store it in their ``$HOME/venv/`` directory, and install additional python packages: + +.. code-block:: console + + [[ -d $HOME/venv ]] | mkdir -p $HOME/venv + python3 -m venv $HOME/venv/regional_workflow + source $HOME/venv/regional_workflow/bin/activate + python3 -m pip install jinja2 + python3 -m pip install pyyaml + python3 -m pip install f90nml + +The virtual environment can be deactivated by running the ``deactivate`` command. The virtual environment built here will be reactivated in :numref:`Step %s ` and needs to be used to generate the workflow and run the experiment. + +.. _LinuxMacExptConfig: + +Configuring an Experiment on General Linux and MacOS Systems +`````````````````````````````````````````````````````````````` + +**Optional: Install Rocoto** + +.. note:: + Users may `install Rocoto `__ if they want to make use of a workflow manager to run their experiments. However, this option has not been tested yet on MacOS and has had limited testing on general Linux plaforms. + + +**Configure the SRW App:** + +Configure an experiment using a template. Copy the contents of ``config.community.yaml`` into ``config.yaml``: + +.. code-block:: console + + cd $SRW/ush + cp config.community.yaml config.yaml + +In the ``config.yaml`` file, set ``MACHINE: macos`` or ``MACHINE: linux``, and modify the account and experiment info. For example: + +.. code-block:: console + + user: + RUN_ENVIR: community + MACHINE: macos + ACCOUNT: user + workflow: + EXPT_SUBDIR: test_community + PREEXISTING_DIR_METHOD: rename + VERBOSE: true + COMPILER: gnu + task_run_fcst: + PREDEF_GRID_NAME: RRFS_CONUS_25km + QUILTING: true + +Due to the limited number of processors on MacOS systems, users must also configure the domain decomposition defaults (usually, there are only 8 CPUs in M1-family chips and 4 CPUs for x86_64 chips). + +For :ref:`Option 1 `, add the following information to ``config.yaml``: + +.. code-block:: console + + task_run_fcst: + LAYOUT_X: 3 + LAYOUT_Y: 2 + WRTCMP_write_groups: 1 + WRTCMP_write_tasks_per_group: 2 + +For :ref:`Option 2 `, add the following information to ``config.yaml``: + +.. code-block:: console + + task_run_fcst: + LAYOUT_X: 3 + LAYOUT_Y: 1 + WRTCMP_write_groups: 1 + WRTCMP_write_tasks_per_group: 1 + +.. note:: + The number of MPI processes required by the forecast will be equal to ``LAYOUT_X`` * ``LAYOUT_Y`` + ``WRTCMP_write_tasks_per_group``. + +**Configure the Machine File** + +Configure a ``macos.yaml`` or ``linux.yaml`` machine file in ``$SRW/ush/machine/`` based on the number of CPUs (``NCORES_PER_NODE``) in the system (usually 8 or 4 in MacOS; varies on Linux systems). Job scheduler (``SCHED``) options can be viewed :ref:`here `. Users must also set the path to the fix file directories. + +.. code-block:: console + + platform: + # Architecture information + WORKFLOW_MANAGER: none + NCORES_PER_NODE: 8 + SCHED: none + # Run commands for executables + RUN_CMD_FCST: 'mpirun -np ${PE_MEMBER01}' + RUN_CMD_POST: 'mpirun -np 4' + RUN_CMD_SERIAL: time + RUN_CMD_UTILS: 'mpirun -np 4' + # Commands to run at the start of each workflow task. + PRE_TASK_CMDS: '{ ulimit -a; }' + task_make_orog: + TOPO_DIR: path/to/FIXgsm/files # (path to location of static input files used by the make_orog task) + task_make_sfc_climo: + SFC_CLIMO_INPUT_DIR: path/to/FIXgsm/files # (path to location of static surface climatology input fields used by sfc_climo_gen) + task_run_fcst: + FIXaer: /path/to/FIXaer/files + FIXgsm: /path/to/FIXgsm/files + FIXlut: /path/to/FIXlut/files + data: + FV3GFS: /Users/username/DATA/UFS/FV3GFS # (used by setup.py to set the values of EXTRN_MDL_SOURCE_BASEDIR_ICS and EXTRN_MDL_SOURCE_BASEDIR_LBCS) + +The ``data:`` section of the machine file can point to various data sources that the user has pre-staged on disk. For example: + +.. code-block:: console + + data: + FV3GFS: + nemsio: /Users/username/DATA/UFS/FV3GFS/nemsio + grib2: /Users/username/DATA/UFS/FV3GFS/grib2 + netcdf: /Users/username/DATA/UFS/FV3GFS/netcdf + RAP: /Users/username/DATA/UFS/RAP/grib2 + HRRR: /Users/username/DATA/UFS/HRRR/grib2 + +This can be helpful when conducting a multiple experiments with different types of data. + +.. _VXConfig: + +Configure METplus Verification Suite (Optional) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Users who want to use the METplus verification suite to evaluate their forecasts need to add additional information to their ``config.yaml`` file. Other users may skip to the :ref:`next section `. + +.. attention:: + METplus *installation* is not included as part of the build process for this release of the SRW App. However, METplus is preinstalled on many `Level 1 & 2 `__ systems. For the v2.0.0 release, METplus *use* is supported on systems with a functioning METplus installation, although installation itself is not supported. For more information about METplus, see :numref:`Section %s `. + + .. COMMENT: Update note for release v2.1! + +.. note:: + If METplus users update their METplus installation, they must update the module load statements in ``ufs-srweather-app/modulefiles/tasks//run_vx.local`` file to correspond to their system's updated installation: + + .. code-block:: console + + module use -a + module load met/ + +To use METplus verification, the path to the MET and METplus directories must be added to ``config.yaml``: + +.. code-block:: console + + platform: + METPLUS_PATH: + MET_INSTALL_DIR: + +Users who have already staged the observation data needed for METplus (i.e., the :term:`CCPA`, :term:`MRMS`, and :term:`NDAS` data) on their system should set the path to this data and set the corresponding ``RUN_TASK_GET_OBS_*`` parameters to false in ``config.yaml``. + +.. code-block:: console + + platform: + CCPA_OBS_DIR: /path/to/UFS_SRW_App/develop/obs_data/ccpa/proc + MRMS_OBS_DIR: /path/to/UFS_SRW_App/develop/obs_data/mrms/proc + NDAS_OBS_DIR: /path/to/UFS_SRW_App/develop/obs_data/ndas/proc + workflow_switches: + RUN_TASK_GET_OBS_CCPA: false + RUN_TASK_GET_OBS_MRMS: false + RUN_TASK_GET_OBS_NDAS: false + +If users have access to NOAA :term:`HPSS` but have not pre-staged the data, they can simply set the ``RUN_TASK_GET_OBS_*`` tasks to true, and the machine will attempt to download the appropriate data from NOAA HPSS. In this case, the ``*_OBS_DIR`` paths must be set to the location where users want the downloaded data to reside. + +Users who do not have access to NOAA HPSS and do not have the data on their system will need to download :term:`CCPA`, :term:`MRMS`, and :term:`NDAS` data manually from collections of publicly available data, such as the ones listed `here `__. + +Next, the verification tasks must be turned on according to the user's needs. Users should add some or all of the following tasks to ``config.yaml``, depending on the verification procedure(s) they have in mind: + +.. code-block:: console + + workflow_switches: + RUN_TASK_VX_GRIDSTAT: true + RUN_TASK_VX_POINTSTAT: true + RUN_TASK_VX_ENSGRID: true + RUN_TASK_VX_ENSPOINT: true + +These tasks are independent, so users may set some values to true and others to false depending on the needs of their experiment. Note that the ENSGRID and ENSPOINT tasks apply only to ensemble model verification. Additional verification tasks appear in :numref:`Table %s `. More details on all of the parameters in this section are available in :numref:`Section %s `. + +.. _GenerateWorkflow: + +Generate the Regional Workflow +------------------------------------------- + +Run the following command from the ``ufs-srweather-app/ush`` directory to generate the workflow: + +.. code-block:: console + + ./generate_FV3LAM_wflow.py + +The last line of output from this script, starting with ``*/1 * * * *`` or ``*/3 * * * *``, can be saved and :ref:`used later ` to automatically run portions of the workflow if users have the Rocoto workflow manager installed on their system. + +This workflow generation script creates an experiment directory and populates it with all the data needed to run through the workflow. The flowchart in :numref:`Figure %s ` describes the experiment generation process. First, ``generate_FV3LAM_wflow.py`` runs the ``setup.py`` script to set the configuration parameters. Second, it symlinks the time-independent (fix) files and other necessary data input files from their location to the experiment directory (``$EXPTDIR``). Third, it creates the input namelist file ``input.nml`` based on the ``input.nml.FV3`` file in the ``parm`` directory. Lastly, it creates the workflow XML file ``FV3LAM_wflow.xml`` that is executed when running the experiment with the Rocoto workflow manager. + +The ``setup.py`` script reads three other configuration scripts in order: (1) ``config_defaults.yaml`` (:numref:`Section %s `), (2) ``config.yaml`` (:numref:`Section %s `), and (3) ``set_predef_grid_params.py``. If a parameter is specified differently in these scripts, the file containing the last defined value will be used. + +The generated workflow will appear in ``$EXPTDIR``, where ``EXPTDIR=${EXPT_BASEDIR}/${EXPT_SUBDIR}``. These variables were specified in the ``config.yaml`` file in :numref:`Step %s `. The settings for these paths can also be viewed in the console output from the ``./generate_FV3LAM_wflow.py`` script or in the ``log.generate_FV3LAM_wflow`` file, which can be found in ``$EXPTDIR``. + +.. _WorkflowGeneration: + +.. figure:: _static/SRW_regional_workflow_gen.png + :alt: Flowchart of the workflow generation process. Scripts are called in the following order: source_util_funcs.sh (which calls bash_utils), then set_FV3nml_sfc_climo_filenames.py, set_FV3nml_ens_stoch_seeds.py, create_diag_table_file.py, and setup.py. setup.py calls several scripts: set_cycle_dates.py, set_grid_params_GFDLgrid.py, set_grid_params_ESGgrid.py, link_fix.py, set_ozone_param.py, set_thompson_mp_fix_files.py, config_defaults.yaml, config.yaml, and valid_param_vals.yaml. Then, it sets a number of variables, including FIXgsm, TOPO_DIR, and SFC_CLIMO_INPUT_DIR variables. Next, set_predef_grid_params.py is called, and the FIXam and FIXLAM directories are set, along with the forecast input files. The setup script also calls set_extrn_mdl_params.py, sets the GRID_GEN_METHOD with HALO, checks various parameters, and generates shell scripts. Then, the workflow generation script sets up YAML-compliant strings and generates the actual Rocoto workflow XML file from the template file (fill_jinja_template.py). The workflow generation script checks the crontab file and, if applicable, copies certain fix files to the experiment directory. Then, it copies templates of various input files to the experiment directory and sets parameters for the input.nml file. Finally, it generates the workflow. Additional information on each step appears in comments within each script. + + *Experiment generation description* + +.. COMMENT: Get updated image/slides from Chan-Hoo! + +.. _WorkflowTaskDescription: + +Description of Workflow Tasks +-------------------------------- + +.. note:: + This section gives a general overview of workflow tasks. To begin running the workflow, skip to :numref:`Step %s ` + +:numref:`Figure %s ` illustrates the overall workflow. Individual tasks that make up the workflow are specified in the ``FV3LAM_wflow.xml`` file. :numref:`Table %s ` describes the function of each baseline task. The first three pre-processing tasks; ``MAKE_GRID``, ``MAKE_OROG``, and ``MAKE_SFC_CLIMO``; are optional. If the user stages pre-generated grid, orography, and surface climatology fix files, these three tasks can be skipped by adding the following lines to the ``config.yaml`` file before running the ``generate_FV3LAM_wflow.py`` script: + +.. code-block:: console + + workflow_switches: + RUN_TASK_MAKE_GRID: false + RUN_TASK_MAKE_OROG: false + RUN_TASK_MAKE_SFC_CLIMO: false + + +.. _WorkflowTasksFig: + +.. figure:: _static/SRW_wflow_flowchart.png + :alt: Flowchart of the workflow tasks. If the make_grid, make_orog, and make_sfc_climo tasks are toggled off, they will not be run. If toggled on, make_grid, make_orog, and make_sfc_climo will run consecutively by calling the corresponding exregional script in the scripts directory. The get_ics, get_lbcs, make_ics, make_lbcs, and run_fcst tasks call their respective exregional scripts. The run_post task will run, and if METplus verification tasks have been configured, those will run during post-processing by calling their exregional scripts. + + *Flowchart of the workflow tasks* + + +The ``FV3LAM_wflow.xml`` file runs the specific j-job scripts (``jobs/JREGIONAL_[task name]``) in the prescribed order when the experiment is launched via the ``launch_FV3LAM_wflow.sh`` script or the ``rocotorun`` command. Each j-job task has its own source script (or "ex-script") named ``exregional_[task name].sh`` in the ``scripts`` directory. Two database files named ``FV3LAM_wflow.db`` and ``FV3LAM_wflow_lock.db`` are generated and updated by the Rocoto calls. There is usually no need for users to modify these files. To relaunch the workflow from scratch, delete these two ``*.db`` files and then call the launch script repeatedly for each task. + + +.. _WorkflowTasksTable: + +.. table:: Baseline workflow tasks in the SRW App + + +----------------------+------------------------------------------------------------+ + | **Workflow Task** | **Task Description** | + +======================+============================================================+ + | make_grid | Pre-processing task to generate regional grid files. Only | + | | needs to be run once per experiment. | + +----------------------+------------------------------------------------------------+ + | make_orog | Pre-processing task to generate orography files. Only | + | | needs to be run once per experiment. | + +----------------------+------------------------------------------------------------+ + | make_sfc_climo | Pre-processing task to generate surface climatology files. | + | | Only needs to be run once per experiment. | + +----------------------+------------------------------------------------------------+ + | get_extrn_ics | Cycle-specific task to obtain external data for the | + | | initial conditions (ICs) | + +----------------------+------------------------------------------------------------+ + | get_extrn_lbcs | Cycle-specific task to obtain external data for the | + | | lateral boundary conditions (LBCs) | + +----------------------+------------------------------------------------------------+ + | make_ics | Generate initial conditions from the external data | + +----------------------+------------------------------------------------------------+ + | make_lbcs | Generate LBCs from the external data | + +----------------------+------------------------------------------------------------+ + | run_fcst | Run the forecast model (UFS Weather Model) | + +----------------------+------------------------------------------------------------+ + | run_post | Run the post-processing tool (UPP) | + +----------------------+------------------------------------------------------------+ + +In addition to the baseline tasks described in :numref:`Table %s ` above, users may choose to run some or all of the METplus verification tasks. These tasks are described in :numref:`Table %s ` below. + +.. _VXWorkflowTasksTable: + +.. table:: Verification (VX) workflow tasks in the SRW App + + +-----------------------+------------------------------------------------------------+ + | **Workflow Task** | **Task Description** | + +=======================+============================================================+ + | GET_OBS_CCPA | Retrieves and organizes hourly :term:`CCPA` data from NOAA | + | | HPSS. Can only be run if ``RUN_TASK_GET_OBS_CCPA: true`` | + | | *and* user has access to NOAA :term:`HPSS` data. | + +-----------------------+------------------------------------------------------------+ + | GET_OBS_NDAS | Retrieves and organizes hourly :term:`NDAS` data from NOAA | + | | HPSS. Can only be run if ``RUN_TASK_GET_OBS_NDAS: true`` | + | | *and* user has access to NOAA HPSS data. | + +-----------------------+------------------------------------------------------------+ + | GET_OBS_MRMS | Retrieves and organizes hourly :term:`MRMS` composite | + | | reflectivity and :term:`echo top` data from NOAA HPSS. Can | + | | only be run if ``RUN_TASK_GET_OBS_MRMS: true`` *and* user | + | | has access to NOAA HPSS data. | + +-----------------------+------------------------------------------------------------+ + | VX_GRIDSTAT | Runs METplus grid-to-grid verification for 1-h accumulated | + | | precipitation | + +-----------------------+------------------------------------------------------------+ + | VX_GRIDSTAT_REFC | Runs METplus grid-to-grid verification for composite | + | | reflectivity | + +-----------------------+------------------------------------------------------------+ + | VX_GRIDSTAT_RETOP | Runs METplus grid-to-grid verification for :term:`echo top`| + +-----------------------+------------------------------------------------------------+ + | VX_GRIDSTAT_##h | Runs METplus grid-to-grid verification for 3-h, 6-h, and | + | | 24-h (i.e., daily) accumulated precipitation. Valid values | + | | for ``##`` are ``03``, ``06``, and ``24``. | + +-----------------------+------------------------------------------------------------+ + | VX_POINTSTAT | Runs METplus grid-to-point verification for surface and | + | | upper-air variables | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID | Runs METplus grid-to-grid ensemble verification for 1-h | + | | accumulated precipitation. Can only be run if | + | | ``DO_ENSEMBLE: true`` and ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID_REFC | Runs METplus grid-to-grid ensemble verification for | + | | composite reflectivity. Can only be run if | + | | ``DO_ENSEMBLE: true`` and | + | | ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID_RETOP | Runs METplus grid-to-grid ensemble verification for | + | | :term:`echo top`. Can only be run if ``DO_ENSEMBLE: true`` | + | | and ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID_##h | Runs METplus grid-to-grid ensemble verification for 3-h, | + | | 6-h, and 24-h (i.e., daily) accumulated precipitation. | + | | Valid values for ``##`` are ``03``, ``06``, and ``24``. | + | | Can only be run if ``DO_ENSEMBLE: true`` and | + | | ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID_MEAN | Runs METplus grid-to-grid verification for ensemble mean | + | | 1-h accumulated precipitation. Can only be run if | + | | ``DO_ENSEMBLE: true`` and ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID_PROB | Runs METplus grid-to-grid verification for 1-h accumulated | + | | precipitation probabilistic output. Can only be run if | + | | ``DO_ENSEMBLE: true`` and ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID_MEAN_##h | Runs METplus grid-to-grid verification for ensemble mean | + | | 3-h, 6-h, and 24h (i.e., daily) accumulated precipitation. | + | | Valid values for ``##`` are ``03``, ``06``, and ``24``. | + | | Can only be run if ``DO_ENSEMBLE: true`` and | + | | ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID_PROB_##h | Runs METplus grid-to-grid verification for 3-h, 6-h, and | + | | 24h (i.e., daily) accumulated precipitation probabilistic | + | | output. Valid values for ``##`` are ``03``, ``06``, and | + | | ``24``. Can only be run if ``DO_ENSEMBLE: true`` and | + | | ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID_PROB_REFC | Runs METplus grid-to-grid verification for ensemble | + | | probabilities for composite reflectivity. Can only be run | + | | if ``DO_ENSEMBLE: true`` and | + | | ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSGRID_PROB_RETOP | Runs METplus grid-to-grid verification for ensemble | + | | probabilities for :term:`echo top`. Can only be run if | + | | ``DO_ENSEMBLE: true`` and ``RUN_TASK_VX_ENSGRID: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSPOINT | Runs METplus grid-to-point ensemble verification for | + | | surface and upper-air variables. Can only be run if | + | | ``DO_ENSEMBLE: true`` and ``RUN_TASK_VX_ENSPOINT: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSPOINT_MEAN | Runs METplus grid-to-point verification for ensemble mean | + | | surface and upper-air variables. Can only be run if | + | | ``DO_ENSEMBLE: true`` and ``RUN_TASK_VX_ENSPOINT: true``. | + +-----------------------+------------------------------------------------------------+ + | VX_ENSPOINT_PROB | Runs METplus grid-to-point verification for ensemble | + | | probabilities for surface and upper-air variables. Can | + | | only be run if ``DO_ENSEMBLE: true`` and | + | | ``RUN_TASK_VX_ENSPOINT: true``. | + +-----------------------+------------------------------------------------------------+ + + +.. _Run: + +Run the Workflow +======================= + +The workflow can be run using the Rocoto workflow manager (see :numref:`Section %s `) or using standalone wrapper scripts (see :numref:`Section %s `). + +.. attention:: + + If users are running the SRW App on a system that does not have Rocoto installed (e.g., `Level 3 & 4 `__ systems, such as MacOS or generic Linux systems), they should follow the process outlined in :numref:`Section %s ` instead of the instructions in this section. + + +.. _UseRocoto: + +Run the Workflow Using Rocoto +-------------------------------- + +The information in this section assumes that Rocoto is available on the desired platform. All official HPC platforms for the UFS SRW App release make use of the Rocoto workflow management software for running experiments. However, if Rocoto is not available, it is still possible to run the workflow using stand-alone scripts according to the process outlined in :numref:`Section %s `. + +There are three ways to run the workflow with Rocoto: (1) automation via crontab (2) by calling the ``launch_FV3LAM_wflow.sh`` script, and (3) by manually calling the ``rocotorun`` command. + +.. note:: + Users may find it helpful to review :numref:`Chapter %s ` to gain a better understanding of Rocoto commands and workflow management before continuing, but this is not required to run the experiment. + +Optionally, an environment variable can be set to navigate to the ``$EXPTDIR`` more easily. If the login shell is bash, it can be set as follows: + +.. code-block:: console + + export EXPTDIR=// + +If the login shell is csh/tcsh, it can be set using: + +.. code-block:: console + + setenv EXPTDIR // + + +.. _Automate: + +Automated Option +^^^^^^^^^^^^^^^^^^^ + +The simplest way to run the Rocoto workflow is to automate the process using a job scheduler such as :term:`Cron`. For automatic resubmission of the workflow at regular intervals (e.g., every minute), the user can add the following commands to their ``config.yaml`` file *before* generating the experiment: + +.. code-block:: console + + USE_CRON_TO_RELAUNCH: true + CRON_RELAUNCH_INTVL_MNTS: 3 + +This will automatically add an appropriate entry to the user's :term:`cron table` and launch the workflow. Alternatively, the user can add a crontab entry using the ``crontab -e`` command. As mentioned in :numref:`Section %s `, the last line of output from ``./generate_FV3LAM_wflow.py`` (starting with ``*/3 * * * *``), can be pasted into the crontab file. It can also be found in the ``$EXPTDIR/log.generate_FV3LAM_wflow`` file. The crontab entry should resemble the following: + +.. code-block:: console + + */3 * * * * cd && ./launch_FV3LAM_wflow.sh called_from_cron="TRUE" + +where ```` is changed to correspond to the user's ``$EXPTDIR``. The number ``3`` can be changed to a different positive integer and simply means that the workflow will be resubmitted every three minutes. + +.. hint:: + + * On NOAA Cloud instances, ``*/1 * * * *`` (or ``CRON_RELAUNCH_INTVL_MNTS: 1``) is the preferred option for cron jobs because compute nodes will shut down if they remain idle too long. If the compute node shuts down, it can take 15-20 minutes to start up a new one. + * On other NOAA HPC systems, admins discourage the ``*/1 * * * *`` due to load problems. ``*/3 * * * *`` (or ``CRON_RELAUNCH_INTVL_MNTS: 3``) is the preferred option for cron jobs on non-NOAA Cloud systems. + +To check the experiment progress: + +.. code-block:: console + + cd $EXPTDIR + rocotostat -w FV3LAM_wflow.xml -d FV3LAM_wflow.db -v 10 + + + +After finishing the experiment, open the crontab using ``crontab -e`` and delete the crontab entry. + +.. note:: + + On Orion, *cron* is only available on the orion-login-1 node, so users will need to work on that node when running *cron* jobs on Orion. + +.. _Success: + +The workflow run is complete when all tasks have "SUCCEEDED". If everything goes smoothly, users will eventually see a workflow status table similar to the following: + +.. code-block:: console + + CYCLE TASK JOBID STATE EXIT STATUS TRIES DURATION + ========================================================================================================== + 201906150000 make_grid 4953154 SUCCEEDED 0 1 5.0 + 201906150000 make_orog 4953176 SUCCEEDED 0 1 26.0 + 201906150000 make_sfc_climo 4953179 SUCCEEDED 0 1 33.0 + 201906150000 get_extrn_ics 4953155 SUCCEEDED 0 1 2.0 + 201906150000 get_extrn_lbcs 4953156 SUCCEEDED 0 1 2.0 + 201906150000 make_ics 4953184 SUCCEEDED 0 1 16.0 + 201906150000 make_lbcs 4953185 SUCCEEDED 0 1 71.0 + 201906150000 run_fcst 4953196 SUCCEEDED 0 1 1035.0 + 201906150000 run_post_f000 4953244 SUCCEEDED 0 1 5.0 + 201906150000 run_post_f001 4953245 SUCCEEDED 0 1 4.0 + ... + 201906150000 run_post_f012 4953381 SUCCEEDED 0 1 7.0 + +If users choose to run METplus verification tasks as part of their experiment, the output above will include additional lines after ``run_post_f012``. The output will resemble the following but may be significantly longer when using ensemble verification: + +.. code-block:: console + + CYCLE TASK JOBID STATE EXIT STATUS TRIES DURATION + ========================================================================================================== + 201906150000 make_grid 30466134 SUCCEEDED 0 1 5.0 + ... + 201906150000 run_post_f012 30468271 SUCCEEDED 0 1 7.0 + 201906150000 run_gridstatvx 30468420 SUCCEEDED 0 1 53.0 + 201906150000 run_gridstatvx_refc 30468421 SUCCEEDED 0 1 934.0 + 201906150000 run_gridstatvx_retop 30468422 SUCCEEDED 0 1 1002.0 + 201906150000 run_gridstatvx_03h 30468491 SUCCEEDED 0 1 43.0 + 201906150000 run_gridstatvx_06h 30468492 SUCCEEDED 0 1 29.0 + 201906150000 run_gridstatvx_24h 30468493 SUCCEEDED 0 1 20.0 + 201906150000 run_pointstatvx 30468423 SUCCEEDED 0 1 670.0 + + +Launch the Rocoto Workflow Using a Script +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Users who prefer not to automate their experiments can run the Rocoto workflow using the ``launch_FV3LAM_wflow.sh`` script provided. Simply call it without any arguments from the experiment directory: + +.. code-block:: console + + cd $EXPTDIR + ./launch_FV3LAM_wflow.sh + +This script creates a log file named ``log.launch_FV3LAM_wflow`` in ``$EXPTDIR`` or appends information to the file if it already exists. The launch script also creates the ``log/FV3LAM_wflow.log`` file, which shows Rocoto task information. Check the end of the log file periodically to see how the experiment is progressing: + +.. code-block:: console + + tail -n 40 log.launch_FV3LAM_wflow + +In order to launch additional tasks in the workflow, call the launch script again; this action will need to be repeated until all tasks in the workflow have been launched. To (re)launch the workflow and check its progress on a single line, run: + +.. code-block:: console + + ./launch_FV3LAM_wflow.sh; tail -n 40 log.launch_FV3LAM_wflow + +This will output the last 40 lines of the log file, which list the status of the workflow tasks (e.g., SUCCEEDED, DEAD, RUNNING, SUBMITTING, QUEUED). The number 40 can be changed according to the user's preferences. The output will look like this: + +.. code-block:: console + + CYCLE TASK JOBID STATE EXIT STATUS TRIES DURATION + ====================================================================================================== + 202006170000 make_grid druby://hfe01:33728 SUBMITTING - 0 0.0 + 202006170000 make_orog - - - - - + 202006170000 make_sfc_climo - - - - - + 202006170000 get_extrn_ics druby://hfe01:33728 SUBMITTING - 0 0.0 + 202006170000 get_extrn_lbcs druby://hfe01:33728 SUBMITTING - 0 0.0 + 202006170000 make_ics - - - - - + 202006170000 make_lbcs - - - - - + 202006170000 run_fcst - - - - - + 202006170000 run_post_00 - - - - - + 202006170000 run_post_01 - - - - - + 202006170000 run_post_02 - - - - - + 202006170000 run_post_03 - - - - - + 202006170000 run_post_04 - - - - - + 202006170000 run_post_05 - - - - - + 202006170000 run_post_06 - - - - - + + Summary of workflow status: + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + 0 out of 1 cycles completed. + Workflow status: IN PROGRESS + +If all the tasks complete successfully, the "Workflow status" at the bottom of the log file will change from "IN PROGRESS" to "SUCCESS". If certain tasks could not complete, the "Workflow status" will instead change to "FAILURE". Error messages for each specific task can be found in the task log files located in ``$EXPTDIR/log``. + +The workflow run is complete when all tasks have "SUCCEEDED", and the ``rocotostat`` command outputs a table similar to the one :ref:`above `. + + +.. _RocotoManualRun: + +Launch the Rocoto Workflow Manually +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**Load Rocoto** + +Instead of running the ``./launch_FV3LAM_wflow.sh`` script, users can load Rocoto and any other required modules manually. This gives the user more control over the process and allows them to view experiment progress more easily. On Level 1 systems, the Rocoto modules are loaded automatically in :numref:`Step %s `. For most other systems, users can load a modified ``wflow_`` modulefile, or they can use a variant on the following commands to load the Rocoto module: + +.. code-block:: console + + module use + module load rocoto + +Some systems may require a version number (e.g., ``module load rocoto/1.3.3``) + +**Run the Rocoto Workflow** + +After loading Rocoto, ``cd`` to the experiment directory and call ``rocotorun`` to launch the workflow tasks. This will start any tasks that do not have a dependency. As the workflow progresses through its stages, ``rocotostat`` will show the state of each task and allow users to monitor progress: + +.. code-block:: console + + cd $EXPTDIR + rocotorun -w FV3LAM_wflow.xml -d FV3LAM_wflow.db -v 10 + rocotostat -w FV3LAM_wflow.xml -d FV3LAM_wflow.db -v 10 + +The ``rocotorun`` and ``rocotostat`` commands above will need to be resubmitted regularly and repeatedly until the experiment is finished. In part, this is to avoid having the system time out. This also ensures that when one task ends, tasks dependent on it will run as soon as possible, and ``rocotostat`` will capture the new progress. + +If the experiment fails, the ``rocotostat`` command will indicate which task failed. Users can look at the log file in the ``log`` subdirectory for the failed task to determine what caused the failure. For example, if the ``make_grid`` task failed, users can open the ``make_grid.log`` file to see what caused the problem: + +.. code-block:: console + + cd $EXPTDIR/log + vi make_grid.log + +.. note:: + + If users have the `Slurm workload manager `__ on their system, they can run the ``squeue`` command in lieu of ``rocotostat`` to check what jobs are currently running. + + +.. _RunUsingStandaloneScripts: + +Run the Workflow Using Stand-Alone Scripts +--------------------------------------------- + +The regional workflow can be run using standalone shell scripts in cases where the Rocoto software is not available on a given platform. If Rocoto *is* available, see :numref:`Section %s ` to run the workflow using Rocoto. + +#. ``cd`` into the experiment directory. For example, from ``ush``, presuming default directory settings: + + .. code-block:: console + + cd ../../expt_dirs/test_community + +#. Set the environment variable ``$EXPTDIR`` for either bash or csh, respectively: + + .. code-block:: console + + export EXPTDIR=`pwd` + setenv EXPTDIR `pwd` + +#. Copy the wrapper scripts from the ``ush`` directory into the experiment directory. Each workflow task has a wrapper script that sets environment variables and runs the job script. + + .. code-block:: console + + cp /ufs-srweather-app/ush/wrappers/* . + +#. Set the ``OMP_NUM_THREADS`` variable. + + .. code-block:: console + + export OMP_NUM_THREADS=1 + +#. Run each of the listed scripts in order. Scripts with the same stage number (listed in :numref:`Table %s `) may be run simultaneously. + + .. code-block:: console + + ./run_make_grid.sh + ./run_get_ics.sh + ./run_get_lbcs.sh + ./run_make_orog.sh + ./run_make_sfc_climo.sh + ./run_make_ics.sh + ./run_make_lbcs.sh + ./run_fcst.sh + ./run_post.sh + +Check the batch script output file in your experiment directory for a “SUCCESS” message near the end of the file. + +.. _RegionalWflowTasks: + +.. table:: List of tasks in the regional workflow in the order that they are executed. + Scripts with the same stage number may be run simultaneously. The number of + processors and wall clock time is a good starting point for Cheyenne or Hera + when running a 48-h forecast on the 25-km CONUS domain. For a brief description of tasks, see :numref:`Table %s `. + + +------------+------------------------+----------------+----------------------------+ + | **Stage/** | **Task Run Script** | **Number of** | **Wall Clock Time (H:mm)** | + | | | **Processors** | | + +============+========================+================+============================+ + | 1 | run_get_ics.sh | 1 | 0:20 (depends on HPSS vs | + | | | | FTP vs staged-on-disk) | + +------------+------------------------+----------------+----------------------------+ + | 1 | run_get_lbcs.sh | 1 | 0:20 (depends on HPSS vs | + | | | | FTP vs staged-on-disk) | + +------------+------------------------+----------------+----------------------------+ + | 1 | run_make_grid.sh | 24 | 0:20 | + +------------+------------------------+----------------+----------------------------+ + | 2 | run_make_orog.sh | 24 | 0:20 | + +------------+------------------------+----------------+----------------------------+ + | 3 | run_make_sfc_climo.sh | 48 | 0:20 | + +------------+------------------------+----------------+----------------------------+ + | 4 | run_make_ics.sh | 48 | 0:30 | + +------------+------------------------+----------------+----------------------------+ + | 4 | run_make_lbcs.sh | 48 | 0:30 | + +------------+------------------------+----------------+----------------------------+ + | 5 | run_fcst.sh | 48 | 0:30 | + +------------+------------------------+----------------+----------------------------+ + | 6 | run_post.sh | 48 | 0:25 (2 min per output | + | | | | forecast hour) | + +------------+------------------------+----------------+----------------------------+ + +Users can access log files for specific tasks in the ``$EXPTDIR/log`` directory. To see how the experiment is progressing, users can also check the end of the ``log.launch_FV3LAM_wflow`` file from the command line: + +.. code-block:: console + + tail -n 40 log.launch_FV3LAM_wflow + +.. hint:: + If any of the scripts return an error that "Primary job terminated normally, but one process returned a non-zero exit code," there may not be enough space on one node to run the process. On an HPC system, the user will need to allocate a(nother) compute node. The process for doing so is system-dependent, and users should check the documentation available for their HPC system. Instructions for allocating a compute node on NOAA Cloud systems can be viewed in :numref:`Section %s ` as an example. + +.. note:: + On most HPC systems, users will need to submit a batch job to run multi-processor jobs. On some HPC systems, users may be able to run the first two jobs (serial) on a login node/command-line. Example scripts for Slurm (Hera) and PBS (Cheyenne) resource managers are provided (``sq_job.sh`` and ``qsub_job.sh``, respectively). These examples will need to be adapted to each user's system. Alternatively, some batch systems allow users to specify most of the settings on the command line (with the ``sbatch`` or ``qsub`` command, for example). + + + +.. _PlotOutput: + +Plot the Output +=============== +Two python scripts are provided to generate plots from the :term:`FV3`-LAM post-processed :term:`GRIB2` output. Information on how to generate the graphics can be found in :numref:`Chapter %s `. diff --git a/docs/UsersGuide/source/WE2Etests.rst b/docs/UsersGuide/source/WE2Etests.rst index 77026b09bd..305ef84cb4 100644 --- a/docs/UsersGuide/source/WE2Etests.rst +++ b/docs/UsersGuide/source/WE2Etests.rst @@ -33,9 +33,9 @@ The test configuration files for these categories are located in the following d ufs-srweather-app/regional_workflow/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco ufs-srweather-app/regional_workflow/tests/WE2E/test_configs/wflow_features -The script to run the WE2E tests is named ``run_WE2E_tests.sh`` and is located in the directory ``ufs-srweather-app/regional_workflow/tests/WE2E``. Each WE2E test has an associated configuration file named ``config.${test_name}.sh``, where ``${test_name}`` is the name of the corresponding test. These configuration files are subsets of the full range of ``config.sh`` experiment configuration options. (See :numref:`Section %s ` for all configurable options and :numref:`Section %s ` for information on configuring ``config.sh``.) For each test, the ``run_WE2E_tests.sh`` script reads in the test configuration file and generates from it a complete ``config.sh`` file. It then calls ``generate_FV3LAM_wflow.sh``, which in turn reads in ``config.sh`` and generates a new experiment for the test. The name of each experiment directory is set to that of the corresponding test, and a copy of ``config.sh`` for each test is placed in its experiment directory. +The script to run the WE2E tests is named ``run_WE2E_tests.sh`` and is located in the directory ``ufs-srweather-app/regional_workflow/tests/WE2E``. Each WE2E test has an associated configuration file named ``config.${test_name}.yaml``, where ``${test_name}`` is the name of the corresponding test. These configuration files are subsets of the full range of ``config.yaml`` experiment configuration options. (See :numref:`Section %s ` for all configurable options and :numref:`Section %s ` for information on configuring ``config.yaml``.) For each test, the ``run_WE2E_tests.sh`` script reads in the test configuration file and generates from it a complete ``config.yaml`` file. It then calls ``generate_FV3LAM_wflow.py``, which in turn reads in ``config.yaml`` and generates a new experiment for the test. The name of each experiment directory is set to that of the corresponding test, and a copy of ``config.yaml`` for each test is placed in its experiment directory. -Since ``run_WE2E_tests.sh`` calls ``generate_FV3LAM_wflow.sh`` for each test, the +Since ``run_WE2E_tests.sh`` calls ``generate_FV3LAM_wflow.py`` for each test, the Python modules required for experiment generation must be loaded before ``run_WE2E_tests.sh`` can be called. See :numref:`Section %s ` for information on loading the Python environment on supported platforms. Note also that ``run_WE2E_tests.sh`` assumes that all of @@ -61,7 +61,7 @@ Users may specify the set of tests to run by creating a text file, such as ``my_ (and ``Ctrl + D`` to exit). For each test in ``my_tests.txt``, ``run_WE2E_tests.sh`` will generate a new experiment directory and, by default, create a new :term:`cron` job in the user's cron table that will (re)launch the workflow every 2 minutes. This cron job calls the workflow launch script ``launch_FV3LAM_wflow.sh`` until the workflow either completes successfully (i.e., all tasks are successful) or fails (i.e., at least one task fails). The cron job is then removed from the user's cron table. -The examples below demonstrate several common ways that ``run_WE2E_tests.sh`` can be called with the ``my_tests.txt`` file above. These examples assume that the user has already built the SRW App and loaded the regional workflow as described in :numref:`Chapter %s ` (and in detail in :numref:`Chapter %s `). +The examples below demonstrate several common ways that ``run_WE2E_tests.sh`` can be called with the ``my_tests.txt`` file above. These examples assume that the user has already built the SRW App and loaded the regional workflow as described in :numref:`Chapter %s ` (and in detail in Chapters :numref:`%s ` and :numref:`%s `). #. To run the tests listed in ``my_tests.txt`` on Hera and charge the computational resources used to the "rtrr" account, use: @@ -252,7 +252,7 @@ Checking Test Status If :term:`cron` jobs are used to periodically relaunch the tests, the status of each test can be checked by viewing the end of the log file (``log.launch_FV3LAM_wflow``). Otherwise (or alternatively), the ``rocotorun``/``rocotostat`` combination of commands can be used. (See :numref:`Section %s ` for details.) The SRW App also provides the script ``get_expts_status.sh`` in the directory -``ufs-srweather-app/regional_workflow/tests/WE2E``, which can be used to generate +``ufs-srweather-app/tests/WE2E``, which can be used to generate a status summary for all tests in a given base directory. This script updates the workflow status of each test by internally calling ``launch_FV3LAM_wflow.sh``. Then, it prints out the status of the various tests in the command prompt. It also creates a status report file named ``expts_status_${create_date}.txt`` (where ``create_date`` @@ -329,11 +329,11 @@ Adding a New Test --------------------- To add a new test named, e.g., ``new_test01``, to one of the existing test categories, such as ``wflow_features``: -#. Choose an existing test configuration file in any one of the category directories that matches most closely the new test to be added. Copy that file to ``config.new_test01.sh`` and, if necessary, move it to the ``wflow_features`` category directory. +#. Choose an existing test configuration file in any one of the category directories that matches most closely the new test to be added. Copy that file to ``config.new_test01.yaml`` and, if necessary, move it to the ``wflow_features`` category directory. -#. Edit the header comments in ``config.new_test01.sh`` so that they properly describe the new test. +#. Edit the header comments in ``config.new_test01.yaml`` so that they properly describe the new test. -#. Edit the contents of ``config.new_test01.sh`` by modifying existing experiment variable values and/or adding new variables such that the test runs with the intended configuration. +#. Edit the contents of ``config.new_test01.yaml`` by modifying existing experiment variable values and/or adding new variables such that the test runs with the intended configuration. .. _AddNewCategory: @@ -371,14 +371,14 @@ To prevent proliferation of WE2E tests, users might want to use the same test fo in the ``grids_extrn_mdls_suites_community`` category. This checks for the successful completion of the Rocoto workflow running a combination of the ``RRFS_CONUScompact_25km`` grid, the ``FV3GFS`` model data for :term:`ICs` and :term:`LBCs`, and the ``FV3_GFS_v16`` physics suite. If this test also happens to use the inline post capability of the UFS :term:`Weather Model` (it currently doesn't; this is only a hypothetical example), then this test can also be used to ensure that the inline post feature of the App/Weather Model (which is activated in the App by setting ``WRITE_DOPOST`` to ``"TRUE"``) is working properly. Since this test will serve two purposes, it should have two names --- one per purpose. -To set the second (alternate) name to ``activate_inline_post``, the user needs to create a symlink named ``config.activate_inline_post.sh`` in the ``wflow_features`` category directory that points to the original configuration file (``config.grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.sh``) in the ``grids_extrn_mdls_suites_community`` category directory: +To set the second (alternate) name to ``activate_inline_post``, the user needs to create a symlink named ``config.activate_inline_post.yaml`` in the ``wflow_features`` category directory that points to the original configuration file (``config.grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml``) in the ``grids_extrn_mdls_suites_community`` category directory: .. code-block:: console - ln -fs --relative + ln -fs --relative In this situation, the primary name for the test is ``grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16`` -(because ``config.grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.sh`` is an actual file, not a symlink), and ``activate_inline_post`` is an alternate name. This approach of allowing multiple names for the same test makes it easier to identify the multiple purposes that a test may serve. +(because ``config.grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml`` is an actual file, not a symlink), and ``activate_inline_post`` is an alternate name. This approach of allowing multiple names for the same test makes it easier to identify the multiple purposes that a test may serve. .. note:: diff --git a/docs/UsersGuide/source/_static/SRW_build_process.png b/docs/UsersGuide/source/_static/SRW_build_process.png new file mode 100644 index 0000000000000000000000000000000000000000..ceb0cbad05203020a6f8b155107eb01f0e949888 GIT binary patch literal 59669 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 z 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 literal 0 HcmV?d00001 diff --git a/docs/UsersGuide/source/_static/SRW_overall_workflow_run.png b/docs/UsersGuide/source/_static/SRW_overall_workflow_run.png new file mode 100644 index 0000000000000000000000000000000000000000..2f2859e7e943462812574d08887c605f3be6b846 GIT binary patch literal 84193 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 literal 0 HcmV?d00001 diff --git a/docs/UsersGuide/source/_static/SRW_regional_workflow_gen.png b/docs/UsersGuide/source/_static/SRW_regional_workflow_gen.png new file mode 100644 index 0000000000000000000000000000000000000000..6f085589ed64cdfb47b1ccf70f772f64eeaf5631 GIT binary patch literal 163031 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

&i(%^Uz~3pBph;jR*i#KgIbZHBHD=k)515sJSs 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�jKOzio6CkX*%d!T^`H?={k9LK#I~0{|BKY(`Ku9Hk)2__ z@oi)qKVD95?*3avnn7UL} zv^e6}zLa_+Xy!tT|ECxnsyPPTOK{GkdHW_RVgC9Ml*lSaxhOcK=p6n?3iXg;SroD4 zDD)LcXFd)AE)GlhABty-8hU8=V73d+YWRMyYR5(Gx%j;hhvlo~Y1v3Lv&%WldmXSB zo^`K^iujb*5@$RurKXbT+eTAJQljNK>LA(3z4<1tO{dC zzqmi8vEf~ft>sg*tk0Y^uu4Fn)HQfk8eiYAkW~U=E3*uyH>?gr@74=-J2PkWN{`%D z!kzkBl~$Vr88vvtO`lk+)h=0dain{OgX;#3!v6x*=2-A$dFW=I`;(OUeCm0N*wG6s zyU%BYcbSDPzO>H(^EP-?Mm|e7l|GM3G4e6507<3H$($oU6tgorRkaw*%1fuyc&+S~ z6V|@z2~nQ=-mBpJ`P0H_H&wUj>SDX3@(Q=_P`*UooagW6`Z1uR1UzW1P%t%4>-tgW z!WlDY&lbpLBt%La&}@EYG<&Jdl7S=sRS&k(qF1oXDm|luT&(%N(8^SsB@@dwqI(!* z-ZKxG4MRK3viYvSz;2dVV&0mZQBKyaHMBnDuTd(L2>evktkn5iDwaErroO95%&!`M z`tx!hrbbkc2(CBa{`!ZCmy)J=OV!oi*k-`%gk}3v=GI$CPAz|U6xA&Ia9=IPx1MjW z3|o-e<*LKPLBdSNHtbnd@Vf1@l zUkDPx-y7RL$yY-5L&b^;AQtg*UD z)`2_eOVwGjY{pD|91{v*QP1p3GS&aKhzE<~TZ$5Bc`tZySwfS-Jw^Ot#vmll<>-Z) zPCez{d*UU6|Jo-)i~y&*E(%$*4|UDA{QHbPvc2THB`?pU{Jl@rMQ$HcQ1kQiRX|1x zoPc1@tW|^HOG1Jm%5v^-@n|DW%x6eswK0{eg3)>ZYLItTFymKTYH1m7&F=qszkn zuYt+@g%TIbTodlUH=;Q@ncPb4{fxuui}>3_rLJ*_J`KCgc>Yf-e?y9M4ba-LjP}Z= zUAVNgjLQ?>@aL3ZKB+1d4Xuw(zNy)IgyV_pIrod7tS+qHM$eHRQswE-&EL|few$gm znK7|DaQ(Bwv9A34s{f?dILCn1_tJkas69$nw8VU$ll}X1EDY$8raj9v z+q2qU^t*Bf(@Wz~f#2JK({slfp-AsnXBQ-GifiaJXh(;VM^jKqRs?P1R-D$`^3Q23 z5C7{XjU$F-UAuXFOvPzDbBd>K>mJm(2)vtT98w@wi}?F6t$UN3FX#4J)rMWEwNYBO zj={DdXLkSBvf;}7rRT%_6fMs{(tAHgu3BvupM}j+)PgdZp|aUjmrc2YoyV(i@0*)v zTnp-S)CKbSW2;ZeC_*nx>NeC;|9MdVA3OLAnxoZ6gQmH*4R$D{BwW&I!Mh)Ch2B1~ zEHLqtz4L_H#CW#A$|3WV|Ck=1#LmNmEoT}eA?E+S07AvNh&_uzmaQ@Aw80MqRIN5+q*NQU%#)~-nyz=If)(B#V-{cPVCgbCn428&r#0g zEND@QdiC5(CLD#!T7%W^DF?gFdnUtXsh_`b)|%aSw{G*~N&qddK=SpK4u;vYYyQ5w zxhdt~dOh8~h8rf=msh&&2;_B}vvNv?v_$^-`Ae-&u9;xAI$!VZwp|WZ>vr#t)BHI7 zE%=-j=%KeDDu9LQ=iAryr_0~Rue+U5FX6uA>8iaci}%i3WA1*S!gXOYo9ekM-5CP?0LGaU$HNPxkceO-dXmqxqp^@`DxW$;n$R~bN`!t(dBQn-(I^H zd28L)y<2jw2S;hF)YHwLHsKg(#S1(FfLjjPnNCmFoy3|o(V+gD2yfz_zBB(G>TV7B zVY0ATRds3B!h(h`H=c3bb*ly*M9W(`$@tM5Ym544Dp&3PJJ>y~HA>57y1%eUVew0UUDsVf+2fUnCI)i-Sy^4%>%0}lWjTqbLVPKsdS#RSoXlg z4MCw_rmmXkR{B0&>BerBgPSsnfT!XhTmWncDX@5XoqAN48zGi3>$aEaskK*9w(l$Z zw_4k#(tFP9TZX5>hXNy|iWK3-s@p}@vwOE}LN*ArWGx1C@bGp21Fz8R-~dj~iyuke zZ<+l~G+;1X^_yW6!u6^-$&o3ZTPR1o}@( zWuheR3E7|}4Zk=e{-Sz{wGn7cQ-#kp4^&siD1Z3B{&ujgTe~DWM4f DO~F@m literal 0 HcmV?d00001 diff --git a/docs/UsersGuide/source/_static/SRW_wflow_flowchart.png b/docs/UsersGuide/source/_static/SRW_wflow_flowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..0cee4f5e65df1e0a87cef48ccc241655a357e3f6 GIT binary patch literal 145622 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

FK5!0ZMnGa=>q z&9pxr6<3v#-Z5y_M2W9O3A=#((DAsGKtMvm(skzetgcM5gG9RC0gvqtz)W=KfP2j&x*;G4-1*Ea1hUt_HJ6>(u$M^m{Hp-3Qc;=oT_ zP8PC$aV$lW2&MOh;ZeY%dB44I$!7?z9(diKt(pUx0XKlVs{lG+2LM~e)-?XnSyZ@1 zsj=?#`pEpaAUaUs`x#opTdj9(*>;`TLiK+kF$RwCsKA^6N~lvX<8-$Bnq715dn#5V zbB1MA>tBF-v;Z`aIE}E@G)DXTr9wkOqUU*C&Pwz#bCu{+a)YS{3R=8wkJN(i*f&LH zd!U%ayfztT-vx=f8%a}BE@~{Ky|4G=Fg*l^qS{c;TgARhclEv9nd8=;YO zOvQPHbK#{qH+Cg#w2$ho|$}XpTdxaf=EB{lgh{g zh`03(|2EZDN=&0f?k;p};bwxHrL{dCc_a3%XWK`_8!ghX2N ziyKlF&1y55gOWk*57w%~xIp0b2}+r6J0r_{0r)GkfLH#hR1Km-(zZsXZmZiZxmgz3 zp)V!u%XF-+rzdy1fIFxBZ(cPSEz;$`fV5y9Wj8y~n0&_XMs^Pd7r2!NhEZ*=v3OZ1 zmDuS+phnBvdXDdO@wwpb17X$>a#x{BYYfb|1!Jgl$d8K;hL9)~pTfIn3Ip2tBbpOv z?q^ft^F?)j4hRh-wt3jswwRovwu4oQ0`JY8qpqi24O6A9q2R1u8`63vd;sC$^V|w86wH#m!V8@w)<9Pgn;PsM% zVXC0*8H~WEz8~-JC+2a3On!dp44$AsXK(v8V>)PL557ZWbPBj57bs-&)-lfa2Sg~K zo;Pu^*==0gfu8%-rbA|cFINyBT|zkh@`vpyKrv5$tbN3Nxb-J93NXP-Ao2nQ=0EuG zzz~7z{<8YstpUNn@!`tYub$9oDQ0sK;SiZ9S|tLH4xSpacrL4Jv(O*a^C{^tJw0nt-^11J2GL zAiJP+%nvYwA?*pa_ldHNGWWstrT4z<#j&3vGJ<@^)(=OWAf})}ahtmUhg%w!l*NRq zqaHQL@VyQ#TioZ1h?@`p9#R$34DvbfN&@UWBq(tV$`O43d3+res%;-BoEW&cV>s+Y zuI2yJ0`M1yuEJ3hf}^3vHSo(Wl22g|3F!N-0JlZ&ihu$fEP<;sGONlR%Pb})bEs(cccojUvz(NCtfxG;fGoQzWNBMB`T8!mR zH63c9sjU}G5|6#KEUU~#L&mA$5i@lly5rP{Zamh8f^?f>E0QacEig#;a_8Buq~d|_ zQw=5mqY&`kOru{JdDpliDL8T?X`Z?*9?JOaMd5k5jcqzq9ihAlJGxm~kOO!Ol~47thz@vN5n2(2!&>cw&@@0fGLsDm02c zsN&K}yPfVKSETY_ctMolxv0eQXp9HNo9Hl~r3QG^5|(lV1DcD!mZnf@2mkecLPB6ldvQnq)(`>0E2SzrI-dM|3Q8ny$OYE1I-IH-I5zwaBB? zVCJFn5vZ6%%#Ex`ZF{xMWAQep-LFT}2#mc9Jxpu`gEhwu{(LVFYn>7Ct?2f!eHX== zi!3}d@cee-#s6?Xj=^^Qf8DF*M4Lzmi5pm+B4kSJH9cJFMrdg0!N2`~P@;6Aet^(K z{-Cwbr}=&%8)F($W%1b*fiCjP*F>iTeH5u-IYdg)1F6XiWM6prkBF!iQ*RdW$}fYV zGQm+V6(U)I+Xd8VxMraX;Ri;!Cj}HN;k%@)BH--kW zE6g%M?$9gseke^kCMJ&BX~Go6Xb#f;%v|U2my@hgbI|dGuEX85s;+bV1UAE0@d4(o z@Zf9YP5rX@v8#`4vPsuY|Bfan;ljH^@$ji@H#<_=K{zVOR8wJ3q!tS|Fa}7h;h%j; zeUqMH@W6J+f1#zsnCt}gW2N%2SwT`aC)a&n|Dftw_Xjm#_KSN-IqI$dO($JB*R%sD z;x-r0TzCh(+XTK4yucmsu#eV@bAfSEVU9XXpTJdrrN z(KMjmJVrTqLBsVae*eN0u00Um`th@MLdz8C%teiXe`D-7e028Ll-3Lb#+7UgQRm4L zQ?*BjJwXI`#7qoqKeO|c=`9`pSu5}TNF{p%e2LSRA0Rnw3!DOS3D=l-aI}9#s6B)|+(H$bN&@`nNGVhbmk3t6dX!Cd?T~y z>*bYEI%K~{UlE`=1nDTa)!-Iz5&SHaU?yDzW6^)v2Rt1eTaTq36bPqoo1s6u7e;1-eMtb6wMMhl@6EssA$kF z!kWo(o98f>XqCE*$rOq|h5J~n%a*`UOp5xmsEaqIew> zunTlbhm?9%_+7hn{@U~WzyHuovBBB1s6)27@;|J-Wmr|+7xqiD=}w6a64FQtQk(8B z>244S*>rbEOLuo8NC`+whlDf|DvgAq@5JZ-Ugw?KfG zkg!=5xQ9(2&J;(|O(ZH>)^{^|m%{Qk0;}>ErqET_8JtWx*_6Em+4j`A_;kDb2Wi4e z`Y}x)T-FYd%U*{CR-elmxjn+ByI)Zk(VKttiOoJYnBN&TiLi$REsUm`7a|Xuee{jY zXad5_SQ8up>AU6aQVu&E9Sm(pZuJ!Ru{4oQ*<)1}UBQ8-#;E$Lc2LQKvLb$$k$o|! z?=R#OPb#3s%*KU;JF{;W{irX-D1+dQx@MG4j0|R;@3D|1gyXW-dOZEyD4&Gxy+Ml| z?BeUE6fE+B9N|=~_hed>qvmNWN6TuD|S7v|ySY;#_YRcuV!4F%A z)Mi&hk<}Z#1w{@s`=gk&7+2abv|Y@SVU4eoCiXIUrg`2`gf8VXpThVKgI|}B-GS&~ zw`e1F!&t;L158~}Q~ZA5tQ1ml#kahffwKMhA5j-o% zo9(^TR6hqnze?l@78Y)h>rTh!HF2zh8DiLj1sE6UR5??GZ62JFp`>g5 z+ssZ6vTP@0^ZK*SCzj~u=E$(-pXQ+BgAe(wfnFG7Udq@_hsNCH?t_e&$!(5w4-`4H z6IxQZbiri^pVx(As7Tx=!Vw^$_KK_>C0%&@2*2~ysvaP^+64$b;1dNAmA#g-mB2ipG7dj9sI|CpB` z5lm$31;MaAWb7|D#7EwXmJ+^al}kSl<_`8a5YM#4(5iv#Ii>5>x4hipAvP2VLi*?s zBolj^^tOFR>h}Vf@V>E}B@2h>0K`Pe#I9KS^|KFe(eWkNd#k&e67eUp_+vrQVVw2c z%O%}FB7@Gcj~?k19x{@dA{2B(hZ6$g%_&}Bj(AF@Kv+x>G-=Fv+ z_4J=u>klzs9CaSj_fT^&H&+iE;O& zA~~<(+f6PyMr0UrsIg-@jjng|amwNOkAZEs>YDZ&%zs62oJ25G-E5Gex(_fbiLcq; z&?oMHuhDorHg7I(OhL){-edALo|5Y}?+KBb2+VP@CMhscrP~)BmkRp3F+BL$W(rpn zYFA>N-Pf+!Btx$0AzD1G-Njg0<76V?slhoNu10L{8vXdQdFt+V4N2x_8YTzcj=xz% zi(>3FbVc19HT6{18)xv39)*mZ$N5d zZxkAQ^L0@jZKOsNM`^L>1Uh!gxkJ^2i)~S^mahsldfA07Ho^ve+r;;SK%b3&B)Hp! z=5Al}zAZ+;)Kr%GZ>8MH0)=F4jBP+`6DL=>#Y68kh+qT{1vBoM<>77sk%8t3+2aFH zUk@}bekG+_ZvTmG?!G7^-{i}E^B7z0X;;XpDopMc+-1t9KKBZ~sSGHpGq0H7`yr$_mAXE-L%qJXEIYc(WW%gQ?HEj3c)nZ$^p_+zoF;c_UN(!}4L$Y^Tl<=R zYrS;kT_YNyM_7WBWetyj1ppT+4746TNy=(4MLiaf=QEo|lfsH0jkv2Ph6X-))PxIf zxGFKQAr|K}dI!Z2o`kv7whB0}j3~I1lP3U4Q=()m*yVFWVIjmWp|ColkQyD2hEJXa z2?+`N&`GrKB$Co;B}?%A)nDrDOW3wDEYw(L=8>*MnovRyfl& zJm5V$6Pf9(#|2X5Hz^6 zd(7shwHKy?nO;&8qfh!iM*phbDBj{oH~55r2YUu`8mU8I>mGl!*3tai=`Rq9v`j?Y zzm83g^BZ=Lx_P@b9$A2Hei*n^JFZMxB@`O`mu1(S&mF>HVNX!(2N+<|mJ;(A?iv&z zXV;XaN~f9$-LmQnbTtZsco_aCHy9jY@!fDo9)Z;Cx~9+0rp2;2J|G$X06dxL=MmpA z6QZILc_7Nz+C(PBv}t-TBMQq5bl1` zEojPR`hawRRn`y|Owpx-7me)<#5!$wzV#r?KfVb-6=FeL_oiKyM&D z%kE%*t9CLL_8#laGrpcgvmlXeDiq3;i>8z(5_0i=a1hU|t0A@-91-btzB?);;JiDM zL`aJ*38qdc4TMQxQ{k7EfS3iLbaNI&G_D(ew^73jXkZVjOE!1!J@fZAYr$~j9wocnAQ4vdrpQ21y<}fs6!a-Uu@~&Wq z^VA-bL`VF`$_M?lt_NCMTTOf)l=21JhmXIiOyZ);WWB@?eGP-ZBwe0 zb4L?G+C#C*eZoK0w361+}+LVP(5-Ix|1fXYmN3m=Z7kn+E~OuA;j@9U?1 zEE|_-Vv}f{_*3aE=M2dBaA1j@@r3um@*43mm@p(UgW)4lf6U|Qd>~AkArex0#`Pwm zpzYLR6eWYh4m)^yGw+xJTZF|m^TMO)vV+4gL4bG!My@_LYHtd3ypMMG@9t;{Pff0U zl!DUUXE)L5_mFOlYVmmDysutw?%7)>5!VCSh(Fl>Yq*=CoJR$X6WY!NSQfpwPaxTg z@IADr@Yp)=6gtEwnpZvPRh*U|*sL9DyV{>XrALzb{iF*+zU4De0-BHx$}b$ixi^hc zOKH!H4x&U#L&LdqY|xp%^zHaNxMq(Mzk2OcmmU)&7&A^AWlN-9p^&GHNnCDzSP1-z zE`)`Pn=aGmTl0puhKnpVC+AtxZ7J%^v&*f+&5uJRf`b7Oa_?+DWx0`vD7(#N2YevB z_q=~9(xe}Zzh`capD25Y%J%I8cOwZ34YHg&+7GUg=ejr|K9?2W*=Fe_BU>ZtpH&d$ zxzwOV3DAWVCs&#kl^$BKlIw?sg~{KB8_=n@>f{y&jHpTsUG28}|N6 zgqwlR03&+;spQVJn0Rg2OMHK$K>YyS57z%cmOhBSL_y-s<6KV=);?JF)@!0(4dZF# z6ZIMdqNg_nhtB2C-*o3BQXHCZ=pbeGJYi}IHp|ZPGUsAtW@>^JKjQS5JyncMAH}Ay z%~~Xx6dldZ`Entz`l-NQGCN3|yTtH1x%bI%Azbefkfm8+neT`$s%g@Ayc7#?}!Z{nk0I z){rD~ZFZXtItNh75$8FzOeKW(nomU3u9)^Oac^$n8nMEYyf665f0EAoD_exieNLv+ zM7NT=HPJs>Ic!P1z zAi3C0aZ5BD^g1$f%>Mz0DTf6`yW_qof=X>Q3JOI=4zzoJ(ZE^7*pWlK|?e0-hy8TCBr%J>^nfMsgla?o~B31ph zh;Q;A;|I#^!DZYN2@|QUG?G`PTryvvgGBOi>r=0KBYR{*eqs>pv9K304pa z@m*`Q@;7YSH8cQXHd^hg59yLyDu%BjCWlHjf8f(nE;J`ItoHo*tsghzUf28&x!uZ% z4tHa-jDoZ;i9iBC6PL zYkyKsK5g7jsd?{d3F>mPC;da1TS9K6CrR-t`@0WCqXf!n8fG>x#e0F=Lwi@le|zo| zD2k*Xc)i)|94tJ(sEI)|mL81l=~c!$YV#zlWvO14&Vyw!FH)*Yi0(N&EU`3vSAp&C zdy1Q{4FB(I6%UbpCZ2ryB3o2V2U%%6Cg6QnE@d4p8&iLPs%=Ug1(<`YC>T=Sxq8dD zk~CTEMj1T7{P6#zKR`?4!(+Msj^|J>NCo+HQf_YvmvooyLB<@va+tB4vp}yRMV8Hz zcduv8=j)`6V?IGUf9X1|B>C;<(GmPl)slVqMa7Y$#^w(Pi9VBuU&MTpr=aD4SG3uW z$k*dTd(LVl@|4uXRzK&fl-Ixo)g$YACfEN2p=Z>9L(V-;at-}=MO2F07UA`tL?SYMc>V;z^Vgg$B7cnbuO_>VMzE0hG8e4A;mwxp%!)L|3@gqg z<~_fD`Q@Fnw%C!9(&$~JWZFNDA9xQ)z_eHGyTjj1M-6+PRn4#Y{C&2)I-Th<&{Awy zH$vLiePR_;pTG_e6K)^5AFl~z3Ar-~CD(k@Ks1-V2b%fa_-%lQ-;Jw5vki_;wQfA8 zX-^K<74`GiabRb(e)3+g-ekVk@T--7qEo5TYtZ8U5o4w4Npcnc`{pLo!&7`r)(>n26o@1LR&5)k@BQzq zL;lNwjw|96i|=tGb#pNy_4cAH@2&h!{z626+?)K&*LPzkp7+^LIWwRlU4pAU8-$o( z7_|>VrWjSoCTIS1Zxd1n2aOZi1`!+0=A)^&q@dOt2j-Nd`#Vn8>69O=EN2tzvOH6w z^n{I1+l_C_Q(o_MYuCxzKm)t=IyCROn>{Oj{|_oQCWul~DzXfDwuDzFJ*E3YMlact z(Yq&$ikVC%TD4PA@Z;aYbmgS|fW78F;?68@it7RTmHql;og-QWOw*~5Poi(a*q_QT z-`q6o*phT`V1=!#ceq)5W2@PBxb5xk2b5InRHsj%A0l`8Ko#%KcU8`IE)VD2*o-^* zZh!p(gKB8gI1JOP^y*a^mD06Gv44S6#zR^DL`1}BvDT%42JW16Js3@dg69Sl!%DlE zBG%}&d?ELUhvUbunGyveRx3i?=_juQm=ksTBqb&7e*OGGjE^sYL&=x86!Z~fC{>zt z`w)|oGSyeog1}RHc`_tqWQ;2^PN&QOgh%06=Q~t}x95A6AWy4GzWQgM&EG%wgmZUS z-;^p*xD}O^Q%zo{8iF$LMY<0#;m5(jX%P2i)jJdDzS!yMSUhfr zo@eOiC$e>0Yi(ypsv?qlCT~eThSDK5q!Cx z>IsOhaT>(&mo7hVjkb^L(wOb1Qw36UGGw7M*CJm&TfE2eCMoK}7Z+~$Qxp7*?B^aq zuT0;KY%qPI>+{@6W0jJXv=Gb|YNHNYD8BY*Q_gzl#`efxT4M{P9*z2@o%&}SF{&Lb zZE)eY#Lm)9dPbA99F-qmzwovM)ysVQOH+jjXwo~kJFGrCF?ygsH!8M9v}pAi6N@XP>*U+pc^_ zxzBo+cWP1+9R>+s&4a{aEkT1o%>|*BXISYlABdpBcst>Az7sFFUI5S(Mf%tPb6+59 zSArse56sWYq%0xkfyfZgm|W6cg^Gao%KPbQ^_1D@yud%+S>l0W_dr(ElsyAo>$&ZZ zv6T9|tbteOEYJ%5t2s;xUSr8j@+C-kS^Ystblk7hdw|&*%qb7gm zGH8((V=EbuKs*s$4@~q(bf6;RGFfXO7h9s+Jg2n1WTg8kP@C7P=JM?;P3o6WT_Fzs zTvm)s*=Cw86vEsToPcub2VaPoHyl;QrQ0m^_f3M*LmG+0NQs}Xo}Q3k|c7(DWJf~FOvCW zT5{#QUQ|9Y7(A(C{dyubIhkI3=>Z}0i2{5a+voyF3t@E36!RCR77xgg(3cPv|Mi_$ z!6P*lX^?%l z7J-$J^@AjemT#&8y~GdX0w&8(X7Uav(wJz$i@8j?o(Pu6QIF9C{(hzKy4`7+UbO#I zx6Y*7;7gl#FHo*1MSWTruH5%0(~=|c#BPFus8=xFoCCPb?g`l-t<@tda{Z7&&KFIC zuBOxvQzMi4kg?!$u$zGUE4}5HW}Y{v=H3Z+wNK5s1AfC5B+ufwF$kr#4~PHW?BLyY zfzAw5z6N+=tbff!vS^i!_zEqA{z1TMA(=vC=+Y`z6|&}CGkxb;=tmZ$0H(Gsb4Jf!pGm+bfpEF z{54?%Dl)H9v6I-@6xXy6tI^KN9z8h-`r-OJG*#<}(!v6FE3rRKQ<3KTHyo z<@s&G*}*HggT`~M5G$Vzg8hp8cmh{hluh$cDr6c%d|Gmm(uWC~m;E|5`bpg8czL>s zLW$F0?T>lfAhMu|bSqLKx?yrXg(R}pgZ=mt2t$f*=plqrP03UeD~M{3qZlD6>k^w1 za0$1CeK>wE2y#@ytE0a@)t9QT9ua{+dD}M&!A?=mbRxriO+_vKcD|Ru6-|CA2g#tpJxikEm;Ek&@nUGqaD| z8$Xm6Thi=wTCY-5#%JIa?i5d*ITT6CFm0G}{T00P3XKIF4YiMy2Yk z9n-oj1RWnjbkF?juLQ1G+f?KRVV&X&Bhv$M9`UdLddEOpKi>wb@k01VJYEk{pc1nj zv0=EKxdpda+_@mX8nPMyXL$0XO=Q`E0s=b&-c-^WQ8n?GT@v@g>E-^+F0*C+>9%F{ z%deOf!(m9nr)Ur^b z)Z)BMq5GGrR|Q;m0{f}!mpwFs2OqDd2<(FyJ+8P#1ZA4`P|u`VDYmYZaRw=n(Xkt# z7a#Nzz1F?uj%Jf|O$8@4-kuNbGbaQFS4CFXe*T166EO| zWO8J(A`>BhvX`OTM}Q5MdyXJVWYM8(QmK;C29~L_QI#f^^F^{}%l_&@Aq4VPAziLIu zG8eHm#P&{_B8X^%xfBY@WN_Fwo_V62{6s6XNAH2of%nM**@s~P`pxt~3L?a8k7^4P znO2+9QuMp1Y0kG#Xr&d-ST1$zm2*>Fk)jmBoDYA!6^QYbvF-$DmEFO7LKF7y$TGgk zs_BPD1|VIJQm^BJfQ9nAaTKL47T^zErk`KD(eyk!?sw3^F8Z~aTB>J5om|rK>I&ay zXJ$e{689y8-U#HG5E7I$iUHvT0_lKydSW8{gZm@cL#m!m*E3^P>U~VFxx+cR z6+;5Oj~yP9Q2(#mZL-h<7PZcv?mp~wKjnfjFWN^X=o#|p_wVRio?w}1I2MTqS@j#@ zQNbupeGVD@(;_Sn0$@RO_8ENk$z8akDkO9%>NLhu7AeSG=yu=0*yvJOidkwA-)@m1 z2BkW+V00#2NrNK#Oo?x}vo*U?86MFPT6k~JqlSJ4<=ya~lvDW}FCp(lUe&FyNOl(+m36k=|Er=QU+@<7MxLYjPk>#fMAo|_I$>Jx+}Syv3d!8Iyma>++<3VKx!Sv1*DbCAaCH2aa7_UM!hH z5IL*eH+mGjPfi zsbNZwKCUy0~vep19dz zZWc5`PhMeWmP$KF@y?8gu4QC8>G2)b3Z$qGjSza4l$4bG%#xmUWuaIOkHQBp1)G2) z;=gMjks!n{kuhjskWpfH_Ix&WdvC&zhjbSN4kW+8M-3Lp7E@B}0R~6XU>p9YTPLYC zd|z$K%1(o(h08I#(I$q=@mrnYa)B&d=Xjuu=9Wa5A?4n}O_^*6p@Aqy;!;~xaN%3S zGt*!K2E(x3gmRq zzyzghw6jX;6bS72a@_^~PDL+hU{GLhEBp^75$cRh7-#4r#Vl&+c(^voZJM0kf}=fN z2dd;-mQYnvE8HLI5%{(TkFh(AN3_(%`>V})s35f4LIcx!^Ytz7$r*wUioUSw@=31J zA)$zrXH;N>ILFhG^0>Wn_gxeA<7^ACkrD2jrNyw_E+b&M$%|%C)K5HjVO(TYxjva_^eG6o z8I%8~G}xn6dHtjvu;-m<5UmQLs&G%uN1jeZ~*JrLRNPUYRO`WDmlV zIi#-|{T#akMI>UnxStmcR#lE{{h%pxT9+;RZMr=CQaU_l&Xg-^hs*>HQ*>lscpx8? zyrW8gEgH$K*(xnIkX@Jo%X2NumA&(LfCr7EE7quq(2t9jda<+cw z)Y2Cs0LLER8g=M_$hWyHI*UaSQVZ^5kGD4Fl1of34G&V!938@aO)I5=9KT6@nx}Sd zM=d&mYQtVROfhtX(kU*8CU_zftGq@b3#kv zeTI$r`>Dr}coZ&j5Zi-b_f`fdVB=!KF3%pjq9fj)ui{iksOwj3m`ZMeX!sF* z*x3gBhi@L_ykQZC)#nC`eM)}1dwPSfcQH95b?cB?2~2DSmLw5E7v`cV>K5!=IQ}Vq zG*Jl6^mu*;i?1p2<9i*qUpl*~K6np1qznEgNHa}#3?}@~FC>rhnSW2drGxYTxiJq4 z;{WUV{ky6Emydf)V7C4J|F<8%!09D+U;T~K^DlAYe}4n${mc&#C5G7kxF7G+_@RJT zL8Nuh)t0t3bLxZF=w%BK2%=(Ri$VX$sC^R@*&UPP6#r9ujc5@QcD~hstS}W(1Jgw-e~dh^6do8@Zg}jpI_IEXxjDf+Y9X$I}J=6 z9RAM0uM-rQSXjkC?$k0c$eI!L)a-)4!ol4c1m+J znKAw@KKsBcnvij1YHBJ`;C-m$Qk{axgNyI!ayS-Qh3i(ocBhAZrtBP_WMFD#Pqlk1 zy6oqPR@2hP7IawmtDT4$=S#LHPojWWBJ<9)$IsiFR+<#}y%Ft;i;LsOSTsu@50)v{ zA7F$4VSAJHxF#?GVlS!SO`o(mug(GzMiGEq4SosmbrLpRhL&8?)`2C54ov({B{sgzG798&-RxuE+oTTq z0!*v}7yY~+-lMFcW0Mz5xp@2rKc?W9gxBV{#QCBPx*p*X(&q>?gMu#3s2(OXDg!wD zU7P1O-AuF$Aot89uA89W-afaj7qBs$EDXqM3+BV|{jXVsiG;}Zmv)TJ%epec4CmPH zRHXN>wkYdS{;dX`5Pv9$$de_qp)G@Hy`G)eP@OruXs24as;GG4Fjp3TDcrx~eKgM! zGVB3j!%?^zZbVal1k35+3wS3uex9A1D;2yxm?@684VDNmNdA;*SybKr$XX7Y%cZIrExwHA!wa09*teT>;ny0i8i}l#=zGN+ z?{HsMLbvDZO~sed8T$Nz@8pxr^K%P3Q!vut;K9jpm6;xXzS{osZ8I7~C{?yG%&umjdG&gX)>2UhY+o6noJB4>d#qu5$2%2?SXx{z6u4MHh5%mcXjR&Q8fC$Ek zFpM;jjA-3WfoiGV^riO1WbSi&pnE6dKl;Kg6#O0WUdC6#1yGF;{!w|cC(30*hF}=+FsB90+TO3QF+?;q?Op>lrveB&>B%GCp6vAg{Zq`G2d7{4Xxr$L(7+fz)V5Fp z`9br=t0rjs{{k2QKd1JvYcO{Tr26mq@YHq$EJRTKREeoy@Gain)sDjA9+u29pt2x_pyg}mopb@Nt%Amy8o_n;4a7pxu&8X|jixpZsZ zk+v-{R{VC%jJp^cxe5#_Qc}Bp^s);Eri;9#ao0Mp*<~)9dXW~|eboCWtHUz2aE#YW z{CX*Qdccw|x)%`gKJy^47P3OnkHg4|uAK=a)am&BFr z-Gc+(l^;bowL*?sY0)djhW8cc=CEsEcGK-jNb$bQ%s4L|MUstng}i$j58{03i;T~T z8v62O3x^D$VzCfd&aDcIxE8BR!Gzqmpusf`^mVzk`?64XU{K?-QKpb%;vbRK09_jgPI=A zmy|F}@Us$o%6n~fcY|ppC1uw@WS<~pUZ#t0Xi5fejP!@j!zvaRgFH9H6*To~*tb-9 zlo>*akq2?5b-kBQN}xiC?*NNgy7a<(?drN#R91BQw?#57!=qE1Rf`Nrv^-su-*yaB zKh>DcW5S3^mR!MYSHp8*sXN5zc!;5#*M@()Jwb%KbkGN~@Za1gk^%Ed@U+GcxF7RL z7<|eZX8sOJ$9(&AQEU+T7Go-@8UBW9-McRFA%#j7!L+hLD5Y_DIWsSUdKGClPDY*B z{^!M6kpPaOeA8N&O+_Lz#5p1qhX|QK7^ev}%*AoOf*?Ah^L$QNr2bCrHqpaO^6h#7 z$3pqcM)MUpilV6)=~sk~hqy?4Fd>PD5_L=(&J*S?r5z6Z|NB(|*u>Cb32pRL+evN~ zyt|iSU&d=;`B+oz5bmQEX?&gA>C2E2snGaS?}O*N^mn7#aIr@MPUEm zs#w10m32()M+tl_!%h4e-HNu$#J2xHGT=#pq9juEG~}Qzk591fScDBdjTjn+EA8)9Q?SyqjKS^E3P+^fFaJFr6!Glb<`A=Jz7`ml*k2kG%9SK zg8~C3%#@wVLfVgG;iV6C${&dy0y*+Q3af>dFY*^-Z1p1o=BSd6pISJjhY-%>Xj3!G zK2$~7Au}Dp+z>bf?jq$0$S0m4tLl%cD>%ARmk`q|=S;My`uoiJR-m7R^w1n+JT)h} zmN>W~l4(TR27K-w0`}I$rhO#LBE;6p1yvH8USjaoHiBmFMu^}3U!80e-)($a}}=`QhcFd2^*r0Kn$y-GD~0hn^P51d8^7xGIy zI-x){qyi1TZ~Q)h?MGW`LMlh{1!iuU^RD~97xEfnu%yN8VlIV+z)!mey#vbU7%bUB z{q%E((IMF6os&cP0vSmK?O(KKB)Kf7W{M*Ue zk2q}u*8rmXSJr|c5J)cB(0}!Jw?9UTW7)iS2EAnUx0lO)A`X9-<{4|~t~gfDRo4gZ zKZfF85cdy;t#-zq7zqkx`FSMGKa;8-p|K@$y-5X6Qxnu|?k~lE%v;u>+vu!z&t??_ z#2l5`7jq0(d6oqnb`SrwBNJP)75spk^z<^%%6C4~)OxMUTg%6YBkfJJ(_)xvbEYC#y1R`5O-zsaR&r?`m9i}CEg`GZg$9{@vqa5dZA7YMxupG`P zH4kB=ZAfJjuN%O^iUR_AV+?Kjhu5+LX2@8j&_Oeofkzf*W{xd{a+bjvQ@M%)iK~%U zG(=ccMoA1l->&2xs0dveg?dd^WNTxVCZDbu-_kQ4s1&LN98O$`nAEFmr2 ze8ArT=O_)HH5t2`h-x|ne@^+N=j8Mv&n!(F?##8dQ^zIaP&Lmjcx@*qlzt+O#_B-i z!mksvOVNzF{Bvp6#M1cA@H7)>EVf7n<6K_Ulr6JcREFPqQF0QWQpDL8EPkl0(m@iTw99hG4J9{y(%UrF|!P`&)9+HeX?mt_B&|D|PBny9V zCWtoco|+aJRe8?#c7;4!UQM9aa^&~Eh{tPRBw%5^FNGuO)-OcwSN|XvS_6Ks|JB<> z=ZuJ!U+?~?vl`q?cEzmrZ~gxMXL){SgT>?UCk}esx=^(w3fUlvS1R42NWTgbBco82 zVjc4%lm-(-Nq<(UoO>|-tZI(xIwK0lo2vhng^PlfRSEWss*!V0gdKv=kxz|OzKk~@ z+@#Xm{aQbag)5_BNQmp8!+V{&@sQ66?=SlInm0lniQ>l3{qpYaJ+eZM(gjv0QZuAu zOnh@fj?%u`+5?*MUDO7@E$=~gqe`7<6eshrX3MEqHYF2gk4Ce2x8DtVv0>EajM=^W zrRPr4komVb&5pkqOk=9~V#Y&gUeYghJYKX;O$ig2qn}+9Sfe#=Qk%c*zDhSD(4k%W zLU6@sAJ6rFvjD!f;VKs`s+A16H|{N)nX?bJ4^txFBnLga==&YboR=83vUu*cisvt8 zxKcm0uR5%p^X1TfrGx8#Ii=6vj(uFlLgZ2z{Cf4X=(8x<;R&`lYjTcaaP(*@{-&H> zzvPo=V$oSN&s5g!4_jshqg*bUTgWbH^i(N&r`cx&@V_2^n{zBl9iW1O%vOv3Ep)yX zP1`p(hSx)nUg8UQ@r|G~AQ0%TdZ4^Q(~$E&g?D1Un*8P-DUJMU$2{sFG<=|;k%S$v zcUYu>uVZ2Y?mnd7hj}^)!T1w z4KQ27_s#SbsSByGNLZ!0dTxr0sNF$F`kY30{5NQh+Jls!FxPa5o{;ONgbx^XXFcKN zrz_`e>VHM@K-GNh0ARu1Sk4o?hl%d zw1@((Xk>wt;1IPM-VeNt%z9%~fJ*tz5D3_}PH==f02y0a%l1GUXv(c1tB$is8-Ez) z=em&|y1Q#du}JuX-Jqo+)f*}fVI5&1CA&Kvz_SNaBi%^U~knoI+I)!FF~r zEzTo>iAJCKTY#4-7&W*Z1|cGstRdu00CVT)f&yTv*v4P9yHG!LfSa7y%}_!wt-&}* zJ|F^7@X|O_3b~bBez*MiLPV+sZ#^ItxdTO)(jN!|O*m&PSWEYC0CF6*E}0Z}xbG7( za6@ck+-s;X)wp#@0iIVw@Dt7iU$mXfDFlR;hC!C6ySm51m=w0+snOZ*E$5;4(P`Fa zoJD`#zfL^;L_ejG?{nSV)wTOx++q+iP}K#LyYv&Dm33e$%X-M8$?K8m8t?l7U@`4# zU5;C^R5rcIM3fVj^%J1_DOtR!$IY`+&JjJdH(Xvy+Un6Q+qFWC@2hWDoW_Rb%n@mZ z{Yi!NXRQQKQg7hPP_Sg?{~h*VmHLu(L*}8?5kMv@abg_7ysRt5ZXZ_bXk61)`@&fj zuOC_R_d}SKJmm;a6j2n}c3fy;5K1saLNF%dK;MO$!TRU-47WF2t&j`q!V%741z8B0k}%xocPs{e+e?;0FpW|g~ZPH zS$KQ5;Lyk>-T?on#^M8%wj7XXz`luW5jJ(HZ$pDZ!}cPi0QM{9ciT$ylo*@B(>u3^ z!enxKv7i8|fE`SfUNtO%bbkb*+k*Yfy?>3Rv5g-Ue2{rwSlc!vkvau(+oHXkoN5?8 zeh!7~WEKR1N;s{0Z2LASr%1E{IRb`}un^M>K)hm5_8a1Q94%BcGj9a<1^l_)zx*V) zfgk1R;nBjdL~ggaY+y;QUTfN$cigd0bL$t3xXza7hD~^?YNqb~{qxhqS8~)~qGutf zp^4DMfFhG(RH}^=Q&Xu`%3}168^pBbazmuVXEp#?xY8Tg`#ptm8~gj~<24oqE{|#W zb>kQdnj{#7HioU`{~8x$g3*!a_WUC2Nv z(EH@|x0`%#Z>4Rjy1X`Dmh$Jn&J7%8(nxi_Ghx-D^;XyZxM6G9s(r#s@}&b( z2tyg8<3`@C;iFDppP#FpJu5+J1P1xNcMjK1xizgDz$n>qW?g%Bx8Ir-_-4MUhN3X- z);)u?!7oU5+{cmVG1)GbSjfCxKT!?Fn~XwG=(i9uD%x#p^)iXPHUQxvd@wj);oAii zp_xHx;mn^vP>^O9Rl%o`G9gehCdzy6yi{i#;n-hXiIMzdoRC2i3mbbLr7-OpH9Fba zsMA9s?;$v*2{)&J=B&e*Xi#Q-0B=|75eh-d5p54`5fr|y zq__JAc&CIV3$Ehj$XgxhQ*!v6Qksp4DTt4sPS2p+E`*_LJrZ=uS!}V_LT)=?J0dbA z#P)s_^auH|h^aMP*1}Uw1>0zzu@=C3SiyYk3HPkIW1|pL{6@0h~+p<=vi*y|E4R`Aw>JriTO9@{kRAGfYaqLgwR69G~ z`a*_G78XbK%ZVK%W{6H6iwkVibUsB&Q~af+AH@awmc=q^N>kjI?^Nyyi8q;zW}M;Zv>VkvTeg*{=S%pMSfFQd zSkZ(J_Wo}8vD!XvaVGT0Ir4)P+6!sWq_|uGx_K-Jev<{ufF6e1#GYTblqgw*;LIWN z@#YdI6!Zy-{&~Je;9px5LWUvhF4JQ+Pi>QMK-f7t8qyUstowp@#34Umy zsqu)#vkln#wNTTT`E^EqXwG{i^=oS{V(UV*>-co6KZx-zLG6BQ6DGJ{sD16eQmnj* ztX9SY=lF;qlebNihsTX15TzL6uNq-nme;O`g;xvBJJR;qJ)`+-0T&p98WS+gZ!TY7 zToeO1OQ8d4cGDXg5ZO{{*huhb<>agJv+i~m-KGVv>aEpv2fuUDng zZ4-JWihU5SUJ|-CiaoN}^*|W2X0leIia(|I+-@YR8iA1Kqx|wS3~Fh-l(w)X6$cos zr4R?$kV!gZ?tKRKZ@w#U$PP}E(73aoLQ8`R zyP-3EniL6ibR)He%9nbkOk=Z-?_g`w%p;oL?R}`+wdyFJ9bO!b4?-W8+g46Fo>+EO z+dXbrXvaFoxe~JoiU`KIJWQl9Hw*cYQV9#iqadK~H^XP`36uZPVK1EX?HiBR26g@3 zAHhlLnN6{$NSsliH(Y2F?cP|_GjFtJX^8^Dw-h$ae7fB9I%LY%N;Wv1-?CvCC>4>| z4{5I7s^kFpnyI@4+Ifnfm38C8#vEmi1eM3_vY(F6y6B?g8k3^2^9O>7xk1i6y`bH6 z5SV25yz*L_5)N##E6B-+Qzbp@i4@&rD@G=sIC(Y)UR$Di&Ji}kf@oZHmmf}(2P_kU zWx)JmY?;Cna)^G`O=%Q^$HpS%7_lZoWvdRQwZBQCwcY&IVHh)Iif|!Y#1h44^X5`9 z|K(f%xDon{i3&kE?`#d`hL2>BuzIaKcYj0II9u$OydHn#-yjl2wN@emLr0@Il#zjw zG`iW|MD5x2d6=pjEd`>NY=QkJ{4;b$N4)2P94sREHZE2wV|wI>)%fZRcU)VdJswl- zm!Dr>xY zSH@mn7@2)xbwL<@<>57mL__%2$Pt~V(Nr43VFLQ9MFYEH?pTRtNF+?Q!S4#N@i*U^ z_$bIKOK3wJvGZ48R8L`e`CALpGLGk2Wx-^GG&U{vvn2|%?;$6=OuZi(8qi7}RUi{> zKF~VM8iLsCuUpVHXoIdmOL6z=dw|EcMHST&WQt(~BzTdC2-)Wr`?(TgG)-K%Fo6nE z%CZ^My$|0C?@A~+bqsCy6q!JT`;dU>EQqYg3>^EOL>m2kA0Hi^K^3h~a`Z*ciU6Kr zp5fZ*x+NKX3z~`$Q?B_f1XQI-;9@iVjROi%F5&6H561d$P&ys%SyI!;S~D`B>o8!m`j zLW)9WpfiFmF)87)`5}B4sj&SLttq16b<~p}d1RnQCtHz~5TFsp`kltnuTew^jOlfn z`JpYPfNA6~nnF4m5esPvgbocFJLxj+_fGg3Xs3NrWiT-b|EL+Chk^`7k6I&AF94GEUNB%TM%WC8bG>c00HTe z?gk|+8l<}$q(Qo+OG*Lh25IT;6p(JDK|*}@sL$`c{-3E=#?)x{?yr(~#P7Ic;JQ_)Isjy?ffwYCDybek*({00-H7II zda~hLUmc!`a;+5`Ii27bK79Yz<_0nv28k;T_Sx<<&-7)KfpF>~$^Mag^}rct==lr@ zUQ+gKp2(ER2U7S`63K6}tRtSQlXS76QVB6#Y8-f1s7KPc9cg&_(WHz6XD81{l+=oX zNz-Kf;`NsGo}==+y!vd&tMArDR~EggFmFkK8G_TxAlRC*P`GJwc=va zZjXWL<~<>06nUucdlQWKS%E}3|D^Vcm64baxJtQ~F-9Lk44fJ3q>)}6L7nlu>D3>>*ZJ_pw3OMvuC>~csYV%5l z*Ss-t%~Z_Y?tAWb^%mjXDQA9Q0#5)2@>be@$ED*LchJE6JA0Wo7QaLuZwA-djh&{Z zwI52Rq!WMLx^u9AKrkCqUGE=#Sz$L?er-m&sJ}**ff2=&;k-h&3YXFmC$m_&_~O1O zG^wYQ$3hV2#$nCo2cKfap^Z*-<;a$XHq3qq%)L8YPj}b*tt7V6C0COpRCz^jfj+K-dl`J(Q&aNk=!G-tOwN#RHtdHtGk~7+k>n|=;_Q?4D9Y+U&AI@l) zYws~zdWL=@ThZ`$cuNlJ!gXngqRIeS4M!C3>V`czj@*y*?naH(%vPF^3Kiyg!3K4g z$;Xgo$)a}ExdOvcLPATW^AX89ZcKr%U_`;36z5;BdcX2}kk6C4Hk6QoC_n0%Mn; z#1MMB$Z)rFv$%FulivA-W*hsZm((fs9XLHh1u!H1?6vppb{y`vx45Nm7*9oz)A4eQ zZ2cR9F>h^{OW$n^5cGyI()I9YZuIGOi(t5QeXLfB5g_?MUCb~!*uS;m-8hI=ZpU$y z~iW5(9* zr(Jm{cQ9S?iD%1^9t{!mp|0KVDfO2~Y#SGKm^C+hvDOzXC%;&T2%5#}K?=I>{xyNm zEoDPNVn6Xz?a#ZENr88nQM5WjRS{v4|MF;8Cikc8{gS};Cl*f$gQnG)tDsB9P721> ztpenf+BzkL-^VTUJT2NQjg%M0bH%G%C=Nc<{-(|m!0a98q7(|SX)Z6{%}fDL3O%xn z1dOPKF%F;HYKrP7e^i7_RVlO$vNeM5+X@@8vHtWXgcBE|JFwFl^(2})w6m>Hq^>S>y9)mUB_{zs^z)gRnT!0!w7VMLZs)5aNf0Mo>jQNE)1ia3`>Z>okT zN)ryaOI7nx#*x@R!?)r%z`H+nL#}fB z`x}sv#CsytE-D)GGmDhgjgoEH3BP|M>|b zk8;Q+Qe{}xSiM0f)41L=B<%dmlE#HwSc&Dcn_u_f)3oF>#FqoFZe>J?<9&PYz3~gg zPcU8_-RIx;wEHp4HtLijhU{f>9C9t}4^5H%@%Z-R|6K59>dcN=mw~E)KR=1RYt_aY zwtxTAAe<&gy;DPMl4n2s&%Z1O_}urv%$uDkM_g1fT_7ep20&~@X;Uzd<^~XrGOys*sDFQ>w6oHm)y;ZuY8NAY(L?15RLp~+Y&jol#d z283Lm(}YAtC4!yvr57+{sRLIE1~G?ZA1@V_+WC;cK@WR38MV5)`o@=dYwyzMIe}U( z3r@#?0PO`J#YSUXN(uuaqoKkm$`W=2Twwjn?LkI|OKrI1nffUhv%yxOWjc3!v5cR2&!g@cm{d;hQ+%^-DJBQlxBfImjrD5^&y& z=2>)=ux`FIF3_m{{Oya-BNnwXQIIL#?~w?^SInw!JgfIWkhl&|di&!i85tY*0sECn zNldpjBCQA^7sxP-EEXo`wH1|)Bzp`%iUyEFJh}wv>?q{R;s9VIQ3BcJR_Q6jvuJc_ zFpyqe#2ImSdRP}ozdo7_XKYlau;#3;fhIf-#7<~%gFG5U)Hs6P28p}@94_;ALCW4B z_ggCre>aW%*P^qf#jm-~2Q(M9B}Lnpk+WD0YVqcJe-`jVUn=TMicKnsynE;pcgE&` zV9O0mBBueGY#0LQYvKax6p&Dk{n8Nx65Id&b+Bb&!pf%69CGy1MfZL;EW59V z9OCEsF56=tk6V8K8jjZJNiqTx$iogvggxrw4HsK}uAn=-jA1R0#)JGsu-x;nMC-IM z#ofjgczVn9+A-?a_<3mNiJpPj^V1m8q^B(Pl0YP|Ga%6nn9@}H#%uE*8^(Y`{Y0`6 zeXEvqFk9K3R;pEBA3rL;s_0vy6$qIZKH3Bfe9NdIn1??#`XgSyp7P70x8F`^@s)#qoE zFrFWMPFo{wP;J5Ygj%+~@C%Um-T*fQTC0k~3Je>7hK4On`J;}1raWMzkdY-_l$Gwn@_a;W|xL|Y)i{5Rr!1Fw)dYMh#vW)zvyVo^3%MQIdcf?j+4`P^o9XIC*<}utU$jhjpyY>h- z!9yNU2w14G`EK1f?b;t@3>BimhHk~e8e}X=X-Zb@x|o!>yL%J`abB(QA!J0ep@twH z`H7BoA)7swb?)KRw}`5gCnwww!8#5DfI;WH?(E4==bMUWv+U2B=WkNsgRk`&`xX?2 z5+{Wg6QcO%Kj+T!usx~$vk`lVflMtg-zOD}@9LJwrLvbJmgNF&^m==HrGs`A_-u~% z7MnDIt9@gj&%hNzFRkf{djQ6U$jQn^qf)rG$|9vDd-965gfaQDua;MlnhEa6a3h7V z3`Mj*nbx8PDz-1991@3Rz}@-12mLVntwA_x)NPS^Wn(WznV>A&p2NHDBto4VAOP(J zf!O97TY%tjba!8H!s5H9cCBx^GdlDeZ06FRjzC@*e^?H)OuJSRdtS7g{m z7715RBQJ}bM5ONI;5C?saq`-G^0jJmr!P~qf83Qhh@DG*jBO@Pq5 zCYq#@CfV*>bzvJ$MR=Brv}V7))EkWB@Qpf}@OvTWm*o78rZJz5kP19Y0OT$75p5R6pp6yHy zIb0)25-c2nsUj8`P+RI3K)9PjTD!T*c^_#rg*7mcJc3g)Sr$g9?HCi1|E+A6g%sosD2IX$<`d?6Mlx|LFb{Ou zNar?yQUN0Q@Hm9~%v59QYgc>Ss5zeb(0d`^2&cW}{4$$O!jV)t#NWU530My;#kbrv z3DNh1Dg1)c?SlLOdobvRC+$5dE)gyyg#wr6N?Fe)Sw2zYGVe^0)>O!Ss2YN^{7@Yl zZ1+A`GQif&{NLWQ9Ofhc1cp%_d)*ywe&ooD!17l^U(zEXT40lVAUR|*d3 zu#jt+8G7pZ;bj9D2%vy}8a0ffch9Xtlm?UL5jZ$G*(;9x@P?D=Fab8~Vx=;Sk0@wC z;SB*LtsYl$8`ndw{Ahkz+^Bl+2pqz!p-_w{ipyv$(Euj@#u-d1Lpr{5i+ALBvmg!9 zNmCN4-x)}HI?6$?h-0)03XDOSG_)sEKuO7%dXk>L3tMrfX5n&wBMXCHs(EZNJQpkM z|KYN?v{@|Hv(IrSSZH~32HMGCea94g8`7l)*khGS2owVrxHX7oW>VU}AgG*(e}CxJ z#El#_@&QsxJVGAn26}fo)2%a0i zC*GJ1y=P^k8TH?FLG|T`r0i~l6-W_{&p$7Sjj54cd9NY2>5Cqw>`#CujdC?O7-yG? zCHFn0oTH}F1-|ZQM>dz&BYCG6g@(XP%C7OMIkQ`VBp`$QL6|=LH&5-1-AR>an!(5X zRq2xTnQYNaqd$8QJq5Ck7dC!k!-h*Derdmk1`dP>*)+ywe{Q`-sIgTtT{laujC4+o zhB<@a;R;f9_d~2TS2ebJ{mutb3b>CtSjvx**jouftc5iFgpjGd3f*3g+@yH>`g~bxG}23Ndvl z?xFvYQkIJW0wSDAvhKmFeA%A1yh)3&LLODJlK5Ba`~(LxPg?wvzH z9oduARn`7}p6c^7xl(#$xZj;zx0x|^_?YJYC-9rzSx)I$ZWXYz1>ZpDuVnZL~4AUwNrk~%AwIf1#N^Jb_A=^ zr@E&}xSik3U(`1^7>?Zh^0JmHWaU7vFMmNxtFidYy4WLqea4*s(eEw}b+hD()y?(T zxAZd2jH+^86ZK3S6Spiq-&0a-AfhRh)>GeW#ZxrFRhK6R59>$advi$M@G@FXRq2xc zW7RVa8#LHRiG3Q)!93mWr_$KhPK9!p{y{Xq5bPbeBhZKe7ed(iW2^$^t}(_ zXEjtSQ?!0{-yheO;{tAY_-B8|7=M|1^h8e1;qh<`cj>=XEezHm)`$9u7)g3$^3>NyyvO4L zA6*+i5&n6!{HVQ){Vh=~Z2%s}4c?A4DeXF~fhh?FsTP?i~}V zys@?}0muL$y~B6Ui{96&+OJ`rAh@OiU;xP5=P1Wyytb_waR;t|tG^ryd%H46*;VCo zpc6GoQ2i^7tlRjx_2Jpfh&LgH+Zs;&TI|yYh6XzG#8!qza+raQ_4tO*I zgbVLcfDh=~t)=-2MV`!e;(q)`kJ(1GK_jw?jUVK%K0RN7S-k5MUz%NiBe&YiBYX0} zCibO?F#WIJt~w>x*9vZivnIzIJCsJJfp6XwyC&{^gQa5cF{o&^sr^i~X^ufe?SK>b zk+86ib;~bjUli-v3aP$CR#s}6NJr=EaL%DRL#EmdVhLo z(~;H*LPA11L~HwA7L=&6CCyjn@FtCF^T;Pqqk-L;Z`Pbftc{1_^}sMY!2TPgKZz>x zZ_~VQ0VcAsPYR@nfmSE{PUGJ#N}E)0adC42w`spyT+3f7p)xFdZOIu4C|Y@Y`w9=B zW*ORTrr@%kS3_7P_(1di?iOTAsUkWwo5rI+L}z-c*Xn~bbR^DpeYR_2`_c1CR>$T3 z?B4g57SQj{&$k)^)B^Zatmm?{#{lB6Uy}c=3V1u&kyUF12I|>5!J{M|4fwbV4lqxFke= zg3hbY+)M@~iEA9gF>W`l>eq$|F|(}s){P4;$6voNzPWs{+AVf3n0t++-{}S&{~B~X z5hXtnku9Lk>jiD_IzSQPf!bTud?FtX5{lyyNE1v7swkT+6@8>AP6aQFYd9TyY6QR* zc_CB-jb~Gu_i>MvQn=*6urfMVT7=&hQD7rbgpDg8?0rWVC_{KWU8K&r z+PhBXhl*1pm~py%HvNXja|R$E;Y94>I-X~*lL69IaQFCogNx0$cktuIy;SQjy>gZc zw3N3wO#(ma+N0lI-I>jeLU0pIT6M~5G~KQ(w^tS~Er2T!o&8-XlBa19$80SW-yeiZ3lt7+gp#Si9K9;g zZ*}X2PA8{QyL4gVu$< z4=%lv@L2Z=MocGq!~$^bba958Bul*o((Uk9r8)~C*q87^Q?nyuFL1fL#yw_@5|ag8 z4dEUtp3(gv=6iI4n3U8)mTryYc;7sF7$mL}Qw=yZ=CZcjRKTsk-jdFF4Q??Lc!2zl zeqxdFDjx>oGT*iM-rRH)`jVT0q0iM3-UyswE(sTBccPehP+g-+8;|9w`9OxeAN+%m z`)M?={;31cUO^2ImEEre2BMS`;E9;&flrlarZ?&an z1F|p=qb5GznUhn*tb!L{E@Tch0x(i|o`EbH7&CO(frQ;6kfY?<22!JSGjQ2dAk9Wl zZ)^F(Mv0UoWldf+x6_3dNXO4w_hO-kI7H3-Pd9$3?7zw%)RuNMQlHC?^w9d09iGu5 zGV!JKmlJG+k6nXGumAc-Z}Iwvmv3ScRTQJUZ^;?AXWdfNgEB?21a9j&gU?B=O5Xz( zqyKBu?z|D&9G756G-)n=f*8}$o_=%@ST8z5{JTsNkQnuu2z#h*f4&VsF7E9B_%glM zuLB7g0_K_ajfBhNmOc@fn2TDP>p^I1%4h>Ne{Jh{db0jhDk-8 zqf2w&{At8{_B%eD!;=y`&n8tjHvG<+wQHL^52c&!7M!Muj}_`cs?>uNt6+MX369{; zo|Y@cRPbfA)$X_UadAqQSvsO}G_W5MB zw$KG)qhB<@XXne??@0iKwA6rWyLskgG!FBeA?^GjGihf_NvO$2cdU(;#^%HNqXQSi zn*=^;cnMZ9g7}Rw?l= zqePX*s0*UbO7@2_`N&*D9bBZff5=j;;puNgh{>Y$o`e5N%F4KCrSt;DX6NJyb_J$m z+g3-E(775lF?{ab0xa$Hy|M=|uYKO8Jn=(-qq(yugzHJEq``Fps|9y(aSUl)o44<> zC+{yB_KAIonLB*A0#K<~Fu*iv`0kuV^^z!HW^4x}l+UxhwBj6}PDRNoD@Fz>uCGxf zm@b@l+~sde9T?n685kMeyYiz6`(?bZ#lT5k8kBmL=x*m0)ltlEo>0obM{(Ns%OahI zHCN}ctf2VpAyGDKU^tbDZ8aeBh>!2<1+tYx4iHl!Y5Jb9Zbp9v(>_TRDg^BNjVVq2 zKDe%+RW1!{ldF(83EdpF2d2U4+Pr{&k$Tc+-pv3A$GLd!yAH4muK04znTS!_;}1N+ z4VokrY-Tc-G)E4R63_-(M@}7^Zu80YALPA#;K4FI9qX}RGvw@%SA#rwyg?f{d?z4@ zluU3_<;|g}<|V*z%>}mxIH%)zNqPNOM2w`w*fHB?(I`lxOy9tH1@f9+fDY8x%Yn1q zkC)OmpXpXsQ$Lu)@RBgd#dSK1dU-@qK{396<;!|%J)uf?qD}2h4C`R55o{ZRx;lCT zPINQJZl)g+;)mewL#`$PC`Ftd{>tZ``&L*;qp!;;$VqY*@W>X$pcI~uX5I0(1aPtv zFd>=ujZo0UeqpO>5j@XRRL#bW*r&ylOg_{T6crJo zB>R=FF{F38y0f2Fb^Qnzt}w+OK0(AqH-3>dQ0qXw-HHwgN6IK!)O9(V9fxh`-p^oy zuHE#}TT zlW~#u^^x2C7u+Q&6Xu+C`IDygFo`?KT`QjTW1nACofbPusuCJ5O#Gln*7Fzb`8{Yw zNtb6+Naa7?*Wa+~l>nxubBA4Ft!;D`G85u6cB`1JxcbF2Ff&X#4}IH9?_aBMV}1I= z+b$x;NO0-~_cFiTYK*rzkn_VYUH3VvO10=OuJ8QdXg+(=GBT+nHl{vDwzw}aV>_sC z-~OoYZlr$PDq)7h(6{7CGsv-qKS79xXRt%fx)v&B2bGp3l1#p5eba#l_lJ-{#Rx6| z9AYF(W_EhlhHmr`%>4A;iY4*ok?ULtmsx;(yFnNQAvt%(^R5R4L9ODjZALe<{$o?k zGk147kucH_UO&4beYtBt{;`>!ch1|I;EovG-dukA4R-xdGKT?nT9G-c;}z|$lVNra z+{UrEdptwL0x8yqbe5E34{Qc@P$`Tz?tUGJ7$A{}!y>R3-)cj)4<91uz+{m%X$`F} zRnGEDW+h-+sW!Hwf+G`)#JtESt*kY|y?we`8NfyNaG=z?CGr5?>nK~lq8XBVdIpgJ z`T^qZg{7LWQE>YWcBK~o(hjIPhS;xBAT<2 zf*C>~@hyB1>o|W?{IbqpYZH^HMjFnG`gsiH`0H`G3HJJv8yk}a@&=C&V8hPelH*zS z^A_N{WJ81ln(FuMKA`FG6kXn-{#7XF@mJs zHijN?*jzC1ZGkVDx?Q&s!utlgJF^9c%XiRrmL*nG=2#e0zc|QM8vp}!;2gRFntcJur$`e$GQZ$BVlVAT&Q}+O7 zJ2w!t{-Md@LGCvrLZQO-PBfP2-XIjmL2rRMb@#blI3;s?kRGZa&h$#+3 z7wr>(3;thf8UyL6^YicJ(GAY`F0vNB&^+Pks82S?!Kv!iz8$CgMtBmB!t{8Zp}#w_ z)B7)|7(fNsWeK~fs^LFP?L$8wy4g;L;*w|q(hr+8Ya_ITy*Y!d32POLR_@C+xU9IO z-IS|REQ8sIu2$5R3iQvsn^JG_vmwwxQy}*@Zi8f{%oAtj1P}L$6R9r1-8+CU;A_AK zs)^VIp!qha(O*A;M+uf!RdH3~;eV^DkbP&XT+;R%%}$a&KZls{08w}HZKgRKTeb8j zscBVp;pm`6P-R8Ec<~}_5=TD-6Hl#I$uv**t>E6CX%eMJja}eP)jn%wl8yS6bZt(0 zi%Io2M_eJdY$1Y?zqGL=417mw+cBq}TM3_;RFoQ%Ao?2LcOzd&*u`Zc$;@gd-idy* z`Wk>nOTcI+pjxaE&w59MT|NXy9z$7{=i3_Yhj`v1l#^~nkzbAlAc0|`NPS%0>VvRn zz#x94G1Oq^H)zDtj#NS{`ugnk({S%P0ol5-9X2T$bSIQqkJ5b$E|J8^$@y;bX3tfc z=|y!b)#2pE_j|{dJl_2*dsg?Zk~-fZZUhHTO7@tB zS5|PkN7Za3M&Ogl8~R8U1yC;8{={KfIjl}X;2gLJF#?*a6?Y>}-A0NRA07=ZUtckNp;NwXSO5mT&(oN1D@p~aNy=9b06lP z=(`ja6){z&mrin*>raLTwZ?jqhR^$r*jj2@C2H>t%x%W-zEN#SJbd7?yE9`OHmEcK z;1ZZ4&e8$zD}@k;{GqgSfqWcZ&<_m~)B_hti6F?0{8Z|ib0jYEbIHE~Bnu$_q6DrA z*r@KcM$J%X>NVh$2q0x5Z_h33fq&!OjV0$UYbu9P=qTgcIoia1-3G^PDxP^;|5^R1 zxsL;Hexdz#Z%H^xrQ>tnAFvg8Wk~p>U)AX?b1bfeS>e8H3L$wR74$KLH+!-WfeeX2 zTXzM46Js_0<1MAvPciTT9^JiPcag9RN*;q~W#`!|zzPl2{}QPg5CWZYMDuKhHF>1~ z(H9dPklJj&)QYqlt8@Uk^jOfV<7;dnCjTHh64&XMFJG<$a*ctjMTd#Zx2WAMw?56_ z?GD~&ZcZGwX5k;gvy0afco#p*2@)Ub`0D(_EDsS|#IFaXDipmC=oaO1m=5t<5Ei=z zoLM|EkG1Ud;4oawuve>tMmR9Txk*GSEZ(}`y}%!Ph#nS9FHa>5yAF1K{!rpu_`@7F z>MvaghX&~EcaMr+;7^3M9Xq4?-)}0BwfArbQXU8~xsSfibd< z0&0T&TM2oJ={p|fhf(yz0o4xGh+0CH1|lKji0(ZDTt*gx8%(B-)u6|$r%i@>$O=RU z=l>5BTn_eePiwbRae5}^e<$@_8609C0lMD_s}=~|1(<-+hXAEoU(Oe*vQkfr)>`tc zNO}WMjh28b>_iv@O>P!HCTtdQ75RlI% z+e~Z6oL&^BM6_w0JWEe_H;EEg112pE4P<$d=|wme$#J-$f3zK7Zr)P}xhE0zJOAQb zTOeH_qolOC8X{r>4fVydpMt@B&jouV-hdx;@V*mUagt_cezXQN>O)AxKTQ4yYx>$s zW`?gmKU~hnvP6_1vYIqUk**%;s5>l*Ql0EGeP^ku+mH|^*{eTA$ZH#7%afd6Xd)=$ zw>H*xA~E||a?j=8#3UHB+xR(3B6i6ei0h@$E3F@&DK?jW)0<-B`|4Adfl-0UAeW)r z{ZRJp*qgUZx&OmeeIXK{r3p}|!{Xt<5tR_Kn&XP{F9pdxKsLCwb??s+jM!8Vhw_!2 zG78ll-;*H$CD(%g-P2IfQJfK5N2zYbrwqs+14X-h$<)7CzbU9L#bo>s42}r~8bH}J zCt!f1hQ1Nj=z2Cwf6Yp}blp<8#7aan9JvT}kV|z8)v_k5kRuTD-{5gZkyCx9Deuyx%_?Vy0WirilGH;2(>ls#x=hMt0rv`eVD_ z6WsK4>hJNzG^ma&=%}ws8UFkBGGd}3C(rMMcJ%)R=bzDF39WTC8oZX`E3+#lYw_@p zD<+}4o<2x;aQ0dDQ8$*ifR`q9J=U03iTfks5gOsOE`kv9A8AD7A?;J_e=aJN1Azo3 z7d+6CLFJ(*t?R1#s1HAU?H-Ha0^LjtX98U+OTd%Ce)5F%aTQr>mBrQHnu^76p>La3 zNIFGbRb_uLdc=BJ2EQos5Zeb!qzY$irYh9nPT?SI?0lowoSm;EY&w5~L(hOL$i9N#_laUtIYVf_foe$< zVEvM{9enJMZm z#Q2I0LM5f@>!E0wTSWgz!-q&BFaXbEXPUGk3>vb$}QYKaT%ZdSN7O|N1*h2VGr0%3wF1R~?HWryQ z`0vRAj0F;cH@g$8@s3J)4wB2A&$QmZ@h)BBV7|$}k4yfoVwLCL7yBL}p4Fd&1(Ec~ zIKd$-)K(;~xv6c&*~DJp_DjJY@EiX3OIusOT|H-QMi5zS2%vCyh+!N;v^5tE?)yX0 zB`}II1_5V^x@Y1xgOU<~yS+(y3n=Mzu!%l#D%Gf#M}%XyRIMs}1YV8U(Hxn#?_Zz9 z!H`M1>rvV;5IlwsIXSr)APRZ~p!{%UDK;QhhTdU@-&E!{A)x4yBFAPl=s}jUbF!z9}G-c zO8{_29ero@vw!@}*ZP?%@>ve+@hn>k{iH}{`IL!#hWFeK<2gLSS-ibKrK=~Gwwlx5 zA1%GvH;BF%FF+U(*T-&WFK_>JJ0Y(2`U9@nZ%>W>ct$!ztXG=*PQk5(Bml~(5R^L( z*K9LZH2{O!1#&5I-qV0Z-r^sEQ!$Mk*8%Wc%fJ}@=_ zp;ah0JZbj4b{;3ZIzcf+kp-?i^ zCB%4u6ZOixUAtcD%%c1?cFa@~H%q~6&v#|SQCN~V5ETSlkMVZJQqNnVi6T~`J_G2| zh-V#j^W+v&(}`6iNyMFj0J0w}CK^zIJXt&WlxmH8T8@}VkY?Za7$HoRi=q(1II>u5 ztZxL=&_>L)+h#f)2;z2_uJ|yznqaM%;MjgR8Lsum&x9)DhtcvLct>GNv zZ7=sXCGPF%iAE?I9p_s1D*AH)1bz(Wu96@Rz613}ztF`zb+m%45#WEqNqH3KKn7ah z*^h;96EY;Z8H73(YZOGDEnsj8W>(O{7u}%sUMs2`;+Xcl#9qxwu#n8rUf0z~a7-NzzR%iIRJ=0t*R z_~G?9bwEHe81W!ErXn*aFq&X;>*6VEli?bCK41AeAc9Oj=ln*{C5A>u$+z}**+3uU zPy8YQDE}TvrqbPwHg!1%8c?OKNODGi69-V%e*Z5EAOXy+>r3Nv2!9pO7$*XxR0<>~ zj$rTTzxXa-_&hR|;>mAVX368C7vk5x=aCs*T)YU{xK$)iT63vjU+5S zNn+3&vFTIRXjJ|?+)+`?nx>Zq9QnF5sMMv2_Ao#=hMJXZXDc%Qm*Ina*|9mva~VphQ{-Tu>E1Rb|} z$HF=eWcukJQ@8vC?CCQH0QuX0V_G!bh$E$IyawIdFx})9&@L9d_p&{i$d*DknZT~a zH`gymF#nd2YUF?C?pNqf9?$nN`i*t=ervazdNeH`-+DDq#@`DSI6vw&At#IBr6uEe zRbpZ5n4Mm#`#5dMQ&MFFM38P;0LfM$+bH?z5Hue&;6qSL)v;G#2DV4jC*fSu^Q%K9 ziB>im%BmogJ5<78R>bPN0o7h_y0}6xNTm5G0leG5oS0^W10on0NYIWRu38OP-#{qU zBOf)wZdiQ6vR%ywi4?wWi6}Ux?+mrJ4;zRKtiLzc{XVRO$Pd%3s}*OJw*4#a$}^#a z&2NT>MbZJ8P#CRK>E-o>f&O zYzd4JVEn3+(pOJ1UGPwg5Zj0uUwZ8gX!?8Fd}BC}rb0Mt+iv9aWgw|Fo0Gadbh^>~ zhc}Sd?0JV*|LupqQuscpx3izWvaHu%EIb}KW?e5FZ0QB;UWZ~zVf@o*EA_X>dcM}l z5YiH3x1>>V&D_~1N@W>22DDu)B&rQZ`Q-le61j&QRI7FC37UJe56E6prs(&tnj4kv zq=G&T9w;jeTXTIbMC`Pj+;!J_Hvf4JhTVm;FWD$B$U8Nb<#ZDLiELICMVBn~F6pDE z^L{(9NU!^$v#^Do1iSm1B$A?Y%a*6U%Mlvu&&IE;UX}`B_&~HSGvo#fx6EjJ%L*SpVmF14#O&zrKa`2CA39oi)?$U#r`}E zex$w&K^)ckaU({HT>zL!1wWZ;iyC&(Wa^9kQV{{7FCjV7ayb7PJA zRt{-Iq#sK65S&HxqnzW9_3lY0+88l-T*c5=TzRhXN4ypE*q-c*1_ZwqG6ZJ@yXeO5 z@@uW(%VNzF>&O|BZ+QWH&#=uv!Lx@mc-RA|l8KKysW>o@1Eopag0zoYpAd|RtsS;j z*hWIgqWK6o2?($vDiUxWebs2}@slJdyEkS^`3&~n)pdW)a@wmAbg+S~;{0ugfZXFC z@&FY>Y+Rh-8mZ(|>s#%I?W?!IACbC67l3JqlwUm(l?QR{h9Az$9`Uul971jZ!6}+k zyj9zh+HDR>vZBJML=KYQlL!fXI8+?J_lVFB%+<~fx%Ed#fMvTsc8rw4Kz(i3UBxy1zVZJeCO9o+t$S4{tOQs`) z2FZj3NEKyK<;RhUBz}V)R4t;BdfV~p^k$uYv<#?3%f4Oj6@Dd1r>7zbjyY2sX0C_S zBI-i8a@SE(TWsv5*6#mNbKZMmF07h=&kq?%zpuhU_m7yB-_iXw6g?>7(-XI;*+#ngM3=zA!=NF-7g&}gqcA|ax#XJdAIsJI-F z#oQnh>U_AfRITUXDu0-?^w{@sHAcS;eT{f^lp*zT{w20=F{(@dyf)+7_um9-%!{?n zJ{Lr2@90*-(*X9oW_I;qz|X)tDWtp6J1-;_$Nb93d+B)^KblC_1xm^r0ti)YYgkBL zWtAK!g`P`ltlDblx7{ltV{P-VQK*T$5iI^vF_@ca#`2D1te| z-i~~m-3MkLE)he)p|zOIbY7tD>5YC#QD3o2kQKkza(rZ^ zU$Z;a(D}iE=$YI%G(`lqwApA{Dvp9AE?k~NKoc{F!6dQUwPQ{&QZ~{)sn%(2b=_Ca zXjgMgJ*+$ZxGKz)azBvk>)4ms@uw?9FP<$lj?Bz9biVn7DP@Ddkrd-}q zYFk@K>4mZ^ched*vTQc&bDN>%qWEcqGMn{J<^?zUQ`KuVcTiHY2<=s`vx)jpGSWOK znyy4nP7 zlStg@9{h}Bi!c9b*#ksvOU}uh1t9VzKvHn);Hy*s5zmO=PW$c^kh-n)o20|smdYvh zKEm2j8oPJHC)%u`=3fc2RI60fzLnx7^fVu*O-@Xx<4UKge}#kYZMf*634XKDY0$p6 z5HaHre84riUJSN}D-gCk`kWEN_gBT{NT3I?R#SH|BV~wVG;sN$JigER*T4D@={G#{ zdj&!>7YRjy6$W@w(crR+AJO1ZJ+NZSFjV!Yq4qAT@qI*T_d3R7rm4>|2VL$F#>3@w zt%yz^*IZ`*s>HZuJ?T$vbz7_z=qp{>y|hHXM^~B_ou;*o=~%7rBRq|q!UWu3q!;N6 zZUbe6iph>59oCvZVG4E$VMW;`4A6htACXmjC43_N;$uM!z~0v_A}dG zj3sqnlUr!8)h0}OpUuq0zvHz0Bzp6TtDi}nKc$?S#7J!>SUS}p+c)1$JTs)KWPS|i zOk6_LUA!k_2-}wT2J)>txBD*+4FJkpzA=ixJIGKqXLNr-r8M5r#)jQ7l!ex!df=shnBT#jAGMH1r5SneO z))2b@jH0yqkn-fCV7#kPE0@{(1ZWS!&{Da~^bbYH#PW*(#K0%9U0;*68S29daeS(X zuk)8Uj=PWi{NreTO#vj}F0!)_$Ew&1UzBzVuc5y7>)1z6F$yHd_sm`6X8GeWrPvC| zx+N!JQzsy_V-3W`JnHQ*e>BB$Swx5<-1tPlX@%WbFZ+xHuyhXns=@qcD^}9p3fBm4 z-(=dKP->}-{V6n@;f9P!jP6}oz%c54}m}`Ri#HKlP1O!S5)PB+d!wQ-)UyhLG zysIGq6Kb3z=8%Zbr-FNsMypBZjKsUkx6w#zbU`b{15{I&ytLemp7UjT{D5W>)%}bq_-k zmp*p`^`MGZ!>g|gks7Yv%>GN_DhtGt3-7aDOWTAKrX~vbFTJ&3QeIm(56CchYX9Fu zDFsVIXciPJ3k*VBQ3zPHOu2Q+Yj&OQq5L`nDxaN{qW`@)@CDoh2yW9Ixk`HEEI(0m z^Ut$Bk6v9B{(AKvbSsXAq)kR7U-{AVA7A)SZx8TZ0NIk9&XrLqJECx4t@VsKx!J{s z>4YWx@BcnTdILVm9=b+~Dh>qqe}0HJ#x<%!8a2Y&+p9zH$g7agFmfL2n1V{4-nqHn7oOJ?A;W_7 z#CGe37V?Y6^zj$_iCE}UJt_RX$4x^<%RW1=|AUj4=)vwQ{6I9uwO-RcyrcW!%GYp7 zWk0)tY6GLy6;rb>#)Xb%u}jfbx&61*4Y}e?46(0xq`>5~pH>lT{LY+$^`4=QVT`2V zIU~Ze(5*BgD}ix||JEd;QZ5^mg`S$&-hHGd#)hfmw0wIRZ!{FEP315pd#!y}GfvKGL7XnBr$X6f!oh;ywIuN)}sj0^G90!7l!p~j2vS&KC zC@6I07ymXrx8Bk+E^T6?M`dAXz#ZXi__uh45ej~jo+`kh2tp=`bpQx|{M4et!9JaQ zFE)k7Zv7R{E{Y`f|Cl~~Kq=G{Etx%+f)PQtX7+-oXRAdJ^oGLN-|U1xucSvvPQoB* z1TRti?)hRVoH!1Z{3>`+UgUUeJNTqDYP#B%*iS0J;k5IOEZt5O%4}W4C7^OIYD}%{|FsNM}8(L zmbrIw>k*9_m&GQ4S)Pd`&zM84U>ckFx&U76c?EC8WEN?(UNA z?gl|Xx)hOa3F!v$+2gtIbH2alFV}Ld8D_57v#)o&KEx5PG~-8NfR+vB^nRvF{wnbZ zJk16_`>${QvCQ-!rO$NLl$9)*@y9%*%YFUQvo04m&qm7a%)WH@Vn0i*etBUDvM<{} zRzV^_fKnd9vFQ*hyYhJk#=(7*%M1Vo$zTMmCNwWzSk41D2V3=k;u#NeB6+gEtSEt| ztd9PFH04(Dk50xW>FyhBd;HdE-aVHp=Ty4CP~>K)i?TPrzV>`=O($o@*!H4I?on*5 zs%0gCh}-I>U_Y+f379SQV0tVRtWXGIBrnMn0O@oaj3r3~agz37mv?<@;M+N!j0Imw zLH*@`FtJ|c95?cjL?oNU#Y8~x#GQFYORZF0WMEMT3XsMNH~t-L7OO0 z6Q|vIZ^I@~5jsi%YWV=`;gn=n8F(FvJ(cn&-_(79Wj538;{_7N(Jo(huUCEV$CE6) zjT}}ycE42XcbI}a!%W#LItw4h*OhF)-_I0=%k?)bSL+Kdv^kXkNsx60U>XAkJWZl< z&%SqhoEL)W1m+}JH3nTj^x#^6qqs0eyq5&#_qGG4C*9+PVRxtHHISw1LBT2=42o#9 zS(sr)Mzk0K8nSYX;1QqYw@N}yfnT7qX#RLZlI1W+h~T&TQW#vyGLPl3KPq|t&7*ul zYNeiZ6?**MCE+gI^ne;3%fhOks7t8gtP-jvK!RpD03!6ZvXI!#csNB+2ceMtY1#Jp zvmkZ^L~yo~UMa^zLn@G6fL~Atqj1nELD`*5NE;-LMA|^R(hSTyDee~i^YDs6v)nYy z1#DWPdGOD?#@L5sB_uvjcElO%LnWhaP{ikwBA#Tpf=+FXqm)F`8UOMn9(YSb?-HO2 zzLO8sw8_qXFDr1lmJT+DRg}IL$e%pE=~xh+A@+42wI6H&)jky@&_|N4FMFT?AyDyW zAosb5r`!d81P{#xxO`HfTdxW)FcwL%2jra=8cOtBzG`v+e6EudEX?ysV0f-EZSFns z7yxe8dlo=@xSZ+qaJmIA-39@iL_~7$DTuu-%E=t3L6`?f;uV4-f%ybD&!ipz7!sXI zSaS)uD)3z#=WYN4x@(O$gGRVhjAZNwB%cxBE7{4461Kcwd_HX1`gUW-p9kEwjKF#v z(~8Z3M*yB@K%b7T8gz?9v4JH!DPn~8^fhzlb>OjlPQgf0ydGk>eN$8xoU)EgXi&(E zNL`+FN}RwS@XWRaE)w>j1^^HEAoGml28e9LGZ(G>*3R?r+~FgxkTJYPn_m9&J3=92q<8lg+JAE#H?$k}7d4237URlZ*(Tp5Rwr|8 zPNvGQ>NB~q5T)DU#O+RJhoo`26)udRz0I*-QoU_hL{%@5s81$IIEFG&fTg?nHt5Ml zos@x*92~R=MjhMwGe2_cSIa71XR2%dJcwG+St2~ymxQe~A19KekC**^Ky4)r$TeBo z;#)#5!#=Xe7Qf7R0Y5!>E(DAw3sNZ2Ot%mB$O?=UMb4gr~;U33Y$5TXBfP(558wr5Jm zaItrSwH%E5MzK&=%M*TQ2vR_?PGald20xL)2(d!znuN~{y?@@_Bs4_HI06SH0XhL1 znBdy70K-<}Og`mA7*Z1y);cK#*Gy1O_&Q4o> z1s_%t9vARY^P<71b(z3Qj-k!ISk5;xZiARGvCQBXH(=HEH>mL3n{5Iz3?rldm8r$Z z-ETn>OGHy>rRw*Zfd}QK{GMi2*J6NAP7b39Z>)pYxcpLl)4TxJF|a*4>+bHoEw8YV z&TDtz3RR*zdr1=wRinx||MQQZp4ulDBr4P{9n}}&fZRZfhU8*p{5eHWf z!Q52zzHPf3Fth%IUW)=YXj`-S$J%`;&or*C`E^*r;5F$Mk>o41g&nWJcBW^;*M@52 zE@La-OnTPA1cA%hMS)6h+2>5pY>RY`-Sa&h{R@MRl{+7Pc6Zf*1upG)b zxF8Nz2*4n z_fn!a8J^mVLL*Z!Grn0$Ifs32xyaj6rI~>K>&P};&1(dSUaV!<3j9w4Cs*1OLs$rtS%tHZ8@N@4;vbaGuRqTcquJ5I<35WTB+QSnO(E92 z7zbo7rv$bNvV-h9ZGS`^T1R+0NJ zgPR9ch{-RVAfgJ@z2m-e#JqnX-Z|ZMA7hTm?hYr3T~ACzruZbI9C#ojv29W^csN#+k&A#c2=}8y)_)n?^7hPvncoY z@6Fzu`__<;lWG-}$!w6|znU~PkNEJ z)H!q?FP6qk;;}z4&LtI@`5G-9f0~JpE&~Cu%~@i=){+s3G_{m-uSu`moSWxD3j^t1 z4`bgfzGUfzyxTY-oPsq}L6b4WS2Vb%K5jnxhN&i8g_&MOwF8u>+a;-Y2nT|GJkg2J)B7bt< zmzBcW38Qmg>&KQh<%C$|CwzR1;3f29$-NT^5jq$hj^kKP0ITjRIUsKexUoTX}4SF*tJFtYl(q= z`fO;_sjjiohm4gcTvS@xwe|BbCBvXb91%vDl;gsPNca!TA}?MHor;@29rD)=QLxYMqB*zcr8jz+-rg&*JLOoy>Tb(pEdf% zfA|$o=cdZ-zc?q}bB*wAE2VB%>XM{Uvt%?Fc1a_uRUl-j3{<&hBkuQ_GV(3xy zQ0Nt_onhz%EIC;^RQcVhE3Dc663esDeG(>9{qW?R`q#cg{rqGsHV3+|)Md;b(l$zSw-HX_DzgYC!Z z9A41$SBibtO|Q?7%byTfQ^bpX*tbwYUx+{F{piWnk8!G|*F=s;R2uHq5OW?r2X5KA zYyzk3W6vD6c22gILfdaH^TaT04xy1QoW{wUU3{5ez8_3)=7VSDws)@}m*xi8bE+nOmjoKMEGVR0^>pGeI$;M!g z$4+`M?yR*4_0&k6u7RLOtIikEZ&z)MzD%_Ts_i;rvfBLIf2ey``PL8PJeR=!LE5(O z8U}TtvexSHIQSlK%0Lp2^5Q5e^NA_iBO3{_d#*6y4@>L1h7zF+vUDJK#f*8(tKDP4 zkioe+y$kZl)0F%poyJS{exq;uGqs@Brb8ATGX<*e)Mw#~DaoCo$)>~U37rcW8*Q!r zM9uH9p~9lE%<+-65JY4Ur4|(MJYfQ`%^1s zUrRhley(eBjyCrq?X%Z!4R+_Cb=$U`XBog$rsO3!#nt24Ke#Dixrbf6h18%{Ig>T5%74%v~Df zP;)G}LLqyg_@DW8>5%4X09z%kR-FltiV2hwv}Akevh%II{(+VP=_QB(NH2dSC-Lwn z>{|Nh;Hk2sj&Nj}N6G^b{|;Y{vBR7r3vNfYS+5$9jdK&Hoj7va!a{>&=Z;S&BeJwu9~;#f#( z@Ha3Rm*ne^V1te-Bq=7S0OY#wvbOI3q$9BIW-1ZOQ7*iJ&Y4SC1M6qToO}p3Ii!4f z-WRI;!NEMnNKOOf)<&geE^fddh*2KkxsdJ$E5w;}b6NbVPC6A*w36RF|Id>PxUxQBsYW{m`8`1)eq37S=Xm${ z2$j*)rHr%|&i<9Khf;!a1QU`|UI_Z>Gk=}5q_o@f_CzShsX1vW{`Z0Z0o;GUJ7Q=e ztNt>U9Dh(RU*+?@)gHb)IWm!lasJEPLZ&HjFUq=oVh1e9lA>B2>$z$BaH>1)dYrXu zrFk?}lE``8ce7bKHM`3HRcxhLphw#6NI0hRUlIF4Tb&jDS-_G>`S6Yzap7J@)l8Ax z2g&Ammizgm1ZWsveHo{3wsW(EJK^Aa-O2ZuuiFD7W^fC_?<#MyqU=Ge{_5Cy9Qu-fl;heI+``9nsDF{R@9MtYcTtt6EXB>^x zuLv56Ys~%k^oUJSeT;+)bhTlS26K^FFki5fSG9 zn2(3W$6SmAj|!Wj*WV=Sp08QF9ue_BZTh7Q*p5xt%_c;MsZ!WWRFvD^PnV0EmA$I^ zuxOo8`tKQ`hy5QM7ovg0Rq;x$TqA;cs-(e1%?L)3OZ?w*2R#Njb&-KNDVp#fp1{x$ z4mAxQyTsH$sv=0q4nbb-Q_|*tbl^Ww zM@H19$^0dS5mYj#ulw_Ia_VIOOrSpTKZwLIHgFhaz6TxH_hSd3Z08s0Z^Co7n!7OU z=l7munUns9>Kh^Ug8HMbZR#2PyYmP!IZA)Mz+Wwsf^Ft@;@G= zy2^s@(JAxMTAgt(C2QX&fMTRvD4**|DNvX}YPy92L6c+GQm;;HE z(5F`rn-|?HB)*#9Y8N(ggT)@Q7LHY;$^+K(v%}l6hhsE14rx2%c0g3+nxn-Wx}q6Dh0xlupsRubtWt9P?USEByEMb$DsUNKS-|Aa z_UD}Qw3;gaXuu!PVa#6k@lcD;kwd`%HM%^A(@F2NKH)&Y0LgrzdrSMZP}Qgt0{TMh z+_?fo|6YdB3k#Gkz_wsPrPr$Ie-|~>Z~5E|fe?XXE6iW95LL0hv12kC-L?;2GU%|SPP_d}-{UXm&2yVir+6GC&Y;pGA6_$bv z%U?)E$RUkpVDL*4DJr0g%@_WN)fz7H>!uO4$)@8E<<4p9vEX55Rw`CZr&?@&fA03` zO%FOW2Q3L=+13iDzfMlp`@3_PxZt#{m(hXSmM0ASg1l(}VV)N8LObp$+9 zFaYAQO}DcO9q+PpB9t#OT31)+_`|Y94oF?J4Ew{v=b*x{4YsB6gq-HXK$j^3`n4mF z78O8~p$M=yC(2Lp02tE{ybH^nA_b#`0}ik@bGef;=d%9_=`7odaaz&x@f z5QWEWEk@1@?2R{^oZ4%+(!fFzfWN_lP8*}_0N5-x(@PMtPnb9G8ef6D>0&s_z^LwHO?nr<+}9@e3I zzr11#h>@;%0Vi%CT;2_^$owFFjILIrRg)v;4rcHij`4yxZySi<7lB;0@9LnQ4jes-Rf941|iqZBAfCT2E7c0WnCUmjB! zh`)PZD^kVu5J3Up;g`vA=Xp$<&iKRx&+gKg%rh zcjIo@yqn-=VE^58H+cyq8G($vb+@&E>mfbBG`aYeI4t9vRIYKl>}&9YKz`QhOX$pA zZ-8FDEr+E$GXdY4`&kk&KZq;ic%U0_&}K-iQG841jmcur`B!|Wj^?{watgjX3~9;n z2Dx^e?p>h5JKdX|cf~rvk&t;EvOE3Ck7RkqHVD(F*9na!k7(0@G7G12BshEN?EV$Y z1k|~q;A;B#PkRbpz5#{UE8NUQ$USgn5hB1_&di!ZN)P1ct09+yX zl9jjhEuH)B1SvCh}P0&zJPppr%>V{{Z305{4R!gKof9ZUf3e? z9XBnHB&psS-hE|Gp-d-(Im6VupP&* zdx1dq94I=RtB6Z%vv|j#xxlWHLSeDgDA|0gymm}ttVj&1U>sBDbLAk&@A!o_br_5q zL=V^=yshpyI`gnmZ4~3I$%L@{@xT! zJM*UVx)&CLHt#uM`F#NS86Hu5GDp}9)Qy0%MGu9vWr3vY*;*iGM#+0VNub6VWsyex z1~(@6Y9au$r^qKW@Sm=~AaenUp<%OB{pU*`TRFQ0Zzr~&M|v13@|n~^i!3Unmc(u7 z-@gI4){<#!g~IFucnY`pv$pS2g>7z|VsgnpP>mit@pjTFSU4E z{LCfJUG^rvzoHjYTn51**UUyGjdQIq!xeoA$h`1EH%5c7sU z<{(y76;6&qjKcF6L6QBtKPtiXitf_6o7+apfUBPIAq`9GK+I;!08e$F>yn^DU+XKy zp^FtP3bChg1HX3#&qyjvR0NRsoawqsCavt;EG#U17k$q&dF?p20Pz{$;9d3GwVD0S za!4A3sBJn!s9y)OO^804rH|{Hop;ORs6O+Mk6&yh(=f}diu(%IpSYa8_de%*XNw&{ z-Xry1p4oJ6R~N@tzI414eg>yC^{%PD(Siu!oXC`uCU<&FT8e%ghrTe#+J5i6^Iu`B ze=3gLMu(Uky+Fdb0&C;D2mWTOERC*1`6P%onT=uB%_MJ z#lg|uPz)sGQ1I!z0xG_4@YjxNsvgQ;%6T=zzFc?^SXG-kU>LvgJCY6Oy!U@mNEjFg zJgV2Fm_hi-_zo~<5dpYIE=ErsLP%zfjC{Z|Eff`0TrhM5yyd29qC@ft``v1xV@SjtAk>UNWYQ0D#^3nUSu+@jcNvn3vYbg0iZ5Au`f2AzXn>t;%Nez!dJ+WO zmYy9?{dV>+glNBDMCs;ybtA;XgQ8OImMQKsdd3^HdYj7pGT>zSTlgjRmF1ru^K0cY zoohqj_q{Jz&E9iEa5>_Y4bggm+JTHreIc4L1XKi${*;Ordd~}|7FUvNue+y_D zDXMutHW1d(w%x(+qAS){99%-<=!{5W|9Ogu35u##C3{g;?b_a|X8A^^T%$_Z2wDa% z8UlQD*|uCIkRxM#iC6Cfj6vP6Z9rdj<@K!0iuZf_HV-{fx<3>@VFc=#OrlrXJxOPq4Pb z@k!yyot8hcbY-5`mXHx(S{sOzGC5=BE9OP4cjvvJXnWqjOHZ5T&bn-=1CM4|=0i+{jxB&M9h?C^TDE}9wa|8QQn?dyO-v%PccPtGKL zjB`zMO*+uPL@g>yQofTHN=Bq8?^{iYcG?XV%PrvAHWc0hd$hT`u5TcR9AY%5Si|2$ zOto)eE4baOs!O>R_Ywi!>vz@ftC~Xrw@%q>x9un{pH@(wt?LuPVZ3tSYqDK_1Af!q zJIDm@ctqMcweH&dJhcz)w<9KhSBS2YD+b0tp6WUERinTvgh!g&2}_? zd@W~H=jBY_w!YlfJ1D)?G}o~>%a4SJwkkv&ll%JLz;4#Bj~(Y7f4dci-=mWHRYW{5 zSUS0l|AoX)(!jWs3arP?@*Ma4xX7Y1qW#(Zx8LeWn<7H_w$iH=4F=FOY(Up?^{Bo2 z6A~JmEvn?!Z9p0BN+Kx{v7@)cy^r;9qvcek`cU$!#24`hoOcH3z#?n4cwax@nPi$`&ELI=_LF8*-#m<{hEHU;^ zt8qudWS%!qjc<_8sZhDU*z>7F?n_uMY{2_JlBukr5T#aEnw2#P0`=3*bI$4mE0n#dUFM`bL~T z)fUmHf?3&3k$CBky!4ongpt_;`8M}^{l$rjms+I0BJJh}*DLr!9NW+L_NYXO4#8fk z5iWo~#`#x`OnS*|>42RYVR{`l zI~CVElr{+a*k9T}(ov3{_aPwo0%C7qA8udGVHBL}2KJ9tf(Vl;`|<@a{asHVJc>7L z1Ni5$R*+i{*ghtl%lq)fMw#S^_aa*Im7w(&s==>6FAsZT1C2&CPlTovr%?2+K@6nO z()v`;ivmK~Ft>nb&PTAC4skARU2&hxgM6(2h_gwhmUD*PZl^O^YE(K1EnTB~Z9R~y zbCG5c7t}Ms2QTl3Im9ZtQ2jQ#{bdGluP~&pGepnUV&77jBU_ zM{PlSlsXZ+{9Hp^k6KL-jVUV_jY5P!U}nBX;W8M4L25OM*f)gv0K9q(5xP@-L~N>* zlc?=<`P+AuMp-6jgG1@(FewlRv_sirZch}w<*tKEH*RVpgMs8`Io3;L@7q%Nv_{JJ>Ok&l4F*_;GHIuw!4TBzrs8>@QFWzEZRXo?15?C~`%t32c7CVw0Eb z9e9F%vUtOaIEG453!V;*hzbOrM*V>3?S!8Cp`{_Vj!#B$u{KpzJ{{3`?FoGi=BhvC zG>l|Ipc%)2s91IuAuWRu4qnG{&{Bg78>Vl|!UXzy^EPK7l0wyd@EKOvy_fBTPCzgG zY_*9&h|-UGHv5wSUASvzcg|W4(T=F3b>8S4-U*>xWpp;JbD7>7ZbURo#-{1g)T>9X zBkZDY2NIU>?pK5o2A)MMnuM@lJ^x7Gk^GQ3DvxmD=2hgnZx49F?56?I(6hKH%ae82 zXA3)sN{~vm^7ZZ3j8`k}f|L0vU(_*SO)qdG@+=3rh+bW?3dyDaWs3Q_M+o=gn!)Bt+0${Preb@fTw3zD*IoJAX~FxcMQz zlKzQM|5N+`3axS#kbp4)SS*W{(LWW zHgdf?f`CVymX`v>e#w4d0sTh@sIOOgNz-B$bbN(!DCPqaD>W;9kRWrbKA$IRTyF-~ zRZ5_`tP3^_Lg6|hsdb2oNz~i*S;-yt?DbJxsdzU;Z92W!k&8nXhHJSy{N4` zok5J~{zp)~k^2LX2I>2{8|+&OX*8EOi|g+-Up778#ThM{MJcCZ9EZa2N5uTSl$bf- zrA@Emr@KCdDn~KlD-}Us9scCnp)&)#Lw4ITxmF z@vCIy)a~PxI!0Gbvy_a~zn}F!sCRhBCs^)pI6EK%iVsavCI2og$wJPlWZO||A+<#~ z<9)1fzHP{h8KsVVO=50(E+wZ>*pn5*ivX>lrdB{_*!1M zlC}SiD^WK$o%-5vp+xZv&GPv&yJUUP@BH`k&dM=Yl$Y-R9$aYPen1Fz+QN(-Q|=P? zB)$- zzOJ!;@-GX(TyRge<{#bupKvsU7;2xLdDt^JK28`bdAo=s(=C-~u8NKwQ_@wm+~gP4m?Lzn=;x z0GjpJlT7{K7Wa|y0|tt->`%SFn&v;(<9BGv9X&g7O8f(kB;wO=Q(va~|H}sgp9BH} z4g>X*vi1abMCARCz55b6=l}OM_-F;8N2b@~_ON8ZmFh)*mepjcTlJ`J(|zXUeS;*V^;-Ki8k_Dt+qy-u{_Cp~FnZ z-pfilqH%A9tF=<}{~qE}6ma6To<`iqA(nFvwDDk~EXC{6=ZbLl=fjI*9Ad~uVnqKs z`-~YCr!v;8dCnvEdI(KN*sp<0Rw1Dxm;c9vgWQgC>bf7sdBL*8T(atD^kU$O{Hu6OcW2KbPvKo(!)js~IdgpAPE zGM?ym*gSHYw(gF5Ea_RV^pbU~3_wc;v{FQ?WUse`|gs4onQP}g7N%sUkTUv&bs2-kZKZP z8+{3i8hW{KCw+nSH(KCr!#v>kStKLR%D(8N(v6ziCKYk=X#1^lqc$UT_e|hDp22N= zZg7D4>NQ0J@r*CK)Rzsl@>TRkC?h^k?+;t1SG8DFB{KREY^O)^KQZ{mSl z_{Q?X7_o1?yw-EYTrhmB;eKs@Y5`&?>-=7`h?uB8D=EPU@s8AG;Su-svKQL>_g_7q zSpRswjDJvWAjf-m4oCdjr8y&)io!x=qQ+@}a7M^;g-`e%T;{4WSOm)ldbATR+e_G& zFdw2aqRKmGT8-8s)-9yGe$J88wgn-z{M6=N{LcdR z>mT9HO=`)u7C0MfsTaw%fx2H3wW3pf3j|QGcYf`7wcOBBWzvp6Ch2T8W%0dbSAZjjJBDt;}tw7PO!l-3p*RcUG!Fv zat@1;rj>rtEVTeJ{}#-t$B~ARJN5bbf~KnJ?~kdI4Ez{dB+v9SHTN)lG8L?`J#9x2 zBe!b}FH>U7Z=-v>S&38au;+)y}wu!r;2{NZF=U2Idw-~{NafQsWnP@+GOINr*jM|PQ$qmJ3q~0>#ars3l033#sX^q5mS@~bu zxiVt1MR;}m=2*^0f8{n+wp_KJWsGz0Dx4`N%o#Sbps7NtIl_%_jq%??7Ig70CkhZy z%IczArx;NvA=C=167*rWo#FV}uKQiwQ(Dc|dRSM&csx`wl2@}m{#I44G@xp}ms_K1 z@?AWGqVG;>iJ^f0KLc?7uF1XK6sjd*P9Bu&BylON>2daPrgNqm+s~_JmUhx|hdLPa z^`9JbksGAfy{kYw%%PNHpZZx=?P=BhzeQhF7-{a!hTe3XeKw**+&Fl>h{Oj*>GyT+ zuZk*AuW`=RlA|tY+HA(S2)~u2{~q(Wuk6A-*%#>EsQ^C*|Gdv>v{)78geLAYmTnb` zt)iNWa_7mbJ;%jh;q7l0JHwgS^RhiG(c1%Ws}AWVH^qZjz)+4#y*Bk{*w|2?#g*(< zr=~p#DB6i&5P%%WSr_RvjQH8?fIK^onz5?_2-nk4=50iOeR%L*0JXZp;$r#NuT$)v zf+sOXLARqMF!?}1UjFkS<<|E0mlS4QD2b@s<6z_&d`jBs3~il14%XjQ&Wab-K_RPx zkw#B5%hq5HYD(eY;f;WJevwM9NKw5$2se9!gj~u6iRaI}nLJ6v4xjzGG7i82wVe7G zK>PAAGb@W^sim}3_VIr8&xk(^9Md$CZRrPc7rEpRp;bRKa)lfV=7r~qDxHb+GNf_1 z4GdgczcBr70v~{=k2Os7tyGP=4VpZjmLYGNp8*m)bxF4C4+E|Ki@n)x5cf_2kn`iF zXx#n~^oIF@?s-dOU->k9mmHE$iXH@J|Bh5dLt9#AAlWe-T^2VvT?Yb!Gsls$V4Lv7y(}cS(ktX!R}!uPvwZgY8w`E?EFLd8ZJ7{uIfc zfwGLPLxBxlmi-5%ia%GNW;LGvy&SHlp*GYHlU+zLtP2L zG}8u|H))+N&n7T%IHJ@PSa&(lX<~Sro3WxPhQIf<9ET}Ghr#G^#y5>9B{k#ajntDZ zLc%gf<5 zL^RW2p`wsL`4OT&65ya>uV27dkn@VQ$1#*~9%x*QqK`KP(6Jqkpjx5*^%fk%6i_!< zeP%&~DnsT`NV^N7+GUMaUq@Cr{qAOSY3S%=fVX2N$BC{-R0@)Njb;J|l?_`U=Bq;BDvR1m7kap@_FT7lzjM&_}mJPzgzawlgBsHGTaFCQbqn$!e(< zUzB7$>o1Dx$^T5_5OW!4zpl)Qf*-Uo&bx}^mM7r}b^kh0S+DR7+{K@(YHFA8WiL-KP~!rido_7!K!XB5`!~^j;3Q@nEw0cimUz-3;7O&y1m8n zg-L1f5DM#WWS@lfmgr)ZQIZn8n{P#Z5x#x4Y z{OTHdZ_3b1BxE|gA+4w^trW5u1wP&}h?a%`2MzV2yhwe4M&43Q2u+T&It-G+^3v20 zBlM_A+GD@{6G2eU@i;<1?i<308m;N+L1KBOfZrYy!gx(uO-q2TIp=(2LDbkPmzN|n zX+FG_Rpz+YC}lbOF`Z_f)kBY0#g;_Fp&@~Dt2HGsU#rkDCg@Da_vRh{UB`67t28=6 zH~f)`iswJd%;d3eH9NqOy`nZ%l}>eZoEi5;V#D)a!6XW3ntnX~^QgkX$@#v<=6z-E zw=!1>Rg(da`(oJJ{p8&3jz1HrAAWUw%9nGFgj3mjPCc=za>HTBv{)#YSjn-iCEY%# zwm_wc^d&I0hZ=XHr42v^zv;tW$7oYbh#|H#`$qSA$?V*zSBvCsaCbfScMFr;PAx{mlO!L708w zM5$OjJYQjQ1ONo8bVC;nzIlTo*)u?WuGRmVgu5h*T{eAw{@o;2=MXxtVu)z1+X0y3 zk=73qg#`*(sU!6d;T+BIo~z{-wsR~@4mr6UZ#;b-i95(ehQcr9s~0Mh(Bzb4>kcw$ zioR_AX2Cp2d{}9htN#pH!$8ke5IzrWvYpaU-%sUY;YcKwD;SuGw+!LhdmSOPm_62W zDd@Ci7rEN-Dp#76DL^_r2GQ>wksovt*yWcJ#Lu@UPRvwRY)1ox!Vy9xdriIBVHP(a z%XsKB#vN<@Oju-VsL8Vz2Jz6P%5kzbdxetsW3u$~?wcj+B`pI<)pgI$wBgRSI!U`pwtx3(c+|L3?(|Hy;weE>BhZISftMBTfEd9{QA zEJRz({!?DtrFYAvKQ)a{IPYH?uZ1rX@VyeT{f{Jxn+@nu)Z97m z=R*0>iL@-PEY>(!T!bXQ4|>3uw8HW^{kHF#iiF&C=F?@=J5G2Mr*5kw?m)-GGQ*Js zlJV69@Gn{>)e66{6HVY7ymo^jVUfp+%WsIg>zO4=8NLbbvk zAD`}rn+YoH=Pa|nu5A^!7aXU_w-I_wgqRWb`if}MALfDtwjvF@PaAvhw$X3Evs? ze|U8x5mb5Fa6gW}+O=bkIA1YyHan4C<@5W25wC|WO@T59mwhm34bgbGs&8m`&k8>u z?A3Q7Hn7~Q^Rri@r90ngL@niXEd=5o9S}j^4~}Z{xr;zJDJ>q>B(YJ%_m0~^?bxswSyf1nw zZ?`vF8gx>uBpzh910vYBPUR})>>XM@mE^Zf8Osjc#6;4Xp*zI$~X;y^mt8zQm^ zdbmqtRW=hw)guSyO%Dlu51By1qm;NC*(0a3yhAjh;yxuG0$y>Guv7dCoHMjReOP0q zuHG=GVRzI)DF<7AvT7O<;>|3otm%HSf{^-Yq;u*Et}qONpA?at=yVg@L-v!RL^!Qg z;>E}!Vw=Cf?#!+BXXi7dB;Q$0sz9IRB3}vNz3(+`*%&>gGo<){a}zFsq0d;a!4jM~zx5`+bBk_b(o?6$xuQb3jNcIHkfU~+^;JqE zPhnf}`^OQzw%fgh?!q>QH{&ut{O80)PTxE4ct?47oH-(KldWjJPlDN`-M*FxaL@nf zj-LNzO)Lsu9KiG|MY(J-38Xf_=<$X{3S=~ih#)>mb4rBus7r=2U-R-5vu9ad^qF~3W>EW@gOw}pU&8$MWEUbk1YFOnEE`>&IhR=P^^`XcuZ799Gc(R7#3i4j?4eMk({4a^F0tzK2 zC{u(K)Xdb*94^louKLitec4)9<4sqN^@z6u!hk)j-Ld<$YjDCnMJ&ie`ZOj~>RfMk zVZ5m?4Mpl{HSdTLCgM^08iAD%YMb&f=2%%M^?2b^d?Gfk86+P61Hw;P2i(ZxDygF~ z9|yx546zn3-aS_g&C#7PUa7UIpdE`WNhzJt{kHSwDRxl?GVha0mzL+^RLh@BXVyig z58cMfwTA*jP_Z3HpB{4CK7Z4PX0`E_c%l_qG8~iD0SO6H*ur_4?cHX)4B3Lho|9#{ zb+_v}o|g#47e)R9g-->+WHn~HQO^>D=tn0qo8&N+)C)#qxOR`}e}B6!AFYEdribB_ zQVVIT;aGig|9K`xx1~=nUd;GRLP@*bK4fHYG^}+vFXT-i2O@IVfa=ua?WEri{HoQ_ zYJG$UMQ| z<%pCo#A3M4DSRVmeZ^tuYG>4Ln4nsjWr9zNWF~lIylZEeZQJb_a}Ys{UhSQloF%*w z%X0yEzuU8uXwpo+F;P8IJ-7fGE@R}b2ys=)X^0CF)8I#Agmy_+IbF3tntZBrmLQ19 zR$%$KC#!>bRJ?*@%@XINkV!aW{*ztw?QCfUkFHPEQENjD#{ig(_Du7d=`HD2Izlq1 zZ2P>sn`8$21pW{rH4#gg1;LOJ>?==^2ei)_kk&a&D)RlAzRTWoVyD2eKEv<^@{IVZ z$SOLGG!6@w5lC@fiA&3i=E_lQ*+v&cHm5M|W>>YCZ2Mom1g!`GgH3@i8uZ=GJ|ES_ z{!tyH7}D!(q_BKipuT1+u8@V#UYH(A&1~={xN~WbY%>JiqO-CM#_xV{6(O+}lO`fm zl7>OwehB4p4K=F5cf~aMPm%Pmq3po}`OSLNUoc`i%GL=RJVQ$)Gh;HUB$hExUHD04 z^%MZJDk@H4NBON$?v!+f*Ne6X_u7zRhefLFbJ!9_+!mBME+V%$`ALQk9C{$tI}xK*8b>~ZF^Q{GL*8v9B|T>gTF+s zw|NEPA1Dc&TE47Ul2|)$iYUiA`UqJlSaL+WqV*aeIu9voi2cHwdwpoMS)KT*T$Fk- zd|tS+GGy8Jxch9!c*7if9xWgJwFd29!JsZ-yhA(b+-M6}7xB;I^Ews{YitRy!hU&! z$swnot&qHkj%J^Jl7SDm3#Ul^l+u5far=Y!nck=OgPALtvG+>UFuVey?17GyDISwu zi<9GBw;g1{)!b;jm_%B7a9OOin;GYvIhuO8Q63+>`#DK=3a`nAvc1?|RS3a4h-XPw z%r|Ogpo!!~W`9rV@Cap+{>?>0WE@(7XqyKWa4ly#B5m*pb;?r21UZ(06ERhJZAqvV z@#pukU-RgKu!hGI2X>Rj4<0Yh&qC;DM}px`Yd>pCv!4(>nk(j2X(quAqb&Qcla;S{ zQ~mDZ?2%0w=VHNc)mJoRWi&S%Wx?L%n@bp9>%tiPTs-<@)AKEknTS?S0ugy?BK3IN z)0YmX+hR#n8pLEFooPSY``y3fY49~6Z>J#g?+4ARs;c#8iRUv)7J8&7in0v9qF`4T(+?N+qUZAGqtRTPy%DM$3XhKbm{=K&#BpoPljPArhG0ZP-gp6X9uD zdPee>eeU7nAs*Agt{#iUC`my*qG@ zR%Rpn*Ln)xpw*hD$2p_XN8xYY?R0+<;Y!Y9%?VxD`;BHO+naoVM3>F!y%6PlTkH2S>cX7*T22C%Qps zIW5Xf7;cLCh92-6fqO}>dM?b-3;$q|{*sy@ZRm>UzS`oU$*7fg5o~m>Yfk#8^0T(U`_n+Lg-5D z2t5WpK7AWKQR%Bv3;IFjua4WjbPbgc9y;ro5eIOrXmeE8uudLHyt_{&Q(F#33cV6o z-q)PMn&wxoff2R8_ZToW4|)?}bn;N}Zu1lB#w$`hVzpBJ?0AH3H#+mq#NXDr^zfB$ zKRNJqXrvsIdJNMFl$|LMk41{sptBK6S-M1kF<)H$^XMk%4oPM34(caFVT4C?gDH8^ z{y?Ey8p$O>nMG1l=@n=|w1fjOZY}oEnnHz}ju=o$^-9}Z7gf^d7kTWi&RO4w*miZy z+avqWNu*dtC6L3x>J+zxOSf{y9OD@6M=wej4)T9Y#qTWRyk-^F>m+tiIVD122|R7} zyN!4O3wNwFq9_8<8|Iuu&QaPXbf5JaJ5O>NImdD%K9l)e%tSKTc4UuE>B`?fnR(!U zKEN-The++Y#>e{q(RG$#aco<=4HDc5(rDuZcXxM*5!{{N?(XjH1VWGi2`(YHySux) z-|D^h`M!PbbMHT%2D-asty)!c%<(Ge2g^)g*m++F4A@@ehM>=21aj^}ch?_1ZgaPV zl{{7u@m2Cbdn`BNtZ$4yK* zB`DHzK!3iV3}weG(B|p-qp3oo_M*BH>4itUPERQ*G^hyFo-wTZovbCuBaH4o zvuIUC6&yNlaP={ssxFhC9xLp6{DH-GMc(g*HJxHKj1MQbaM_p`j{PDOgqdcp6Q6$v zMTkabGG_+}1mF)6g{cZ@S@OhS=n_n$bQX~L&MU>>wP4bYa9EV&utx_lH$^!6J)q5C z7!mzSC9&8>uv_lNei)+{Nh2H93ebC{qa}@iXB@?C*E8d`g;`>%!F>7SV?TAK{-LyH24ao^*%pFIS*Ppo1iw$)T~q zvZ-r;Q|d$Hm!Q}2Ri{`Jrcc2#5j7Im9xd;R;YoMKF1q`6b$0r-1?9zTKG79e%p&3; zxx?B)j2gZmh8qKas|E+rl-T$nUG59y_uFl!_ZJ48TnIfq;1R=f30q~m2cAyjHD=hG1Bq3uk&>?}eO{J7<}R~)#up!NAe zl*HE?_nXZgcAM&GLdJKxA>S>X$}6iqe2(WZ1w*crn!53j%kpc2!x!gh2Ncc^ys=nV zgYRVEpU0d>^U?~W3gnp6tA~|{2xefl-ZT>dcz!i6)uWP28A^SuYu`E9s+_meO$+9tM zWzdX>@{#+_2@a$P-r)|5CE3X6n~}tRIpIN=)H7vz7pRHG9WpBln|7<%fWIhX*ulRH z6~yZ}7|pF5jkm|T zIR)Z(Ui}#tny9O1@stw0DBC_bS_cv)vp<2`TDut8}7`J?D4VoJz5(y zuAoz|x#}+3A;TyHkwvb#QNVFb_|dr3cvvl^+8}aRa7d)%kK?lzrM3Dv_-R|u^DWVh zQyK9MbQjbTlHaPOz@JOLilP4N3*}CeuR5iK2FZzC0;2sls;ahGB}j%UnJ#)-A2&hf zB&)jGJ0h|Ug{EX&6L0M*Hr>{~2g1bcSjd3g|P;EkAO=qnQJMdpWp&?Fn=m3wEscP%3i5Ti?2Ml;)B`& zND{Wb_CJ`B0VL>b%26p4ammtElivqR>AJANv_7(87^d$;~6@{M9d z-hZmc5|IE=6q+|*7Z}!u=sXH;9iBa2_btn8k|l9B{Z`gHN7cd>zZpEix6n&+b}QNH zB~H_NO)@8-I*uhTCDo(WXIb$xBY8)z{hV?9hvECa!yh!0ABU1?g`x!jV$Ac+Pb7I> zvIXIAF&q-H8VE{;F9u#dcB2~RbUd3>E-@9V7}u))`X%0tcMkY;QccweFW8DbBL1o- zL(=kitY^1R{t8-5(3s5*dVL{;>qUne!@K0aHXBe;v=@Pmz<$rIK z9wxqitH^*F3?$z!*P8q{JD7x_BJ9GSbf*8^MT3>8L>a!f33`(ZZJmuyhH0{g+{Ja2 z7M41Xd3luY*h_D8yVD~$zbod1F&-M57{(=>jK D3a}}fQrkcMm}@-ryr50v#gbA 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

{-d6*21bqKd< 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 Date: Mon, 31 Oct 2022 16:36:05 -0400 Subject: [PATCH 14/45] Set agent in matrix block instead of child stages (#441) --- .cicd/Jenkinsfile | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/.cicd/Jenkinsfile b/.cicd/Jenkinsfile index fcf5836c7c..26fb2ed355 100644 --- a/.cicd/Jenkinsfile +++ b/.cicd/Jenkinsfile @@ -99,6 +99,10 @@ pipeline { } } + agent { + label env.SRW_PLATFORM + } + environment { BRANCH_NAME_ESCAPED = env.BRANCH_NAME.replace('/', '_') BUILD_VERSION = "${env.SRW_PLATFORM}-${env.SRW_COMPILER}-${env.BRANCH_NAME_ESCAPED}-${env.BUILD_NUMBER}" @@ -109,12 +113,8 @@ pipeline { stages { // Clean the workspace, checkout the repository, and run checkout_externals stage('Initialize') { - agent { - label env.SRW_PLATFORM - } - steps { - echo "Initializing SRW (${env.SRW_COMPILER}) build environment on ${env.SRW_PLATFORM}" + echo "Initializing SRW (${env.SRW_COMPILER}) build environment on ${env.SRW_PLATFORM} (using ${env.WORKSPACE})" cleanWs() checkout scm sh '"${WORKSPACE}/manage_externals/checkout_externals"' @@ -123,12 +123,8 @@ pipeline { // Run the unified build script; if successful create a tarball of the build and upload to S3 stage('Build') { - agent { - label env.SRW_PLATFORM - } - steps { - echo "Building SRW (${env.SRW_COMPILER}) on ${env.SRW_PLATFORM}" + echo "Building SRW (${env.SRW_COMPILER}) on ${env.SRW_PLATFORM} (using ${env.WORKSPACE})" sh 'bash --login "${WORKSPACE}/.cicd/scripts/srw_build.sh"' } @@ -142,16 +138,12 @@ pipeline { // Run the unified test script stage('Test') { - agent { - label env.SRW_PLATFORM - } - environment { SRW_WE2E_EXPERIMENT_BASE_DIR = "${env.WORKSPACE}/expt_dirs" } steps { - echo "Testing SRW (${env.SRW_COMPILER}) on ${env.SRW_PLATFORM}" + echo "Testing SRW (${env.SRW_COMPILER}) on ${env.SRW_PLATFORM} (using ${env.WORKSPACE})" // If executing for a Pull Request, check for the run_we2e_comprehensive_tests. If set, // override the value of the SRW_WE2E_COMPREHENSIVE_TESTS parameter From 2217d1c9281916a6c0bc187bd6e032703adb28a3 Mon Sep 17 00:00:00 2001 From: Mark Potts <33099090+mark-a-potts@users.noreply.github.com> Date: Tue, 1 Nov 2022 08:24:07 -0400 Subject: [PATCH 15/45] [RELEASE] Fixes for gaea, noaacloud, and miniconda updates (#444) * Update build_cheyenne_gnu.lua remove loading of system python3 * Update build_cheyenne_intel.lua remove loading system python module * Update wflow_cheyenne.lua Load updated miniconda3 and ask to activate regional_workflow enviroment * Update wflow_hera.lua Load an updated miniconda3 and ask to activate regional_workflow environment * Update wflow_jet.lua Update miniconda3 module location and ask to activate regional_workflow * Update wflow_orion.lua Update miniconda3/4.12.0 module location and ask to activate regional_workflow environment * Update load_modules_run_task.sh Run an additional cycle of "conda deactivate" and "conda activate regional_workflow". It ensures that _python3_ binary path from the *regional_workflow* environment becomes prepended to the search $PATH, and is found first, before the _python3_ from miniconda3/4.12.0 from the *base* environment. * Update wflow_cheyenne.lua "conda activate regional_workfow" * Update and rename conda_regional_workflow.lua to miniconda_regional_workflow.lua use new miniconda3/4.12.0 with regional_workflow environment * Update make_grid.local.lua * Update get_extrn_ics.local.lua * Update get_extrn_lbcs.local.lua * Update make_ics.local.lua * Update make_lbcs.local.lua * Update and rename make_orog.hardcoded.lua to make_orog.local.lua * Update run_fcst.local.lua * Update run_vx.local.lua * Create make_sfc_climo.local.lua * Update miniconda_regional_workflow.lua * Update get_obs.local.lua all the requested packages for the python3 are found in regional_workflow environment * Update miniconda_regional_workflow.lua load updated miniconda3/4.12.0 with regional_workflow environment * Update miniconda_regional_workflow.lua Load an updated miniconda3/4.12.0 with the regional_workflow environment * Enable SCHED_NATIVE_CMD on all systems. * Update build_cheyenne_gnu.lua need to have miniconda3 loaded in build module * Update build_cheyenne_intel.lua need to have miniconda3 loaded in the build module * Update build_gaea_intel.lua need to have miniconda3 loaded in build module * Update build_hera_intel.lua need to have miniconda3 loaded in build module * Update build_jet_intel.lua need to have miniconda3 loaded in the build modulefile * Update build_orion_intel.lua need to have miniconda3 loaded in build modulefile * Update load_modules_wflow.sh conda activate command same across the platforms * Don't export variables for those that use SLURM. * Add some missing task specific modulefiles. * Update miniconda_regional_workflow.lua miniconda3 is now loaded in build__, not in *.local files * Update miniconda_regional_workflow.lua miniconda3 is now loaded in build__, not in *.local files * Update miniconda_regional_workflow.lua miniconda3 is now loaded in build__, not in *.local files * Update miniconda_regional_workflow.lua miniconda3 is now loaded in build__, not in *.local files * Update miniconda_regional_workflow.lua * fixes for noaacloud that work with Daniels pr * removed extra lines * removed commented lines * Removed set -x and some commented lines * put module list back in * removed ldd * removed miniconda from build*.lua files * returned conda load to local files * returned python to cheyenne * unload python module before setting up miniconda * added unload python to miniconda_regional_workflow.lua file * added local files for orion Co-authored-by: Natalie Perlin <68030316+natalie-perlin@users.noreply.github.com> Co-authored-by: Daniel Abdi Co-authored-by: Mark Potts --- modulefiles/build_cheyenne_gnu.lua | 2 +- modulefiles/build_cheyenne_intel.lua | 2 +- modulefiles/build_noaacloud_intel.lua | 12 ++++---- modulefiles/build_orion_intel.lua | 1 - modulefiles/srw_common_spack.lua | 30 +++++++++++++++++++ .../cheyenne/conda_regional_workflow.lua | 3 -- .../tasks/cheyenne/get_extrn_ics.local.lua | 2 +- .../tasks/cheyenne/get_extrn_lbcs.local.lua | 2 +- .../tasks/cheyenne/make_grid.local.lua | 2 +- modulefiles/tasks/cheyenne/make_ics.local.lua | 2 +- .../tasks/cheyenne/make_lbcs.local.lua | 2 +- .../tasks/cheyenne/make_orog.hardcoded.lua | 4 --- .../tasks/cheyenne/make_orog.local.lua | 1 + .../tasks/cheyenne/make_sfc_climo.local.lua | 2 +- .../cheyenne/miniconda_regional_workflow.lua | 5 ++++ modulefiles/tasks/cheyenne/run_fcst.local.lua | 2 +- modulefiles/tasks/cheyenne/run_vx.local.lua | 2 +- .../gaea/miniconda_regional_workflow.lua | 2 +- modulefiles/tasks/hera/get_obs.local.lua | 5 +--- .../hera/miniconda_regional_workflow.lua | 4 +-- .../tasks/jet/miniconda_regional_workflow.lua | 4 +-- .../noaacloud/miniconda_regional_workflow.lua | 5 +--- modulefiles/tasks/orion/make_orog.local.lua | 1 + .../tasks/orion/make_sfc_climo.local.lua | 1 + .../orion/miniconda_regional_workflow.lua | 4 +-- modulefiles/wflow_cheyenne.lua | 6 ++-- modulefiles/wflow_hera.lua | 4 +-- modulefiles/wflow_jet.lua | 4 +-- modulefiles/wflow_noaacloud.lua | 8 ++--- modulefiles/wflow_orion.lua | 4 +-- ush/load_modules_wflow.sh | 10 +++---- 31 files changed, 80 insertions(+), 58 deletions(-) create mode 100644 modulefiles/srw_common_spack.lua delete mode 100644 modulefiles/tasks/cheyenne/conda_regional_workflow.lua delete mode 100644 modulefiles/tasks/cheyenne/make_orog.hardcoded.lua create mode 100644 modulefiles/tasks/cheyenne/make_orog.local.lua create mode 100644 modulefiles/tasks/cheyenne/miniconda_regional_workflow.lua create mode 100644 modulefiles/tasks/orion/make_orog.local.lua create mode 100644 modulefiles/tasks/orion/make_sfc_climo.local.lua diff --git a/modulefiles/build_cheyenne_gnu.lua b/modulefiles/build_cheyenne_gnu.lua index 6f1dc5d75e..705eac625a 100644 --- a/modulefiles/build_cheyenne_gnu.lua +++ b/modulefiles/build_cheyenne_gnu.lua @@ -6,10 +6,10 @@ the CISL machine Cheyenne using GNU whatis([===[Loads libraries needed for building the UFS SRW App on Cheyenne ]===]) load(pathJoin("cmake", os.getenv("cmake_ver") or "3.22.0")) -load(pathJoin("python", os.getenv("python_ver") or "3.7.9")) load(pathJoin("ncarenv", os.getenv("ncarenv_ver") or "1.3")) load(pathJoin("gnu", os.getenv("gnu_ver") or "11.2.0")) load(pathJoin("mpt", os.getenv("mpt_ver") or "2.25")) +load(pathJoin("python", os.getenv("python_ver") or "3.7.9")) setenv("MKLROOT", "/glade/u/apps/opt/intel/2022.1/mkl/latest") load(pathJoin("ncarcompilers", os.getenv("ncarcompilers_ver") or "0.5.0")) unload("netcdf") diff --git a/modulefiles/build_cheyenne_intel.lua b/modulefiles/build_cheyenne_intel.lua index 2c5f2a332f..3f2e8a73b6 100644 --- a/modulefiles/build_cheyenne_intel.lua +++ b/modulefiles/build_cheyenne_intel.lua @@ -6,11 +6,11 @@ the CISL machine Cheyenne using Intel-2022.1 whatis([===[Loads libraries needed for building the UFS SRW App on Cheyenne ]===]) load(pathJoin("cmake", os.getenv("cmake_ver") or "3.22.0")) -load(pathJoin("python", os.getenv("python_ver") or "3.7.9")) load(pathJoin("ncarenv", os.getenv("ncarenv_ver") or "1.3")) load(pathJoin("intel", os.getenv("intel_ver") or "2022.1")) load(pathJoin("mpt", os.getenv("mpt_ver") or "2.25")) load(pathJoin("mkl", os.getenv("mkl_ver") or "2022.1")) +load(pathJoin("python", os.getenv("python_ver") or "3.7.9")) load(pathJoin("ncarcompilers", os.getenv("ncarcompilers_ver") or "0.5.0")) unload("netcdf") diff --git a/modulefiles/build_noaacloud_intel.lua b/modulefiles/build_noaacloud_intel.lua index cb1205a42b..6f99a415cf 100644 --- a/modulefiles/build_noaacloud_intel.lua +++ b/modulefiles/build_noaacloud_intel.lua @@ -5,14 +5,12 @@ the NOAA cloud using Intel-oneapi whatis([===[Loads libraries needed for building the UFS SRW App on NOAA cloud ]===]) -prepend_path("MODULEPATH", "/contrib/spack-stack/apps/srw-app-test/modulefiles/Core") +prepend_path("MODULEPATH", "/contrib/EPIC/spack-stack/envs/srw-develop-intel/install/modulefiles/Core") +prepend_path("MODULEPATH", "/apps/modules/modulefiles") +load("intel/2021.3.0") +load("impi/2021.3.0") load("stack-intel") load("stack-intel-oneapi-mpi") load("cmake/3.22.1") -load("srw_common") -load("esmf/8.2.0") -load("netcdf-c") -load("netcdf-fortran") -load("libpng") -load("jasper") +load("srw_common_spack") diff --git a/modulefiles/build_orion_intel.lua b/modulefiles/build_orion_intel.lua index 92795c6f8c..200b2bbf35 100644 --- a/modulefiles/build_orion_intel.lua +++ b/modulefiles/build_orion_intel.lua @@ -9,7 +9,6 @@ load("contrib") load("noaatools") load(pathJoin("cmake", os.getenv("cmake_ver") or "3.22.1")) -load(pathJoin("python", os.getenv("python_ver") or "3.9.2")) prepend_path("MODULEPATH","/apps/contrib/NCEP/libs/hpc-stack/modulefiles/stack") load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) diff --git a/modulefiles/srw_common_spack.lua b/modulefiles/srw_common_spack.lua new file mode 100644 index 0000000000..8e0a607a9d --- /dev/null +++ b/modulefiles/srw_common_spack.lua @@ -0,0 +1,30 @@ +load("jasper/2.0.25") +load("zlib/1.2.11") +load("libpng/1.6.37") +load("netcdf-c/4.7.4") +load("netcdf-fortran/4.5.4") +load("pio/2.5.3") +load("esmf/8.3.0b09") +load("fms/2022.01") + +load("bufr/11.7.0") +load("bacio/2.4.1") +load("crtm/2.3.0") +load("g2/3.4.5") +load("g2tmpl/1.10.0") +load("ip/3.3.3") +load("sp/2.3.3") +load("w3emc/2.9.2") + +load("gftl-shared/1.5.0") +load("yafyaml/0.5.1") +load("mapl/2.22.0-esmf-8.3.0b09-esmf-8.3.0") + +load("nemsio/2.5.4") +load("sfcio/1.4.1") +load("sigio/2.3.2") +load("w3nco/2.4.1") +load("wrf_io/1.2.0") + +load("ncio/1.1.2") +load("wgrib2/2.0.8") diff --git a/modulefiles/tasks/cheyenne/conda_regional_workflow.lua b/modulefiles/tasks/cheyenne/conda_regional_workflow.lua deleted file mode 100644 index 53ba3f6936..0000000000 --- a/modulefiles/tasks/cheyenne/conda_regional_workflow.lua +++ /dev/null @@ -1,3 +0,0 @@ -unload("python") -load("conda") -setenv("SRW_ENV", "/glade/p/ral/jntp/UFS_SRW_app/conda/regional_workflow") diff --git a/modulefiles/tasks/cheyenne/get_extrn_ics.local.lua b/modulefiles/tasks/cheyenne/get_extrn_ics.local.lua index 494c85136d..d371c08301 100644 --- a/modulefiles/tasks/cheyenne/get_extrn_ics.local.lua +++ b/modulefiles/tasks/cheyenne/get_extrn_ics.local.lua @@ -1 +1 @@ -load("conda_regional_workflow") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/get_extrn_lbcs.local.lua b/modulefiles/tasks/cheyenne/get_extrn_lbcs.local.lua index 494c85136d..d371c08301 100644 --- a/modulefiles/tasks/cheyenne/get_extrn_lbcs.local.lua +++ b/modulefiles/tasks/cheyenne/get_extrn_lbcs.local.lua @@ -1 +1 @@ -load("conda_regional_workflow") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/make_grid.local.lua b/modulefiles/tasks/cheyenne/make_grid.local.lua index 494c85136d..d371c08301 100644 --- a/modulefiles/tasks/cheyenne/make_grid.local.lua +++ b/modulefiles/tasks/cheyenne/make_grid.local.lua @@ -1 +1 @@ -load("conda_regional_workflow") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/make_ics.local.lua b/modulefiles/tasks/cheyenne/make_ics.local.lua index 494c85136d..d371c08301 100644 --- a/modulefiles/tasks/cheyenne/make_ics.local.lua +++ b/modulefiles/tasks/cheyenne/make_ics.local.lua @@ -1 +1 @@ -load("conda_regional_workflow") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/make_lbcs.local.lua b/modulefiles/tasks/cheyenne/make_lbcs.local.lua index 494c85136d..d371c08301 100644 --- a/modulefiles/tasks/cheyenne/make_lbcs.local.lua +++ b/modulefiles/tasks/cheyenne/make_lbcs.local.lua @@ -1 +1 @@ -load("conda_regional_workflow") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/make_orog.hardcoded.lua b/modulefiles/tasks/cheyenne/make_orog.hardcoded.lua deleted file mode 100644 index 2395a81c8e..0000000000 --- a/modulefiles/tasks/cheyenne/make_orog.hardcoded.lua +++ /dev/null @@ -1,4 +0,0 @@ -load("ncarenv/1.3") -load("intel/19.0.2") -load("ncarcompilers/0.5.0") -load("netcdf/4.6.3") diff --git a/modulefiles/tasks/cheyenne/make_orog.local.lua b/modulefiles/tasks/cheyenne/make_orog.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/cheyenne/make_orog.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/make_sfc_climo.local.lua b/modulefiles/tasks/cheyenne/make_sfc_climo.local.lua index 494c85136d..d371c08301 100644 --- a/modulefiles/tasks/cheyenne/make_sfc_climo.local.lua +++ b/modulefiles/tasks/cheyenne/make_sfc_climo.local.lua @@ -1 +1 @@ -load("conda_regional_workflow") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/miniconda_regional_workflow.lua b/modulefiles/tasks/cheyenne/miniconda_regional_workflow.lua new file mode 100644 index 0000000000..2263141a0a --- /dev/null +++ b/modulefiles/tasks/cheyenne/miniconda_regional_workflow.lua @@ -0,0 +1,5 @@ +unload("python") +prepend_path("MODULEPATH","/glade/work/epicufsrt/contrib/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) + +setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/tasks/cheyenne/run_fcst.local.lua b/modulefiles/tasks/cheyenne/run_fcst.local.lua index 494c85136d..d371c08301 100644 --- a/modulefiles/tasks/cheyenne/run_fcst.local.lua +++ b/modulefiles/tasks/cheyenne/run_fcst.local.lua @@ -1 +1 @@ -load("conda_regional_workflow") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/run_vx.local.lua b/modulefiles/tasks/cheyenne/run_vx.local.lua index 494c85136d..d371c08301 100644 --- a/modulefiles/tasks/cheyenne/run_vx.local.lua +++ b/modulefiles/tasks/cheyenne/run_vx.local.lua @@ -1 +1 @@ -load("conda_regional_workflow") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/miniconda_regional_workflow.lua b/modulefiles/tasks/gaea/miniconda_regional_workflow.lua index dd8ec8f7e4..74336ca1cf 100644 --- a/modulefiles/tasks/gaea/miniconda_regional_workflow.lua +++ b/modulefiles/tasks/gaea/miniconda_regional_workflow.lua @@ -1,4 +1,4 @@ -prepend_path("MODULEPATH", "/lustre/f2/dev/role.epic/contrib/modulefiles") +prepend_path("MODULEPATH","/lustre/f2/dev/role.epic/contrib/modulefiles") load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/tasks/hera/get_obs.local.lua b/modulefiles/tasks/hera/get_obs.local.lua index c53d3ff3de..d1afe2451e 100644 --- a/modulefiles/tasks/hera/get_obs.local.lua +++ b/modulefiles/tasks/hera/get_obs.local.lua @@ -1,5 +1,2 @@ load("hpss") -prepend_path("MODULEPATH", "/contrib/miniconda3/modulefiles") -load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12") - -setenv("SRW_ENV", "pygraf") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/miniconda_regional_workflow.lua b/modulefiles/tasks/hera/miniconda_regional_workflow.lua index 0443b7d948..7934169824 100644 --- a/modulefiles/tasks/hera/miniconda_regional_workflow.lua +++ b/modulefiles/tasks/hera/miniconda_regional_workflow.lua @@ -1,4 +1,4 @@ -prepend_path("MODULEPATH", "/contrib/miniconda3/modulefiles") -load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12")) +prepend_path("MODULEPATH","/scratch1/NCEPDEV/nems/role.epic/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/tasks/jet/miniconda_regional_workflow.lua b/modulefiles/tasks/jet/miniconda_regional_workflow.lua index 0443b7d948..ef4f248966 100644 --- a/modulefiles/tasks/jet/miniconda_regional_workflow.lua +++ b/modulefiles/tasks/jet/miniconda_regional_workflow.lua @@ -1,4 +1,4 @@ -prepend_path("MODULEPATH", "/contrib/miniconda3/modulefiles") -load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12")) +prepend_path("MODULEPATH","/mnt/lfs4/HFIP/hfv3gfs/role.epic/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/tasks/noaacloud/miniconda_regional_workflow.lua b/modulefiles/tasks/noaacloud/miniconda_regional_workflow.lua index 74486df795..602d60842f 100644 --- a/modulefiles/tasks/noaacloud/miniconda_regional_workflow.lua +++ b/modulefiles/tasks/noaacloud/miniconda_regional_workflow.lua @@ -1,4 +1 @@ -prepend_path("MODULEPATH", "/contrib/GST/miniconda3/modulefiles") -load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.10.3")) - -setenv("SRW_ENV", "regional_workflow") +prepend_path("PATH", "/contrib/EPIC/miniconda3/4.12.0/envs/regional_workflow/bin") diff --git a/modulefiles/tasks/orion/make_orog.local.lua b/modulefiles/tasks/orion/make_orog.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/make_orog.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/orion/make_sfc_climo.local.lua b/modulefiles/tasks/orion/make_sfc_climo.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/make_sfc_climo.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/orion/miniconda_regional_workflow.lua b/modulefiles/tasks/orion/miniconda_regional_workflow.lua index 22b0f4a5ce..793a8824a9 100644 --- a/modulefiles/tasks/orion/miniconda_regional_workflow.lua +++ b/modulefiles/tasks/orion/miniconda_regional_workflow.lua @@ -1,4 +1,4 @@ -append_path("MODULEPATH", "/apps/contrib/miniconda3-noaa-gsl/modulefiles") -load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "3.8")) +append_path("MODULEPATH","/work/noaa/epic-ps/role-epic-ps/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) setenv("SRW_ENV", "regional_workflow") diff --git a/modulefiles/wflow_cheyenne.lua b/modulefiles/wflow_cheyenne.lua index aa44485679..35b7365d43 100644 --- a/modulefiles/wflow_cheyenne.lua +++ b/modulefiles/wflow_cheyenne.lua @@ -10,11 +10,13 @@ load("ncarenv") append_path("MODULEPATH","/glade/p/ral/jntp/UFS_SRW_app/modules") load("rocoto") -load(pathJoin("conda", os.getenv("conda_ver") or "latest")) +unload("python") +prepend_path("MODULEPATH","/glade/work/epicufsrt/contrib/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) if mode() == "load" then LmodMsgRaw([===[Please do the following to activate conda: - > conda activate /glade/p/ral/jntp/UFS_SRW_app/conda/regional_workflow + > conda activate regional_workflow ]===]) end diff --git a/modulefiles/wflow_hera.lua b/modulefiles/wflow_hera.lua index 58bc83d0c4..efca665dd2 100644 --- a/modulefiles/wflow_hera.lua +++ b/modulefiles/wflow_hera.lua @@ -7,8 +7,8 @@ whatis([===[Loads libraries needed for running the UFS SRW App on Hera ]===]) load("rocoto") -prepend_path("MODULEPATH","/contrib/miniconda3/modulefiles") -load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12")) +prepend_path("MODULEPATH","/scratch1/NCEPDEV/nems/role.epic/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) if mode() == "load" then LmodMsgRaw([===[Please do the following to activate conda: diff --git a/modulefiles/wflow_jet.lua b/modulefiles/wflow_jet.lua index 3c651ae788..be11c223bc 100644 --- a/modulefiles/wflow_jet.lua +++ b/modulefiles/wflow_jet.lua @@ -7,8 +7,8 @@ whatis([===[Loads libraries needed for running the UFS SRW App on Jet ]===]) load("rocoto") -prepend_path("MODULEPATH","/contrib/miniconda3/modulefiles") -load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.5.12")) +prepend_path("MODULEPATH","/mnt/lfs4/HFIP/hfv3gfs/role.epic/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) if mode() == "load" then LmodMsgRaw([===[Please do the following to activate conda: diff --git a/modulefiles/wflow_noaacloud.lua b/modulefiles/wflow_noaacloud.lua index 23746052a0..45444a9eb2 100644 --- a/modulefiles/wflow_noaacloud.lua +++ b/modulefiles/wflow_noaacloud.lua @@ -8,12 +8,12 @@ whatis([===[Loads libraries needed for running the UFS SRW App on NOAA cloud ]== prepend_path("MODULEPATH","/apps/modules/modulefiles") load("rocoto") -prepend_path("MODULEPATH","/contrib/GST/miniconda3/modulefiles") -load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.10.3")) +prepend_path("MODULEPATH","/contrib/EPIC/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) -setenv("PROJ_LIB","/contrib/GST/miniconda/envs/regional_workflow/share/proj") +setenv("PROJ_LIB","/contrib/EPIC/miniconda3/4.12.0/envs/regional_workflow/share/proj") setenv("OPT","/contrib/EPIC/hpc-modules") -append_path("PATH","/contrib/GST/miniconda/envs/regional_workflow/bin") +append_path("PATH","/contrib/EPIC/miniconda3/4.12.0/envs/regional_workflow/bin") if mode() == "load" then LmodMsgRaw([===[Please do the following to activate conda: diff --git a/modulefiles/wflow_orion.lua b/modulefiles/wflow_orion.lua index 29518b70a9..a8edef0089 100644 --- a/modulefiles/wflow_orion.lua +++ b/modulefiles/wflow_orion.lua @@ -8,8 +8,8 @@ whatis([===[Loads libraries needed for running SRW on Orion ]===]) load("contrib") load("rocoto") -append_path("MODULEPATH","/apps/contrib/miniconda3-noaa-gsl/modulefiles") -load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "3.8")) +append_path("MODULEPATH","/work/noaa/epic-ps/role-epic-ps/miniconda3/modulefiles") +load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) if mode() == "load" then LmodMsgRaw([===[Please do the following to activate conda: diff --git a/ush/load_modules_wflow.sh b/ush/load_modules_wflow.sh index 6049805a62..5e7e30e3a7 100755 --- a/ush/load_modules_wflow.sh +++ b/ush/load_modules_wflow.sh @@ -60,13 +60,11 @@ task failed: [[ ${SHELLOPTS} =~ nounset ]] && has_mu=true || has_mu=false $has_mu && set +u -if [[ "${machine}" == 'cheyenne' ]]; then - conda activate /glade/p/ral/jntp/UFS_SRW_app/conda/regional_workflow -else - if [ ! -z $(command -v conda) ]; then - conda activate regional_workflow - fi + +if [ ! -z $(command -v conda) ]; then + conda activate regional_workflow fi + $has_mu && set -u # List loaded modulefiles From 63897f010929405a151885965243247887ac7118 Mon Sep 17 00:00:00 2001 From: Jesse McFarland Date: Fri, 4 Nov 2022 15:44:48 -0400 Subject: [PATCH 16/45] Disable comprehensive tests option in Jenkinsfile (#454) --- .cicd/Jenkinsfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.cicd/Jenkinsfile b/.cicd/Jenkinsfile index 26fb2ed355..b15e8b1962 100644 --- a/.cicd/Jenkinsfile +++ b/.cicd/Jenkinsfile @@ -16,7 +16,8 @@ pipeline { choice(name: 'SRW_PLATFORM_FILTER', choices: ['all', 'cheyenne', 'gaea', 'hera', 'jet', 'orion'], description: 'Specify the platform(s) to use') // Allow job runner to filter based on compiler choice(name: 'SRW_COMPILER_FILTER', choices: ['all', 'gnu', 'intel'], description: 'Specify the compiler(s) to use to build') - booleanParam name: 'SRW_WE2E_COMPREHENSIVE_TESTS', defaultValue: false, description: 'Whether to execute the comprehensive end-to-end tests' + // Uncomment the following line to re-enable comprehensive tests + // booleanParam name: 'SRW_WE2E_COMPREHENSIVE_TESTS', defaultValue: false, description: 'Whether to execute the comprehensive end-to-end tests' } stages { @@ -145,6 +146,11 @@ pipeline { steps { echo "Testing SRW (${env.SRW_COMPILER}) on ${env.SRW_PLATFORM} (using ${env.WORKSPACE})" + // Remove the following line to re-enable comprehensive tests + sh 'SRW_WE2E_COMPREHENSIVE_TESTS=false bash --login "${WORKSPACE}/.cicd/scripts/srw_test.sh"' + + // Uncomment the following block to re-enable comprehensive tests + /* // If executing for a Pull Request, check for the run_we2e_comprehensive_tests. If set, // override the value of the SRW_WE2E_COMPREHENSIVE_TESTS parameter script { @@ -161,6 +167,7 @@ pipeline { sh "SRW_WE2E_COMPREHENSIVE_TESTS=${run_we2e_comprehensive_tests}" + ' bash --login "${WORKSPACE}/.cicd/scripts/srw_test.sh"' } + */ } post { From 474ab7ddcd11f40202f49d8a7c56cefecf78b259 Mon Sep 17 00:00:00 2001 From: danielabdi-noaa <52012304+danielabdi-noaa@users.noreply.github.com> Date: Fri, 4 Nov 2022 18:05:34 -0600 Subject: [PATCH 17/45] Updates to the NCO mode (#443) * Add a move step to binaries for NCO purposes. * Pass COMROOT to setpdy. * Correct path of post dependency on forecat. * Remove DATA_SHARED directory. * Remove symlinks and use unique id for run_fcst instead. * Remove forecast directory after post is done. * Use raw workflow_id * Add templated data paths to wcoss2 that use compath.py. * Remove cron relaunch from config.nco * Undo for_ICS/LBCS stuff in NCO mode. * Remove RESTART symlinking because DATAFCST is accessible to all other tasks. * Undo cyc addition to COMIN. * Update devclean. * Follow symlinks when tarring log files in Jenkins. * Add memory otpion for get_extrn_ics/lbcs. * Optimize fundamental test coverage. * Reduce work load on orion. * Add minimum memory requirement to all serial tasks. * Simplify set_predef_grid_params. * Simplify generate_FV3LAM_wflow. * Simplify link_fix. * Simplify to get rid of export_vars from setup. * Import only necessary variables from environment. * Use `eval echo` or `eval` depending on situation. * Add cyc back to COMIN. * Fix calculate_cost. * Fix gaea test list. * Remove a test case from cheyenne that is taking extremely long. * Reduce memory requirement for serial job to 1G. * Create COMINaws ics/lbcs staging directory. * Also symlink gfs ics/lbcs if on disk and in community mode. * Remove failing tests on orion. * Exclude gaea from --mem specification. * Add a run_vx modulefile for orion. * Add separate fundamental list for cheyenne GNU runs. * Bug fix for wcoss2 GFS version * Load prod_util on wcoss2. * Rename AWSROOT to EXTROOT. * Remove leftover COMINaws. --- .cicd/Jenkinsfile | 2 +- devbuild.sh | 27 +- devclean.sh | 4 +- jobs/JREGIONAL_GET_EXTRN_MDL_FILES | 2 +- jobs/JREGIONAL_RUN_FCST | 2 +- modulefiles/tasks/orion/run_vx.local.lua | 1 + .../tasks/wcoss2/get_extrn_ics.local.lua | 3 +- .../tasks/wcoss2/get_extrn_lbcs.local.lua | 3 +- modulefiles/tasks/wcoss2/get_obs.local.lua | 3 +- modulefiles/tasks/wcoss2/make_grid.local.lua | 3 +- modulefiles/tasks/wcoss2/make_ics.local.lua | 3 +- modulefiles/tasks/wcoss2/make_lbcs.local.lua | 3 +- .../tasks/wcoss2/make_sfc_climo.local.lua | 3 +- .../tasks/wcoss2/python_regional_workflow.lua | 3 + modulefiles/tasks/wcoss2/run_fcst.local.lua | 3 +- modulefiles/tasks/wcoss2/run_vx.local.lua | 3 +- parm/FV3LAM_wflow.xml | 110 +++++- scripts/exregional_get_extrn_mdl_files.sh | 17 +- scripts/exregional_make_ics.sh | 12 +- scripts/exregional_make_lbcs.sh | 12 +- scripts/exregional_run_fcst.sh | 43 --- scripts/exregional_run_post.sh | 15 +- .../WE2E/machine_suites/fundamental.cheyenne | 9 + .../machine_suites/fundamental.cheyenne.gnu | 6 + tests/WE2E/machine_suites/fundamental.gaea | 9 + .../WE2E/machine_suites/fundamental.hera.nco | 10 + tests/WE2E/machine_suites/fundamental.jet | 10 + tests/WE2E/machine_suites/fundamental.orion | 5 + tests/WE2E/run_WE2E_tests.sh | 20 +- ush/calculate_cost.py | 42 ++- ush/config.nco.yaml | 2 - ush/config_defaults.yaml | 25 ++ ush/generate_FV3LAM_wflow.py | 322 +++--------------- ush/get_crontab_contents.py | 6 +- ush/job_preamble.sh | 52 ++- ush/link_fix.py | 52 +-- ush/load_modules_run_task.sh | 7 +- ush/machine/wcoss2.yaml | 7 + ush/retrieve_data.py | 14 +- ush/set_gridparams_GFDLgrid.py | 6 +- ush/set_ozone_param.py | 4 - ush/set_predef_grid_params.py | 90 +++-- ush/set_thompson_mp_fix_files.py | 19 +- ush/setup.py | 151 ++++---- versions/build.ver.wcoss2 | 1 - versions/run.ver.wcoss2 | 7 + 46 files changed, 557 insertions(+), 596 deletions(-) create mode 100644 modulefiles/tasks/orion/run_vx.local.lua create mode 100644 modulefiles/tasks/wcoss2/python_regional_workflow.lua create mode 100644 tests/WE2E/machine_suites/fundamental.cheyenne create mode 100644 tests/WE2E/machine_suites/fundamental.cheyenne.gnu create mode 100644 tests/WE2E/machine_suites/fundamental.gaea create mode 100644 tests/WE2E/machine_suites/fundamental.hera.nco create mode 100644 tests/WE2E/machine_suites/fundamental.jet create mode 100644 tests/WE2E/machine_suites/fundamental.orion diff --git a/.cicd/Jenkinsfile b/.cicd/Jenkinsfile index b15e8b1962..75a9e96308 100644 --- a/.cicd/Jenkinsfile +++ b/.cicd/Jenkinsfile @@ -173,7 +173,7 @@ pipeline { post { always { // Archive the test log files - sh 'cd "${SRW_WE2E_EXPERIMENT_BASE_DIR}" && tar --create --gzip --verbose --file "${WORKSPACE}/we2e_test_logs-${SRW_PLATFORM}-${SRW_COMPILER}.tgz" */log.generate_FV3LAM_wflow */log.launch_FV3LAM_wflow */log/*' + sh 'cd "${SRW_WE2E_EXPERIMENT_BASE_DIR}" && tar --create --gzip --verbose --dereference --file "${WORKSPACE}/we2e_test_logs-${SRW_PLATFORM}-${SRW_COMPILER}.tgz" */log.generate_FV3LAM_wflow */log.launch_FV3LAM_wflow */log/*' // Remove the data sets from the experiments directory to conserve disk space sh 'find "${SRW_WE2E_EXPERIMENT_BASE_DIR}" -regextype posix-extended -regex "^.*(orog|[0-9]{10})$" -type d | xargs rm -rf' s3Upload consoleLogLevel: 'INFO', dontSetBuildResultOnFailure: false, dontWaitForConcurrentBuildCompletion: false, entries: [[bucket: 'woc-epic-jenkins-artifacts', excludedFile: '', flatten: false, gzipFiles: false, keepForever: false, managedArtifacts: true, noUploadOnFailure: false, selectedRegion: 'us-east-1', showDirectlyInBrowser: false, sourceFile: 'we2e_test_results-*-*.txt', storageClass: 'STANDARD', uploadFromSlave: false, useServerSideEncryption: false], [bucket: 'woc-epic-jenkins-artifacts', excludedFile: '', flatten: false, gzipFiles: false, keepForever: false, managedArtifacts: true, noUploadOnFailure: false, selectedRegion: 'us-east-1', showDirectlyInBrowser: false, sourceFile: 'we2e_test_logs-*-*.tgz', storageClass: 'STANDARD', uploadFromSlave: false, useServerSideEncryption: false]], pluginFailureResultConstraint: 'FAILURE', profileName: 'main', userMetadata: [] diff --git a/devbuild.sh b/devbuild.sh index 218a0eeb81..d31ed0eca7 100755 --- a/devbuild.sh +++ b/devbuild.sh @@ -33,6 +33,8 @@ OPTIONS does a "make clean" --build does a "make" (build only) + --move + move binaries to final location. --build-dir=BUILD_DIR build directory --install-dir=INSTALL_DIR @@ -125,6 +127,7 @@ BUILD_RRFS_UTILS="off" # Make options CLEAN=false BUILD=false +MOVE=false USE_SUB_MODULES=false #change default to true later # process required arguments @@ -155,6 +158,7 @@ while :; do --continue=?*|--continue=) usage_error "$1 argument ignored." ;; --clean) CLEAN=true ;; --build) BUILD=true ;; + --move) MOVE=true ;; --build-dir=?*) BUILD_DIR=${1#*=} ;; --build-dir|--build-dir=) usage_error "$1 requires argument." ;; --install-dir=?*) INSTALL_DIR=${1#*=} ;; @@ -398,18 +402,31 @@ module list mkdir -p ${BUILD_DIR} cd ${BUILD_DIR} -printf "... Generate CMAKE configuration ...\n" -cmake ${SRW_DIR} ${CMAKE_SETTINGS} 2>&1 | tee log.cmake - if [ "${CLEAN}" = true ]; then - printf "... Clean executables ...\n" - make ${MAKE_SETTINGS} clean 2>&1 | tee log.make + if [ -f $PWD/Makefile ]; then + printf "... Clean executables ...\n" + make ${MAKE_SETTINGS} clean 2>&1 | tee log.make + fi elif [ "${BUILD}" = true ]; then + printf "... Generate CMAKE configuration ...\n" + cmake ${SRW_DIR} ${CMAKE_SETTINGS} 2>&1 | tee log.cmake + printf "... Compile executables ...\n" make ${MAKE_SETTINGS} build 2>&1 | tee log.make else + printf "... Generate CMAKE configuration ...\n" + cmake ${SRW_DIR} ${CMAKE_SETTINGS} 2>&1 | tee log.cmake + printf "... Compile and install executables ...\n" make ${MAKE_SETTINGS} install 2>&1 | tee log.make + + if [ "${MOVE}" = true ]; then + if [[ ! ${SRW_DIR} -ef ${INSTALL_DIR} ]]; then + printf "... Moving executables to final locations ...\n" + mkdir -p ${SRW_DIR}/${BIN_DIR} + mv ${INSTALL_DIR}/${BIN_DIR}/* ${SRW_DIR}/${BIN_DIR} + fi + fi fi exit 0 diff --git a/devclean.sh b/devclean.sh index d3c316514e..36fbc36898 100755 --- a/devclean.sh +++ b/devclean.sh @@ -119,9 +119,11 @@ elif [ "${CLEAN}" = true ]; then printf '%s\n' " from the installation directory = ${INSTALL_DIR} " [[ -d "${BUILD_DIR}" ]] && rm -rf ${BUILD_DIR} && printf '%s\n' "rm -rf ${BUILD_DIR}" [[ -d "${INSTALL_DIR}/${BIN_DIR}" ]] && ( rm -rf ${INSTALL_DIR}/${BIN_DIR} && printf '%s\n' "rm -rf ${INSTALL_DIR}/${BIN_DIR}" ) - [[ -d "${INSTALL_DIR}/lib" ]] && ( rm -rf ${INSTALL_DIR}/share && printf '%s\n' "rm -rf ${INSTALL_DIR}/share" ) + [[ -d "${SRW_DIR}/${BIN_DIR}" ]] && ( rm -rf ${SRW_DIR}/${BIN_DIR} && printf '%s\n' "rm -rf ${SRW_DIR}/${BIN_DIR}" ) + [[ -d "${INSTALL_DIR}/share" ]] && ( rm -rf ${INSTALL_DIR}/share && printf '%s\n' "rm -rf ${INSTALL_DIR}/share" ) [[ -d "${INSTALL_DIR}/include" ]] && ( rm -rf ${INSTALL_DIR}/include && printf '%s\n' "rm -rf ${INSTALL_DIR}/include" ) [[ -d "${INSTALL_DIR}/lib" ]] && rm -rf ${INSTALL_DIR}/lib && printf '%s\n' "rm -rf ${INSTALL_DIR}/lib" + [[ -d "${INSTALL_DIR}/lib64" ]] && rm -rf ${INSTALL_DIR}/lib && printf '%s\n' "rm -rf ${INSTALL_DIR}/lib64" [[ -d "${SRW_DIR}/manage_externals/manic" ]] && rm -f ${SRW_DIR}/manage_externals/manic/*.pyc && printf '%s\n' "rm -f ${SRW_DIR}/manage_externals/manic/*.pyc" echo " " fi diff --git a/jobs/JREGIONAL_GET_EXTRN_MDL_FILES b/jobs/JREGIONAL_GET_EXTRN_MDL_FILES index 8975a3e678..1c07956433 100755 --- a/jobs/JREGIONAL_GET_EXTRN_MDL_FILES +++ b/jobs/JREGIONAL_GET_EXTRN_MDL_FILES @@ -209,7 +209,7 @@ esac #----------------------------------------------------------------------- # if [ $RUN_ENVIR = "nco" ]; then - export EXTRN_MDL_STAGING_DIR="${COMIN}/for_${ICS_OR_LBCS}" + export EXTRN_MDL_STAGING_DIR="${COMINext}" mkdir_vrfy -p "${EXTRN_MDL_STAGING_DIR}" else export EXTRN_MDL_STAGING_DIR="${COMIN}/${EXTRN_MDL_NAME}/for_${ICS_OR_LBCS}" diff --git a/jobs/JREGIONAL_RUN_FCST b/jobs/JREGIONAL_RUN_FCST index ab56af59a5..58a255757c 100755 --- a/jobs/JREGIONAL_RUN_FCST +++ b/jobs/JREGIONAL_RUN_FCST @@ -19,7 +19,7 @@ # . ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh -. $USHdir/job_preamble.sh +. $USHdir/job_preamble.sh "TRUE" # #----------------------------------------------------------------------- # diff --git a/modulefiles/tasks/orion/run_vx.local.lua b/modulefiles/tasks/orion/run_vx.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/run_vx.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/get_extrn_ics.local.lua b/modulefiles/tasks/wcoss2/get_extrn_ics.local.lua index 16559474cd..3370fa018b 100644 --- a/modulefiles/tasks/wcoss2/get_extrn_ics.local.lua +++ b/modulefiles/tasks/wcoss2/get_extrn_ics.local.lua @@ -1,2 +1 @@ -load(pathJoin("intel", os.getenv("intel_ver"))) -load(pathJoin("python", os.getenv("python_ver"))) +load("python_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/get_extrn_lbcs.local.lua b/modulefiles/tasks/wcoss2/get_extrn_lbcs.local.lua index 16559474cd..3370fa018b 100644 --- a/modulefiles/tasks/wcoss2/get_extrn_lbcs.local.lua +++ b/modulefiles/tasks/wcoss2/get_extrn_lbcs.local.lua @@ -1,2 +1 @@ -load(pathJoin("intel", os.getenv("intel_ver"))) -load(pathJoin("python", os.getenv("python_ver"))) +load("python_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/get_obs.local.lua b/modulefiles/tasks/wcoss2/get_obs.local.lua index 16559474cd..3370fa018b 100644 --- a/modulefiles/tasks/wcoss2/get_obs.local.lua +++ b/modulefiles/tasks/wcoss2/get_obs.local.lua @@ -1,2 +1 @@ -load(pathJoin("intel", os.getenv("intel_ver"))) -load(pathJoin("python", os.getenv("python_ver"))) +load("python_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/make_grid.local.lua b/modulefiles/tasks/wcoss2/make_grid.local.lua index 16559474cd..3370fa018b 100644 --- a/modulefiles/tasks/wcoss2/make_grid.local.lua +++ b/modulefiles/tasks/wcoss2/make_grid.local.lua @@ -1,2 +1 @@ -load(pathJoin("intel", os.getenv("intel_ver"))) -load(pathJoin("python", os.getenv("python_ver"))) +load("python_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/make_ics.local.lua b/modulefiles/tasks/wcoss2/make_ics.local.lua index 16559474cd..3370fa018b 100644 --- a/modulefiles/tasks/wcoss2/make_ics.local.lua +++ b/modulefiles/tasks/wcoss2/make_ics.local.lua @@ -1,2 +1 @@ -load(pathJoin("intel", os.getenv("intel_ver"))) -load(pathJoin("python", os.getenv("python_ver"))) +load("python_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/make_lbcs.local.lua b/modulefiles/tasks/wcoss2/make_lbcs.local.lua index 16559474cd..3370fa018b 100644 --- a/modulefiles/tasks/wcoss2/make_lbcs.local.lua +++ b/modulefiles/tasks/wcoss2/make_lbcs.local.lua @@ -1,2 +1 @@ -load(pathJoin("intel", os.getenv("intel_ver"))) -load(pathJoin("python", os.getenv("python_ver"))) +load("python_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/make_sfc_climo.local.lua b/modulefiles/tasks/wcoss2/make_sfc_climo.local.lua index 16559474cd..3370fa018b 100644 --- a/modulefiles/tasks/wcoss2/make_sfc_climo.local.lua +++ b/modulefiles/tasks/wcoss2/make_sfc_climo.local.lua @@ -1,2 +1 @@ -load(pathJoin("intel", os.getenv("intel_ver"))) -load(pathJoin("python", os.getenv("python_ver"))) +load("python_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/python_regional_workflow.lua b/modulefiles/tasks/wcoss2/python_regional_workflow.lua new file mode 100644 index 0000000000..519f1cdf4a --- /dev/null +++ b/modulefiles/tasks/wcoss2/python_regional_workflow.lua @@ -0,0 +1,3 @@ +load(pathJoin("intel", os.getenv("intel_ver"))) +load(pathJoin("python", os.getenv("python_ver"))) +load(pathJoin("prod_util", os.getenv("prod_util_ver"))) diff --git a/modulefiles/tasks/wcoss2/run_fcst.local.lua b/modulefiles/tasks/wcoss2/run_fcst.local.lua index 16559474cd..3370fa018b 100644 --- a/modulefiles/tasks/wcoss2/run_fcst.local.lua +++ b/modulefiles/tasks/wcoss2/run_fcst.local.lua @@ -1,2 +1 @@ -load(pathJoin("intel", os.getenv("intel_ver"))) -load(pathJoin("python", os.getenv("python_ver"))) +load("python_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/run_vx.local.lua b/modulefiles/tasks/wcoss2/run_vx.local.lua index 16559474cd..3370fa018b 100644 --- a/modulefiles/tasks/wcoss2/run_vx.local.lua +++ b/modulefiles/tasks/wcoss2/run_vx.local.lua @@ -1,2 +1 @@ -load(pathJoin("intel", os.getenv("intel_ver"))) -load(pathJoin("python", os.getenv("python_ver"))) +load("python_regional_workflow") diff --git a/parm/FV3LAM_wflow.xml b/parm/FV3LAM_wflow.xml index e1696ae5a8..622e0b42d6 100644 --- a/parm/FV3LAM_wflow.xml +++ b/parm/FV3LAM_wflow.xml @@ -90,25 +90,26 @@ specifies the number of processes per node being used (the PPN_... entities). - - + + + {%- if run_envir == "nco" %} {%- if do_ensemble %} -{{ run }}.@Y@m@d/{{ net }}.t@Hz.{{ ensmem_indx_name }}#{{ ensmem_indx_name }}#.dyn"> -{{ run }}.@Y@m@d/{{ net }}.t@Hz.{{ ensmem_indx_name }}#{{ ensmem_indx_name }}#.phy"> +@Y@m@d@H/dyn"> +@Y@m@d@H/phy"> {%- else %} -{{ run }}.@Y@m@d/{{ net }}.t@Hz.dyn"> -{{ run }}.@Y@m@d/{{ net }}.t@Hz.phy"> +@Y@m@d@H/dyn"> +@Y@m@d@H/phy"> {%- endif %} {%- else %} -@Y@m@d@H{{ slash_ensmem_subdir }}/dyn"> -@Y@m@d@H{{ slash_ensmem_subdir }}/phy"> +@Y@m@d@H{{ slash_ensmem_subdir }}/dyn"> +@Y@m@d@H{{ slash_ensmem_subdir }}/phy"> {%- endif %} {%- if run_envir == "nco" %} @@ -301,6 +302,9 @@ MODULES_RUN_TASK_FP script. &RSRV_HPSS; &LOAD_MODULES_RUN_TASK_FP; "&GET_EXTRN_ICS_TN;" "&JOBSdir;/JREGIONAL_GET_EXTRN_MDL_FILES" {{ nnodes_get_extrn_ics }}:ppn={{ ppn_get_extrn_ics }} + {%- if machine not in ["GAEA"] %} + {{ mem_get_extrn_ics }} + {%- endif %} {{ wtime_get_extrn_ics }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -326,6 +330,9 @@ MODULES_RUN_TASK_FP script. &RSRV_HPSS; &LOAD_MODULES_RUN_TASK_FP; "&GET_EXTRN_LBCS_TN;" "&JOBSdir;/JREGIONAL_GET_EXTRN_MDL_FILES" {{ nnodes_get_extrn_lbcs }}:ppn={{ ppn_get_extrn_lbcs }} + {%- if machine not in ["GAEA"] %} + {{ mem_get_extrn_lbcs }} + {%- endif %} {{ wtime_get_extrn_lbcs }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -745,6 +752,9 @@ the tag to be identical to the ones above for other output times. &RSRV_HPSS; &LOAD_MODULES_RUN_TASK_FP; "&GET_OBS;" "&JOBSdir;/JREGIONAL_GET_OBS_CCPA" {{ nnodes_get_obs_ccpa }}:ppn={{ ppn_get_obs_ccpa }} + {%- if machine not in ["GAEA"] %} + {{ mem_get_obs_ccpa }} + {%- endif %} {{ wtime_get_obs_ccpa }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -773,6 +783,9 @@ the tag to be identical to the ones above for other output times. &RSRV_HPSS; &LOAD_MODULES_RUN_TASK_FP; "&GET_OBS;" "&JOBSdir;/JREGIONAL_GET_OBS_MRMS" {{ nnodes_get_obs_mrms }}:ppn={{ ppn_get_obs_mrms }} + {%- if machine not in ["GAEA"] %} + {{ mem_get_obs_mrms }} + {%- endif %} {{ wtime_get_obs_mrms }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -802,6 +815,9 @@ the tag to be identical to the ones above for other output times. &RSRV_HPSS; &LOAD_MODULES_RUN_TASK_FP; "&GET_OBS;" "&JOBSdir;/JREGIONAL_GET_OBS_NDAS" {{ nnodes_get_obs_ndas }}:ppn={{ ppn_get_obs_ndas }} + {%- if machine not in ["GAEA"] %} + {{ mem_get_obs_ndas }} + {%- endif %} {{ wtime_get_obs_ndas }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -829,6 +845,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_GRIDSTAT" {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_gridstat }} + {%- endif %} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -881,6 +900,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_GRIDSTAT" {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_gridstat }} + {%- endif %} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -932,6 +954,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_GRIDSTAT" {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_gridstat }} + {%- endif %} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -983,6 +1008,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_GRIDSTAT" {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_gridstat }} + {%- endif %} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1020,6 +1048,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_GRIDSTAT" {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_gridstat }} + {%- endif %} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1057,6 +1088,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_GRIDSTAT" {{ nnodes_vx_gridstat }}:ppn={{ ppn_vx_gridstat }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_gridstat }} + {%- endif %} {{ wtime_vx_gridstat }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1094,6 +1128,9 @@ the tag to be identical to the ones above for other output times. &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_POINTSTAT" {{ nnodes_vx_pointstat }}:ppn={{ ppn_vx_pointstat }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_pointstat }} + {%- endif %} {{ wtime_vx_pointstat }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1148,6 +1185,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID" {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid }} + {%- endif %} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1181,6 +1221,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID" {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid }} + {%- endif %} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1214,6 +1257,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID" {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid }} + {%- endif %} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1247,6 +1293,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID" {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid }} + {%- endif %} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1279,6 +1328,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID" {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid }} + {%- endif %} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1310,6 +1362,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID" {{ nnodes_vx_ensgrid }}:ppn={{ ppn_vx_ensgrid }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid }} + {%- endif %} {{ wtime_vx_ensgrid }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1340,6 +1395,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_MEAN" {{ nnodes_vx_ensgrid_mean }}:ppn={{ ppn_vx_ensgrid_mean }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_mean }} + {%- endif %} {{ wtime_vx_ensgrid_mean }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1372,6 +1430,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_PROB" {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_prob }} + {%- endif %} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1404,6 +1465,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_MEAN" {{ nnodes_vx_ensgrid_mean }}:ppn={{ ppn_vx_ensgrid_mean }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_mean }} + {%- endif %} {{ wtime_vx_ensgrid_mean }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1436,6 +1500,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_PROB" {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_prob }} + {%- endif %} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1469,6 +1536,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_MEAN" {{ nnodes_vx_ensgrid_mean }}:ppn={{ ppn_vx_ensgrid_mean }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_mean }} + {%- endif %} {{ wtime_vx_ensgrid_mean }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1501,6 +1571,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_PROB" {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_prob }} + {%- endif %} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1534,6 +1607,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_MEAN" {{ nnodes_vx_ensgrid_mean }}:ppn={{ ppn_vx_ensgrid_mean }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_mean }} + {%- endif %} {{ wtime_vx_ensgrid_mean }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1566,6 +1642,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_PROB" {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_prob }} + {%- endif %} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1598,6 +1677,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_PROB" {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_prob }} + {%- endif %} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1629,6 +1711,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSGRID_PROB" {{ nnodes_vx_ensgrid_prob }}:ppn={{ ppn_vx_ensgrid_prob }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_ensgrid_prob }} + {%- endif %} {{ wtime_vx_ensgrid_prob }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1661,6 +1746,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSPOINT" {{ nnodes_vx_enspoint }}:ppn={{ ppn_vx_enspoint }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_enspoint }} + {%- endif %} {{ wtime_vx_enspoint }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1690,6 +1778,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSPOINT_MEAN" {{ nnodes_vx_enspoint_mean }}:ppn={{ ppn_vx_enspoint_mean }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_enspoint_mean }} + {%- endif %} {{ wtime_vx_enspoint_mean }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; @@ -1719,6 +1810,9 @@ the tag to be identical to the ones above for other output times. &RSRV_DEFAULT; &LOAD_MODULES_RUN_TASK_FP; "&VX_TN;" "&JOBSdir;/JREGIONAL_RUN_VX_ENSPOINT_PROB" {{ nnodes_vx_enspoint_prob }}:ppn={{ ppn_vx_enspoint_prob }} + {%- if machine not in ["GAEA"] %} + {{ mem_vx_enspoint_prob }} + {%- endif %} {{ wtime_vx_enspoint_prob }} &NCORES_PER_NODE; &SCHED_NATIVE_CMD; diff --git a/scripts/exregional_get_extrn_mdl_files.sh b/scripts/exregional_get_extrn_mdl_files.sh index 6032123020..824d2b4fdc 100755 --- a/scripts/exregional_get_extrn_mdl_files.sh +++ b/scripts/exregional_get_extrn_mdl_files.sh @@ -90,8 +90,19 @@ mm=${yyyymmddhh:4:2} dd=${yyyymmddhh:6:2} hh=${yyyymmddhh:8:2} - +# +#----------------------------------------------------------------------- +# +# if path has space in between it is a command, otherwise +# treat it as a template path +# +#----------------------------------------------------------------------- +# input_file_path=$(eval echo ${input_file_path}) +if [[ $input_file_path = *" "* ]]; then + input_file_path=$(eval ${input_file_path}) +fi + # #----------------------------------------------------------------------- # @@ -118,6 +129,10 @@ if [ -n "${input_file_path:-}" ] ; then --input_file_path ${input_file_path}" fi +if [ $SYMLINK_FIX_FILES = "TRUE" ]; then + additional_flags="$additional_flags \ + --symlink" +fi # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_make_ics.sh b/scripts/exregional_make_ics.sh index e8f84f4136..9714f36021 100755 --- a/scripts/exregional_make_ics.sh +++ b/scripts/exregional_make_ics.sh @@ -86,7 +86,7 @@ fi #----------------------------------------------------------------------- # if [ $RUN_ENVIR = "nco" ]; then - extrn_mdl_staging_dir="${COMIN}/for_ICS" + extrn_mdl_staging_dir="${COMINext}" extrn_mdl_var_defns_fp="${extrn_mdl_staging_dir}/${NET}.${cycle}.${EXTRN_MDL_NAME_ICS}.ICS.${EXTRN_MDL_VAR_DEFNS_FN}.sh" else extrn_mdl_staging_dir="${COMIN}/${EXTRN_MDL_NAME_ICS}/for_ICS" @@ -592,16 +592,6 @@ mv_vrfy gfs.bndy.nc ${INPUT_DATA}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile${TI # #----------------------------------------------------------------------- # -# Clean up the external model data files in NCO mode -# -#----------------------------------------------------------------------- -# -if [ "${RUN_ENVIR}" = "nco" ]; then - rm_vrfy -rf ${extrn_mdl_staging_dir} -fi -# -#----------------------------------------------------------------------- -# # Process FVCOM Data # #----------------------------------------------------------------------- diff --git a/scripts/exregional_make_lbcs.sh b/scripts/exregional_make_lbcs.sh index 123350e886..2c0c59ef19 100755 --- a/scripts/exregional_make_lbcs.sh +++ b/scripts/exregional_make_lbcs.sh @@ -84,7 +84,7 @@ fi #----------------------------------------------------------------------- # if [ $RUN_ENVIR = "nco" ]; then - extrn_mdl_staging_dir="${COMIN}/for_LBCS" + extrn_mdl_staging_dir="${COMINext}" extrn_mdl_var_defns_fp="${extrn_mdl_staging_dir}/${NET}.${cycle}.${EXTRN_MDL_NAME_LBCS}.LBCS.${EXTRN_MDL_VAR_DEFNS_FN}.sh" else extrn_mdl_staging_dir="${COMIN}/${EXTRN_MDL_NAME_LBCS}/for_LBCS" @@ -499,16 +499,6 @@ done # #----------------------------------------------------------------------- # -# Clean up the external model data files in NCO mode -# -#----------------------------------------------------------------------- -# -if [ "${RUN_ENVIR}" = "nco" ]; then - rm_vrfy -rf ${extrn_mdl_staging_dir} -fi -# -#----------------------------------------------------------------------- -# # Print message indicating successful completion of script. # #----------------------------------------------------------------------- diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 2bf946a9f6..67bf7b18c3 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -471,34 +471,6 @@ Call to function to create a diag table file for the current cycle's # #----------------------------------------------------------------------- # -# Pre-generate symlinks to forecast output in DATA pointing to DATA_SHARED -# -#----------------------------------------------------------------------- -# -if [ "${RUN_ENVIR}" = "nco" ]; then - - # first set suffix for minutes and seconds of forecast time - mnts_secs_str="" - if [ "${SUB_HOURLY_POST}" = "TRUE" ]; then - if [ ${fhr}${fmn} = "00000" ]; then - mnts_secs_str=":"$( $DATE_UTIL --utc --date "${yyyymmdd} ${hh} UTC + ${dt_atmos} seconds" "+%M:%S" ) - else - mnts_secs_str=":${fmn}:00" - fi - fi - - # create the symlinks - for fhr in $(seq -f "%03g" 0 ${FCST_LEN_HRS}); do - ln_vrfy -sf "${DATA_SHARED}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr}${mnts_secs_str}.nc" "dynf${fhr}${mnts_secs_str}.nc" - ln_vrfy -sf "${DATA_SHARED}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr}${mnts_secs_str}.nc" "phyf${fhr}${mnts_secs_str}.nc" - done - - # create an intermediate symlink to RESTART - ln_vrfy -sf "${DATA}/RESTART" "${COMIN}/RESTART" -fi -# -#----------------------------------------------------------------------- -# # Run the FV3-LAM model. Note that we have to launch the forecast from # the current cycle's directory because the FV3 executable will look for # input files in the current directory. Since those files have been @@ -515,21 +487,6 @@ POST_STEP # #----------------------------------------------------------------------- # -# Move RESTART directory to COMIN and create symlink in DATA only for -# NCO mode and when it is not empty. -# -#----------------------------------------------------------------------- -# -if [ "${RUN_ENVIR}" = "nco" ]; then - rm_vrfy -rf "${COMIN}/RESTART" - if [ "$(ls -A RESTART)" ]; then - mv_vrfy RESTART ${COMIN} - ln_vrfy -sf ${COMIN}/RESTART ${DATA}/RESTART - fi -fi -# -#----------------------------------------------------------------------- -# # If doing inline post, create the directory in which the post-processing # output will be stored (postprd_dir). # diff --git a/scripts/exregional_run_post.sh b/scripts/exregional_run_post.sh index 2c18754c09..1a51dedf0f 100755 --- a/scripts/exregional_run_post.sh +++ b/scripts/exregional_run_post.sh @@ -166,13 +166,13 @@ fi # # Set the names of the forecast model's write-component output files. # -if [ "${RUN_ENVIR}" != "nco" ]; then - dyn_file="${DATA}/dynf${fhr}${mnts_secs_str}.nc" - phy_file="${DATA}/phyf${fhr}${mnts_secs_str}.nc" +if [ "${RUN_ENVIR}" = "nco" ]; then + DATAFCST=$DATAROOT/run_fcst${dot_ensmem/./_}.${share_pid} else - dyn_file="${DATA_SHARED}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr}${mnts_secs_str}.nc" - phy_file="${DATA_SHARED}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr}${mnts_secs_str}.nc" + DATAFCST=$DATA fi +dyn_file="${DATAFCST}/dynf${fhr}${mnts_secs_str}.nc" +phy_file="${DATAFCST}/phyf${fhr}${mnts_secs_str}.nc" # # Set parameters that specify the actual time (not forecast time) of the # output. @@ -291,6 +291,11 @@ for fid in "${fids[@]}"; do done rm_vrfy -rf ${DATA_FHR} + +# Delete the forecast directory +if [ $RUN_ENVIR = "nco" ] && [ $KEEPDATA = "FALSE" ]; then + rm -rf $DATAFCST +fi # #----------------------------------------------------------------------- # diff --git a/tests/WE2E/machine_suites/fundamental.cheyenne b/tests/WE2E/machine_suites/fundamental.cheyenne new file mode 100644 index 0000000000..9158a03326 --- /dev/null +++ b/tests/WE2E/machine_suites/fundamental.cheyenne @@ -0,0 +1,9 @@ +grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_HRRR +grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_HRRR +specify_RESTART_INTERVAL +specify_template_filenames +grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_HRRR +grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta +pregen_grid_orog_sfc_climo +custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_FALSE +custom_GFDLgrid__GFDLgrid_USE_NUM_CELLS_IN_FILENAMES_eq_TRUE diff --git a/tests/WE2E/machine_suites/fundamental.cheyenne.gnu b/tests/WE2E/machine_suites/fundamental.cheyenne.gnu new file mode 100644 index 0000000000..f269650e98 --- /dev/null +++ b/tests/WE2E/machine_suites/fundamental.cheyenne.gnu @@ -0,0 +1,6 @@ +MET_verification +grid_CONUS_25km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16 +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta +grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16 +grid_RRFS_NA_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta diff --git a/tests/WE2E/machine_suites/fundamental.gaea b/tests/WE2E/machine_suites/fundamental.gaea new file mode 100644 index 0000000000..2c079bb14b --- /dev/null +++ b/tests/WE2E/machine_suites/fundamental.gaea @@ -0,0 +1,9 @@ +grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta +grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta +grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2 +grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16 +grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR +grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_HRRR +grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_RRFS_v1beta +nco_ensemble +grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta diff --git a/tests/WE2E/machine_suites/fundamental.hera.nco b/tests/WE2E/machine_suites/fundamental.hera.nco new file mode 100644 index 0000000000..6493f676ba --- /dev/null +++ b/tests/WE2E/machine_suites/fundamental.hera.nco @@ -0,0 +1,10 @@ +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2 +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16 +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_RAP_suite_HRRR +grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v15p2 +grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR +grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp_regional +MET_ensemble_verification +community_ensemble_2mems_stoch +pregen_grid_orog_sfc_climo diff --git a/tests/WE2E/machine_suites/fundamental.jet b/tests/WE2E/machine_suites/fundamental.jet new file mode 100644 index 0000000000..fc81810364 --- /dev/null +++ b/tests/WE2E/machine_suites/fundamental.jet @@ -0,0 +1,10 @@ +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2 +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16 +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_RAP_suite_HRRR +grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v15p2 +nco_grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR +custom_GFDLgrid +custom_ESGgrid +specify_DOT_OR_USCORE +specify_DT_ATMOS_LAYOUT_XY_BLOCKSIZE +specify_RESTART_INTERVAL diff --git a/tests/WE2E/machine_suites/fundamental.orion b/tests/WE2E/machine_suites/fundamental.orion new file mode 100644 index 0000000000..5cf7b73c16 --- /dev/null +++ b/tests/WE2E/machine_suites/fundamental.orion @@ -0,0 +1,5 @@ +grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_RRFS_v1beta +grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta +community_ensemble_008mems +deactivate_tasks +inline_post diff --git a/tests/WE2E/run_WE2E_tests.sh b/tests/WE2E/run_WE2E_tests.sh index 53edf57fde..6c8680b3ec 100755 --- a/tests/WE2E/run_WE2E_tests.sh +++ b/tests/WE2E/run_WE2E_tests.sh @@ -430,10 +430,24 @@ elif [ -n "${tests_file}" ] || [ -n "${test_type}" ] ; then # one managed in the repo if [ -n "${test_type}" ] ; then - # Check for a pre-defined set. It could be machine dependent or not. - user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine} + # Check for a pre-defined set. It could be machine dependent or has the mode + # (community or nco), or default + user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine}.nco if [ ! -f ${user_spec_tests_fp} ]; then - user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type} + user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine}.com + if [ ! -f ${user_spec_tests_fp} ]; then + user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine}.${compiler} + if [ ! -f ${user_spec_tests_fp} ]; then + user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine} + if [ ! -f ${user_spec_tests_fp} ]; then + user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type} + fi + fi + else + run_envir=${run_envir:-"community"} + fi + else + run_envir=${run_envir:-"nco"} fi elif [ -n "${tests_file}" ] ; then user_spec_tests_fp=$( readlink -f "${tests_file}" ) diff --git a/ush/calculate_cost.py b/ush/calculate_cost.py index 67b73ea974..1e0b52a204 100755 --- a/ush/calculate_cost.py +++ b/ush/calculate_cost.py @@ -7,7 +7,6 @@ from python_utils import ( set_env_var, import_vars, - export_vars, load_config_file, flatten_dict, ) @@ -21,13 +20,29 @@ def calculate_cost(config_fn): global PREDEF_GRID_NAME, QUILTING, GRID_GEN_METHOD # import all environment variables - import_vars() + IMPORTS = [ + "PREDEF_GRID_NAME", + "QUILTING", + "GRID_GEN_METHOD", + "DT_ATMOS", + "LAYOUT_X", + "LAYOUT_Y", + "BLOCKSIZE", + ] + import_vars(env_vars=IMPORTS) # get grid config parameters (predefined or custom) if PREDEF_GRID_NAME: - set_env_var("QUILTING", False) - set_predef_grid_params() - import_vars() + QUILTING = False + params_dict = set_predef_grid_params( + PREDEF_GRID_NAME, + QUILTING, + DT_ATMOS, + LAYOUT_X, + LAYOUT_Y, + BLOCKSIZE, + ) + import_vars(dictionary=params_dict) else: cfg_u = load_config_file(config_fn) cfg_u = flatten_dict(cfg_u) @@ -45,6 +60,8 @@ def calculate_cost(config_fn): iend_of_t7_on_t6g=GFDLgrid_IEND_OF_RGNL_DOM_ON_T6G, jstart_of_t7_on_t6g=GFDLgrid_JSTART_OF_RGNL_DOM_ON_T6G, jend_of_t7_on_t6g=GFDLgrid_JEND_OF_RGNL_DOM_ON_T6G, + RUN_ENVIR="community", + VERBOSE=False, ) elif GRID_GEN_METHOD == "ESGgrid": @@ -66,9 +83,16 @@ def calculate_cost(config_fn): # reference grid (6-hour forecast on RRFS_CONUS_25km) PREDEF_GRID_NAME = "RRFS_CONUS_25km" - export_vars() - set_predef_grid_params() - import_vars() + params_dict = set_predef_grid_params( + PREDEF_GRID_NAME, + QUILTING, + DT_ATMOS, + LAYOUT_X, + LAYOUT_Y, + BLOCKSIZE, + ) + import_vars(dictionary=params_dict) + cost.extend([DT_ATMOS, ESGgrid_NX * ESGgrid_NY]) return cost @@ -100,9 +124,11 @@ def test_calculate_cost(self): def setUp(self): set_env_var("DEBUG", False) + set_env_var("VERBOSE", False) set_env_var("PREDEF_GRID_NAME", "RRFS_CONUS_3km") set_env_var("DT_ATMOS", 36) set_env_var("LAYOUT_X", 18) set_env_var("LAYOUT_Y", 36) set_env_var("BLOCKSIZE", 28) set_env_var("QUILTING", False) + set_env_var("RUN_ENVIR", "community") diff --git a/ush/config.nco.yaml b/ush/config.nco.yaml index eec2ac1765..e8cb83ad58 100644 --- a/ush/config.nco.yaml +++ b/ush/config.nco.yaml @@ -6,8 +6,6 @@ user: MACHINE: hera ACCOUNT: an_account workflow: - USE_CRON_TO_RELAUNCH: true - CRON_RELAUNCH_INTVL_MNTS: 3 EXPT_SUBDIR: test_nco CCPP_PHYS_SUITE: FV3_GFS_v16 DATE_FIRST_CYCL: '2022040700' diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 56806fdb06..ac1a7b91af 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -1121,6 +1121,7 @@ task_get_extrn_ics: GET_EXTRN_ICS_TN: "get_extrn_ics" NNODES_GET_EXTRN_ICS: 1 PPN_GET_EXTRN_ICS: 1 + MEM_GET_EXTRN_ICS: 2G WTIME_GET_EXTRN_ICS: 00:45:00 MAXTRIES_GET_EXTRN_ICS: 1 # @@ -1242,6 +1243,7 @@ task_get_extrn_lbcs: GET_EXTRN_LBCS_TN: "get_extrn_lbcs" NNODES_GET_EXTRN_LBCS: 1 PPN_GET_EXTRN_LBCS: 1 + MEM_GET_EXTRN_LBCS: 2G WTIME_GET_EXTRN_LBCS: 00:45:00 MAXTRIES_GET_EXTRN_LBCS: 1 # @@ -1772,6 +1774,7 @@ task_get_obs_ccpa: GET_OBS_CCPA_TN: "get_obs_ccpa" NNODES_GET_OBS_CCPA: 1 PPN_GET_OBS_CCPA: 1 + MEM_GET_OBS_CCPA: 2G WTIME_GET_OBS_CCPA: 00:45:00 MAXTRIES_GET_OBS_CCPA: 1 @@ -1782,6 +1785,7 @@ task_get_obs_mrms: GET_OBS_MRMS_TN: "get_obs_mrms" NNODES_GET_OBS_MRMS: 1 PPN_GET_OBS_MRMS: 1 + MEM_GET_OBS_MRMS: 2G WTIME_GET_OBS_MRMS: 00:45:00 MAXTRIES_GET_OBS_MRMS: 1 @@ -1792,6 +1796,7 @@ task_get_obs_ndas: GET_OBS_NDAS_TN: "get_obs_ndas" NNODES_GET_OBS_NDAS: 1 PPN_GET_OBS_NDAS: 1 + MEM_GET_OBS_NDAS: 2G WTIME_GET_OBS_NDAS: 02:00:00 MAXTRIES_GET_OBS_NDAS: 1 @@ -1802,6 +1807,7 @@ task_run_vx_gridstat: VX_GRIDSTAT_TN: "run_gridstatvx" NNODES_VX_GRIDSTAT: 1 PPN_VX_GRIDSTAT: 1 + MEM_VX_GRIDSTAT: 2G WTIME_VX_GRIDSTAT: 02:00:00 MAXTRIES_VX_GRIDSTAT: 1 @@ -1812,6 +1818,7 @@ task_run_vx_gridstat_refc: VX_GRIDSTAT_REFC_TN: "run_gridstatvx_refc" NNODES_VX_GRIDSTAT: 1 PPN_VX_GRIDSTAT: 1 + MEM_VX_GRIDSTAT: 2G WTIME_VX_GRIDSTAT: 02:00:00 MAXTRIES_VX_GRIDSTAT_REFC: 1 @@ -1822,6 +1829,7 @@ task_run_vx_gridstat_retop: VX_GRIDSTAT_RETOP_TN: "run_gridstatvx_retop" NNODES_VX_GRIDSTAT: 1 PPN_VX_GRIDSTAT: 1 + MEM_VX_GRIDSTAT: 2G WTIME_VX_GRIDSTAT: 02:00:00 MAXTRIES_VX_GRIDSTAT_RETOP: 1 @@ -1832,6 +1840,7 @@ task_run_vx_gridstat_03h: VX_GRIDSTAT_03h_TN: "run_gridstatvx_03h" NNODES_VX_GRIDSTAT: 1 PPN_VX_GRIDSTAT: 1 + MEM_VX_GRIDSTAT: 2G WTIME_VX_GRIDSTAT: 02:00:00 MAXTRIES_VX_GRIDSTAT_03h: 1 @@ -1842,6 +1851,7 @@ task_run_vx_gridstat_06h: VX_GRIDSTAT_06h_TN: "run_gridstatvx_06h" NNODES_VX_GRIDSTAT: 1 PPN_VX_GRIDSTAT: 1 + MEM_VX_GRIDSTAT: 2G WTIME_VX_GRIDSTAT: 02:00:00 MAXTRIES_VX_GRIDSTAT_06h: 1 @@ -1852,6 +1862,7 @@ task_run_vx_gridstat_24h: VX_GRIDSTAT_24h_TN: "run_gridstatvx_24h" NNODES_VX_GRIDSTAT: 1 PPN_VX_GRIDSTAT: 1 + MEM_VX_GRIDSTAT: 2G WTIME_VX_GRIDSTAT: 02:00:00 MAXTRIES_VX_GRIDSTAT_24h: 1 @@ -1862,6 +1873,7 @@ task_run_vx_pointstat: VX_POINTSTAT_TN: "run_pointstatvx" NNODES_VX_POINTSTAT: 1 PPN_VX_POINTSTAT: 1 + MEM_VX_POINTSTAT: 2G WTIME_VX_POINTSTAT: 01:00:00 MAXTRIES_VX_POINTSTAT: 1 @@ -1881,6 +1893,7 @@ task_run_vx_ensgrid: MAXTRIES_VX_ENSGRID_PROB_RETOP: 1 NNODES_VX_ENSGRID: 1 PPN_VX_ENSGRID: 1 + MEM_VX_ENSGRID: 2G WTIME_VX_ENSGRID: 01:00:00 MAXTRIES_VX_ENSGRID: 1 @@ -1892,6 +1905,7 @@ task_run_vx_ensgrid_refc: VX_ENSGRID_REFC_TN: "run_ensgridvx_refc" NNODES_VX_ENSGRID: 1 PPN_VX_ENSGRID: 1 + MEM_VX_ENSGRID: 2G WTIME_VX_ENSGRID: 01:00:00 MAXTRIES_VX_ENSGRID_REFC: 1 @@ -1902,6 +1916,7 @@ task_run_vx_ensgrid_mean: VX_ENSGRID_MEAN_TN: "run_ensgridvx_mean" NNODES_VX_ENSGRID_MEAN: 1 PPN_VX_ENSGRID_MEAN: 1 + MEM_VX_ENSGRID_MEAN: 2G WTIME_VX_ENSGRID_MEAN: 01:00:00 MAXTRIES_VX_ENSGRID_MEAN: 1 @@ -1912,6 +1927,7 @@ task_run_vx_ensgrid_mean_03h: VX_ENSGRID_MEAN_03h_TN: "run_ensgridvx_mean_03h" NNODES_VX_ENSGRID_MEAN: 1 PPN_VX_ENSGRID_MEAN: 1 + MEM_VX_ENSGRID_MEAN: 2G WTIME_VX_ENSGRID_MEAN: 01:00:00 MAXTRIES_VX_ENSGRID_MEAN_03h: 1 @@ -1922,6 +1938,7 @@ task_run_vx_ensgrid_mean_06h: VX_ENSGRID_MEAN_06h_TN: "run_ensgridvx_mean_06h" NNODES_VX_ENSGRID_MEAN: 1 PPN_VX_ENSGRID_MEAN: 1 + MEM_VX_ENSGRID_MEAN: 2G WTIME_VX_ENSGRID_MEAN: 01:00:00 MAXTRIES_VX_ENSGRID_MEAN_06h: 1 @@ -1932,6 +1949,7 @@ task_run_vx_ensgrid_mean_24h: VX_ENSGRID_MEAN_24h_TN: "run_ensgridvx_mean_24h" NNODES_VX_ENSGRID_MEAN: 1 PPN_VX_ENSGRID_MEAN: 1 + MEM_VX_ENSGRID_MEAN: 2G WTIME_VX_ENSGRID_MEAN: 01:00:00 MAXTRIES_VX_ENSGRID_MEAN_24h: 1 @@ -1942,6 +1960,7 @@ task_run_vx_ensgrid_prob: VX_ENSGRID_PROB_TN: "run_ensgridvx_prob" NNODES_VX_ENSGRID_PROB: 1 PPN_VX_ENSGRID_PROB: 1 + MEM_VX_ENSGRID_PROB: 2G WTIME_VX_ENSGRID_PROB: 01:00:00 MAXTRIES_VX_ENSGRID_PROB: 1 @@ -1952,6 +1971,7 @@ task_run_vx_ensgrid_prob_03h: VX_ENSGRID_PROB_03h_TN: "run_ensgridvx_prob_03h" NNODES_VX_ENSGRID_PROB: 1 PPN_VX_ENSGRID_PROB: 1 + MEM_VX_ENSGRID_PROB: 2G WTIME_VX_ENSGRID_PROB: 01:00:00 MAXTRIES_VX_ENSGRID_PROB_03h: 1 @@ -1962,6 +1982,7 @@ task_run_vx_ensgrid_prob_06h: VX_ENSGRID_PROB_06h_TN: "run_ensgridvx_prob_06h" NNODES_VX_ENSGRID_PROB: 1 PPN_VX_ENSGRID_PROB: 1 + MEM_VX_ENSGRID_PROB: 2G WTIME_VX_ENSGRID_PROB: 01:00:00 MAXTRIES_VX_ENSGRID_PROB_06h: 1 @@ -1972,6 +1993,7 @@ task_run_vx_ensgrid_prob_24h: VX_ENSGRID_PROB_24h_TN: "run_ensgridvx_prob_24h" NNODES_VX_ENSGRID_PROB: 1 PPN_VX_ENSGRID_PROB: 1 + MEM_VX_ENSGRID_PROB: 2G WTIME_VX_ENSGRID_PROB: 01:00:00 MAXTRIES_VX_ENSGRID_PROB_24h: 1 @@ -1982,6 +2004,7 @@ task_run_vx_enspoint: VX_ENSPOINT_TN: "run_enspointvx" NNODES_VX_ENSPOINT: 1 PPN_VX_ENSPOINT: 1 + MEM_VX_ENSPOINT: 2G WTIME_VX_ENSPOINT: 01:00:00 MAXTRIES_VX_ENSPOINT: 1 @@ -1992,6 +2015,7 @@ task_run_vx_enspoint_mean: VX_ENSPOINT_MEAN_TN: "run_enspointvx_mean" NNODES_VX_ENSPOINT_MEAN: 1 PPN_VX_ENSPOINT_MEAN: 1 + MEM_VX_ENSPOINT_MEAN: 2G WTIME_VX_ENSPOINT_MEAN: 01:00:00 MAXTRIES_VX_ENSPOINT_MEAN: 1 @@ -2002,6 +2026,7 @@ task_run_vx_enspoint_prob: VX_ENSPOINT_PROB_TN: "run_enspointvx_prob" NNODES_VX_ENSPOINT_PROB: 1 PPN_VX_ENSPOINT_PROB: 1 + MEM_VX_ENSPOINT_PROB: 2G WTIME_VX_ENSPOINT_PROB: 01:00:00 MAXTRIES_VX_ENSPOINT_PROB: 1 diff --git a/ush/generate_FV3LAM_wflow.py b/ush/generate_FV3LAM_wflow.py index 969485fce0..79e779b9b4 100755 --- a/ush/generate_FV3LAM_wflow.py +++ b/ush/generate_FV3LAM_wflow.py @@ -14,6 +14,7 @@ print_err_msg_exit, log_info, import_vars, + export_vars, cp_vrfy, cd_vrfy, rm_vrfy, @@ -29,6 +30,7 @@ find_pattern_in_str, set_env_var, get_env_var, + lowercase, ) from setup import setup @@ -64,15 +66,13 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = "log.generate_FV3LAM_wflow") -> ========================================================================""" ) - # define utilities - define_macos_utilities() - # The setup function reads the user configuration file and fills in # non-user-specified values from config_defaults.yaml - setup() + var_defs_dict = setup() - # import all environment variables - import_vars() + # export/import all environment variables + export_vars(source_dict=var_defs_dict) + import_vars(dictionary=var_defs_dict) # # ----------------------------------------------------------------------- @@ -108,6 +108,13 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = "log.generate_FV3LAM_wflow") -> WFLOW_XML_FP = '{WFLOW_XML_FP}'""" ) + # + # Dictionary of settings to pass to fill_jinja + # + settings = {} + for k, v in var_defs_dict.items(): + settings[lowercase(k)] = v + ensmem_indx_name = "" uscore_ensmem_name = "" slash_ensmem_subdir = "" @@ -116,283 +123,38 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = "log.generate_FV3LAM_wflow") -> uscore_ensmem_name = f"_mem#{ensmem_indx_name}#" slash_ensmem_subdir = f"/mem#{ensmem_indx_name}#" - # get time string d = DATE_FIRST_CYCL + timedelta(seconds=DT_ATMOS) time_str = d.strftime("%M:%S") - # Dictionary of settings - settings = { - # - # Parameters needed by the job scheduler. - # - "account": ACCOUNT, - "sched": SCHED, - "partition_default": PARTITION_DEFAULT, - "queue_default": QUEUE_DEFAULT, - "partition_hpss": PARTITION_HPSS, - "queue_hpss": QUEUE_HPSS, - "partition_fcst": PARTITION_FCST, - "queue_fcst": QUEUE_FCST, - "machine": MACHINE, - "sched_native_cmd": SCHED_NATIVE_CMD, - "workflow_id": WORKFLOW_ID, - # - # Run environment - # - "run_envir": RUN_ENVIR, - "run": RUN, - "net": NET, - # - # Workflow task names. - # - "make_grid_tn": MAKE_GRID_TN, - "make_orog_tn": MAKE_OROG_TN, - "make_sfc_climo_tn": MAKE_SFC_CLIMO_TN, - "get_extrn_ics_tn": GET_EXTRN_ICS_TN, - "get_extrn_lbcs_tn": GET_EXTRN_LBCS_TN, - "make_ics_tn": MAKE_ICS_TN, - "make_lbcs_tn": MAKE_LBCS_TN, - "run_fcst_tn": RUN_FCST_TN, - "run_post_tn": RUN_POST_TN, - "get_obs_ccpa_tn": GET_OBS_CCPA_TN, - "get_obs_ndas_tn": GET_OBS_NDAS_TN, - "get_obs_mrms_tn": GET_OBS_MRMS_TN, - "vx_tn": VX_TN, - "vx_gridstat_tn": VX_GRIDSTAT_TN, - "vx_gridstat_refc_tn": VX_GRIDSTAT_REFC_TN, - "vx_gridstat_retop_tn": VX_GRIDSTAT_RETOP_TN, - "vx_gridstat_03h_tn": VX_GRIDSTAT_03h_TN, - "vx_gridstat_06h_tn": VX_GRIDSTAT_06h_TN, - "vx_gridstat_24h_tn": VX_GRIDSTAT_24h_TN, - "vx_pointstat_tn": VX_POINTSTAT_TN, - "vx_ensgrid_tn": VX_ENSGRID_TN, - "vx_ensgrid_refc_tn": VX_ENSGRID_REFC_TN, - "vx_ensgrid_retop_tn": VX_ENSGRID_RETOP_TN, - "vx_ensgrid_03h_tn": VX_ENSGRID_03h_TN, - "vx_ensgrid_06h_tn": VX_ENSGRID_06h_TN, - "vx_ensgrid_24h_tn": VX_ENSGRID_24h_TN, - "vx_ensgrid_mean_tn": VX_ENSGRID_MEAN_TN, - "vx_ensgrid_prob_tn": VX_ENSGRID_PROB_TN, - "vx_ensgrid_mean_03h_tn": VX_ENSGRID_MEAN_03h_TN, - "vx_ensgrid_prob_03h_tn": VX_ENSGRID_PROB_03h_TN, - "vx_ensgrid_mean_06h_tn": VX_ENSGRID_MEAN_06h_TN, - "vx_ensgrid_prob_06h_tn": VX_ENSGRID_PROB_06h_TN, - "vx_ensgrid_mean_24h_tn": VX_ENSGRID_MEAN_24h_TN, - "vx_ensgrid_prob_24h_tn": VX_ENSGRID_PROB_24h_TN, - "vx_ensgrid_prob_refc_tn": VX_ENSGRID_PROB_REFC_TN, - "vx_ensgrid_prob_retop_tn": VX_ENSGRID_PROB_RETOP_TN, - "vx_enspoint_tn": VX_ENSPOINT_TN, - "vx_enspoint_mean_tn": VX_ENSPOINT_MEAN_TN, - "vx_enspoint_prob_tn": VX_ENSPOINT_PROB_TN, - # - # Entity used to load the module file for each GET_OBS_* task. - # - "get_obs": GET_OBS, - # - # Number of nodes to use for each task. - # - "nnodes_make_grid": NNODES_MAKE_GRID, - "nnodes_make_orog": NNODES_MAKE_OROG, - "nnodes_make_sfc_climo": NNODES_MAKE_SFC_CLIMO, - "nnodes_get_extrn_ics": NNODES_GET_EXTRN_ICS, - "nnodes_get_extrn_lbcs": NNODES_GET_EXTRN_LBCS, - "nnodes_make_ics": NNODES_MAKE_ICS, - "nnodes_make_lbcs": NNODES_MAKE_LBCS, - "nnodes_run_fcst": NNODES_RUN_FCST, - "nnodes_run_post": NNODES_RUN_POST, - "nnodes_get_obs_ccpa": NNODES_GET_OBS_CCPA, - "nnodes_get_obs_mrms": NNODES_GET_OBS_MRMS, - "nnodes_get_obs_ndas": NNODES_GET_OBS_NDAS, - "nnodes_vx_gridstat": NNODES_VX_GRIDSTAT, - "nnodes_vx_pointstat": NNODES_VX_POINTSTAT, - "nnodes_vx_ensgrid": NNODES_VX_ENSGRID, - "nnodes_vx_ensgrid_mean": NNODES_VX_ENSGRID_MEAN, - "nnodes_vx_ensgrid_prob": NNODES_VX_ENSGRID_PROB, - "nnodes_vx_enspoint": NNODES_VX_ENSPOINT, - "nnodes_vx_enspoint_mean": NNODES_VX_ENSPOINT_MEAN, - "nnodes_vx_enspoint_prob": NNODES_VX_ENSPOINT_PROB, - # - # Number of cores used for a task - # - "ncores_run_fcst": PE_MEMBER01, - "native_run_fcst": f"--cpus-per-task {OMP_NUM_THREADS_RUN_FCST} --exclusive", - # - # Number of OpenMP threads for the run_fcst task - # - "omp_num_threads_run_fcst": OMP_NUM_THREADS_RUN_FCST, - # - # Number of logical processes per node for each task. If running without - # threading, this is equal to the number of MPI processes per node. - # - "ppn_make_grid": PPN_MAKE_GRID, - "ppn_make_orog": PPN_MAKE_OROG, - "ppn_make_sfc_climo": PPN_MAKE_SFC_CLIMO, - "ppn_get_extrn_ics": PPN_GET_EXTRN_ICS, - "ppn_get_extrn_lbcs": PPN_GET_EXTRN_LBCS, - "ppn_make_ics": PPN_MAKE_ICS, - "ppn_make_lbcs": PPN_MAKE_LBCS, - "ppn_run_fcst": PPN_RUN_FCST, - "ppn_run_post": PPN_RUN_POST, - "ppn_get_obs_ccpa": PPN_GET_OBS_CCPA, - "ppn_get_obs_mrms": PPN_GET_OBS_MRMS, - "ppn_get_obs_ndas": PPN_GET_OBS_NDAS, - "ppn_vx_gridstat": PPN_VX_GRIDSTAT, - "ppn_vx_pointstat": PPN_VX_POINTSTAT, - "ppn_vx_ensgrid": PPN_VX_ENSGRID, - "ppn_vx_ensgrid_mean": PPN_VX_ENSGRID_MEAN, - "ppn_vx_ensgrid_prob": PPN_VX_ENSGRID_PROB, - "ppn_vx_enspoint": PPN_VX_ENSPOINT, - "ppn_vx_enspoint_mean": PPN_VX_ENSPOINT_MEAN, - "ppn_vx_enspoint_prob": PPN_VX_ENSPOINT_PROB, - # - # Maximum wallclock time for each task. - # - "wtime_make_grid": WTIME_MAKE_GRID, - "wtime_make_orog": WTIME_MAKE_OROG, - "wtime_make_sfc_climo": WTIME_MAKE_SFC_CLIMO, - "wtime_get_extrn_ics": WTIME_GET_EXTRN_ICS, - "wtime_get_extrn_lbcs": WTIME_GET_EXTRN_LBCS, - "wtime_make_ics": WTIME_MAKE_ICS, - "wtime_make_lbcs": WTIME_MAKE_LBCS, - "wtime_run_fcst": WTIME_RUN_FCST, - "wtime_run_post": WTIME_RUN_POST, - "wtime_get_obs_ccpa": WTIME_GET_OBS_CCPA, - "wtime_get_obs_mrms": WTIME_GET_OBS_MRMS, - "wtime_get_obs_ndas": WTIME_GET_OBS_NDAS, - "wtime_vx_gridstat": WTIME_VX_GRIDSTAT, - "wtime_vx_pointstat": WTIME_VX_POINTSTAT, - "wtime_vx_ensgrid": WTIME_VX_ENSGRID, - "wtime_vx_ensgrid_mean": WTIME_VX_ENSGRID_MEAN, - "wtime_vx_ensgrid_prob": WTIME_VX_ENSGRID_PROB, - "wtime_vx_enspoint": WTIME_VX_ENSPOINT, - "wtime_vx_enspoint_mean": WTIME_VX_ENSPOINT_MEAN, - "wtime_vx_enspoint_prob": WTIME_VX_ENSPOINT_PROB, - # - # Maximum number of tries for each task. - # - "maxtries_make_grid": MAXTRIES_MAKE_GRID, - "maxtries_make_orog": MAXTRIES_MAKE_OROG, - "maxtries_make_sfc_climo": MAXTRIES_MAKE_SFC_CLIMO, - "maxtries_get_extrn_ics": MAXTRIES_GET_EXTRN_ICS, - "maxtries_get_extrn_lbcs": MAXTRIES_GET_EXTRN_LBCS, - "maxtries_make_ics": MAXTRIES_MAKE_ICS, - "maxtries_make_lbcs": MAXTRIES_MAKE_LBCS, - "maxtries_run_fcst": MAXTRIES_RUN_FCST, - "maxtries_run_post": MAXTRIES_RUN_POST, - "maxtries_get_obs_ccpa": MAXTRIES_GET_OBS_CCPA, - "maxtries_get_obs_mrms": MAXTRIES_GET_OBS_MRMS, - "maxtries_get_obs_ndas": MAXTRIES_GET_OBS_NDAS, - "maxtries_vx_gridstat": MAXTRIES_VX_GRIDSTAT, - "maxtries_vx_gridstat_refc": MAXTRIES_VX_GRIDSTAT_REFC, - "maxtries_vx_gridstat_retop": MAXTRIES_VX_GRIDSTAT_RETOP, - "maxtries_vx_gridstat_03h": MAXTRIES_VX_GRIDSTAT_03h, - "maxtries_vx_gridstat_06h": MAXTRIES_VX_GRIDSTAT_06h, - "maxtries_vx_gridstat_24h": MAXTRIES_VX_GRIDSTAT_24h, - "maxtries_vx_pointstat": MAXTRIES_VX_POINTSTAT, - "maxtries_vx_ensgrid": MAXTRIES_VX_ENSGRID, - "maxtries_vx_ensgrid_refc": MAXTRIES_VX_ENSGRID_REFC, - "maxtries_vx_ensgrid_retop": MAXTRIES_VX_ENSGRID_RETOP, - "maxtries_vx_ensgrid_03h": MAXTRIES_VX_ENSGRID_03h, - "maxtries_vx_ensgrid_06h": MAXTRIES_VX_ENSGRID_06h, - "maxtries_vx_ensgrid_24h": MAXTRIES_VX_ENSGRID_24h, - "maxtries_vx_ensgrid_mean": MAXTRIES_VX_ENSGRID_MEAN, - "maxtries_vx_ensgrid_prob": MAXTRIES_VX_ENSGRID_PROB, - "maxtries_vx_ensgrid_mean_03h": MAXTRIES_VX_ENSGRID_MEAN_03h, - "maxtries_vx_ensgrid_prob_03h": MAXTRIES_VX_ENSGRID_PROB_03h, - "maxtries_vx_ensgrid_mean_06h": MAXTRIES_VX_ENSGRID_MEAN_06h, - "maxtries_vx_ensgrid_prob_06h": MAXTRIES_VX_ENSGRID_PROB_06h, - "maxtries_vx_ensgrid_mean_24h": MAXTRIES_VX_ENSGRID_MEAN_24h, - "maxtries_vx_ensgrid_prob_24h": MAXTRIES_VX_ENSGRID_PROB_24h, - "maxtries_vx_ensgrid_prob_refc": MAXTRIES_VX_ENSGRID_PROB_REFC, - "maxtries_vx_ensgrid_prob_retop": MAXTRIES_VX_ENSGRID_PROB_RETOP, - "maxtries_vx_enspoint": MAXTRIES_VX_ENSPOINT, - "maxtries_vx_enspoint_mean": MAXTRIES_VX_ENSPOINT_MEAN, - "maxtries_vx_enspoint_prob": MAXTRIES_VX_ENSPOINT_PROB, - # - # Flags that specify whether to run the preprocessing or - # verification-related tasks. - # - "run_task_make_grid": RUN_TASK_MAKE_GRID, - "run_task_make_orog": RUN_TASK_MAKE_OROG, - "run_task_make_sfc_climo": RUN_TASK_MAKE_SFC_CLIMO, - "run_task_get_extrn_ics": RUN_TASK_GET_EXTRN_ICS, - "run_task_get_extrn_lbcs": RUN_TASK_GET_EXTRN_LBCS, - "run_task_make_ics": RUN_TASK_MAKE_ICS, - "run_task_make_lbcs": RUN_TASK_MAKE_LBCS, - "run_task_run_fcst": RUN_TASK_RUN_FCST, - "run_task_run_post": RUN_TASK_RUN_POST, - "run_task_get_obs_ccpa": RUN_TASK_GET_OBS_CCPA, - "run_task_get_obs_mrms": RUN_TASK_GET_OBS_MRMS, - "run_task_get_obs_ndas": RUN_TASK_GET_OBS_NDAS, - "run_task_vx_gridstat": RUN_TASK_VX_GRIDSTAT, - "run_task_vx_pointstat": RUN_TASK_VX_POINTSTAT, - "run_task_vx_ensgrid": RUN_TASK_VX_ENSGRID, - "run_task_vx_enspoint": RUN_TASK_VX_ENSPOINT, - # - # Number of physical cores per node for the current machine. - # - "ncores_per_node": NCORES_PER_NODE, - # - # Directories and files. - # - "exptdir": EXPTDIR, - "jobsdir": JOBSdir, - "logdir": LOGDIR, - "scriptsdir": SCRIPTSdir, - "comin_basedir": COMIN_BASEDIR, - "comout_basedir": COMOUT_BASEDIR, - "global_var_defns_fp": GLOBAL_VAR_DEFNS_FP, - "load_modules_run_task_fp": LOAD_MODULES_RUN_TASK_FP, - # - # External model information for generating ICs and LBCs. - # - "extrn_mdl_name_ics": EXTRN_MDL_NAME_ICS, - "extrn_mdl_name_lbcs": EXTRN_MDL_NAME_LBCS, - # - # Parameters that determine the set of cycles to run. - # - "date_first_cycl": date_to_str(DATE_FIRST_CYCL, format="%Y%m%d%H00"), - "date_last_cycl": date_to_str(DATE_LAST_CYCL, format="%Y%m%d%H00"), - "cdate_first_cycl": DATE_FIRST_CYCL, - "cycl_freq": f"{INCR_CYCL_FREQ:02d}:00:00", - # - # Forecast length (same for all cycles). - # - "fcst_len_hrs": FCST_LEN_HRS, - # - # Inline post - # - "write_dopost": WRITE_DOPOST, - # - # METPlus-specific information - # - "model": MODEL, - "met_install_dir": MET_INSTALL_DIR, - "met_bin_exec": MET_BIN_EXEC, - "metplus_path": METPLUS_PATH, - "vx_config_dir": VX_CONFIG_DIR, - "metplus_conf": METPLUS_CONF, - "met_config": MET_CONFIG, - "ccpa_obs_dir": CCPA_OBS_DIR, - "mrms_obs_dir": MRMS_OBS_DIR, - "ndas_obs_dir": NDAS_OBS_DIR, - # - # Ensemble-related parameters. - # - "do_ensemble": DO_ENSEMBLE, - "num_ens_members": NUM_ENS_MEMBERS, - "ndigits_ensmem_names": f"{NDIGITS_ENSMEM_NAMES}", - "ensmem_indx_name": ensmem_indx_name, - "uscore_ensmem_name": uscore_ensmem_name, - "slash_ensmem_subdir": slash_ensmem_subdir, - # - # Parameters associated with subhourly post-processed output - # - "sub_hourly_post": SUB_HOURLY_POST, - "delta_min": DT_SUBHOURLY_POST_MNTS, - "first_fv3_file_tstr": f"000:{time_str}", - } - # End of "settings" variable. + settings.update( + { + # + # Number of cores used for a task + # + "ncores_run_fcst": PE_MEMBER01, + "native_run_fcst": f"--cpus-per-task {OMP_NUM_THREADS_RUN_FCST} --exclusive", + # + # Parameters that determine the set of cycles to run. + # + "date_first_cycl": date_to_str(DATE_FIRST_CYCL, format="%Y%m%d%H00"), + "date_last_cycl": date_to_str(DATE_LAST_CYCL, format="%Y%m%d%H00"), + "cdate_first_cycl": DATE_FIRST_CYCL, + "cycl_freq": f"{INCR_CYCL_FREQ:02d}:00:00", + # + # Ensemble-related parameters. + # + "ensmem_indx_name": ensmem_indx_name, + "uscore_ensmem_name": uscore_ensmem_name, + "slash_ensmem_subdir": slash_ensmem_subdir, + # + # Parameters associated with subhourly post-processed output + # + "delta_min": DT_SUBHOURLY_POST_MNTS, + "first_fv3_file_tstr": f"000:{time_str}", + } + ) + + # Log "settings" variable. settings_str = cfg_to_yaml_str(settings) log_info( diff --git a/ush/get_crontab_contents.py b/ush/get_crontab_contents.py index a1e7863a43..774d311ac0 100644 --- a/ush/get_crontab_contents.py +++ b/ush/get_crontab_contents.py @@ -48,7 +48,7 @@ def get_crontab_contents(called_from_cron): print_input_args(locals()) # import selected env vars - IMPORTS = ["MACHINE", "USER", "DEBUG"] + IMPORTS = ["MACHINE", "DEBUG"] import_vars(env_vars=IMPORTS) __crontab_cmd__ = "crontab" @@ -93,7 +93,7 @@ def add_crontab_line(): """Add crontab line to cron table""" # import selected env vars - IMPORTS = ["MACHINE", "USER", "CRONTAB_LINE", "VERBOSE", "EXPTDIR"] + IMPORTS = ["MACHINE", "CRONTAB_LINE", "VERBOSE", "EXPTDIR"] import_vars(env_vars=IMPORTS) # @@ -160,7 +160,7 @@ def delete_crontab_line(called_from_cron): print_input_args(locals()) # import selected env vars - IMPORTS = ["MACHINE", "USER", "CRONTAB_LINE", "DEBUG"] + IMPORTS = ["MACHINE", "CRONTAB_LINE", "DEBUG"] import_vars(env_vars=IMPORTS) # diff --git a/ush/job_preamble.sh b/ush/job_preamble.sh index 63ffb1bbeb..438f4f888c 100644 --- a/ush/job_preamble.sh +++ b/ush/job_preamble.sh @@ -1,5 +1,17 @@ #!/bin/bash +# +#----------------------------------------------------------------------- +# +# If requested to share data with next task, override jobid +# +#----------------------------------------------------------------------- +# +export share_pid=${WORKFLOW_ID}_${PDY}${cyc} +if [ $# -ne 0 ]; then + export pid=$share_pid + export jobid=${job}.${pid} +fi # #----------------------------------------------------------------------- # @@ -25,11 +37,9 @@ fi #----------------------------------------------------------------------- # export DATA= -export DATA_SHARED= if [ "${RUN_ENVIR}" = "nco" ]; then export DATA=${DATAROOT}/${jobid} - export DATA_SHARED=${DATAROOT}/${RUN}.${PDY}.${WORKFLOW_ID} - mkdir_vrfy -p $DATA $DATA_SHARED + mkdir_vrfy -p $DATA cd $DATA fi # @@ -41,7 +51,7 @@ fi # if [ "${RUN_ENVIR}" = "nco" ]; then if [ ! -z $(command -v setpdy.sh) ]; then - setpdy.sh + COMROOT=$COMROOT setpdy.sh . ./PDY fi fi @@ -104,9 +114,28 @@ export -f POST_STEP if [ "${RUN_ENVIR}" = "nco" ]; then export COMIN="${COMIN_BASEDIR}/${RUN}.${PDY}/${cyc}" export COMOUT="${COMOUT_BASEDIR}/${RUN}.${PDY}/${cyc}" + export COMINext="${EXTROOT}/${RUN}.${PDY}/${cyc}" else export COMIN="${COMIN_BASEDIR}/${PDY}${cyc}" export COMOUT="${COMOUT_BASEDIR}/${PDY}${cyc}" + export COMINext="${EXTROOT}/${PDY}${cyc}" +fi + +# +#----------------------------------------------------------------------- +# +# Create symlinks to log files in the experiment directory. Makes viewing +# log files easier in NCO mode, as well as make CIs work +# +#----------------------------------------------------------------------- +# +if [ "${RUN_ENVIR}" = "nco" ]; then + __EXPTLOG=${EXPTDIR}/log + mkdir_vrfy -p ${__EXPTLOG} + for i in ${LOGDIR}/*.${WORKFLOW_ID}.log; do + __LOGB=$(basename $i .${WORKFLOW_ID}.log) + ln_vrfy -sf $i ${__EXPTLOG}/${__LOGB}.log + done fi # #----------------------------------------------------------------------- @@ -117,19 +146,10 @@ fi # function job_postamble() { - if [ "${RUN_ENVIR}" = "nco" ]; then - - # Remove temp directory + # Remove temp directory + if [ "${RUN_ENVIR}" = "nco" ] && [ $# -eq 0 ]; then cd ${DATAROOT} - [[ $KEEPDATA = "FALSE" ]] && rm -rf $DATA $DATA_SHARED - - # Create symlinks to log files - local EXPTLOG=${EXPTDIR}/log - mkdir_vrfy -p ${EXPTLOG} - for i in ${LOGDIR}/*.${WORKFLOW_ID}.log; do - local LOGB=$(basename $i .${WORKFLOW_ID}.log) - ln_vrfy -sf $i ${EXPTLOG}/${LOGB}.log - done + [[ $KEEPDATA = "FALSE" ]] && rm -rf $DATA fi # Print exit message diff --git a/ush/link_fix.py b/ush/link_fix.py index 5602d5170f..f18b82e9cd 100755 --- a/ush/link_fix.py +++ b/ush/link_fix.py @@ -8,7 +8,6 @@ from python_utils import ( import_vars, - set_env_var, print_input_args, print_info_msg, print_err_msg_exit, @@ -23,10 +22,10 @@ ) -def link_fix(verbose, file_group): +def link_fix(cfg_d, file_group): """This file defines a function that ... Args: - verbose: True or False + cfg_d: dictionary of settings file_group: could be on of ["grid", "orog", "sfc_climo"] Returns: a string: resolution @@ -38,7 +37,7 @@ def link_fix(verbose, file_group): check_var_valid_value(file_group, valid_vals_file_group) # import all environement variables - import_vars() + import_vars(dictionary=flatten_dict(cfg_d)) # # ----------------------------------------------------------------------- @@ -55,7 +54,7 @@ def link_fix(verbose, file_group): # ----------------------------------------------------------------------- # print_info_msg( - f"Creating links in the FIXlam directory to the grid files...", verbose=verbose + f"Creating links in the FIXlam directory to the grid files...", verbose=VERBOSE ) # # ----------------------------------------------------------------------- @@ -400,32 +399,33 @@ def parse_args(argv): if __name__ == "__main__": args = parse_args(sys.argv[1:]) cfg = load_shell_config(args.path_to_defns) - cfg = flatten_dict(cfg) - import_vars(dictionary=cfg) - link_fix(VERBOSE, args.file_group) + link_fix(cfg, args.file_group) class Testing(unittest.TestCase): def test_link_fix(self): - res = link_fix(verbose=True, file_group="grid") - self.assertTrue(res == "3357") - - def setUp(self): define_macos_utilities() TEST_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_data") FIXlam = os.path.join(TEST_DIR, "expt", "fix_lam") mkdir_vrfy("-p", FIXlam) - set_env_var("FIXlam", FIXlam) - set_env_var("DOT_OR_USCORE", "_") - set_env_var("TILE_RGNL", 7) - set_env_var("NH0", 0) - set_env_var("NHW", 6) - set_env_var("NH4", 4) - set_env_var("NH3", 3) - set_env_var("GRID_DIR", TEST_DIR + os.sep + "RRFS_CONUS_3km") - set_env_var("RUN_TASK_MAKE_GRID", "FALSE") - set_env_var("OROG_DIR", TEST_DIR + os.sep + "RRFS_CONUS_3km") - set_env_var("RUN_TASK_MAKE_OROG", "FALSE") - set_env_var("SFC_CLIMO_DIR", TEST_DIR + os.sep + "RRFS_CONUS_3km") - set_env_var("RUN_TASK_MAKE_SFC_CLIMO", "FALSE") - set_env_var("CCPP_PHYS_SUITE", "FV3_GSD_SAR") + + cfg_d = { + "FIXlam": FIXlam, + "DOT_OR_USCORE": "_", + "TILE_RGNL": 7, + "NH0": 0, + "NHW": 6, + "NH4": 4, + "NH3": 3, + "GRID_DIR": TEST_DIR + os.sep + "RRFS_CONUS_3km", + "RUN_TASK_MAKE_GRID": "FALSE", + "OROG_DIR": TEST_DIR + os.sep + "RRFS_CONUS_3km", + "RUN_TASK_MAKE_OROG": "FALSE", + "SFC_CLIMO_DIR": TEST_DIR + os.sep + "RRFS_CONUS_3km", + "RUN_TASK_MAKE_SFC_CLIMO": "FALSE", + "CCPP_PHYS_SUITE": "FV3_GSD_SAR", + "VERBOSE": False, + } + + res = link_fix(cfg_d, file_group="grid") + self.assertTrue(res == "3357") diff --git a/ush/load_modules_run_task.sh b/ush/load_modules_run_task.sh index 6d5f8cde50..f49e4de0b8 100755 --- a/ush/load_modules_run_task.sh +++ b/ush/load_modules_run_task.sh @@ -81,14 +81,15 @@ jjob_fp="$2" set +u if [ ! -z ${SLURM_JOB_ID} ]; then export job=${SLURM_JOB_NAME} - export jobid=${job}.${SLURM_JOB_ID} + export pid=${pid:-${SLURM_JOB_ID}} elif [ ! -z ${PBS_JOBID} ]; then export job=${PBS_JOBNAME} - export jobid=${job}.${PBS_JOBID} + export pid=${pid:-${PBS_JOBID}} else export job=${task_name} - export jobid=${job}.$$ + export pid=${pid:-$$} fi +export jobid=${job}.${pid} set -u # #----------------------------------------------------------------------- diff --git a/ush/machine/wcoss2.yaml b/ush/machine/wcoss2.yaml index 059dc0776c..4ed9ab7e3d 100644 --- a/ush/machine/wcoss2.yaml +++ b/ush/machine/wcoss2.yaml @@ -32,3 +32,10 @@ task_run_fcst: FIXaer: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_am FIXlut: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_lut +data: + GSMGFS: compath.py ${envir}/gsmgfs/${gsmgfs_ver}/gsmgfs.${PDY} + FV3GFS: compath.py ${envir}/gfs/${gfs_ver}/gfs.${PDY} + RAP: compath.py ${envir}/rap/${rap_ver}/rap.${PDY} + NAM: compath.py ${envir}/nam/${nam_ver}/nam.${PDY} + HRRR: compath.py ${envir}/hrrr/${hrrr_ver}/hrrr.${PDY} + diff --git a/ush/retrieve_data.py b/ush/retrieve_data.py index 2d7bcefa17..a0d7326832 100755 --- a/ush/retrieve_data.py +++ b/ush/retrieve_data.py @@ -70,7 +70,7 @@ def clean_up_output_dir(expected_subdir, local_archive, output_path, source_path return unavailable -def copy_file(source, destination): +def copy_file(source, destination, copy_cmd): """ Copy a file from a source and place it in the destination location. @@ -85,7 +85,7 @@ def copy_file(source, destination): # Using subprocess here because system copy is much faster than # python copy options. - cmd = f"cp {source} {destination}" + cmd = f"{copy_cmd} {source} {destination}" logging.info(f"Running command: \n {cmd}") try: subprocess.run( @@ -381,7 +381,10 @@ def get_requested_files(cla, file_templates, input_locs, method="disk", **kwargs logging.debug(f"Full file path: {input_loc}") if method == "disk": - retrieved = copy_file(input_loc, target_path) + if cla.symlink: + retrieved = copy_file(input_loc, target_path, "ln -sf") + else: + retrieved = copy_file(input_loc, target_path, "cp") if method == "download": retrieved = download_file(input_loc) @@ -945,6 +948,11 @@ def parse_args(argv): ) # Optional + parser.add_argument( + "--symlink", + action="store_true", + help="Symlink data files when source is disk", + ) parser.add_argument( "--debug", action="store_true", diff --git a/ush/set_gridparams_GFDLgrid.py b/ush/set_gridparams_GFDLgrid.py index 70a309c3fd..6edff861bb 100644 --- a/ush/set_gridparams_GFDLgrid.py +++ b/ush/set_gridparams_GFDLgrid.py @@ -38,6 +38,8 @@ def set_gridparams_GFDLgrid( iend_of_t7_on_t6g, jstart_of_t7_on_t6g, jend_of_t7_on_t6g, + RUN_ENVIR, + VERBOSE, ): """Sets the parameters for a grid that is to be generated using the "GFDLgrid" grid generation method (i.e. GRID_GEN_METHOD set to "ESGgrid"). @@ -59,8 +61,6 @@ def set_gridparams_GFDLgrid( print_input_args(locals()) # get needed environment variables - IMPORTS = ["VERBOSE", "RUN_ENVIR"] - import_vars(env_vars=IMPORTS) IMPORTS = ["NH4"] USHdir = os.path.dirname(os.path.abspath(__file__)) constants_cfg = load_config_file(os.path.join(USHdir, "constants.yaml")) @@ -493,6 +493,8 @@ def test_set_gridparams_GFDLgrid(self): iend_of_t7_on_t6g=84, jstart_of_t7_on_t6g=17, jend_of_t7_on_t6g=80, + RUN_ENVIR="community", + VERBOSE=False, ) self.assertEqual( diff --git a/ush/set_ozone_param.py b/ush/set_ozone_param.py index 28f6e1ef68..5bc29c612f 100644 --- a/ush/set_ozone_param.py +++ b/ush/set_ozone_param.py @@ -6,12 +6,8 @@ from python_utils import ( log_info, - import_vars, - export_vars, - set_env_var, list_to_str, print_input_args, - define_macos_utilities, load_xml_file, has_tag_with_value, find_pattern_in_str, diff --git a/ush/set_predef_grid_params.py b/ush/set_predef_grid_params.py index faf8c75c58..d0ab5a97cb 100644 --- a/ush/set_predef_grid_params.py +++ b/ush/set_predef_grid_params.py @@ -5,36 +5,31 @@ from textwrap import dedent from python_utils import ( - import_vars, - export_vars, - set_env_var, - get_env_var, - print_input_args, - define_macos_utilities, load_config_file, - cfg_to_yaml_str, flatten_dict, ) -def set_predef_grid_params(): +def set_predef_grid_params( + PREDEF_GRID_NAME, + QUILTING, + DT_ATMOS, + LAYOUT_X, + LAYOUT_Y, + BLOCKSIZE, +): """Sets grid parameters for the specified predfined grid Args: - None + PREDEF_GRID_NAME, + QUILTING, + DT_ATMOS, + LAYOUT_X, + LAYOUT_Y, + BLOCKSIZE, Returns: - None + Dictionary of grid parameters """ - # import all environement variables - IMPORTS = [ - "PREDEF_GRID_NAME", - "QUILTING", - "DT_ATMOS", - "LAYOUT_X", - "LAYOUT_Y", - "BLOCKSIZE", - ] - import_vars(env_vars=IMPORTS) USHdir = os.path.dirname(os.path.abspath(__file__)) params_dict = load_config_file(os.path.join(USHdir, "predef_grid_params.yaml")) @@ -55,37 +50,36 @@ def set_predef_grid_params(): params_dict = flatten_dict(params_dict) # take care of special vars - special_vars = ["DT_ATMOS", "LAYOUT_X", "LAYOUT_Y", "BLOCKSIZE"] - for var in special_vars: - if globals()[var] is not None: - params_dict[var] = globals()[var] - - # export variables to environment - export_vars(source_dict=params_dict) + if DT_ATMOS is not None: + params_dict["DT_ATMOS"] = DT_ATMOS + if LAYOUT_X is not None: + params_dict["LAYOUT_X"] = LAYOUT_X + if LAYOUT_Y is not None: + params_dict["LAYOUT_Y"] = LAYOUT_Y + if BLOCKSIZE is not None: + params_dict["BLOCKSIZE"] = BLOCKSIZE return params_dict -if __name__ == "__main__": - params_dict = set_predef_grid_params() - print(cfg_to_shell_str(params_dict), end="") - - class Testing(unittest.TestCase): def test_set_predef_grid_params(self): - set_predef_grid_params() - self.assertEqual(get_env_var("GRID_GEN_METHOD"), "ESGgrid") - self.assertEqual(get_env_var("ESGgrid_LON_CTR"), -97.5) - set_env_var("QUILTING", True) - set_predef_grid_params() - self.assertEqual(get_env_var("WRTCMP_nx"), 1799) - - def setUp(self): - define_macos_utilities() - set_env_var("DEBUG", False) - set_env_var("PREDEF_GRID_NAME", "RRFS_CONUS_3km") - set_env_var("DT_ATMOS", 36) - set_env_var("LAYOUT_X", 18) - set_env_var("LAYOUT_Y", 36) - set_env_var("BLOCKSIZE", 28) - set_env_var("QUILTING", False) + params_dict = set_predef_grid_params( + PREDEF_GRID_NAME="RRFS_CONUS_3km", + QUILTING=False, + DT_ATMOS=36, + LAYOUT_X=18, + LAYOUT_Y=36, + BLOCKSIZE=28, + ) + self.assertEqual(params_dict["GRID_GEN_METHOD"], "ESGgrid") + self.assertEqual(params_dict["ESGgrid_LON_CTR"], -97.5) + params_dict = set_predef_grid_params( + PREDEF_GRID_NAME="RRFS_CONUS_3km", + QUILTING=True, + DT_ATMOS=36, + LAYOUT_X=18, + LAYOUT_Y=36, + BLOCKSIZE=28, + ) + self.assertEqual(params_dict["WRTCMP_nx"], 1799) diff --git a/ush/set_thompson_mp_fix_files.py b/ush/set_thompson_mp_fix_files.py index df69c2b232..6eecd9fa7a 100644 --- a/ush/set_thompson_mp_fix_files.py +++ b/ush/set_thompson_mp_fix_files.py @@ -6,9 +6,6 @@ from python_utils import ( log_info, - import_vars, - export_vars, - set_env_var, list_to_str, print_input_args, define_macos_utilities, @@ -18,6 +15,9 @@ def set_thompson_mp_fix_files( + EXTRN_MDL_NAME_ICS, + EXTRN_MDL_NAME_LBCS, + CCPP_PHYS_SUITE, ccpp_phys_suite_fp, thompson_mp_climo_fn, CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, @@ -34,6 +34,9 @@ def set_thompson_mp_fix_files( symlinks to these files are created in the run directories. Args: + EXTRN_MDL_NAME_ICS, + EXTRN_MDL_NAME_LBCS, + CCPP_PHYS_SUITE, ccpp_phys_suite_fp: full path to CCPP physics suite thompson_mp_climo_fn: netcdf file for thompson microphysics CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING @@ -44,10 +47,6 @@ def set_thompson_mp_fix_files( print_input_args(locals()) - # import some environment variables - IMPORTS = ["EXTRN_MDL_NAME_ICS", "EXTRN_MDL_NAME_LBCS", "CCPP_PHYS_SUITE"] - import_vars(env_vars=IMPORTS) - # # ----------------------------------------------------------------------- # @@ -130,6 +129,9 @@ def test_set_thompson_mp_fix_files(self): self.assertEqual( True, set_thompson_mp_fix_files( + "FV3GFS", + "FV3GFS", + "FV3_GSD_SAR", f"{USHdir}{os.sep}test_data{os.sep}suite_FV3_GSD_SAR.xml", "Thompson_MP_MONTHLY_CLIMO.nc", CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, @@ -138,9 +140,6 @@ def test_set_thompson_mp_fix_files(self): ) def setUp(self): - set_env_var("EXTRN_MDL_NAME_ICS", "FV3GFS") - set_env_var("EXTRN_MDL_NAME_LBCS", "FV3GFS") - set_env_var("CCPP_PHYS_SUITE", "FV3_GSD_SAR") global CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING = [ diff --git a/ush/setup.py b/ush/setup.py index 1bdf2453a8..77c09d7a13 100644 --- a/ush/setup.py +++ b/ush/setup.py @@ -19,7 +19,6 @@ flatten_dict, update_dict, import_vars, - export_vars, get_env_var, load_config_file, cfg_to_shell_str, @@ -53,7 +52,7 @@ def setup(): Args: None Returns: - None + Dictionary of settings """ logger = getLogger(__name__) @@ -61,9 +60,6 @@ def setup(): USHdir = os.path.dirname(os.path.abspath(__file__)) cd_vrfy(USHdir) - # import all environment variables - import_vars() - # print message log_info( f""" @@ -210,10 +206,12 @@ def get_location(xcs, fmt): os.path.join(USHdir, os.pardir, "parm", "fixed_files_mapping.yaml") ) import_vars(dictionary=flatten_dict(cfg_f)) + cfg_d.update(cfg_f) # Load constants file and save its contents to a variable for later cfg_c = load_config_file(os.path.join(USHdir, CONSTANTS_FN)) import_vars(dictionary=flatten_dict(cfg_c)) + cfg_d.update(cfg_c) # # ----------------------------------------------------------------------- @@ -236,13 +234,17 @@ def get_location(xcs, fmt): # # ----------------------------------------------------------------------- # - # export env vars before calling another module - export_vars() if PREDEF_GRID_NAME: - set_predef_grid_params() - - import_vars() + params_dict = set_predef_grid_params( + PREDEF_GRID_NAME, + QUILTING, + DT_ATMOS, + LAYOUT_X, + LAYOUT_Y, + BLOCKSIZE, + ) + import_vars(dictionary=params_dict) # # ----------------------------------------------------------------------- @@ -847,37 +849,46 @@ def get_location(xcs, fmt): global POST_OUTPUT_DOMAIN_NAME global COMIN_BASEDIR, COMOUT_BASEDIR - global OPSROOT, COMROOT, PACKAGEROOT, DATAROOT, DCOMROOT, DBNROOT + global OPSROOT, COMROOT, PACKAGEROOT, DATAROOT, DCOMROOT, DBNROOT, EXTROOT global SENDECF, SENDDBN, SENDDBN_NTC, SENDCOM, SENDWEB global KEEPDATA, MAILTO, MAILCC + # Stuff to import from parent shell environment + IMPORTS = [ + "OPSROOT", + "COMROOT", + "PACKAGEROOT", + "DATAROOT", + "DCOMROOT", + "DBNROOT", + "SENDECF", + "SENDDBN", + "SENDDBN_NTC", + "SENDCOM", + "SENDWEB", + "KEEPDATA", + "MAILTO", + "MAILCC", + ] + import_vars(env_vars=IMPORTS) + # Main directory locations if RUN_ENVIR == "nco": - try: - OPSROOT = ( - os.path.abspath(f"{EXPT_BASEDIR}{os.sep}..{os.sep}nco_dirs") - if OPSROOT is None - else OPSROOT - ) - except NameError: - OPSROOT = EXPTDIR - try: - COMROOT - except NameError: + OPSROOT = ( + os.path.abspath(f"{EXPT_BASEDIR}{os.sep}..{os.sep}nco_dirs") + if OPSROOT is None + else OPSROOT + ) + if COMROOT is None: COMROOT = os.path.join(OPSROOT, "com") - try: - PACKAGEROOT - except NameError: + if PACKAGEROOT is None: PACKAGEROOT = os.path.join(OPSROOT, "packages") - try: - DATAROOT - except NameError: + if DATAROOT is None: DATAROOT = os.path.join(OPSROOT, "tmp") - try: - DCOMROOT - except NameError: + if DCOMROOT is None: DCOMROOT = os.path.join(OPSROOT, "dcom") + EXTROOT = os.path.join(OPSROOT, "ext") COMIN_BASEDIR = os.path.join(COMROOT, NET, model_ver) COMOUT_BASEDIR = os.path.join(COMROOT, NET, model_ver) @@ -893,45 +904,24 @@ def get_location(xcs, fmt): PACKAGEROOT = EXPTDIR DATAROOT = EXPTDIR DCOMROOT = EXPTDIR + EXTROOT = EXPTDIR LOGDIR = os.path.join(EXPTDIR, "log") - try: - DBNROOT - except NameError: + if DBNROOT is None: DBNROOT = None - try: - SENDECF - except NameError: + if SENDECF is None: SENDECF = False - try: - SENDDBN - except NameError: + if SENDDBN is None: SENDDBN = False - try: - SENDDBN_NTC - except NameError: + if SENDDBN_NTC is None: SENDDBN_NTC = False - try: - SENDCOM - except NameError: + if SENDCOM is None: SENDCOM = False - try: - SENDWEB - except NameError: + if SENDWEB is None: SENDWEB = False - try: - KEEPDATA - except NameError: + if KEEPDATA is None: KEEPDATA = True - try: - MAILTO - except NameError: - MAILTO = None - try: - MAILCC - except NameError: - MAILCC = None # create NCO directories if RUN_ENVIR == "nco": @@ -940,6 +930,7 @@ def get_location(xcs, fmt): mkdir_vrfy(f" -p '{PACKAGEROOT}'") mkdir_vrfy(f" -p '{DATAROOT}'") mkdir_vrfy(f" -p '{DCOMROOT}'") + mkdir_vrfy(f" -p '{EXTROOT}'") if DBNROOT is not None: mkdir_vrfy(f" -p '{DBNROOT}'") @@ -1420,6 +1411,8 @@ def get_location(xcs, fmt): iend_of_t7_on_t6g=GFDLgrid_IEND_OF_RGNL_DOM_ON_T6G, jstart_of_t7_on_t6g=GFDLgrid_JSTART_OF_RGNL_DOM_ON_T6G, jend_of_t7_on_t6g=GFDLgrid_JEND_OF_RGNL_DOM_ON_T6G, + RUN_ENVIR=RUN_ENVIR, + VERBOSE=VERBOSE, ) # # ----------------------------------------------------------------------- @@ -1461,6 +1454,9 @@ def get_location(xcs, fmt): grid_params[k] for k in ["LON_CTR", "LAT_CTR", "NX", "NY", "NHW", "STRETCH_FAC"] ) + # grid params + cfg_d["grid_params"] = grid_params + # # ----------------------------------------------------------------------- # @@ -1496,14 +1492,11 @@ def get_location(xcs, fmt): # ----------------------------------------------------------------------- # - # export env vars - export_vars() - # link fix files res_in_grid_fns = "" if not RUN_TASK_MAKE_GRID: - res_in_grid_fns = link_fix(verbose=VERBOSE, file_group="grid") + res_in_grid_fns = link_fix(globals(), file_group="grid") RES_IN_FIXLAM_FILENAMES = res_in_grid_fns # @@ -1518,7 +1511,7 @@ def get_location(xcs, fmt): res_in_orog_fns = "" if not RUN_TASK_MAKE_OROG: - res_in_orog_fns = link_fix(verbose=VERBOSE, file_group="orog") + res_in_orog_fns = link_fix(globals(), file_group="orog") if not RES_IN_FIXLAM_FILENAMES and (res_in_orog_fns != RES_IN_FIXLAM_FILENAMES): raise Exception( @@ -1544,7 +1537,7 @@ def get_location(xcs, fmt): res_in_sfc_climo_fns = "" if not RUN_TASK_MAKE_SFC_CLIMO: - res_in_sfc_climo_fns = link_fix(verbose=VERBOSE, file_group="sfc_climo") + res_in_sfc_climo_fns = link_fix(globals(), file_group="sfc_climo") if RES_IN_FIXLAM_FILENAMES and res_in_sfc_climo_fns != RES_IN_FIXLAM_FILENAMES: raise Exception( @@ -1677,6 +1670,9 @@ def get_location(xcs, fmt): # ----------------------------------------------------------------------- # SDF_USES_THOMPSON_MP = set_thompson_mp_fix_files( + EXTRN_MDL_NAME_ICS, + EXTRN_MDL_NAME_LBCS, + CCPP_PHYS_SUITE, CCPP_PHYS_SUITE_IN_CCPP_FP, THOMPSON_MP_CLIMO_FN, CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING, @@ -1687,18 +1683,6 @@ def get_location(xcs, fmt): global GLOBAL_VAR_DEFNS_FP GLOBAL_VAR_DEFNS_FP = os.path.join(EXPTDIR, GLOBAL_VAR_DEFNS_FN) - # fixed files section - cfg_d.update(cfg_f) - - # update dictionary with globals() values - update_dict(globals(), cfg_d) - - # constants section - cfg_d.update(cfg_c) - - # grid params - cfg_d["grid_params"] = grid_params - # # ----------------------------------------------------------------------- # @@ -1897,6 +1881,7 @@ def get_location(xcs, fmt): "DATAROOT": DATAROOT, "DCOMROOT": DCOMROOT, "DBNROOT": DBNROOT, + "EXTROOT": EXTROOT, "SENDECF": SENDECF, "SENDDBN": SENDDBN, "SENDDBN_NTC": SENDDBN_NTC, @@ -1916,6 +1901,9 @@ def get_location(xcs, fmt): # ----------------------------------------------------------------------- # + # update dictionary with globals() values + update_dict(globals(), cfg_d) + # print content of var_defns if DEBUG=True all_lines = cfg_to_yaml_str(cfg_d) log_info(all_lines, verbose=DEBUG) @@ -1935,9 +1923,6 @@ def get_location(xcs, fmt): with open(GLOBAL_VAR_DEFNS_FP, "a") as f: f.write(cfg_to_shell_str(cfg_d)) - # export all global variables back to the environment - export_vars() - # # ----------------------------------------------------------------------- # @@ -1961,6 +1946,10 @@ def get_location(xcs, fmt): {k} = {cfg_v[vkey]}""" ) + # add LOGDIR and return flat dict + cfg_d.update({"LOGDIR": LOGDIR}) + return cfg_d + # # ----------------------------------------------------------------------- diff --git a/versions/build.ver.wcoss2 b/versions/build.ver.wcoss2 index 9a89f97716..5d9b42c82a 100644 --- a/versions/build.ver.wcoss2 +++ b/versions/build.ver.wcoss2 @@ -1,7 +1,6 @@ #!/bin/bash export module_ver=8.5.2 -export gfs_ver=v16.2 export envvar_ver=1.0 export PrgEnv_intel_ver=8.1.0 diff --git a/versions/run.ver.wcoss2 b/versions/run.ver.wcoss2 index acdfffdf6d..6a06331a85 100644 --- a/versions/run.ver.wcoss2 +++ b/versions/run.ver.wcoss2 @@ -3,3 +3,10 @@ export intel_ver=19.1.3.304 export python_ver=3.8.6 export rocoto_ver=1.3.5 + +export gfs_ver=v16.2 +export nam_ver=v4.2 +export rap_ver=v5.1 +export gsmgfs_ver=v16.2 +export hrrr_ver=v3 +export prod_util_ver=2.0.14 From 04fd9c652090bc1139b1a4a6b1201b4f424b17d9 Mon Sep 17 00:00:00 2001 From: "Chan-Hoo.Jeon-NOAA" <60152248+chan-hoo@users.noreply.github.com> Date: Wed, 9 Nov 2022 10:44:24 -0500 Subject: [PATCH 18/45] Fix time offset issue on ICS with GFS nemsio and netcdf files and add new archive file name on HPSS (#457) * fix time offset with gfs * add new archive file name and we2e test * add ics_or_lbcs to test_retrieve.py * Add check availability of nemsio and netcdf * Copy file_templates dict before modifying it. * remove native from xml for dev_transfer on wcoss2 * correct data locations on wcoss2 * remove met_verification from fundamental.cheyenne.gnu * replace cyc to hh in data locations * make lbcs condition general Co-authored-by: Daniel Abdi --- jobs/JREGIONAL_GET_EXTRN_MDL_FILES | 26 +++++++++++------ parm/FV3LAM_wflow.xml | 4 +++ parm/data_locations.yml | 7 +++++ scripts/exregional_get_extrn_mdl_files.sh | 1 + .../machine_suites/fundamental.cheyenne.gnu | 1 - ..._lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml | 28 +++++++++++++++++++ ush/machine/wcoss2.yaml | 4 +-- ush/retrieve_data.py | 17 +++++++++++ ush/test_retrieve_data.py | 10 +++++++ 9 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml diff --git a/jobs/JREGIONAL_GET_EXTRN_MDL_FILES b/jobs/JREGIONAL_GET_EXTRN_MDL_FILES index 1c07956433..c75c709b2a 100755 --- a/jobs/JREGIONAL_GET_EXTRN_MDL_FILES +++ b/jobs/JREGIONAL_GET_EXTRN_MDL_FILES @@ -93,10 +93,11 @@ check_var_valid_value "ICS_OR_LBCS" "valid_vals_ICS_OR_LBCS" if [ "${ICS_OR_LBCS}" = "ICS" ]; then export TIME_OFFSET_HRS=${EXTRN_MDL_ICS_OFFSET_HRS:-0} export EXTRN_MDL_NAME=${EXTRN_MDL_NAME_ICS} - + GFS_FILE_FMT=${FV3GFS_FILE_FMT_ICS} elif [ "${ICS_OR_LBCS}" = "LBCS" ]; then export TIME_OFFSET_HRS=${EXTRN_MDL_LBCS_OFFSET_HRS:-0} export EXTRN_MDL_NAME=${EXTRN_MDL_NAME_LBCS} + GFS_FILE_FMT=${FV3GFS_FILE_FMT_LBCS} fi # @@ -159,10 +160,10 @@ case ${EXTRN_MDL_NAME} in # The transition date from the GSMGFS to the FV3GFS was 2019061212, i.e. # this was the first official forecast with the FV3GFS. So we set the # last CDATE for the GSMGFS to the one 6 hours before this. - cdate_max="2019061206" - if [ "$EXTRN_MDL_CDATE" -gt "$cdate_max" ]; then + CDATE_max="2019061206" + if [ "$EXTRN_MDL_CDATE" -gt "$CDATE_max" ]; then print_err_msg_exit "\ - $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $cdate_max max)" + $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $CDATE_max max)" fi ;; @@ -171,11 +172,20 @@ case ${EXTRN_MDL_NAME} in # this was the first official forecast with the FV3GFS. However, paral- # lel runs with the FV3GFS go back to 2018121500. So we set the first # EXTRN_MDL_CDATE for the FV3GFS to this date and time. -# CDATE_min="2019061212" CDATE_min="2018121500" + CDATE_min_netcdf="2021032100" + CDATE_max_nemsio="2021032018" if [ "$EXTRN_MDL_CDATE" -lt "$CDATE_min" ]; then print_err_msg_exit "\ - $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $cdate_min min)" + $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $CDATE_min min)" + elif [ "${GFS_FILE_FMT}" = "netcdf" ] && [ "${EXTRN_MDL_CDATE}" -lt "${CDATE_min_netcdf}" ]; then + print_err_msg_exit "\ + NETCDF is not available for this date:: However, NEMSIO is available:: \ + $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $CDATE_min_netcdf min)" + elif [ "${GFS_FILE_FMT}" = "nemsio" ] && [ "${EXTRN_MDL_CDATE}" -gt "${CDATE_max_nemsio}" ]; then + print_err_msg_exit "\ + NEMSIO is not available for this date:: However, NETCDF is available:: \ + $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $CDATE_max_nemsio max)" fi ;; @@ -185,7 +195,7 @@ case ${EXTRN_MDL_NAME} in CDATE_min="2015070100" if [ "$EXTRN_MDL_CDATE" -lt "$CDATE_min" ]; then print_err_msg_exit "\ - $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $cdate_min min)" + $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $CDATE_min min)" fi ;; @@ -196,7 +206,7 @@ case ${EXTRN_MDL_NAME} in CDATE_min="2014103000" if [ "$EXTRN_MDL_CDATE" -lt "$CDATE_min" ]; then print_err_msg_exit "\ - $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $cdate_min min)" + $(data_unavailable $EXTRN_MDL_NAME $EXTRN_MDL_CDATE $CDATE_min min)" fi ;; diff --git a/parm/FV3LAM_wflow.xml b/parm/FV3LAM_wflow.xml index 622e0b42d6..97d2f1a700 100644 --- a/parm/FV3LAM_wflow.xml +++ b/parm/FV3LAM_wflow.xml @@ -307,7 +307,9 @@ MODULES_RUN_TASK_FP script. {%- endif %} {{ wtime_get_extrn_ics }} &NCORES_PER_NODE; + {%- if machine not in ["WCOSS2"] %} &SCHED_NATIVE_CMD; + {%- endif %} &GET_EXTRN_ICS_TN; &LOGDIR;/&GET_EXTRN_ICS_TN;_@Y@m@d@H&LOGEXT; @@ -335,7 +337,9 @@ MODULES_RUN_TASK_FP script. {%- endif %} {{ wtime_get_extrn_lbcs }} &NCORES_PER_NODE; + {%- if machine not in ["WCOSS2"] %} &SCHED_NATIVE_CMD; + {%- endif %} &GET_EXTRN_LBCS_TN; &LOGDIR;/&GET_EXTRN_LBCS_TN;_@Y@m@d@H&LOGEXT; diff --git a/parm/data_locations.yml b/parm/data_locations.yml index 067708f99f..8297ac975a 100644 --- a/parm/data_locations.yml +++ b/parm/data_locations.yml @@ -64,17 +64,20 @@ FV3GFS: - gfs.t{hh}z.sfcanl.nemsio fcst: - gfs.t{hh}z.atmf{fcst_hr:03d}.nemsio + - gfs.t{hh}z.sfcf{fcst_hr:03d}.nemsio netcdf: anl: - gfs.t{hh}z.atmanl.nc - gfs.t{hh}z.sfcanl.nc fcst: - gfs.t{hh}z.atmf{fcst_hr:03d}.nc + - gfs.t{hh}z.sfcf{fcst_hr:03d}.nc hpss: protocol: htar archive_path: - /NCEPPROD/hpssprod/runhistory/rh{yyyy}/{yyyymm}/{yyyymmdd} - /NCEPPROD/hpssprod/runhistory/rh{yyyy}/{yyyymm}/{yyyymmdd} + - /NCEPPROD/hpssprod/runhistory/rh{yyyy}/{yyyymm}/{yyyymmdd} archive_internal_dir: - ./gfs.{yyyymmdd}/{hh} - ./gfs.{yyyymmdd}/{hh}/atmos @@ -83,9 +86,11 @@ FV3GFS: anl: - gpfs_dell1_nco_ops_com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_pgrb2.tar - com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_pgrb2.tar + - com_gfs_v16.2_gfs.{yyyymmdd}_{hh}.gfs_pgrb2.tar fcst: - gpfs_dell1_nco_ops_com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_pgrb2.tar - com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_pgrb2.tar + - com_gfs_v16.2_gfs.{yyyymmdd}_{hh}.gfs_pgrb2.tar nemsio: anl: - gpfs_dell1_nco_ops_com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_nemsioa.tar @@ -97,9 +102,11 @@ FV3GFS: anl: - gpfs_dell1_nco_ops_com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_nca.tar - com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_nca.tar + - com_gfs_v16.2_gfs.{yyyymmdd}_{hh}.gfs_nca.tar fcst: - ['gpfs_dell1_nco_ops_com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_nca.tar', 'gpfs_dell1_nco_ops_com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_ncb.tar'] - ['com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_nca.tar', 'com_gfs_prod_gfs.{yyyymmdd}_{hh}.gfs_ncb.tar'] + - ['com_gfs_v16.2_gfs.{yyyymmdd}_{hh}.gfs_nca.tar', 'com_gfs_v16.2_gfs.{yyyymmdd}_{hh}.gfs_ncb.tar'] file_names: <<: *gfs_file_names aws: diff --git a/scripts/exregional_get_extrn_mdl_files.sh b/scripts/exregional_get_extrn_mdl_files.sh index 824d2b4fdc..6a7eaa90b2 100755 --- a/scripts/exregional_get_extrn_mdl_files.sh +++ b/scripts/exregional_get_extrn_mdl_files.sh @@ -154,6 +154,7 @@ python3 -u ${USHdir}/retrieve_data.py \ --data_stores ${data_stores} \ --external_model ${EXTRN_MDL_NAME} \ --fcst_hrs ${fcst_hrs[@]} \ + --ics_or_lbcs ${ICS_OR_LBCS} \ --output_path ${EXTRN_MDL_STAGING_DIR} \ --summary_file ${EXTRN_DEFNS} \ $additional_flags" diff --git a/tests/WE2E/machine_suites/fundamental.cheyenne.gnu b/tests/WE2E/machine_suites/fundamental.cheyenne.gnu index f269650e98..5cb49719b6 100644 --- a/tests/WE2E/machine_suites/fundamental.cheyenne.gnu +++ b/tests/WE2E/machine_suites/fundamental.cheyenne.gnu @@ -1,4 +1,3 @@ -MET_verification grid_CONUS_25km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16 grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml new file mode 100644 index 0000000000..bbfb59f8c5 --- /dev/null +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml @@ -0,0 +1,28 @@ +metadata: + description: |- + This test is to ensure that the workflow running in nco mode completes + successfully on the RRFS_CONUS_25km grid using the FV3_GFS_v16 physics + suite with time-offset ICs/LBCs derived from the FV3GFS. +user: + RUN_ENVIR: nco +workflow: + CCPP_PHYS_SUITE: FV3_GFS_v16 + DATE_FIRST_CYCL: '2022081012' + DATE_LAST_CYCL: '2022081012' + FCST_LEN_HRS: 6 + PREEXISTING_DIR_METHOD: rename +workflow_switches: + RUN_TASK_MAKE_GRID: false + RUN_TASK_MAKE_OROG: false + RUN_TASK_MAKE_SFC_CLIMO: false +task_get_extrn_ics: + EXTRN_MDL_NAME_ICS: FV3GFS + FV3GFS_FILE_FMT_ICS: netcdf + EXTRN_MDL_ICS_OFFSET_HRS: 6 +task_get_extrn_lbcs: + EXTRN_MDL_NAME_LBCS: FV3GFS + FV3GFS_FILE_FMT_LBCS: netcdf + LBC_SPEC_INTVL_HRS: 3 + EXTRN_MDL_LBCS_OFFSET_HRS: 6 +task_run_fcst: + PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/ush/machine/wcoss2.yaml b/ush/machine/wcoss2.yaml index 4ed9ab7e3d..4a9bfcab50 100644 --- a/ush/machine/wcoss2.yaml +++ b/ush/machine/wcoss2.yaml @@ -34,8 +34,8 @@ task_run_fcst: FIXlut: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_lut data: GSMGFS: compath.py ${envir}/gsmgfs/${gsmgfs_ver}/gsmgfs.${PDY} - FV3GFS: compath.py ${envir}/gfs/${gfs_ver}/gfs.${PDY} + FV3GFS: compath.py ${envir}/gfs/${gfs_ver}/gfs.${PDY}/${hh}/atmos RAP: compath.py ${envir}/rap/${rap_ver}/rap.${PDY} NAM: compath.py ${envir}/nam/${nam_ver}/nam.${PDY} - HRRR: compath.py ${envir}/hrrr/${hrrr_ver}/hrrr.${PDY} + HRRR: compath.py ${envir}/hrrr/${hrrr_ver}/hrrr.${PDY}/conus diff --git a/ush/retrieve_data.py b/ush/retrieve_data.py index a0d7326832..e6ad879fbc 100755 --- a/ush/retrieve_data.py +++ b/ush/retrieve_data.py @@ -34,6 +34,7 @@ import sys from textwrap import dedent import time +from copy import deepcopy import yaml @@ -289,6 +290,16 @@ def get_file_templates(cla, known_data_info, data_store, use_cla_tmpl=False): """ file_templates = known_data_info.get(data_store, {}).get("file_names") + file_templates = deepcopy(file_templates) + + # Remove sfc files from fcst in file_names of external models for LBCs + # sfc files needed in fcst when time_offset is not zero. + if cla.ics_or_lbcs == "LBCS": + for format in ['netcdf', 'nemsio']: + for i, tmpl in enumerate(file_templates.get(format, {}).get('fcst', [])): + if "sfc" in tmpl: + del file_templates[format]['fcst'][i] + if use_cla_tmpl: file_templates = cla.file_templates if cla.file_templates else file_templates @@ -946,6 +957,12 @@ def parse_args(argv): required=True, type=os.path.abspath, ) + parser.add_argument( + "--ics_or_lbcs", + choices=("ICS", "LBCS"), + help="Flag for whether ICS or LBCS.", + required=True, + ) # Optional parser.add_argument( diff --git a/ush/test_retrieve_data.py b/ush/test_retrieve_data.py index dffa638562..e35eac2dad 100644 --- a/ush/test_retrieve_data.py +++ b/ush/test_retrieve_data.py @@ -48,6 +48,7 @@ def test_fv3gfs_grib2_lbcs_from_hpss(self): '--external_model', 'FV3GFS', '--fcst_hrs', '6', '12', '3', '--output_path', tmp_dir, + '--ics_or_lbcs', 'LBCS', '--debug', '--file_type', 'grib2', ] @@ -80,6 +81,7 @@ def test_fv3gfs_netcdf_lbcs_from_hpss(self): '--external_model', 'FV3GFS', '--fcst_hrs', '24', '48', '24', '--output_path', tmp_dir, + '--ics_or_lbcs', 'LBCS', '--debug', '--file_type', 'netcdf', ] @@ -112,6 +114,7 @@ def test_gdas_ics_from_aws(self): '--external_model', 'GDAS', '--fcst_hrs', '6', '9', '3', '--output_path', out_path_tmpl, + '--ics_or_lbcs', 'LBCS', '--debug', '--file_type', 'netcdf', '--members', '9', '10', @@ -147,6 +150,7 @@ def test_gefs_grib2_ics_from_aws(self): '--external_model', 'GEFS', '--fcst_hrs', '6', '--output_path', out_path_tmpl, + '--ics_or_lbcs', 'ICS', '--debug', '--file_type', 'netcdf', '--members', '1', '2', @@ -180,6 +184,7 @@ def test_hrrr_ics_from_hpss(self): '--external_model', 'HRRR', '--fcst_hrs', '0', '--output_path', tmp_dir, + '--ics_or_lbcs', 'ICS', '--debug', ] # fmt: on @@ -209,6 +214,7 @@ def test_hrrr_lbcs_from_hpss(self): '--external_model', 'HRRR', '--fcst_hrs', '3', '24', '3', '--output_path', tmp_dir, + '--ics_or_lbcs', 'LBCS', '--debug', ] # fmt: on @@ -237,6 +243,7 @@ def test_hrrr_ics_from_aws(self): '--external_model', 'HRRR', '--fcst_hrs', '0', '--output_path', tmp_dir, + '--ics_or_lbcs', 'ICS', '--debug', ] # fmt: on @@ -265,6 +272,7 @@ def test_hrrr_lbcs_from_aws(self): '--external_model', 'HRRR', '--fcst_hrs', '3', '24', '3', '--output_path', tmp_dir, + '--ics_or_lbcs', 'LBCS', '--debug', ] # fmt: on @@ -294,6 +302,7 @@ def test_rap_ics_from_aws(self): '--external_model', 'RAP', '--fcst_hrs', '3', '--output_path', tmp_dir, + '--ics_or_lbcs', 'ICS', '--debug', ] # fmt: on @@ -323,6 +332,7 @@ def test_rap_lbcs_from_aws(self): '--external_model', 'RAP', '--fcst_hrs', '3', '30', '6', '--output_path', tmp_dir, + '--ics_or_lbcs', 'LBCS', '--debug', ] # fmt: on From 50008bad919950861af7d50b5856e9d7701c1118 Mon Sep 17 00:00:00 2001 From: danielabdi-noaa <52012304+danielabdi-noaa@users.noreply.github.com> Date: Wed, 9 Nov 2022 12:08:18 -0700 Subject: [PATCH 19/45] Minor bug fixes (#459) * Bug fix forecast directory deletion. * Bug fix in build only mode. * Remove unused sample.nc * Make setup_WE2E work irrespective of conda activation. * Fix the bug fix. --- scripts/exregional_run_post.sh | 3 ++- sorc/CMakeLists.txt | 2 +- tests/WE2E/setup_WE2E_tests.sh | 3 ++- ush/python_utils/test_data/sample.nc | Bin 10824 -> 0 bytes ush/setup.py | 2 -- 5 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 ush/python_utils/test_data/sample.nc diff --git a/scripts/exregional_run_post.sh b/scripts/exregional_run_post.sh index 1a51dedf0f..2b950a9421 100755 --- a/scripts/exregional_run_post.sh +++ b/scripts/exregional_run_post.sh @@ -293,7 +293,8 @@ done rm_vrfy -rf ${DATA_FHR} # Delete the forecast directory -if [ $RUN_ENVIR = "nco" ] && [ $KEEPDATA = "FALSE" ]; then +fhr_l=$(printf "%03d" $FCST_LEN_HRS) +if [ $RUN_ENVIR = "nco" ] && [ $KEEPDATA = "FALSE" ] && [ $fhr = $fhr_l ]; then rm -rf $DATAFCST fi # diff --git a/sorc/CMakeLists.txt b/sorc/CMakeLists.txt index 1028fc87e9..33e44d6f90 100644 --- a/sorc/CMakeLists.txt +++ b/sorc/CMakeLists.txt @@ -35,7 +35,7 @@ endif() # Build UFS weather model if (BUILD_UFS) - list(APPEND TARGET_LIST UFS) + list(APPEND TARGET_LIST ufs-weather-model) if(NOT CCPP_SUITES) set(CCPP_SUITES "FV3_GFS_2017_gfdlmp,FV3_GFS_2017_gfdlmp_regional,FV3_GFS_v15p2,FV3_GFS_v16,FV3_RRFS_v1beta,FV3_HRRR,FV3_GFS_v15_thompson_mynn_lam3km") diff --git a/tests/WE2E/setup_WE2E_tests.sh b/tests/WE2E/setup_WE2E_tests.sh index 823829304d..ec94948e51 100755 --- a/tests/WE2E/setup_WE2E_tests.sh +++ b/tests/WE2E/setup_WE2E_tests.sh @@ -1,4 +1,5 @@ -#!/bin/bash -l +#!/usr/bin/env bash +[ -n "$HOME" ] && exec -c "$0" "$@" #---------------------------------------------------------------------- # Wrapper for the automation of UFS Short Range Weather App Workflow diff --git a/ush/python_utils/test_data/sample.nc b/ush/python_utils/test_data/sample.nc deleted file mode 100644 index 9e31e16a3d622e35de5e5f753c96dd95ae118665..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10824 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 Date: Thu, 10 Nov 2022 12:30:06 -0500 Subject: [PATCH 20/45] [develop] Added return code to srw_build.sh script. (#461) * [develop] Added return code to srw_build.sh script. * Correct issue in sorc/CMakeLists.txt so that the ufs-model will build again. * Restore PID functionality in tests/build.sh for GitHub Actions autoci builds. * Add return code to tests/build.sh and read the code in srw_build.sh. --- .cicd/scripts/srw_build.sh | 4 ++++ tests/build.sh | 3 +++ 2 files changed, 7 insertions(+) diff --git a/.cicd/scripts/srw_build.sh b/.cicd/scripts/srw_build.sh index c8a4943238..10327366f0 100755 --- a/.cicd/scripts/srw_build.sh +++ b/.cicd/scripts/srw_build.sh @@ -26,7 +26,10 @@ fi # Build and install cd ${workspace}/tests +set +e ./build.sh ${platform} ${SRW_COMPILER} +build_exit=$? +set -e cd - # Create combined log file for upload to s3 @@ -34,3 +37,4 @@ build_dir="${workspace}/build_${SRW_COMPILER}" cat ${build_dir}/log.cmake ${build_dir}/log.make \ >${build_dir}/srw_build-${platform}-${SRW_COMPILER}.log +exit $build_exit diff --git a/tests/build.sh b/tests/build.sh index 461e87067a..01248c80f2 100755 --- a/tests/build.sh +++ b/tests/build.sh @@ -159,3 +159,6 @@ else msg="PASS" fi echo "$msg" >> ${TEST_OUTPUT} +if [[ $n_fail -gt 0 ]]; then + exit 1 +fi From 5356d1e217e1bc1a139d2127dd3e9317b6cb651a Mon Sep 17 00:00:00 2001 From: Natalie Perlin <68030316+natalie-perlin@users.noreply.github.com> Date: Fri, 11 Nov 2022 11:15:35 -0500 Subject: [PATCH 21/45] Updates for building and running on MacOS (x86_64 and M1) (#467) * Update build_macos_gnu.lua architecture-independent method * Update build_macos_gnu.lua * Update wflow_macos.lua use conda environment and conda activate command * Update lmod-setup.sh updates for MacOS * Update lmod-setup.csh updates for MacOS * Update wflow_macos.lua updated for MacOS --- etc/lmod-setup.csh | 5 +-- etc/lmod-setup.sh | 5 +-- modulefiles/build_macos_gnu.lua | 61 +++++++++------------------------ modulefiles/wflow_macos.lua | 17 ++++----- 4 files changed, 28 insertions(+), 60 deletions(-) diff --git a/etc/lmod-setup.csh b/etc/lmod-setup.csh index c8e1fc5ae2..69cffe5e12 100644 --- a/etc/lmod-setup.csh +++ b/etc/lmod-setup.csh @@ -16,8 +16,9 @@ endif source /etc/csh.login if ( "$L_MACHINE" == macos ) then - set ENV="/opt/homebrew/opt/lmod/init/csh" - # setenv ENV "/usr/local/opt/lmod/init/csh" + arch=$(uname -m) + [[ "$arch" = arm64 ]] && export ENV="/opt/homebrew/opt/lmod/init/csh" + [[ "$arch" = x86_64 ]] && export ENV="/usr/local/opt/lmod/init/csh" source $ENV module purge diff --git a/etc/lmod-setup.sh b/etc/lmod-setup.sh index 91e9228a9f..324868afce 100644 --- a/etc/lmod-setup.sh +++ b/etc/lmod-setup.sh @@ -23,8 +23,9 @@ $has_mu && set -u $has_me && set -e if [ "$L_MACHINE" = macos ]; then - export BASH_ENV="/opt/homebrew/opt/lmod/init/bash" - # export BASH_ENV="/usr/local/opt/lmod/init/bash" + arch=$(uname -m) + [[ "$arch" = arm64 ]] && export BASH_ENV="/opt/homebrew/opt/lmod/init/bash" + [[ "$arch" = x86_64 ]] && export BASH_ENV="/usr/local/opt/lmod/init/bash" source $BASH_ENV module purge diff --git a/modulefiles/build_macos_gnu.lua b/modulefiles/build_macos_gnu.lua index e964a26099..d92de9a4da 100644 --- a/modulefiles/build_macos_gnu.lua +++ b/modulefiles/build_macos_gnu.lua @@ -1,8 +1,6 @@ help([[ -This module needs to be customized for the user's Linux environment: +This module needs to be customized for the user's MacOS environment: specify compilers, path for HPC-stack, load the modules, set compiler and linker flags - Option 1: M1/arm64 platform, OS BigSur, Monterey (Darwin 20,21) - Option 2: Intel/x86_64 platform, OS Catalina (Darwin 19) ]]) whatis([===[Loads libraries needed for building the UFS SRW App on macos ]===]) @@ -23,48 +21,21 @@ load("hpc-gnu") load("openmpi") load("hpc-openmpi") -load("jasper/2.0.25") -load("zlib/1.2.11") - -load("hdf5/1.10.6") -load("netcdf/4.7.4") -load("pio/2.5.3") -load("esmf/8.3.0b09") -load("fms/2022.01") - -load("bacio/2.4.1") -load("crtm/2.3.0") -load("g2/3.4.3") -load("g2tmpl/1.10.0") -load("ip/3.3.3") -load("sp/2.3.3") -load("w3nco/2.4.1") -load("upp/10.0.10") - -load("gftl-shared/1.3.3") -load("yafyaml/0.5.1") -load("mapl/2.12.2-esmf-8.3.0b09") -load("gfsio/1.4.1") -load("landsfcutil/2.4.1") -load("nemsio/2.5.4") -load("nemsiogfs/2.5.3") -load("sfcio/1.4.1") -load("sigio/2.3.2") -load("w3emc/2.9.2") -load("wgrib2/2.0.8") - --- Option 1 compiler paths: -setenv("CC", "/opt/homebrew/bin/gcc") -setenv("FC", "/opt/homebrew/bin/gfortran") -setenv("CXX", "/opt/homebrew/bin/g++") - --- Option 2 compiler paths: ---[[ -setenv("CC", "/usr/local/bin/gcc") -setenv("FC", "/usr/local/bin/gfortran") -setenv("CXX", "/usr/local/bin/g++") ---]] --- +load("srw_common") + +-- MacOS with arm64 architecture: `uname -m` expands to arm64 +-- MacOS with Intel architecture: `uname -m` expands to x86_64 +local arch = 'eval $(uname -m)' +if (arch == "arm64") then + setenv("CC", "/opt/homebrew/bin/gcc") + setenv("FC", "/opt/homebrew/bin/gfortran") + setenv("CXX", "/opt/homebrew/bin/g++") +else + setenv("CC", "/usr/local/bin/gcc") + setenv("FC", "/usr/local/bin/gfortran") + setenv("CXX", "/usr/local/bin/g++") +end + -- Set MPI compilers depending on the MPI libraries built: local MPI_CC="mpicc" local MPI_CXX="mpicxx" diff --git a/modulefiles/wflow_macos.lua b/modulefiles/wflow_macos.lua index d1425197ad..769f1bc05e 100644 --- a/modulefiles/wflow_macos.lua +++ b/modulefiles/wflow_macos.lua @@ -1,11 +1,11 @@ help([[ -This module activates python environement for running the UFS SRW App on general macOS +This module set a path needed to activate conda environement for running UFS SRW App on general macOS ]]) -whatis([===[This module activates python environment for running the UFS SRW App on macOS]===]) +whatis([===[This module activates conda environment for running the UFS SRW App on macOS]===]) setenv("CMAKE_Platform", "macos") -setenv("VENV", pathJoin(os.getenv("HOME"), "venv/regional_workflow")) +setenv("VENV", pathJoin(os.getenv("HOME"), "condaenv/envs/regional_workflow")) --[[ local ROCOTOmod="/Users/username/modules" @@ -14,13 +14,8 @@ load(rocoto) --]] if mode() == "load" then - LmodMsgRaw([===[Verify the Python virtual environment path \$VENV shown below is correct, " -set to the correct path otherwise: " -VENV=$env(VENV) " -Please do the following to activate python virtual environment: - > source \$VENV/bin/activate " + LmodMsgRaw([===[Please do the following to activate conda virtual environment: + > conda activate $VENV " ]===]) end -if mode() == "unload" then - execute{cmd="deactivate", modeA={"unload"}} -end + From b839658fec9240b8e20d8ace2a70162219ed7906 Mon Sep 17 00:00:00 2001 From: Natalie Perlin <68030316+natalie-perlin@users.noreply.github.com> Date: Mon, 14 Nov 2022 09:16:50 -0500 Subject: [PATCH 22/45] [develop] Patch to correct a variable name to a lower-case (#468) * Update plot_allvars.py Updating a variable name "Geopotential Height" to "Geopotential height". Lower-case is needed for it to work with a newer Python. * Update plot_allvars_diff.py Updating a variable name "Geopotential Height" to "Geopotential height" (lower-case). This is needed to work with newer Python --- ush/Python/plot_allvars.py | 2 +- ush/Python/plot_allvars_diff.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ush/Python/plot_allvars.py b/ush/Python/plot_allvars.py index 3af564e522..87a38ab0e1 100755 --- a/ush/Python/plot_allvars.py +++ b/ush/Python/plot_allvars.py @@ -353,7 +353,7 @@ def rotate_wind(true_lat,lov_lon,earth_lons,uin,vin,proj,inverse=False): cin = data1.select(name='Convective inhibition',typeOfLevel='surface')[0].values # 500 mb height, wind, vorticity - z500 = data1.select(name='Geopotential Height',level=500)[0].values * 0.1 + z500 = data1.select(name='Geopotential height',level=500)[0].values * 0.1 z500 = ndimage.filters.gaussian_filter(z500, 6.89) vort500 = data1.select(name='Absolute vorticity',level=500)[0].values * 100000 vort500 = ndimage.filters.gaussian_filter(vort500,1.7225) diff --git a/ush/Python/plot_allvars_diff.py b/ush/Python/plot_allvars_diff.py index ec85df2e5b..12fcdbd949 100755 --- a/ush/Python/plot_allvars_diff.py +++ b/ush/Python/plot_allvars_diff.py @@ -383,9 +383,9 @@ def rotate_wind(true_lat,lov_lon,earth_lons,uin,vin,proj,inverse=False): cin_diff = cin_2 - cin_1 # 500 mb height, wind, vorticity - z500_1 = data1.select(name='Geopotential Height',level=500)[0].values * 0.1 + z500_1 = data1.select(name='Geopotential height',level=500)[0].values * 0.1 z500_1 = ndimage.filters.gaussian_filter(z500_1, 6.89) - z500_2 = data2.select(name='Geopotential Height',level=500)[0].values * 0.1 + z500_2 = data2.select(name='Geopotential height',level=500)[0].values * 0.1 z500_2 = ndimage.filters.gaussian_filter(z500_2, 6.89) z500_diff = z500_2 - z500_1 vort500_1 = data1.select(name='Absolute vorticity',level=500)[0].values * 100000 From 6e84102f17c921ee9ba5d84936c562eed8687903 Mon Sep 17 00:00:00 2001 From: danielabdi-noaa <52012304+danielabdi-noaa@users.noreply.github.com> Date: Wed, 16 Nov 2022 07:28:06 -0700 Subject: [PATCH 23/45] =?UTF-8?q?[develop]=20Source=20task=20specific=20po?= =?UTF-8?q?rtions=20of=20var=5Fdefns.sh=20file=20in=20ex-=20and=20j-job=20?= =?UTF-8?q?s=E2=80=A6=20(#465)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Source task specific portions of var_defns.sh file in ex- and j-job scripts. * Simplify source_config. * Put dictionary filtering in a function. * Add missing modulefiles now that python3 is required in all tasks. * Rearrange some config entries. * Move fix directories to platform section. * Move fix files for orography and surface climatology to platform. * Move data store types to platform. * Remove useless NOMADS script & logic and rely on retrieve_data instead. The NOMADS test case works for current date - 7. * Forward arguments from setup_WE2E to run_WE2E. * Don't set OPSROOT default * Move PREDEF_GRID_NAME to workflow section. * Bugfix for cheyenne-gnu issue + forward compiler in setup_WE2E. * Add templating for DATE_FIRST/LAST_CYCL in run_WE2E --- .cicd/scripts/srw_test.sh | 4 +- jobs/JREGIONAL_GET_EXTRN_MDL_FILES | 2 +- jobs/JREGIONAL_GET_OBS_CCPA | 2 +- jobs/JREGIONAL_GET_OBS_MRMS | 2 +- jobs/JREGIONAL_GET_OBS_NDAS | 2 +- jobs/JREGIONAL_MAKE_GRID | 2 +- jobs/JREGIONAL_MAKE_ICS | 2 +- jobs/JREGIONAL_MAKE_LBCS | 2 +- jobs/JREGIONAL_MAKE_OROG | 2 +- jobs/JREGIONAL_MAKE_SFC_CLIMO | 8 +- jobs/JREGIONAL_RUN_FCST | 2 +- jobs/JREGIONAL_RUN_POST | 2 +- jobs/JREGIONAL_RUN_VX_ENSGRID | 2 +- jobs/JREGIONAL_RUN_VX_ENSGRID_MEAN | 2 +- jobs/JREGIONAL_RUN_VX_ENSGRID_PROB | 2 +- jobs/JREGIONAL_RUN_VX_ENSPOINT | 2 +- jobs/JREGIONAL_RUN_VX_ENSPOINT_MEAN | 2 +- jobs/JREGIONAL_RUN_VX_ENSPOINT_PROB | 2 +- jobs/JREGIONAL_RUN_VX_GRIDSTAT | 2 +- jobs/JREGIONAL_RUN_VX_POINTSTAT | 2 +- modulefiles/build_orion_intel.lua | 1 + modulefiles/tasks/cheyenne/get_obs.local.lua | 1 + modulefiles/tasks/cheyenne/run_post.local.lua | 1 + modulefiles/tasks/gaea/get_obs.local.lua | 1 + modulefiles/tasks/gaea/run_post.local.lua | 1 + modulefiles/tasks/hera/make_orog.local.lua | 1 + modulefiles/tasks/hera/run_post.local.lua | 1 + modulefiles/tasks/jet/get_obs.local.lua | 2 + modulefiles/tasks/jet/make_orog.local.lua | 1 + modulefiles/tasks/jet/run_post.local.lua | 1 + modulefiles/tasks/noaacloud/get_obs.local.lua | 1 + modulefiles/tasks/noaacloud/run_vx.local.lua | 1 + modulefiles/tasks/odin/get_obs.local.lua | 0 modulefiles/tasks/orion/get_obs.local.lua | 1 + .../orion/miniconda_regional_workflow.lua | 1 + modulefiles/tasks/orion/run_post.local.lua | 1 + modulefiles/tasks/stampede/get_obs.local.lua | 0 modulefiles/tasks/wcoss2/make_orog.local.lua | 1 + modulefiles/tasks/wcoss2/run_post.local.lua | 1 + modulefiles/wflow_orion.lua | 1 + parm/FV3LAM_wflow.xml | 48 ++++- scripts/exregional_get_extrn_mdl_files.sh | 2 +- scripts/exregional_get_obs_ccpa.sh | 2 +- scripts/exregional_get_obs_mrms.sh | 2 +- scripts/exregional_get_obs_ndas.sh | 2 +- scripts/exregional_make_grid.sh | 2 +- scripts/exregional_make_ics.sh | 2 +- scripts/exregional_make_lbcs.sh | 2 +- scripts/exregional_make_orog.sh | 10 +- scripts/exregional_make_sfc_climo.sh | 18 +- scripts/exregional_run_fcst.sh | 2 +- scripts/exregional_run_post.sh | 2 +- scripts/exregional_run_vx_ensgrid.sh | 2 +- scripts/exregional_run_vx_ensgrid_mean.sh | 2 +- scripts/exregional_run_vx_ensgrid_prob.sh | 2 +- scripts/exregional_run_vx_enspoint.sh | 2 +- scripts/exregional_run_vx_enspoint_mean.sh | 2 +- scripts/exregional_run_vx_enspoint_prob.sh | 2 +- scripts/exregional_run_vx_gridstat.sh | 2 +- scripts/exregional_run_vx_pointstat.sh | 2 +- .../WE2E/get_WE2Etest_names_subdirs_descs.sh | 6 + tests/WE2E/run_WE2E_tests.sh | 20 +- tests/WE2E/setup_WE2E_tests.sh | 59 ++---- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ...cs_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ...3km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml | 3 +- ..._FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml | 3 +- ...GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp.yaml | 3 +- ...FV3GFS_suite_GFS_2017_gfdlmp_regional.yaml | 3 +- ...cs_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ...5km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml | 3 +- ..._FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml | 3 +- ...S_25km_ics_FV3GFS_lbcs_RAP_suite_HRRR.yaml | 3 +- ...GFS_lbcs_GSMGFS_suite_GFS_2017_gfdlmp.yaml | 3 +- ...cs_GSMGFS_lbcs_GSMGFS_suite_GFS_v15p2.yaml | 3 +- ..._ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v16.yaml | 3 +- ...ONUS_25km_ics_NAM_lbcs_NAM_suite_HRRR.yaml | 3 +- ...km_ics_NAM_lbcs_NAM_suite_RRFS_v1beta.yaml | 3 +- ...FS_suite_GFS_v15_thompson_mynn_lam3km.yaml | 2 +- ...cs_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ...3km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml | 3 +- ..._FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ...act_13km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml | 3 +- ...m_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ...ct_25km_ics_HRRR_lbcs_HRRR_suite_HRRR.yaml | 3 +- ..._ics_HRRR_lbcs_HRRR_suite_RRFS_v1beta.yaml | 3 +- ...act_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml | 3 +- ...m_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ...3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml | 3 +- ...pact_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml | 3 +- ...m_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml | 3 +- ..._FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml | 2 +- ..._FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml | 6 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ...3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ..._Ind_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml | 3 +- ...m_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml | 3 +- ..._ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml | 3 +- ..._lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml | 7 +- ...FS_suite_GFS_v15_thompson_mynn_lam3km.yaml | 2 +- ...act_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml | 2 +- .../config.GST_release_public_v1.yaml | 6 +- .../config.MET_ensemble_verification.yaml | 2 +- .../config.MET_verification.yaml | 2 +- .../config.community_ensemble_008mems.yaml | 3 +- .../config.community_ensemble_2mems.yaml | 3 +- ...config.community_ensemble_2mems_stoch.yaml | 3 +- .../config.deactivate_tasks.yaml | 3 +- ...3GFS_lbcs_FV3GFS_fmt_grib2_2019061200.yaml | 3 +- ...3GFS_lbcs_FV3GFS_fmt_grib2_2019101818.yaml | 3 +- ...3GFS_lbcs_FV3GFS_fmt_grib2_2020022518.yaml | 3 +- ...3GFS_lbcs_FV3GFS_fmt_grib2_2020022600.yaml | 3 +- ...3GFS_lbcs_FV3GFS_fmt_grib2_2021010100.yaml | 3 +- ...PSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio.yaml | 3 +- ...GFS_lbcs_FV3GFS_fmt_nemsio_2019061200.yaml | 3 +- ...GFS_lbcs_FV3GFS_fmt_nemsio_2019101818.yaml | 3 +- ...GFS_lbcs_FV3GFS_fmt_nemsio_2020022518.yaml | 3 +- ...GFS_lbcs_FV3GFS_fmt_nemsio_2020022600.yaml | 3 +- ...GFS_lbcs_FV3GFS_fmt_nemsio_2021010100.yaml | 3 +- ...GFS_lbcs_FV3GFS_fmt_netcdf_2021062000.yaml | 3 +- ...lbcs_FV3GFS_fmt_netcdf_2022060112_48h.yaml | 3 +- ....get_from_HPSS_ics_GSMGFS_lbcs_GSMGFS.yaml | 3 +- ...onfig.get_from_HPSS_ics_HRRR_lbcs_RAP.yaml | 3 +- ...config.get_from_HPSS_ics_RAP_lbcs_RAP.yaml | 3 +- ...t_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS.yaml} | 15 +- .../wflow_features/config.inline_post.yaml | 2 +- .../wflow_features/config.nco_ensemble.yaml | 3 +- .../config.pregen_grid_orog_sfc_climo.yaml | 3 +- .../config.specify_DOT_OR_USCORE.yaml | 3 +- ....specify_DT_ATMOS_LAYOUT_XY_BLOCKSIZE.yaml | 2 +- ...specify_EXTRN_MDL_SYSBASEDIR_ICS_LBCS.yaml | 3 +- .../config.specify_RESTART_INTERVAL.yaml | 2 +- .../config.specify_template_filenames.yaml | 3 +- .../wflow_features/config.subhourly_post.yaml | 2 +- .../config.subhourly_post_ensemble_2mems.yaml | 2 +- ush/NOMADS_get_extrn_mdl_files.sh | 70 ------ ush/bash_utils/source_config.sh | 43 +--- ush/config.community.yaml | 2 +- ush/config.nco.yaml | 2 +- ush/config_defaults.yaml | 199 +++++++++--------- ush/generate_FV3LAM_wflow.py | 41 ---- ush/machine/cheyenne.yaml | 7 +- ush/machine/gaea.yaml | 7 +- ush/machine/hera.yaml | 12 +- ush/machine/jet.yaml | 12 +- ush/machine/linux.yaml | 7 +- ush/machine/macos.yaml | 7 +- ush/machine/noaacloud.yaml | 12 +- ush/machine/odin.yaml | 7 +- ush/machine/orion.yaml | 12 +- ush/machine/singularity.yaml | 12 +- ush/machine/stampede.yaml | 7 +- ush/machine/wcoss2.yaml | 12 +- ush/python_utils/config_parser.py | 21 +- ush/python_utils/environment.py | 11 +- ush/setup.py | 12 +- 166 files changed, 412 insertions(+), 622 deletions(-) create mode 100644 modulefiles/tasks/cheyenne/get_obs.local.lua create mode 100644 modulefiles/tasks/cheyenne/run_post.local.lua create mode 100644 modulefiles/tasks/gaea/get_obs.local.lua create mode 100644 modulefiles/tasks/gaea/run_post.local.lua create mode 100644 modulefiles/tasks/hera/make_orog.local.lua create mode 100644 modulefiles/tasks/hera/run_post.local.lua create mode 100644 modulefiles/tasks/jet/get_obs.local.lua create mode 100644 modulefiles/tasks/jet/make_orog.local.lua create mode 100644 modulefiles/tasks/jet/run_post.local.lua create mode 100644 modulefiles/tasks/noaacloud/get_obs.local.lua create mode 100644 modulefiles/tasks/noaacloud/run_vx.local.lua create mode 100644 modulefiles/tasks/odin/get_obs.local.lua create mode 100644 modulefiles/tasks/orion/get_obs.local.lua create mode 100644 modulefiles/tasks/orion/run_post.local.lua create mode 100644 modulefiles/tasks/stampede/get_obs.local.lua create mode 100644 modulefiles/tasks/wcoss2/make_orog.local.lua create mode 100644 modulefiles/tasks/wcoss2/run_post.local.lua rename tests/WE2E/test_configs/wflow_features/{config.get_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio.yaml => config.get_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS.yaml} (68%) delete mode 100755 ush/NOMADS_get_extrn_mdl_files.sh diff --git a/.cicd/scripts/srw_test.sh b/.cicd/scripts/srw_test.sh index d6b6134993..4c4cbc95af 100755 --- a/.cicd/scripts/srw_test.sh +++ b/.cicd/scripts/srw_test.sh @@ -38,7 +38,9 @@ else fi cd ${we2e_test_dir} -./setup_WE2E_tests.sh ${platform} ${SRW_PROJECT} ${SRW_COMPILER} ${test_type} ${we2e_experiment_base_dir} ${nco_dir} +./setup_WE2E_tests.sh ${platform} ${SRW_PROJECT} ${SRW_COMPILER} ${test_type} \ + expt_basedir=${we2e_experiment_base_dir} \ + opsroot=${nco_dir} # Allow the tests to start before checking for status. # TODO: Create a parameter that sets the initial start delay. diff --git a/jobs/JREGIONAL_GET_EXTRN_MDL_FILES b/jobs/JREGIONAL_GET_EXTRN_MDL_FILES index c75c709b2a..8fafa8f4e5 100755 --- a/jobs/JREGIONAL_GET_EXTRN_MDL_FILES +++ b/jobs/JREGIONAL_GET_EXTRN_MDL_FILES @@ -28,8 +28,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_get_extrn_ics|task_get_extrn_lbcs" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_GET_OBS_CCPA b/jobs/JREGIONAL_GET_OBS_CCPA index aaf527a477..722d38a0ac 100755 --- a/jobs/JREGIONAL_GET_OBS_CCPA +++ b/jobs/JREGIONAL_GET_OBS_CCPA @@ -19,8 +19,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_get_obs_ccpa" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_GET_OBS_MRMS b/jobs/JREGIONAL_GET_OBS_MRMS index 4dc80c30bb..33331fe9f5 100755 --- a/jobs/JREGIONAL_GET_OBS_MRMS +++ b/jobs/JREGIONAL_GET_OBS_MRMS @@ -15,8 +15,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_get_obs_mrms" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_GET_OBS_NDAS b/jobs/JREGIONAL_GET_OBS_NDAS index 836c367378..18faa0fe59 100755 --- a/jobs/JREGIONAL_GET_OBS_NDAS +++ b/jobs/JREGIONAL_GET_OBS_NDAS @@ -15,8 +15,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_get_obs_ndas" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_MAKE_GRID b/jobs/JREGIONAL_MAKE_GRID index c4c68da734..0a6adfe277 100755 --- a/jobs/JREGIONAL_MAKE_GRID +++ b/jobs/JREGIONAL_MAKE_GRID @@ -105,8 +105,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_grid" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_MAKE_ICS b/jobs/JREGIONAL_MAKE_ICS index 525720b14a..4fd9238a05 100755 --- a/jobs/JREGIONAL_MAKE_ICS +++ b/jobs/JREGIONAL_MAKE_ICS @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_ics" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_MAKE_LBCS b/jobs/JREGIONAL_MAKE_LBCS index e92ca94354..0a6aab6b98 100755 --- a/jobs/JREGIONAL_MAKE_LBCS +++ b/jobs/JREGIONAL_MAKE_LBCS @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_lbcs" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_MAKE_OROG b/jobs/JREGIONAL_MAKE_OROG index b28285f07e..8f50c134ff 100755 --- a/jobs/JREGIONAL_MAKE_OROG +++ b/jobs/JREGIONAL_MAKE_OROG @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_orog" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_MAKE_SFC_CLIMO b/jobs/JREGIONAL_MAKE_SFC_CLIMO index 9a0aff34c1..fe7773230c 100755 --- a/jobs/JREGIONAL_MAKE_SFC_CLIMO +++ b/jobs/JREGIONAL_MAKE_SFC_CLIMO @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_sfc_climo" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- @@ -64,8 +64,10 @@ mkdir_vrfy -p "${SFC_CLIMO_DIR}" #----------------------------------------------------------------------- # DATA="${DATA:-${SFC_CLIMO_DIR}/tmp}" -check_for_preexist_dir_file "$DATA" "delete" -mkdir_vrfy $DATA +if [ $RUN_ENVIR != "nco" ]; then + check_for_preexist_dir_file "$DATA" "delete" + mkdir_vrfy $DATA +fi # #----------------------------------------------------------------------- # diff --git a/jobs/JREGIONAL_RUN_FCST b/jobs/JREGIONAL_RUN_FCST index 58a255757c..e2501c37e4 100755 --- a/jobs/JREGIONAL_RUN_FCST +++ b/jobs/JREGIONAL_RUN_FCST @@ -17,8 +17,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_fcst" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh "TRUE" # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_RUN_POST b/jobs/JREGIONAL_RUN_POST index 153c94ca45..8783cb2d91 100755 --- a/jobs/JREGIONAL_RUN_POST +++ b/jobs/JREGIONAL_RUN_POST @@ -16,8 +16,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_post|task_run_fcst" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_RUN_VX_ENSGRID b/jobs/JREGIONAL_RUN_VX_ENSGRID index d20f85fa1a..0ad9445c1a 100755 --- a/jobs/JREGIONAL_RUN_VX_ENSGRID +++ b/jobs/JREGIONAL_RUN_VX_ENSGRID @@ -16,8 +16,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_ensgrid" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_RUN_VX_ENSGRID_MEAN b/jobs/JREGIONAL_RUN_VX_ENSGRID_MEAN index 3864d4765b..a72f7b1bfb 100755 --- a/jobs/JREGIONAL_RUN_VX_ENSGRID_MEAN +++ b/jobs/JREGIONAL_RUN_VX_ENSGRID_MEAN @@ -16,8 +16,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_ensgrid_mean" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_RUN_VX_ENSGRID_PROB b/jobs/JREGIONAL_RUN_VX_ENSGRID_PROB index 545273f6ad..e99ec56676 100755 --- a/jobs/JREGIONAL_RUN_VX_ENSGRID_PROB +++ b/jobs/JREGIONAL_RUN_VX_ENSGRID_PROB @@ -16,8 +16,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_ensgrid_prob" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_RUN_VX_ENSPOINT b/jobs/JREGIONAL_RUN_VX_ENSPOINT index b8edbd292f..412416729e 100755 --- a/jobs/JREGIONAL_RUN_VX_ENSPOINT +++ b/jobs/JREGIONAL_RUN_VX_ENSPOINT @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_enspoint" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_RUN_VX_ENSPOINT_MEAN b/jobs/JREGIONAL_RUN_VX_ENSPOINT_MEAN index 6e6351ca72..06f42d11dc 100755 --- a/jobs/JREGIONAL_RUN_VX_ENSPOINT_MEAN +++ b/jobs/JREGIONAL_RUN_VX_ENSPOINT_MEAN @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_enspoint_mean" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_RUN_VX_ENSPOINT_PROB b/jobs/JREGIONAL_RUN_VX_ENSPOINT_PROB index 244ddd8c5d..1935f5599b 100755 --- a/jobs/JREGIONAL_RUN_VX_ENSPOINT_PROB +++ b/jobs/JREGIONAL_RUN_VX_ENSPOINT_PROB @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_enspoint_prob" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_RUN_VX_GRIDSTAT b/jobs/JREGIONAL_RUN_VX_GRIDSTAT index f6b4b59ce0..f93c196d4c 100755 --- a/jobs/JREGIONAL_RUN_VX_GRIDSTAT +++ b/jobs/JREGIONAL_RUN_VX_GRIDSTAT @@ -16,8 +16,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_gridstat" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/jobs/JREGIONAL_RUN_VX_POINTSTAT b/jobs/JREGIONAL_RUN_VX_POINTSTAT index 0d5d83a175..8ebce34d2c 100755 --- a/jobs/JREGIONAL_RUN_VX_POINTSTAT +++ b/jobs/JREGIONAL_RUN_VX_POINTSTAT @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_pointstat" ${GLOBAL_VAR_DEFNS_FP} . $USHdir/job_preamble.sh # #----------------------------------------------------------------------- diff --git a/modulefiles/build_orion_intel.lua b/modulefiles/build_orion_intel.lua index 200b2bbf35..92795c6f8c 100644 --- a/modulefiles/build_orion_intel.lua +++ b/modulefiles/build_orion_intel.lua @@ -9,6 +9,7 @@ load("contrib") load("noaatools") load(pathJoin("cmake", os.getenv("cmake_ver") or "3.22.1")) +load(pathJoin("python", os.getenv("python_ver") or "3.9.2")) prepend_path("MODULEPATH","/apps/contrib/NCEP/libs/hpc-stack/modulefiles/stack") load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) diff --git a/modulefiles/tasks/cheyenne/get_obs.local.lua b/modulefiles/tasks/cheyenne/get_obs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/cheyenne/get_obs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/cheyenne/run_post.local.lua b/modulefiles/tasks/cheyenne/run_post.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/cheyenne/run_post.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/get_obs.local.lua b/modulefiles/tasks/gaea/get_obs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/get_obs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/gaea/run_post.local.lua b/modulefiles/tasks/gaea/run_post.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/gaea/run_post.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/make_orog.local.lua b/modulefiles/tasks/hera/make_orog.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/hera/make_orog.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/hera/run_post.local.lua b/modulefiles/tasks/hera/run_post.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/hera/run_post.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/get_obs.local.lua b/modulefiles/tasks/jet/get_obs.local.lua new file mode 100644 index 0000000000..d1afe2451e --- /dev/null +++ b/modulefiles/tasks/jet/get_obs.local.lua @@ -0,0 +1,2 @@ +load("hpss") +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/make_orog.local.lua b/modulefiles/tasks/jet/make_orog.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/jet/make_orog.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/jet/run_post.local.lua b/modulefiles/tasks/jet/run_post.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/jet/run_post.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/get_obs.local.lua b/modulefiles/tasks/noaacloud/get_obs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/get_obs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/noaacloud/run_vx.local.lua b/modulefiles/tasks/noaacloud/run_vx.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/noaacloud/run_vx.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/odin/get_obs.local.lua b/modulefiles/tasks/odin/get_obs.local.lua new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modulefiles/tasks/orion/get_obs.local.lua b/modulefiles/tasks/orion/get_obs.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/get_obs.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/orion/miniconda_regional_workflow.lua b/modulefiles/tasks/orion/miniconda_regional_workflow.lua index 793a8824a9..5b7b0afc57 100644 --- a/modulefiles/tasks/orion/miniconda_regional_workflow.lua +++ b/modulefiles/tasks/orion/miniconda_regional_workflow.lua @@ -1,3 +1,4 @@ +unload("python") append_path("MODULEPATH","/work/noaa/epic-ps/role-epic-ps/miniconda3/modulefiles") load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) diff --git a/modulefiles/tasks/orion/run_post.local.lua b/modulefiles/tasks/orion/run_post.local.lua new file mode 100644 index 0000000000..d371c08301 --- /dev/null +++ b/modulefiles/tasks/orion/run_post.local.lua @@ -0,0 +1 @@ +load("miniconda_regional_workflow") diff --git a/modulefiles/tasks/stampede/get_obs.local.lua b/modulefiles/tasks/stampede/get_obs.local.lua new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modulefiles/tasks/wcoss2/make_orog.local.lua b/modulefiles/tasks/wcoss2/make_orog.local.lua new file mode 100644 index 0000000000..3370fa018b --- /dev/null +++ b/modulefiles/tasks/wcoss2/make_orog.local.lua @@ -0,0 +1 @@ +load("python_regional_workflow") diff --git a/modulefiles/tasks/wcoss2/run_post.local.lua b/modulefiles/tasks/wcoss2/run_post.local.lua new file mode 100644 index 0000000000..3370fa018b --- /dev/null +++ b/modulefiles/tasks/wcoss2/run_post.local.lua @@ -0,0 +1 @@ +load("python_regional_workflow") diff --git a/modulefiles/wflow_orion.lua b/modulefiles/wflow_orion.lua index a8edef0089..a818e193cf 100644 --- a/modulefiles/wflow_orion.lua +++ b/modulefiles/wflow_orion.lua @@ -8,6 +8,7 @@ whatis([===[Loads libraries needed for running SRW on Orion ]===]) load("contrib") load("rocoto") +unload("python") append_path("MODULEPATH","/work/noaa/epic-ps/role-epic-ps/miniconda3/modulefiles") load(pathJoin("miniconda3", os.getenv("miniconda3_ver") or "4.12.0")) diff --git a/parm/FV3LAM_wflow.xml b/parm/FV3LAM_wflow.xml index 97d2f1a700..b0b632fee4 100644 --- a/parm/FV3LAM_wflow.xml +++ b/parm/FV3LAM_wflow.xml @@ -36,6 +36,7 @@ Workflow task names. + @@ -67,11 +68,6 @@ Workflow task names. - - - @@ -90,6 +86,7 @@ specifies the number of processes per node being used (the PPN_... entities). + @@ -214,6 +211,7 @@ MODULES_RUN_TASK_FP script. &LOGDIR;/&MAKE_GRID_TN;&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -238,6 +236,7 @@ MODULES_RUN_TASK_FP script. &LOGDIR;/&MAKE_OROG_TN;&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -270,6 +269,7 @@ MODULES_RUN_TASK_FP script. &LOGDIR;/&MAKE_SFC_CLIMO_TN;&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -314,6 +314,7 @@ MODULES_RUN_TASK_FP script. &LOGDIR;/&GET_EXTRN_ICS_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -344,6 +345,7 @@ MODULES_RUN_TASK_FP script. &LOGDIR;/&GET_EXTRN_LBCS_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -379,6 +381,7 @@ MODULES_RUN_TASK_FP script. &LOGDIR;/&MAKE_ICS_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -426,6 +429,7 @@ MODULES_RUN_TASK_FP script. &LOGDIR;/&MAKE_LBCS_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -482,6 +486,7 @@ MODULES_RUN_TASK_FP script. &LOGDIR;/&RUN_FCST_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -534,6 +539,7 @@ later below for other output times. &LOGDIR;/&RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn#_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -590,6 +596,7 @@ for other output times. &LOGDIR;/&RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn#_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -656,6 +663,7 @@ always zero). {%- endif %} GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -721,6 +729,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&RUN_POST_TN;{{ uscore_ensmem_name }}_f#fhr##fmn#_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; PDY@Y@m@d cyc@H subcyc@M @@ -766,6 +775,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&GET_OBS_CCPA_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -797,6 +807,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&GET_OBS_MRMS_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&MRMS_OBS_DIR; PDY@Y@m@d cyc@H @@ -829,6 +840,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&GET_OBS_NDAS_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&NDAS_OBS_DIR; PDY@Y@m@d cyc@H @@ -859,6 +871,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_GRIDSTAT_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -914,6 +927,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_GRIDSTAT_REFC_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&MRMS_OBS_DIR; PDY@Y@m@d cyc@H @@ -968,6 +982,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_GRIDSTAT_RETOP_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&MRMS_OBS_DIR; PDY@Y@m@d cyc@H @@ -1022,6 +1037,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_GRIDSTAT_03h_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1062,6 +1078,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_GRIDSTAT_06h_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1102,6 +1119,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_GRIDSTAT_24h_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1142,6 +1160,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_POINTSTAT_TN;{{ uscore_ensmem_name }}_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&NDAS_OBS_DIR; PDY@Y@m@d cyc@H @@ -1199,6 +1218,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1235,6 +1255,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_03h_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1271,6 +1292,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_06h_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1307,6 +1329,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_24h_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1342,6 +1365,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_REFC_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&MRMS_OBS_DIR; PDY@Y@m@d cyc@H @@ -1376,6 +1400,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_RETOP_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&MRMS_OBS_DIR; PDY@Y@m@d cyc@H @@ -1409,6 +1434,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_MEAN_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1444,6 +1470,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_PROB_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1479,6 +1506,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_MEAN_03h_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1514,6 +1542,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_PROB_03h_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1550,6 +1579,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_MEAN_06h_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1585,6 +1615,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_PROB_06h_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1621,6 +1652,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_MEAN_24h_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1656,6 +1688,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_PROB_24h_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&CCPA_OBS_DIR; PDY@Y@m@d cyc@H @@ -1691,6 +1724,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_PROB_REFC_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&MRMS_OBS_DIR; PDY@Y@m@d cyc@H @@ -1725,6 +1759,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSGRID_PROB_RETOP_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&MRMS_OBS_DIR; PDY@Y@m@d cyc@H @@ -1760,6 +1795,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSPOINT_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&NDAS_OBS_DIR; PDY@Y@m@d cyc@H @@ -1792,6 +1828,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSPOINT_MEAN_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&NDAS_OBS_DIR; PDY@Y@m@d cyc@H @@ -1824,6 +1861,7 @@ the tag to be identical to the ones above for other output times. &LOGDIR;/&VX_ENSPOINT_PROB_TN;_@Y@m@d@H&LOGEXT; GLOBAL_VAR_DEFNS_FP&GLOBAL_VAR_DEFNS_FP; + USHdir&USHdir; OBS_DIR&NDAS_OBS_DIR; PDY@Y@m@d cyc@H diff --git a/scripts/exregional_get_extrn_mdl_files.sh b/scripts/exregional_get_extrn_mdl_files.sh index 6a7eaa90b2..26b409c46e 100755 --- a/scripts/exregional_get_extrn_mdl_files.sh +++ b/scripts/exregional_get_extrn_mdl_files.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_get_extrn_ics|task_get_extrn_lbcs" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_get_obs_ccpa.sh b/scripts/exregional_get_obs_ccpa.sh index 8607861c63..ccb7e78297 100755 --- a/scripts/exregional_get_obs_ccpa.sh +++ b/scripts/exregional_get_obs_ccpa.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_get_obs_ccpa" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_get_obs_mrms.sh b/scripts/exregional_get_obs_mrms.sh index f6da0cac86..89ea7a7a19 100755 --- a/scripts/exregional_get_obs_mrms.sh +++ b/scripts/exregional_get_obs_mrms.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_get_obs_mrms" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_get_obs_ndas.sh b/scripts/exregional_get_obs_ndas.sh index b7587b18e6..f800def427 100755 --- a/scripts/exregional_get_obs_ndas.sh +++ b/scripts/exregional_get_obs_ndas.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_get_obs_ndas" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_make_grid.sh b/scripts/exregional_make_grid.sh index f1c3f1a8b8..e19448e03d 100755 --- a/scripts/exregional_make_grid.sh +++ b/scripts/exregional_make_grid.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_grid" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_make_ics.sh b/scripts/exregional_make_ics.sh index 9714f36021..3af3d29c7c 100755 --- a/scripts/exregional_make_ics.sh +++ b/scripts/exregional_make_ics.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_ics|task_get_extrn_ics" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_make_lbcs.sh b/scripts/exregional_make_lbcs.sh index 2c0c59ef19..5f185256dc 100755 --- a/scripts/exregional_make_lbcs.sh +++ b/scripts/exregional_make_lbcs.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_lbcs|task_get_extrn_lbcs" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_make_orog.sh b/scripts/exregional_make_orog.sh index f743748ecd..0a61eb3f03 100755 --- a/scripts/exregional_make_orog.sh +++ b/scripts/exregional_make_orog.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_orog|task_make_grid" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # @@ -122,12 +122,12 @@ DATA="${DATA:-${raw_dir}/tmp}" mkdir_vrfy -p "${DATA}" cd_vrfy "${DATA}" # -# Copy topography and related data files from the system directory (TOPO_DIR) +# Copy topography and related data files from the system directory (FIXorg) # to the temporary directory. # -cp_vrfy ${TOPO_DIR}/thirty.second.antarctic.new.bin fort.15 -cp_vrfy ${TOPO_DIR}/landcover30.fixed . -cp_vrfy ${TOPO_DIR}/gmted2010.30sec.int fort.235 +cp_vrfy ${FIXorg}/thirty.second.antarctic.new.bin fort.15 +cp_vrfy ${FIXorg}/landcover30.fixed . +cp_vrfy ${FIXorg}/gmted2010.30sec.int fort.235 # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_make_sfc_climo.sh b/scripts/exregional_make_sfc_climo.sh index d32b39260a..ad00e307ef 100755 --- a/scripts/exregional_make_sfc_climo.sh +++ b/scripts/exregional_make_sfc_climo.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_make_sfc_climo" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # @@ -82,14 +82,14 @@ cd_vrfy $DATA # cat << EOF > ./fort.41 &config -input_facsf_file="${SFC_CLIMO_INPUT_DIR}/facsf.1.0.nc" -input_substrate_temperature_file="${SFC_CLIMO_INPUT_DIR}/substrate_temperature.2.6x1.5.nc" -input_maximum_snow_albedo_file="${SFC_CLIMO_INPUT_DIR}/maximum_snow_albedo.0.05.nc" -input_snowfree_albedo_file="${SFC_CLIMO_INPUT_DIR}/snowfree_albedo.4comp.0.05.nc" -input_slope_type_file="${SFC_CLIMO_INPUT_DIR}/slope_type.1.0.nc" -input_soil_type_file="${SFC_CLIMO_INPUT_DIR}/soil_type.statsgo.0.05.nc" -input_vegetation_type_file="${SFC_CLIMO_INPUT_DIR}/vegetation_type.igbp.0.05.nc" -input_vegetation_greenness_file="${SFC_CLIMO_INPUT_DIR}/vegetation_greenness.0.144.nc" +input_facsf_file="${FIXsfc}/facsf.1.0.nc" +input_substrate_temperature_file="${FIXsfc}/substrate_temperature.2.6x1.5.nc" +input_maximum_snow_albedo_file="${FIXsfc}/maximum_snow_albedo.0.05.nc" +input_snowfree_albedo_file="${FIXsfc}/snowfree_albedo.4comp.0.05.nc" +input_slope_type_file="${FIXsfc}/slope_type.1.0.nc" +input_soil_type_file="${FIXsfc}/soil_type.statsgo.0.05.nc" +input_vegetation_type_file="${FIXsfc}/vegetation_type.igbp.0.05.nc" +input_vegetation_greenness_file="${FIXsfc}/vegetation_greenness.0.144.nc" mosaic_file_mdl="${FIXlam}/${CRES}${DOT_OR_USCORE}mosaic.halo${NH4}.nc" orog_dir_mdl="${FIXlam}" orog_files_mdl="${CRES}${DOT_OR_USCORE}oro_data.tile${TILE_RGNL}.halo${NH4}.nc" diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 67bf7b18c3..1380275fde 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_fcst|task_run_post|task_get_extrn_lbcs" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_post.sh b/scripts/exregional_run_post.sh index 2b950a9421..c3de8c3f28 100755 --- a/scripts/exregional_run_post.sh +++ b/scripts/exregional_run_post.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_post" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_vx_ensgrid.sh b/scripts/exregional_run_vx_ensgrid.sh index c6a7b4c6a2..a5080cc7cb 100755 --- a/scripts/exregional_run_vx_ensgrid.sh +++ b/scripts/exregional_run_vx_ensgrid.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_ensgrid|task_run_post" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_vx_ensgrid_mean.sh b/scripts/exregional_run_vx_ensgrid_mean.sh index 9679ae60ea..9d09e18028 100755 --- a/scripts/exregional_run_vx_ensgrid_mean.sh +++ b/scripts/exregional_run_vx_ensgrid_mean.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_ensgrid_mean|task_run_post" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_vx_ensgrid_prob.sh b/scripts/exregional_run_vx_ensgrid_prob.sh index f21a31bb70..ad6afcd26d 100755 --- a/scripts/exregional_run_vx_ensgrid_prob.sh +++ b/scripts/exregional_run_vx_ensgrid_prob.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_ensgrid_prob|task_run_post" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_vx_enspoint.sh b/scripts/exregional_run_vx_enspoint.sh index b2e459ad4a..32793de7b8 100755 --- a/scripts/exregional_run_vx_enspoint.sh +++ b/scripts/exregional_run_vx_enspoint.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_enspoint|task_run_post" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_vx_enspoint_mean.sh b/scripts/exregional_run_vx_enspoint_mean.sh index 556342dee3..58dbc3306c 100755 --- a/scripts/exregional_run_vx_enspoint_mean.sh +++ b/scripts/exregional_run_vx_enspoint_mean.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_enspoint_mean|task_run_post" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_vx_enspoint_prob.sh b/scripts/exregional_run_vx_enspoint_prob.sh index fc44c24e5b..b17eb4b39b 100755 --- a/scripts/exregional_run_vx_enspoint_prob.sh +++ b/scripts/exregional_run_vx_enspoint_prob.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_enspoint_prob|task_run_post" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_vx_gridstat.sh b/scripts/exregional_run_vx_gridstat.sh index 2d5f34184e..dcc8da93b8 100755 --- a/scripts/exregional_run_vx_gridstat.sh +++ b/scripts/exregional_run_vx_gridstat.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_gridstat|task_run_post" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_vx_pointstat.sh b/scripts/exregional_run_vx_pointstat.sh index ce2518563b..65df885e66 100755 --- a/scripts/exregional_run_vx_pointstat.sh +++ b/scripts/exregional_run_vx_pointstat.sh @@ -7,8 +7,8 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} . $USHdir/source_util_funcs.sh +source_config_for_task "task_run_vx_pointstat|task_run_post" ${GLOBAL_VAR_DEFNS_FP} # #----------------------------------------------------------------------- # diff --git a/tests/WE2E/get_WE2Etest_names_subdirs_descs.sh b/tests/WE2E/get_WE2Etest_names_subdirs_descs.sh index 04248a7615..7ce1a6dd8b 100755 --- a/tests/WE2E/get_WE2Etest_names_subdirs_descs.sh +++ b/tests/WE2E/get_WE2Etest_names_subdirs_descs.sh @@ -1076,6 +1076,12 @@ configuration files of the primary WE2E tests... # so the factor of 3600 is needed to convert the number of seconds to hours. # # Convert cycles to seconds + if [[ $DATE_FIRST_CYCL != [0-9]* ]]; then + DATE_FIRST_CYCL=$(eval ${DATE_FIRST_CYCL}) + fi + if [[ $DATE_LAST_CYCL != [0-9]* ]]; then + DATE_LAST_CYCL=$(eval ${DATE_LAST_CYCL}) + fi first=$(date --utc --date "${DATE_FIRST_CYCL:0:8} ${DATE_FIRST_CYCL:8:2}" +"%s") last=$(date --utc --date "${DATE_LAST_CYCL:0:8} ${DATE_LAST_CYCL:8:2}" +"%s") # Diff and convert seconds to number of cycles where freq is in diff --git a/tests/WE2E/run_WE2E_tests.sh b/tests/WE2E/run_WE2E_tests.sh index 6c8680b3ec..18063eee33 100755 --- a/tests/WE2E/run_WE2E_tests.sh +++ b/tests/WE2E/run_WE2E_tests.sh @@ -43,7 +43,7 @@ HOMEdir=${scrfunc_dir%/*/*} # #----------------------------------------------------------------------- # -USHdir="$HOMEdir/ush" +export USHdir="$HOMEdir/ush" TESTSdir="$HOMEdir/tests" WE2Edir="$TESTSdir/WE2E" # @@ -914,6 +914,20 @@ RUN_ENVIR=${run_envir}" RUN_ENVIR=${run_envir} fi +# +# Eval DATE_FIRST/LAST_CYCL commands +# +if [[ $DATE_FIRST_CYCL != [0-9]* ]]; then + DATE_FIRST_CYCL=$(eval ${DATE_FIRST_CYCL}) + expt_config_str=${expt_config_str}" +DATE_FIRST_CYCL=${DATE_FIRST_CYCL}" +fi +if [[ $DATE_LAST_CYCL != [0-9]* ]]; then + DATE_LAST_CYCL=$(eval ${DATE_LAST_CYCL}) + expt_config_str=${expt_config_str}" +DATE_LAST_CYCL=${DATE_LAST_CYCL}" +fi + # #----------------------------------------------------------------------- # @@ -998,13 +1012,11 @@ model_ver="we2e"" # # Set OPSROOT. # - OPSROOT=${opsroot:-$( readlink -f "$HOMEdir/../nco_dirs" )} - expt_config_str=${expt_config_str}" # # Set NCO mode OPSROOT # -OPSROOT=\"${OPSROOT}\"" +OPSROOT=\"${opsroot}\"" fi # diff --git a/tests/WE2E/setup_WE2E_tests.sh b/tests/WE2E/setup_WE2E_tests.sh index ec94948e51..c031ad89b2 100755 --- a/tests/WE2E/setup_WE2E_tests.sh +++ b/tests/WE2E/setup_WE2E_tests.sh @@ -26,15 +26,13 @@ function usage { echo - echo "Usage: $0 machine slurm_account [compiler] [test_type] [expts_dir] [nco_dirs] [run_envir] | -h" + echo "Usage: $0 machine account [compiler] [test_type] [others] | -h" echo echo " machine [required] is one of: ${machines[@]}" - echo " slurm_account [required] case sensitive name of the user-specific slurm account" - echo " compiler [optional] compiler used for build" + echo " account [required] case sensitive name of the user-specific slurm account" + echo " compiler [optional] compiler used to build binaries (intel or gnu)" echo " test_type [optional] test type: fundamental or comprehensive or all or any other name" - echo " expts_dir [optional] Experiment base directory" - echo " nco_dirs [optional] NCO operations root directory" - echo " run_envir [optional] either 'community' or 'nco' " + echo " others [optional] All other arguments are forwarded to run_WE2E_tests.sh" echo " -h display this help" echo exit 1 @@ -46,52 +44,41 @@ machines=( hera jet cheyenne orion wcoss2 gaea odin singularity macos noaacloud if [ "$1" = "-h" ] ; then usage ; fi [[ $# -le 1 ]] && usage -machine=$1 -machine=$(echo "${machine}" | tr '[A-Z]' '[a-z]') # scripts in sorc need lower case machine name +machine=${1,,} account=$2 compiler=${3:-intel} test_type=${4:-fundamental} -#----------------------------------------------------------------------- -# Set directories -#----------------------------------------------------------------------- -scrfunc_fp=$( readlink -f "${BASH_SOURCE[0]}" ) -scrfunc_fn=$( basename "${scrfunc_fp}" ) -scrfunc_dir=$( dirname "${scrfunc_fp}" ) - -TESTS_DIR=$( dirname "${scrfunc_dir}" ) -SRW_APP_DIR=$( dirname "${TESTS_DIR}" ) -TOP_DIR=$( dirname "${SRW_APP_DIR}" ) - -EXPTS_DIR=${5:-"${TOP_DIR}/expt_dirs"} -NCO_DIR=${6:-"${TOP_DIR}/nco_dirs"} - -RUN_ENVIR=${7:-""} - #---------------------------------------------------------------------- -# Use exec_subdir consistent with the automated build. +# Set some default options, if user did not pass them #---------------------------------------------------------------------- - -exec_subdir="install_${compiler}/exec" +opts= +if [[ "$*" != *"debug"* ]]; then + opts="${opts} debug=TRUE" +fi +if [[ "$*" != *"verbose"* ]]; then + opts="${opts} verbose=TRUE" +fi +if [[ "$*" != *"cron_relaunch_intvl_mnts"* ]]; then + opts="${opts} cron_relaunch_intvl_mnts=4" +fi +if [[ "$*" != *"exec_subdir"* ]]; then + opts="${opts} exec_subdir=install_${compiler}/exec" +fi #----------------------------------------------------------------------- # Run E2E Tests #----------------------------------------------------------------------- # Load Python Modules -source ${SRW_APP_DIR}/ush/load_modules_wflow.sh ${machine} +source ../../ush/load_modules_wflow.sh ${machine} # Run the E2E Workflow tests ./run_WE2E_tests.sh \ - test_type=${test_type} \ machine=${machine} \ account=${account} \ - exec_subdir=${exec_subdir} \ compiler=${compiler} \ - expt_basedir=${EXPTS_DIR} \ - opsroot=${NCO_DIR} \ - debug="TRUE" \ - verbose="TRUE" \ - cron_relaunch_intvl_mnts=4 \ - run_envir=${RUN_ENVIR} + test_type=${test_type} \ + ${opts} \ + "${@:5}" diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_CONUS_25km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_CONUS_25km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index 6db673ff7a..98f586e706 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_CONUS_25km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_CONUS_25km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -8,6 +8,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: CONUS_25km_GFDLgrid DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -19,5 +20,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: CONUS_25km_GFDLgrid diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_CONUS_3km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_CONUS_3km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index cfc8c9022e..8b25ba7017 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_CONUS_3km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_CONUS_3km_GFDLgrid_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -8,6 +8,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: CONUS_3km_GFDLgrid DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -19,5 +20,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: CONUS_3km_GFDLgrid diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_AK_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_AK_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index 448d147b2a..3ec6ffd247 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_AK_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_AK_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_AK_13km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 6 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_AK_13km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_AK_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_AK_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index 3f23a3634b..2e6caf0b12 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_AK_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_AK_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_AK_3km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 6 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_AK_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml index 4cdda3773d..e034ccb453 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_13km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_13km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index 5d1047a399..4fac3cf1ec 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUS_13km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_13km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml index 74fc5dc55b..c20617f78c 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUS_13km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_13km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml index e682260e7d..5047e6854a 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUS_13km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_13km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp.yaml index 10fcfc4705..f07904f058 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_2017_gfdlmp + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp_regional.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp_regional.yaml index 9e0720319d..7a27c095ec 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp_regional.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp_regional.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_2017_gfdlmp_regional + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 6 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml index a4e561bf44..f3b26934d9 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index 2f75756cde..f582575176 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml index 06c7a8e8ea..30e65ed3d6 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml index a4f951174e..0304ee9561 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_RAP_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_RAP_suite_HRRR.yaml index d2c63d16a8..526ba26496 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_RAP_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_RAP_suite_HRRR.yaml @@ -11,6 +11,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 6 @@ -25,5 +26,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_2017_gfdlmp.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_2017_gfdlmp.yaml index 6638c5698a..3d1f4e6fb0 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_2017_gfdlmp.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_2017_gfdlmp.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_2017_gfdlmp + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019052000' DATE_LAST_CYCL: '2019052000' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: GSMGFS LBC_SPEC_INTVL_HRS: 6 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v15p2.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v15p2.yaml index 905a321ef8..0bd7ef392c 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v15p2.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v15p2.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019052000' DATE_LAST_CYCL: '2019052000' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: GSMGFS LBC_SPEC_INTVL_HRS: 6 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v16.yaml index 3d212cce95..ecf18a34d7 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_GSMGFS_lbcs_GSMGFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019052000' DATE_LAST_CYCL: '2019052000' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: GSMGFS LBC_SPEC_INTVL_HRS: 6 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_HRRR.yaml index 10e209af3e..51a717d720 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_HRRR.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2021061500' DATE_LAST_CYCL: '2021061500' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: NAM LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_RRFS_v1beta.yaml index ea88871abc..191df39ae4 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_25km_ics_NAM_lbcs_NAM_suite_RRFS_v1beta.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2021061500' DATE_LAST_CYCL: '2021061500' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: NAM LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15_thompson_mynn_lam3km.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15_thompson_mynn_lam3km.yaml index 61e66aa422..b1e237e0ca 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15_thompson_mynn_lam3km.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15_thompson_mynn_lam3km.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15_thompson_mynn_lam3km + PREDEF_GRID_NAME: RRFS_CONUS_3km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -19,5 +20,4 @@ task_get_extrn_lbcs: LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_3km USE_MERRA_CLIMO: true diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml index 5ab1079d34..1df625c3e5 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15p2.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_3km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index cfa905f250..71919a759e 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUS_3km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml index 9c64581c41..41305029ff 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_HRRR.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUS_3km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml index 1cd8234708..3ad76c7a5f 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUS_3km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index 2c7f2a9902..ca190522fa 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUScompact_13km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_13km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml index d01a2ba1cb..d631bdf8d6 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml @@ -8,6 +8,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUScompact_13km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 6 @@ -23,5 +24,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_13km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml index 8dd3ba2ae2..e53dbad8dc 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_13km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUScompact_13km DATE_FIRST_CYCL: '2020080100' DATE_LAST_CYCL: '2020080100' FCST_LEN_HRS: 6 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_13km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index 7632d6234f..f79f039f2b 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_HRRR.yaml index a68751923e..d3a36fc970 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_HRRR.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 24 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_RRFS_v1beta.yaml index e4feb98a39..aa91edfccb 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_HRRR_suite_RRFS_v1beta.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 24 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml index b255e5b12e..84098b1d07 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 6 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml index fbffddf60d..d83d0a91b4 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 3 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_25km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index bb1b456c27..fac46ebe0c 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUScompact_3km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml index 4b3180596e..e151746bd8 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUScompact_3km DATE_FIRST_CYCL: '2020080100' DATE_LAST_CYCL: '2020080100' FCST_LEN_HRS: 6 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml index 56f1452b3b..b00a24ae84 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUScompact_3km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 6 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml index 2eee7019b4..44dfec5e75 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_CONUScompact_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml @@ -8,6 +8,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUScompact_3km DATE_FIRST_CYCL: '2020080100' DATE_LAST_CYCL: '2020080100' FCST_LEN_HRS: 6 @@ -23,5 +24,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_NA_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_NA_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml index 662116f2b2..0d0d6a847b 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_NA_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_NA_13km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml @@ -10,6 +10,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_NA_13km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -31,7 +32,6 @@ task_make_lbcs: WTIME_MAKE_LBCS: 01:00:00 task_run_fcst: OMP_STACKSIZE_RUN_FCST: 2048m - PREDEF_GRID_NAME: RRFS_NA_13km task_run_post: NNODES_RUN_POST: 6 PPN_RUN_POST: 12 diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_NA_3km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_NA_3km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml index 8b6da1b2a6..156e1d6360 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_NA_3km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_NA_3km_ics_FV3GFS_lbcs_FV3GFS_suite_RRFS_v1beta.yaml @@ -10,10 +10,13 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_NA_3km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 PREEXISTING_DIR_METHOD: rename +task_make_orog: + WTIME_MAKE_OROG: 01:00:00 task_get_extrn_ics: EXTRN_MDL_NAME_ICS: FV3GFS USE_USER_STAGED_EXTRN_FILES: true @@ -21,8 +24,6 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 6 USE_USER_STAGED_EXTRN_FILES: true -task_make_orog: - WTIME_MAKE_OROG: 01:00:00 task_make_ics: NNODES_MAKE_ICS: 12 PPN_MAKE_ICS: 4 @@ -33,7 +34,6 @@ task_make_lbcs: WTIME_MAKE_LBCS: 01:00:00 task_run_fcst: OMP_STACKSIZE_RUN_FCST: 2048m - PREDEF_GRID_NAME: RRFS_NA_3km task_run_post: NNODES_RUN_POST: 8 PPN_RUN_POST: 12 diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_SUBCONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_SUBCONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index a51bcbb346..60a83ce68d 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_SUBCONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_SUBCONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_SUBCONUS_3km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_SUBCONUS_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_SUBCONUS_3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_SUBCONUS_3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml index 6842aa2100..b28755e521 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_SUBCONUS_3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_RRFS_SUBCONUS_3km_ics_HRRR_lbcs_RAP_suite_GFS_v15p2.yaml @@ -8,6 +8,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_SUBCONUS_3km DATE_FIRST_CYCL: '2020080100' DATE_LAST_CYCL: '2020080100' FCST_LEN_HRS: 6 @@ -23,5 +24,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_SUBCONUS_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index 971b2d3d54..abdc2c9f81 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: SUBCONUS_Ind_3km DATE_FIRST_CYCL: '2019061518' DATE_LAST_CYCL: '2019061518' FCST_LEN_HRS: 6 @@ -20,5 +21,3 @@ task_get_extrn_lbcs: LBC_SPEC_INTVL_HRS: 6 FV3GFS_FILE_FMT_LBCS: grib2 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: SUBCONUS_Ind_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml index 199eb388e3..baa6173237 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: SUBCONUS_Ind_3km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 6 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: SUBCONUS_Ind_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml index a025df00e4..94f794c78e 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_community/config.grid_SUBCONUS_Ind_3km_ics_HRRR_lbcs_RAP_suite_RRFS_v1beta.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: SUBCONUS_Ind_3km DATE_FIRST_CYCL: '2020080100' DATE_LAST_CYCL: '2020080100' FCST_LEN_HRS: 6 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: SUBCONUS_Ind_3km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml index ba302d8e67..4ef3f80834 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_13km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: nco workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUS_13km DATE_FIRST_CYCL: '2019061500' DATE_LAST_CYCL: '2019061500' FCST_LEN_HRS: 6 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: grib2 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_13km diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml index bbfb59f8c5..9709986da7 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_timeoffset_suite_GFS_v16.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: nco workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2022081012' DATE_LAST_CYCL: '2022081012' FCST_LEN_HRS: 6 @@ -17,12 +18,10 @@ workflow_switches: RUN_TASK_MAKE_SFC_CLIMO: false task_get_extrn_ics: EXTRN_MDL_NAME_ICS: FV3GFS - FV3GFS_FILE_FMT_ICS: netcdf EXTRN_MDL_ICS_OFFSET_HRS: 6 + FV3GFS_FILE_FMT_ICS: netcdf task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS - FV3GFS_FILE_FMT_LBCS: netcdf LBC_SPEC_INTVL_HRS: 3 EXTRN_MDL_LBCS_OFFSET_HRS: 6 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km + FV3GFS_FILE_FMT_LBCS: netcdf diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15_thompson_mynn_lam3km.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15_thompson_mynn_lam3km.yaml index 6f7e723756..350bac9fd2 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15_thompson_mynn_lam3km.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUS_3km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_v15_thompson_mynn_lam3km.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: nco workflow: CCPP_PHYS_SUITE: FV3_GFS_v15_thompson_mynn_lam3km + PREDEF_GRID_NAME: RRFS_CONUS_3km DATE_FIRST_CYCL: '2019061500' DATE_LAST_CYCL: '2019061500' FCST_LEN_HRS: 6 @@ -23,5 +24,4 @@ task_get_extrn_lbcs: LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: grib2 task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_3km USE_MERRA_CLIMO: true diff --git a/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml index 3519878448..287465aeea 100644 --- a/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml +++ b/tests/WE2E/test_configs/grids_extrn_mdls_suites_nco/config.nco_grid_RRFS_CONUScompact_25km_ics_HRRR_lbcs_RAP_suite_HRRR.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: nco workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 6 @@ -28,4 +29,3 @@ task_get_extrn_lbcs: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' task_run_fcst: WRITE_DOPOST: true - PREDEF_GRID_NAME: RRFS_CONUScompact_25km diff --git a/tests/WE2E/test_configs/release_SRW_v1/config.GST_release_public_v1.yaml b/tests/WE2E/test_configs/release_SRW_v1/config.GST_release_public_v1.yaml index eb450a5a79..72dc3e169e 100644 --- a/tests/WE2E/test_configs/release_SRW_v1/config.GST_release_public_v1.yaml +++ b/tests/WE2E/test_configs/release_SRW_v1/config.GST_release_public_v1.yaml @@ -6,13 +6,11 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019061500' DATE_LAST_CYCL: '2019061500' FCST_LEN_HRS: 48 PREEXISTING_DIR_METHOD: rename -task_run_fcst: - WTIME_RUN_FCST: 01:00:00 - PREDEF_GRID_NAME: RRFS_CONUS_25km task_get_extrn_ics: EXTRN_MDL_NAME_ICS: FV3GFS FV3GFS_FILE_FMT_ICS: grib2 @@ -22,3 +20,5 @@ task_get_extrn_lbcs: LBC_SPEC_INTVL_HRS: 6 FV3GFS_FILE_FMT_LBCS: grib2 USE_USER_STAGED_EXTRN_FILES: true +task_run_fcst: + WTIME_RUN_FCST: 01:00:00 diff --git a/tests/WE2E/test_configs/wflow_features/config.MET_ensemble_verification.yaml b/tests/WE2E/test_configs/wflow_features/config.MET_ensemble_verification.yaml index 45b98e2167..4299c2b795 100644 --- a/tests/WE2E/test_configs/wflow_features/config.MET_ensemble_verification.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.MET_ensemble_verification.yaml @@ -8,6 +8,7 @@ platform: MODEL: FV3_GFS_v15p2_CONUS_25km workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019061500' DATE_LAST_CYCL: '2019061500' FCST_LEN_HRS: 6 @@ -28,7 +29,6 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true task_run_fcst: WTIME_RUN_FCST: 01:00:00 - PREDEF_GRID_NAME: RRFS_CONUS_25km global: DO_ENSEMBLE: true NUM_ENS_MEMBERS: 2 diff --git a/tests/WE2E/test_configs/wflow_features/config.MET_verification.yaml b/tests/WE2E/test_configs/wflow_features/config.MET_verification.yaml index 178cba9c6f..06569a9195 100644 --- a/tests/WE2E/test_configs/wflow_features/config.MET_verification.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.MET_verification.yaml @@ -8,6 +8,7 @@ platform: MODEL: FV3_GFS_v15p2_CONUS_25km workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019061500' DATE_LAST_CYCL: '2019061500' FCST_LEN_HRS: 6 @@ -26,4 +27,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true task_run_fcst: WTIME_RUN_FCST: 01:00:00 - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.community_ensemble_008mems.yaml b/tests/WE2E/test_configs/wflow_features/config.community_ensemble_008mems.yaml index b273aaf8cb..e7e8ae4e84 100644 --- a/tests/WE2E/test_configs/wflow_features/config.community_ensemble_008mems.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.community_ensemble_008mems.yaml @@ -10,6 +10,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_2017_gfdlmp + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070212' INCR_CYCL_FREQ: 12 @@ -22,8 +23,6 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km global: DO_ENSEMBLE: true NUM_ENS_MEMBERS: 8 diff --git a/tests/WE2E/test_configs/wflow_features/config.community_ensemble_2mems.yaml b/tests/WE2E/test_configs/wflow_features/config.community_ensemble_2mems.yaml index 7646a8f3bf..8e52964f0a 100644 --- a/tests/WE2E/test_configs/wflow_features/config.community_ensemble_2mems.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.community_ensemble_2mems.yaml @@ -13,6 +13,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_2017_gfdlmp + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070212' INCR_CYCL_FREQ: 12 @@ -25,8 +26,6 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km global: DO_ENSEMBLE: true NUM_ENS_MEMBERS: 2 diff --git a/tests/WE2E/test_configs/wflow_features/config.community_ensemble_2mems_stoch.yaml b/tests/WE2E/test_configs/wflow_features/config.community_ensemble_2mems_stoch.yaml index 67bc91e71b..ab5c6bdde0 100644 --- a/tests/WE2E/test_configs/wflow_features/config.community_ensemble_2mems_stoch.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.community_ensemble_2mems_stoch.yaml @@ -11,12 +11,11 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: SUBCONUS_Ind_3km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 3 PREEXISTING_DIR_METHOD: rename -task_run_fcst: - PREDEF_GRID_NAME: SUBCONUS_Ind_3km task_get_extrn_ics: EXTRN_MDL_NAME_ICS: HRRR USE_USER_STAGED_EXTRN_FILES: true diff --git a/tests/WE2E/test_configs/wflow_features/config.deactivate_tasks.yaml b/tests/WE2E/test_configs/wflow_features/config.deactivate_tasks.yaml index f6758dc15d..5defa0bf98 100644 --- a/tests/WE2E/test_configs/wflow_features/config.deactivate_tasks.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.deactivate_tasks.yaml @@ -20,6 +20,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -38,5 +39,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019061200.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019061200.yaml index 9861ea10ee..2f1733dcdc 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019061200.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019061200.yaml @@ -8,6 +8,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019061200' DATE_LAST_CYCL: '2019061200' FCST_LEN_HRS: 6 @@ -19,5 +20,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: grib2 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019101818.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019101818.yaml index cad54c746b..da8d40bc4a 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019101818.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2019101818.yaml @@ -10,6 +10,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019101818' DATE_LAST_CYCL: '2019101818' FCST_LEN_HRS: 6 @@ -21,5 +22,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: grib2 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2020022518.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2020022518.yaml index 96bdf56151..ecba3523c7 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2020022518.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2020022518.yaml @@ -9,6 +9,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2020022518' DATE_LAST_CYCL: '2020022518' FCST_LEN_HRS: 6 @@ -20,5 +21,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: grib2 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2020022600.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2020022600.yaml index 2b5e3ff026..764ebaf16d 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2020022600.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2020022600.yaml @@ -9,6 +9,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2020022600' DATE_LAST_CYCL: '2020022600' FCST_LEN_HRS: 6 @@ -20,5 +21,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: grib2 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2021010100.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2021010100.yaml index eae43995e6..c66933e646 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2021010100.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_grib2_2021010100.yaml @@ -9,6 +9,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2021010100' DATE_LAST_CYCL: '2021010100' FCST_LEN_HRS: 6 @@ -20,5 +21,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: grib2 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio.yaml index 825d6cf737..84f2ee2900 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_2017_gfdlmp + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -16,5 +17,3 @@ task_get_extrn_ics: task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019061200.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019061200.yaml index fdcb63f6b2..294442641a 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019061200.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019061200.yaml @@ -8,6 +8,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019061200' DATE_LAST_CYCL: '2019061200' FCST_LEN_HRS: 6 @@ -19,5 +20,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: nemsio -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019101818.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019101818.yaml index be3afcc55e..922a7074fd 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019101818.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2019101818.yaml @@ -10,6 +10,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019101818' DATE_LAST_CYCL: '2019101818' FCST_LEN_HRS: 6 @@ -21,5 +22,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: nemsio -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2020022518.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2020022518.yaml index ab94e5f5d7..f1b86257c4 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2020022518.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2020022518.yaml @@ -9,6 +9,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2020022518' DATE_LAST_CYCL: '2020022518' FCST_LEN_HRS: 6 @@ -20,5 +21,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: nemsio -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2020022600.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2020022600.yaml index 3fd247724f..047506e591 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2020022600.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2020022600.yaml @@ -9,6 +9,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2020022600' DATE_LAST_CYCL: '2020022600' FCST_LEN_HRS: 6 @@ -20,5 +21,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: nemsio -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2021010100.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2021010100.yaml index 2452697445..1bd80d361e 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2021010100.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio_2021010100.yaml @@ -9,6 +9,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2021010100' DATE_LAST_CYCL: '2021010100' FCST_LEN_HRS: 6 @@ -20,5 +21,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: nemsio -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2021062000.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2021062000.yaml index 0f169fe266..0765846138 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2021062000.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2021062000.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2021062000' DATE_LAST_CYCL: '2021062000' FCST_LEN_HRS: 6 @@ -18,5 +19,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: netcdf -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2022060112_48h.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2022060112_48h.yaml index 2beab31369..d6c6f68088 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2022060112_48h.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_FV3GFS_lbcs_FV3GFS_fmt_netcdf_2022060112_48h.yaml @@ -7,12 +7,11 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2022060112' DATE_LAST_CYCL: '2022060112' FCST_LEN_HRS: 48 PREEXISTING_DIR_METHOD: rename -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km task_get_extrn_ics: EXTRN_MDL_NAME_ICS: FV3GFS FV3GFS_FILE_FMT_ICS: netcdf diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_GSMGFS_lbcs_GSMGFS.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_GSMGFS_lbcs_GSMGFS.yaml index 2539a5a440..a7f4670035 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_GSMGFS_lbcs_GSMGFS.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_GSMGFS_lbcs_GSMGFS.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_2017_gfdlmp + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019052000' DATE_LAST_CYCL: '2019052000' FCST_LEN_HRS: 6 @@ -16,5 +17,3 @@ task_get_extrn_ics: task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: GSMGFS LBC_SPEC_INTVL_HRS: 6 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_HRRR_lbcs_RAP.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_HRRR_lbcs_RAP.yaml index f8425df483..9821a4b6ce 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_HRRR_lbcs_RAP.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_HRRR_lbcs_RAP.yaml @@ -9,6 +9,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2020080100' DATE_LAST_CYCL: '2020080100' FCST_LEN_HRS: 6 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: LBC_SPEC_INTVL_HRS: 3 EXTRN_MDL_FILES_LBCS: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUScompact_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_RAP_lbcs_RAP.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_RAP_lbcs_RAP.yaml index 6599e5ca15..ef3386913b 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_RAP_lbcs_RAP.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_HPSS_ics_RAP_lbcs_RAP.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019052000' DATE_LAST_CYCL: '2019052000' FCST_LEN_HRS: 6 @@ -16,5 +17,3 @@ task_get_extrn_ics: task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: RAP LBC_SPEC_INTVL_HRS: 3 -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.get_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio.yaml b/tests/WE2E/test_configs/wflow_features/config.get_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS.yaml similarity index 68% rename from tests/WE2E/test_configs/wflow_features/config.get_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio.yaml rename to tests/WE2E/test_configs/wflow_features/config.get_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS.yaml index 5ec180b13e..7b30698ef2 100644 --- a/tests/WE2E/test_configs/wflow_features/config.get_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS_fmt_nemsio.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.get_from_NOMADS_ics_FV3GFS_lbcs_FV3GFS.yaml @@ -5,20 +5,19 @@ metadata: (from which ICs and LBCs will be derived). user: RUN_ENVIR: community +platform: + EXTRN_MDL_DATA_STORES: nomads hpss aws workflow: CCPP_PHYS_SUITE: FV3_GFS_2017_gfdlmp - DATE_FIRST_CYCL: '2020082600' - DATE_LAST_CYCL: '2020082600' + PREDEF_GRID_NAME: RRFS_CONUS_25km + DATE_FIRST_CYCL: date --utc --date="2 days ago" +%Y%m%d00 + DATE_LAST_CYCL: date --utc --date="2 days ago" +%Y%m%d00 FCST_LEN_HRS: 6 PREEXISTING_DIR_METHOD: rename task_get_extrn_ics: EXTRN_MDL_NAME_ICS: FV3GFS - NOMADS: true - NOMADS_file_type: NEMSIO + FV3GFS_FILE_FMT_ICS: netcdf task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 - NOMADS: true - NOMADS_file_type: NEMSIO -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km + FV3GFS_FILE_FMT_LBCS: netcdf diff --git a/tests/WE2E/test_configs/wflow_features/config.inline_post.yaml b/tests/WE2E/test_configs/wflow_features/config.inline_post.yaml index 1c5a30a798..bc0d464d85 100644 --- a/tests/WE2E/test_configs/wflow_features/config.inline_post.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.inline_post.yaml @@ -6,6 +6,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -19,4 +20,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true task_run_fcst: WRITE_DOPOST: true - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.nco_ensemble.yaml b/tests/WE2E/test_configs/wflow_features/config.nco_ensemble.yaml index ce410707c0..d12aeb80f6 100644 --- a/tests/WE2E/test_configs/wflow_features/config.nco_ensemble.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.nco_ensemble.yaml @@ -13,6 +13,7 @@ user: RUN_ENVIR: nco workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070212' INCR_CYCL_FREQ: 12 @@ -29,8 +30,6 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km global: DO_ENSEMBLE: true NUM_ENS_MEMBERS: 2 diff --git a/tests/WE2E/test_configs/wflow_features/config.pregen_grid_orog_sfc_climo.yaml b/tests/WE2E/test_configs/wflow_features/config.pregen_grid_orog_sfc_climo.yaml index 9c0ea38c77..8ccf1a4bd6 100644 --- a/tests/WE2E/test_configs/wflow_features/config.pregen_grid_orog_sfc_climo.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.pregen_grid_orog_sfc_climo.yaml @@ -6,6 +6,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -21,5 +22,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.specify_DOT_OR_USCORE.yaml b/tests/WE2E/test_configs/wflow_features/config.specify_DOT_OR_USCORE.yaml index 54bfca45e7..515569aa3a 100644 --- a/tests/WE2E/test_configs/wflow_features/config.specify_DOT_OR_USCORE.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.specify_DOT_OR_USCORE.yaml @@ -18,6 +18,7 @@ user: workflow: DOT_OR_USCORE: . CCPP_PHYS_SUITE: FV3_GFS_2017_gfdlmp + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019052000' DATE_LAST_CYCL: '2019052000' FCST_LEN_HRS: 6 @@ -29,5 +30,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: GSMGFS LBC_SPEC_INTVL_HRS: 6 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.specify_DT_ATMOS_LAYOUT_XY_BLOCKSIZE.yaml b/tests/WE2E/test_configs/wflow_features/config.specify_DT_ATMOS_LAYOUT_XY_BLOCKSIZE.yaml index 94566e29d3..e7dd5f62f0 100644 --- a/tests/WE2E/test_configs/wflow_features/config.specify_DT_ATMOS_LAYOUT_XY_BLOCKSIZE.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.specify_DT_ATMOS_LAYOUT_XY_BLOCKSIZE.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_HRRR + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2020080100' DATE_LAST_CYCL: '2020080100' FCST_LEN_HRS: 6 @@ -27,4 +28,3 @@ task_run_fcst: LAYOUT_X: 10 LAYOUT_Y: 4 BLOCKSIZE: 35 - PREDEF_GRID_NAME: RRFS_CONUScompact_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.specify_EXTRN_MDL_SYSBASEDIR_ICS_LBCS.yaml b/tests/WE2E/test_configs/wflow_features/config.specify_EXTRN_MDL_SYSBASEDIR_ICS_LBCS.yaml index 2222127c3d..68b35b56db 100644 --- a/tests/WE2E/test_configs/wflow_features/config.specify_EXTRN_MDL_SYSBASEDIR_ICS_LBCS.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.specify_EXTRN_MDL_SYSBASEDIR_ICS_LBCS.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2021061500' DATE_LAST_CYCL: '2021061500' FCST_LEN_HRS: 6 @@ -20,5 +21,3 @@ task_get_extrn_lbcs: LBC_SPEC_INTVL_HRS: 3 FV3GFS_FILE_FMT_LBCS: grib2 EXTRN_MDL_SYSBASEDIR_LBCS: set_to_non_default_location_in_testing_script -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.specify_RESTART_INTERVAL.yaml b/tests/WE2E/test_configs/wflow_features/config.specify_RESTART_INTERVAL.yaml index 9c974b8e7f..954576895b 100644 --- a/tests/WE2E/test_configs/wflow_features/config.specify_RESTART_INTERVAL.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.specify_RESTART_INTERVAL.yaml @@ -7,6 +7,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -20,4 +21,3 @@ task_get_extrn_lbcs: USE_USER_STAGED_EXTRN_FILES: true task_run_fcst: RESTART_INTERVAL: 1 - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.specify_template_filenames.yaml b/tests/WE2E/test_configs/wflow_features/config.specify_template_filenames.yaml index 289c63e2da..8fdff3997b 100644 --- a/tests/WE2E/test_configs/wflow_features/config.specify_template_filenames.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.specify_template_filenames.yaml @@ -11,6 +11,7 @@ workflow: MODEL_CONFIG_TMPL_FN: model_configure NEMS_CONFIG_TMPL_FN: nems.configure CCPP_PHYS_SUITE: FV3_GFS_v15p2 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019070100' DATE_LAST_CYCL: '2019070100' FCST_LEN_HRS: 6 @@ -22,5 +23,3 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: FV3GFS LBC_SPEC_INTVL_HRS: 3 USE_USER_STAGED_EXTRN_FILES: true -task_run_fcst: - PREDEF_GRID_NAME: RRFS_CONUS_25km diff --git a/tests/WE2E/test_configs/wflow_features/config.subhourly_post.yaml b/tests/WE2E/test_configs/wflow_features/config.subhourly_post.yaml index 5916ad4ca9..bf5f54201b 100644 --- a/tests/WE2E/test_configs/wflow_features/config.subhourly_post.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.subhourly_post.yaml @@ -6,6 +6,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 3 @@ -23,7 +24,6 @@ task_get_extrn_lbcs: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' task_run_fcst: DT_ATMOS: 120 - PREDEF_GRID_NAME: RRFS_CONUScompact_25km task_run_post: SUB_HOURLY_POST: true DT_SUBHOURLY_POST_MNTS: 2 diff --git a/tests/WE2E/test_configs/wflow_features/config.subhourly_post_ensemble_2mems.yaml b/tests/WE2E/test_configs/wflow_features/config.subhourly_post_ensemble_2mems.yaml index 038b3d9466..08518f5b0f 100644 --- a/tests/WE2E/test_configs/wflow_features/config.subhourly_post_ensemble_2mems.yaml +++ b/tests/WE2E/test_configs/wflow_features/config.subhourly_post_ensemble_2mems.yaml @@ -11,6 +11,7 @@ user: RUN_ENVIR: community workflow: CCPP_PHYS_SUITE: FV3_RRFS_v1beta + PREDEF_GRID_NAME: RRFS_CONUScompact_25km DATE_FIRST_CYCL: '2020081000' DATE_LAST_CYCL: '2020081000' FCST_LEN_HRS: 3 @@ -28,7 +29,6 @@ task_get_extrn_lbcs: - '{yy}{jjj}{hh}00{fcst_hr:02d}00' task_run_fcst: DT_ATMOS: 120 - PREDEF_GRID_NAME: RRFS_CONUScompact_25km task_run_post: SUB_HOURLY_POST: true DT_SUBHOURLY_POST_MNTS: 12 diff --git a/ush/NOMADS_get_extrn_mdl_files.sh b/ush/NOMADS_get_extrn_mdl_files.sh deleted file mode 100755 index 789eeff3dc..0000000000 --- a/ush/NOMADS_get_extrn_mdl_files.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash -# Command line arguments -if [ -z "$1" -o -z "$2" ]; then - echo "Usage: $0 yyyymmdd hh file_fmt nfcst nfcst_int" - echo "yyymmdd and hh are required and other variables are optional" - exit -fi -## date (year month day) and time (hour) -yyyymmdd=$1 #i.e. "20191224" -hh=$2 #i.e. "12" -## -## file format (grib2 or nemsio), the default format is grib2 -if [ "$#" -ge 3 ]; then - file_fmt=$3 -else - file_fmt="grib2" -fi -## forecast length, the default value are 6 hours -if [ "$#" -ge 4 ]; then - nfcst=$4 -else - nfcst=6 -fi -## forecast interval, the default interval are 3 hours -if [ "$#" -ge 5 ]; then - nfcst_int=$5 -else - nfcst_int=3 -fi - -# Get the data (do not need to edit anything after this point!) -yyyymm=$((yyyymmdd/100)) -#din_loc_ic=`./xmlquery DIN_LOC_IC --value` -mkdir -p gfs.$yyyymmdd/$hh -echo "Download files to $din_loc_ic/$yyyymm/$yyyymmdd ..." -cd gfs.$yyyymmdd/$hh - -#getting online analysis data -if [ $file_fmt == "grib2" ] || [ $file_fmt == "GRIB2" ]; then - wget --tries=2 -c https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.$yyyymmdd/$hh/gfs.t${hh}z.pgrb2.0p25.f000 -else - wget --tries=2 -c https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.$yyyymmdd/$hh/gfs.t${hh}z.atmanl.nemsio - wget --tries=2 -c https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.$yyyymmdd/$hh/gfs.t${hh}z.sfcanl.nemsio -fi - -#getting online forecast data -ifcst=$nfcst_int -while [ $ifcst -le $nfcst ] -do -echo $ifcst - if [ $ifcst -le 99 ]; then - if [ $ifcst -le 9 ]; then - ifcst_str="00"$ifcst - else - ifcst_str="0"$ifcst - fi - else - ifcst_str="$ifcst" - fi - echo $ifcst_str -# -if [ $file_fmt == "grib2" ] || [ $file_fmt == "GRIB2" ]; then - wget --tries=2 -c https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.$yyyymmdd/$hh/gfs.t${hh}z.pgrb2.0p25.f${ifcst_str} -else - wget --tries=2 -c https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.$yyyymmdd/$hh/gfs.t${hh}z.atmf${ifcst_str}.nemsio - wget --tries=2 -c https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.$yyyymmdd/$hh/gfs.t${hh}z.sfcf${ifcst_str}.nemsio -fi -# -ifcst=$[$ifcst+$nfcst_int] -done diff --git a/ush/bash_utils/source_config.sh b/ush/bash_utils/source_config.sh index 5d0d047d00..df5a79a0df 100644 --- a/ush/bash_utils/source_config.sh +++ b/ush/bash_utils/source_config.sh @@ -6,48 +6,7 @@ # function config_to_str() { -# -#----------------------------------------------------------------------- -# -# Save current shell options (in a global array). Then set new options -# for this script/function. -# -#----------------------------------------------------------------------- -# - { save_shell_opts; . ${USHdir}/preamble.sh; } > /dev/null 2>&1 - -# -#----------------------------------------------------------------------- -# -# Get the full path to the file in which this script/function is located -# (scrfunc_fp), the name of that file (scrfunc_fn), and the directory in -# which the file is located (scrfunc_dir). -# -#----------------------------------------------------------------------- -# - local scrfunc_fp=$( $READLINK -f "${BASH_SOURCE[0]}" ) - local scrfunc_fn=$( basename "${scrfunc_fp}" ) - local scrfunc_dir=$( dirname "${scrfunc_fp}" ) - -# -#----------------------------------------------------------------------- -# Get the contents of a config file as shell string -#----------------------------------------------------------------------- -# - local ushdir=${scrfunc_dir%/*} - - $ushdir/config_utils.py -o $1 -c $2 "${@:3}" - -# -#----------------------------------------------------------------------- -# -# Restore the shell options saved at the beginning of this script/func- -# tion. -# -#----------------------------------------------------------------------- -# - { restore_shell_opts; } > /dev/null 2>&1 - + $USHdir/config_utils.py -o $1 -c $2 "${@:3}" } # diff --git a/ush/config.community.yaml b/ush/config.community.yaml index 5a13ffeb9d..3769bd3183 100644 --- a/ush/config.community.yaml +++ b/ush/config.community.yaml @@ -15,6 +15,7 @@ platform: workflow: EXPT_SUBDIR: test_community CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2019061518' DATE_LAST_CYCL: '2019061518' FCST_LEN_HRS: 12 @@ -42,7 +43,6 @@ task_get_extrn_lbcs: task_run_fcst: WTIME_RUN_FCST: 02:00:00 QUILTING: true - PREDEF_GRID_NAME: RRFS_CONUS_25km global: DO_ENSEMBLE: false NUM_ENS_MEMBERS: 2 diff --git a/ush/config.nco.yaml b/ush/config.nco.yaml index e8cb83ad58..f6971ac732 100644 --- a/ush/config.nco.yaml +++ b/ush/config.nco.yaml @@ -8,6 +8,7 @@ user: workflow: EXPT_SUBDIR: test_nco CCPP_PHYS_SUITE: FV3_GFS_v16 + PREDEF_GRID_NAME: RRFS_CONUS_25km DATE_FIRST_CYCL: '2022040700' DATE_LAST_CYCL: '2022040700' FCST_LEN_HRS: 6 @@ -34,6 +35,5 @@ task_run_fcst: WTIME_RUN_FCST: 01:00:00 WRITE_DOPOST: true QUILTING: true - PREDEF_GRID_NAME: RRFS_CONUS_25km task_run_post: POST_OUTPUT_DOMAIN_NAME: conus_25km diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index ac1a7b91af..295fc17781 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -3,8 +3,8 @@ #---------------------------- metadata: description: >- - Default configuration for an experiment. The valid values each parameter - takes are specified in valid_param_vals.yaml + Default configuration for an experiment. The valid values for most of the + parameters are specified in valid_param_vals.yaml version: !!str '1.0' #---------------------------- # USER config parameters @@ -333,6 +333,47 @@ platform: TEST_PREGEN_BASEDIR: "" TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS: "" TEST_ALT_EXTRN_MDL_SYSBASEDIR_LBCS: "" + # + #----------------------------------------------------------------------- + # + # Set parameters associated with the fixed (i.e. static) files. Definitions: + # + # FIXgsm: + # System directory in which the majority of fixed (i.e. time-independent) + # files that are needed to run the FV3-LAM model are located + # + # FIXaer: + # System directory where MERRA2 aerosol climatology files are located + # + # FIXlut: + # System directory where the lookup tables for optics properties are located + # + # FIXorg: + # System directory where orography data is located + # + # FIXsfc: + # System directory where surface climatology data is located + # + #----------------------------------------------------------------------- + # + FIXgsm: "" + FIXaer: "" + FIXlut: "" + FIXorg: "" + FIXsfc: "" + # + #----------------------------------------------------------------------- + # + # EXTRN_MDL_DATA_STORES: + # A list of data stores where the scripts should look for external model + # data. The list is in priority order. If disk information is provided + # via USE_USER_STAGED_EXTRN_FILES or a known location on the platform, + # the disk location will be highest priority. Options are disk, hpss, + # aws, and nomads. + # + #----------------------------------------------------------------------- + # + EXTRN_MDL_DATA_STORES: "" #----------------------------- # WORKFLOW config parameters @@ -569,6 +610,40 @@ workflow: # #----------------------------------------------------------------------- # + # Set PREDEF_GRID_NAME. This parameter specifies a predefined regional + # grid, as follows: + # + # * If PREDEF_GRID_NAME is set to a valid predefined grid name, the grid + # generation method GRID_GEN_METHOD, the (native) grid parameters, and + # the write-component grid parameters are set to predefined values for + # the specified grid, overwriting any settings of these parameters in + # the user-specified experiment configuration file. In addition, if + # the time step DT_ATMOS and the computational parameters LAYOUT_X, + # LAYOUT_Y, and BLOCKSIZE are not specified in that configuration file, + # they are also set to predefined values for the specified grid. + # + # * If PREDEF_GRID_NAME is set to an empty string, it implies the user + # is providing the native grid parameters in the user-specified + # experiment configuration file (EXPT_CONFIG_FN). In this case, the + # grid generation method GRID_GEN_METHOD, the native grid parameters, + # and the write-component grid parameters as well as the time step + # forecast model's main time step DT_ATMOS and the computational + # parameters LAYOUT_X, LAYOUT_Y, and BLOCKSIZE must be set in that + # configuration file; otherwise, the values of all of these parameters + # in this default experiment configuration file will be used. + # + # Setting PREDEF_GRID_NAME provides a convenient method of specifying a + # commonly used set of grid-dependent parameters. The predefined grid + # parameters are specified in the script + # + # $HOMEdir/ush/set_predef_grid_params.py + # + #----------------------------------------------------------------------- + # + PREDEF_GRID_NAME: "" + # + #----------------------------------------------------------------------- + # # Set forecast parameters. Definitions: # # DATE_FIRST_CYCL: @@ -649,16 +724,22 @@ workflow: # be set manually; it is not inherited from the build system in the # ufs-srweather-app directory. # + # SYMLINK_FIX_FILES: + # Symlink fix files to experiment directory if true; otherwise copy the files. + # + # GET_OBS: + # Task modulefile name for all get_obs_* tasks + # + # VX_TN: + # Task modulefile name for all verification tasks + # #------------------------------------------------------------------------ # COMPILER: "intel" + SYMLINK_FIX_FILES: true - #is this the right place? GET_OBS: "get_obs" VX_TN: "run_vx" - VX_ENSGRID_TN: "run_ensgridvx" - VX_ENSGRID_PROB_REFC_TN: "run_ensgridvx_prob_refc" - MAXTRIES_VX_ENSGRID_PROB_REFC: 1 #---------------------------- # NCO specific variables @@ -905,7 +986,7 @@ task_make_grid: ESGgrid_WIDE_HALO_WIDTH: "" ESGgrid_PAZI: "" -#----------------------------------------------------------------------- + #----------------------------------------------------------------------- # # Set parameters specific to the "GFDLgrid" method of generating a regional # grid (i.e. for GRID_GEN_METHOD set to "GFDLgrid"). The following @@ -1097,7 +1178,6 @@ task_make_orog: OMP_NUM_THREADS_MAKE_OROG: 6 OMP_STACKSIZE_MAKE_OROG: "2048m" OROG_DIR: "" - TOPO_DIR: "" #---------------------------- # MAKE SFC CLIMO config parameters @@ -1112,7 +1192,6 @@ task_make_sfc_climo: OMP_NUM_THREADS_MAKE_SFC_CLIMO: 1 OMP_STACKSIZE_MAKE_SFC_CLIMO: "1024m" SFC_CLIMO_DIR: "" - SFC_CLIMO_INPUT_DIR: "" #---------------------------- # EXTRN ICS config parameters @@ -1207,34 +1286,11 @@ task_get_extrn_ics: # Or for FV3GFS grib files: # EXTRN_MDL_FILES_ICS=( gfs.t{hh}z.pgrb2.0p25.f{fcst_hr:03d} ) # - # EXTRN_MDL_DATA_STORES: - # A list of data stores where the scripts should look for external model - # data. The list is in priority order. If disk information is provided - # via USE_USER_STAGED_EXTRN_FILES or a known location on the platform, - # the disk location will be highest priority. Options are disk, hpss, - # aws, and nomads. - # #----------------------------------------------------------------------- # USE_USER_STAGED_EXTRN_FILES: false EXTRN_MDL_SOURCE_BASEDIR_ICS: "" EXTRN_MDL_FILES_ICS: "" - EXTRN_MDL_DATA_STORES: "" - # - #----------------------------------------------------------------------- - # - # Set NOMADS online data associated parameters. Definitions: - # - # NOMADS: - # Flag controlling whether or not using NOMADS online data. - # - # NOMADS_file_type: - # Flag controlling the format of data. - # - #----------------------------------------------------------------------- - # - NOMADS: false - NOMADS_file_type: "nemsio" #---------------------------- # EXTRN LBCS config parameters @@ -1311,23 +1367,11 @@ task_get_extrn_lbcs: # EXTRN_MDL_FILES_LBCS: # Analogous to EXTRN_MDL_FILES_ICS but for LBCs instead of ICs. # - # EXTRN_MDL_DATA_STORES: - # Analogous to EXTRN_MDL_DATA_STORES in ICS but for LBCs - # #----------------------------------------------------------------------- # USE_USER_STAGED_EXTRN_FILES: false EXTRN_MDL_SOURCE_BASEDIR_LBCS: "" EXTRN_MDL_FILES_LBCS: "" - EXTRN_MDL_DATA_STORES: "" - # - #----------------------------------------------------------------------- - # Analogus to NOMADS for ICSs - #----------------------------------------------------------------------- - # - NOMADS: false - NOMADS_file_type: "nemsio" - #---------------------------- # MAKE ICS config parameters @@ -1627,70 +1671,12 @@ task_run_fcst: # #----------------------------------------------------------------------- # - # Set PREDEF_GRID_NAME. This parameter specifies a predefined regional - # grid, as follows: - # - # * If PREDEF_GRID_NAME is set to a valid predefined grid name, the grid - # generation method GRID_GEN_METHOD, the (native) grid parameters, and - # the write-component grid parameters are set to predefined values for - # the specified grid, overwriting any settings of these parameters in - # the user-specified experiment configuration file. In addition, if - # the time step DT_ATMOS and the computational parameters LAYOUT_X, - # LAYOUT_Y, and BLOCKSIZE are not specified in that configuration file, - # they are also set to predefined values for the specified grid. - # - # * If PREDEF_GRID_NAME is set to an empty string, it implies the user - # is providing the native grid parameters in the user-specified - # experiment configuration file (EXPT_CONFIG_FN). In this case, the - # grid generation method GRID_GEN_METHOD, the native grid parameters, - # and the write-component grid parameters as well as the time step - # forecast model's main time step DT_ATMOS and the computational - # parameters LAYOUT_X, LAYOUT_Y, and BLOCKSIZE must be set in that - # configuration file; otherwise, the values of all of these parameters - # in this default experiment configuration file will be used. - # - # Setting PREDEF_GRID_NAME provides a convenient method of specifying a - # commonly used set of grid-dependent parameters. The predefined grid - # parameters are specified in the script - # - # $HOMEdir/ush/set_predef_grid_params.py - # - #----------------------------------------------------------------------- - # - PREDEF_GRID_NAME: "" - # - #----------------------------------------------------------------------- - # # Flag that determines whether MERRA2 aerosol climatology data and # lookup tables for optics properties are obtained # #----------------------------------------------------------------------- # USE_MERRA_CLIMO: false - # - #----------------------------------------------------------------------- - # - # Set parameters associated with the fixed (i.e. static) files. Definitions: - # - # SYMLINK_FIX_FILES: - # Symlink fix files to experiment directory if true; otherwise copy the files. - # - # FIXgsm: - # System directory in which the majority of fixed (i.e. time-independent) - # files that are needed to run the FV3-LAM model are located - # - # FIXaer: - # System directory where MERRA2 aerosol climatology files are located - # - # FIXlut: - # System directory where the lookup tables for optics properties are located - # - #----------------------------------------------------------------------- - # - SYMLINK_FIX_FILES: true - FIXgsm: "" - FIXaer: "" - FIXlut: "" #---------------------------- # POST config parameters @@ -1881,6 +1867,8 @@ task_run_vx_pointstat: # VX_ENSGRID config parameters #----------------------------- task_run_vx_ensgrid: + VX_ENSGRID_TN: "run_ensgridvx" + MAXTRIES_VX_ENSGRID: 1 VX_ENSGRID_03h_TN: "run_ensgridvx_03h" MAXTRIES_VX_ENSGRID_03h: 1 VX_ENSGRID_06h_TN: "run_ensgridvx_06h" @@ -1889,13 +1877,10 @@ task_run_vx_ensgrid: MAXTRIES_VX_ENSGRID_24h: 1 VX_ENSGRID_RETOP_TN: "run_ensgridvx_retop" MAXTRIES_VX_ENSGRID_RETOP: 1 - VX_ENSGRID_PROB_RETOP_TN: "run_ensgridvx_prob_retop" - MAXTRIES_VX_ENSGRID_PROB_RETOP: 1 NNODES_VX_ENSGRID: 1 PPN_VX_ENSGRID: 1 MEM_VX_ENSGRID: 2G WTIME_VX_ENSGRID: 01:00:00 - MAXTRIES_VX_ENSGRID: 1 #---------------------------- @@ -1959,6 +1944,10 @@ task_run_vx_ensgrid_mean_24h: task_run_vx_ensgrid_prob: VX_ENSGRID_PROB_TN: "run_ensgridvx_prob" NNODES_VX_ENSGRID_PROB: 1 + VX_ENSGRID_PROB_RETOP_TN: "run_ensgridvx_prob_retop" + MAXTRIES_VX_ENSGRID_PROB_RETOP: 1 + VX_ENSGRID_PROB_REFC_TN: "run_ensgridvx_prob_refc" + MAXTRIES_VX_ENSGRID_PROB_REFC: 1 PPN_VX_ENSGRID_PROB: 1 MEM_VX_ENSGRID_PROB: 2G WTIME_VX_ENSGRID_PROB: 01:00:00 diff --git a/ush/generate_FV3LAM_wflow.py b/ush/generate_FV3LAM_wflow.py index 79e779b9b4..304afc925e 100755 --- a/ush/generate_FV3LAM_wflow.py +++ b/ush/generate_FV3LAM_wflow.py @@ -10,14 +10,10 @@ from datetime import datetime, timedelta from python_utils import ( - print_info_msg, - print_err_msg_exit, log_info, import_vars, export_vars, cp_vrfy, - cd_vrfy, - rm_vrfy, ln_vrfy, mkdir_vrfy, mv_vrfy, @@ -648,20 +644,6 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = "log.generate_FV3LAM_wflow") -> set_FV3nml_sfc_climo_filenames() - # Call function to get NOMADS data - if NOMADS: - raise Exception("Nomads script does not work!") - - # get_nomads_data( - # NOMADS_file_type, - # EXPTDIR, - # USHdir, - # DATE_FIRST_CYCL, - # CYCL_HRS, - # FCST_LEN_HRS, - # LBC_SPEC_INTVL_HRS, - # ) - # # ----------------------------------------------------------------------- # @@ -737,29 +719,6 @@ def generate_FV3LAM_wflow(USHdir, logfile: str = "log.generate_FV3LAM_wflow") -> mv_vrfy(logfile, EXPTDIR) -def get_nomads_data( - NOMADS_file_type, - EXPTDIR, - USHdir, - DATE_FIRST_CYCL, - CYCL_HRS, - FCST_LEN_HRS, - LBC_SPEC_INTVL_HRS, -): - print("Getting NOMADS online data") - print(f"NOMADS_file_type= {NOMADS_file_type}") - cd_vrfy(EXPTDIR) - NOMADS_script = os.path.join(USHdir, "NOMADS_get_extrn_mdl_files.sh") - run_command( - f"""{NOMADS_script} \ - {date_to_str(DATE_FIRST_CYCL,format='%Y%m%d')} \ - {date_to_str(DATE_FIRST_CYCL,format='%H')} \ - {NOMADS_file_type} \ - {FCST_LEN_HRS} \ - {LBC_SPEC_INTVL_HRS}""" - ) - - def setup_logging(logfile: str = "log.generate_FV3LAM_wflow") -> None: """ Sets up logging, printing high-priority (INFO and higher) messages to screen, and printing all diff --git a/ush/machine/cheyenne.yaml b/ush/machine/cheyenne.yaml index ffb27f2759..932b464937 100644 --- a/ush/machine/cheyenne.yaml +++ b/ush/machine/cheyenne.yaml @@ -21,13 +21,10 @@ platform: TEST_PREGEN_BASEDIR: /glade/p/ral/jntp/UFS_SRW_App/develop/FV3LAM_pregen TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS: /glade/p/ral/jntp/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir TEST_ALT_EXTRN_MDL_SYSBASEDIR_LBCS: /glade/p/ral/jntp/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir -task_make_orog: - TOPO_DIR: /glade/p/ral/jntp/UFS_SRW_App/develop/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /glade/p/ral/jntp/UFS_SRW_App/develop/fix/fix_sfc_climo -task_run_fcst: FIXaer: /glade/p/ral/jntp/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /glade/p/ral/jntp/UFS_SRW_App/develop/fix/fix_am FIXlut: /glade/p/ral/jntp/UFS_SRW_App/develop/fix/fix_lut + FIXorg: /glade/p/ral/jntp/UFS_SRW_App/develop/fix/fix_orog + FIXsfc: /glade/p/ral/jntp/UFS_SRW_App/develop/fix/fix_sfc_climo data: FV3GFS: /glade/p/ral/jntp/UFS_CAM/COMGFS/gfs.${yyyymmdd}/${hh} diff --git a/ush/machine/gaea.yaml b/ush/machine/gaea.yaml index a2a2b47090..63a50f8d2d 100644 --- a/ush/machine/gaea.yaml +++ b/ush/machine/gaea.yaml @@ -21,13 +21,10 @@ platform: TEST_PREGEN_BASEDIR: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/FV3LAM_pregen TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir TEST_ALT_EXTRN_MDL_SYSBASEDIR_LBCS: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir -task_make_orog: - TOPO_DIR: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/fix/fix_sfc_climo -task_run_fcst: FIXaer: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/fix/fix_am FIXlut: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/fix/fix_lut + FIXorg: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/fix/fix_orog + FIXsfc: /lustre/f2/pdata/ncep_shared/UFS_SRW_App/develop/fix/fix_sfc_climo data: FV3GFS: /lustre/f2/dev/Mark.Potts/EPIC/SRW/model_data/FV3GFS/${yyyymmdd}${hh} diff --git a/ush/machine/hera.yaml b/ush/machine/hera.yaml index 21617c8d0d..3027b1e4fc 100644 --- a/ush/machine/hera.yaml +++ b/ush/machine/hera.yaml @@ -25,15 +25,9 @@ platform: TEST_PREGEN_BASEDIR: /scratch2/BMC/det/UFS_SRW_App/develop/FV3LAM_pregen TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS: /scratch2/BMC/det/UFS_SRW_app/develop/dummy_FV3GFS_sys_dir TEST_ALT_EXTRN_MDL_SYSBASEDIR_LBCS: /scratch2/BMC/det/UFS_SRW_app/develop/dummy_FV3GFS_sys_dir -task_make_orog: - TOPO_DIR: /scratch2/BMC/det/UFS_SRW_App/develop/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /scratch2/BMC/det/UFS_SRW_App/develop/fix/fix_sfc_climo -task_get_extrn_ics: - EXTRN_MDL_DATA_STORES: hpss aws nomads -task_get_extrn_lbcs: - EXTRN_MDL_DATA_STORES: hpss aws nomads -task_run_fcst: FIXaer: /scratch2/BMC/det/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /scratch2/BMC/det/UFS_SRW_App/develop/fix/fix_am FIXlut: /scratch2/BMC/det/UFS_SRW_App/develop/fix/fix_lut + FIXorg: /scratch2/BMC/det/UFS_SRW_App/develop/fix/fix_orog + FIXsfc: /scratch2/BMC/det/UFS_SRW_App/develop/fix/fix_sfc_climo + EXTRN_MDL_DATA_STORES: hpss aws nomads diff --git a/ush/machine/jet.yaml b/ush/machine/jet.yaml index 37dd70ea85..535b05672d 100644 --- a/ush/machine/jet.yaml +++ b/ush/machine/jet.yaml @@ -25,18 +25,12 @@ platform: TEST_PREGEN_BASEDIR: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/FV3LAM_pregen TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir TEST_ALT_EXTRN_MDL_SYSBASEDIR_LBCS: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir -task_make_orog: - TOPO_DIR: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/fix/fix_sfc_climo -task_get_extrn_ics: - EXTRN_MDL_DATA_STORES: hpss aws nomads -task_get_extrn_lbcs: - EXTRN_MDL_DATA_STORES: hpss aws nomads -task_run_fcst: FIXaer: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/fix/fix_am FIXlut: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/fix/fix_lut + FIXorg: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/fix/fix_orog + FIXsfc: /mnt/lfs4/BMC/wrfruc/UFS_SRW_App/develop/fix/fix_sfc_climo + EXTRN_MDL_DATA_STORES: hpss aws nomads data: FV3GFS: nemsio: /public/data/grids/gfs/nemsio diff --git a/ush/machine/linux.yaml b/ush/machine/linux.yaml index f447cf4dda..c7a36ad6bc 100644 --- a/ush/machine/linux.yaml +++ b/ush/machine/linux.yaml @@ -7,13 +7,10 @@ platform: RUN_CMD_SERIAL: time RUN_CMD_UTILS: mpirun -n 4 PRE_TASK_CMDS: '{ ulimit -a; }' -task_make_orog: - TOPO_DIR: /home/username/DATA/UFS/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /home/username/DATA/UFS/fix/fix_sfc_climo -task_run_fcst: FIXaer: /home/username/DATA/UFS/fix/fix_aer FIXgsm: /home/username/DATA/UFS/fix/fix_am FIXlut: /home/username/DATA/UFS/fix/fix_lut + FIXorg: /home/username/DATA/UFS/fix/fix_orog + FIXsfc: /home/username/DATA/UFS/fix/fix_sfc_climo data: FV3GFS: /home/username/DATA/UFS/FV3GFS diff --git a/ush/machine/macos.yaml b/ush/machine/macos.yaml index 97ec29bf90..506c136b82 100644 --- a/ush/machine/macos.yaml +++ b/ush/machine/macos.yaml @@ -7,13 +7,10 @@ platform: RUN_CMD_SERIAL: time RUN_CMD_UTILS: mpirun -n 4 PRE_TASK_CMDS: '{ ulimit -a; }' -task_make_orog: - TOPO_DIR: /Users/username/DATA/UFS/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /Users/username/DATA/UFS/fix/fix_sfc_climo -task_run_fcst: FIXaer: /Users/username/DATA/UFS/fix/fix_aer FIXgsm: /Users/username/DATA/UFS/fix/fix_am FIXlut: /Users/username/DATA/UFS/fix/fix_lut + FIXorg: /Users/username/DATA/UFS/fix/fix_orog + FIXsfc: /Users/username/DATA/UFS/fix/fix_sfc_climo data: FV3GFS: /Users/username/DATA/UFS/FV3GFS diff --git a/ush/machine/noaacloud.yaml b/ush/machine/noaacloud.yaml index 32246aae54..a5800aa7de 100644 --- a/ush/machine/noaacloud.yaml +++ b/ush/machine/noaacloud.yaml @@ -18,17 +18,11 @@ platform: TEST_PREGEN_BASEDIR: /contrib/EPIC/UFS_SRW_App/develop/FV3LAM_pregen TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS: /contrib/EPIC/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir TEST_ALT_EXTRN_MDL_SYSBASEDIR_LBCS: /contrib/EPIC/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir -task_make_orog: - TOPO_DIR: /contrib/EPIC/UFS_SRW_App/develop/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /contrib/EPIC/UFS_SRW_App/develop/fix/fix_sfc_climo -task_get_extrn_ics: - EXTRN_MDL_DATA_STORES: aws nomads -task_get_extrn_lbcs: - EXTRN_MDL_DATA_STORES: aws nomads -task_run_fcst: FIXaer: /contrib/EPIC/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /contrib/EPIC/UFS_SRW_App/develop/fix/fix_am FIXlut: /contrib/EPIC/UFS_SRW_App/develop/fix/fix_lut + FIXorg: /contrib/EPIC/UFS_SRW_App/develop/fix/fix_orog + FIXsfc: /contrib/EPIC/UFS_SRW_App/develop/fix/fix_sfc_climo + EXTRN_MDL_DATA_STORES: aws nomads data: FV3GFS: /contrib/GST/model_data/FV3GFS/${yyyymmdd}${hh} diff --git a/ush/machine/odin.yaml b/ush/machine/odin.yaml index dbf9bb2a8b..b47a654793 100644 --- a/ush/machine/odin.yaml +++ b/ush/machine/odin.yaml @@ -19,14 +19,11 @@ platform: TEST_PREGEN_BASEDIR: /scratch/ywang/UFS_SRW_App/develop/FV3LAM_pregen TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS: /scratch/ywang/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir TEST_ALT_EXTRN_MDL_SYSBASEDIR_LBCS: /scratch/ywang/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir -task_make_orog: - TOPO_DIR: /scratch/ywang/UFS_SRW_App/develop/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /scratch/ywang/UFS_SRW_App/develop/fix/fix_sfc_climo -task_run_fcst: FIXaer: /scratch/ywang/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /scratch/ywang/UFS_SRW_App/develop/fix/fix_am FIXlut: /scratch/ywang/UFS_SRW_App/develop/fix/fix_lut + FIXorg: /scratch/ywang/UFS_SRW_App/develop/fix/fix_orog + FIXsfc: /scratch/ywang/UFS_SRW_App/develop/fix/fix_sfc_climo data: GSMGFS: /scratch/ywang/UFS_SRW_App/develop/input_model_data/GFS FV3GFS: /scratch/ywang/UFS_SRW_App/develop/input_model_data/FV3GFS diff --git a/ush/machine/orion.yaml b/ush/machine/orion.yaml index 00aba1a85b..a3ca5ba133 100644 --- a/ush/machine/orion.yaml +++ b/ush/machine/orion.yaml @@ -23,15 +23,9 @@ platform: PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' TEST_EXTRN_MDL_SOURCE_BASEDIR: /work/noaa/fv3-cam/UFS_SRW_App/develop/input_model_data TEST_PREGEN_BASEDIR: /work/noaa/fv3-cam/UFS_SRW_App/develop/FV3LAM_pregen -task_make_orog: - TOPO_DIR: /work/noaa/fv3-cam/UFS_SRW_App/develop/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /work/noaa/fv3-cam/UFS_SRW_App/develop/fix/fix_sfc_climo -task_get_extrn_ics: - EXTRN_MDL_DATA_STORES: aws nomads -task_get_extrn_lbcs: - EXTRN_MDL_DATA_STORES: aws nomads -task_run_fcst: FIXaer: /work/noaa/fv3-cam/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /work/noaa/fv3-cam/UFS_SRW_App/develop/fix/fix_am FIXlut: /work/noaa/fv3-cam/UFS_SRW_App/develop/fix/fix_lut + FIXorg: /work/noaa/fv3-cam/UFS_SRW_App/develop/fix/fix_orog + FIXsfc: /work/noaa/fv3-cam/UFS_SRW_App/develop/fix/fix_sfc_climo + EXTRN_MDL_DATA_STORES: aws nomads diff --git a/ush/machine/singularity.yaml b/ush/machine/singularity.yaml index 3fbea67c69..43399460cd 100644 --- a/ush/machine/singularity.yaml +++ b/ush/machine/singularity.yaml @@ -15,15 +15,9 @@ platform: RUN_CMD_UTILS: mpirun -np $nprocs --oversubscribe SCHED_NATIVE_CMD: --export=NONE PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' -task_make_orog: - TOPO_DIR: /contrib/global/glopara/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /contrib/global/glopara/fix/fix_sfc_climo -task_get_extrn_ics: - EXTRN_MDL_DATA_STORES: aws nomads -task_get_extrn_lbcs: - EXTRN_MDL_DATA_STORES: aws nomads -task_run_fcst: FIXaer: /contrib/global/glopara/fix/fix_aer FIXgsm: /contrib/global/glopara/fix/fix_am FIXlut: /contrib/global/glopara/fix/fix_lut + FIXorg: /contrib/global/glopara/fix/fix_orog + FIXsfc: /contrib/global/glopara/fix/fix_sfc_climo + EXTRN_MDL_DATA_STORES: aws nomads diff --git a/ush/machine/stampede.yaml b/ush/machine/stampede.yaml index 4dbb1ccdb6..2e663bbcd2 100644 --- a/ush/machine/stampede.yaml +++ b/ush/machine/stampede.yaml @@ -19,14 +19,11 @@ platform: TEST_PREGEN_BASEDIR: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/FV3LAM_pregen TEST_ALT_EXTRN_MDL_SYSBASEDIR_ICS: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir TEST_ALT_EXTRN_MDL_SYSBASEDIR_LBCS: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/dummy_FV3GFS_sys_dir -task_make_orog: - TOPO_DIR: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/fix/fix_sfc_climo -task_run_fcst: FIXaer: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/fix/fix_am FIXlut: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/fix/fix_lut + FIXorg: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/fix/fix_orog + FIXsfc: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/fix/fix_sfc_climo data: GSMGFS: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/input_model_data/GFS FV3GFS: /work2/00315/tg455890/stampede2/UFS_SRW_App/develop/input_model_data/FV3GFS diff --git a/ush/machine/wcoss2.yaml b/ush/machine/wcoss2.yaml index 4a9bfcab50..bd59520955 100644 --- a/ush/machine/wcoss2.yaml +++ b/ush/machine/wcoss2.yaml @@ -20,18 +20,12 @@ platform: PRE_TASK_CMDS: '{ ulimit -s unlimited; ulimit -a; }' TEST_EXTRN_MDL_SOURCE_BASEDIR: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/input_model_data TEST_PREGEN_BASEDIR: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/FV3LAM_pregen -task_make_orog: - TOPO_DIR: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_orog -task_make_sfc_climo: - SFC_CLIMO_INPUT_DIR: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_sfc_climo -task_get_extrn_ics: - EXTRN_MDL_DATA_STORES: hpss aws nomads -task_get_extrn_lbcs: - EXTRN_MDL_DATA_STORES: hpss aws nomads -task_run_fcst: FIXaer: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_aer FIXgsm: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_am FIXlut: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_lut + FIXorg: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_orog + FIXsfc: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_sfc_climo + EXTRN_MDL_DATA_STORES: hpss aws nomads data: GSMGFS: compath.py ${envir}/gsmgfs/${gsmgfs_ver}/gsmgfs.${PDY} FV3GFS: compath.py ${envir}/gfs/${gfs_ver}/gfs.${PDY}/${hh}/atmos diff --git a/ush/python_utils/config_parser.py b/ush/python_utils/config_parser.py index e53b8cec1f..5d3febb88f 100644 --- a/ush/python_utils/config_parser.py +++ b/ush/python_utils/config_parser.py @@ -402,6 +402,21 @@ def check_structure_dict(dict_o, dict_t): return True +def filter_dict(dict_o, keys_regex): + """Filter dictionary keys based on a list of keys + Args: + dict_o: the source dictionary + keys_regex: list of keys to retain (could be regex exp.) + """ + + keys = [] + for k in keys_regex: + r = re.compile(k) + keys += list(filter(r.match, dict_o.keys())) + dict_t = {k: dict_o[k] for k in keys} + return dict_t + + ################## # CONFIG loader ################## @@ -490,11 +505,7 @@ def cfg_main(): cfg = structure_dict(cfg, cfg_t) if args.keys: - keys = [] - for k in args.keys: - r = re.compile(k) - keys += list(filter(r.match, cfg.keys())) - cfg = {k: cfg[k] for k in keys} + cfg = filter_dict(cfg, args.keys) if args.flatten: cfg = flatten_dict(cfg) diff --git a/ush/python_utils/environment.py b/ush/python_utils/environment.py index f327a74f40..da50085933 100644 --- a/ush/python_utils/environment.py +++ b/ush/python_utils/environment.py @@ -20,7 +20,7 @@ def str_to_date(s): l = len(s) if l == 8: v = datetime.strptime(s, "%Y%m%d") - if l == 10: + elif l == 10: v = datetime.strptime(s, "%Y%m%d%H") elif l == 12: v = datetime.strptime(s, "%Y%m%d%H%M") @@ -69,8 +69,13 @@ def str_to_type(s, return_string=0): if return_string == 2: return s return v - if s.isnumeric(): - return int(s) + # int + try: + v = int(s) + return v + except: + pass + # float try: v = float(s) return v diff --git a/ush/setup.py b/ush/setup.py index 1e0c19b266..572433459f 100644 --- a/ush/setup.py +++ b/ush/setup.py @@ -23,7 +23,6 @@ load_config_file, cfg_to_shell_str, cfg_to_yaml_str, - load_shell_config, load_ini_config, get_ini_value, ) @@ -456,7 +455,7 @@ def get_location(xcs, fmt): # # ----------------------------------------------------------------------- # - global FIXgsm, FIXaer, FIXlut, TOPO_DIR, SFC_CLIMO_INPUT_DIR, DOMAIN_PREGEN_BASEDIR + global FIXgsm, FIXaer, FIXlut, FIXorg, FIXsfc, DOMAIN_PREGEN_BASEDIR global RELATIVE_LINK_FLAG, WORKFLOW_MANAGER, NCORES_PER_NODE, SCHED, QUEUE_DEFAULT global QUEUE_HPSS, QUEUE_FCST, PARTITION_DEFAULT, PARTITION_HPSS, PARTITION_FCST @@ -468,8 +467,8 @@ def get_location(xcs, fmt): "FIXgsm", "FIXaer", "FIXlut", - "TOPO_DIR", - "SFC_CLIMO_INPUT_DIR", + "FIXorg", + "FIXsfc", ] globalvars = globals() for val in mandatory: @@ -1723,15 +1722,10 @@ def get_location(xcs, fmt): "FIXam": FIXam, "FIXclim": FIXclim, "FIXlam": FIXlam, - "FIXgsm": FIXgsm, - "FIXaer": FIXaer, - "FIXlut": FIXlut, "VX_CONFIG_DIR": VX_CONFIG_DIR, "METPLUS_CONF": METPLUS_CONF, "MET_CONFIG": MET_CONFIG, "UFS_WTHR_MDL_DIR": UFS_WTHR_MDL_DIR, - "SFC_CLIMO_INPUT_DIR": SFC_CLIMO_INPUT_DIR, - "TOPO_DIR": TOPO_DIR, "EXPTDIR": EXPTDIR, "GRID_DIR": GRID_DIR, "OROG_DIR": OROG_DIR, From db1302f024f3c1d40f6cb921e4c53497a09208f3 Mon Sep 17 00:00:00 2001 From: "Chan-Hoo.Jeon-NOAA" <60152248+chan-hoo@users.noreply.github.com> Date: Thu, 17 Nov 2022 09:22:54 -0500 Subject: [PATCH 24/45] [develop] bugfix: set PDYext and cycext in get_extrn_ics/lbcs for time-offset (#475) * change PDY to yyyymmdd for time-offset * change prod in nco we2e script * modify ex-script rather than machine file * fix typo * Set PDYext cycext Co-authored-by: chan-hoo --- scripts/exregional_get_extrn_mdl_files.sh | 3 +++ ush/machine/wcoss2.yaml | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/exregional_get_extrn_mdl_files.sh b/scripts/exregional_get_extrn_mdl_files.sh index 26b409c46e..97ac031f2d 100755 --- a/scripts/exregional_get_extrn_mdl_files.sh +++ b/scripts/exregional_get_extrn_mdl_files.sh @@ -90,6 +90,9 @@ mm=${yyyymmddhh:4:2} dd=${yyyymmddhh:6:2} hh=${yyyymmddhh:8:2} +# Set to use the pre-defined data paths in the machine file (ush/machine/). +PDYext=${yyyymmdd} +cycext=${hh} # #----------------------------------------------------------------------- # diff --git a/ush/machine/wcoss2.yaml b/ush/machine/wcoss2.yaml index bd59520955..c304d8cb08 100644 --- a/ush/machine/wcoss2.yaml +++ b/ush/machine/wcoss2.yaml @@ -27,9 +27,9 @@ platform: FIXsfc: /lfs/h2/emc/lam/noscrub/UFS_SRW_App/develop/fix/fix_sfc_climo EXTRN_MDL_DATA_STORES: hpss aws nomads data: - GSMGFS: compath.py ${envir}/gsmgfs/${gsmgfs_ver}/gsmgfs.${PDY} - FV3GFS: compath.py ${envir}/gfs/${gfs_ver}/gfs.${PDY}/${hh}/atmos - RAP: compath.py ${envir}/rap/${rap_ver}/rap.${PDY} - NAM: compath.py ${envir}/nam/${nam_ver}/nam.${PDY} - HRRR: compath.py ${envir}/hrrr/${hrrr_ver}/hrrr.${PDY}/conus + GSMGFS: compath.py ${envir}/gsmgfs/${gsmgfs_ver}/gsmgfs.${PDYext} + FV3GFS: compath.py ${envir}/gfs/${gfs_ver}/gfs.${PDYext}/${cycext}/atmos + RAP: compath.py ${envir}/rap/${rap_ver}/rap.${PDYext} + NAM: compath.py ${envir}/nam/${nam_ver}/nam.${PDYext} + HRRR: compath.py ${envir}/hrrr/${hrrr_ver}/hrrr.${PDYext}/conus From d03e64619628809cf4e302a0ef1054db3d6d2ccb Mon Sep 17 00:00:00 2001 From: Michael Lueken <63728921+MichaelLueken@users.noreply.github.com> Date: Thu, 17 Nov 2022 09:27:22 -0500 Subject: [PATCH 25/45] [develop] Add Hera GNU modulefile and fundamental test suite and update Hera Intel modulefile. (#477) * Add hera gnu fundamental test to Jenkins. * Remove a couple of test cases. * [develop] Add build_hera_gnu.lua file. Completes #476. Co-authored-by: Daniel Abdi --- .cicd/Jenkinsfile | 2 +- modulefiles/build_hera_gnu.lua | 30 +++++++++++++++++++ modulefiles/build_hera_intel.lua | 9 +++++- .../machine_suites/fundamental.hera.gnu.com | 4 +++ ...al.hera.nco => fundamental.hera.intel.nco} | 0 tests/WE2E/run_WE2E_tests.sh | 4 +-- 6 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 modulefiles/build_hera_gnu.lua create mode 100644 tests/WE2E/machine_suites/fundamental.hera.gnu.com rename tests/WE2E/machine_suites/{fundamental.hera.nco => fundamental.hera.intel.nco} (100%) diff --git a/.cicd/Jenkinsfile b/.cicd/Jenkinsfile index 75a9e96308..64a45b1808 100644 --- a/.cicd/Jenkinsfile +++ b/.cicd/Jenkinsfile @@ -90,7 +90,7 @@ pipeline { exclude { axis { name 'SRW_PLATFORM' - values 'gaea', 'hera', 'jet', 'orion' //, 'pclusternoaav2use1' , 'azclusternoaav2eus1', 'gclusternoaav2usc1' + values 'gaea', 'jet', 'orion' //, 'pclusternoaav2use1' , 'azclusternoaav2eus1', 'gclusternoaav2usc1' } axis { diff --git a/modulefiles/build_hera_gnu.lua b/modulefiles/build_hera_gnu.lua new file mode 100644 index 0000000000..45bdd736a3 --- /dev/null +++ b/modulefiles/build_hera_gnu.lua @@ -0,0 +1,30 @@ +help([[ +This module loads libraries for building the UFS SRW App on +the NOAA RDHPC machine Hera using GNU 9.2.0 +]]) + +whatis([===[Loads libraries needed for building the UFS SRW App on Hera using GNU 9.2.0 ]===]) + +prepend_path("MODULEPATH","/contrib/sutils/modulefiles") +load("sutils") + +load(pathJoin("cmake", os.getenv("cmake_ver") or "3.20.1")) + +gnu_ver=os.getenv("gnu_ver") or "9.2.0" +load(pathJoin("gnu", gnu_ver)) + +prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/gnu-9.2/modulefiles/stack") + +load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) +load(pathJoin("hpc-gnu", os.getenv("hpc-gnu_ver") or "9.2")) +load(pathJoin("hpc-mpich", os.getenv("hpc-mpich_ver") or "3.3.2")) + +load("srw_common") + +load(pathJoin("nccmp", os.getenv("nccmp_ver") or "1.8.9")) +load(pathJoin("nco", os.getenv("nco_ver") or "4.9.3")) + +setenv("CMAKE_C_COMPILER","mpicc") +setenv("CMAKE_CXX_COMPILER","mpicxx") +setenv("CMAKE_Fortran_COMPILER","mpif90") +setenv("CMAKE_Platform","hera.gnu") diff --git a/modulefiles/build_hera_intel.lua b/modulefiles/build_hera_intel.lua index 69d74a0dd6..02af59a626 100644 --- a/modulefiles/build_hera_intel.lua +++ b/modulefiles/build_hera_intel.lua @@ -10,7 +10,14 @@ load("sutils") load(pathJoin("cmake", os.getenv("cmake_ver") or "3.20.1")) -prepend_path("MODULEPATH","/scratch2/NCEPDEV/nwprod/hpc-stack/libs/hpc-stack/modulefiles/stack") +intel_ver=os.getenv("intel_ver") or "2022.1.2" +load(pathJoin("intel", intel_ver)) + +impi_ver=os.getenv("impi_ver") or "2022.1.2" +load(pathJoin("impi", impi_ver)) + +prepend_path("MODULEPATH","/scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/intel-2022.1.2/modulefiles/stack") + load(pathJoin("hpc", os.getenv("hpc_ver") or "1.2.0")) load(pathJoin("hpc-intel", os.getenv("hpc_intel_ver") or "2022.1.2")) load(pathJoin("hpc-impi", os.getenv("hpc_impi_ver") or "2022.1.2")) diff --git a/tests/WE2E/machine_suites/fundamental.hera.gnu.com b/tests/WE2E/machine_suites/fundamental.hera.gnu.com new file mode 100644 index 0000000000..bd59be10a8 --- /dev/null +++ b/tests/WE2E/machine_suites/fundamental.hera.gnu.com @@ -0,0 +1,4 @@ +MET_verification +community_ensemble_2mems +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp +grid_RRFS_CONUS_25km_ics_FV3GFS_lbcs_FV3GFS_suite_GFS_2017_gfdlmp_regional diff --git a/tests/WE2E/machine_suites/fundamental.hera.nco b/tests/WE2E/machine_suites/fundamental.hera.intel.nco similarity index 100% rename from tests/WE2E/machine_suites/fundamental.hera.nco rename to tests/WE2E/machine_suites/fundamental.hera.intel.nco diff --git a/tests/WE2E/run_WE2E_tests.sh b/tests/WE2E/run_WE2E_tests.sh index 18063eee33..461041c08d 100755 --- a/tests/WE2E/run_WE2E_tests.sh +++ b/tests/WE2E/run_WE2E_tests.sh @@ -432,9 +432,9 @@ elif [ -n "${tests_file}" ] || [ -n "${test_type}" ] ; then if [ -n "${test_type}" ] ; then # Check for a pre-defined set. It could be machine dependent or has the mode # (community or nco), or default - user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine}.nco + user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine}.${compiler}.nco if [ ! -f ${user_spec_tests_fp} ]; then - user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine}.com + user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine}.${compiler}.com if [ ! -f ${user_spec_tests_fp} ]; then user_spec_tests_fp=${scrfunc_dir}/machine_suites/${test_type}.${machine}.${compiler} if [ ! -f ${user_spec_tests_fp} ]; then From 370834b0d28931ddb52fefcf4f473400b4917298 Mon Sep 17 00:00:00 2001 From: Michael Lueken <63728921+MichaelLueken@users.noreply.github.com> Date: Mon, 21 Nov 2022 12:13:41 -0500 Subject: [PATCH 26/45] [develop] Updated README.md and Introduction.rst for the SRW v2.1.0 release (#493) --- README.md | 6 +++--- docs/UsersGuide/source/Introduction.rst | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6956aa7a40..f746ae5c78 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ The Unified Forecast System (UFS) is a community-based, coupled, comprehensive Earth modeling system. It is designed to be the source system for NOAA’s operational numerical weather prediction applications while enabling research, development, and contribution opportunities for the broader weather enterprise. For more information about the UFS, visit the UFS Portal at https://ufscommunity.org/. -The UFS includes multiple applications (see a complete list at https://ufscommunity.org/science/aboutapps/) that support different forecast durations and spatial domains. This documentation describes the development branch of the UFS Short-Range Weather (SRW) Application, which targets predictions of atmospheric behavior on a limited spatial domain and on time scales from minutes to several days. The development branch of the application is continually evolving as the system undergoes open development. The latest SRW App release (v2.0.0) represents a snapshot of this continuously evolving system. +The UFS includes multiple applications (see a complete list at https://ufscommunity.org/science/aboutapps/) that support different forecast durations and spatial domains. This documentation describes the development branch of the UFS Short-Range Weather (SRW) Application, which targets predictions of atmospheric behavior on a limited spatial domain and on time scales from minutes to several days. The development branch of the application is continually evolving as the system undergoes open development. The latest SRW App release (v2.1.0) represents a snapshot of this continuously evolving system. -The UFS SRW App User's Guide associated with the development branch is at: https://ufs-srweather-app.readthedocs.io/en/develop/, while the guide specific to the SRW App v2.0.0 release can be found at: https://ufs-srweather-app.readthedocs.io/en/release-public-v2/. The repository is at: https://github.com/ufs-community/ufs-srweather-app. +The UFS SRW App User's Guide associated with the development branch is at: https://ufs-srweather-app.readthedocs.io/en/develop/, while the guide specific to the SRW App v2.1.0 release can be found at: https://ufs-srweather-app.readthedocs.io/en/release-public-v2.1.0/. The repository is at: https://github.com/ufs-community/ufs-srweather-app. For instructions on how to clone the repository, build the code, and run the workflow, see: https://github.com/ufs-community/ufs-srweather-app/wiki/Getting-Started -UFS Development Team. (2022, June 23). Unified Forecast System (UFS) Short-Range Weather (SRW) Application (Version v2.0.0). Zenodo. https://doi.org/10.5281/zenodo.6505854 +UFS Development Team. (2022, Nov. 17). Unified Forecast System (UFS) Short-Range Weather (SRW) Application (Version v2.1.0). Zenodo. https://doi.org/10.5281/zenodo.7277602 [![Python unittests](https://github.com/ufs-community/ufs-srweather-app/actions/workflows/python_unittests.yaml/badge.svg)](https://github.com/ufs-community/ufs-srweather-app/actions/workflows/python_unittests.yaml) [![Python functional tests](https://github.com/ufs-community/ufs-srweather-app/actions/workflows/python_func_tests.yaml/badge.svg)](https://github.com/ufs-community/ufs-srweather-app/actions/workflows/python_func_tests.yaml) diff --git a/docs/UsersGuide/source/Introduction.rst b/docs/UsersGuide/source/Introduction.rst index 7e39ba7769..476f013838 100644 --- a/docs/UsersGuide/source/Introduction.rst +++ b/docs/UsersGuide/source/Introduction.rst @@ -6,13 +6,13 @@ Introduction The Unified Forecast System (:term:`UFS`) is a community-based, coupled, comprehensive Earth modeling system. NOAA's operational model suite for numerical weather prediction (:term:`NWP`) is quickly transitioning to the UFS from a number of different modeling systems. The UFS enables research, development, and contribution opportunities within the broader :term:`Weather Enterprise` (including government, industry, and academia). For more information about the UFS, visit the `UFS Portal `__. -The UFS includes `multiple applications `__ that support different forecast durations and spatial domains. This documentation describes the UFS Short-Range Weather (SRW) Application, which targets predictions of atmospheric behavior on a limited spatial domain and on time scales from minutes to several days. The SRW Application v2.0.0 release includes a prognostic atmospheric model, pre- and post-processing, and a community workflow for running the system end-to-end. These components are documented within this User's Guide and supported through a `community forum `__. New and improved capabilities for this release include the addition of a verification package (METplus) for both deterministic and ensemble simulations and support for four stochastically perturbed physics schemes. Future work will expand the capabilities of the application to include data assimilation (DA) and a forecast restart/cycling capability. +The UFS includes `multiple applications `__ that support different forecast durations and spatial domains. This documentation describes the UFS Short-Range Weather (SRW) Application, which targets predictions of atmospheric behavior on a limited spatial domain and on time scales from minutes to several days. The SRW Application v2.1.0 release includes a prognostic atmospheric model, pre- and post-processing, and a community workflow for running the system end-to-end. These components are documented within this User's Guide and supported through a `community forum `__. New and improved capabilities for this release include the addition of a verification package (METplus) for both deterministic and ensemble simulations and support for four stochastically perturbed physics schemes. Future work will expand the capabilities of the application to include data assimilation (DA) and a forecast restart/cycling capability. This documentation provides a :ref:`Quick Start Guide ` designed for use on `Level 1 systems `__ or as an overview of the workflow. It also provides a :ref:`Container-Based Quick Start Guide ` for running the SRW Application in a container and detailed chapters on :ref:`building ` and :ref:`running ` the SRW App on any supported platform. Additionally, this User's Guide provides an overview of the :ref:`release components ` and details on how to customize or modify different portions of the workflow. -The SRW App v2.0.0 citation is as follows and should be used when presenting results based on research conducted with the App: +The SRW App v2.1.0 citation is as follows and should be used when presenting results based on research conducted with the App: -UFS Development Team. (2022, June 23). Unified Forecast System (UFS) Short-Range Weather (SRW) Application (Version v2.0.0). Zenodo. https://doi.org/10.5281/zenodo.6505854 +UFS Development Team. (2022, Nov. 17). Unified Forecast System (UFS) Short-Range Weather (SRW) Application (Version v2.1.0). Zenodo. https://doi.org/10.5281/zenodo.7277602 How to Use This Document From f0963f62f77516f4e7c1203e08b40a8d80012372 Mon Sep 17 00:00:00 2001 From: Mark Potts <33099090+mark-a-potts@users.noreply.github.com> Date: Mon, 28 Nov 2022 09:30:59 -0500 Subject: [PATCH 27/45] [develop] Python-based crontab replacement (#466) * new script to run and monitor e2e tests without cron * fixed find command and directed system output to /dev/null * Modify run_WE2E_tests.sh - When on Cheyenne, set use_cron_to_relaunch=false - When use_cron_to_relaunch=false, output a message at the end of the script describing how to run the new run_srw_tests.py script to manage the tests - Regardless of other variables, print a message at the end of the script showing the user where the test directory is * Updated .cicd/scripts/srw_test.sh to work with ush/run_srw_tests.py Co-authored-by: Michael Kavulich, Jr Co-authored-by: michael.lueken --- .cicd/scripts/srw_test.sh | 22 ++++++++++--- tests/WE2E/run_WE2E_tests.sh | 42 ++++++++++++++++++++++++ ush/run_srw_tests.py | 62 ++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 4 deletions(-) create mode 100755 ush/run_srw_tests.py diff --git a/.cicd/scripts/srw_test.sh b/.cicd/scripts/srw_test.sh index 4c4cbc95af..8df2ff5c2f 100755 --- a/.cicd/scripts/srw_test.sh +++ b/.cicd/scripts/srw_test.sh @@ -42,13 +42,22 @@ cd ${we2e_test_dir} expt_basedir=${we2e_experiment_base_dir} \ opsroot=${nco_dir} -# Allow the tests to start before checking for status. -# TODO: Create a parameter that sets the initial start delay. -sleep 300 +# Run the new run_srw_tests script if the machine is Cheyenne. +if [[ "${platform}" = "cheyenne" ]]; then + cd ${workspace}/ush + ./run_srw_tests.py -e=${we2e_experiment_base_dir} + cd ${we2e_test_dir} +fi # Progress file progress_file="${workspace}/we2e_test_results-${platform}-${SRW_COMPILER}.txt" +# Allow the tests to start before checking for status. +# TODO: Create a parameter that sets the initial start delay. +if [[ "${platform}" != "cheyenne" ]]; then + sleep 300 +fi + # Wait for all tests to complete. while true; do @@ -74,10 +83,15 @@ done # TODO: Create parameter that sets the interval for the we2e cron jobs; this # value should be some factor of that interval to ensure the cron jobs execute # before the workspace is cleaned up. -sleep 600 +if [[ "${platform}" != "cheyenne" ]]; then + sleep 600 +fi # Set exit code to number of failures set +e failures=$(grep "Workflow status: FAILURE" ${progress_file} | wc -l) +if [[ $failures -ne 0 ]]; then + failures=1 +fi set -e exit ${failures} diff --git a/tests/WE2E/run_WE2E_tests.sh b/tests/WE2E/run_WE2E_tests.sh index 461041c08d..3887483ecd 100755 --- a/tests/WE2E/run_WE2E_tests.sh +++ b/tests/WE2E/run_WE2E_tests.sh @@ -395,6 +395,16 @@ if [ -z "${machine}" ]; then The argument \"machine\" specifying the machine or platform on which to run the WE2E tests was not specified in the call to this script. \ ${help_msg}" +fi + # Cheyenne-specific test limitation + +if [ "${machine,,}" = "cheyenne" ]; then + use_cron_to_relaunch=FALSE + echo " +Due to system limitations, the 'use_cron_to_relaunch' command can not be used on +the '${machine}' machine. Setting this variable to false. + +" fi if [ -z "${account}" ]; then @@ -1310,6 +1320,38 @@ Could not generate an experiment for the test specified by test_name: test_name = \"${test_name}\"" done + +# Print notes about monitoring/running jobs if use_cron_to_relaunch = FALSE +topdir=${scrfunc_dir%/*/*/*} +expt_dirs_fullpath="${topdir}/expt_dirs" + +echo " + ======================================================================== + ======================================================================== + + All experiments have been generated in the directory + ${expt_dirs_fullpath} + + ======================================================================== + ======================================================================== +" + +if [ "${use_cron_to_relaunch,,}" = "false" ]; then + echo " + +The variable 'use_cron_to_relaunch' has been set to FALSE. Jobs will not be automatically run via crontab. + +You can run each task manually in the experiment directory: +(${expt_dirs_fullpath}) + +Or you can use the 'run_srw_tests.py' script in the ush/ directory: + + cd $USHdir + ./run_srw_tests.py -e=${expt_dirs_fullpath} + +" +fi + # #----------------------------------------------------------------------- # diff --git a/ush/run_srw_tests.py b/ush/run_srw_tests.py new file mode 100755 index 0000000000..9e77be14b8 --- /dev/null +++ b/ush/run_srw_tests.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import time +import argparse + +# Python class to handle the launching of a set of SRW tests +# The expectation is to have a "clean" experiment directory with only new experiments +# that are ready to run (e.g. no _old* experiments left around from previous tests +# This script takes only one parameter "-e" or "--exptdir" which points to the +# expt_basedir specified when the run_WE2E_tests.sh is run to set up the tests. +# The script will work sequentially through each of the test directories and +# launch the workflow for each with a call to launch_FV3LAM_wflow.sh +# After the initial launch, the checkTests method is called to monitor the +# status of each test and call the launch_FV3LAM_wflow.sh script repeatedly +# in each uncompleted workflow until all workflows are done. +class SRWTest: + def __init__(self, exptdir): + self.exptdir=exptdir + # Get a list of test directories + cmdstring="find {} -maxdepth 1 -type d | tail -n+2".format(self.exptdir) + status= subprocess.check_output(cmdstring,shell=True).strip().decode('utf-8') + # Turn the stdout from the shell command into a list + self.testDirectories = status.split("\n") + self.launchcmd = "./launch_FV3LAM_wflow.sh >& /dev/null" + # Loop through each of the test directories and launch the initial jobs in the workflow + for testD in self.testDirectories: + print("starting {} workflow".format(testD)) + os.chdir(testD) + os.system(self.launchcmd) + os.chdir(self.exptdir) + # Now start monitoring the workflows + self.checkTests() + + def checkTests(self): + while(len(self.testDirectories) > 0): + # Only continue running launch command for workflows that aren't complete + # so check for any that have failed or completed and cull them from the list + cmdstring="grep -L 'wflow_status =' */log.launch_FV3LAM_wflow | xargs dirname" + try: + status= subprocess.check_output(cmdstring,shell=True).strip().decode('utf-8') + except: + print("Tests have all completed") + return + self.testDirectories = status.split("\n") + # continue looping through directories + for testD in self.testDirectories: + os.chdir(testD) + os.system(self.launchcmd) + os.chdir(self.exptdir) + print("calling launch_FV3LAM_wflow.sh from {}".format(testD)) + time.sleep(5.0) + time.sleep(30.0) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Run through a set of SRW WE2E tests until they are complete') + parser.add_argument('-e','--exptdir', help='directory where experiments have been staged', required=False,default=os.getcwd()) + args = vars(parser.parse_args()) + + test = SRWTest(args['exptdir']) + From 98edca0bc25875432936944e8ef87acdc5e34781 Mon Sep 17 00:00:00 2001 From: Gillian Petro <96886803+gspetro-NOAA@users.noreply.github.com> Date: Tue, 29 Nov 2022 09:38:14 -0500 Subject: [PATCH 28/45] [develop] Pull in relevant doc updates from release v2.1.0 (#498) * update build process img * update img * Revert changes This reverts commit b839658fec9240b8e20d8ace2a70162219ed7906. * BuildSRW updates - esp mac/linux * remove Contributor's Guide * update Glossary and RunSRW * update build/run process images * remove outdated images; add new * Components & CCPP updates, misc * ConfigWflow updates * Container updates * update FAQ * graphics updates * I/O updates * Intro updates * Grid ch updates * Grid ch updates * Quickstart Updates * Rocoto edits * WE2E ch * update supported tests * update fix file list * minor update * minor edits * minor edits * misc minor fixes * change /home to /Users/gillianpetro * fix geopotential height * update hpc-stack doc link * nperlin changes * nperlin changes Co-authored-by: gspetro --- README.md | 2 +- docs/UsersGuide/source/BuildSRW.rst | 94 ++-- docs/UsersGuide/source/Components.rst | 37 +- docs/UsersGuide/source/ConfigWorkflow.rst | 18 +- .../UsersGuide/source/ContainerQuickstart.rst | 18 +- docs/UsersGuide/source/ContributorsGuide.rst | 463 ------------------ docs/UsersGuide/source/FAQ.rst | 173 +++++-- docs/UsersGuide/source/Glossary.rst | 31 +- docs/UsersGuide/source/Graphics.rst | 114 ++--- docs/UsersGuide/source/InputOutputFiles.rst | 121 +++-- docs/UsersGuide/source/Introduction.rst | 149 +++--- docs/UsersGuide/source/LAMGrids.rst | 199 ++------ docs/UsersGuide/source/Quickstart.rst | 67 +-- docs/UsersGuide/source/RocotoInfo.rst | 14 +- docs/UsersGuide/source/RunSRW.rst | 293 +++++------ docs/UsersGuide/source/WE2Etests.rst | 49 +- .../source/_static/FV3LAM_wflow_flowchart.png | Bin 56074 -> 0 bytes .../_static/FV3LAM_wflow_flowchart_v2.png | Bin 561715 -> 0 bytes .../_static/FV3LAM_wflow_input_path.png | Bin 64507 -> 0 bytes .../source/_static/FV3LAM_wflow_overall.png | Bin 52544 -> 0 bytes .../_static/FV3regional_workflow_gen.png | Bin 81430 -> 0 bytes .../_static/FV3regional_workflow_gen_v2.png | Bin 550227 -> 0 bytes .../source/_static/SRW_build_process.png | Bin 59669 -> 60664 bytes .../_static/SRW_overall_workflow_run.png | Bin 84193 -> 0 bytes .../source/_static/SRW_run_process.png | Bin 0 -> 81455 bytes .../source/_static/SRW_wflow_input_path.png | Bin 0 -> 141217 bytes docs/UsersGuide/source/conf.py | 2 +- docs/UsersGuide/source/index.rst | 1 - docs/UsersGuide/source/tables/.DS_Store | Bin 6148 -> 6148 bytes docs/UsersGuide/source/tables/CCPPUpdates.rst | 58 +++ docs/UsersGuide/source/tables/Tests.csv | 64 +-- docs/UsersGuide/source/tables/Tests.rst | 6 +- .../source/tables/fix_file_list.rst | 26 +- 33 files changed, 757 insertions(+), 1242 deletions(-) delete mode 100644 docs/UsersGuide/source/ContributorsGuide.rst delete mode 100644 docs/UsersGuide/source/_static/FV3LAM_wflow_flowchart.png delete mode 100644 docs/UsersGuide/source/_static/FV3LAM_wflow_flowchart_v2.png delete mode 100644 docs/UsersGuide/source/_static/FV3LAM_wflow_input_path.png delete mode 100644 docs/UsersGuide/source/_static/FV3LAM_wflow_overall.png delete mode 100644 docs/UsersGuide/source/_static/FV3regional_workflow_gen.png delete mode 100644 docs/UsersGuide/source/_static/FV3regional_workflow_gen_v2.png delete mode 100644 docs/UsersGuide/source/_static/SRW_overall_workflow_run.png create mode 100644 docs/UsersGuide/source/_static/SRW_run_process.png create mode 100644 docs/UsersGuide/source/_static/SRW_wflow_input_path.png create mode 100644 docs/UsersGuide/source/tables/CCPPUpdates.rst diff --git a/README.md b/README.md index f746ae5c78..bcb75fe601 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # UFS Short-Range Weather Application -The Unified Forecast System (UFS) is a community-based, coupled, comprehensive Earth modeling system. It is designed to be the source system for NOAA’s operational numerical weather prediction applications while enabling research, development, and contribution opportunities for the broader weather enterprise. For more information about the UFS, visit the UFS Portal at https://ufscommunity.org/. +The Unified Forecast System (UFS) is a community-based, coupled, comprehensive Earth modeling system. It is designed to be the source system for NOAA’s operational numerical weather prediction applications while enabling research, development, and contribution opportunities for the broader Weather Enterprise. For more information about the UFS, visit the UFS Portal at https://ufscommunity.org/. The UFS includes multiple applications (see a complete list at https://ufscommunity.org/science/aboutapps/) that support different forecast durations and spatial domains. This documentation describes the development branch of the UFS Short-Range Weather (SRW) Application, which targets predictions of atmospheric behavior on a limited spatial domain and on time scales from minutes to several days. The development branch of the application is continually evolving as the system undergoes open development. The latest SRW App release (v2.1.0) represents a snapshot of this continuously evolving system. diff --git a/docs/UsersGuide/source/BuildSRW.rst b/docs/UsersGuide/source/BuildSRW.rst index 85790b482c..4cf6ff71ae 100644 --- a/docs/UsersGuide/source/BuildSRW.rst +++ b/docs/UsersGuide/source/BuildSRW.rst @@ -30,18 +30,18 @@ To build the SRW App, users will complete the following steps: .. _HPCstackInfo: -Install the HPC-Stack -======================== +Install the Prerequisite Software Stack +========================================== -.. Attention:: - Skip the HPC-Stack installation if working on a `Level 1 system `_ (e.g., Cheyenne, Hera, Orion, NOAA Cloud). +Currently, installation of the prerequisite software stack is supported via HPC-Stack. :term:`HPC-Stack` is a repository that provides a unified, shell script-based system to build the software stack required for `UFS `__ applications such as the SRW App. -**Definition:** :term:`HPC-Stack` is a repository that provides a unified, shell script-based build system to build the software stack required for `UFS `_ applications such as the SRW App. +.. Attention:: + Skip the HPC-Stack installation if working on a `Level 1 system `__ (e.g., Cheyenne, Hera, Orion, NOAA Cloud), and :ref:`continue to the next section `. Background ---------------- -The UFS Weather Model draws on over 50 code libraries to run its applications. These libraries range from libraries developed in-house at NOAA (e.g., NCEPLIBS, FMS) to libraries developed by NOAA's partners (e.g., PIO, ESMF) to truly third party libraries (e.g., NETCDF). Individual installation of these libraries is not practical, so the `HPC-Stack `__ was developed as a central installation system to ensure that the infrastructure environment across multiple platforms is as similar as possible. Installation of the HPC-Stack is required to run the SRW App. +The UFS Weather Model draws on over 50 code libraries to run its applications. These libraries range from libraries developed in-house at NOAA (e.g., NCEPLIBS, FMS) to libraries developed by NOAA's partners (e.g., PIO, ESMF) to truly third party libraries (e.g., netCDF). Individual installation of these libraries is not practical, so the `HPC-Stack `__ was developed as a central installation system to ensure that the infrastructure environment across multiple platforms is as similar as possible. Installation of the HPC-Stack is required to run the SRW App. Instructions ------------------------- @@ -57,6 +57,9 @@ Users working on systems that fall under `Support Levels 2-4 `. +.. attention:: + Although HPC-Stack is the fully-supported option as of the v2.1.0 release, UFS applications are gradually shifting to :term:`spack-stack`, which is a :term:`Spack`-based method for installing UFS prerequisite software libraries. The spack-stack is currently used on NOAA Cloud platforms and in containers, while HPC-Stack is still used on other Level 1 systems and is the software stack validated by the UFS Weather Model as of the v2.1.0 release. Users are encouraged to check out `spack-stack `__ to prepare for the upcoming shift in support from HPC-Stack to spack-stack. + After completing installation, continue to the next section (:numref:`Section %s: Download the UFS SRW Application Code `). .. _DownloadSRWApp: @@ -114,7 +117,7 @@ The cloned repository contains the configuration files and sub-directories shown | | configuration files such as ``model_configure``, | | | ``diag_table``, and ``field_table``. | +--------------------------------+-----------------------------------------------------------+ - | README.md | Getting Started Guide | + | README.md | Contains SRW App introductory information | +--------------------------------+-----------------------------------------------------------+ | rename_model.sh | Used to rename the model before it becomes NCO | | | operational. The SRW App is a generic app that is the base| @@ -160,7 +163,7 @@ Run the executable that pulls in SRW App components from external repositories: .. code-block:: console - cd $SRW + cd ./manage_externals/checkout_externals The script should output dialogue indicating that it is retrieving different code repositories. It may take several minutes to download these repositories. @@ -169,7 +172,7 @@ To see more options for the ``checkout_externals`` script, users can run ``./man * ``-S``: Outputs the status of the repositories managed by ``checkout_externals``. By default only summary information is provided. Use with the ``-v`` (verbose) option to see details. * ``-x [EXCLUDE [EXCLUDE ...]]``: allows users to exclude components when checking out externals. - * ``-o``: By default only the required externals are checked out. This flag will also checkout the optional externals. + * ``-o``: By default only the required externals are checked out. This flag will also check out the optional externals. Generally, users will not need to use the options and can simply run the script, but the options are available for those who are curious. @@ -189,10 +192,10 @@ On Level 1 systems for which a modulefile is provided under the ``modulefiles`` ./devbuild.sh --platform= -where ```` is replaced with the name of the platform the user is working on. Valid values are: ``cheyenne`` | ``gaea`` | ``hera`` | ``jet`` | ``linux`` | ``macos`` | ``noaacloud`` | ``odin`` | ``orion`` | ``singularity`` | ``wcoss2`` +where ```` is replaced with the name of the platform the user is working on. Valid values include: ``cheyenne`` | ``gaea`` | ``hera`` | ``jet`` | ``linux`` | ``macos`` | ``noaacloud`` | ``orion`` .. note:: - Although build modulefiles exist for generic Linux and MacOS machines, users will need to alter these according to the instructions in Sections :numref:`%s ` & :numref:`%s `. Users on these systems may have more success building the SRW App with the :ref:`CMake Approach ` instead. + Although build modulefiles exist for generic Linux and MacOS machines, users will need to alter these according to the instructions in Sections :numref:`%s ` & :numref:`%s `. Users on these systems may have more success building the SRW App with the :ref:`CMake Approach ` instead. If compiler auto-detection fails for some reason, specify it using the ``--compiler`` argument. For example: @@ -375,7 +378,7 @@ Set Up the Build Environment .. attention:: * If users successfully built the executables in :numref:`Table %s `, they should skip to step :numref:`Chapter %s `. - * Users who want to build the SRW App on a generic MacOS should skip to :numref:`Section %s ` and follow the approach there. + * Users who want to build the SRW App on MacOS or generic Linux systems should skip to :numref:`Section %s ` and follow the approach there. If the ``devbuild.sh`` approach failed, users need to set up their environment to run a workflow on their specific platform. First, users should make sure ``Lmod`` is the app used for loading modulefiles. This is the case on most Level 1 systems; however, on systems such as Gaea/Odin, the default modulefile loader is from Cray and must be switched to Lmod. For example, on Gaea, users can run one of the following two commands depending on whether they have a bash or csh shell, respectively: @@ -384,9 +387,11 @@ If the ``devbuild.sh`` approach failed, users need to set up their environment t source etc/lmod-setup.sh gaea source etc/lmod-setup.csh gaea -If users execute one of the above commands on systems that don't need it, it will not cause any problems (it will simply do a ``module purge``). +.. note:: -From here on, ``Lmod`` is ready to load the modulefiles needed by the SRW App. These modulefiles are located in the ``modulefiles`` directory. To load the necessary modulefile for a specific ```` using a given ````, run: + If users execute one of the above commands on systems that don't need it, it will not cause any problems (it will simply do a ``module purge``). + +From here, ``Lmod`` is ready to load the modulefiles needed by the SRW App. These modulefiles are located in the ``modulefiles`` directory. To load the necessary modulefile for a specific ```` using a given ````, run: .. code-block:: console @@ -423,7 +428,7 @@ From the build directory, run the following commands to build the pre-processing cmake .. -DCMAKE_INSTALL_PREFIX=.. -DCMAKE_INSTALL_BINDIR=exec .. make -j 4 >& build.out & -``-DCMAKE_INSTALL_PREFIX`` specifies the location in which the ``exec``, ``include``, ``lib``, and ``share`` directories will be created. These directories will contain various components of the SRW App. Its recommended value ``..`` denotes one directory up from the build directory. In the next line, the ``make`` argument ``-j 4`` indicates that the build will run in parallel with 4 threads. Although users can specify a larger or smaller number of threads (e.g., ``-j 8``, ``-j 2``), it is highly recommended to use at least 4 parallel threads to prevent overly long installation times. +``-DCMAKE_INSTALL_PREFIX`` specifies the location where the ``exec``, ``include``, ``lib``, and ``share`` directories will be created. These directories will contain various components of the SRW App. Its recommended value ``..`` denotes one directory up from the build directory. In the next line, the ``make`` argument ``-j 4`` indicates that the build will run in parallel with 4 threads. Although users can specify a larger or smaller number of threads (e.g., ``-j 8``, ``-j 2``), it is highly recommended to use at least 4 parallel threads to prevent overly long installation times. The build will take a few minutes to complete. When it starts, a random number is printed to the console, and when it is done, a ``[1]+ Done`` message is printed to the console. ``[1]+ Exit`` indicates an error. Output from the build will be in the ``ufs-srweather-app/build/build.out`` file. When the build completes, users should see the forecast model executable ``ufs_model`` and several pre- and post-processing executables in the ``ufs-srweather-app/exec`` directory. These executables are described in :numref:`Table %s `. @@ -431,62 +436,41 @@ The build will take a few minutes to complete. When it starts, a random number i If you see the ``build.out`` file, but there is no ``ufs-srweather-app/exec`` directory, wait a few more minutes for the build to complete. -.. _MacDetails: +.. _MacLinuxDetails: -Additional Details for Building on MacOS ------------------------------------------- +Additional Details for Building on MacOS or Generic Linux +------------------------------------------------------------ .. note:: - Users who are **not** building the SRW App on a MacOS machine may skip to the :numref:`Section %s ` to finish building the SRW App or continue to :numref:`Chapter %s ` to configure and run an experiment. + Users who are **not** building the SRW App on MacOS or generic Linux platforms may skip to :numref:`Section %s ` to finish building the SRW App or continue to :numref:`Chapter %s ` to configure and run an experiment. -The SRW App can be built on MacOS machines, presuming HPC-Stack has already been installed successfully. The following two options have been tested: +The SRW App can be built on MacOS and generic Linux machines after the prerequisite software has been installed on these systems (via :term:`HPC-Stack` or :term:`spack-stack`). The installation for MacOS is architecture-independent and has been tested using both x86_64 and M1 chips (running natively). The following configurations for MacOS have been tested: -* **Option 1:** MacBookAir 2020, M1 chip (arm64, running natively), 4+4 cores, Big Sur 11.6.4, GNU compiler suite v.11.2.0_3 (gcc, gfortran, g++); no MPI pre-installed + #. MacBookPro 2019, 2.4 GHz 8-core Intel Core i9 (x86_64), Monterey Sur 12.1, GNU compiler suite v.11.3.0 (gcc, gfortran, g++); mpich 3.3.2 or openmpi/4.1.2 + #. MacBookAir 2020, M1 chip (arm64, running natively), 4+4 cores, Big Sur 11.6.4, GNU compiler suite v.11.3.0 (gcc, gfortran, g++); mpich 3.3.2 or openmpi/4.1.2 + #. MacBook Pro 2015, 2.8 GHz Quad-Core Intel Core i7 (x86_64), Catalina OS X 10.15.7, GNU compiler suite v.11.2.0_3 (gcc, gfortran, g++); mpich 3.3.2 or openmpi/4.1.2 -* **Option 2:** MacBook Pro 2015, 2.8 GHz Quad-Core Intel Core i7 (x86_64), Catalina OS X 10.15.7, GNU compiler suite v.11.2.0_3 (gcc, gfortran, g++); no MPI pre-installed +Several Linux builds have been tested on systems with x86_64 architectures. -The ``build_macos_gnu`` modulefile initializes the module environment, lists the location of HPC-Stack modules, loads the meta-modules and modules, and sets compilers, additional flags, and environment variables needed for building the SRW App. The modulefile must be modified to include the absolute path to the user's HPC-Stack installation and ``ufs-srweather-app`` directories. In particular, the following section must be modified: +The ``./modulefiles/build__gnu.lua`` modulefile (where ```` is ``macos`` or ``linux``) is written as a Lmod module in the Lua language, and it can be loaded once the Lmod module environment has been initialized (which should have happened even prior to :ref:`installing HPC-Stack `). This module lists the location of the HPC-Stack modules, loads the meta-modules and modules, sets serial and parallel compilers, additional flags, and any environment variables needed for building the SRW App. The modulefile must be modified to include the absolute path to the user's HPC-Stack installation: .. code-block:: console - # This path should point to your HPCstack installation directory - setenv HPCstack "/Users/username/hpc-stack/install" - - # This path should point to your SRW Application directory - setenv SRW "/Users/username/ufs-srweather-app" + - This path should point to your HPCstack installation directory + local HPCstack="/Users/username/hpc-stack/install" -An excerpt of the ``build_macos_gnu`` contents appears below for Option 1. To use Option 2, the user will need to comment out the lines specific to Option 1 (using a double hyphen) and uncomment the lines specific to Option 2 in the ``build_macos_gnu`` modulefile. Additionally, users need to verify that all file paths reflect their system's configuration and that the correct version numbers for software libraries appear in the modulefile. - -.. code-block:: console +Linux users need to configure the ``ufs-srweather-app/etc/lmod-setup.sh`` file for the ``linux`` case and set the ``BASH_ENV`` variable to point to the Lmod initialization script. There is no need to modify this script for the ``macos`` case presuming that Lmod followed a standard installation procedure using the Homebrew package manager for MacOS. - -- Option 1 compiler paths: - setenv("CC", "/opt/homebrew/bin/gcc") - setenv("FC", "/opt/homebrew/bin/gfortran") - setenv("CXX", "/opt/homebrew/bin/g++") - - -- Option 2 compiler paths: - --[[ - setenv("CC", "/usr/local/bin/gcc") - setenv("FC", "/usr/local/bin/gfortran") - setenv("CXX", "/usr/local/bin/g++") - --]] - -Then, users must source the Lmod setup file, just as they would on other systems, and load the modulefiles needed for building and running the SRW App: +Next, users must source the Lmod setup file, just as they would on other systems, and load the modulefiles needed for building and running the SRW App: .. code-block:: console - - source etc/lmod-setup.sh macos + + source etc/lmod-setup.sh module use - module load build_macos_gnu - export LDFLAGS="-L${MPI_ROOT}/lib" - -In a csh/tcsh shell, users would run ``source etc/lmod-setup.csh macos`` in place of the first line in the code block above. - -Additionally, for Option 1 systems, set the variable ``ENABLE_QUAD_PRECISION`` to ``OFF`` in the ``$SRW/src/ufs-weather-model/FV3/atmos_cubed_sphere/CMakeLists.txt`` file. This change is optional if using Option 2 to build the SRW App. To make this change using a streamline editor (`sed`), run: - -.. code-block:: console + module load build__gnu + export LDFLAGS+=" -L${MPI_ROOT}/lib " - sed -i .bak 's/QUAD_PRECISION\" ON)/QUAD_PRECISION\" OFF)/' $SRW/src/ufs-weather-model/FV3/atmos_cubed_sphere/CMakeLists.txt +In a csh/tcsh shell, users would run ``source etc/lmod-setup.csh `` in place of the first line in the code block above. The last line is primarily needed for the MacOS platforms. Proceed to building the executables using the process outlined in :numref:`Step %s `. diff --git a/docs/UsersGuide/source/Components.rst b/docs/UsersGuide/source/Components.rst index b187db6680..2b6ff1ddd8 100644 --- a/docs/UsersGuide/source/Components.rst +++ b/docs/UsersGuide/source/Components.rst @@ -8,11 +8,11 @@ The SRW Application assembles a variety of components, including: * Pre-processor Utilities & Initial Conditions * UFS Weather Forecast Model -* Unified Post-Processor +* Unified Post Processor * Visualization Examples * Build System and Workflow -These components are documented within this User's Guide and supported through a `community forum `_. +These components are documented within this User's Guide and supported through the `GitHub Discussions `__ forum. .. _Utils: @@ -30,25 +30,23 @@ The SRW Application can be initialized from a range of operational initial condi Forecast Model ============== -The prognostic atmospheric model in the UFS SRW Application is the Finite-Volume Cubed-Sphere -(:term:`FV3`) dynamical core configured with a Limited Area Model (:term:`LAM`) capability :cite:`BlackEtAl2021`. The :term:`dynamical core` is the computational part of a model that solves the equations of fluid motion. A User’s Guide for the UFS :term:`Weather Model` is `here `__. +The prognostic atmospheric model in the UFS SRW Application is the Finite-Volume Cubed-Sphere (:term:`FV3`) dynamical core configured with a Limited Area Model (:term:`LAM`) capability :cite:`BlackEtAl2021`. The :term:`dynamical core` is the computational part of a model that solves the equations of fluid motion. A User's Guide for the UFS Weather Model can be accessed `here `__. Supported model resolutions in this release include 3-, 13-, and 25-km predefined contiguous U.S. (:term:`CONUS`) domains, each with 127 vertical levels. Preliminary tools for users to define their own domain are also available in the release with full, formal support of these tools to be provided in future releases. The Extended Schmidt Gnomonic (ESG) grid is used with the FV3-LAM, which features relatively uniform grid cells across the entirety of the domain. Additional information about the FV3 dynamical core can be found in the `scientific documentation `__, the `technical documentation `__, and on the `NOAA Geophysical Fluid Dynamics Laboratory website `__. -Interoperable atmospheric physics, along with various land surface model options, are supported through the Common Community Physics Package (CCPP), described `here `__. Atmospheric physics are a set of numerical methods describing small-scale processes such as clouds, turbulence, radiation, and their interactions. There will be four physics suites supported for the SRW App v2.0.0 release. The first is the FV3_RRFS_v1beta physics suite, which is being tested for use in the future operational implementation of the Rapid Refresh Forecast System (RRFS) planned for 2023-2024, and the second is an updated version of the physics suite used in the operational Global Forecast System (GFS) v16. Additionally, FV3_WoFS_v0 and FV3_HRRR will be supported. A scientific description of the CCPP parameterizations and suites can be found in the `CCPP Scientific Documentation `__, and CCPP technical aspects are described in the `CCPP Technical Documentation `__. The model namelist has many settings beyond the physics options that can optimize various aspects of the model for use with each of the supported suites. Additional information on Stochastic Physics options is available `here `__. +Interoperable atmospheric physics, along with various land surface model options, are supported through the Common Community Physics Package (CCPP), described `here `__. Atmospheric physics are a set of numerical methods describing small-scale processes such as clouds, turbulence, radiation, and their interactions. There are four physics suites supported as of the SRW App v2.1.0 release. The first is the FV3_RRFS_v1beta physics suite, which is being tested for use in the future operational implementation of the Rapid Refresh Forecast System (:term:`RRFS`) planned for 2023-2024, and the second is an updated version of the physics suite used in the operational Global Forecast System (GFS) v16. Additionally, FV3_WoFS_v0 and FV3_HRRR are supported. A detailed list of CCPP updates since the SRW App v2.0.0 release is available :ref:`here `. A full scientific description of CCPP parameterizations and suites can be found in the `CCPP Scientific Documentation `__, and CCPP technical aspects are described in the `CCPP Technical Documentation `__. The model namelist has many settings beyond the physics options that can optimize various aspects of the model for use with each of the supported suites. Additional information on Stochastic Physics options is available `here `__. .. note:: SPP is currently only available for specific physics schemes used in the RAP/HRRR physics suite. Users need to be aware of which physics suite definition file (:term:`SDF`) is chosen when turning this option on. Among the supported physics suites, the full set of parameterizations can only be used with the ``FV3_HRRR`` option for ``CCPP_PHYS_SUITE``. The SRW App supports the use of both :term:`GRIB2` and :term:`NEMSIO` input data. The UFS Weather Model ingests initial and lateral boundary condition files produced by :term:`chgres_cube` and outputs files in netCDF format on a specific projection (e.g., Lambert Conformal) in the horizontal direction and model levels in the vertical direction. -Post-processor +Post Processor ============== The SRW Application is distributed with the Unified Post Processor (:term:`UPP`) included in the workflow as a way to convert the netCDF output on the native model grid to :term:`GRIB2` format on standard isobaric vertical coordinates. The UPP can also be used to compute a variety of useful diagnostic fields, as described in the `UPP User's Guide `__. -Output from UPP can be used with visualization, plotting, and verification packages or in -further downstream post-processing (e.g., statistical post-processing techniques). +Output from UPP can be used with visualization, plotting, and verification packages or in further downstream post-processing (e.g., statistical post-processing techniques). .. _MetplusComponent: @@ -57,39 +55,38 @@ METplus Verification Suite The enhanced Model Evaluation Tools (`METplus `__) verification system has been integrated into the SRW App to facilitate forecast evaluation. METplus is a verification framework that spans a wide range of temporal scales (warn-on-forecast to climate) and spatial scales (storm to global). It is supported by the `Developmental Testbed Center (DTC) `__. -METplus *installation* is not included as part of the build process for the most recent release of the SRW App. However, METplus is preinstalled on many `Level 1 & 2 `__ systems; existing builds can be viewed `here `__. METplus can be installed on other systems individually or as part of :term:`HPC-Stack` installation. Users on systems without a previous installation of METplus can follow the `MET Installation Guide `__ and `METplus Installation Guide `__ for individual installation. Currently, METplus *installation* is not a supported feature for this release of the SRW App. However, METplus *use* is supported on systems with a functioning METplus installation. +METplus *installation* is not included as part of the build process for the most recent release of the SRW App. However, METplus is preinstalled on many `Level 1 & 2 `__ systems; existing builds can be viewed `here `__. -The core components of the METplus framework include the statistical driver, MET, the associated database and display systems known as METviewer and METexpress, and a suite of Python wrappers to provide low-level automation and examples, also called use-cases. MET is a set of verification tools developed for use by the :term:`NWP` community. It matches up grids with either gridded analyses or point observations and applies configurable methods to compute statistics and diagnostics. Extensive documentation is available in the `METplus User’s Guide `__ and `MET User’s Guide `__. Documentation for all other components of the framework can be found at the Documentation link for each component on the METplus `downloads `__ page. +METplus can be installed on other systems individually or as part of :term:`HPC-Stack` installation. Users on systems without a previous installation of METplus can follow the `MET Installation Guide `__ and `METplus Installation Guide `__ for individual installation. Currently, METplus *installation* is not a supported feature for this release of the SRW App. However, METplus *use* is supported on systems with a functioning METplus installation. -Among other techniques, MET provides the capability to compute standard verification scores for comparing deterministic gridded model data to point-based and gridded observations. It also provides ensemble and probabilistic verification methods for comparing gridded model data to point-based or gridded observations. Verification tasks to accomplish these comparisons are defined in the SRW App in :numref:`Table %s `. Currently, the SRW App supports the use of :term:`NDAS` observation files in `prepBUFR format `__ (which include conventional point-based surface and upper-air data) for point-based verification. It also supports gridded Climatology-Calibrated Precipitation Analysis (:term:`CCPA`) data for accumulated precipitation evaluation and Multi-Radar/Multi-Sensor (:term:`MRMS`) gridded analysis data for composite reflectivity and :term:`echo top` verification. +The core components of the METplus framework include the statistical driver, MET, the associated database and display systems known as METviewer and METexpress, and a suite of Python wrappers to provide low-level automation and examples, also called use cases. MET is a set of verification tools developed for use by the :term:`NWP` community. It matches up grids with either gridded analyses or point observations and applies configurable methods to compute statistics and diagnostics. Extensive documentation is available in the `METplus User's Guide `__ and `MET User's Guide `__. Documentation for all other components of the framework can be found at the Documentation link for each component on the METplus `downloads `__ page. + +Among other techniques, MET provides the capability to compute standard verification scores for comparing deterministic gridded model data to point-based and gridded observations. It also provides ensemble and probabilistic verification methods for comparing gridded model data to point-based or gridded observations. Verification tasks to accomplish these comparisons are defined in the SRW App in :numref:`Table %s `. Currently, the SRW App supports the use of :term:`NDAS` observation files (which include conventional point-based surface and upper-air data) in `prepBUFR format `__ for point-based verification. It also supports gridded Climatology-Calibrated Precipitation Analysis (:term:`CCPA`) data for accumulated precipitation evaluation and Multi-Radar/Multi-Sensor (:term:`MRMS`) gridded analysis data for composite reflectivity and :term:`echo top` verification. METplus is being actively developed by :term:`NCAR`/Research Applications Laboratory (RAL), NOAA/Earth Systems Research Laboratories (ESRL), and NOAA/Environmental Modeling Center (:term:`EMC`), and it is open to community contributions. Visualization Example ===================== -A Python script is provided to create basic visualizations of the model output. The script -is designed to output graphics in PNG format for 14 standard meteorological variables +A Python script is provided to create basic visualizations of the model output. The script is designed to output graphics in PNG format for several standard meteorological variables when using the pre-defined :term:`CONUS` domain. A difference plotting script is also included to visually compare two runs for the same domain and resolution. These scripts are provided only as an example for users familiar with Python. They may be used to perform a visual check to verify that the application is producing reasonable results. -After running ``manage_externals/checkout_externals``, the visualization scripts will be available in the ``ufs-srweather-app/ush/Python`` directory. Usage information and instructions are described in :numref:`Chapter %s ` and are also included at the top of the script. +After running ``manage_externals/checkout_externals``, the visualization scripts will be available in the ``ufs-srweather-app/ush/Python`` directory. Usage information and instructions are described in :numref:`Chapter %s ` and are also included at the top of each script. Build System and Workflow ========================= The SRW Application has a portable build system and a user-friendly, modular, and expandable workflow framework. -An umbrella CMake-based build system is used for building the components necessary for running the end-to-end SRW Application, including the UFS Weather Model and the pre- and post-processing software. Additional libraries necessary for the application (e.g., :term:`NCEPLIBS-external` and :term:`NCEPLIBS`) are not included in the SRW Application build system but are available pre-built on pre-configured platforms. On other systems, they can be installed via the HPC-Stack (see :doc:`HPC-Stack Documentation `). There is a small set of system libraries and utilities that are assumed to be present on the target computer: the CMake build software, a Fortran, C, and C++ compiler, and an :term:`MPI` library. +An umbrella CMake-based build system is used for building the components necessary for running the end-to-end SRW Application, including the UFS Weather Model and the pre- and post-processing software. Additional libraries necessary for the application (e.g., :term:`NCEPLIBS-external` and :term:`NCEPLIBS`) are not included in the SRW Application build system but are available pre-built on pre-configured platforms. On other systems, they can be installed via the HPC-Stack (see :doc:`HPC-Stack Documentation `). There is a small set of system libraries and utilities that are assumed to be present on the target computer: the CMake build software; a Fortran, C, and C++ compiler; and an :term:`MPI` library. Once built, the provided experiment generator script can be used to create a Rocoto-based -workflow file that will run each task in the system in the proper sequence (see :numref:`Chapter %s ` or the `Rocoto documentation `_ for more information on Rocoto). If Rocoto and/or a batch system is not present on the available platform, the individual components can be run in a stand-alone, command line fashion with provided run scripts. The generated namelist for the atmospheric model can be modified in order to vary settings such as forecast starting and ending dates, forecast length hours, the :term:`CCPP` physics suite, integration time step, history file output frequency, and more. It also allows for configuration of other elements of the workflow; for example, users can choose whether to run some or all of the pre-processing, forecast model, and post-processing steps. +workflow file that will run each task in the system in the proper sequence (see :numref:`Chapter %s ` or the `Rocoto documentation `__ for more information on Rocoto). If Rocoto and/or a batch system is not present on the available platform, the individual components can be run in a stand-alone, command line fashion with provided run scripts. The generated namelist for the atmospheric model can be modified in order to vary settings such as forecast starting and ending dates, forecast length hours, the :term:`CCPP` physics suite, integration time step, history file output frequency, and more. It also allows for configuration of other elements of the workflow; for example, users can choose whether to run some or all of the pre-processing, forecast model, and post-processing steps. -The latest SRW Application release has been tested on a variety of platforms widely used by -researchers, such as the NOAA Research and Development High-Performance Computing Systems -(RDHPCS), including Hera, Orion, and Jet; the National Center for Atmospheric Research (:term:`NCAR`) Cheyenne system; the National Severe Storms Laboratory (NSSL) HPC machine, Odin; the National Science Foundation Stampede2 system; and generic Linux and MacOS systems using Intel and GNU compilers. Four `levels of support `_ have been defined for the SRW Application, including pre-configured (Level 1), configurable (Level 2), limited test platforms (Level 3), and build only platforms (Level 4). Each level is further described below. +The latest SRW Application release has been tested on a variety of platforms widely used by researchers, such as the NOAA Research and Development High-Performance Computing Systems (RDHPCS), including Hera, Orion, and Jet; the National Center for Atmospheric Research (:term:`NCAR`) Cheyenne system; and generic Linux and MacOS systems using Intel and GNU compilers. Four `levels of support `__ have been defined for the SRW Application, including pre-configured (Level 1), configurable (Level 2), limited-test (Level 3), and build-only (Level 4) platforms. Each level is further described below. On pre-configured (Level 1) computational platforms, all the required libraries for building the SRW Application are available in a central place. That means bundled libraries (NCEPLIBS) and third-party libraries (NCEPLIBS-external) have both been built. The SRW Application is expected to build and run out-of-the-box on these pre-configured platforms. A few additional computational platforms are considered configurable for the SRW Application release. Configurable platforms (Level 2) are platforms where all of the required libraries for building the SRW Application are expected to install successfully but are not available in a central location. Applications and models are expected to build and run once the required bundled libraries (e.g., NCEPLIBS) and third-party libraries (e.g., NCEPLIBS-external) are built. -Limited-Test (Level 3) and Build-Only (Level 4) computational platforms are those in which the developers have built the code but little or no pre-release testing has been conducted, respectively. A complete description of the levels of support, along with a list of preconfigured and configurable platforms can be found in the `SRW Application Wiki `_. +Limited-Test (Level 3) and Build-Only (Level 4) computational platforms are those in which the developers have built the code but little or no pre-release testing has been conducted, respectively. A complete description of the levels of support, along with a list of preconfigured and configurable platforms can be found in the `SRW Application Wiki `__. diff --git a/docs/UsersGuide/source/ConfigWorkflow.rst b/docs/UsersGuide/source/ConfigWorkflow.rst index eb0407e954..ecde1be5d3 100644 --- a/docs/UsersGuide/source/ConfigWorkflow.rst +++ b/docs/UsersGuide/source/ConfigWorkflow.rst @@ -488,8 +488,7 @@ Verification Tasks ``RUN_TASK_VX_ENSPOINT``: (Default: false) Flag that determines whether to run the ensemble point verification task. If this flag is set, both ensemble-stat point verification and point verification of ensemble-stat output is computed. The :ref:`MET Ensemble-Stat tool ` provides verification statistics for ensemble forecasts and can be used in conjunction with the :ref:`MET Point-Stat tool `. See :numref:`Section %s ` for additional parameters related to this task. Valid values: ``True`` | ``False`` -.. - COMMENT: Might be worth defining "ensemble-stat verification for gridded data," "ensemble point verification," "ensemble-stat point verification," and "point verification of ensemble-stat output" +.. COMMENT: COMMENT: Define "ensemble-stat verification for gridded data," "ensemble point verification," "ensemble-stat point verification," and "point verification of ensemble-stat output"? .. _make-grid: @@ -917,10 +916,12 @@ Non-default parameters for the ``make_lbcs`` task are set in the ``task_make_lbc ``OMP_STACKSIZE_MAKE_LBCS``: (Default: "1024m") Controls the size of the stack for threads created by the OpenMP implementation. +.. _FcstConfigParams: + FORECAST Configuration Parameters ===================================== -Non-default parameters for the ``run_fcst`` task are set in the ``task_run_fcst`` section of the ``config.yaml`` file. +Non-default parameters for the ``run_fcst`` task are set in the ``task_run_fcst:`` section of the ``config.yaml`` file. Basic Task Parameters --------------------------------- @@ -961,13 +962,15 @@ For each workflow task, certain parameter values must be passed to the job sched ``OMP_STACKSIZE_RUN_FCST``: (Default: "1024m") Controls the size of the stack for threads created by the OpenMP implementation. +.. _ModelConfigParams: + Model Configuration Parameters ---------------------------------- These parameters set values in the Weather Model's ``model_configure`` file. ``DT_ATMOS``: (Default: "") - Time step for the outermost atmospheric model loop in seconds. This corresponds to the frequency at which the physics routines and the top level dynamics routine are called. (Note that one call to the top-level dynamics routine results in multiple calls to the horizontal dynamics, :term:`tracer` transport, and vertical dynamics routines; see the `FV3 dycore scientific documentation `__ for details.) Must be set. Takes an integer value. In the SRW App, a default value for ``DT_ATMOS`` appears in the ``set_predef_grid_params.yaml`` script, but a different value can be set in ``config.yaml``. + Time step for the outermost atmospheric model loop in seconds. This corresponds to the frequency at which the physics routines and the top level dynamics routine are called. (Note that one call to the top-level dynamics routine results in multiple calls to the horizontal dynamics, :term:`tracer` transport, and vertical dynamics routines; see the `FV3 dycore scientific documentation `__ for details.) Must be set. Takes an integer value. In the SRW App, a default value for ``DT_ATMOS`` appears in the ``set_predef_grid_params.yaml`` script, but a different value can be set in ``config.yaml``. In general, the smaller the grid cell size is, the smaller this value needs to be in order to avoid numerical instabilities during the forecast. ``RESTART_INTERVAL``: (Default: 0) Frequency of the output restart files in hours. Using the default interval (0), restart files are produced at the end of a forecast run. When ``RESTART_INTERVAL: 1``, restart files are produced every hour with the prefix "YYYYMMDD.HHmmSS." in the ``RESTART`` directory. @@ -1012,7 +1015,7 @@ Write-Component (Quilting) Parameters Flag that determines whether to output extra (debugging) information from :term:`ESMF` routines. Note that the write component uses ESMF library routines to interpolate from the native forecast model grid to the user-specified output grid (which is defined in the model configuration file ``model_configure`` in the forecast run directory). Valid values: ``True`` | ``False`` ``WRTCMP_write_groups``: (Default: 1) - The number of write groups (i.e., groups of :term:`MPI` tasks) to use in the write component. + The number of write groups (i.e., groups of :term:`MPI` tasks) to use in the write component. Each write group will write to one set of output files (a ``dynf${fhr}.nc`` and a ``phyf${fhr}.nc`` file, where ``${fhr}`` is the forecast hour). Each write group contains ``WRTCMP_write_tasks_per_group`` tasks. Usually, one write group is sufficient. This may need to be increased if the forecast is proceeding so quickly that a single write group cannot complete writing to its set of files before there is a need/request to start writing the next set of files at the next output time. ``WRTCMP_write_tasks_per_group``: (Default: 20) The number of MPI tasks to allocate for each write group. @@ -1912,11 +1915,6 @@ The parameters below turn on SPP in Noah or RUC LSM (support for Noah MP is in p ``LSM_SPP_MAG_LIST``: (Default: [ 0.017, 0.001, 0.001, 0.001, 0.001, 0.001, 0.2 ] ) Sets the maximum random pattern amplitude for each of the LSM perturbations. -.. COMMENT: This variable no longer appears and was going to be removed. See if anything has replaced it. - ``LSM_SPP_EACH_STEP``: (Default: "true") - When set to "TRUE", it sets ``lndp_each_step=.true.`` and perturbs each time step. - - .. _HaloBlend: Halo Blend Parameter diff --git a/docs/UsersGuide/source/ContainerQuickstart.rst b/docs/UsersGuide/source/ContainerQuickstart.rst index 8b72c079e5..025893a840 100644 --- a/docs/UsersGuide/source/ContainerQuickstart.rst +++ b/docs/UsersGuide/source/ContainerQuickstart.rst @@ -4,7 +4,7 @@ Container-Based Quick Start Guide ==================================== -This Container-Based Quick Start Guide will help users build and run the "out-of-the-box" case for the Unified Forecast System (:term:`UFS`) Short-Range Weather (SRW) Application using a `Singularity `__ container. The :term:`container` approach provides a uniform enviroment in which to build and run the SRW App. Normally, the details of building and running the SRW App vary from system to system due to the many possible combinations of operating systems, compilers, :term:`MPI`'s, and package versions available. Installation via Singularity container reduces this variability and allows for a smoother SRW App build experience. Normally, containers can only run on a single compute node and are not compatible with the `Rocoto workflow manager `__, so users must run each task in the workflow manually. However, the Singularity container described in this chapter has been adapted such that it is able to run across multiple nodes using Rocoto. This makes it an excellent starting point for beginners. The :ref:`non-container build approach ` may still be more appropriate for users who desire additional customizability, particularly if they already have experience running the SRW App. +This Container-Based Quick Start Guide will help users build and run the "out-of-the-box" case for the Unified Forecast System (:term:`UFS`) Short-Range Weather (SRW) Application using a `Singularity `__ container. The :term:`container` approach provides a uniform enviroment in which to build and run the SRW App. Normally, the details of building and running the SRW App vary from system to system due to the many possible combinations of operating systems, compilers, :term:`MPIs `, and package versions available. Installation via Singularity container reduces this variability and allows for a smoother SRW App build experience. Normally, containers can only run on a single compute node and are not compatible with the `Rocoto workflow manager `__, so users must run each task in the workflow manually. However, the Singularity container described in this chapter has been adapted such that it is able to run across multiple nodes using Rocoto. This makes it an excellent starting point for beginners. The :ref:`non-container build approach ` may still be more appropriate for users who desire additional customizability, particularly if they already have experience running the SRW App. The "out-of-the-box" SRW App case described in this User's Guide builds a weather forecast for June 15-16, 2019. Multiple convective weather events during these two days produced over 200 filtered storm reports. Severe weather was clustered in two areas: the Upper Midwest through the Ohio Valley and the Southern Great Plains. This forecast uses a predefined 25-km Continental United States (:term:`CONUS`) grid (RRFS_CONUS_25km), the Global Forecast System (:term:`GFS`) version 16 physics suite (FV3_GFS_v16 :term:`CCPP`), and :term:`FV3`-based GFS raw external model data for initialization. @@ -28,7 +28,7 @@ Users must have an **Intel** compiler and :term:`MPI` (available for free `here Install Singularity ^^^^^^^^^^^^^^^^^^^^^^^ -To build and run the SRW App using a Singularity container, first install the Singularity package according to the `Singularity Installation Guide `__. This will include the installation of dependencies and the installation of the Go programming language. SingularityCE Version 3.7 or above is recommended. +To build and run the SRW App using a Singularity container, first install the Singularity package according to the `Singularity Installation Guide `__. This will include the installation of dependencies and the installation of the Go programming language. SingularityCE Version 3.7 or above is recommended. .. warning:: Docker containers can only be run with root privileges, and users cannot have root privileges on :term:`HPCs `. Therefore, it is not possible to build the SRW App, which uses the HPC-Stack, inside a Docker container on an HPC system. However, a Singularity image may be built directly from a Docker image for use on the system. @@ -124,11 +124,11 @@ On non-Level 1 systems, users should build the container in a writable sandbox: Some users may prefer to issue the command without the ``sudo`` prefix. Whether ``sudo`` is required is system-dependent. .. note:: - Users can choose to build a release version of the container (SRW App v2.0.0) using a similar command: + Users can choose to build a release version of the container (SRW App v2.1.0) using a similar command: .. code-block:: console - sudo singularity build --sandbox ubuntu20.04-intel-srwapp docker://noaaepic/ubuntu20.04-intel22-ufs-srwapp:release-public-v2 + sudo singularity build --sandbox ubuntu20.04-intel-srwapp docker://noaaepic/ubuntu20.04-intel-srwapp:release-public-v2.1.0 .. _WorkOnHPC: @@ -210,7 +210,7 @@ Users can run ``exit`` to exit the shell. Download and Stage the Data ============================ -The SRW App requires input files to run. These include static datasets, initial and boundary condition files, and model configuration files. On Level 1 systems, the data required to run SRW App tests are already available as long as the bind argument (starting with ``-B``) in :numref:`Step %s ` included the directory with the input model data. For Level 2-4 systems, the data must be added manually by the user. Detailed instructions on how to add the data can be found in :numref:`Section %s `. Sections :numref:`%s ` and :numref:`%s ` contain useful background information on the input and output files used in the SRW App. +The SRW App requires input files to run. These include static datasets, initial and boundary condition files, and model configuration files. On Level 1 systems, the data required to run SRW App tests are already available as long as the bind argument (starting with ``-B``) in :numref:`Step %s ` included the directory with the input model data. See :numref:`Table %s ` for Level 1 data locations. For Level 2-4 systems, the data must be added manually by the user. Detailed instructions on how to add the data can be found in :numref:`Section %s `. Sections :numref:`%s ` and :numref:`%s ` contain useful background information on the input and output files used in the SRW App. .. _GenerateForecastC: @@ -246,7 +246,7 @@ To activate the regional workflow, run the following commands: where: - * ```` is replaced with the actual path to the modulefiles on the user's system (often ``$PWD/modulefiles``), and + * ```` is replaced with the actual path to the modulefiles on the user's local system (often ``$PWD/modulefiles``), and * ```` is a valid, lowercased machine/platform name (see the ``MACHINE`` variable in :numref:`Section %s `). The ``wflow_`` modulefile will then output instructions to activate the regional workflow. The user should run the commands specified in the modulefile output. For example, if the output says: @@ -310,7 +310,7 @@ From here, users can follow the steps below to configure the out-of-the-box SRW .. code-block:: console USE_CRON_TO_RELAUNCH: TRUE - CRON_RELAUNCH_INTVL_MNTS: 02 + CRON_RELAUNCH_INTVL_MNTS: 3 There are instructions for running the experiment via additional methods in :numref:`Section %s `. However, this technique (automation via :term:`crontab`) is the simplest option. @@ -351,7 +351,7 @@ Run the following command to generate the workflow: .. code-block:: console - python generate_FV3LAM_wflow.py + ./generate_FV3LAM_wflow.py This workflow generation script creates an experiment directory and populates it with all the data needed to run through the workflow. The last line of output from this script should start with ``*/3 * * * *`` (or similar). @@ -387,7 +387,7 @@ where: New Experiment =============== -To run a new experiment in the container at a later time, users will need to rerun the commands in :numref:`Section %s ` to reactivate the regional workflow. Then, users can configure a new experiment by updating the environment variables in ``config.yaml`` to reflect the desired experiment configuration. Basic instructions appear in :numref:`Section %s ` above, and detailed instructions can be viewed in :numref:`Section %s `. After adjusting the configuration file, regenerate the experiment by running ``python generate_FV3LAM_wflow.py``. +To run a new experiment in the container at a later time, users will need to rerun the commands in :numref:`Section %s ` to reactivate the regional workflow. Then, users can configure a new experiment by updating the environment variables in ``config.yaml`` to reflect the desired experiment configuration. Basic instructions appear in :numref:`Section %s ` above, and detailed instructions can be viewed in :numref:`Section %s `. After adjusting the configuration file, regenerate the experiment by running ``./generate_FV3LAM_wflow.py``. Plot the Output =============== diff --git a/docs/UsersGuide/source/ContributorsGuide.rst b/docs/UsersGuide/source/ContributorsGuide.rst deleted file mode 100644 index efb90ca4cc..0000000000 --- a/docs/UsersGuide/source/ContributorsGuide.rst +++ /dev/null @@ -1,463 +0,0 @@ - -.. _ContributorsGuide: - -============================== -SRW App Contributor's Guide -============================== - -.. _Background: - -Background -=========== - -Authoritative branch ------------------------ - -The ``ufs-srweather-app`` repository maintains a main branch for development called ``develop``. The HEAD of ``develop`` reflects the latest development changes. It points to regularly updated hashes for individual sub-components. Pull requests (PRs) will be merged to ``develop``. - -The ``develop`` branch is protected by the code management team: - #. Pull requests for this branch require approval by at least two code reviewers. - #. A code manager should perform at least one of the reviews and the merge, but other contributors are welcome to provide comments/suggestions. - - -Code Management Team --------------------------- - -Scientists from across multiple labs and organizations have volunteered to review pull requests for the ``develop`` branch: - -.. table:: - - +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ - | **Organization** | **Reviewers** | **Areas of Expertise** | - +==================+================================================+=============================================================================================+ - | EMC | Chan-Hoo Jeon (@chan-hoo) | Workflow, Operational platform testing (WCOSS/NCO), and Air quality modeling (Online-CMAQ) | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Ben Blake (@BenjaminBlake-NOAA) | Output visualization, Rocoto | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Ratko Vasic (@RatkoVasic-NOAA) | Workflow, NCO requirements, and operational platform testing | - +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ - | EPIC | Mark Potts (@mark-a-potts) | HPC systems | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Jong Kim (@jkbk2004) | UFS Weather Model configuration, forecast sensitivity analysis, data assimilation | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Michael Lueken (@MichaelLueken) | SRW App code management | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Natalie Perlin (@natalie-perlin) | Generic Linux/Mac installations, hpc-stack/spack-stack | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Gillian Petro (@gspetro-NOAA) | Documentation | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Edward Snyder (@EdwardSnyder-NOAA) | WE2E testing, input data | - +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ - | GLERL | David Wright (@dmwright526) | FVCOM integration, output visualization, preprocessing tasks | - +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ - | GSL | Jeff Beck (@JeffBeck-NOAA) | SRW App configuration/workflow, code management, meteorological evaluation | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Gerard Ketefian (@gsketefian) | regional workflow scripts, jinja templates, and verification tasks | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Linlin Pan (@panll) | Workflow, CCPP/physics, verification | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Christina Holt (@christinaholtNOAA) | Workflow, conda environment support, testing, and code management | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Christopher Harrop (@christopherwharrop-noaa) | Rocoto, code management, and testing | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Daniel Abdi (@danielabdi-noaa) | Workflow generation, testing RRFS on the cloud, environment modules | - +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ - | NCAR | Mike Kavulich (@mkavulich) | CCPP/physics | - | +------------------------------------------------+---------------------------------------------------------------------------------------------+ - | | Will Mayfield (@willmayfield) | Verification/METplus tasks, regional workflow (esp. on Cheyenne) | - +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ - | NSSL | Yunheng Wang (@ywangwof) | HPC systems, code management and regional workflow especially on Stampede, Jet | - | | | and NSSL computers | - +------------------+------------------------------------------------+---------------------------------------------------------------------------------------------+ - -.. _ContribProcess: - -Contribution Process -======================== - -The steps below should be followed in order to make changes to the ``develop`` branch of the ``ufs-srweather-app`` repository. Communication with code managers and the code management team throughout the process is encouraged. - - #. **Issue** - Open an issue to document changes. Click `here `__ to open a new ``ufs-srweather-app`` issue or see :numref:`Step %s ` for detailed instructions. - #. **GitFlow** - Follow `GitFlow `__ procedures for development. - #. **Fork the repository** - Read more `here `__ about forking in GitHub. - #. **Create a branch** - Create a branch in your fork of the authoritative repository. Follow `GitFlow `__ conventions when creating the branch. All development should take place on a branch, *not* on ``develop``. Branches should be named as follows, where [name] is a one-word description of the branch: - - * **bugfix/[name]:** Fixes a demonstrably incorrect portion of code - * **feature/[name]:** Adds a new feature to the code or improves an existing portion of the code - * **text/[name]:** Changes elements of the repository that do not impact program output or log files (e.g., changes to README, documentation, comments, changing quoted Registry elements, white space alignment). Any change that does not impact the compiled code in any way should fall under this category. - - #. **Development** - Perform and test changes in the branch (not on ``develop``!). Document work in the issue and mention the issue number in commit messages to link your work to the issue (e.g., ``commit -m "Issue #23 - "``). Test code modifications on as many platforms as possible, and request help with further testing from the code management team when unable to test on all Level 1 platforms. Document changes to the workflow and capabilities in the ``.rst`` files so that the SRW App documentation stays up-to-date. - #. **Pull request** - When ready to merge changes back to the ``develop`` branch, the code developer should initiate a pull request (PR) of the feature branch into the ``develop`` branch. Read `here `__ about pull requests in GitHub. When a PR is initiated, the :ref:`PR Template