diff --git a/ci/cases/pr/C48_S2SA_gefs.yaml b/ci/cases/pr/C48_S2SA_gefs.yaml index 927a979b13..2abbf0043e 100644 --- a/ci/cases/pr/C48_S2SA_gefs.yaml +++ b/ci/cases/pr/C48_S2SA_gefs.yaml @@ -9,9 +9,9 @@ arguments: resens: 48 nens: 2 gfs_cyc: 1 + start: cold comrot: {{ 'RUNTESTS' | getenv }}/COMROT expdir: {{ 'RUNTESTS' | getenv }}/EXPDIR - icsdir: {{ 'ICSDIR_ROOT' | getenv }}/C48C48mx500 idate: 2021032312 edate: 2021032312 yaml: {{ HOMEgfs }}/ci/platforms/gefs_ci_defaults.yaml diff --git a/jobs/JGFS_ATMOS_CYCLONE_GENESIS b/jobs/JGFS_ATMOS_CYCLONE_GENESIS index d2d147125c..5ac97e079c 100755 --- a/jobs/JGFS_ATMOS_CYCLONE_GENESIS +++ b/jobs/JGFS_ATMOS_CYCLONE_GENESIS @@ -1,7 +1,7 @@ #! /usr/bin/env bash source "${HOMEgfs}/ush/preamble.sh" -source "${HOMEgfs}/ush/jjob_header.sh" -e "vrfy" -c "base vrfy" +source "${HOMEgfs}/ush/jjob_header.sh" -e "genesis" -c "base genesis" ############################################## diff --git a/jobs/JGFS_ATMOS_CYCLONE_TRACKER b/jobs/JGFS_ATMOS_CYCLONE_TRACKER index 09ec630009..a91d8e3c5b 100755 --- a/jobs/JGFS_ATMOS_CYCLONE_TRACKER +++ b/jobs/JGFS_ATMOS_CYCLONE_TRACKER @@ -1,7 +1,7 @@ #! /usr/bin/env bash source "${HOMEgfs}/ush/preamble.sh" -source "${HOMEgfs}/ush/jjob_header.sh" -e "vrfy" -c "base vrfy" +source "${HOMEgfs}/ush/jjob_header.sh" -e "tracker" -c "base tracker" export COMPONENT="atmos" diff --git a/jobs/JGFS_ATMOS_FSU_GENESIS b/jobs/JGFS_ATMOS_FSU_GENESIS index c31037aa08..cc730e21bb 100755 --- a/jobs/JGFS_ATMOS_FSU_GENESIS +++ b/jobs/JGFS_ATMOS_FSU_GENESIS @@ -1,7 +1,7 @@ #! /usr/bin/env bash source "${HOMEgfs}/ush/preamble.sh" -source "${HOMEgfs}/ush/jjob_header.sh" -e "vrfy" -c "base vrfy" +source "${HOMEgfs}/ush/jjob_header.sh" -e "genesis_fsu" -c "base genesis_fsu" export COMPONENT="atmos" diff --git a/jobs/JGLOBAL_FORECAST b/jobs/JGLOBAL_FORECAST index e42c81eaa4..b2825af54f 100755 --- a/jobs/JGLOBAL_FORECAST +++ b/jobs/JGLOBAL_FORECAST @@ -46,7 +46,7 @@ declare -rx gcyc="${GDATE:8:2}" # Construct COM variables from templates (see config.com) YMD=${PDY} HH=${cyc} generate_com -rx COM_ATMOS_RESTART COM_ATMOS_INPUT COM_ATMOS_ANALYSIS \ - COM_ATMOS_HISTORY COM_ATMOS_MASTER COM_TOP + COM_ATMOS_HISTORY COM_ATMOS_MASTER COM_TOP COM_CONF RUN=${rCDUMP} YMD="${gPDY}" HH="${gcyc}" generate_com -rx \ COM_ATMOS_RESTART_PREV:COM_ATMOS_RESTART_TMPL diff --git a/jobs/rocoto/genesis.sh b/jobs/rocoto/genesis.sh new file mode 100755 index 0000000000..009a7006ef --- /dev/null +++ b/jobs/rocoto/genesis.sh @@ -0,0 +1,20 @@ +#! /usr/bin/env bash + +source "${HOMEgfs}/ush/preamble.sh" + +############################################################### +# Source FV3GFS workflow modules +source "${HOMEgfs}/ush/load_fv3gfs_modules.sh" +status=$? +(( status != 0 )) && exit "${status}" + +export job="genesis" +export jobid="${job}.$$" + +############################################################### +# Execute the JJOB + +"${HOMEgfs}/jobs/JGFS_ATMOS_CYCLONE_GENESIS" +status=$? + +exit "${status}" diff --git a/jobs/rocoto/genesis_fsu.sh b/jobs/rocoto/genesis_fsu.sh new file mode 100755 index 0000000000..05c0ff8827 --- /dev/null +++ b/jobs/rocoto/genesis_fsu.sh @@ -0,0 +1,20 @@ +#! /usr/bin/env bash + +source "${HOMEgfs}/ush/preamble.sh" + +############################################################### +# Source FV3GFS workflow modules +source "${HOMEgfs}/ush/load_fv3gfs_modules.sh" +status=$? +(( status != 0 )) && exit "${status}" + +export job="genesis_fsu" +export jobid="${job}.$$" + +############################################################### +# Execute the JJOB + +"${HOMEgfs}/jobs/JGFS_ATMOS_FSU_GENESIS" +status=$? + +exit "${status}" diff --git a/jobs/rocoto/tracker.sh b/jobs/rocoto/tracker.sh new file mode 100755 index 0000000000..3e2efd644e --- /dev/null +++ b/jobs/rocoto/tracker.sh @@ -0,0 +1,20 @@ +#! /usr/bin/env bash + +source "${HOMEgfs}/ush/preamble.sh" + +############################################################### +# Source FV3GFS workflow modules +source "${HOMEgfs}/ush/load_fv3gfs_modules.sh" +status=$? +(( status != 0 )) && exit "${status}" + +export job="tracker" +export jobid="${job}.$$" + +############################################################### +# Execute the JJOB + +"${HOMEgfs}/jobs/JGFS_ATMOS_CYCLONE_TRACKER" +status=$? + +exit "${status}" diff --git a/jobs/rocoto/vrfy.sh b/jobs/rocoto/vrfy.sh index 67ac43e137..1c0cf61d3b 100755 --- a/jobs/rocoto/vrfy.sh +++ b/jobs/rocoto/vrfy.sh @@ -52,34 +52,6 @@ if [[ "${RUNMOS}" == "YES" && "${CDUMP}" == "gfs" ]]; then fi -################################################################################ -echo -echo "=============== START TO RUN CYCLONE TRACK VERIFICATION ===============" -if [[ ${VRFYTRAK} = "YES" ]]; then - - COMINsyn=${COMINsyn:-$(compath.py "${envir}/com/gfs/${gfs_ver}")/syndat} - export COMINsyn - - ${TRACKERSH} -fi - - -################################################################################ -echo -echo "=============== START TO RUN CYCLONE GENESIS VERIFICATION ===============" -if [[ ${VRFYGENESIS} = "YES" && "${CDUMP}" = "gfs" ]]; then - ${GENESISSH} -fi - - -################################################################################ -echo -echo "=============== START TO RUN CYCLONE GENESIS VERIFICATION (FSU) ===============" -if [[ ${VRFYFSU} = "YES" && "${CDUMP}" = "gfs" ]]; then - ${GENESISFSU} -fi - - ############################################################### # Force Exit out cleanly cd "${DATAROOT}" diff --git a/parm/config/gefs/config.base.emc.dyn b/parm/config/gefs/config.base.emc.dyn index ab779e481b..5b08f2522c 100644 --- a/parm/config/gefs/config.base.emc.dyn +++ b/parm/config/gefs/config.base.emc.dyn @@ -138,7 +138,7 @@ export DO_WAVE="NO" export DO_OCN="NO" export DO_ICE="NO" export DO_AERO="NO" -export CCPP_SUITE="FV3_GFS_v17_p8" +export CCPP_SUITE="FV3_GFS_v17_p8_ugwpv1" export WAVE_CDUMP="" # When to include wave suite: gdas, gfs, or both export DOBNDPNT_WAVE="NO" export cplwav2atm=".false." @@ -204,7 +204,7 @@ case "${APP}" in export DO_COUPLED="YES" export DO_OCN="YES" export DO_ICE="YES" - export CCPP_SUITE="FV3_GFS_v17_coupled_p8" # TODO: Does this include FV3_GFS_v17_p8? Can this be used instead of FV3_GFS_v17_p8 on L141 + export CCPP_SUITE="FV3_GFS_v17_coupled_p8_ugwpv1" # TODO: Does this include FV3_GFS_v17_p8? Can this be used instead of FV3_GFS_v17_p8 on L141 export confignamevarfornems="cpld" if [[ "${APP}" =~ A$ ]]; then @@ -282,11 +282,16 @@ export NMEM_ENS=@NMEM_ENS@ export ENSMEM="000" export MEMDIR="mem${ENSMEM}" +export DOIAU="NO" # While we are not doing IAU, we may want to warm start w/ IAU in the future # Check if cycle is cold starting if [[ "${EXP_WARM_START}" = ".false." ]]; then - export IAU_FHROT=0 + export IAU_FHROT=0 else + if [[ "${DOIAU}" = "YES" ]]; then export IAU_FHROT=3 + else + export IAU_FHROT=0 + fi fi # turned on nsst in anal and/or fcst steps, and turn off rtgsst diff --git a/parm/config/gefs/config.fcst b/parm/config/gefs/config.fcst index a125c96331..4d43c38b82 100644 --- a/parm/config/gefs/config.fcst +++ b/parm/config/gefs/config.fcst @@ -119,24 +119,27 @@ if (( gwd_opt == 2 )); then #export do_ugwp_v1_orog_only=".false." #--used for UFS p8 - export knob_ugwp_version=0 + export knob_ugwp_version=1 export do_ugwp=".false." export do_tofd=".false." - export do_ugwp_v0=".true." - export do_ugwp_v1=".false." + export do_ugwp_v0=".false." + export do_ugwp_v1=".true." export do_ugwp_v0_orog_only=".false." export do_ugwp_v0_nst_only=".false." - export do_gsl_drag_ls_bl=".false." + export do_gsl_drag_ls_bl=".true." export do_gsl_drag_ss=".true." - export do_gsl_drag_tofd=".false." + export do_gsl_drag_tofd=".true." export do_ugwp_v1_orog_only=".false." launch_level=$(echo "${LEVS}/2.35" |bc) export launch_level + if [[ ${do_gsl_drag_ls_bl} == ".true." ]]; then + export cdmbgwd=${cdmbgwd_gsl} + fi fi # Sponge layer settings -export tau=10.0 -export rf_cutoff=7.5e2 +export tau=0. +export rf_cutoff=10. export d2_bg_k1=0.20 export d2_bg_k2=0.04 export dz_min=6 diff --git a/parm/config/gefs/config.ufs b/parm/config/gefs/config.ufs index 563ee8f021..8418459cc3 100644 --- a/parm/config/gefs/config.ufs +++ b/parm/config/gefs/config.ufs @@ -112,6 +112,8 @@ case "${fv3_res}" in export nthreads_fv3=1 export nthreads_fv3_gfs=1 export cdmbgwd="0.071,2.1,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="40.0,1.77,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=6.0e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=1 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=1 export WRITE_GROUP_GFS=1 @@ -126,6 +128,8 @@ case "${fv3_res}" in export nthreads_fv3=1 export nthreads_fv3_gfs=1 export cdmbgwd="0.14,1.8,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="20.0,2.5,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=3.0e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=1 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=1 export WRITE_GROUP_GFS=1 @@ -140,6 +144,8 @@ case "${fv3_res}" in export nthreads_fv3=1 export nthreads_fv3_gfs=2 export cdmbgwd="0.23,1.5,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="10.0,3.5,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=1.5e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=1 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=10 export WRITE_GROUP_GFS=2 @@ -154,6 +160,8 @@ case "${fv3_res}" in export nthreads_fv3=1 export nthreads_fv3_gfs=2 export cdmbgwd="1.1,0.72,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="5.0,5.0,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=0.8e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=2 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=8 export WRITE_GROUP_GFS=2 @@ -168,6 +176,8 @@ case "${fv3_res}" in export nthreads_fv3=4 export nthreads_fv3_gfs=4 export cdmbgwd="4.0,0.15,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="2.5,7.5,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=0.5e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=2 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=10 export WRITE_GROUP_GFS=4 @@ -182,6 +192,8 @@ case "${fv3_res}" in export nthreads_fv3=4 export nthreads_fv3_gfs=4 export cdmbgwd="4.0,0.10,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="1.67,8.8,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=0.35e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=4 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=10 # TODO: refine these numbers when a case is available export WRITE_GROUP_GFS=4 @@ -196,6 +208,8 @@ case "${fv3_res}" in export nthreads_fv3=4 export nthreads_fv3_gfs=4 export cdmbgwd="4.0,0.05,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="0.625,14.1,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=0.13e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=4 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=10 # TODO: refine these numbers when a case is available export WRITE_GROUP_GFS=4 diff --git a/parm/config/gfs/config.base.emc.dyn b/parm/config/gfs/config.base.emc.dyn index 884fe1723c..6398daac35 100644 --- a/parm/config/gfs/config.base.emc.dyn +++ b/parm/config/gfs/config.base.emc.dyn @@ -57,6 +57,9 @@ export DO_BUFRSND="NO" # BUFR sounding products export DO_GEMPAK="NO" # GEMPAK products export DO_AWIPS="NO" # AWIPS products export DO_VRFY="YES" # VRFY step +export DO_TRACKER="YES" # Hurricane track verification +export DO_GENESIS="YES" # Cyclone genesis verification +export DO_GENESIS_FSU="NO" # Cyclone genesis verification (FSU) export DO_VERFOZN="YES" # Ozone data assimilation monitoring export DO_VERFRAD="YES" # Radiance data assimilation monitoring export DO_VMINMON="YES" # GSI minimization monitoring @@ -148,7 +151,7 @@ export DO_WAVE="NO" export DO_OCN="NO" export DO_ICE="NO" export DO_AERO="NO" -export CCPP_SUITE="FV3_GFS_v17_p8" +export CCPP_SUITE="FV3_GFS_v17_p8_ugwpv1" export WAVE_CDUMP="" # When to include wave suite: gdas, gfs, or both export DOBNDPNT_WAVE="NO" export cplwav2atm=".false." @@ -214,7 +217,7 @@ case "${APP}" in export DO_COUPLED="YES" export DO_OCN="YES" export DO_ICE="YES" - export CCPP_SUITE="FV3_GFS_v17_coupled_p8" # TODO: Does this include FV3_GFS_v17_p8? Can this be used instead of FV3_GFS_v17_p8 on L149 + export CCPP_SUITE="FV3_GFS_v17_coupled_p8_ugwpv1" # TODO: Does this include FV3_GFS_v17_p8? Can this be used instead of FV3_GFS_v17_p8 on L149 export confignamevarfornems="cpld" if [[ "${APP}" =~ A$ ]]; then diff --git a/parm/config/gfs/config.fcst b/parm/config/gfs/config.fcst index 5202a90731..7a3c1b3b30 100644 --- a/parm/config/gfs/config.fcst +++ b/parm/config/gfs/config.fcst @@ -119,24 +119,27 @@ if (( gwd_opt == 2 )); then #export do_ugwp_v1_orog_only=".false." #--used for UFS p8 - export knob_ugwp_version=0 + export knob_ugwp_version=1 export do_ugwp=".false." export do_tofd=".false." - export do_ugwp_v0=".true." - export do_ugwp_v1=".false." + export do_ugwp_v0=".false." + export do_ugwp_v1=".true." export do_ugwp_v0_orog_only=".false." export do_ugwp_v0_nst_only=".false." - export do_gsl_drag_ls_bl=".false." + export do_gsl_drag_ls_bl=".true." export do_gsl_drag_ss=".true." - export do_gsl_drag_tofd=".false." + export do_gsl_drag_tofd=".true." export do_ugwp_v1_orog_only=".false." launch_level=$(echo "${LEVS}/2.35" |bc) export launch_level + if [[ ${do_gsl_drag_ls_bl} == ".true." ]]; then + export cdmbgwd=${cdmbgwd_gsl} + fi fi # Sponge layer settings -export tau=10.0 -export rf_cutoff=7.5e2 +export tau=0. +export rf_cutoff=10. export d2_bg_k1=0.20 export d2_bg_k2=0.04 export dz_min=6 diff --git a/parm/config/gfs/config.genesis b/parm/config/gfs/config.genesis new file mode 100644 index 0000000000..62a1bf88c0 --- /dev/null +++ b/parm/config/gfs/config.genesis @@ -0,0 +1,12 @@ +#! /usr/bin/env bash + +########## config.genesis ########## +echo "BEGIN: config.genesis" + +# Get task specific resources +. "${EXPDIR}/config.resources" genesis + +# Get tropcy settings +. "${EXPDIR}/config.tropcy" + +echo "END: config.genesis" diff --git a/parm/config/gfs/config.genesis_fsu b/parm/config/gfs/config.genesis_fsu new file mode 100644 index 0000000000..13948592c4 --- /dev/null +++ b/parm/config/gfs/config.genesis_fsu @@ -0,0 +1,12 @@ +#! /usr/bin/env bash + +########## config.genesis_fsu ########## +echo "BEGIN: config.genesis_fsu" + +# Get task specific resources +. "${EXPDIR}/config.resources" genesis_fsu + +# Get tropcy settings +. "${EXPDIR}/config.tropcy" + +echo "END: config.genesis_fsu" diff --git a/parm/config/gfs/config.resources b/parm/config/gfs/config.resources index 1f89994b69..1139fdc9a7 100644 --- a/parm/config/gfs/config.resources +++ b/parm/config/gfs/config.resources @@ -15,6 +15,7 @@ if [[ $# -ne 1 ]]; then echo "landanl" echo "aeroanlinit aeroanlrun aeroanlfinal" echo "anal sfcanl analcalc analdiag fcst post echgres" + echo "tracker genesis genesis_fsu" echo "verfozn verfrad vminmon vrfy fit2obs metp arch cleanup" echo "eobs ediag eomg eupd ecen esfc efcs epos earc" echo "init_chem mom6ic ocnpost" @@ -749,19 +750,39 @@ elif [[ ${step} = "vminmon" ]]; then export npe_node_vminmon_gfs=1 export memory_vminmon="1G" +elif [[ ${step} = "tracker" ]]; then + + export wtime_tracker="00:10:00" + export npe_tracker=1 + export nth_tracker=1 + export npe_node_tracker=1 + export memory_tracker="4G" + +elif [[ ${step} = "genesis" ]]; then + + export wtime_genesis="00:25:00" + export npe_genesis=1 + export nth_genesis=1 + export npe_node_genesis=1 + export memory_genesis="4G" + +elif [[ ${step} = "genesis_fsu" ]]; then + + export wtime_genesis_fsu="00:10:00" + export npe_genesis_fsu=1 + export nth_genesis_fsu=1 + export npe_node_genesis_fsu=1 + export memory_genesis_fsu="4G" + elif [[ ${step} = "vrfy" ]]; then - export wtime_vrfy="03:00:00" - export wtime_vrfy_gfs="06:00:00" - export npe_vrfy=3 + export wtime_vrfy="00:10:00" + export wtime_vrfy_gfs="00:10:00" + export npe_vrfy=1 export nth_vrfy=1 export npe_node_vrfy=1 export npe_vrfy_gfs=1 export npe_node_vrfy_gfs=1 - if [[ ${machine} == "HERA" ]]; then - export memory_vrfy="16384M" - fi - export is_exclusive=True elif [[ "${step}" = "fit2obs" ]]; then diff --git a/parm/config/gfs/config.tracker b/parm/config/gfs/config.tracker new file mode 100644 index 0000000000..71fcf9196d --- /dev/null +++ b/parm/config/gfs/config.tracker @@ -0,0 +1,12 @@ +#! /usr/bin/env bash + +########## config.tracker ########## +echo "BEGIN: config.tracker" + +# Get task specific resources +. "${EXPDIR}/config.resources" tracker + +# Get tropcy settings +. "${EXPDIR}/config.tropcy" + +echo "END: config.tracker" diff --git a/parm/config/gfs/config.tropcy b/parm/config/gfs/config.tropcy new file mode 100644 index 0000000000..718abe3be5 --- /dev/null +++ b/parm/config/gfs/config.tropcy @@ -0,0 +1,15 @@ +#! /usr/bin/env bash + +########## config.tropcy ########## +echo "BEGIN: config.tropcy" + +# Tracker/genesis package location +export HOMEens_tracker=${BASE_GIT}/TC_tracker/${ens_tracker_ver} + +export SENDCOM="YES" # Needed by tracker scripts still + +export FHOUT_CYCLONE=6 +FHMAX_CYCLONE=$(( FHMAX_GFS<240 ? FHMAX_GFS : 240 )) +export FHMAX_CYCLONE + +echo "END: config.tropcy" diff --git a/parm/config/gfs/config.ufs b/parm/config/gfs/config.ufs index 2441716a05..e499d90fdd 100644 --- a/parm/config/gfs/config.ufs +++ b/parm/config/gfs/config.ufs @@ -112,6 +112,8 @@ case "${fv3_res}" in export nthreads_fv3=1 export nthreads_fv3_gfs=1 export cdmbgwd="0.071,2.1,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="40.0,1.77,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=6.0e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=1 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=1 export WRITE_GROUP_GFS=1 @@ -126,6 +128,8 @@ case "${fv3_res}" in export nthreads_fv3=1 export nthreads_fv3_gfs=1 export cdmbgwd="0.14,1.8,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="20.0,2.5,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=3.0e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=1 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=1 export WRITE_GROUP_GFS=1 @@ -140,6 +144,8 @@ case "${fv3_res}" in export nthreads_fv3=1 export nthreads_fv3_gfs=2 export cdmbgwd="0.23,1.5,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="10.0,3.5,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=1.5e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=1 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=10 export WRITE_GROUP_GFS=2 @@ -154,6 +160,8 @@ case "${fv3_res}" in export nthreads_fv3=2 export nthreads_fv3_gfs=2 export cdmbgwd="1.1,0.72,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="5.0,5.0,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=0.8e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=4 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=10 export WRITE_GROUP_GFS=4 @@ -168,6 +176,8 @@ case "${fv3_res}" in export nthreads_fv3=4 export nthreads_fv3_gfs=4 export cdmbgwd="4.0,0.15,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="2.5,7.5,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=0.5e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=2 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=10 export WRITE_GROUP_GFS=4 @@ -182,6 +192,8 @@ case "${fv3_res}" in export nthreads_fv3=4 export nthreads_fv3_gfs=4 export cdmbgwd="4.0,0.10,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="1.67,8.8,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=0.35e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=4 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=10 # TODO: refine these numbers when a case is available export WRITE_GROUP_GFS=4 @@ -196,6 +208,8 @@ case "${fv3_res}" in export nthreads_fv3=4 export nthreads_fv3_gfs=4 export cdmbgwd="4.0,0.05,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling + export cdmbgwd_gsl="0.625,14.1,1.0,1.0" # settings for GSL drag suite + export knob_ugwp_tauamp=0.13e-3 # setting for UGWPv1 non-stationary GWD export WRITE_GROUP=4 export WRTTASK_PER_GROUP_PER_THREAD_PER_TILE=10 # TODO: refine these numbers when a case is available export WRITE_GROUP_GFS=4 diff --git a/parm/config/gfs/config.vrfy b/parm/config/gfs/config.vrfy index 8b8c393ee1..945d0ecfba 100644 --- a/parm/config/gfs/config.vrfy +++ b/parm/config/gfs/config.vrfy @@ -10,45 +10,8 @@ echo "BEGIN: config.vrfy" export CDFNL="gdas" # Scores verification against GDAS/GFS analysis export MKPGB4PRCP="YES" # Make 0.25-deg pgb files in ARCDIR for precip verification -export VRFYTRAK="YES" # Hurricane track verification -export VRFYGENESIS="YES" # Cyclone genesis verification -export VRFYFSU="NO" # Cyclone genesis verification (FSU) export RUNMOS="NO" # whether to run entire MOS package -#------------------------------------------------- -# Cyclone genesis and cyclone track verification -#------------------------------------------------- - -export SENDCOM="YES" # Needed by tracker/genesis scripts still - -export HOMEens_tracker=$BASE_GIT/TC_tracker/${tracker_ver} - -if [[ "${VRFYTRAK}" = "YES" ]]; then - - export TRACKERSH="${HOMEgfs}/jobs/JGFS_ATMOS_CYCLONE_TRACKER" - COMINsyn=${COMINsyn:-$(compath.py "${envir}"/com/gfs/"${gfs_ver}")/syndat} - export COMINsyn - if [[ "${RUN}" = "gdas" ]]; then - export FHOUT_CYCLONE=3 - export FHMAX_CYCLONE=${FHMAX} - else - export FHOUT_CYCLONE=6 - FHMAX_CYCLONE=$(( FHMAX_GFS<240 ? FHMAX_GFS : 240 )) - export FHMAX_CYCLONE - fi -fi - - -if [[ "${VRFYGENESIS}" == "YES" && "${RUN}" == "gfs" ]]; then - - export GENESISSH="${HOMEgfs}/jobs/JGFS_ATMOS_CYCLONE_GENESIS" -fi - -if [[ "${VRFYFSU}" == "YES" && "${RUN}" == "gfs" ]]; then - - export GENESISFSU="${HOMEgfs}/jobs/JGFS_ATMOS_FSU_GENESIS" -fi - if [[ "${RUNMOS}" == "YES" && "${RUN}" == "gfs" ]]; then if [[ "${machine}" = "HERA" ]] ; then diff --git a/scripts/exgdas_enkf_earc.sh b/scripts/exgdas_enkf_earc.sh index f172a4ef41..199b5609a2 100755 --- a/scripts/exgdas_enkf_earc.sh +++ b/scripts/exgdas_enkf_earc.sh @@ -8,8 +8,6 @@ source "${HOMEgfs}/ush/preamble.sh" export n=$((10#${ENSGRP})) export CDUMP_ENKF="${EUPD_CYC:-"gdas"}" -export ARCH_LIST="${COM_TOP}/earc${ENSGRP}" - # ICS are restarts and always lag INC by $assim_freq hours. EARCINC_CYC=${ARCH_CYC} EARCICS_CYC=$((ARCH_CYC-assim_freq)) @@ -17,10 +15,6 @@ if [ "${EARCICS_CYC}" -lt 0 ]; then EARCICS_CYC=$((EARCICS_CYC+24)) fi -[[ -d ${ARCH_LIST} ]] && rm -rf "${ARCH_LIST}" -mkdir -p "${ARCH_LIST}" -cd "${ARCH_LIST}" || exit 2 - "${HOMEgfs}/ush/hpssarch_gen.sh" "${RUN}" status=$? if [ "${status}" -ne 0 ]; then @@ -66,7 +60,7 @@ if (( 10#${ENSGRP} > 0 )) && [[ ${HPSSARCH} = "YES" || ${LOCALARCH} = "YES" ]]; if [ "${PDY}${cyc}" -gt "${SDATE}" ]; then # Don't run for first half cycle - ${TARCMD} -P -cvf "${ATARDIR}/${PDY}${cyc}/${RUN}_grp${ENSGRP}.tar" $(cat "${ARCH_LIST}/${RUN}_grp${n}.txt") + ${TARCMD} -P -cvf "${ATARDIR}/${PDY}${cyc}/${RUN}_grp${ENSGRP}.tar" $(cat "${DATA}/${RUN}_grp${n}.txt") status=$? if [ "${status}" -ne 0 ] && [ "${PDY}${cyc}" -ge "${firstday}" ]; then echo "FATAL ERROR: ${TARCMD} ${PDY}${cyc} ${RUN}_grp${ENSGRP}.tar failed" @@ -74,7 +68,7 @@ if (( 10#${ENSGRP} > 0 )) && [[ ${HPSSARCH} = "YES" || ${LOCALARCH} = "YES" ]]; fi if [ "${SAVEWARMICA}" = "YES" ] && [ "${cyc}" -eq "${EARCINC_CYC}" ]; then - ${TARCMD} -P -cvf "${ATARDIR}/${PDY}${cyc}/${RUN}_restarta_grp${ENSGRP}.tar" $(cat "${ARCH_LIST}/${RUN}_restarta_grp${n}.txt") + ${TARCMD} -P -cvf "${ATARDIR}/${PDY}${cyc}/${RUN}_restarta_grp${ENSGRP}.tar" $(cat "${DATA}/${RUN}_restarta_grp${n}.txt") status=$? if [ "${status}" -ne 0 ]; then echo "FATAL ERROR: ${TARCMD} ${PDY}${cyc} ${RUN}_restarta_grp${ENSGRP}.tar failed" @@ -83,7 +77,7 @@ if (( 10#${ENSGRP} > 0 )) && [[ ${HPSSARCH} = "YES" || ${LOCALARCH} = "YES" ]]; fi if [ "${SAVEWARMICB}" = "YES" ] && [ "${cyc}" -eq "${EARCICS_CYC}" ]; then - ${TARCMD} -P -cvf "${ATARDIR}/${PDY}${cyc}/${RUN}_restartb_grp${ENSGRP}.tar" $(cat "${ARCH_LIST}/${RUN}_restartb_grp${n}.txt") + ${TARCMD} -P -cvf "${ATARDIR}/${PDY}${cyc}/${RUN}_restartb_grp${ENSGRP}.tar" $(cat "${DATA}/${RUN}_restartb_grp${n}.txt") status=$? if [ "${status}" -ne 0 ]; then echo "FATAL ERROR: ${TARCMD} ${PDY}${cyc} ${RUN}_restartb_grp${ENSGRP}.tar failed" @@ -122,12 +116,16 @@ if [ "${ENSGRP}" -eq 0 ]; then break fi fi - done < "${ARCH_LIST}/${RUN}.txt" + done < "${DATA}/${RUN}.txt" # Create the tarball tar_fl=${ATARDIR}/${PDY}${cyc}/${RUN}.tar - ${TARCMD} -P -cvf "${tar_fl}" $(cat "${ARCH_LIST}/${RUN}.txt") + ${TARCMD} -P -cvf "${tar_fl}" $(cat "${DATA}/${RUN}.txt") status=$? + if [[ "${status}" -ne 0 ]]; then + echo "FATAL ERROR: Tarring of ${tar_fl} failed" + exit "${status}" + fi # If rstprod was found, change the group of the tarball if [[ "${has_rstprod}" == "YES" ]]; then diff --git a/scripts/exgdas_enkf_fcst.sh b/scripts/exgdas_enkf_fcst.sh index 7eb2a3a711..fd6136ddd2 100755 --- a/scripts/exgdas_enkf_fcst.sh +++ b/scripts/exgdas_enkf_fcst.sh @@ -131,7 +131,7 @@ for imem in $(seq "${ENSBEG}" "${ENSEND}"); do # Construct COM variables from templates (see config.com) # Can't make these read-only because we are looping over members MEMDIR="${memchar}" YMD=${PDY} HH=${cyc} generate_com -x COM_ATMOS_RESTART COM_ATMOS_INPUT COM_ATMOS_ANALYSIS \ - COM_ATMOS_HISTORY COM_ATMOS_MASTER + COM_ATMOS_HISTORY COM_ATMOS_MASTER COM_CONF MEMDIR="${memchar}" YMD="${gPDY}" HH="${gcyc}" generate_com -x COM_ATMOS_RESTART_PREV:COM_ATMOS_RESTART_TMPL diff --git a/scripts/exglobal_stage_ic.sh b/scripts/exglobal_stage_ic.sh index 53042c7e45..58b37f3114 100755 --- a/scripts/exglobal_stage_ic.sh +++ b/scripts/exglobal_stage_ic.sh @@ -9,9 +9,9 @@ gPDY="${GDATE:0:8}" gcyc="${GDATE:8:2}" MEMDIR_ARRAY=() -if [[ "${RUN}" == "gefs" ]]; then +if [[ "${RUN:-}" = "gefs" ]]; then # Populate the member_dirs array based on the value of NMEM_ENS - for ((ii = 0; ii <= "${NMEM_ENS}"; ii++)); do + for ((ii = 0; ii <= "${NMEM_ENS:-0}"; ii++)); do MEMDIR_ARRAY+=("mem$(printf "%03d" "${ii}")") done else @@ -27,35 +27,58 @@ error_message() { ############################################################### for MEMDIR in "${MEMDIR_ARRAY[@]}"; do - # Stage the FV3 initial conditions to ROTDIR (cold start) - YMD=${PDY} HH=${cyc} generate_com COM_ATMOS_INPUT - [[ ! -d "${COM_ATMOS_INPUT}" ]] && mkdir -p "${COM_ATMOS_INPUT}" - src="${BASE_CPLIC}/${CPL_ATMIC}/${PDY}${cyc}/${MEMDIR}/atmos/gfs_ctrl.nc" - tgt="${COM_ATMOS_INPUT}/gfs_ctrl.nc" - ${NCP} "${src}" "${tgt}" - rc=$? - ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" - err=$((err + rc)) - for ftype in gfs_data sfc_data; do - for ((tt = 1; tt <= 6; tt++)); do - src="${BASE_CPLIC}/${CPL_ATMIC}/${PDY}${cyc}/${MEMDIR}/atmos/${ftype}.tile${tt}.nc" - tgt="${COM_ATMOS_INPUT}/${ftype}.tile${tt}.nc" - ${NCP} "${src}" "${tgt}" - rc=$? - tgt="${COM_ATMOS_INPUT}/${ftype}.tile${tt}.nc" + + # Stage atmosphere initial conditions to ROTDIR + if [[ ${EXP_WARM_START:-".false."} = ".true." ]]; then + # Stage the FV3 restarts to ROTDIR (warm start) + RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_ATMOS_RESTART_PREV:COM_ATMOS_RESTART_TMPL + [[ ! -d "${COM_ATMOS_RESTART_PREV}" ]] && mkdir -p "${COM_ATMOS_RESTART_PREV}" + for ftype in coupler.res fv_core.res.nc; do + src="${BASE_CPLIC}/${CPL_ATMIC:-}/${PDY}${cyc}/${MEMDIR}/atmos/${PDY}.${cyc}0000.${ftype}" + tgt="${COM_ATMOS_RESTART_PREV}/${PDY}.${cyc}0000.${ftype}" ${NCP} "${src}" "${tgt}" rc=$? ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" err=$((err + rc)) done - done + for ftype in ca_data fv_core.res fv_srf_wnd.res fv_tracer.res phy_data sfc_data; do + for ((tt = 1; tt <= 6; tt++)); do + src="${BASE_CPLIC}/${CPL_ATMIC:-}/${PDY}${cyc}/${MEMDIR}/atmos/${PDY}.${cyc}0000.${ftype}.tile${tt}.nc" + tgt="${COM_ATMOS_RESTART_PREV}/${PDY}.${cyc}0000.${ftype}.tile${tt}.nc" + ${NCP} "${src}" "${tgt}" + rc=$? + ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" + err=$((err + rc)) + done + done + else + # Stage the FV3 cold-start initial conditions to ROTDIR + YMD=${PDY} HH=${cyc} generate_com COM_ATMOS_INPUT + [[ ! -d "${COM_ATMOS_INPUT}" ]] && mkdir -p "${COM_ATMOS_INPUT}" + src="${BASE_CPLIC}/${CPL_ATMIC:-}/${PDY}${cyc}/${MEMDIR}/atmos/gfs_ctrl.nc" + tgt="${COM_ATMOS_INPUT}/gfs_ctrl.nc" + ${NCP} "${src}" "${tgt}" + rc=$? + ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" + err=$((err + rc)) + for ftype in gfs_data sfc_data; do + for ((tt = 1; tt <= 6; tt++)); do + src="${BASE_CPLIC}/${CPL_ATMIC:-}/${PDY}${cyc}/${MEMDIR}/atmos/${ftype}.tile${tt}.nc" + tgt="${COM_ATMOS_INPUT}/${ftype}.tile${tt}.nc" + ${NCP} "${src}" "${tgt}" + rc=$? + ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" + err=$((err + rc)) + done + done + fi # Stage ocean initial conditions to ROTDIR (warm start) if [[ "${DO_OCN:-}" = "YES" ]]; then - RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_OCEAN_RESTART - [[ ! -d "${COM_OCEAN_RESTART}" ]] && mkdir -p "${COM_OCEAN_RESTART}" - src="${BASE_CPLIC}/${CPL_OCNIC}/${PDY}${cyc}/${MEMDIR}/ocean/${PDY}.${cyc}0000.MOM.res.nc" - tgt="${COM_OCEAN_RESTART}/${PDY}.${cyc}0000.MOM.res.nc" + RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_OCEAN_RESTART_PREV:COM_OCEAN_RESTART_TMPL + [[ ! -d "${COM_OCEAN_RESTART_PREV}" ]] && mkdir -p "${COM_OCEAN_RESTART_PREV}" + src="${BASE_CPLIC}/${CPL_OCNIC:-}/${PDY}${cyc}/${MEMDIR}/ocean/${PDY}.${cyc}0000.MOM.res.nc" + tgt="${COM_OCEAN_RESTART_PREV}/${PDY}.${cyc}0000.MOM.res.nc" ${NCP} "${src}" "${tgt}" rc=$? ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" @@ -66,8 +89,8 @@ for MEMDIR in "${MEMDIR_ARRAY[@]}"; do ;; "025" ) for nn in $(seq 1 3); do - src="${BASE_CPLIC}/${CPL_OCNIC}/${PDY}${cyc}/${MEMDIR}/ocean/${PDY}.${cyc}0000.MOM.res_${nn}.nc" - tgt="${COM_OCEAN_RESTART}/${PDY}.${cyc}0000.MOM.res_${nn}.nc" + src="${BASE_CPLIC}/${CPL_OCNIC:-}/${PDY}${cyc}/${MEMDIR}/ocean/${PDY}.${cyc}0000.MOM.res_${nn}.nc" + tgt="${COM_OCEAN_RESTART_PREV}/${PDY}.${cyc}0000.MOM.res_${nn}.nc" ${NCP} "${src}" "${tgt}" rc=$? ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" @@ -80,13 +103,33 @@ for MEMDIR in "${MEMDIR_ARRAY[@]}"; do err=$((err + rc)) ;; esac + + # TODO: Do mediator restarts exists in a ATMW configuration? + # TODO: No mediator is presumably involved in an ATMA configuration + if [[ ${EXP_WARM_START:-".false."} = ".true." ]]; then + # Stage the mediator restarts to ROTDIR (warm start/restart the coupled model) + RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_MED_RESTART_PREV:COM_MED_RESTART_TMPL + [[ ! -d "${COM_MED_RESTART_PREV}" ]] && mkdir -p "${COM_MED_RESTART_PREV}" + src="${BASE_CPLIC}/${CPL_MEDIC:-}/${PDY}${cyc}/${MEMDIR}/med/${PDY}.${cyc}0000.ufs.cpld.cpl.r.nc" + tgt="${COM_MED_RESTART_PREV}/${PDY}.${cyc}0000.ufs.cpld.cpl.r.nc" + if [[ -f "${src}" ]]; then + ${NCP} "${src}" "${tgt}" + rc=$? + ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" + err=$((err + rc)) + else + echo "WARNING: No mediator restarts available with warm_start=${EXP_WARM_START}" + fi + fi + fi + # Stage ice initial conditions to ROTDIR (warm start) if [[ "${DO_ICE:-}" = "YES" ]]; then - RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_ICE_RESTART - [[ ! -d "${COM_ICE_RESTART}" ]] && mkdir -p "${COM_ICE_RESTART}" - src="${BASE_CPLIC}/${CPL_ICEIC}/${PDY}${cyc}/${MEMDIR}/ice/${PDY}.${cyc}0000.cice_model.res.nc" - tgt="${COM_ICE_RESTART}/${PDY}.${cyc}0000.cice_model.res.nc" + RUN=${rCDUMP} YMD=${gPDY} HH=${gcyc} generate_com COM_ICE_RESTART_PREV:COM_ICE_RESTART_TMPL + [[ ! -d "${COM_ICE_RESTART_PREV}" ]] && mkdir -p "${COM_ICE_RESTART_PREV}" + src="${BASE_CPLIC}/${CPL_ICEIC:-}/${PDY}${cyc}/${MEMDIR}/ice/${PDY}.${cyc}0000.cice_model.res.nc" + tgt="${COM_ICE_RESTART_PREV}/${PDY}.${cyc}0000.cice_model.res.nc" ${NCP} "${src}" "${tgt}" rc=$? ((rc != 0)) && error_message "${src}" "${tgt}" "${rc}" @@ -98,7 +141,7 @@ for MEMDIR in "${MEMDIR_ARRAY[@]}"; do YMD=${PDY} HH=${cyc} generate_com COM_WAVE_RESTART [[ ! -d "${COM_WAVE_RESTART}" ]] && mkdir -p "${COM_WAVE_RESTART}" for grdID in ${waveGRD}; do # TODO: check if this is a bash array; if so adjust - src="${BASE_CPLIC}/${CPL_WAVIC}/${PDY}${cyc}/${MEMDIR}/wave/${PDY}.${cyc}0000.restart.${grdID}" + src="${BASE_CPLIC}/${CPL_WAVIC:-}/${PDY}${cyc}/${MEMDIR}/wave/${PDY}.${cyc}0000.restart.${grdID}" tgt="${COM_WAVE_RESTART}/${PDY}.${cyc}0000.restart.${grdID}" ${NCP} "${src}" "${tgt}" rc=$? @@ -108,6 +151,7 @@ for MEMDIR in "${MEMDIR_ARRAY[@]}"; do fi done # for MEMDIR in "${MEMDIR_ARRAY[@]}"; do + ############################################################### # Check for errors and exit if any of the above failed if [[ "${err}" -ne 0 ]]; then diff --git a/sorc/build_ufs.sh b/sorc/build_ufs.sh index aaeeefea23..3e3f879f1a 100755 --- a/sorc/build_ufs.sh +++ b/sorc/build_ufs.sh @@ -5,7 +5,7 @@ cwd=$(pwd) # Default settings APP="S2SWA" -CCPP_SUITES="FV3_GFS_v17_p8,FV3_GFS_v17_coupled_p8" # TODO: does the g-w need to build with all these CCPP_SUITES? +CCPP_SUITES="FV3_GFS_v17_p8_ugwpv1,FV3_GFS_v17_coupled_p8_ugwpv1" # TODO: does the g-w need to build with all these CCPP_SUITES? while getopts ":da:j:v" option; do case "${option}" in diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index bafa61dd0e..9d93f52840 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -381,7 +381,7 @@ EOF # time step parameters in FV3 k_split=${k_split:-2} - n_split=${n_split:-6} + n_split=${n_split:-5} if [[ "${MONO:0:4}" = "mono" ]]; then # monotonic options d_con=${d_con_mono:-"0."} @@ -514,7 +514,10 @@ FV3_out() { done else # No need to copy FV3 restart files when RUN=gfs or gefs - ${NCP} "${DATA}/input.nml" "${COM_ATMOS_HISTORY}/input.nml" + ${NCP} "${DATA}/input.nml" "${COM_CONF}/ufs.input.nml" + ${NCP} "${DATA}/model_configure" "${COM_CONF}/ufs.model_configure" + ${NCP} "${DATA}/nems.configure" "${COM_CONF}/ufs.nems.configure" + ${NCP} "${DATA}/diag_table" "${COM_CONF}/ufs.diag_table" fi echo "SUB ${FUNCNAME[0]}: Output data for FV3 copied" } @@ -853,7 +856,7 @@ MOM6_out() { # Copy MOM_input from DATA to COM_OCEAN_INPUT after the forecast is run (and successfull) if [[ ! -d ${COM_OCEAN_INPUT} ]]; then mkdir -p "${COM_OCEAN_INPUT}"; fi - ${NCP} "${DATA}/INPUT/MOM_input" "${COM_OCEAN_INPUT}/" + ${NCP} "${DATA}/INPUT/MOM_input" "${COM_CONF}/ufs.MOM_input" # TODO: mediator should have its own CMEPS_out() function # Copy mediator restarts from DATA to COM @@ -883,9 +886,9 @@ CICE_postdet() { dumpfreq=${dumpfreq:-"y"} # "h","d","m" or "y" for restarts at intervals of "hours", "days", "months" or "years" if [[ "${RUN}" =~ "gdas" ]]; then - cice_hist_avg=".false." # DA needs instantaneous + cice_hist_avg=".false., .false., .false., .false., .false." # DA needs instantaneous else - cice_hist_avg=".true." # P8 wants averaged over histfreq_n + cice_hist_avg=".true., .true., .true., .true., .true." # P8 wants averaged over histfreq_n fi FRAZIL_FWSALT=${FRAZIL_FWSALT:-".true."} @@ -991,7 +994,7 @@ CICE_out() { # Copy ice_in namelist from DATA to COMOUTice after the forecast is run (and successfull) if [[ ! -d "${COM_ICE_INPUT}" ]]; then mkdir -p "${COM_ICE_INPUT}"; fi - ${NCP} "${DATA}/ice_in" "${COM_ICE_INPUT}/ice_in" + ${NCP} "${DATA}/ice_in" "${COM_CONF}/ufs.ice_in" } GOCART_rc() { diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index ce0b50f818..84d377019a 100755 --- a/ush/forecast_predet.sh +++ b/ush/forecast_predet.sh @@ -88,7 +88,7 @@ common_predet(){ tcyc=${scyc} fi - + mkdir -p "${COM_CONF}" cd "${DATA}" || ( echo "FATAL ERROR: Unable to 'cd ${DATA}', ABORT!"; exit 8 ) } diff --git a/ush/parsing_namelists_FV3.sh b/ush/parsing_namelists_FV3.sh index ec3af83415..da51966645 100755 --- a/ush/parsing_namelists_FV3.sh +++ b/ush/parsing_namelists_FV3.sh @@ -81,6 +81,10 @@ cat > input.nml < input.nml <> input.nml < None: self.do_verfozn = _base.get('DO_VERFOZN', True) self.do_verfrad = _base.get('DO_VERFRAD', True) self.do_vminmon = _base.get('DO_VMINMON', True) + self.do_tracker = _base.get('DO_TRACKER', True) + self.do_genesis = _base.get('DO_GENESIS', True) + self.do_genesis_fsu = _base.get('DO_GENESIS_FSU', False) self.do_metp = _base.get('DO_METP', False) self.do_hpssarch = _base.get('HPSSARCH', False) @@ -167,14 +171,14 @@ def get_task_names(self) -> Dict[str, List[str]]: pass @staticmethod - def get_gfs_interval(gfs_cyc: int) -> str: + def get_gfs_interval(gfs_cyc: int) -> timedelta: """ return interval in hours based on gfs_cyc """ - gfs_internal_map = {'0': None, '1': '24:00:00', '2': '12:00:00', '4': '06:00:00'} + gfs_internal_map = {'1': '24H', '2': '12H', '4': '6H'} try: - return gfs_internal_map[str(gfs_cyc)] + return to_timedelta(gfs_internal_map[str(gfs_cyc)]) except KeyError: raise KeyError(f'Invalid gfs_cyc = {gfs_cyc}') diff --git a/workflow/applications/gfs_cycled.py b/workflow/applications/gfs_cycled.py index 3b8472d3c8..3dc199c5ec 100644 --- a/workflow/applications/gfs_cycled.py +++ b/workflow/applications/gfs_cycled.py @@ -1,6 +1,6 @@ from typing import Dict, Any from applications.applications import AppConfig -from wxflow import Configuration +from wxflow import Configuration, to_timedelta from datetime import timedelta @@ -68,6 +68,15 @@ def _get_app_configs(self): if self.do_vminmon: configs += ['vminmon'] + if self.do_tracker: + configs += ['tracker'] + + if self.do_genesis: + configs += ['genesis'] + + if self.do_genesis_fsu: + configs += ['genesis_fsu'] + if self.do_metp: configs += ['metp'] @@ -195,6 +204,15 @@ def get_task_names(self): if self.do_vminmon: gfs_tasks += ['vminmon'] + if self.do_tracker: + gfs_tasks += ['tracker'] + + if self.do_genesis: + gfs_tasks += ['genesis'] + + if self.do_genesis_fsu: + gfs_tasks += ['genesis_fsu'] + if self.do_metp: gfs_tasks += ['metp'] @@ -247,47 +265,45 @@ def get_gfs_cyc_dates(base: Dict[str, Any]) -> Dict[str, Any]: base_out = base.copy() - gfs_cyc = base['gfs_cyc'] sdate = base['SDATE'] edate = base['EDATE'] - base_out['INTERVAL'] = '06:00:00' # Cycled interval is 6 hours - - interval_gfs = AppConfig.get_gfs_interval(gfs_cyc) + base_out['INTERVAL'] = to_timedelta(f"{base['assim_freq']}H") # Set GFS cycling dates - hrinc = 0 - hrdet = 0 - if gfs_cyc == 0: - return base_out - elif gfs_cyc == 1: - hrinc = 24 - sdate.hour - hrdet = edate.hour - elif gfs_cyc == 2: - if sdate.hour in [0, 12]: - hrinc = 12 - elif sdate.hour in [6, 18]: + gfs_cyc = base['gfs_cyc'] + if gfs_cyc != 0: + interval_gfs = AppConfig.get_gfs_interval(gfs_cyc) + hrinc = 0 + hrdet = 0 + if gfs_cyc == 1: + hrinc = 24 - sdate.hour + hrdet = edate.hour + elif gfs_cyc == 2: + if sdate.hour in [0, 12]: + hrinc = 12 + elif sdate.hour in [6, 18]: + hrinc = 6 + if edate.hour in [6, 18]: + hrdet = 6 + elif gfs_cyc == 4: hrinc = 6 - if edate.hour in [6, 18]: - hrdet = 6 - elif gfs_cyc == 4: - hrinc = 6 - sdate_gfs = sdate + timedelta(hours=hrinc) - edate_gfs = edate - timedelta(hours=hrdet) - if sdate_gfs > edate: - print('W A R N I N G!') - print('Starting date for GFS cycles is after Ending date of experiment') - print(f'SDATE = {sdate.strftime("%Y%m%d%H")}, EDATE = {edate.strftime("%Y%m%d%H")}') - print(f'SDATE_GFS = {sdate_gfs.strftime("%Y%m%d%H")}, EDATE_GFS = {edate_gfs.strftime("%Y%m%d%H")}') - gfs_cyc = 0 - - base_out['gfs_cyc'] = gfs_cyc - base_out['SDATE_GFS'] = sdate_gfs - base_out['EDATE_GFS'] = edate_gfs - base_out['INTERVAL_GFS'] = interval_gfs - - fhmax_gfs = {} - for hh in ['00', '06', '12', '18']: - fhmax_gfs[hh] = base.get(f'FHMAX_GFS_{hh}', base.get('FHMAX_GFS_00', 120)) - base_out['FHMAX_GFS'] = fhmax_gfs + sdate_gfs = sdate + timedelta(hours=hrinc) + edate_gfs = edate - timedelta(hours=hrdet) + if sdate_gfs > edate: + print('W A R N I N G!') + print('Starting date for GFS cycles is after Ending date of experiment') + print(f'SDATE = {sdate.strftime("%Y%m%d%H")}, EDATE = {edate.strftime("%Y%m%d%H")}') + print(f'SDATE_GFS = {sdate_gfs.strftime("%Y%m%d%H")}, EDATE_GFS = {edate_gfs.strftime("%Y%m%d%H")}') + gfs_cyc = 0 + + base_out['gfs_cyc'] = gfs_cyc + base_out['SDATE_GFS'] = sdate_gfs + base_out['EDATE_GFS'] = edate_gfs + base_out['INTERVAL_GFS'] = interval_gfs + + fhmax_gfs = {} + for hh in ['00', '06', '12', '18']: + fhmax_gfs[hh] = base.get(f'FHMAX_GFS_{hh}', base.get('FHMAX_GFS_00', 120)) + base_out['FHMAX_GFS'] = fhmax_gfs return base_out diff --git a/workflow/applications/gfs_forecast_only.py b/workflow/applications/gfs_forecast_only.py index 73e17ee7aa..a130baf6e9 100644 --- a/workflow/applications/gfs_forecast_only.py +++ b/workflow/applications/gfs_forecast_only.py @@ -26,6 +26,15 @@ def _get_app_configs(self): if self.do_ocean or self.do_ice: configs += ['ocnpost'] + if self.do_atm and self.do_tracker: + configs += ['tracker'] + + if self.do_atm and self.do_genesis: + configs += ['genesis'] + + if self.do_atm and self.do_genesis_fsu: + configs += ['genesis_fsu'] + if self.do_atm and self.do_metp: configs += ['metp'] @@ -85,6 +94,15 @@ def get_task_names(self): if self.do_atm: tasks += ['vrfy'] + if self.do_atm and self.do_tracker: + tasks += ['tracker'] + + if self.do_atm and self.do_genesis: + tasks += ['genesis'] + + if self.do_atm and self.do_genesis_fsu: + tasks += ['genesis_fsu'] + if self.do_atm and self.do_metp: tasks += ['metp'] diff --git a/workflow/rocoto/gefs_xml.py b/workflow/rocoto/gefs_xml.py index 7e8df32991..b25a73fa6c 100644 --- a/workflow/rocoto/gefs_xml.py +++ b/workflow/rocoto/gefs_xml.py @@ -2,7 +2,7 @@ from rocoto.workflow_xml import RocotoXML from applications.applications import AppConfig -from wxflow import to_timedelta +from wxflow import to_timedelta, timedelta_to_HMS from typing import Dict @@ -16,13 +16,17 @@ def __init__(self, app_config: AppConfig, rocoto_config: Dict) -> None: def get_cycledefs(self): sdate = self._base['SDATE'] edate = self._base['EDATE'] - interval = self._base.get('INTERVAL_GFS', '24:00:00') + interval = self._base.get('INTERVAL_GFS', to_timedelta('24H')) + sdate_str = sdate.strftime("%Y%m%d%H%M") + edate_str = edate.strftime("%Y%m%d%H%M") + interval_str = timedelta_to_HMS(interval) strings = [] - strings.append(f'\t{sdate.strftime("%Y%m%d%H%M")} {edate.strftime("%Y%m%d%H%M")} {interval}') + strings.append(f'\t{sdate_str} {edate_str} {interval_str}') - sdate = sdate + to_timedelta(interval) + sdate = sdate + interval if sdate <= edate: - strings.append(f'\t{sdate.strftime("%Y%m%d%H%M")} {edate.strftime("%Y%m%d%H%M")} {interval}') + sdate_str = sdate.strftime("%Y%m%d%H%M") + strings.append(f'\t{sdate_str} {edate_str} {interval_str}') strings.append('') strings.append('') diff --git a/workflow/rocoto/gfs_cycled_xml.py b/workflow/rocoto/gfs_cycled_xml.py index d817b3ac03..afd663c337 100644 --- a/workflow/rocoto/gfs_cycled_xml.py +++ b/workflow/rocoto/gfs_cycled_xml.py @@ -2,7 +2,7 @@ from rocoto.workflow_xml import RocotoXML from applications.applications import AppConfig -from wxflow import to_timedelta +from wxflow import to_timedelta, timedelta_to_HMS from typing import Dict @@ -14,21 +14,29 @@ def __init__(self, app_config: AppConfig, rocoto_config: Dict) -> None: def get_cycledefs(self): sdate = self._base['SDATE'] edate = self._base['EDATE'] - interval = self._base.get('INTERVAL', '06:00:00') + interval = to_timedelta(f"{self._base['assim_freq']}H") + sdate_str = sdate.strftime("%Y%m%d%H%M") + edate_str = edate.strftime("%Y%m%d%H%M") + interval_str = timedelta_to_HMS(interval) strings = [] - strings.append(f'\t{sdate.strftime("%Y%m%d%H%M")} {sdate.strftime("%Y%m%d%H%M")} {interval}') - sdate = sdate + to_timedelta(interval) - strings.append(f'\t{sdate.strftime("%Y%m%d%H%M")} {edate.strftime("%Y%m%d%H%M")} {interval}') + strings.append(f'\t{sdate_str} {sdate_str} {interval_str}') + sdate = sdate + interval + sdate_str = sdate.strftime("%Y%m%d%H%M") + strings.append(f'\t{sdate_str} {edate_str} {interval_str}') if self._app_config.gfs_cyc != 0: sdate_gfs = self._base['SDATE_GFS'] edate_gfs = self._base['EDATE_GFS'] interval_gfs = self._base['INTERVAL_GFS'] - strings.append(f'\t{sdate_gfs.strftime("%Y%m%d%H%M")} {edate_gfs.strftime("%Y%m%d%H%M")} {interval_gfs}') + sdate_gfs_str = sdate_gfs.strftime("%Y%m%d%H%M") + edate_gfs_str = edate_gfs.strftime("%Y%m%d%H%M") + interval_gfs_str = timedelta_to_HMS(interval_gfs) + strings.append(f'\t{sdate_gfs_str} {edate_gfs_str} {interval_gfs_str}') - sdate_gfs = sdate_gfs + to_timedelta(interval_gfs) + sdate_gfs = sdate_gfs + interval_gfs + sdate_gfs_str = sdate_gfs.strftime("%Y%m%d%H%M") if sdate_gfs <= edate_gfs: - strings.append(f'\t{sdate_gfs.strftime("%Y%m%d%H%M")} {edate_gfs.strftime("%Y%m%d%H%M")} {interval_gfs}') + strings.append(f'\t{sdate_gfs_str} {edate_gfs_str} {interval_gfs_str}') strings.append('') strings.append('') diff --git a/workflow/rocoto/gfs_forecast_only_xml.py b/workflow/rocoto/gfs_forecast_only_xml.py index 7ae4eb34c5..cf53e685e9 100644 --- a/workflow/rocoto/gfs_forecast_only_xml.py +++ b/workflow/rocoto/gfs_forecast_only_xml.py @@ -2,7 +2,7 @@ from rocoto.workflow_xml import RocotoXML from applications.applications import AppConfig -from wxflow import to_timedelta +from wxflow import to_timedelta, timedelta_to_HMS from typing import Dict @@ -14,13 +14,13 @@ def __init__(self, app_config: AppConfig, rocoto_config: Dict) -> None: def get_cycledefs(self): sdate = self._base['SDATE'] edate = self._base['EDATE'] - interval = self._base.get('INTERVAL_GFS', '24:00:00') + interval = self._base.get('INTERVAL_GFS', to_timedelta('24H')) strings = [] - strings.append(f'\t{sdate.strftime("%Y%m%d%H%M")} {edate.strftime("%Y%m%d%H%M")} {interval}') + strings.append(f'\t{sdate.strftime("%Y%m%d%H%M")} {edate.strftime("%Y%m%d%H%M")} {timedelta_to_HMS(interval)}') - sdate = sdate + to_timedelta(interval) + sdate = sdate + interval if sdate <= edate: - strings.append(f'\t{sdate.strftime("%Y%m%d%H%M")} {edate.strftime("%Y%m%d%H%M")} {interval}') + strings.append(f'\t{sdate.strftime("%Y%m%d%H%M")} {edate.strftime("%Y%m%d%H%M")} {timedelta_to_HMS(interval)}') strings.append('') strings.append('') diff --git a/workflow/rocoto/gfs_tasks.py b/workflow/rocoto/gfs_tasks.py index 24d31521c2..cde0c96771 100644 --- a/workflow/rocoto/gfs_tasks.py +++ b/workflow/rocoto/gfs_tasks.py @@ -1,5 +1,6 @@ from applications.applications import AppConfig from rocoto.tasks import Tasks, create_wf_task +from wxflow import timedelta_to_HMS import rocoto.rocoto as rocoto import numpy as np @@ -86,10 +87,10 @@ def prep(self): gfs_enkf = True if self.app_config.do_hybvar and 'gfs' in self.app_config.eupd_cdumps else False deps = [] - dep_dict = {'type': 'metatask', 'name': 'gdaspost', 'offset': '-06:00:00'} + dep_dict = {'type': 'metatask', 'name': 'gdaspost', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) data = f'{atm_hist_path}/gdas.t@Hz.atmf009.nc' - dep_dict = {'type': 'data', 'data': data, 'offset': '-06:00:00'} + dep_dict = {'type': 'data', 'data': data, 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) data = f'{dump_path}/{self.cdump}.t@Hz.updated.status.tm00.bufr_d' dep_dict = {'type': 'data', 'data': data} @@ -116,7 +117,7 @@ def waveinit(self): dep_dict = {'type': 'task', 'name': f'{self.cdump}prep'} deps.append(rocoto.add_dependency(dep_dict)) if self.cdump in ['gdas']: - dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': '-06:00:00'} + dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='or', dep=deps) cycledef = 'gdas_half,gdas' if self.cdump in ['gdas'] else self.cdump @@ -155,7 +156,7 @@ def aerosol_init(self): interval = self._base['INTERVAL_GFS'] elif self.cdump in ['gdas']: interval = self._base['INTERVAL'] - offset = f'-{interval}' + offset = timedelta_to_HMS(-interval) # Files from previous cycle files = [f'@Y@m@d.@H0000.fv_core.res.nc'] + \ @@ -181,7 +182,7 @@ def anal(self): dep_dict = {'type': 'task', 'name': f'{self.cdump}prep'} deps.append(rocoto.add_dependency(dep_dict)) if self.app_config.do_hybvar: - dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': '-06:00:00'} + dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) else: @@ -223,7 +224,7 @@ def analcalc(self): dep_dict = {'type': 'task', 'name': f'{self.cdump}sfcanl'} deps.append(rocoto.add_dependency(dep_dict)) if self.app_config.do_hybvar and self.cdump in ['gdas']: - dep_dict = {'type': 'task', 'name': 'enkfgdasechgres', 'offset': '-06:00:00'} + dep_dict = {'type': 'task', 'name': 'enkfgdasechgres', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) @@ -262,7 +263,7 @@ def atmanlinit(self): dep_dict = {'type': 'task', 'name': f'{self.cdump}prepatmiodaobs'} deps.append(rocoto.add_dependency(dep_dict)) if self.app_config.do_hybvar: - dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': '-06:00:00'} + dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) else: @@ -369,7 +370,7 @@ def ocnanalprep(self): deps = [] data = f'{ocean_hist_path}/gdas.t@Hz.ocnf009.nc' - dep_dict = {'type': 'data', 'data': data, 'offset': '-06:00:00'} + dep_dict = {'type': 'data', 'data': data, 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep=deps) @@ -490,8 +491,6 @@ def _fcst_forecast_only(self): wave_job = 'waveprep' if self.app_config.model_app in ['ATMW'] else 'waveinit' dep_dict = {'type': 'task', 'name': f'{self.cdump}{wave_job}'} dependencies.append(rocoto.add_dependency(dep_dict)) - dep_dict = {'type': 'task', 'name': f'{self.cdump}waveinit'} - dependencies.append(rocoto.add_dependency(dep_dict)) if self.app_config.do_aero: # Calculate offset based on CDUMP = gfs | gdas @@ -500,7 +499,7 @@ def _fcst_forecast_only(self): interval = self._base['INTERVAL_GFS'] elif self.cdump in ['gdas']: interval = self._base['INTERVAL'] - offset = f'-{interval}' + offset = timedelta_to_HMS(-interval) deps = [] dep_dict = {'type': 'task', 'name': f'{self.cdump}aerosol_init'} deps.append(rocoto.add_dependency(dep_dict)) @@ -536,7 +535,7 @@ def _fcst_cycled(self): dependencies = rocoto.create_dependency(dep_condition='and', dep=dependencies) if self.cdump in ['gdas']: - dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': '-06:00:00'} + dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} dependencies.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='or', dep=dependencies) @@ -902,6 +901,39 @@ def vminmon(self): return task + def tracker(self): + deps = [] + dep_dict = {'type': 'metatask', 'name': f'{self.cdump}post'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep=deps) + + resources = self.get_resource('tracker') + task = create_wf_task('tracker', resources, cdump=self.cdump, envar=self.envars, dependency=dependencies) + + return task + + def genesis(self): + deps = [] + dep_dict = {'type': 'metatask', 'name': f'{self.cdump}post'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep=deps) + + resources = self.get_resource('genesis') + task = create_wf_task('genesis', resources, cdump=self.cdump, envar=self.envars, dependency=dependencies) + + return task + + def genesis_fsu(self): + deps = [] + dep_dict = {'type': 'metatask', 'name': f'{self.cdump}post'} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep=deps) + + resources = self.get_resource('genesis_fsu') + task = create_wf_task('genesis_fsu', resources, cdump=self.cdump, envar=self.envars, dependency=dependencies) + + return task + def vrfy(self): deps = [] dep_dict = {'type': 'metatask', 'name': f'{self.cdump}post'} @@ -956,11 +988,15 @@ def arch(self): dependencies = [] if self.app_config.mode in ['cycled']: if self.cdump in ['gfs']: + dep_dict = {'type': 'task', 'name': f'{self.cdump}postanl'} + deps.append(rocoto.add_dependency(dep_dict)) if self.app_config.do_vminmon: dep_dict = {'type': 'task', 'name': f'{self.cdump}vminmon'} deps.append(rocoto.add_dependency(dep_dict)) elif self.cdump in ['gdas']: # Block for handling half cycle dependencies deps2 = [] + dep_dict = {'type': 'task', 'name': f'{self.cdump}postanl'} + deps2.append(rocoto.add_dependency(dep_dict)) if self.app_config.do_fit2obs: dep_dict = {'type': 'task', 'name': f'{self.cdump}fit2obs'} deps2.append(rocoto.add_dependency(dep_dict)) @@ -974,12 +1010,24 @@ def arch(self): dep_dict = {'type': 'task', 'name': f'{self.cdump}vminmon'} deps2.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps2) - dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': '-06:00:00'} + dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} dependencies.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='or', dep=dependencies) + if self.cdump in ['gfs'] and self.app_config.do_tracker: + dep_dict = {'type': 'task', 'name': f'{self.cdump}tracker'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.cdump in ['gfs'] and self.app_config.do_genesis: + dep_dict = {'type': 'task', 'name': f'{self.cdump}genesis'} + deps.append(rocoto.add_dependency(dep_dict)) + if self.cdump in ['gfs'] and self.app_config.do_genesis_fsu: + dep_dict = {'type': 'task', 'name': f'{self.cdump}genesis_fsu'} + deps.append(rocoto.add_dependency(dep_dict)) if self.app_config.do_vrfy: dep_dict = {'type': 'task', 'name': f'{self.cdump}vrfy'} deps.append(rocoto.add_dependency(dep_dict)) + # Post job dependencies + dep_dict = {'type': 'metatask', 'name': f'{self.cdump}post'} + deps.append(rocoto.add_dependency(dep_dict)) if self.app_config.do_wave: dep_dict = {'type': 'task', 'name': f'{self.cdump}wavepostsbs'} deps.append(rocoto.add_dependency(dep_dict)) @@ -992,10 +1040,6 @@ def arch(self): if self.app_config.mode in ['forecast-only']: # TODO: fix ocnpost to run in cycled mode dep_dict = {'type': 'metatask', 'name': f'{self.cdump}ocnpost'} deps.append(rocoto.add_dependency(dep_dict)) - # If all verification and ocean/wave coupling is off, add the gdas/gfs post metatask as a dependency - if len(deps) == 0: - dep_dict = {'type': 'metatask', 'name': f'{self.cdump}post'} - deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps + dependencies) @@ -1029,7 +1073,7 @@ def eobs(self): deps = [] dep_dict = {'type': 'task', 'name': f'{self.cdump.replace("enkf","")}prep'} deps.append(rocoto.add_dependency(dep_dict)) - dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': '-06:00:00'} + dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) @@ -1084,7 +1128,7 @@ def atmensanlinit(self): deps = [] dep_dict = {'type': 'task', 'name': f'{self.cdump.replace("enkf","")}prepatmiodaobs'} deps.append(rocoto.add_dependency(dep_dict)) - dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': '-06:00:00'} + dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) @@ -1100,7 +1144,7 @@ def atmensanlrun(self): deps = [] dep_dict = {'type': 'task', 'name': f'{self.cdump}atmensanlinit'} deps.append(rocoto.add_dependency(dep_dict)) - dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': '-06:00:00'} + dep_dict = {'type': 'metatask', 'name': 'enkfgdasepmn', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) @@ -1198,7 +1242,7 @@ def efcs(self): dep_dict = {'type': 'task', 'name': f'{self.cdump}esfc'} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) - dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': '-06:00:00'} + dep_dict = {'type': 'cycleexist', 'condition': 'not', 'offset': f"-{timedelta_to_HMS(self._base['cycle_interval'])}"} dependencies.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='or', dep=dependencies) diff --git a/workflow/rocoto/tasks.py b/workflow/rocoto/tasks.py index b1dd1b0d92..fd66ee2031 100644 --- a/workflow/rocoto/tasks.py +++ b/workflow/rocoto/tasks.py @@ -3,7 +3,7 @@ import numpy as np from applications.applications import AppConfig import rocoto.rocoto as rocoto -from wxflow import Template, TemplateConstants +from wxflow import Template, TemplateConstants, to_timedelta __all__ = ['Tasks', 'create_wf_task'] @@ -21,6 +21,7 @@ class Tasks: 'preplandobs', 'landanl', 'fcst', 'post', 'ocnpost', 'verfozn', 'verfrad', 'vminmon', 'vrfy', 'metp', + 'tracker', 'genesis', 'genesis_fsu', 'postsnd', 'awips', 'gempak', 'waveawipsbulls', 'waveawipsgridded', 'wavegempak', 'waveinit', 'wavepostbndpnt', 'wavepostbndpntbll', 'wavepostpnt', 'wavepostsbs', 'waveprep'] @@ -33,6 +34,7 @@ def __init__(self, app_config: AppConfig, cdump: str) -> None: # Save dict_configs and base in the internal state (never know where it may be needed) self._configs = self.app_config.configs self._base = self._configs['base'] + self._base['cycle_interval'] = to_timedelta(f'{self._base["assim_freq"]}H') self.n_tiles = 6 # TODO - this needs to be elsewhere diff --git a/workflow/setup_expt.py b/workflow/setup_expt.py index a808cafd91..b1fa439052 100755 --- a/workflow/setup_expt.py +++ b/workflow/setup_expt.py @@ -432,7 +432,8 @@ def _gfs_or_gefs_forecast_args(parser): return parser def _gefs_args(parser): - parser.add_argument('--start', help=SUPPRESS, type=str, required=False, default='cold') + parser.add_argument('--start', help='restart mode: warm or cold', type=str, + choices=['warm', 'cold'], required=False, default='cold') parser.add_argument('--configdir', help=SUPPRESS, type=str, required=False, default=os.path.join(_top, 'parm/config/gefs')) parser.add_argument('--yaml', help='Defaults to substitute from', type=str, required=False,