From 7090cff91e7cce3e41dd9487abd774dcc468a4fe Mon Sep 17 00:00:00 2001 From: mingshichen-noaa <48537176+mingshichen-noaa@users.noreply.github.com> Date: Thu, 12 Dec 2024 13:38:27 -0500 Subject: [PATCH 01/10] Update GSI analysis jobs to use COMIN/COMOUT (#3092) NCO has requested that each COM variable specify whether it is an input or an output. This completes that process for the global jgdas enkf select obs job and relevant .JGLOBAL_ATMOS_ANALYSIS and JGLOBAL_ATMOS_ANALYSIS_CALC jobs. Refs #2451 --- jobs/JGDAS_ENKF_SELECT_OBS | 64 +++---- jobs/JGLOBAL_ATMOS_ANALYSIS | 30 ++-- jobs/JGLOBAL_ATMOS_ANALYSIS_CALC | 13 +- scripts/exglobal_atmos_analysis.sh | 223 ++++++++++++------------ scripts/exglobal_atmos_analysis_calc.sh | 48 ++--- ush/calcanl_gfs.py | 4 +- ush/calcinc_gfs.py | 2 +- ush/gaussian_sfcanl.sh | 19 +- 8 files changed, 206 insertions(+), 197 deletions(-) diff --git a/jobs/JGDAS_ENKF_SELECT_OBS b/jobs/JGDAS_ENKF_SELECT_OBS index 3cfe48bb2b..2b876c0b3a 100755 --- a/jobs/JGDAS_ENKF_SELECT_OBS +++ b/jobs/JGDAS_ENKF_SELECT_OBS @@ -32,21 +32,25 @@ GPREFIX_DET="${GDUMP}.t${gcyc}z." export GSUFFIX=".ensmean.nc" # Generate COM variables from templates -RUN=${RUN/enkf} YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COM_OBS -MEMDIR='ensstat' YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COM_ATMOS_ANALYSIS -declare -rx COM_ATMOS_ANALYSIS_ENS="${COM_ATMOS_ANALYSIS}" +RUN=${RUN/enkf} YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMIN_OBS:COM_OBS_TMPL +MEMDIR='ensstat' YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMOUT_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL +declare -rx COMOUT_ATMOS_ANALYSIS_ENS="${COMOUT_ATMOS_ANALYSIS}" -RUN=${RUN/enkf} YMD=${PDY} HH=${cyc} declare_from_tmpl -r COM_ATMOS_ANALYSIS_DET:COM_ATMOS_ANALYSIS_TMPL +RUN=${RUN/enkf} YMD=${PDY} HH=${cyc} declare_from_tmpl -r \ + COMOUT_ATMOS_ANALYSIS_DET:COM_ATMOS_ANALYSIS_TMPL MEMDIR='ensstat' RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ - COM_ATMOS_ANALYSIS_PREV:COM_ATMOS_ANALYSIS_TMPL \ - COM_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL \ + COMIN_ATMOS_ANALYSIS_PREV:COM_ATMOS_ANALYSIS_TMPL \ + COMIN_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL -RUN="${GDUMP}" YMD=${gPDY} HH=${gcyc} declare_from_tmpl -r COM_ATMOS_ANALYSIS_DET_PREV:COM_ATMOS_ANALYSIS_TMPL +RUN="${GDUMP}" YMD=${gPDY} HH=${gcyc} declare_from_tmpl -r \ + COMIN_ATMOS_ANALYSIS_DET_PREV:COM_ATMOS_ANALYSIS_TMPL -mkdir -m 775 -p "${COM_ATMOS_ANALYSIS}" +mkdir -p "${COMOUT_ATMOS_ANALYSIS}" -export ATMGES_ENSMEAN="${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006${GSUFFIX}" +export ATMGES_ENSMEAN="${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006${GSUFFIX}" if [[ ! -f ${ATMGES_ENSMEAN} ]]; then echo "FATAL ERROR: FILE MISSING: ATMGES_ENSMEAN = ${ATMGES_ENSMEAN}" exit 1 @@ -61,44 +65,44 @@ status=$? export LEVS # Link observational data -export PREPQC="${COM_OBS}/${OPREFIX}prepbufr" +export PREPQC="${COMIN_OBS}/${OPREFIX}prepbufr" if [[ ! -f ${PREPQC} ]]; then echo "WARNING: Global PREPBUFR FILE ${PREPQC} MISSING" fi -export TCVITL="${COM_OBS}/${APREFIX_DET}syndata.tcvitals.tm00" +export TCVITL="${COMIN_OBS}/${APREFIX_DET}syndata.tcvitals.tm00" if [[ ${DONST} = "YES" ]]; then - export NSSTBF="${COM_OBS}/${OPREFIX}nsstbufr" + export NSSTBF="${COMIN_OBS}/${OPREFIX}nsstbufr" fi -export PREPQCPF="${COM_OBS}/${OPREFIX}prepbufr.acft_profiles" +export PREPQCPF="${COMIN_OBS}/${OPREFIX}prepbufr.acft_profiles" # Deterministic analysis and increment files -export SFCANL="${COM_ATMOS_ANALYSIS_DET}/${APREFIX_DET}sfcanl.nc" -export DTFANL="${COM_ATMOS_ANALYSIS_DET}/${APREFIX_DET}dtfanl.nc" -export ATMANL="${COM_ATMOS_ANALYSIS_DET}/${APREFIX_DET}atmanl.nc" -export ATMINC="${COM_ATMOS_ANALYSIS_DET}/${APREFIX_DET}atminc.nc" +export SFCANL="${COMOUT_ATMOS_ANALYSIS_DET}/${APREFIX_DET}sfcanl.nc" +export DTFANL="${COMOUT_ATMOS_ANALYSIS_DET}/${APREFIX_DET}dtfanl.nc" +export ATMANL="${COMOUT_ATMOS_ANALYSIS_DET}/${APREFIX_DET}atmanl.nc" +export ATMINC="${COMOUT_ATMOS_ANALYSIS_DET}/${APREFIX_DET}atminc.nc" # Guess Bias correction coefficients related to control -export GBIAS=${COM_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias -export GBIASPC=${COM_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias_pc -export GBIASAIR=${COM_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias_air -export GRADSTAT=${COM_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}radstat +export GBIAS=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias +export GBIASPC=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias_pc +export GBIASAIR=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}abias_air +export GRADSTAT=${COMIN_ATMOS_ANALYSIS_DET_PREV}/${GPREFIX_DET}radstat # Bias correction coefficients related to ensemble mean -export ABIAS="${COM_ATMOS_ANALYSIS}/${APREFIX}abias.ensmean" -export ABIASPC="${COM_ATMOS_ANALYSIS}/${APREFIX}abias_pc.ensmean" -export ABIASAIR="${COM_ATMOS_ANALYSIS}/${APREFIX}abias_air.ensmean" -export ABIASe="${COM_ATMOS_ANALYSIS}/${APREFIX}abias_int.ensmean" +export ABIAS="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias.ensmean" +export ABIASPC="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_pc.ensmean" +export ABIASAIR="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_air.ensmean" +export ABIASe="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_int.ensmean" # Diagnostics related to ensemble mean -export GSISTAT="${COM_ATMOS_ANALYSIS}/${APREFIX}gsistat.ensmean" -export CNVSTAT="${COM_ATMOS_ANALYSIS}/${APREFIX}cnvstat.ensmean" -export OZNSTAT="${COM_ATMOS_ANALYSIS}/${APREFIX}oznstat.ensmean" -export RADSTAT="${COM_ATMOS_ANALYSIS}/${APREFIX}radstat.ensmean" +export GSISTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}gsistat.ensmean" +export CNVSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}cnvstat.ensmean" +export OZNSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}oznstat.ensmean" +export RADSTAT="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}radstat.ensmean" # Select observations based on ensemble mean export RUN_SELECT="YES" export USE_SELECT="NO" -export SELECT_OBS="${COM_ATMOS_ANALYSIS}/${APREFIX}obsinput.ensmean" +export SELECT_OBS="${COMOUT_ATMOS_ANALYSIS}/${APREFIX}obsinput.ensmean" export DIAG_SUFFIX="_ensmean" diff --git a/jobs/JGLOBAL_ATMOS_ANALYSIS b/jobs/JGLOBAL_ATMOS_ANALYSIS index 5776aa6d13..b13f026ba2 100755 --- a/jobs/JGLOBAL_ATMOS_ANALYSIS +++ b/jobs/JGLOBAL_ATMOS_ANALYSIS @@ -31,18 +31,20 @@ export APREFIX="${rCDUMP}.t${cyc}z." export GPREFIX_ENS="${GDUMP_ENS}.t${gcyc}z." # Generate COM variables from templates -YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COM_OBS COM_ATMOS_ANALYSIS +YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMIN_OBS:COM_OBS_TMPL \ + COMOUT_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ - COM_ATMOS_ANALYSIS_PREV:COM_ATMOS_ANALYSIS_TMPL \ - COM_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL + COMIN_ATMOS_ANALYSIS_PREV:COM_ATMOS_ANALYSIS_TMPL \ + COMIN_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL MEMDIR='ensstat' RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ - COM_ATMOS_HISTORY_ENS_PREV:COM_ATMOS_HISTORY_TMPL + COMIN_ATMOS_HISTORY_ENS_PREV:COM_ATMOS_HISTORY_TMPL -mkdir -m 775 -p "${COM_ATMOS_ANALYSIS}" +mkdir -p "${COMOUT_ATMOS_ANALYSIS}" -export ATMGES="${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006.nc" +export ATMGES="${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006.nc" if [ ! -f ${ATMGES} ]; then echo "FATAL ERROR: FILE MISSING: ATMGES = ${ATMGES}" exit 1 @@ -55,7 +57,7 @@ status=$? if [ ${DOHYBVAR} = "YES" ]; then - export ATMGES_ENSMEAN="${COM_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}atmf006.ensmean.nc" + export ATMGES_ENSMEAN="${COMIN_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}atmf006.ensmean.nc" if [ ! -f ${ATMGES_ENSMEAN} ]; then echo "FATAL ERROR: FILE MISSING: ATMGES_ENSMEAN = ${ATMGES_ENSMEAN}" exit 2 @@ -64,17 +66,17 @@ fi # Link observational data -export PREPQC="${COM_OBS}/${OPREFIX}prepbufr" +export PREPQC="${COMIN_OBS}/${OPREFIX}prepbufr" if [[ ! -f ${PREPQC} ]]; then echo "WARNING: Global PREPBUFR FILE ${PREPQC} MISSING" fi -export TCVITL="${COM_OBS}/${OPREFIX}syndata.tcvitals.tm00" +export TCVITL="${COMIN_OBS}/${OPREFIX}syndata.tcvitals.tm00" if [[ ${DONST} = "YES" ]]; then if [[ ${MAKE_NSSTBUFR} == "YES" ]]; then - export NSSTBF="${COM_OBS}/${OPREFIX}nsstbufr" + export NSSTBF="${COMIN_OBS}/${OPREFIX}nsstbufr" fi fi -export PREPQCPF="${COM_OBS}/${OPREFIX}prepbufr.acft_profiles" +export PREPQCPF="${COMIN_OBS}/${OPREFIX}prepbufr.acft_profiles" # Copy fix file for obsproc # TODO: Why is this necessary? if [[ ${RUN} = "gfs" ]]; then @@ -95,9 +97,9 @@ status=$? # Send Alerts ############################################## if [ ${SENDDBN} = YES -a ${RUN} = gdas ] ; then - ${DBNROOT}/bin/dbn_alert MODEL GDAS_MSC_abias ${job} ${COM_ATMOS_ANALYSIS}/${APREFIX}abias - ${DBNROOT}/bin/dbn_alert MODEL GDAS_MSC_abias_pc ${job} ${COM_ATMOS_ANALYSIS}/${APREFIX}abias_pc - ${DBNROOT}/bin/dbn_alert MODEL GDAS_MSC_abias_air ${job} ${COM_ATMOS_ANALYSIS}/${APREFIX}abias_air + ${DBNROOT}/bin/dbn_alert MODEL GDAS_MSC_abias ${job} ${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias + ${DBNROOT}/bin/dbn_alert MODEL GDAS_MSC_abias_pc ${job} ${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_pc + ${DBNROOT}/bin/dbn_alert MODEL GDAS_MSC_abias_air ${job} ${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_air fi diff --git a/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC b/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC index 5b6073254a..063a006658 100755 --- a/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC +++ b/jobs/JGLOBAL_ATMOS_ANALYSIS_CALC @@ -28,16 +28,19 @@ export GPREFIX="${GDUMP}.t${gcyc}z." export APREFIX="${RUN}.t${cyc}z." export GPREFIX_ENS="${GDUMP_ENS}.t${gcyc}z." -RUN=${rCDUMP} YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COM_OBS +RUN=${rCDUMP} YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMIN_OBS:COM_OBS_TMPL -YMD=${PDY} HH=${cyc} declare_from_tmpl -rx COM_ATMOS_ANALYSIS COM_ATMOS_RESTART +YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMOUT_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \ + COMIN_ATMOS_RESTART:COM_ATMOS_RESTART_TMPL RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ - COM_OBS_PREV:COM_OBS_TMPL \ - COM_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL + COMIN_OBS_PREV:COM_OBS_TMPL \ + COMIN_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL -export ATMGES="${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006.nc" +export ATMGES="${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006.nc" if [ ! -f ${ATMGES} ]; then echo "FATAL ERROR: FILE MISSING: ATMGES = ${ATMGES}" exit 1 diff --git a/scripts/exglobal_atmos_analysis.sh b/scripts/exglobal_atmos_analysis.sh index 932adf8e10..bd11b81c39 100755 --- a/scripts/exglobal_atmos_analysis.sh +++ b/scripts/exglobal_atmos_analysis.sh @@ -92,112 +92,112 @@ export hofx_2m_sfcfile=${hofx_2m_sfcfile:-".false."} # Observations OPREFIX=${OPREFIX:-""} OSUFFIX=${OSUFFIX:-""} -PREPQC=${PREPQC:-${COM_OBS}/${OPREFIX}prepbufr${OSUFFIX}} -PREPQCPF=${PREPQCPF:-${COM_OBS}/${OPREFIX}prepbufr.acft_profiles${OSUFFIX}} -NSSTBF=${NSSTBF:-${COM_OBS}/${OPREFIX}nsstbufr${OSUFFIX}} -SATWND=${SATWND:-${COM_OBS}/${OPREFIX}satwnd.tm00.bufr_d${OSUFFIX}} -OSCATBF=${OSCATBF:-${COM_OBS}/${OPREFIX}oscatw.tm00.bufr_d${OSUFFIX}} -RAPIDSCATBF=${RAPIDSCATBF:-${COM_OBS}/${OPREFIX}rapidscatw.tm00.bufr_d${OSUFFIX}} -GSNDBF=${GSNDBF:-${COM_OBS}/${OPREFIX}goesnd.tm00.bufr_d${OSUFFIX}} -GSNDBF1=${GSNDBF1:-${COM_OBS}/${OPREFIX}goesfv.tm00.bufr_d${OSUFFIX}} -#B1HRS2=${B1HRS2:-${COM_OBS}/${OPREFIX}1bhrs2.tm00.bufr_d${OSUFFIX}} # HIRS temporarily disabled due to CRTM versioning issues -B1MSU=${B1MSU:-${COM_OBS}/${OPREFIX}1bmsu.tm00.bufr_d${OSUFFIX}} -#B1HRS3=${B1HRS3:-${COM_OBS}/${OPREFIX}1bhrs3.tm00.bufr_d${OSUFFIX}} # HIRS temporarily disabled due to CRTM versioning issues -#B1HRS4=${B1HRS4:-${COM_OBS}/${OPREFIX}1bhrs4.tm00.bufr_d${OSUFFIX}} # HIRS temporarily disabled due to CRTM versioning issues -B1AMUA=${B1AMUA:-${COM_OBS}/${OPREFIX}1bamua.tm00.bufr_d${OSUFFIX}} -B1AMUB=${B1AMUB:-${COM_OBS}/${OPREFIX}1bamub.tm00.bufr_d${OSUFFIX}} -B1MHS=${B1MHS:-${COM_OBS}/${OPREFIX}1bmhs.tm00.bufr_d${OSUFFIX}} -ESHRS3=${ESHRS3:-${COM_OBS}/${OPREFIX}eshrs3.tm00.bufr_d${OSUFFIX}} -ESAMUA=${ESAMUA:-${COM_OBS}/${OPREFIX}esamua.tm00.bufr_d${OSUFFIX}} -ESAMUB=${ESAMUB:-${COM_OBS}/${OPREFIX}esamub.tm00.bufr_d${OSUFFIX}} -ESMHS=${ESMHS:-${COM_OBS}/${OPREFIX}esmhs.tm00.bufr_d${OSUFFIX}} -HRS3DB=${HRS3DB:-${COM_OBS}/${OPREFIX}hrs3db.tm00.bufr_d${OSUFFIX}} -AMUADB=${AMUADB:-${COM_OBS}/${OPREFIX}amuadb.tm00.bufr_d${OSUFFIX}} -AMUBDB=${AMUBDB:-${COM_OBS}/${OPREFIX}amubdb.tm00.bufr_d${OSUFFIX}} -MHSDB=${MHSDB:-${COM_OBS}/${OPREFIX}mhsdb.tm00.bufr_d${OSUFFIX}} -AIRSBF=${AIRSBF:-${COM_OBS}/${OPREFIX}airsev.tm00.bufr_d${OSUFFIX}} -IASIBF=${IASIBF:-${COM_OBS}/${OPREFIX}mtiasi.tm00.bufr_d${OSUFFIX}} -ESIASI=${ESIASI:-${COM_OBS}/${OPREFIX}esiasi.tm00.bufr_d${OSUFFIX}} -IASIDB=${IASIDB:-${COM_OBS}/${OPREFIX}iasidb.tm00.bufr_d${OSUFFIX}} -AMSREBF=${AMSREBF:-${COM_OBS}/${OPREFIX}amsre.tm00.bufr_d${OSUFFIX}} -AMSR2BF=${AMSR2BF:-${COM_OBS}/${OPREFIX}amsr2.tm00.bufr_d${OSUFFIX}} -GMI1CRBF=${GMI1CRBF:-${COM_OBS}/${OPREFIX}gmi1cr.tm00.bufr_d${OSUFFIX}} # GMI temporarily disabled due to array overflow. -SAPHIRBF=${SAPHIRBF:-${COM_OBS}/${OPREFIX}saphir.tm00.bufr_d${OSUFFIX}} -SEVIRIBF=${SEVIRIBF:-${COM_OBS}/${OPREFIX}sevcsr.tm00.bufr_d${OSUFFIX}} -AHIBF=${AHIBF:-${COM_OBS}/${OPREFIX}ahicsr.tm00.bufr_d${OSUFFIX}} -SSTVIIRS=${SSTVIIRS:-${COM_OBS}/${OPREFIX}sstvcw.tm00.bufr_d${OSUFFIX}} -ABIBF=${ABIBF:-${COM_OBS}/${OPREFIX}gsrcsr.tm00.bufr_d${OSUFFIX}} -CRISBF=${CRISBF:-${COM_OBS}/${OPREFIX}cris.tm00.bufr_d${OSUFFIX}} -ESCRIS=${ESCRIS:-${COM_OBS}/${OPREFIX}escris.tm00.bufr_d${OSUFFIX}} -CRISDB=${CRISDB:-${COM_OBS}/${OPREFIX}crisdb.tm00.bufr_d${OSUFFIX}} -CRISFSBF=${CRISFSBF:-${COM_OBS}/${OPREFIX}crisf4.tm00.bufr_d${OSUFFIX}} -ESCRISFS=${ESCRISFS:-${COM_OBS}/${OPREFIX}escrsf.tm00.bufr_d${OSUFFIX}} -CRISFSDB=${CRISFSDB:-${COM_OBS}/${OPREFIX}crsfdb.tm00.bufr_d${OSUFFIX}} -ATMSBF=${ATMSBF:-${COM_OBS}/${OPREFIX}atms.tm00.bufr_d${OSUFFIX}} -ESATMS=${ESATMS:-${COM_OBS}/${OPREFIX}esatms.tm00.bufr_d${OSUFFIX}} -ATMSDB=${ATMSDB:-${COM_OBS}/${OPREFIX}atmsdb.tm00.bufr_d${OSUFFIX}} -SSMITBF=${SSMITBF:-${COM_OBS}/${OPREFIX}ssmit.tm00.bufr_d${OSUFFIX}} -SSMISBF=${SSMISBF:-${COM_OBS}/${OPREFIX}ssmisu.tm00.bufr_d${OSUFFIX}} -SBUVBF=${SBUVBF:-${COM_OBS}/${OPREFIX}osbuv8.tm00.bufr_d${OSUFFIX}} -OMPSNPBF=${OMPSNPBF:-${COM_OBS}/${OPREFIX}ompsn8.tm00.bufr_d${OSUFFIX}} -OMPSTCBF=${OMPSTCBF:-${COM_OBS}/${OPREFIX}ompst8.tm00.bufr_d${OSUFFIX}} -OMPSLPBF=${OMPSLPBF:-${COM_OBS}/${OPREFIX}ompslp.tm00.bufr_d${OSUFFIX}} -GOMEBF=${GOMEBF:-${COM_OBS}/${OPREFIX}gome.tm00.bufr_d${OSUFFIX}} -OMIBF=${OMIBF:-${COM_OBS}/${OPREFIX}omi.tm00.bufr_d${OSUFFIX}} -MLSBF=${MLSBF:-${COM_OBS}/${OPREFIX}mls.tm00.bufr_d${OSUFFIX}} -SMIPCP=${SMIPCP:-${COM_OBS}/${OPREFIX}spssmi.tm00.bufr_d${OSUFFIX}} -TMIPCP=${TMIPCP:-${COM_OBS}/${OPREFIX}sptrmm.tm00.bufr_d${OSUFFIX}} -GPSROBF=${GPSROBF:-${COM_OBS}/${OPREFIX}gpsro.tm00.bufr_d${OSUFFIX}} -TCVITL=${TCVITL:-${COM_OBS}/${OPREFIX}syndata.tcvitals.tm00} -B1AVHAM=${B1AVHAM:-${COM_OBS}/${OPREFIX}avcsam.tm00.bufr_d${OSUFFIX}} -B1AVHPM=${B1AVHPM:-${COM_OBS}/${OPREFIX}avcspm.tm00.bufr_d${OSUFFIX}} -HDOB=${HDOB:-${COM_OBS}/${OPREFIX}hdob.tm00.bufr_d${OSUFFIX}} +PREPQC=${PREPQC:-${COMIN_OBS}/${OPREFIX}prepbufr${OSUFFIX}} +PREPQCPF=${PREPQCPF:-${COMIN_OBS}/${OPREFIX}prepbufr.acft_profiles${OSUFFIX}} +NSSTBF=${NSSTBF:-${COMIN_OBS}/${OPREFIX}nsstbufr${OSUFFIX}} +SATWND=${SATWND:-${COMIN_OBS}/${OPREFIX}satwnd.tm00.bufr_d${OSUFFIX}} +OSCATBF=${OSCATBF:-${COMIN_OBS}/${OPREFIX}oscatw.tm00.bufr_d${OSUFFIX}} +RAPIDSCATBF=${RAPIDSCATBF:-${COMIN_OBS}/${OPREFIX}rapidscatw.tm00.bufr_d${OSUFFIX}} +GSNDBF=${GSNDBF:-${COMIN_OBS}/${OPREFIX}goesnd.tm00.bufr_d${OSUFFIX}} +GSNDBF1=${GSNDBF1:-${COMIN_OBS}/${OPREFIX}goesfv.tm00.bufr_d${OSUFFIX}} +#B1HRS2=${B1HRS2:-${COMIN_OBS}/${OPREFIX}1bhrs2.tm00.bufr_d${OSUFFIX}} # HIRS temporarily disabled due to CRTM versioning issues +B1MSU=${B1MSU:-${COMIN_OBS}/${OPREFIX}1bmsu.tm00.bufr_d${OSUFFIX}} +#B1HRS3=${B1HRS3:-${COMIN_OBS}/${OPREFIX}1bhrs3.tm00.bufr_d${OSUFFIX}} # HIRS temporarily disabled due to CRTM versioning issues +#B1HRS4=${B1HRS4:-${COMIN_OBS}/${OPREFIX}1bhrs4.tm00.bufr_d${OSUFFIX}} # HIRS temporarily disabled due to CRTM versioning issues +B1AMUA=${B1AMUA:-${COMIN_OBS}/${OPREFIX}1bamua.tm00.bufr_d${OSUFFIX}} +B1AMUB=${B1AMUB:-${COMIN_OBS}/${OPREFIX}1bamub.tm00.bufr_d${OSUFFIX}} +B1MHS=${B1MHS:-${COMIN_OBS}/${OPREFIX}1bmhs.tm00.bufr_d${OSUFFIX}} +ESHRS3=${ESHRS3:-${COMIN_OBS}/${OPREFIX}eshrs3.tm00.bufr_d${OSUFFIX}} +ESAMUA=${ESAMUA:-${COMIN_OBS}/${OPREFIX}esamua.tm00.bufr_d${OSUFFIX}} +ESAMUB=${ESAMUB:-${COMIN_OBS}/${OPREFIX}esamub.tm00.bufr_d${OSUFFIX}} +ESMHS=${ESMHS:-${COMIN_OBS}/${OPREFIX}esmhs.tm00.bufr_d${OSUFFIX}} +HRS3DB=${HRS3DB:-${COMIN_OBS}/${OPREFIX}hrs3db.tm00.bufr_d${OSUFFIX}} +AMUADB=${AMUADB:-${COMIN_OBS}/${OPREFIX}amuadb.tm00.bufr_d${OSUFFIX}} +AMUBDB=${AMUBDB:-${COMIN_OBS}/${OPREFIX}amubdb.tm00.bufr_d${OSUFFIX}} +MHSDB=${MHSDB:-${COMIN_OBS}/${OPREFIX}mhsdb.tm00.bufr_d${OSUFFIX}} +AIRSBF=${AIRSBF:-${COMIN_OBS}/${OPREFIX}airsev.tm00.bufr_d${OSUFFIX}} +IASIBF=${IASIBF:-${COMIN_OBS}/${OPREFIX}mtiasi.tm00.bufr_d${OSUFFIX}} +ESIASI=${ESIASI:-${COMIN_OBS}/${OPREFIX}esiasi.tm00.bufr_d${OSUFFIX}} +IASIDB=${IASIDB:-${COMIN_OBS}/${OPREFIX}iasidb.tm00.bufr_d${OSUFFIX}} +AMSREBF=${AMSREBF:-${COMIN_OBS}/${OPREFIX}amsre.tm00.bufr_d${OSUFFIX}} +AMSR2BF=${AMSR2BF:-${COMIN_OBS}/${OPREFIX}amsr2.tm00.bufr_d${OSUFFIX}} +GMI1CRBF=${GMI1CRBF:-${COMIN_OBS}/${OPREFIX}gmi1cr.tm00.bufr_d${OSUFFIX}} # GMI temporarily disabled due to array overflow. +SAPHIRBF=${SAPHIRBF:-${COMIN_OBS}/${OPREFIX}saphir.tm00.bufr_d${OSUFFIX}} +SEVIRIBF=${SEVIRIBF:-${COMIN_OBS}/${OPREFIX}sevcsr.tm00.bufr_d${OSUFFIX}} +AHIBF=${AHIBF:-${COMIN_OBS}/${OPREFIX}ahicsr.tm00.bufr_d${OSUFFIX}} +SSTVIIRS=${SSTVIIRS:-${COMIN_OBS}/${OPREFIX}sstvcw.tm00.bufr_d${OSUFFIX}} +ABIBF=${ABIBF:-${COMIN_OBS}/${OPREFIX}gsrcsr.tm00.bufr_d${OSUFFIX}} +CRISBF=${CRISBF:-${COMIN_OBS}/${OPREFIX}cris.tm00.bufr_d${OSUFFIX}} +ESCRIS=${ESCRIS:-${COMIN_OBS}/${OPREFIX}escris.tm00.bufr_d${OSUFFIX}} +CRISDB=${CRISDB:-${COMIN_OBS}/${OPREFIX}crisdb.tm00.bufr_d${OSUFFIX}} +CRISFSBF=${CRISFSBF:-${COMIN_OBS}/${OPREFIX}crisf4.tm00.bufr_d${OSUFFIX}} +ESCRISFS=${ESCRISFS:-${COMIN_OBS}/${OPREFIX}escrsf.tm00.bufr_d${OSUFFIX}} +CRISFSDB=${CRISFSDB:-${COMIN_OBS}/${OPREFIX}crsfdb.tm00.bufr_d${OSUFFIX}} +ATMSBF=${ATMSBF:-${COMIN_OBS}/${OPREFIX}atms.tm00.bufr_d${OSUFFIX}} +ESATMS=${ESATMS:-${COMIN_OBS}/${OPREFIX}esatms.tm00.bufr_d${OSUFFIX}} +ATMSDB=${ATMSDB:-${COMIN_OBS}/${OPREFIX}atmsdb.tm00.bufr_d${OSUFFIX}} +SSMITBF=${SSMITBF:-${COMIN_OBS}/${OPREFIX}ssmit.tm00.bufr_d${OSUFFIX}} +SSMISBF=${SSMISBF:-${COMIN_OBS}/${OPREFIX}ssmisu.tm00.bufr_d${OSUFFIX}} +SBUVBF=${SBUVBF:-${COMIN_OBS}/${OPREFIX}osbuv8.tm00.bufr_d${OSUFFIX}} +OMPSNPBF=${OMPSNPBF:-${COMIN_OBS}/${OPREFIX}ompsn8.tm00.bufr_d${OSUFFIX}} +OMPSTCBF=${OMPSTCBF:-${COMIN_OBS}/${OPREFIX}ompst8.tm00.bufr_d${OSUFFIX}} +OMPSLPBF=${OMPSLPBF:-${COMIN_OBS}/${OPREFIX}ompslp.tm00.bufr_d${OSUFFIX}} +GOMEBF=${GOMEBF:-${COMIN_OBS}/${OPREFIX}gome.tm00.bufr_d${OSUFFIX}} +OMIBF=${OMIBF:-${COMIN_OBS}/${OPREFIX}omi.tm00.bufr_d${OSUFFIX}} +MLSBF=${MLSBF:-${COMIN_OBS}/${OPREFIX}mls.tm00.bufr_d${OSUFFIX}} +SMIPCP=${SMIPCP:-${COMIN_OBS}/${OPREFIX}spssmi.tm00.bufr_d${OSUFFIX}} +TMIPCP=${TMIPCP:-${COMIN_OBS}/${OPREFIX}sptrmm.tm00.bufr_d${OSUFFIX}} +GPSROBF=${GPSROBF:-${COMIN_OBS}/${OPREFIX}gpsro.tm00.bufr_d${OSUFFIX}} +TCVITL=${TCVITL:-${COMIN_OBS}/${OPREFIX}syndata.tcvitals.tm00} +B1AVHAM=${B1AVHAM:-${COMIN_OBS}/${OPREFIX}avcsam.tm00.bufr_d${OSUFFIX}} +B1AVHPM=${B1AVHPM:-${COMIN_OBS}/${OPREFIX}avcspm.tm00.bufr_d${OSUFFIX}} +HDOB=${HDOB:-${COMIN_OBS}/${OPREFIX}hdob.tm00.bufr_d${OSUFFIX}} # Guess files GPREFIX=${GPREFIX:-""} GSUFFIX=${GSUFFIX:-".nc"} -SFCG03=${SFCG03:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf003${GSUFFIX}} -SFCG04=${SFCG04:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf004${GSUFFIX}} -SFCG05=${SFCG05:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf005${GSUFFIX}} -SFCGES=${SFCGES:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf006${GSUFFIX}} -SFCG07=${SFCG07:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf007${GSUFFIX}} -SFCG08=${SFCG08:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf008${GSUFFIX}} -SFCG09=${SFCG09:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf009${GSUFFIX}} -ATMG03=${ATMG03:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf003${GSUFFIX}} -ATMG04=${ATMG04:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf004${GSUFFIX}} -ATMG05=${ATMG05:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf005${GSUFFIX}} -ATMGES=${ATMGES:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006${GSUFFIX}} -ATMG07=${ATMG07:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf007${GSUFFIX}} -ATMG08=${ATMG08:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf008${GSUFFIX}} -ATMG09=${ATMG09:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf009${GSUFFIX}} -GBIAS=${GBIAS:-${COM_ATMOS_ANALYSIS_PREV}/${GPREFIX}abias} -GBIASPC=${GBIASPC:-${COM_ATMOS_ANALYSIS_PREV}/${GPREFIX}abias_pc} -GBIASAIR=${GBIASAIR:-${COM_ATMOS_ANALYSIS_PREV}/${GPREFIX}abias_air} -GRADSTAT=${GRADSTAT:-${COM_ATMOS_ANALYSIS_PREV}/${GPREFIX}radstat} +SFCG03=${SFCG03:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf003${GSUFFIX}} +SFCG04=${SFCG04:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf004${GSUFFIX}} +SFCG05=${SFCG05:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf005${GSUFFIX}} +SFCGES=${SFCGES:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf006${GSUFFIX}} +SFCG07=${SFCG07:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf007${GSUFFIX}} +SFCG08=${SFCG08:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf008${GSUFFIX}} +SFCG09=${SFCG09:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}sfcf009${GSUFFIX}} +ATMG03=${ATMG03:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf003${GSUFFIX}} +ATMG04=${ATMG04:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf004${GSUFFIX}} +ATMG05=${ATMG05:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf005${GSUFFIX}} +ATMGES=${ATMGES:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006${GSUFFIX}} +ATMG07=${ATMG07:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf007${GSUFFIX}} +ATMG08=${ATMG08:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf008${GSUFFIX}} +ATMG09=${ATMG09:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf009${GSUFFIX}} +GBIAS=${GBIAS:-${COMIN_ATMOS_ANALYSIS_PREV}/${GPREFIX}abias} +GBIASPC=${GBIASPC:-${COMIN_ATMOS_ANALYSIS_PREV}/${GPREFIX}abias_pc} +GBIASAIR=${GBIASAIR:-${COMIN_ATMOS_ANALYSIS_PREV}/${GPREFIX}abias_air} +GRADSTAT=${GRADSTAT:-${COMIN_ATMOS_ANALYSIS_PREV}/${GPREFIX}radstat} # Analysis files export APREFIX=${APREFIX:-""} -SFCANL=${SFCANL:-${COM_ATMOS_ANALYSIS}/${APREFIX}sfcanl.nc} -DTFANL=${DTFANL:-${COM_ATMOS_ANALYSIS}/${APREFIX}dtfanl.nc} -ATMANL=${ATMANL:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmanl.nc} -ABIAS=${ABIAS:-${COM_ATMOS_ANALYSIS}/${APREFIX}abias} -ABIASPC=${ABIASPC:-${COM_ATMOS_ANALYSIS}/${APREFIX}abias_pc} -ABIASAIR=${ABIASAIR:-${COM_ATMOS_ANALYSIS}/${APREFIX}abias_air} -ABIASe=${ABIASe:-${COM_ATMOS_ANALYSIS}/${APREFIX}abias_int} -RADSTAT=${RADSTAT:-${COM_ATMOS_ANALYSIS}/${APREFIX}radstat} -GSISTAT=${GSISTAT:-${COM_ATMOS_ANALYSIS}/${APREFIX}gsistat} -PCPSTAT=${PCPSTAT:-${COM_ATMOS_ANALYSIS}/${APREFIX}pcpstat} -CNVSTAT=${CNVSTAT:-${COM_ATMOS_ANALYSIS}/${APREFIX}cnvstat} -OZNSTAT=${OZNSTAT:-${COM_ATMOS_ANALYSIS}/${APREFIX}oznstat} +SFCANL=${SFCANL:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}sfcanl.nc} +DTFANL=${DTFANL:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}dtfanl.nc} +ATMANL=${ATMANL:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmanl.nc} +ABIAS=${ABIAS:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias} +ABIASPC=${ABIASPC:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_pc} +ABIASAIR=${ABIASAIR:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_air} +ABIASe=${ABIASe:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}abias_int} +RADSTAT=${RADSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}radstat} +GSISTAT=${GSISTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}gsistat} +PCPSTAT=${PCPSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}pcpstat} +CNVSTAT=${CNVSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}cnvstat} +OZNSTAT=${OZNSTAT:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}oznstat} # Increment files -ATMINC=${ATMINC:-${COM_ATMOS_ANALYSIS}/${APREFIX}atminc.nc} +ATMINC=${ATMINC:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atminc.nc} # Obs diag RUN_SELECT=${RUN_SELECT:-"NO"} USE_SELECT=${USE_SELECT:-"NO"} USE_RADSTAT=${USE_RADSTAT:-"YES"} -SELECT_OBS=${SELECT_OBS:-${COM_ATMOS_ANALYSIS}/${APREFIX}obsinput} +SELECT_OBS=${SELECT_OBS:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}obsinput} GENDIAG=${GENDIAG:-"YES"} DIAG_SUFFIX=${DIAG_SUFFIX:-""} if [ ${netcdf_diag} = ".true." ] ; then @@ -211,7 +211,7 @@ nm="" if [ ${CFP_MP} = "YES" ]; then nm=0 fi -DIAG_DIR=${DIAG_DIR:-${COM_ATMOS_ANALYSIS}/gsidiags} +DIAG_DIR=${DIAG_DIR:-${COMOUT_ATMOS_ANALYSIS}/gsidiags} # Set script / GSI control parameters DOHYBVAR=${DOHYBVAR:-"NO"} @@ -242,8 +242,8 @@ JCAP=${JCAP:--9999} # there is no jcap in these files # Get header information from Ensemble Guess files if [ ${DOHYBVAR} = "YES" ]; then - SFCGES_ENSMEAN=${SFCGES_ENSMEAN:-${COM_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}sfcf006.ensmean.nc} - export ATMGES_ENSMEAN=${ATMGES_ENSMEAN:-${COM_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}atmf006.ensmean.nc} + SFCGES_ENSMEAN=${SFCGES_ENSMEAN:-${COMIN_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}sfcf006.ensmean.nc} + export ATMGES_ENSMEAN=${ATMGES_ENSMEAN:-${COMIN_ATMOS_HISTORY_ENS_PREV}/${GPREFIX_ENS}atmf006.ensmean.nc} LONB_ENKF=${LONB_ENKF:-$(${NCLEN} ${ATMGES_ENSMEAN} grid_xt)} # get LONB_ENKF LATB_ENKF=${LATB_ENKF:-$(${NCLEN} ${ATMGES_ENSMEAN} grid_yt)} # get LATB_ENFK LEVS_ENKF=${LEVS_ENKF:-$(${NCLEN} ${ATMGES_ENSMEAN} pfull)} # get LATB_ENFK @@ -335,18 +335,18 @@ fi # Set 4D-EnVar specific variables if [ ${DOHYBVAR} = "YES" -a ${l4densvar} = ".true." -a ${lwrite4danl} = ".true." ]; then - ATMA03=${ATMA03:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma003.nc} - ATMI03=${ATMI03:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi003.nc} - ATMA04=${ATMA04:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma004.nc} - ATMI04=${ATMI04:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi004.nc} - ATMA05=${ATMA05:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma005.nc} - ATMI05=${ATMI05:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi005.nc} - ATMA07=${ATMA07:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma007.nc} - ATMI07=${ATMI07:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi007.nc} - ATMA08=${ATMA08:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma008.nc} - ATMI08=${ATMI08:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi008.nc} - ATMA09=${ATMA09:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma009.nc} - ATMI09=${ATMI09:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi009.nc} + ATMA03=${ATMA03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma003.nc} + ATMI03=${ATMI03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi003.nc} + ATMA04=${ATMA04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma004.nc} + ATMI04=${ATMI04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi004.nc} + ATMA05=${ATMA05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma005.nc} + ATMI05=${ATMI05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi005.nc} + ATMA07=${ATMA07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma007.nc} + ATMI07=${ATMI07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi007.nc} + ATMA08=${ATMA08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma008.nc} + ATMI08=${ATMI08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi008.nc} + ATMA09=${ATMA09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma009.nc} + ATMI09=${ATMI09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi009.nc} fi ################################################################################ @@ -545,12 +545,13 @@ if [ ${DOHYBVAR} = "YES" ]; then for imem in $(seq 1 ${NMEM_ENS}); do memchar="mem$(printf %03i "${imem}")" - MEMDIR=${memchar} RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl COM_ATMOS_HISTORY + MEMDIR=${memchar} RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl \ + COMIN_ATMOS_HISTORY:COM_ATMOS_HISTORY_TMPL for fhr in ${fhrs}; do - ${NLN} ${COM_ATMOS_HISTORY}/${GPREFIX_ENS}atmf0${fhr}${ENKF_SUFFIX}.nc ./ensemble_data/sigf${fhr}_ens_${memchar} + ${NLN} ${COMIN_ATMOS_HISTORY}/${GPREFIX_ENS}atmf0${fhr}${ENKF_SUFFIX}.nc ./ensemble_data/sigf${fhr}_ens_${memchar} if [ ${cnvw_option} = ".true." ]; then - ${NLN} ${COM_ATMOS_HISTORY}/${GPREFIX_ENS}sfcf0${fhr}.nc ./ensemble_data/sfcf${fhr}_ens_${memchar} + ${NLN} ${COMIN_ATMOS_HISTORY}/${GPREFIX_ENS}sfcf0${fhr}.nc ./ensemble_data/sfcf${fhr}_ens_${memchar} fi done done @@ -990,7 +991,7 @@ cd ${pwd} if [ ${SENDECF} = "YES" -a "${RUN}" != "enkf" ]; then ecflow_client --event release_fcst fi -echo "${rCDUMP} ${CDATE} atminc done at $(date)" > ${COM_ATMOS_ANALYSIS}/${APREFIX}loginc.txt +echo "${rCDUMP} ${CDATE} atminc done at $(date)" > ${COMOUT_ATMOS_ANALYSIS}/${APREFIX}loginc.txt ################################################################################ diff --git a/scripts/exglobal_atmos_analysis_calc.sh b/scripts/exglobal_atmos_analysis_calc.sh index 423e800879..74455ee2cb 100755 --- a/scripts/exglobal_atmos_analysis_calc.sh +++ b/scripts/exglobal_atmos_analysis_calc.sh @@ -69,22 +69,22 @@ SENDDBN=${SENDDBN:-"NO"} # Guess files GPREFIX=${GPREFIX:-""} -ATMG03=${ATMG03:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf003.nc} -ATMG04=${ATMG04:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf004.nc} -ATMG05=${ATMG05:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf005.nc} -ATMGES=${ATMGES:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006.nc} -ATMG07=${ATMG07:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf007.nc} -ATMG08=${ATMG08:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf008.nc} -ATMG09=${ATMG09:-${COM_ATMOS_HISTORY_PREV}/${GPREFIX}atmf009.nc} +ATMG03=${ATMG03:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf003.nc} +ATMG04=${ATMG04:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf004.nc} +ATMG05=${ATMG05:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf005.nc} +ATMGES=${ATMGES:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf006.nc} +ATMG07=${ATMG07:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf007.nc} +ATMG08=${ATMG08:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf008.nc} +ATMG09=${ATMG09:-${COMIN_ATMOS_HISTORY_PREV}/${GPREFIX}atmf009.nc} # Analysis files export APREFIX=${APREFIX:-""} -SFCANL=${SFCANL:-${COM_ATMOS_ANALYSIS}/${APREFIX}sfcanl.nc} -DTFANL=${DTFANL:-${COM_ATMOS_ANALYSIS}/${APREFIX}dtfanl.nc} -ATMANL=${ATMANL:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmanl.nc} +SFCANL=${SFCANL:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}sfcanl.nc} +DTFANL=${DTFANL:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}dtfanl.nc} +ATMANL=${ATMANL:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmanl.nc} # Increment files -ATMINC=${ATMINC:-${COM_ATMOS_ANALYSIS}/${APREFIX}atminc.nc} +ATMINC=${ATMINC:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atminc.nc} # Set script / GSI control parameters DOHYBVAR=${DOHYBVAR:-"NO"} @@ -101,18 +101,18 @@ fi # Set 4D-EnVar specific variables if [ $DOHYBVAR = "YES" -a $l4densvar = ".true." -a $lwrite4danl = ".true." ]; then - ATMA03=${ATMA03:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma003.nc} - ATMI03=${ATMI03:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi003.nc} - ATMA04=${ATMA04:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma004.nc} - ATMI04=${ATMI04:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi004.nc} - ATMA05=${ATMA05:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma005.nc} - ATMI05=${ATMI05:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi005.nc} - ATMA07=${ATMA07:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma007.nc} - ATMI07=${ATMI07:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi007.nc} - ATMA08=${ATMA08:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma008.nc} - ATMI08=${ATMI08:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi008.nc} - ATMA09=${ATMA09:-${COM_ATMOS_ANALYSIS}/${APREFIX}atma009.nc} - ATMI09=${ATMI09:-${COM_ATMOS_ANALYSIS}/${APREFIX}atmi009.nc} + ATMA03=${ATMA03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma003.nc} + ATMI03=${ATMI03:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi003.nc} + ATMA04=${ATMA04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma004.nc} + ATMI04=${ATMI04:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi004.nc} + ATMA05=${ATMA05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma005.nc} + ATMI05=${ATMI05:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi005.nc} + ATMA07=${ATMA07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma007.nc} + ATMI07=${ATMI07:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi007.nc} + ATMA08=${ATMA08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma008.nc} + ATMI08=${ATMI08:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi008.nc} + ATMA09=${ATMA09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atma009.nc} + ATMI09=${ATMI09:-${COMOUT_ATMOS_ANALYSIS}/${APREFIX}atmi009.nc} fi ################################################################################ @@ -181,7 +181,7 @@ if [ $DOGAUSFCANL = "YES" ]; then export err=$?; err_chk fi -echo "${rCDUMP} ${PDY}${cyc} atmanl and sfcanl done at $(date)" > "${COM_ATMOS_ANALYSIS}/${APREFIX}loganl.txt" +echo "${rCDUMP} ${PDY}${cyc} atmanl and sfcanl done at $(date)" > "${COMOUT_ATMOS_ANALYSIS}/${APREFIX}loganl.txt" ################################################################################ # Postprocessing diff --git a/ush/calcanl_gfs.py b/ush/calcanl_gfs.py index 9dc6ff9fa6..f5e65f3824 100755 --- a/ush/calcanl_gfs.py +++ b/ush/calcanl_gfs.py @@ -346,9 +346,9 @@ def calcanl_gfs(DoIAU, l4DEnsVar, Write4Danl, ComOut, APrefix, DoIAU = gsi_utils.isTrue(os.getenv('DOIAU', 'NO')) l4DEnsVar = gsi_utils.isTrue(os.getenv('l4densvar', 'NO')) Write4Danl = gsi_utils.isTrue(os.getenv('lwrite4danl', 'NO')) - ComIn_Ges = os.getenv('COM_ATMOS_HISTORY_PREV', './') + ComIn_Ges = os.getenv('COMIN_ATMOS_HISTORY_PREV', './') GPrefix = os.getenv('GPREFIX', './') - ComOut = os.getenv('COM_ATMOS_ANALYSIS', './') + ComOut = os.getenv('COMOUT_ATMOS_ANALYSIS', './') APrefix = os.getenv('APREFIX', '') NThreads = os.getenv('NTHREADS_CHGRES', 1) FixDir = os.path.join(os.getenv('FIXgfs', './'), 'am') diff --git a/ush/calcinc_gfs.py b/ush/calcinc_gfs.py index cb334ac836..770ed79f3d 100755 --- a/ush/calcinc_gfs.py +++ b/ush/calcinc_gfs.py @@ -70,7 +70,7 @@ def calcinc_gfs(DoIAU, l4DEnsVar, Write4Danl, ComOut, APrefix, IAUHrs, DoIAU = gsi_utils.isTrue(os.getenv('DOIAU', 'NO')) l4DEnsVar = gsi_utils.isTrue(os.getenv('l4densvar', 'NO')) Write4Danl = gsi_utils.isTrue(os.getenv('lwrite4danl', 'NO')) - ComOut = os.getenv('COM_ATMOS_ANALYSIS', './') + ComOut = os.getenv('COMOUT_ATMOS_ANALYSIS', './') APrefix = os.getenv('APREFIX', '') NThreads = os.getenv('NTHREADS_CALCINC', 1) IMP_Physics = os.getenv('imp_physics', 11) diff --git a/ush/gaussian_sfcanl.sh b/ush/gaussian_sfcanl.sh index 4ac762824b..8b8f066cfe 100755 --- a/ush/gaussian_sfcanl.sh +++ b/ush/gaussian_sfcanl.sh @@ -77,7 +77,7 @@ # ${FIXWGTS} # ${FIXgfs}/am/global_hyblev.l65.txt # -# input data : ${COM_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile*.nc +# input data : ${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile*.nc # # output data: $PGMOUT # $PGMERR @@ -133,8 +133,7 @@ export REDERR=${REDERR:-'2>'} ${INISCRIPT:-} pwd=$(pwd) cd "${DATA}" || exit 99 -[[ -d "${COM_ATMOS_ANALYSIS}" ]] || mkdir -p "${COM_ATMOS_ANALYSIS}" -[[ -d "${COM_ATMOS_RESTART}" ]] || mkdir -p "${COM_ATMOS_RESTART}" +[[ -d "${COMOUT_ATMOS_ANALYSIS}" ]] || mkdir -p "${COMOUT_ATMOS_ANALYSIS}" ################################################################################ # Make surface analysis @@ -153,12 +152,12 @@ export OMP_NUM_THREADS=${OMP_NUM_THREADS_SFC:-1} ${NLN} "${FIXWGTS}" "./weights.nc" # input analysis tiles (with nst records) -${NLN} "${COM_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile1.nc" "./anal.tile1.nc" -${NLN} "${COM_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile2.nc" "./anal.tile2.nc" -${NLN} "${COM_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile3.nc" "./anal.tile3.nc" -${NLN} "${COM_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile4.nc" "./anal.tile4.nc" -${NLN} "${COM_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile5.nc" "./anal.tile5.nc" -${NLN} "${COM_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile6.nc" "./anal.tile6.nc" +${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile1.nc" "./anal.tile1.nc" +${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile2.nc" "./anal.tile2.nc" +${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile3.nc" "./anal.tile3.nc" +${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile4.nc" "./anal.tile4.nc" +${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile5.nc" "./anal.tile5.nc" +${NLN} "${COMIN_ATMOS_RESTART}/${PDY}.${cyc}0000.sfcanl_data.tile6.nc" "./anal.tile6.nc" # input orography tiles ${NLN} "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile1.nc" "./orog.tile1.nc" @@ -171,7 +170,7 @@ ${NLN} "${FIXorog}/${CASE}/${CASE}.mx${OCNRES}_oro_data.tile6.nc" "./orog.tile6. ${NLN} "${SIGLEVEL}" "./vcoord.txt" # output gaussian global surface analysis files -${NLN} "${COM_ATMOS_ANALYSIS}/${APREFIX}sfcanl.nc" "./sfc.gaussian.analysis.file" +${NLN} "${COMOUT_ATMOS_ANALYSIS}/${APREFIX}sfcanl.nc" "./sfc.gaussian.analysis.file" # Namelist uses booleans now if [[ ${DONST} == "YES" ]]; then do_nst='.true.'; else do_nst='.false.'; fi From 0c7a3c6c42345b52d580a2b1c95546b5f1cdbe05 Mon Sep 17 00:00:00 2001 From: DavidNew-NOAA <134300700+DavidNew-NOAA@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:22:02 -0500 Subject: [PATCH 02/10] Turn C96C48_ufs_hybatmDA and C48mx500_3DVarAOWCDA into a regression test (#3120) This PR is a companion to NOAA-EMC/GDASApp#1365 It turns ```C96C48_ufs_hybatmDA``` and ```C48mx500_3DVarAOWCDA``` into a regression test using the JEDI application testing feature. This feature is turned on using the new ```DO_TEST_MODE``` parameter added to ```config.base``` in GW PR [#3115](https://github.com/NOAA-EMC/global-workflow/pull/3115). This parameter is set to ```"YES"``` in the yaml defaults for the JEDI-based CI tests in GW. The motivation for this PR is a need to catch changes in JEDI which alter the outputs of our applications. --------- Co-authored-by: CoryMartin-NOAA Co-authored-by: RussTreadon-NOAA <26926959+RussTreadon-NOAA@users.noreply.github.com> --- ci/cases/yamls/soca_gfs_defaults_ci.yaml | 2 ++ ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml | 7 +++++++ parm/config/gfs/config.atmanl | 1 + parm/config/gfs/config.atmensanl | 1 + parm/config/gfs/config.marineanl | 1 + parm/config/gfs/config.resources.ORION | 7 +++++-- parm/config/gfs/yaml/defaults.yaml | 3 +++ parm/gdas/atmanl_jedi_config.yaml.j2 | 2 +- parm/gdas/atmensanl_jedi_config.yaml.j2 | 2 +- sorc/gdas.cd | 2 +- sorc/link_workflow.sh | 1 - ush/python/pygfs/task/marine_analysis.py | 6 +++++- 12 files changed, 28 insertions(+), 7 deletions(-) diff --git a/ci/cases/yamls/soca_gfs_defaults_ci.yaml b/ci/cases/yamls/soca_gfs_defaults_ci.yaml index c18eac9196..69971537c2 100644 --- a/ci/cases/yamls/soca_gfs_defaults_ci.yaml +++ b/ci/cases/yamls/soca_gfs_defaults_ci.yaml @@ -7,3 +7,5 @@ base: marineanl: SOCA_NINNER: 1 DO_TEST_MODE: "YES" +marineanl: + JCB_ALGO_YAML_VAR: "{{ HOMEgfs }}/sorc/gdas.cd/test/gw-ci/soca/jcb-prototype_3dfgat_3DVarAOWCDA.yaml.j2" diff --git a/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml b/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml index b956066f6b..b7344e8e35 100644 --- a/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml +++ b/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml @@ -5,10 +5,17 @@ base: DO_JEDIATMVAR: "YES" DO_JEDIATMENS: "YES" ACCOUNT: {{ 'HPC_ACCOUNT' | getenv }} + DO_TEST_MODE: "YES" atmanl: + JCB_ALGO_YAML_VAR: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jcb-prototype_3dvar_ufs_hybatmDA.yaml.j2" + JCB_ALGO_YAML_FV3INC: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jcb-prototype_3dvar-fv3inc_ufs_hybatmDA.yaml.j2" LAYOUT_X_ATMANL: 4 LAYOUT_Y_ATMANL: 4 atmensanl: + JCB_ALGO_YAML_LETKF: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jcb-prototype_lgetkf_ufs_hybatmDA.yaml.j2" + JCB_ALGO_YAML_OBS: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jcb-prototype_lgetkf_observer_ufs_hybatmDA.yaml.j2" + JCB_ALGO_YAML_SOL: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jcb-prototype_lgetkf_solver_ufs_hybatmDA.yaml.j2" + JCB_ALGO_YAML_FV3INC: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jcb-prototype_lgetkf-fv3inc_ufs_hybatmDA.yaml.j2" LAYOUT_X_ATMENSANL: 4 LAYOUT_Y_ATMENSANL: 4 esfc: diff --git a/parm/config/gfs/config.atmanl b/parm/config/gfs/config.atmanl index 1d700a479c..df35a41d89 100644 --- a/parm/config/gfs/config.atmanl +++ b/parm/config/gfs/config.atmanl @@ -6,6 +6,7 @@ echo "BEGIN: config.atmanl" export JCB_ALGO_YAML_VAR=@JCB_ALGO_YAML_VAR@ +export JCB_ALGO_YAML_FV3INC=@JCB_ALGO_YAML_FV3INC@ export STATICB_TYPE=@STATICB_TYPE@ export LOCALIZATION_TYPE="bump" diff --git a/parm/config/gfs/config.atmensanl b/parm/config/gfs/config.atmensanl index 2726f655bd..77f5e2ee86 100644 --- a/parm/config/gfs/config.atmensanl +++ b/parm/config/gfs/config.atmensanl @@ -8,6 +8,7 @@ echo "BEGIN: config.atmensanl" export JCB_ALGO_YAML_LETKF=@JCB_ALGO_YAML_LETKF@ export JCB_ALGO_YAML_OBS=@JCB_ALGO_YAML_OBS@ export JCB_ALGO_YAML_SOL=@JCB_ALGO_YAML_SOL@ +export JCB_ALGO_YAML_FV3INC=@JCB_ALGO_YAML_FV3INC@ export INTERP_METHOD='barycentric' diff --git a/parm/config/gfs/config.marineanl b/parm/config/gfs/config.marineanl index 0b55fa447d..b0fbbedb54 100644 --- a/parm/config/gfs/config.marineanl +++ b/parm/config/gfs/config.marineanl @@ -6,6 +6,7 @@ echo "BEGIN: config.marineanl" export JEDI_CONFIG_YAML="${PARMgfs}/gdas/soca_bmat_jedi_config.yaml.j2" +export JCB_ALGO_YAML_VAR=@JCB_ALGO_YAML_VAR@ export MARINE_OBS_YAML_DIR="${PARMgfs}/gdas/soca/obs/config" export MARINE_OBS_LIST_YAML=@SOCA_OBS_LIST@ diff --git a/parm/config/gfs/config.resources.ORION b/parm/config/gfs/config.resources.ORION index fceb8feeb1..a10588b6d0 100644 --- a/parm/config/gfs/config.resources.ORION +++ b/parm/config/gfs/config.resources.ORION @@ -30,10 +30,13 @@ case ${step} in export walltime="00:45:00" ;; "atmensanlobs") - # Run on 8 nodes for memory requirement - export tasks_per_node=8 + # Run on 12 nodes for memory requirement + export tasks_per_node=12 export walltime="00:45:00" ;; + "atmensanlsol") + export tasks_per_node=12 + ;; *) ;; esac diff --git a/parm/config/gfs/yaml/defaults.yaml b/parm/config/gfs/yaml/defaults.yaml index c9ecd11f5b..55f4b03f50 100644 --- a/parm/config/gfs/yaml/defaults.yaml +++ b/parm/config/gfs/yaml/defaults.yaml @@ -27,6 +27,7 @@ base: atmanl: JCB_ALGO_YAML_VAR: "${PARMgfs}/gdas/atm/jcb-prototype_3dvar.yaml.j2" + JCB_ALGO_YAML_FV3INC: "${PARMgfs}/gdas/atm/jcb-prototype_3dvar-fv3inc.yaml.j2" STATICB_TYPE: "gsibec" LAYOUT_X_ATMANL: 8 LAYOUT_Y_ATMANL: 8 @@ -37,6 +38,7 @@ atmensanl: JCB_ALGO_YAML_LETKF: "${PARMgfs}/gdas/atm/jcb-prototype_lgetkf.yaml.j2" JCB_ALGO_YAML_OBS: "${PARMgfs}/gdas/atm/jcb-prototype_lgetkf_observer.yaml.j2" JCB_ALGO_YAML_SOL: "${PARMgfs}/gdas/atm/jcb-prototype_lgetkf_solver.yaml.j2" + JCB_ALGO_YAML_FV3INC: "${PARMgfs}/gdas/atm/jcb-prototype_lgetkf-fv3inc.yaml.j2" LAYOUT_X_ATMENSANL: 8 LAYOUT_Y_ATMENSANL: 8 IO_LAYOUT_X: 1 @@ -54,6 +56,7 @@ marineanl: SOCA_INPUT_FIX_DIR: "${FIXgfs}/gdas/soca/72x35x25/soca" SOCA_OBS_LIST: "${PARMgfs}/gdas/soca/obs/obs_list.yaml" # TODO: This is also repeated in oceanprepobs SOCA_NINNER: 100 + JCB_ALGO_YAML_VAR: "${PARMgfs}/gdas/soca/marine-jcb-3dfgat.yaml.j2" prepoceanobs: SOCA_INPUT_FIX_DIR: "${FIXgfs}/gdas/soca/72x35x25/soca" diff --git a/parm/gdas/atmanl_jedi_config.yaml.j2 b/parm/gdas/atmanl_jedi_config.yaml.j2 index 4046ba0931..7a700c5cf6 100644 --- a/parm/gdas/atmanl_jedi_config.yaml.j2 +++ b/parm/gdas/atmanl_jedi_config.yaml.j2 @@ -10,4 +10,4 @@ atmanlfv3inc: exe_src: '{{ EXECgfs }}/fv3jedi_fv3inc.x' mpi_cmd: '{{ APRUN_ATMANLFV3INC }}' jcb_base_yaml: '{{ PARMgfs }}/gdas/atm/jcb-base.yaml.j2' - jcb_algo: fv3jedi_fv3inc_variational + jcb_algo_yaml: '{{ JCB_ALGO_YAML_FV3INC }}' diff --git a/parm/gdas/atmensanl_jedi_config.yaml.j2 b/parm/gdas/atmensanl_jedi_config.yaml.j2 index 9ab2ec6ace..e5acba5db9 100644 --- a/parm/gdas/atmensanl_jedi_config.yaml.j2 +++ b/parm/gdas/atmensanl_jedi_config.yaml.j2 @@ -17,7 +17,7 @@ atmensanlfv3inc: exe_src: '{{ EXECgfs }}/fv3jedi_fv3inc.x' mpi_cmd: '{{ APRUN_ATMENSANLFV3INC }}' jcb_base_yaml: '{{ PARMgfs }}/gdas/atm/jcb-base.yaml.j2' - jcb_algo: fv3jedi_fv3inc_lgetkf + jcb_algo_yaml: '{{ JCB_ALGO_YAML_FV3INC }}' atmensanlletkf: rundir: '{{ DATA }}' exe_src: '{{ EXECgfs }}/gdas.x' diff --git a/sorc/gdas.cd b/sorc/gdas.cd index d91663bb58..d9b40c9bde 160000 --- a/sorc/gdas.cd +++ b/sorc/gdas.cd @@ -1 +1 @@ -Subproject commit d91663bb585fbfa30db99d6126a1d4f24906b69b +Subproject commit d9b40c9bde1e5e70451f309a5e010267aaadba00 diff --git a/sorc/link_workflow.sh b/sorc/link_workflow.sh index b35b7ff35a..a6d55d462c 100755 --- a/sorc/link_workflow.sh +++ b/sorc/link_workflow.sh @@ -242,7 +242,6 @@ if [[ -d "${HOMEgfs}/sorc/gdas.cd/build" ]]; then cd "${HOMEgfs}/ush" || exit 1 ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/soca" . ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ufsda" . - ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/jediinc2fv3.py" . ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ioda/bufr2ioda/gen_bufr2ioda_json.py" . ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ioda/bufr2ioda/gen_bufr2ioda_yaml.py" . ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/ush/ioda/bufr2ioda/run_bufr2ioda.py" . diff --git a/ush/python/pygfs/task/marine_analysis.py b/ush/python/pygfs/task/marine_analysis.py index ebb1502634..dd48c9f80f 100644 --- a/ush/python/pygfs/task/marine_analysis.py +++ b/ush/python/pygfs/task/marine_analysis.py @@ -214,6 +214,10 @@ def _prep_variational_yaml(self: Task) -> None: envconfig_jcb['cyc'] = os.getenv('cyc') envconfig_jcb['SOCA_NINNER'] = self.task_config.SOCA_NINNER envconfig_jcb['obs_list'] = ['adt_rads_all'] + envconfig_jcb['HOMEgfs'] = self.task_config.HOMEgfs + envconfig_jcb['DO_TEST_MODE'] = self.task_config.DO_TEST_MODE + envconfig_jcb['RUN'] = self.task_config.RUN + envconfig_jcb['current_cycle'] = self.task_config.current_cycle envconfig_jcb['MOM6_LEVS'] = mdau.get_mom6_levels(str(self.task_config.OCNRES).zfill(3)) # Write obs_list_short @@ -222,7 +226,7 @@ def _prep_variational_yaml(self: Task) -> None: # Render the JCB configuration files jcb_base_yaml = os.path.join(self.task_config.PARMsoca, 'marine-jcb-base.yaml') - jcb_algo_yaml = os.path.join(self.task_config.PARMsoca, 'marine-jcb-3dfgat.yaml.j2') + jcb_algo_yaml = self.task_config.JCB_ALGO_YAML_VAR jcb_base_config = parse_j2yaml(path=jcb_base_yaml, data=envconfig_jcb) jcb_algo_config = parse_j2yaml(path=jcb_algo_yaml, data=envconfig_jcb) From 2b11995b80d07676ff32179de5aec730d71877c7 Mon Sep 17 00:00:00 2001 From: TerrenceMcGuinness-NOAA Date: Fri, 13 Dec 2024 10:13:08 -0500 Subject: [PATCH 03/10] Update HPC_ACCOUNT on Hercules to fv3-cpu (#3164) Hotfix to update CI allocation to run on **fv3-cpu** for Hercules Also updated variable name to HPC_ACCOUNT for Gaea as it was set to SLURM_ACCOUNT -- Co-authored-by: Terry McGUinness --- ci/platforms/config.gaea | 2 +- ci/platforms/config.hercules | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/platforms/config.gaea b/ci/platforms/config.gaea index cce109d494..f4b8cc13ec 100644 --- a/ci/platforms/config.gaea +++ b/ci/platforms/config.gaea @@ -3,6 +3,6 @@ export GFS_CI_ROOT=/gpfs/f5/epic/proj-shared/global/GFS_CI_ROOT export ICSDIR_ROOT=/gpfs/f5/epic/proj-shared/global/glopara/data/ICSDIR export STMP="/gpfs/f5/epic/scratch/${USER}" -export SLURM_ACCOUNT=ufs-ard +export HPC_ACCOUNT=ufs-ard export max_concurrent_cases=5 export max_concurrent_pr=4 diff --git a/ci/platforms/config.hercules b/ci/platforms/config.hercules index 5329adae49..4d5af21c78 100644 --- a/ci/platforms/config.hercules +++ b/ci/platforms/config.hercules @@ -2,7 +2,7 @@ export GFS_CI_ROOT=/work2/noaa/stmp/GFS_CI_ROOT/HERCULES export ICSDIR_ROOT=/work/noaa/global/glopara/data/ICSDIR -export HPC_ACCOUNT=nems +export HPC_ACCOUNT=fv3-cpu export max_concurrent_cases=5 export max_concurrent_pr=4 From 0db859eaa6899bd4d79f4196f49c9a8e941dd2d3 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Fri, 13 Dec 2024 11:48:39 -0500 Subject: [PATCH 04/10] Enable traditional threading as an option (#3149) In a previous PR, stubs were added to enable traditional threading in the UFS. This PR takes the next step to execute the model with traditional threading. Specifically; 1. Do not use the `_esmf` `ufs_configure` file for traditional threading. This sets the `globalResourceControl` to `false` (traditional threading) ... this was done in the previous PR 2. when calculating components pet bounds do not multiply with number of threads also in `ufs_configure` ... this PR 3. `export OMP_NUM_THREADS=$UFS_THREADS` ... this was done in the previous PR The default behaviour to use ESMF-managed threading is retained. Traditional threading can be achieved by toggling `USE_ESMF_THREADING` flag in `config.fcst` Closes #3122 - as in allows the model to be configured to run w/ traditional threading. Testing on C768 S2SW was successful on Hercules (This was previously reported to be failing) The use of traditional threading will be inefficient for model components that are not thread-enabled and supported e.g. MOM6 and CICE6, but since they require smaller number of tasks compared to ATM or WAV, the CPU 'waste' is not huge. --- parm/config/gefs/config.resources | 63 ++++++++++++++++++++++-------- parm/config/gfs/config.resources | 63 ++++++++++++++++++++++-------- ush/parsing_model_configure_FV3.sh | 2 +- 3 files changed, 95 insertions(+), 33 deletions(-) diff --git a/parm/config/gefs/config.resources b/parm/config/gefs/config.resources index a730ea401c..e1b9a036de 100644 --- a/parm/config/gefs/config.resources +++ b/parm/config/gefs/config.resources @@ -110,22 +110,33 @@ case ${step} in [[ "${DO_ICE}" == "YES" ]] && nthreads_cice6=1 fi - # PETS for the atmosphere dycore - (( FV3PETS = ntasks_fv3 * nthreads_fv3 )) - echo "FV3 using (nthreads, PETS) = (${nthreads_fv3}, ${FV3PETS})" + # FV3 + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( FV3THREADS = nthreads_fv3 )) + (( FV3PETS = ntasks_fv3 * nthreads_fv3 )) + else + (( FV3THREADS = UFS_THREADS )) + (( FV3PETS = ntasks_fv3 )) + fi + echo "FV3 using (nthreads, PETS) = (${FV3THREADS}, ${FV3PETS})" - # PETS for quilting + # Write grid component + QUILTPETS=0; QUILTTHREADS=0 if [[ "${QUILTING:-}" == ".true." ]]; then - (( QUILTPETS = ntasks_quilt * nthreads_fv3 )) + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( QUILTTHREADS = nthreads_fv3 )) + (( QUILTPETS = ntasks_quilt * nthreads_fv3 )) + else + (( QUILTTHREADS = UFS_THREADS )) + (( QUILTPETS = ntasks_quilt )) + fi (( WRTTASK_PER_GROUP = WRTTASK_PER_GROUP_PER_THREAD )) export WRTTASK_PER_GROUP - else - QUILTPETS=0 fi - echo "QUILT using (nthreads, PETS) = (${nthreads_fv3}, ${QUILTPETS})" + echo "QUILT using (nthreads, PETS) = (${QUILTTHREADS}, ${QUILTPETS})" # Total PETS for the atmosphere component - ATMTHREADS=${nthreads_fv3} + ATMTHREADS=${FV3THREADS} (( ATMPETS = FV3PETS + QUILTPETS )) export ATMPETS ATMTHREADS echo "FV3ATM using (nthreads, PETS) = (${ATMTHREADS}, ${ATMPETS})" @@ -133,6 +144,7 @@ case ${step} in # Total PETS for the coupled model (starting w/ the atmosphere) NTASKS_TOT=${ATMPETS} + # Mediator # The mediator PETS can overlap with other components, usually it lands on the atmosphere tasks. # However, it is suggested limiting mediator PETS to 300, as it may cause the slow performance. # See https://docs.google.com/document/d/1bKpi-52t5jIfv2tuNHmQkYUe3hkKsiG_DG_s6Mnukog/edit @@ -143,6 +155,7 @@ case ${step} in export MEDPETS MEDTHREADS echo "MEDIATOR using (threads, PETS) = (${MEDTHREADS}, ${MEDPETS})" + # GOCART CHMPETS=0; CHMTHREADS=0 if [[ "${DO_AERO_FCST}" == "YES" ]]; then # GOCART shares the same grid and forecast tasks as FV3 (do not add write grid component tasks). @@ -153,28 +166,46 @@ case ${step} in fi export CHMPETS CHMTHREADS + # Waves WAVPETS=0; WAVTHREADS=0 if [[ "${DO_WAVE}" == "YES" ]]; then - (( WAVPETS = ntasks_ww3 * nthreads_ww3 )) - (( WAVTHREADS = nthreads_ww3 )) + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( WAVTHREADS = nthreads_ww3 )) + (( WAVPETS = ntasks_ww3 * nthreads_ww3 )) + else + (( WAVTHREADS = UFS_THREADS )) + (( WAVPETS = ntasks_ww3 )) + fi echo "WW3 using (threads, PETS) = (${WAVTHREADS}, ${WAVPETS})" (( NTASKS_TOT = NTASKS_TOT + WAVPETS )) fi export WAVPETS WAVTHREADS + # Ocean OCNPETS=0; OCNTHREADS=0 if [[ "${DO_OCN}" == "YES" ]]; then - (( OCNPETS = ntasks_mom6 * nthreads_mom6 )) - (( OCNTHREADS = nthreads_mom6 )) + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( OCNTHREADS = nthreads_mom6 )) + (( OCNPETS = ntasks_mom6 * nthreads_mom6 )) + else + (( OCNTHREADS = UFS_THREADS )) + (( OCNPETS = ntasks_mom6 )) + fi echo "MOM6 using (threads, PETS) = (${OCNTHREADS}, ${OCNPETS})" (( NTASKS_TOT = NTASKS_TOT + OCNPETS )) fi export OCNPETS OCNTHREADS + # Ice ICEPETS=0; ICETHREADS=0 if [[ "${DO_ICE}" == "YES" ]]; then - (( ICEPETS = ntasks_cice6 * nthreads_cice6 )) - (( ICETHREADS = nthreads_cice6 )) + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( ICETHREADS = nthreads_cice6 )) + (( ICEPETS = ntasks_cice6 * nthreads_cice6 )) + else + (( ICETHREADS = UFS_THREADS )) + (( ICEPETS = ntasks_cice6 )) + fi echo "CICE6 using (threads, PETS) = (${ICETHREADS}, ${ICEPETS})" (( NTASKS_TOT = NTASKS_TOT + ICEPETS )) fi @@ -184,7 +215,7 @@ case ${step} in declare -x "ntasks"="${NTASKS_TOT}" declare -x "threads_per_task"="${UFS_THREADS}" - declare -x "tasks_per_node"="${max_tasks_per_node}" + tasks_per_node=$(( max_tasks_per_node / threads_per_task )) case "${CASE}" in "C48" | "C96" | "C192") diff --git a/parm/config/gfs/config.resources b/parm/config/gfs/config.resources index bc2a89054e..e642082290 100644 --- a/parm/config/gfs/config.resources +++ b/parm/config/gfs/config.resources @@ -775,22 +775,33 @@ case ${step} in export npy_nest=${npy_nest:-961} fi - # PETS for the atmosphere dycore - (( FV3PETS = ntasks_fv3 * nthreads_fv3 )) - echo "FV3 using (nthreads, PETS) = (${nthreads_fv3}, ${FV3PETS})" + # FV3 + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( FV3THREADS = nthreads_fv3 )) + (( FV3PETS = ntasks_fv3 * nthreads_fv3 )) + else + (( FV3THREADS = UFS_THREADS )) + (( FV3PETS = ntasks_fv3 )) + fi + echo "FV3 using (nthreads, PETS) = (${FV3THREADS}, ${FV3PETS})" - # PETS for quilting + # Write grid component + QUILTPETS=0; QUILTTHREADS=0 if [[ "${QUILTING:-}" == ".true." ]]; then - (( QUILTPETS = ntasks_quilt * nthreads_fv3 )) + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( QUILTTHREADS = nthreads_fv3 )) + (( QUILTPETS = ntasks_quilt * nthreads_fv3 )) + else + (( QUILTTHREADS = UFS_THREADS )) + (( QUILTPETS = ntasks_quilt )) + fi (( WRTTASK_PER_GROUP = WRTTASK_PER_GROUP_PER_THREAD )) export WRTTASK_PER_GROUP - else - QUILTPETS=0 fi - echo "QUILT using (nthreads, PETS) = (${nthreads_fv3}, ${QUILTPETS})" + echo "QUILT using (nthreads, PETS) = (${QUILTTHREADS}, ${QUILTPETS})" # Total PETS for the atmosphere component - ATMTHREADS=${nthreads_fv3} + ATMTHREADS=${FV3THREADS} (( ATMPETS = FV3PETS + QUILTPETS )) export ATMPETS ATMTHREADS echo "FV3ATM using (nthreads, PETS) = (${ATMTHREADS}, ${ATMPETS})" @@ -798,6 +809,7 @@ case ${step} in # Total PETS for the coupled model (starting w/ the atmosphere) NTASKS_TOT=${ATMPETS} + # Mediator # The mediator PETS can overlap with other components, usually it lands on the atmosphere tasks. # However, it is suggested limiting mediator PETS to 300, as it may cause the slow performance. # See https://docs.google.com/document/d/1bKpi-52t5jIfv2tuNHmQkYUe3hkKsiG_DG_s6Mnukog/edit @@ -808,6 +820,7 @@ case ${step} in export MEDPETS MEDTHREADS echo "MEDIATOR using (threads, PETS) = (${MEDTHREADS}, ${MEDPETS})" + # GOCART CHMPETS=0; CHMTHREADS=0 if [[ "${DO_AERO_FCST}" == "YES" ]]; then # GOCART shares the same grid and forecast tasks as FV3 (do not add write grid component tasks). @@ -818,28 +831,46 @@ case ${step} in fi export CHMPETS CHMTHREADS + # Waves WAVPETS=0; WAVTHREADS=0 if [[ "${DO_WAVE}" == "YES" ]]; then - (( WAVPETS = ntasks_ww3 * nthreads_ww3 )) - (( WAVTHREADS = nthreads_ww3 )) + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( WAVTHREADS = nthreads_ww3 )) + (( WAVPETS = ntasks_ww3 * nthreads_ww3 )) + else + (( WAVTHREADS = UFS_THREADS )) + (( WAVPETS = ntasks_ww3 )) + fi echo "WW3 using (threads, PETS) = (${WAVTHREADS}, ${WAVPETS})" (( NTASKS_TOT = NTASKS_TOT + WAVPETS )) fi export WAVPETS WAVTHREADS + # Ocean OCNPETS=0; OCNTHREADS=0 if [[ "${DO_OCN}" == "YES" ]]; then - (( OCNPETS = ntasks_mom6 * nthreads_mom6 )) - (( OCNTHREADS = nthreads_mom6 )) + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( OCNTHREADS = nthreads_mom6 )) + (( OCNPETS = ntasks_mom6 * nthreads_mom6 )) + else + (( OCNTHREADS = UFS_THREADS )) + (( OCNPETS = ntasks_mom6 )) + fi echo "MOM6 using (threads, PETS) = (${OCNTHREADS}, ${OCNPETS})" (( NTASKS_TOT = NTASKS_TOT + OCNPETS )) fi export OCNPETS OCNTHREADS + # Ice ICEPETS=0; ICETHREADS=0 if [[ "${DO_ICE}" == "YES" ]]; then - (( ICEPETS = ntasks_cice6 * nthreads_cice6 )) - (( ICETHREADS = nthreads_cice6 )) + if [[ "${USE_ESMF_THREADING:-}" == "YES" ]]; then + (( ICETHREADS = nthreads_cice6 )) + (( ICEPETS = ntasks_cice6 * nthreads_cice6 )) + else + (( ICETHREADS = UFS_THREADS )) + (( ICEPETS = ntasks_cice6 )) + fi echo "CICE6 using (threads, PETS) = (${ICETHREADS}, ${ICEPETS})" (( NTASKS_TOT = NTASKS_TOT + ICEPETS )) fi @@ -849,7 +880,7 @@ case ${step} in declare -x "ntasks"="${NTASKS_TOT}" declare -x "threads_per_task"="${UFS_THREADS}" - declare -x "tasks_per_node"="${max_tasks_per_node}" + tasks_per_node=$(( max_tasks_per_node / threads_per_task )) case "${CASE}" in "C48" | "C96" | "C192") diff --git a/ush/parsing_model_configure_FV3.sh b/ush/parsing_model_configure_FV3.sh index 7cf7bf8662..8033d7686a 100755 --- a/ush/parsing_model_configure_FV3.sh +++ b/ush/parsing_model_configure_FV3.sh @@ -26,7 +26,7 @@ local FHROT=${IAU_FHROT:-0} local DT_ATMOS=${DELTIM} local RESTART_INTERVAL="${FV3_RESTART_FH[*]}" # QUILTING -local QUILTING_RESTART=".true." +local QUILTING_RESTART="${QUILTING_RESTART:-${QUILTING}}" local WRITE_GROUP=${WRITE_GROUP:-1} local WRTTASK_PER_GROUP=${WRTTASK_PER_GROUP:-24} local ITASKS=1 From 93719beb030ab1689c69009b26b1ce83833bb830 Mon Sep 17 00:00:00 2001 From: Jessica Meixner Date: Sat, 14 Dec 2024 03:16:23 +0000 Subject: [PATCH 05/10] Update ufs-weather-model to 2024-12-06 commit (#3145) This PR updates ufs-weather-model hash to the latest commit which addresses an issue seen in an earlier commit (see: https://github.com/NOAA-EMC/global-workflow/issues/3110) Note this includes the PR that enables PIO for WW3, however additional work is required to use this feature. Another notable PR update is for a PIO finalize bug in CICE which also required updates to ice_in Resolves #3110 --- sorc/build_ww3prepost.sh | 1 + sorc/link_workflow.sh | 6 ++---- sorc/ufs_model.fd | 2 +- ush/parsing_namelists_CICE.sh | 3 ++- ush/parsing_ufs_configure.sh | 10 ++++++++++ 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/sorc/build_ww3prepost.sh b/sorc/build_ww3prepost.sh index 67ee5e1dc2..5c86774067 100755 --- a/sorc/build_ww3prepost.sh +++ b/sorc/build_ww3prepost.sh @@ -78,6 +78,7 @@ sed -e "s/DIST/SHRD/g"\ -e "s/OMPH / /g"\ -e "s/MPIT / /g"\ -e "s/MPI / /g"\ + -e "s/PIO / /g"\ -e "s/B4B / /g"\ -e "s/PDLIB / /g"\ -e "s/SCOTCH / /g"\ diff --git a/sorc/link_workflow.sh b/sorc/link_workflow.sh index a6d55d462c..a43fd5b3f4 100755 --- a/sorc/link_workflow.sh +++ b/sorc/link_workflow.sh @@ -144,10 +144,8 @@ cd "${HOMEgfs}/parm/ufs" || exit 1 ${LINK_OR_COPY} "${HOMEgfs}/sorc/ufs_model.fd/tests/parm/noahmptable.tbl" . cd "${HOMEgfs}/parm/post" || exit 1 -for file in params_grib2_tbl_new nam_micro_lookup.dat -do - ${LINK_OR_COPY} "${HOMEgfs}/sorc/upp.fd/parm/${file}" . -done +${LINK_OR_COPY} "${HOMEgfs}/sorc/upp.fd/parm/params_grib2_tbl_new" . +${LINK_OR_COPY} "${HOMEgfs}/sorc/upp.fd/fix/nam_micro_lookup.dat" . for dir in gfs gefs sfs do ${LINK_OR_COPY} "${HOMEgfs}/sorc/upp.fd/parm/${dir}" . diff --git a/sorc/ufs_model.fd b/sorc/ufs_model.fd index 6a4e09e947..63ace62a36 160000 --- a/sorc/ufs_model.fd +++ b/sorc/ufs_model.fd @@ -1 +1 @@ -Subproject commit 6a4e09e94773ffa39ce7ab6a54a885efada91f21 +Subproject commit 63ace62a36a263f03b914a92fc5536509e862dbc diff --git a/ush/parsing_namelists_CICE.sh b/ush/parsing_namelists_CICE.sh index 3822094c97..16c89ee80d 100755 --- a/ush/parsing_namelists_CICE.sh +++ b/ush/parsing_namelists_CICE.sh @@ -70,7 +70,8 @@ local CICE_RESTART_FORMAT="pnetcdf2" local CICE_DUMPFREQ="y" # "h","d","m" or "y" for restarts at intervals of "hours", "days", "months" or "years" local CICE_DUMPFREQ_N=10000 # Set this to a really large value, as cice, mom6 and cmeps restart interval is controlled by ufs.configure local CICE_DIAGFREQ=$(( 86400 / DT_CICE )) # frequency of diagnostic output in timesteps, recommended for 1x per day -local CICE_HISTFREQ_N="0, 0, ${FHOUT_ICE}, 1, 1" +local CICE_HISTFREQ_N="0, 0, ${FHOUT_ICE}, 0, 1" +local CICE_hist_suffix="'x','x','x','x','x'" if [[ "${RUN}" =~ "gdas" ]]; then local CICE_HIST_AVG=".false., .false., .false., .false., .false." # DA needs instantaneous else diff --git a/ush/parsing_ufs_configure.sh b/ush/parsing_ufs_configure.sh index 062b40591e..d8276476c4 100755 --- a/ush/parsing_ufs_configure.sh +++ b/ush/parsing_ufs_configure.sh @@ -77,6 +77,16 @@ if [[ "${cplwav}" = ".true." ]]; then local MULTIGRID="${waveMULTIGRID}" local WW3_user_sets_restname="false" + local WW3_user_histname="false" + local WW3_historync="false" + local WW3_restartnc="false" + local WW3_restart_from_binary="false" + local WW3_PIO_FORMAT="pnetcdf" + local WW3_PIO_IOTASKS=-99 + local WW3_PIO_STRIDE=4 + local WW3_PIO_REARR="box" + local WW3_PIO_ROOT=-99 + fi if [[ "${cplchm}" = ".true." ]]; then From bef3e0baaec85a4323055c5f2ef6b286b241c2a6 Mon Sep 17 00:00:00 2001 From: Cory Martin Date: Fri, 13 Dec 2024 22:20:16 -0500 Subject: [PATCH 06/10] Switch Aerosol DA to use JCB and Jedi class (#3125) This PR switches to using JCB for aerosol DA YAML generation + makes use of the Jedi class refactoring already done by @DavidNew-NOAA for the atmospheric JEDI-based DA. Resolves #3035 Note this PR is in draft for 2 reasons. 1) Need associated GDASApp PR to be opened and merged first and 2) requires some fix file updates. This will be coordinated with an issue and linked to this PR once @andytangborn is satisfied with a first-attempt at the fix files. --------- Co-authored-by: RussTreadon-NOAA Co-authored-by: DavidNew-NOAA --- parm/config/gfs/config.aeroanl | 16 +- parm/config/gfs/config.aeroanlgenb | 5 +- parm/gdas/aero_bmat_jedi_config.yaml.j2 | 19 ++ parm/gdas/aero_finalize_bmatrix_bkg.yaml.j2 | 4 +- parm/gdas/aero_finalize_variational.yaml.j2 | 2 +- parm/gdas/aero_stage_bmatrix_bkg.yaml.j2 | 9 +- parm/gdas/aeroanl_jedi_config.yaml.j2 | 7 + .../exgdas_aero_analysis_generate_bmatrix.py | 12 +- scripts/exglobal_aero_analysis_finalize.py | 2 + scripts/exglobal_aero_analysis_initialize.py | 2 + scripts/exglobal_aero_analysis_variational.py | 4 +- sorc/gdas.cd | 2 +- ush/python/pygfs/__init__.py | 1 - ush/python/pygfs/task/aero_analysis.py | 186 ++++++----- ush/python/pygfs/task/aero_bmatrix.py | 296 +++++------------- ush/python/pygfs/task/bmatrix.py | 28 -- 16 files changed, 238 insertions(+), 357 deletions(-) create mode 100644 parm/gdas/aero_bmat_jedi_config.yaml.j2 create mode 100644 parm/gdas/aeroanl_jedi_config.yaml.j2 delete mode 100644 ush/python/pygfs/task/bmatrix.py diff --git a/parm/config/gfs/config.aeroanl b/parm/config/gfs/config.aeroanl index 5ac03bd7ee..591d9490ee 100644 --- a/parm/config/gfs/config.aeroanl +++ b/parm/config/gfs/config.aeroanl @@ -7,10 +7,10 @@ echo "BEGIN: config.aeroanl" # define analysis resolution based on deterministic res case ${CASE} in - "C1152" | "C768" | "C384" | "C192") - CASE_ANL="C192" + "C1152" | "C768" | "C384") + CASE_ANL="C384" ;; - "C96" | "C48") + "C192" | "C96" | "C48") CASE_ANL=${CASE} ;; *) @@ -18,14 +18,16 @@ case ${CASE} in exit 4 esac export CASE_ANL -export OBS_LIST="${PARMgfs}/gdas/aero/obs/lists/gdas_aero.yaml.j2" +export JCB_ALGO_YAML_VAR=${PARMgfs}/gdas/aero/jcb-prototype_3dvar.yaml.j2 export STATICB_TYPE='diffusion' -export BERROR_YAML="${PARMgfs}/gdas/aero/berror/staticb_${STATICB_TYPE}.yaml.j2" +export BERROR_YAML="aero_background_error_static_${STATICB_TYPE}" export BERROR_DATA_DIR="${FIXgfs}/gdas/aero/clim_b" export CRTM_FIX_YAML="${PARMgfs}/gdas/aero_crtm_coeff.yaml.j2" export JEDI_FIX_YAML="${PARMgfs}/gdas/aero_jedi_fix.yaml.j2" +export JEDI_CONFIG_YAML="${PARMgfs}/gdas/aeroanl_jedi_config.yaml.j2" + export AERO_STAGE_VARIATIONAL_TMPL="${PARMgfs}/gdas/aero_stage_variational.yaml.j2" export AERO_FINALIZE_VARIATIONAL_TMPL="${PARMgfs}/gdas/aero_finalize_variational.yaml.j2" @@ -33,15 +35,11 @@ export io_layout_x=@IO_LAYOUT_X@ export io_layout_y=@IO_LAYOUT_Y@ export JEDIEXE="${EXECgfs}/gdas.x" -export BMATEXE="${EXECgfs}/gdasapp_chem_diagb.x" -export DIFFUSIONEXE="${EXECgfs}/gdas_fv3jedi_error_covariance_toolbox.x" if [[ "${DOIAU}" == "YES" ]]; then export aero_bkg_times="3,6,9" - export JEDIYAML="${PARMgfs}/gdas/aero/variational/3dvar_fgat_gfs_aero.yaml.j2" else export aero_bkg_times="6," # Trailing comma is necessary so this is treated as a list - export JEDIYAML="${PARMgfs}/gdas/aero/variational/3dvar_gfs_aero.yaml.j2" fi echo "END: config.aeroanl" diff --git a/parm/config/gfs/config.aeroanlgenb b/parm/config/gfs/config.aeroanlgenb index b41b22a524..d1f0ed10bd 100644 --- a/parm/config/gfs/config.aeroanlgenb +++ b/parm/config/gfs/config.aeroanlgenb @@ -8,9 +8,8 @@ echo "BEGIN: config.aeroanlgenb" # Get task specific resources source "${EXPDIR}/config.resources" aeroanlgenb -export BMATYAML="${PARMgfs}/gdas/aero/berror/aero_diagb.yaml.j2" -export DIFFUSIONYAML="${PARMgfs}/gdas/aero/berror/aero_diffusionparm.yaml.j2" -export INTERPYAML="${PARMgfs}/gdas/aero/berror/aero_interp.yaml.j2" +export JEDI_CONFIG_YAML="${PARMgfs}/gdas/aero_bmat_jedi_config.yaml.j2" +export JCB_BASE_YAML="${PARMgfs}/gdas/aero/jcb-base.yaml.j2" export AERO_BMATRIX_STAGE_TMPL="${PARMgfs}/gdas/aero_stage_bmatrix_bkg.yaml.j2" export AERO_BMATRIX_FINALIZE_TMPL="${PARMgfs}/gdas/aero_finalize_bmatrix_bkg.yaml.j2" export aero_diffusion_iter=10 diff --git a/parm/gdas/aero_bmat_jedi_config.yaml.j2 b/parm/gdas/aero_bmat_jedi_config.yaml.j2 new file mode 100644 index 0000000000..4f0a779335 --- /dev/null +++ b/parm/gdas/aero_bmat_jedi_config.yaml.j2 @@ -0,0 +1,19 @@ +aero_interpbkg: + rundir: '{{ DATA }}' + exe_src: '{{ EXECgfs }}/gdas.x' + jedi_args: ['fv3jedi', 'convertstate'] + mpi_cmd: '{{ APRUN_AEROANLGENB }}' + jcb_base_yaml: '{{ PARMgfs }}/gdas/aero/jcb-base.yaml.j2' + jcb_algo: aero_convert_background +aero_diagb: + rundir: '{{ DATA }}' + exe_src: '{{ EXECgfs }}/gdasapp_chem_diagb.x' + mpi_cmd: '{{ APRUN_AEROANLGENB }}' + jcb_base_yaml: '{{ PARMgfs }}/gdas/aero/jcb-base.yaml.j2' + jcb_algo: aero_gen_bmatrix_diagb +aero_diffusion: + rundir: '{{ DATA }}' + exe_src: '{{ EXECgfs }}/gdas_fv3jedi_error_covariance_toolbox.x' + mpi_cmd: '{{ APRUN_AEROANLGENB }}' + jcb_base_yaml: '{{ PARMgfs }}/gdas/aero/jcb-base.yaml.j2' + jcb_algo: aero_gen_bmatrix_diffusion diff --git a/parm/gdas/aero_finalize_bmatrix_bkg.yaml.j2 b/parm/gdas/aero_finalize_bmatrix_bkg.yaml.j2 index b33f280945..d7addee30d 100644 --- a/parm/gdas/aero_finalize_bmatrix_bkg.yaml.j2 +++ b/parm/gdas/aero_finalize_bmatrix_bkg.yaml.j2 @@ -4,9 +4,9 @@ {% set background_time = current_cycle | add_to_datetime(offset_td) %} copy: ### copy YAMLs used -{% set yaml_list = ['chem_diagb.yaml', 'chem_diffusion.yaml'] %} +{% set yaml_list = ['aero_diagb.yaml', 'aero_diffusion.yaml', 'aero_interpbkg.yaml'] %} {% for fname in yaml_list %} -- ["{{ DATA }}/{{ HEAD }}{{ fname }}", "{{ COMOUT_CHEM_BMAT }}/{{ HEAD }}{{ fname }}"] +- ["{{ DATA }}/{{ fname }}", "{{ COMOUT_CHEM_BMAT }}/{{ HEAD }}{{ fname }}"] {% endfor %} ### copy stddev files to ROTDIR {% for tile in range(1, ntiles+1) %} diff --git a/parm/gdas/aero_finalize_variational.yaml.j2 b/parm/gdas/aero_finalize_variational.yaml.j2 index 7dadd36291..67deb41301 100644 --- a/parm/gdas/aero_finalize_variational.yaml.j2 +++ b/parm/gdas/aero_finalize_variational.yaml.j2 @@ -12,7 +12,7 @@ mkdir: - "{{ COMOUT_ATMOS_RESTART }}" copy: ## copy variational YAML to ROTDIR -- ["{{ DATA }}/{{ APREFIX }}aerovar.yaml", "{{ COMOUT_CHEM_ANALYSIS }}/{{ APREFIX }}aerovar.yaml"] +- ["{{ DATA }}/aeroanlvar.yaml", "{{ COMOUT_CHEM_ANALYSIS }}/{{ APREFIX }}aerovar.yaml"] ## copy increments {% for tile in range(1,ntiles+1) %} - ["{{ DATA }}/anl/aeroinc.{{ current_cycle | to_fv3time }}.fv_tracer.res.tile{{ tile }}.nc", "{{ COMOUT_CHEM_ANALYSIS }}/aeroinc.{{ current_cycle | to_fv3time }}.fv_tracer.res.tile{{ tile }}.nc"] diff --git a/parm/gdas/aero_stage_bmatrix_bkg.yaml.j2 b/parm/gdas/aero_stage_bmatrix_bkg.yaml.j2 index 9005b9ff12..18f5598bd8 100644 --- a/parm/gdas/aero_stage_bmatrix_bkg.yaml.j2 +++ b/parm/gdas/aero_stage_bmatrix_bkg.yaml.j2 @@ -12,6 +12,7 @@ mkdir: - "{{ DATA }}/stddev" - "{{ DATA }}/clm_stddev" - "{{ DATA }}/diffusion" +- "{{ DATA }}/rescale" copy: ###################################### # copy deterministic background files @@ -30,9 +31,15 @@ copy: - ["{{ COM_ATMOS_RESTART_TMPL | replace_tmpl(tmpl_dict) }}/{{ background_time | to_fv3time }}.{{ ftype }}.tile{{ tile }}.nc", "{{ DATA }}/bkg/{{ background_time | to_fv3time }}.{{ ftype }}.tile{{ tile }}.nc"] {% endfor %} {% endfor %} +###################################### # copy climatological stddev files ###################################### {% for tile in range(1, ntiles+1) %} - ["{{ BERROR_DATA_DIR }}/stddev.fv_tracer.res.tile{{ tile }}.nc", "{{ DATA }}/clm_stddev/stddev.fv_tracer.res.tile{{ tile }}.nc"] {% endfor %} - +###################################### +# copy stddev rescaling factor files +###################################### +{% for tile in range(1, ntiles+1) %} +- ["{{ BERROR_DATA_DIR }}/rescale.fv_tracer.res.tile{{ tile }}.nc", "{{ DATA }}/rescale/rescale.fv_tracer.res.tile{{ tile }}.nc"] +{% endfor %} diff --git a/parm/gdas/aeroanl_jedi_config.yaml.j2 b/parm/gdas/aeroanl_jedi_config.yaml.j2 new file mode 100644 index 0000000000..4171f94676 --- /dev/null +++ b/parm/gdas/aeroanl_jedi_config.yaml.j2 @@ -0,0 +1,7 @@ +aeroanlvar: + rundir: '{{ DATA }}' + exe_src: '{{ EXECgfs }}/gdas.x' + mpi_cmd: '{{ APRUN_AEROANL }}' + jedi_args: ['fv3jedi', 'variational'] + jcb_base_yaml: '{{ PARMgfs }}/gdas/aero/jcb-base.yaml.j2' + jcb_algo_yaml: '{{ JCB_ALGO_YAML_VAR }}' diff --git a/scripts/exgdas_aero_analysis_generate_bmatrix.py b/scripts/exgdas_aero_analysis_generate_bmatrix.py index 0d8389c40d..124ca4e413 100755 --- a/scripts/exgdas_aero_analysis_generate_bmatrix.py +++ b/scripts/exgdas_aero_analysis_generate_bmatrix.py @@ -18,10 +18,8 @@ # Take configuration from environment and cast it as python dictionary config = cast_strdict_as_dtypedict(os.environ) - # Instantiate the aerosol variance and diffusion correlation tasks - AeroB = AerosolBMatrix(config) - AeroB.initialize() - AeroB.interpBackground() - AeroB.computeVariance() - AeroB.computeDiffusion() - AeroB.finalize() + # Create an instance of the AerosolBMatrix task + aeroBMat = AerosolBMatrix(config) + aeroBMat.initialize() + aeroBMat.execute() + aeroBMat.finalize() diff --git a/scripts/exglobal_aero_analysis_finalize.py b/scripts/exglobal_aero_analysis_finalize.py index e9464b47e5..19adcc4c38 100755 --- a/scripts/exglobal_aero_analysis_finalize.py +++ b/scripts/exglobal_aero_analysis_finalize.py @@ -21,4 +21,6 @@ # Instantiate the aerosol analysis task AeroAnl = AerosolAnalysis(config) + + # Finalize JEDI aerosol variational analysis AeroAnl.finalize() diff --git a/scripts/exglobal_aero_analysis_initialize.py b/scripts/exglobal_aero_analysis_initialize.py index 3a57dc8401..e3699f23e5 100755 --- a/scripts/exglobal_aero_analysis_initialize.py +++ b/scripts/exglobal_aero_analysis_initialize.py @@ -21,4 +21,6 @@ # Instantiate the aerosol analysis task AeroAnl = AerosolAnalysis(config) + + # Initialize JEDI aerosol variational analysis AeroAnl.initialize() diff --git a/scripts/exglobal_aero_analysis_variational.py b/scripts/exglobal_aero_analysis_variational.py index dd5bb4f65a..1a99d3c5d7 100755 --- a/scripts/exglobal_aero_analysis_variational.py +++ b/scripts/exglobal_aero_analysis_variational.py @@ -19,4 +19,6 @@ # Instantiate the aerosol analysis task AeroAnl = AerosolAnalysis(config) - AeroAnl.variational() + + # Execute JEDI variational analysis + AeroAnl.execute('aeroanlvar') diff --git a/sorc/gdas.cd b/sorc/gdas.cd index d9b40c9bde..a2ea3770ae 160000 --- a/sorc/gdas.cd +++ b/sorc/gdas.cd @@ -1 +1 @@ -Subproject commit d9b40c9bde1e5e70451f309a5e010267aaadba00 +Subproject commit a2ea3770aeb9d4308bde51bb1d8c9c94cc9534c8 diff --git a/ush/python/pygfs/__init__.py b/ush/python/pygfs/__init__.py index 9f290fafd3..6b7b7eb4c9 100644 --- a/ush/python/pygfs/__init__.py +++ b/ush/python/pygfs/__init__.py @@ -2,7 +2,6 @@ import os from .task.analysis import Analysis -from .task.bmatrix import BMatrix from .task.aero_emissions import AerosolEmissions from .task.aero_analysis import AerosolAnalysis from .task.aero_bmatrix import AerosolBMatrix diff --git a/ush/python/pygfs/task/aero_analysis.py b/ush/python/pygfs/task/aero_analysis.py index 0389e109a1..de9360a9ac 100644 --- a/ush/python/pygfs/task/aero_analysis.py +++ b/ush/python/pygfs/task/aero_analysis.py @@ -5,34 +5,49 @@ import gzip import tarfile from logging import getLogger -from typing import Dict, List, Any +from pprint import pformat +from netCDF4 import Dataset +from typing import Dict, List from wxflow import (AttrDict, FileHandler, add_to_datetime, to_fv3time, to_timedelta, - chdir, to_fv3time, - YAMLFile, parse_j2yaml, save_as_yaml, - logit, - Executable, - WorkflowException) -from pygfs.task.analysis import Analysis + Task, + YAMLFile, parse_j2yaml, + logit) +from pygfs.jedi import Jedi logger = getLogger(__name__.split('.')[-1]) -class AerosolAnalysis(Analysis): +class AerosolAnalysis(Task): """ - Class for global aerosol analysis tasks + Class for JEDI-based global aerosol analysis tasks """ @logit(logger, name="AerosolAnalysis") def __init__(self, config): + """Constructor global aero analysis task + + This method will construct a global aero analysis task. + This includes: + - extending the task_config attribute AttrDict to include parameters required for this task + - instantiate the Jedi attribute object + + Parameters + ---------- + config: Dict + dictionary object containing task configuration + + Returns + ---------- + None + """ super().__init__(config) _res = int(self.task_config['CASE'][1:]) _res_anl = int(self.task_config['CASE_ANL'][1:]) _window_begin = add_to_datetime(self.task_config.current_cycle, -to_timedelta(f"{self.task_config['assim_freq']}H") / 2) - _jedi_yaml = os.path.join(self.task_config.DATA, f"{self.task_config.RUN}.t{self.task_config['cyc']:02d}z.aerovar.yaml") # Create a local dictionary that is repeatedly used across this class local_dict = AttrDict( @@ -50,72 +65,94 @@ def __init__(self, config): 'OPREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z.", 'APREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z.", 'GPREFIX': f"gdas.t{self.task_config.previous_cycle.hour:02d}z.", - 'jedi_yaml': _jedi_yaml, + 'aero_obsdatain_path': f"{self.task_config.DATA}/obs/", + 'aero_obsdataout_path': f"{self.task_config.DATA}/diags/", + 'BKG_TSTEP': "PT3H" # FGAT } ) # Extend task_config with local_dict self.task_config = AttrDict(**self.task_config, **local_dict) + # Create dictionary of Jedi objects + expected_keys = ['aeroanlvar'] + self.jedi_dict = Jedi.get_jedi_dict(self.task_config.JEDI_CONFIG_YAML, self.task_config, expected_keys) + @logit(logger) - def initialize(self: Analysis) -> None: + def initialize(self) -> None: """Initialize a global aerosol analysis This method will initialize a global aerosol analysis using JEDI. This includes: + - initialize JEDI applications + - staging observation files + - staging bias correction files - staging CRTM fix files - staging FV3-JEDI fix files - staging B error files - staging model backgrounds - - generating a YAML file for the JEDI executable - creating output directories """ - super().initialize() + + # initialize JEDI variational application + logger.info(f"Initializing JEDI variational DA application") + self.jedi_dict['aeroanlvar'].initialize(self.task_config) + + # stage observations + logger.info(f"Staging list of observation files generated from JEDI config") + obs_dict = self.jedi_dict['aeroanlvar'].render_jcb(self.task_config, 'aero_obs_staging') + FileHandler(obs_dict).sync() + logger.debug(f"Observation files:\n{pformat(obs_dict)}") + + # # stage bias corrections + # logger.info(f"Staging list of bias correction files") + # bias_dict = self.jedi_dict['aeroanlvar'].render_jcb(self.task_config, 'aero_bias_staging') + # if bias_dict['copy'] is None: + # logger.info(f"No bias correction files to stage") + # else: + # bias_dict['copy'] = Jedi.remove_redundant(bias_dict['copy']) + # FileHandler(bias_dict).sync() + # logger.debug(f"Bias correction files:\n{pformat(bias_dict)}") + + # # extract bias corrections + # Jedi.extract_tar_from_filehandler_dict(bias_dict) # stage CRTM fix files logger.info(f"Staging CRTM fix files from {self.task_config.CRTM_FIX_YAML}") - crtm_fix_list = parse_j2yaml(self.task_config.CRTM_FIX_YAML, self.task_config) - FileHandler(crtm_fix_list).sync() + crtm_fix_dict = parse_j2yaml(self.task_config.CRTM_FIX_YAML, self.task_config) + FileHandler(crtm_fix_dict).sync() + logger.debug(f"CRTM fix files:\n{pformat(crtm_fix_dict)}") # stage fix files logger.info(f"Staging JEDI fix files from {self.task_config.JEDI_FIX_YAML}") - jedi_fix_list = parse_j2yaml(self.task_config.JEDI_FIX_YAML, self.task_config) - FileHandler(jedi_fix_list).sync() + jedi_fix_dict = parse_j2yaml(self.task_config.JEDI_FIX_YAML, self.task_config) + FileHandler(jedi_fix_dict).sync() + logger.debug(f"JEDI fix files:\n{pformat(jedi_fix_dict)}") # stage files from COM and create working directories logger.info(f"Staging files prescribed from {self.task_config.AERO_STAGE_VARIATIONAL_TMPL}") - aero_var_stage_list = parse_j2yaml(self.task_config.AERO_STAGE_VARIATIONAL_TMPL, self.task_config) - FileHandler(aero_var_stage_list).sync() - - # generate variational YAML file - logger.debug(f"Generate variational YAML file: {self.task_config.jedi_yaml}") - save_as_yaml(self.task_config.jedi_config, self.task_config.jedi_yaml) - logger.info(f"Wrote variational YAML to: {self.task_config.jedi_yaml}") + aero_var_stage_dict = parse_j2yaml(self.task_config.AERO_STAGE_VARIATIONAL_TMPL, self.task_config) + FileHandler(aero_var_stage_dict).sync() + logger.debug(f"Staging from COM:\n{pformat(aero_var_stage_dict)}") @logit(logger) - def variational(self: Analysis) -> None: + def execute(self, jedi_dict_key: str) -> None: + """Execute JEDI application of aero analysis - chdir(self.task_config.DATA) - - exec_cmd = Executable(self.task_config.APRUN_AEROANL) - exec_name = os.path.join(self.task_config.DATA, 'gdas.x') - exec_cmd.add_default_arg(exec_name) - exec_cmd.add_default_arg('fv3jedi') - exec_cmd.add_default_arg('variational') - exec_cmd.add_default_arg(self.task_config.jedi_yaml) + Parameters + ---------- + jedi_dict_key + key specifying particular Jedi object in self.jedi_dict - try: - logger.debug(f"Executing {exec_cmd}") - exec_cmd() - except OSError: - raise OSError(f"Failed to execute {exec_cmd}") - except Exception: - raise WorkflowException(f"An error occured during execution of {exec_cmd}") + Returns + ---------- + None + """ - pass + self.jedi_dict[jedi_dict_key].execute() @logit(logger) - def finalize(self: Analysis) -> None: + def finalize(self) -> None: """Finalize a global aerosol analysis This method will finalize a global aerosol analysis using JEDI. @@ -145,6 +182,9 @@ def finalize(self: Analysis) -> None: logger.info('Adding increments to RESTART files') self._add_fms_cube_sphere_increments() + # tar up bias correction files + # NOTE TODO + # copy files back to COM logger.info(f"Copying files to COM based on {self.task_config.AERO_FINALIZE_VARIATIONAL_TMPL}") aero_var_final_list = parse_j2yaml(self.task_config.AERO_FINALIZE_VARIATIONAL_TMPL, self.task_config) @@ -161,7 +201,7 @@ def clean(self): super().clean() @logit(logger) - def _add_fms_cube_sphere_increments(self: Analysis) -> None: + def _add_fms_cube_sphere_increments(self) -> None: """This method adds increments to RESTART files to get an analysis """ if self.task_config.DOIAU: @@ -176,46 +216,32 @@ def _add_fms_cube_sphere_increments(self: Analysis) -> None: # get list of increment vars incvars_list_path = os.path.join(self.task_config['PARMgfs'], 'gdas', 'aeroanl_inc_vars.yaml') incvars = YAMLFile(path=incvars_list_path)['incvars'] - super().add_fv3_increments(inc_template, bkg_template, incvars) + self.add_fv3_increments(inc_template, bkg_template, incvars) @logit(logger) - def get_bkg_dict(self, task_config: Dict[str, Any]) -> Dict[str, List[str]]: - """Compile a dictionary of model background files to copy - - This method constructs a dictionary of FV3 RESTART files (coupler, core, tracer) - that are needed for global aerosol DA and returns said dictionary for use by the FileHandler class. + def add_fv3_increments(self, inc_file_tmpl: str, bkg_file_tmpl: str, incvars: List) -> None: + """Add cubed-sphere increments to cubed-sphere backgrounds Parameters ---------- - task_config: Dict - a dictionary containing all of the configuration needed for the task - - Returns - ---------- - bkg_dict: Dict - a dictionary containing the list of model background files to copy for FileHandler + inc_file_tmpl : str + template of the FV3 increment file of the form: 'filetype.tile{tilenum}.nc' + bkg_file_tmpl : str + template of the FV3 background file of the form: 'filetype.tile{tilenum}.nc' + incvars : List + List of increment variables to add to the background """ - bkg_dict = {} - return bkg_dict - - @logit(logger) - def get_berror_dict(self, config: Dict[str, Any]) -> Dict[str, List[str]]: - """Compile a dictionary of background error files to copy - This method will construct a dictionary of BUMP background error files - for global aerosol DA and return said dictionary for use by the FileHandler class. - This dictionary contains coupler and fv_tracer files - for correlation and standard deviation as well as NICAS localization. - - Parameters - ---------- - config: Dict - a dictionary containing all of the configuration needed - - Returns - ---------- - berror_dict: Dict - a dictionary containing the list of background error files to copy for FileHandler - """ - berror_dict = {} - return berror_dict + for itile in range(1, self.task_config.ntiles + 1): + inc_path = inc_file_tmpl.format(tilenum=itile) + bkg_path = bkg_file_tmpl.format(tilenum=itile) + with Dataset(inc_path, mode='r') as incfile, Dataset(bkg_path, mode='a') as rstfile: + for vname in incvars: + increment = incfile.variables[vname][:] + bkg = rstfile.variables[vname][:] + anl = bkg + increment + rstfile.variables[vname][:] = anl[:] + try: + rstfile.variables[vname].delncattr('checksum') # remove the checksum so fv3 does not complain + except (AttributeError, RuntimeError): + pass # checksum is missing, move on diff --git a/ush/python/pygfs/task/aero_bmatrix.py b/ush/python/pygfs/task/aero_bmatrix.py index c652bad558..572eaaf9dc 100644 --- a/ush/python/pygfs/task/aero_bmatrix.py +++ b/ush/python/pygfs/task/aero_bmatrix.py @@ -2,31 +2,43 @@ import os from logging import getLogger -from typing import List, Dict, Any, Union +from typing import List, Dict -from wxflow import (AttrDict, FileHandler, rm_p, - add_to_datetime, to_fv3time, to_timedelta, - to_fv3time, chdir, Executable, WorkflowException, - parse_j2yaml, save_as_yaml, logit) -from pygfs.task.bmatrix import BMatrix +from wxflow import (AttrDict, FileHandler, + add_to_datetime, to_timedelta, + parse_j2yaml, logit, Task) +from pygfs.jedi import Jedi logger = getLogger(__name__.split('.')[-1]) -class AerosolBMatrix(BMatrix): +class AerosolBMatrix(Task): """ Class for global aerosol BMatrix tasks """ @logit(logger, name="AerosolBMatrix") - def __init__(self, config: Dict[str, Any]) -> None: + def __init__(self, config): + """Constructor global aero analysis bmatrix task + + This method will construct a global aero bmatrix task object. + This includes: + - extending the task_config attribute AttrDict to include parameters required for this task + - instantiate the Jedi attribute object + + Parameters + ---------- + config: Dict + dictionary object containing task configuration + + Returns + ---------- + None + """ super().__init__(config) _res = int(self.task_config['CASE'][1:]) _res_anl = int(self.task_config['CASE_ANL'][1:]) - - _bmat_yaml = os.path.join(self.task_config.DATA, f"{self.task_config.RUN}.t{self.task_config['cyc']:02d}z.chem_diagb.yaml") - _diffusion_yaml = os.path.join(self.task_config.DATA, f"{self.task_config.RUN}.t{self.task_config['cyc']:02d}z.chem_diffusion.yaml") - _convertstate_yaml = os.path.join(self.task_config.DATA, f"{self.task_config.RUN}.t{self.task_config['cyc']:02d}z.chem_convertstate.yaml") + _window_begin = add_to_datetime(self.task_config.current_cycle, -to_timedelta(f"{self.task_config['assim_freq']}H") / 2) # Create a local dictionary that is repeatedly used across this class local_dict = AttrDict( @@ -38,257 +50,95 @@ def __init__(self, config: Dict[str, Any]) -> None: 'npx_anl': _res_anl + 1, 'npy_anl': _res_anl + 1, 'npz_anl': self.task_config['LEVS'] - 1, + 'AERO_WINDOW_BEGIN': _window_begin, + 'AERO_WINDOW_LENGTH': f"PT{self.task_config['assim_freq']}H", 'aero_bkg_fhr': map(int, str(self.task_config['aero_bkg_times']).split(',')), 'OPREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z.", 'APREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z.", 'GPREFIX': f"gdas.t{self.task_config.previous_cycle.hour:02d}z.", - 'bmat_yaml': _bmat_yaml, - 'diffusion_yaml': _diffusion_yaml, - 'convertstate_yaml': _convertstate_yaml, + 'aero_obsdatain_path': f"{self.task_config.DATA}/obs/", + 'aero_obsdataout_path': f"{self.task_config.DATA}/diags/", } ) # task_config is everything that this task should need self.task_config = AttrDict(**self.task_config, **local_dict) - @logit(logger) - def initialize(self: BMatrix) -> None: - super().initialize() - # stage fix files - logger.info(f"Staging JEDI fix files from {self.task_config.JEDI_FIX_YAML}") - jedi_fix_list = parse_j2yaml(self.task_config.JEDI_FIX_YAML, self.task_config) - FileHandler(jedi_fix_list).sync() - - # stage backgrounds - logger.info(f"Staging backgrounds prescribed from {self.task_config.AERO_BMATRIX_STAGE_TMPL}") - aero_bmat_stage_list = parse_j2yaml(self.task_config.AERO_BMATRIX_STAGE_TMPL, self.task_config) - FileHandler(aero_bmat_stage_list).sync() - - # generate convert state YAML file - logger.info(f"Generate convert state YAML file: {self.task_config.convertstate_yaml}") - self.task_config.convertstate_config = parse_j2yaml(self.task_config.INTERPYAML, - self.task_config, - searchpath=self.gdasapp_j2tmpl_dir) - save_as_yaml(self.task_config.convertstate_config, self.task_config.convertstate_yaml) - logger.info(f"Wrote convert state YAML to: {self.task_config.convertstate_yaml}") - - # generate diagb YAML file - logger.info(f"Generate bmat YAML file: {self.task_config.bmat_yaml}") - self.task_config.bmat_config = parse_j2yaml(self.task_config.BMATYAML, - self.task_config, - searchpath=self.gdasapp_j2tmpl_dir) - save_as_yaml(self.task_config.bmat_config, self.task_config.bmat_yaml) - logger.info(f"Wrote bmat YAML to: {self.task_config.bmat_yaml}") - - # generate diffusion parameters YAML file - logger.info(f"Generate diffusion YAML file: {self.task_config.diffusion_yaml}") - self.task_config.diffusion_config = parse_j2yaml(self.task_config.DIFFUSIONYAML, - self.task_config, - searchpath=self.gdasapp_j2tmpl_dir) - save_as_yaml(self.task_config.diffusion_config, self.task_config.diffusion_yaml) - logger.info(f"Wrote diffusion YAML to: {self.task_config.diffusion_yaml}") - - # link executable to run directory - self.link_bmatexe() - self.link_diffusion_exe() - self.link_jediexe() - - @logit(logger) - def interpBackground(self) -> None: - chdir(self.task_config.DATA) - - exec_cmd = Executable(self.task_config.APRUN_AEROANLGENB) - exec_name = os.path.join(self.task_config.DATA, 'gdas.x') - exec_cmd.add_default_arg(exec_name) - exec_cmd.add_default_arg('fv3jedi') - exec_cmd.add_default_arg('convertstate') - exec_cmd.add_default_arg(self.task_config.convertstate_yaml) - - try: - logger.debug(f"Executing {exec_cmd}") - exec_cmd() - except OSError: - raise OSError(f"Failed to execute {exec_cmd}") - except Exception: - raise WorkflowException(f"An error occured during execution of {exec_cmd}") - - pass - - @logit(logger) - def computeVariance(self) -> None: - - chdir(self.task_config.DATA) - - exec_cmd = Executable(self.task_config.APRUN_AEROANLGENB) - exec_name = os.path.join(self.task_config.DATA, 'gdasapp_chem_diagb.x') - exec_cmd.add_default_arg(exec_name) - exec_cmd.add_default_arg(self.task_config.bmat_yaml) - - try: - logger.debug(f"Executing {exec_cmd}") - exec_cmd() - except OSError: - raise OSError(f"Failed to execute {exec_cmd}") - except Exception: - raise WorkflowException(f"An error occured during execution of {exec_cmd}") - - pass + # Create dictionary of Jedi objects + expected_keys = ['aero_interpbkg', 'aero_diagb', 'aero_diffusion'] + self.jedi_dict = Jedi.get_jedi_dict(self.task_config.JEDI_CONFIG_YAML, self.task_config, expected_keys) @logit(logger) - def computeDiffusion(self) -> None: - - chdir(self.task_config.DATA) - - exec_cmd_diffusion = Executable(self.task_config.APRUN_AEROANLGENB) - exec_name_diffusion = os.path.join(self.task_config.DATA, 'gdas_fv3jedi_error_covariance_toolbox.x') - exec_cmd_diffusion.add_default_arg(exec_name_diffusion) - exec_cmd_diffusion.add_default_arg(self.task_config.diffusion_yaml) + def initialize(self: Task) -> None: + """Initialize a global aerosol B-matrix - try: - logger.debug(f"Executing {exec_cmd_diffusion}") - exec_cmd_diffusion() - except OSError: - raise OSError(f"Failed to execute {exec_cmd_diffusion}") - except Exception: - raise WorkflowException(f"An error occured during execution of {exec_cmd_diffusion}") - - pass - - @logit(logger) - def finalize(self) -> None: - super().finalize() - # save files to COMOUT - logger.info(f"Saving files to COMOUT based on {self.task_config.AERO_BMATRIX_FINALIZE_TMPL}") - aero_bmat_finalize_list = parse_j2yaml(self.task_config.AERO_BMATRIX_FINALIZE_TMPL, self.task_config) - FileHandler(aero_bmat_finalize_list).sync() - - @logit(logger) - def link_jediexe(self) -> None: - """ - - This method links a JEDI executable to the run directory + This method will initialize a global aerosol B-Matrix. + This includes: + - staging the determinstic backgrounds + - staging fix files + - initializing the JEDI applications Parameters ---------- - Task: GDAS task - - Returns - ---------- None - """ - exe_src = self.task_config.JEDIEXE - - # TODO: linking is not permitted per EE2. Needs work in JEDI to be able to copy the exec. - logger.info(f"Link executable {exe_src} to DATA/") - logger.warn("Linking is not permitted per EE2.") - exe_dest = os.path.join(self.task_config.DATA, os.path.basename(exe_src)) - if os.path.exists(exe_dest): - rm_p(exe_dest) - os.symlink(exe_src, exe_dest) - - return exe_dest - - @logit(logger) - def link_bmatexe(self) -> None: - """ - - This method links a JEDI executable to the run directory - - Parameters - ---------- - Task: GDAS task Returns ---------- None """ - exe_src = self.task_config.BMATEXE - # TODO: linking is not permitted per EE2. Needs work in JEDI to be able to copy the exec. - logger.info(f"Link executable {exe_src} to DATA/") - logger.warn("Linking is not permitted per EE2.") - exe_dest = os.path.join(self.task_config.DATA, os.path.basename(exe_src)) - if os.path.exists(exe_dest): - rm_p(exe_dest) - os.symlink(exe_src, exe_dest) + # stage fix files + logger.info(f"Staging JEDI fix files from {self.task_config.JEDI_FIX_YAML}") + jedi_fix_list = parse_j2yaml(self.task_config.JEDI_FIX_YAML, self.task_config) + FileHandler(jedi_fix_list).sync() + + # stage backgrounds + logger.info(f"Staging backgrounds prescribed from {self.task_config.AERO_BMATRIX_STAGE_TMPL}") + aero_bmat_stage_list = parse_j2yaml(self.task_config.AERO_BMATRIX_STAGE_TMPL, self.task_config) + FileHandler(aero_bmat_stage_list).sync() - return + # initialize JEDI applications + self.jedi_dict['aero_interpbkg'].initialize(self.task_config) + self.jedi_dict['aero_diagb'].initialize(self.task_config) + self.jedi_dict['aero_diffusion'].initialize(self.task_config) @logit(logger) - def link_diffusion_exe(self) -> None: - """ + def execute(self) -> None: + """Generate the full B-matrix - This method links a JEDI (fv3jedi_error_covariance_toolbox.x) - executable to the run directory + This method will generate the full B-matrix according to the configuration. + This includes: + - running all JEDI applications required to generate the B-matrix Parameters ---------- - Task: GDAS task + None Returns ---------- None """ - exe_src_diffusion = self.task_config.DIFFUSIONEXE + # interpolate backgrounds to analysis resolution + self.jedi_dict['aero_interpbkg'].execute() - # TODO: linking is not permitted per EE2. Needs work in JEDI to be able to copy the exec. - logger.info(f"Link executable {exe_src_diffusion} to DATA/") - logger.warn("Linking is not permitted per EE2.") - exe_dest_diffusion = os.path.join(self.task_config.DATA, os.path.basename(exe_src_diffusion)) - if os.path.exists(exe_dest_diffusion): - rm_p(exe_dest_diffusion) - os.symlink(exe_src_diffusion, exe_dest_diffusion) + # variance partitioning + self.jedi_dict['aero_diagb'].execute() - return + # diffusion + self.jedi_dict['aero_diffusion'].execute() @logit(logger) - def get_bkg_dict(self, task_config: Dict[str, Any]) -> Dict[str, List[str]]: - """Compile a dictionary of model background files to copy + def finalize(self) -> None: + """Finalize a global aerosol bmatrix - This method constructs a dictionary of FV3 RESTART files (coupler, core, tracer) - that are needed for global aerosol DA and returns said dictionary for use by the FileHandler class. + This method will finalize a global aerosol bmatrix using JEDI. + This includes: + - copying the bmatrix files to COM + - copying YAMLs to COM - Parameters - ---------- - task_config: Dict - a dictionary containing all of the configuration needed for the task - - Returns - ---------- - bkg_dict: Dict - a dictionary containing the list of model background files to copy for FileHandler """ - # NOTE for now this is FV3 RESTART files and just assumed to be fh006 - - # get FV3 RESTART files, this will be a lot simpler when using history files - rst_dir = task_config.COM_ATMOS_RESTART_PREV - run_dir = os.path.join(task_config['DATA'], 'bkg') - - # Start accumulating list of background files to copy - bkglist = [] - - # if using IAU, we can use FGAT - bkgtimes = [] - begintime = task_config.previous_cycle - for fcsthr in task_config.aero_bkg_fhr: - bkgtimes.append(add_to_datetime(begintime, to_timedelta(f"{fcsthr}H"))) - - # now loop over background times - for bkgtime in bkgtimes: - # aerosol DA needs coupler - basename = f'{to_fv3time(bkgtime)}.coupler.res' - bkglist.append([os.path.join(rst_dir, basename), os.path.join(run_dir, basename)]) - - # aerosol DA only needs core/tracer - for ftype in ['core', 'tracer']: - template = f'{to_fv3time(bkgtime)}.fv_{ftype}.res.tile{{tilenum}}.nc' - for itile in range(1, task_config.ntiles + 1): - basename = template.format(tilenum=itile) - bkglist.append([os.path.join(rst_dir, basename), os.path.join(run_dir, basename)]) - - bkg_dict = { - 'mkdir': [run_dir], - 'copy': bkglist, - } - return bkg_dict + # save files to COMOUT + logger.info(f"Saving files to COMOUT based on {self.task_config.AERO_BMATRIX_FINALIZE_TMPL}") + aero_bmat_finalize_list = parse_j2yaml(self.task_config.AERO_BMATRIX_FINALIZE_TMPL, self.task_config) + FileHandler(aero_bmat_finalize_list).sync() diff --git a/ush/python/pygfs/task/bmatrix.py b/ush/python/pygfs/task/bmatrix.py deleted file mode 100644 index d0edba2358..0000000000 --- a/ush/python/pygfs/task/bmatrix.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import os -from logging import getLogger -from typing import List, Dict, Any, Union - -from wxflow import (parse_j2yaml, FileHandler, logit, - Task, Executable, WorkflowException) - -logger = getLogger(__name__.split('.')[-1]) - - -class BMatrix(Task): - """Parent class for GDAS BMatrix tasks - - The BMatrix class is the parent class for all - Global Data Assimilation System (GDAS) BMatrix tasks - """ - def __init__(self, config: Dict[str, Any]) -> None: - super().__init__(config) - # Store location of GDASApp jinja2 templates - self.gdasapp_j2tmpl_dir = os.path.join(self.task_config.PARMgfs, 'gdas') - - def initialize(self) -> None: - super().initialize() - - def finalize(self) -> None: - super().finalize() From be7626d608a7e2c30473aaf3ec7e8a8ed6da1f68 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Mon, 16 Dec 2024 00:34:07 -0500 Subject: [PATCH 07/10] Allow building of the ufs-weather-model, WW3 pre/post execs for GFS, GEFS, SFS in the same clone of global-workflow (#3098) GFS and GEFS (and now SFS) uses different compile time options for the UFS-weather-model. For the purposes of CI testing, a multi-build pipeline under Jenkins was created by @TerrenceMcGuinness-NOAA. This served well, until now. With the inclusion of SFS, a third variety of the model is being built. Under the multi-build pipeline paradigm, a second (or third) clone and build of the global-workflow is required. This adds cloning and compilation time of the global-workflow. This PR allows compiling the ufs-weather-model in a single clone of the global-workflow. The compiled executables based on the options for GFS, GEFS, and SFS results in a model executable as `gfs_model.x`, `gefs_model.x`, and `sfs_model.x`. The forecast script uses the right executable. This PR also differentiates the WW3 pre/post executables based on `gfs_` or `gefs_`. SFS variants need to be introduced, when `NET=sfs` is added. In the process of updating the WW3 pre/post executable names, it was discovered (via `grep`) the following are not used: - `ww3_prep` - `ww3_outf` - `ww3_ounf` - `ww3_ounp` These need to be confirmed by running the workflow to ensure they are indeed not used at runtime. This PR also updates the `Jenkinsfile` to use the multi-build from the single location. --------- Co-authored-by: Walter Kolczynski - NOAA Co-authored-by: David Huber <69919478+DavidHuber-NOAA@users.noreply.github.com> --- ci/Jenkinsfile | 180 +++++++-------- ci/cases/pr/C48_S2SWA_gefs.yaml | 2 +- ci/cases/pr/C96_S2SWA_gefs_replay_ics.yaml | 2 +- ci/cases/yamls/build.yaml | 3 - ci/scripts/utils/ci_utils_wrapper.sh | 4 +- parm/config/gefs/config.fcst | 10 +- parm/config/gfs/config.fcst | 6 +- scripts/exgfs_wave_post_pnt.sh | 10 +- sorc/build_all.sh | 7 +- sorc/build_ufs.sh | 21 +- sorc/build_ww3prepost.sh | 133 +++++------ sorc/link_workflow.sh | 256 +++++++++++---------- ush/wave_grib2_sbs.sh | 21 +- ush/wave_grid_interp_sbs.sh | 13 +- ush/wave_grid_moddef.sh | 21 +- ush/wave_outp_spec.sh | 14 +- ush/wave_prnc_cur.sh | 10 +- ush/wave_prnc_ice.sh | 20 +- 18 files changed, 359 insertions(+), 374 deletions(-) delete mode 100644 ci/cases/yamls/build.yaml diff --git a/ci/Jenkinsfile b/ci/Jenkinsfile index b3bd6a917a..9e2381268d 100644 --- a/ci/Jenkinsfile +++ b/ci/Jenkinsfile @@ -1,9 +1,10 @@ def Machine = 'none' def machine = 'none' def CUSTOM_WORKSPACE = 'none' -def cases = '' +def HOMEgfs = 'none' +def CI_CASES = '' def GH = 'none' -// Location of the custom workspaces for each machine in the CI system. They are persitent for each iteration of the PR. +// Location of the custom workspaces for each machine in the CI system. They are persistent for each iteration of the PR. def NodeName = [hera: 'Hera-EMC', orion: 'Orion-EMC', hercules: 'Hercules-EMC', gaea: 'Gaea'] def custom_workspace = [hera: '/scratch1/NCEPDEV/global/CI', orion: '/work2/noaa/stmp/CI/ORION', hercules: '/work2/noaa/global/CI/HERCULES', gaea: '/gpfs/f5/epic/proj-shared/global/CI'] def repo_url = 'git@github.com:NOAA-EMC/global-workflow.git' @@ -19,8 +20,8 @@ pipeline { } stages { // This initial stage is used to get the Machine name from the GitHub labels on the PR - // which is used to designate the Nodes in the Jenkins Controler by the agent label - // Each Jenknis Node is connected to said machine via an JAVA agent via an ssh tunnel + // which is used to designate the Nodes in the Jenkins Controller by the agent label + // Each Jenkins Node is connected to said machine via an JAVA agent via an ssh tunnel // no op 2 stage('1. Get Machine') { @@ -81,7 +82,9 @@ pipeline { properties([parameters([[$class: 'NodeParameterDefinition', allowedSlaves: ['built-in', 'Hercules-EMC', 'Hera-EMC', 'Orion-EMC', 'Gaea'], defaultSlaves: ['built-in'], name: '', nodeEligibility: [$class: 'AllNodeEligibility'], triggerIfResult: 'allCases']])]) GH = sh(script: "which gh || echo '~/bin/gh'", returnStdout: true).trim() CUSTOM_WORKSPACE = "${WORKSPACE}" - sh(script: "mkdir -p ${CUSTOM_WORKSPACE}/RUNTESTS;rm -Rf ${CUSTOM_WORKSPACE}/RUNTESTS/*") + HOMEgfs = "${CUSTOM_WORKSPACE}/global-workflow" + sh(script: "rm -Rf ${CUSTOM_WORKSPACE}/global-workflow; mkdir -p ${CUSTOM_WORKSPACE}/global-workflow") + sh(script: "rm -Rf ${CUSTOM_WORKSPACE}/RUNTESTS; mkdir -p ${CUSTOM_WORKSPACE}/RUNTESTS") sh(script: """${GH} pr edit ${env.CHANGE_ID} --repo ${repo_url} --add-label "CI-${Machine}-Building" --remove-label "CI-${Machine}-Ready" """) } echo "Building and running on ${Machine} in directory ${CUSTOM_WORKSPACE}" @@ -90,94 +93,75 @@ pipeline { } stage('3. Build System') { - matrix { - agent { label NodeName[machine].toLowerCase() } - axes { - axis { - name 'system' - values 'gfs', 'gefs' - } - } - stages { - stage('Building') { - steps { - catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') { - script { - def HOMEgfs = "${CUSTOM_WORKSPACE}/${system}" // local HOMEgfs is used to build the system on per system basis under the custome workspace for each buile system - env.HOME_GFS = HOMEgfs // setting path in HOMEgfs as an environment variable HOME_GFS for some systems that using the path in its .bashrc - sh(script: "mkdir -p ${HOMEgfs}") - ws(HOMEgfs) { - if (fileExists("${HOMEgfs}/sorc/BUILT_semaphor")) { // if the system is already built, skip the build in the case of re-runs - sh(script: "cat ${HOMEgfs}/sorc/BUILT_semaphor", returnStdout: true).trim() // TODO: and user configurable control to manage build semphore - checkout scm - dir('sorc') { - sh(script: './link_workflow.sh') - } - } else { - try { - echo "Checking out the code for ${system} on ${Machine} using scm in ${HOMEgfs}" - checkout scm - } catch (Exception e) { - if (env.CHANGE_ID) { - sh(script: """${GH} pr comment ${env.CHANGE_ID} --repo ${repo_url} --body "Checkout **Failed** on ${Machine} in Build# ${env.BUILD_NUMBER}: ${e.getMessage()}" """) - } - STATUS = 'Failed' - error("Failed to checkout: ${e.getMessage()}") - } - def gist_url = "" - def error_logs = "" - def error_logs_message = "" - def builds_file = readYaml file: 'ci/cases/yamls/build.yaml' - def build_args_list = builds_file['builds'] - def build_args = build_args_list[system].join(' ').trim().replaceAll('null', '') - dir("${HOMEgfs}/sorc") { - try { - sh(script: "${build_args}") - } catch (Exception error_build) { - echo "Failed to build system: ${error_build.getMessage()}" - if ( fileExists("logs/error.logs") ) { - def fileContent = readFile 'logs/error.logs' - def lines = fileContent.readLines() - for (line in lines) { - echo "archiving: ${line}" - if (fileExists("${line}") && readFile("${line}").length() > 0 ){ - try { - archiveArtifacts artifacts: "${line}", fingerprint: true - error_logs = error_logs + "${HOMEgfs}/sorc/${line} " - error_logs_message = error_logs_message + "${HOMEgfs}/sorc/${line}\n" - } - catch (Exception error_arch) { echo "Failed to archive error log ${line}: ${error_arch.getMessage()}" } - } - } - try { - sh(script: "${HOMEgfs}/ci/scripts/utils/publish_logs.py --file ${error_logs} --repo PR_BUILD_${env.CHANGE_ID}") - gist_url=sh(script: "${HOMEgfs}/ci/scripts/utils/publish_logs.py --file ${error_logs} --gist PR_BUILD_${env.CHANGE_ID}", returnStdout: true).trim() - sh(script: """${GH} pr comment ${env.CHANGE_ID} --repo ${repo_url} --body "Build **FAILED** on **${Machine}** in Build# ${env.BUILD_NUMBER} with error logs:\n\\`\\`\\`\n${error_logs_message}\\`\\`\\`\n\nFollow link here to view the contents of the above file(s): [(link)](${gist_url})" """) - } catch (Exception error_comment) { - echo "Failed to comment on PR: ${error_comment.getMessage()}" - } - STATUS = 'Failed' - error("Failed to build system on ${Machine}") + agent { label NodeName[machine].toLowerCase() } + steps { + catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') { + script { + ws(HOMEgfs) { + echo "Checking out the code on ${Machine} using scm in ${HOMEgfs}" + try { + checkout scm + } catch (Exception e) { + echo "Failed to checkout the code on ${Machine} using scm in ${HOMEgfs}, try again ..." + sleep time: 45, unit: 'SECONDS' + try { + checkout scm + } catch (Exception ee) { + echo "Failed to checkout the code on ${Machine} using scm in ${HOMEgfs}: ${ee.getMessage()}" + if (env.CHANGE_ID) { + sh(script: """${GH} pr comment ${env.CHANGE_ID} --repo ${repo_url} --body "Checkout **Failed** on ${Machine} in Build# ${env.BUILD_NUMBER}: ${ee.getMessage()}" """) + } + STATUS = 'Failed' + error("Failed to checkout: ${ee.getMessage()}") + } + } + def gist_url = "" + def error_logs = "" + def error_logs_message = "" + dir("${HOMEgfs}/sorc") { + try { + sh(script: './build_all.sh -kgu') // build the global-workflow executables for GFS variant (UFS-wx-model, WW3 pre/post executables) + sh(script: './build_ww3prepost.sh -w > ./logs/build_ww3prepost_gefs.log 2>&1') // build the WW3 pre/post processing executables for GEFS variant + sh(script: './build_ufs.sh -w -e gefs_model.x > ./logs/build_ufs_gefs.log 2>&1') // build the UFS-wx-model executable for GEFS variant + } catch (Exception error_build) { + echo "Failed to build global-workflow: ${error_build.getMessage()}" + if ( fileExists("logs/error.logs") ) { + def fileContent = readFile 'logs/error.logs' + def lines = fileContent.readLines() + for (line in lines) { + echo "archiving: ${line}" + if (fileExists("${line}") && readFile("${line}").length() > 0 ){ + try { + archiveArtifacts artifacts: "${line}", fingerprint: true + error_logs = error_logs + "${HOMEgfs}/sorc/${line} " + error_logs_message = error_logs_message + "${HOMEgfs}/sorc/${line}\n" } + catch (Exception error_arch) { echo "Failed to archive error log ${line}: ${error_arch.getMessage()}" } } - sh(script: './link_workflow.sh') - //sh(script: "echo ${HOMEgfs} > BUILT_semaphor") } - } - if (env.CHANGE_ID && system == 'gfs') { try { - sh(script: """${GH} pr edit ${env.CHANGE_ID} --repo ${repo_url} --add-label "CI-${Machine}-Running" --remove-label "CI-${Machine}-Building" """) - } catch (Exception e) { - echo "Failed to update label from Buildng to Running: ${e.getMessage()}" + sh(script: "${HOMEgfs}/ci/scripts/utils/publish_logs.py --file ${error_logs} --repo PR_BUILD_${env.CHANGE_ID}") + gist_url=sh(script: "${HOMEgfs}/ci/scripts/utils/publish_logs.py --file ${error_logs} --gist PR_BUILD_${env.CHANGE_ID}", returnStdout: true).trim() + sh(script: """${GH} pr comment ${env.CHANGE_ID} --repo ${repo_url} --body "Build **FAILED** on **${Machine}** in Build# ${env.BUILD_NUMBER} with error logs:\n\\`\\`\\`\n${error_logs_message}\\`\\`\\`\n\nFollow link here to view the contents of the above file(s): [(link)](${gist_url})" """) + } catch (Exception error_comment) { + echo "Failed to comment on PR: ${error_comment.getMessage()}" } + STATUS = 'Failed' + error("Failed to build global-workflow on ${Machine}") } - if (system == 'gfs') { - cases = sh(script: "${HOMEgfs}/ci/scripts/utils/get_host_case_list.py ${machine}", returnStdout: true).trim().split() - echo "Cases to run: ${cases}" - } - } + } + sh(script: './link_workflow.sh') + } + if (env.CHANGE_ID) { + try { + sh(script: """${GH} pr edit ${env.CHANGE_ID} --repo ${repo_url} --add-label "CI-${Machine}-Running" --remove-label "CI-${Machine}-Building" """) + } catch (Exception e) { + echo "Failed to update label from Building to Running: ${e.getMessage()}" + } } - } + // Get a list of CI cases to run + CI_CASES = sh(script: "${HOMEgfs}/ci/scripts/utils/get_host_case_list.py ${machine}", returnStdout: true).trim().split() + echo "Cases to run: ${CI_CASES}" } } } @@ -191,21 +175,16 @@ pipeline { agent { label NodeName[machine].toLowerCase() } steps { script { - def parallelStages = cases.collectEntries { caseName -> + def parallelStages = CI_CASES.collectEntries { caseName -> ["${caseName}": { stage("Create ${caseName}") { script { - sh(script: "sed -n '/{.*}/!p' ${CUSTOM_WORKSPACE}/gfs/ci/cases/pr/${caseName}.yaml > ${CUSTOM_WORKSPACE}/gfs/ci/cases/pr/${caseName}.yaml.tmp") - def yaml_case = readYaml file: "${CUSTOM_WORKSPACE}/gfs/ci/cases/pr/${caseName}.yaml.tmp" - def build_system = yaml_case.experiment.system - def HOMEgfs = "${CUSTOM_WORKSPACE}/${build_system}" // local HOMEgfs is used to populate the XML on per system basis - env.HOME_GFS = HOMEgfs // setting path in HOMEgfs as an environment variable HOME_GFS for some systems that using the path in its .bashrc env.RUNTESTS = "${CUSTOM_WORKSPACE}/RUNTESTS" try { error_output = sh(script: "${HOMEgfs}/ci/scripts/utils/ci_utils_wrapper.sh create_experiment ${HOMEgfs}/ci/cases/pr/${caseName}.yaml", returnStdout: true).trim() } catch (Exception error_create) { - sh(script: """${GH} pr comment ${env.CHANGE_ID} --repo ${repo_url} --body "${Case} **FAILED** to create experment on ${Machine} in BUILD# ${env.BUILD_NUMBER}\n with the error:\n\\`\\`\\`\n${error_output}\\`\\`\\`" """) - error("Case ${caseName} failed to create experment directory") + sh(script: """${GH} pr comment ${env.CHANGE_ID} --repo ${repo_url} --body "${Case} **FAILED** to create experiment on ${Machine} in BUILD# ${env.BUILD_NUMBER}\n with the error:\n\\`\\`\\`\n${error_output}\\`\\`\\`" """) + error("Case ${caseName} failed to create experiment directory") } } } @@ -213,15 +192,11 @@ pipeline { stage("Running ${caseName}") { catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { script { - HOMEgfs = "${CUSTOM_WORKSPACE}/gfs" // common HOMEgfs is used to launch the scripts that run the experiments - env.HOME_GFS = HOMEgfs // setting path in HOMEgfs as an environment variable HOME_GFS for some systems that using the path in its .bashrc def pslot = sh(script: "${HOMEgfs}/ci/scripts/utils/ci_utils_wrapper.sh get_pslot ${CUSTOM_WORKSPACE}/RUNTESTS ${caseName}", returnStdout: true).trim() def error_file = "${CUSTOM_WORKSPACE}/RUNTESTS/${pslot}_error.logs" sh(script: " rm -f ${error_file}") - def yaml_case = readYaml file: "${CUSTOM_WORKSPACE}/gfs/ci/cases/pr/${caseName}.yaml.tmp" - def build_system = yaml_case.experiment.system try { - sh(script: "${HOMEgfs}/ci/scripts/run-check_ci.sh ${CUSTOM_WORKSPACE} ${pslot} ${build_system}") + sh(script: "${HOMEgfs}/ci/scripts/run-check_ci.sh ${CUSTOM_WORKSPACE} ${pslot} 'global-workflow'") sh(script: "${HOMEgfs}/ci/scripts/utils/ci_utils_wrapper.sh cleanup_experiment ${CUSTOM_WORKSPACE}/RUNTESTS/EXPDIR/${pslot}") } catch (Exception error_experment) { sh(script: "${HOMEgfs}/ci/scripts/utils/ci_utils_wrapper.sh cancel_batch_jobs ${pslot}") @@ -251,7 +226,7 @@ pipeline { echo "Failed to comment on PR: ${error_comment.getMessage()}" } } else { - echo "No error logs found for failed cases in $CUSTOM_WORKSPACE/RUNTESTS/${pslot}_error.logs" + echo "No error logs found for failed cases in ${CUSTOM_WORKSPACE}/RUNTESTS/${pslot}_error.logs" } STATUS = 'Failed' try { @@ -273,11 +248,10 @@ pipeline { } } - stage( '5. FINALIZE' ) { + stage( '5. Finalize' ) { agent { label NodeName[machine].toLowerCase() } steps { script { - env.HOME_GFS = "${CUSTOM_WORKSPACE}/gfs" // setting path to HOMEgfs as an environment variable HOME_GFS for some systems that using the path in its .bashrc sh(script: """ labels=\$(${GH} pr view ${env.CHANGE_ID} --repo ${repo_url} --json labels --jq '.labels[].name') for label in \$labels; do @@ -298,7 +272,7 @@ pipeline { echo "Failed to remove custom work directory ${CUSTOM_WORKSPACE} on ${Machine}: ${e.getMessage()}" } } else { - echo "Failed to build and run Global-workflow in ${CUSTOM_WORKSPACE} and on ${Machine}" + echo "Failed to build and run global-workflow in ${CUSTOM_WORKSPACE} on ${Machine}" } } } diff --git a/ci/cases/pr/C48_S2SWA_gefs.yaml b/ci/cases/pr/C48_S2SWA_gefs.yaml index f39031f1a1..856759b46a 100644 --- a/ci/cases/pr/C48_S2SWA_gefs.yaml +++ b/ci/cases/pr/C48_S2SWA_gefs.yaml @@ -18,4 +18,4 @@ arguments: yaml: {{ HOMEgfs }}/ci/cases/yamls/gefs_defaults_ci.yaml skip_ci_on_hosts: - - wcoss2 + - None diff --git a/ci/cases/pr/C96_S2SWA_gefs_replay_ics.yaml b/ci/cases/pr/C96_S2SWA_gefs_replay_ics.yaml index 7118dde53f..b5c2742406 100644 --- a/ci/cases/pr/C96_S2SWA_gefs_replay_ics.yaml +++ b/ci/cases/pr/C96_S2SWA_gefs_replay_ics.yaml @@ -19,4 +19,4 @@ arguments: icsdir: {{ 'ICSDIR_ROOT' | getenv }}/C96mx100/20240610 skip_ci_on_hosts: - - wcoss2 + - None diff --git a/ci/cases/yamls/build.yaml b/ci/cases/yamls/build.yaml deleted file mode 100644 index 2b2938719f..0000000000 --- a/ci/cases/yamls/build.yaml +++ /dev/null @@ -1,3 +0,0 @@ -builds: - - gefs: './build_all.sh -kw' - - gfs: './build_all.sh -kgu' diff --git a/ci/scripts/utils/ci_utils_wrapper.sh b/ci/scripts/utils/ci_utils_wrapper.sh index 51c392fb99..a4fd1776c8 100755 --- a/ci/scripts/utils/ci_utils_wrapper.sh +++ b/ci/scripts/utils/ci_utils_wrapper.sh @@ -3,7 +3,7 @@ HOMEgfs="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." >/dev/null 2>&1 && pwd )" source "${HOMEgfs}/ush/detect_machine.sh" -utitilty_function="${1}" +utility_function="${1}" source "${HOMEgfs}/ci/scripts/utils/ci_utils.sh" -${utitilty_function} "${@:2}" +${utility_function} "${@:2}" diff --git a/parm/config/gefs/config.fcst b/parm/config/gefs/config.fcst index d57e7e9e92..43e2724dc6 100644 --- a/parm/config/gefs/config.fcst +++ b/parm/config/gefs/config.fcst @@ -51,7 +51,11 @@ export esmf_logkind="ESMF_LOGKIND_MULTI_ON_ERROR" #Options: ESMF_LOGKIND_MULTI_O export FORECASTSH="${SCRgfs}/exglobal_forecast.sh" #export FORECASTSH="${SCRgfs}/exglobal_forecast.py" # Temp. while this is worked on -export FCSTEXEC="ufs_model.x" +if [[ "${SFS_POST:-}" == "YES" ]]; then + export FCSTEXEC="sfs_model.x" +else + export FCSTEXEC="gefs_model.x" +fi ####################################################################### # Model configuration @@ -105,7 +109,7 @@ if (( gwd_opt == 2 )); then export do_gsl_drag_ls_bl=".true." export do_gsl_drag_ss=".false." export do_gsl_drag_tofd=".true." - export do_gwd_opt_psl=".true." + export do_gwd_opt_psl=".true." export do_ugwp_v1_orog_only=".false." launch_level=$(echo "${LEVS}/2.35" |bc) export launch_level @@ -133,7 +137,7 @@ if [[ "${progsigma}" == ".true." ]]; then tbp="_progsigma" ; fi if [[ "${DO_AERO_FCST}" == "YES" ]]; then export IAER=2011 # spectral band mapping method for aerosol optical properties else - export IAER=1011 + export IAER=1011 fi export iovr_lw=3 ; #de-correlation length cloud overlap method (Barker, 2008) export iovr_sw=3 ; #de-correlation length cloud overlap method (Barker, 2008) diff --git a/parm/config/gfs/config.fcst b/parm/config/gfs/config.fcst index c95f8796e5..5be4f4eca7 100644 --- a/parm/config/gfs/config.fcst +++ b/parm/config/gfs/config.fcst @@ -62,7 +62,7 @@ export esmf_logkind="ESMF_LOGKIND_MULTI_ON_ERROR" #Options: ESMF_LOGKIND_MULTI_O export FORECASTSH="${SCRgfs}/exglobal_forecast.sh" #export FORECASTSH="${SCRgfs}/exglobal_forecast.py" # Temp. while this is worked on -export FCSTEXEC="ufs_model.x" +export FCSTEXEC="gfs_model.x" ####################################################################### # Model configuration @@ -116,7 +116,7 @@ if (( gwd_opt == 2 )); then export do_gsl_drag_ls_bl=".true." export do_gsl_drag_ss=".false." export do_gsl_drag_tofd=".true." - export do_gwd_opt_psl=".true." + export do_gwd_opt_psl=".true." export do_ugwp_v1_orog_only=".false." launch_level=$(echo "${LEVS}/2.35" |bc) export launch_level @@ -148,7 +148,7 @@ if [[ "${progsigma}" == ".true." ]]; then tbp="_progsigma" ; fi if [[ "${DO_AERO_FCST}" == "YES" ]]; then export IAER=2011 # spectral band mapping method for aerosol optical properties else - export IAER=1011 + export IAER=1011 fi export iovr_lw=3 ; #de-correlation length cloud overlap method (Barker, 2008) export iovr_sw=3 ; #de-correlation length cloud overlap method (Barker, 2008) diff --git a/scripts/exgfs_wave_post_pnt.sh b/scripts/exgfs_wave_post_pnt.sh index 06769303a1..96c60fc96c 100755 --- a/scripts/exgfs_wave_post_pnt.sh +++ b/scripts/exgfs_wave_post_pnt.sh @@ -271,18 +271,18 @@ source "${USHgfs}/preamble.sh" rm -f buoy_tmp.loc buoy_log.ww3 ww3_oup.inp ${NLN} ./out_pnt.${waveuoutpGRD} ./out_pnt.ww3 ${NLN} ./mod_def.${waveuoutpGRD} ./mod_def.ww3 - export pgm=ww3_outp;. prep_step - ${EXECgfs}/ww3_outp > buoy_lst.loc 2>&1 - export err=$?;err_chk + export pgm="${NET,,}_ww3_outp.x" + source prep_step + "${EXECgfs}/${pgm}" > buoy_lst.loc 2>&1 + export err=$?;err_chk if [ "$err" != '0' ] && [ ! -f buoy_log.ww3 ] then - pgm=wave_post set +x echo ' ' echo '******************************************** ' - echo '*** FATAL ERROR : ERROR IN ww3_outp *** ' + echo "*** FATAL ERROR : ERROR IN ${pgm} *** " echo '******************************************** ' echo ' ' cat buoy_tmp.loc diff --git a/sorc/build_all.sh b/sorc/build_all.sh index e75c853c39..9414846f2a 100755 --- a/sorc/build_all.sh +++ b/sorc/build_all.sh @@ -56,6 +56,7 @@ _wave_opt="" _hydro_opt="" _build_job_max=20 _quick_kill="NO" +_ufs_exec="-e gfs_model.x" # Reset option counter in case this script is sourced OPTIND=1 while getopts ":a:dfghj:kuvwy" option; do @@ -69,8 +70,8 @@ while getopts ":a:dfghj:kuvwy" option; do k) _quick_kill="YES" ;; u) _build_ufsda="YES" ;; v) _verbose_opt="-v";; - w) _wave_opt="-w";; - y) _hydro_opt="-y";; + w) _wave_opt="-w"; _ufs_exec="-e gefs_model.x";; + y) _hydro_opt="-y"; _ufs_exec="-e sfs_model.x";; :) echo "[${BASH_SOURCE[0]}]: ${option} requires an argument" _usage @@ -133,7 +134,7 @@ declare -A build_opts big_jobs=0 build_jobs["ufs"]=8 big_jobs=$((big_jobs+1)) -build_opts["ufs"]="${_wave_opt} ${_hydro_opt} ${_verbose_opt} ${_build_ufs_opt} ${_build_debug}" +build_opts["ufs"]="${_wave_opt} ${_hydro_opt} ${_verbose_opt} ${_build_ufs_opt} ${_build_debug} ${_ufs_exec}" build_jobs["upp"]=1 build_opts["upp"]="${_build_debug}" diff --git a/sorc/build_ufs.sh b/sorc/build_ufs.sh index 6432962a5a..773c104be3 100755 --- a/sorc/build_ufs.sh +++ b/sorc/build_ufs.sh @@ -8,8 +8,9 @@ APP="S2SWA" CCPP_SUITES="FV3_GFS_v17_p8_ugwpv1,FV3_GFS_v17_coupled_p8_ugwpv1,FV3_global_nest_v1" # TODO: does the g-w need to build with all these CCPP_SUITES? PDLIB="ON" HYDRO="OFF" +EXEC_NAME="gfs_model.x" -while getopts ":da:fj:vwy" option; do +while getopts ":da:fj:e:vwy" option; do case "${option}" in d) BUILD_TYPE="Debug";; a) APP="${OPTARG}";; @@ -18,6 +19,7 @@ while getopts ":da:fj:vwy" option; do v) export BUILD_VERBOSE="YES";; w) PDLIB="OFF";; y) HYDRO="ON";; + e) EXEC_NAME="${OPTARG}";; :) echo "[${BASH_SOURCE[0]}]: ${option} requires an argument" ;; @@ -40,13 +42,20 @@ if [[ ${BUILD_TYPE:-"Release"} = "DEBUG" ]] ; then elif [[ "${FASTER:-OFF}" == ON ]] ; then MAKE_OPT+=" -DFASTER=ON" fi -COMPILE_NR=0 + +case "${EXEC_NAME}" in + "ufs_model.x") COMPILE_ID=0 ;; + "gfs_model.x") COMPILE_ID=1 ;; + "gefs_model.x") COMPILE_ID=2 ;; + "sfs_model.x") COMPILE_ID=3 ;; + *) echo "Unsupported executable name: ${EXEC_NAME}"; exit 1 ;; +esac CLEAN_BEFORE=YES CLEAN_AFTER=NO -BUILD_JOBS=${BUILD_JOBS:-8} ./tests/compile.sh "${MACHINE_ID}" "${MAKE_OPT}" "${COMPILE_NR}" "intel" "${CLEAN_BEFORE}" "${CLEAN_AFTER}" -mv "./tests/fv3_${COMPILE_NR}.exe" ./tests/ufs_model.x -mv "./tests/modules.fv3_${COMPILE_NR}.lua" ./tests/modules.ufs_model.lua -cp "./modulefiles/ufs_common.lua" ./tests/ufs_common.lua +BUILD_JOBS=${BUILD_JOBS:-8} ./tests/compile.sh "${MACHINE_ID}" "${MAKE_OPT}" "${COMPILE_ID}" "intel" "${CLEAN_BEFORE}" "${CLEAN_AFTER}" +mv "./tests/fv3_${COMPILE_ID}.exe" "./tests/${EXEC_NAME}" +if [[ ! -f "./tests/modules.ufs_model.lua" ]]; then mv "./tests/modules.fv3_${COMPILE_ID}.lua" "./tests/modules.ufs_model.lua"; fi +if [[ ! -f "./tests/ufs_common.lua" ]]; then cp "./modulefiles/ufs_common.lua" ./tests/ufs_common.lua; fi exit 0 diff --git a/sorc/build_ww3prepost.sh b/sorc/build_ww3prepost.sh index 5c86774067..5668404db3 100755 --- a/sorc/build_ww3prepost.sh +++ b/sorc/build_ww3prepost.sh @@ -1,69 +1,56 @@ #! /usr/bin/env bash set -x -script_dir=$(dirname "${BASH_SOURCE[0]}") -cd "${script_dir}" || exit 1 +# shellcheck disable=SC2312 +_HOMEgfs=$(cd "$(dirname "$(readlink -f -n "${BASH_SOURCE[0]}" )" )/.." && pwd -P) +cd "${_HOMEgfs}/sorc" || exit 1 # Default settings -APP="S2SWA" PDLIB="ON" while getopts ":j:a:dvw" option; do case "${option}" in - a) APP="${OPTARG}";; - d) BUILD_TYPE="Debug";; - j) BUILD_JOBS="${OPTARG}";; - v) export BUILD_VERBOSE="YES";; - w) PDLIB="OFF";; - :) - echo "[${BASH_SOURCE[0]}]: ${option} requires an argument" - usage - ;; - *) - echo "[${BASH_SOURCE[0]}]: Unrecognized option: ${option}" - usage - ;; + d) BUILD_TYPE="Debug" ;; + j) BUILD_JOBS="${OPTARG}" ;; + v) export BUILD_VERBOSE="YES" ;; + w) PDLIB="OFF" ;; + :) + echo "[${BASH_SOURCE[0]}]: ${option} requires an argument" + usage + ;; + *) + echo "[${BASH_SOURCE[0]}]: Unrecognized option: ${option}" + usage + ;; esac done -# Determine which switch to use -if [[ "${APP}" == "ATMW" ]]; then - ww3switch="model/esmf/switch" -else - if [[ "${PDLIB}" == "ON" ]]; then - ww3switch="model/bin/switch_meshcap_pdlib" - else - ww3switch="model/bin/switch_meshcap" - fi -fi - -# Check final exec folder exists -if [[ ! -d "../exec" ]]; then - mkdir ../exec -fi - -finalexecdir="$( pwd -P )/../exec" - -#Determine machine and load modules +# Determine machine and load modules set +x -source "${script_dir}/ufs_model.fd/tests/detect_machine.sh" -source "${script_dir}/ufs_model.fd/tests/module-setup.sh" -module use "${script_dir}/ufs_model.fd/modulefiles" +source "${_HOMEgfs}/sorc/ufs_model.fd/tests/detect_machine.sh" +source "${_HOMEgfs}/sorc/ufs_model.fd/tests/module-setup.sh" +module use "${_HOMEgfs}/sorc/ufs_model.fd/modulefiles" module load "ufs_${MACHINE_ID}.intel" set -x -#Set WW3 directory, switch, prep and post exes -cd ufs_model.fd/WW3 || exit 1 -WW3_DIR=$( pwd -P ) +#Set WW3 directory +cd "${_HOMEgfs}/sorc/ufs_model.fd/WW3" || exit 1 +WW3_DIR=$(pwd -P) export WW3_DIR -export SWITCHFILE="${WW3_DIR}/${ww3switch}" -# Build exes for prep jobs and post jobs: -prep_exes="ww3_grid ww3_prep ww3_prnc ww3_grid" -post_exes="ww3_outp ww3_outf ww3_outp ww3_gint ww3_ounf ww3_ounp ww3_grib" +# Determine which switch to use +if [[ "${PDLIB}" == "ON" ]]; then + ww3switch="model/bin/switch_meshcap_pdlib" + path_build="${WW3_DIR}/build/pdlib_ON" + path_install="${WW3_DIR}/install/pdlib_ON" +else + ww3switch="model/bin/switch_meshcap" + path_build="${WW3_DIR}/build/pdlib_OFF" + path_install="${WW3_DIR}/install/pdlib_OFF" +fi +export SWITCHFILE="${WW3_DIR}/${ww3switch}" #create build directory: -path_build="${WW3_DIR}/build_SHRD" [[ -d "${path_build}" ]] && rm -rf "${path_build}" mkdir -p "${path_build}" || exit 1 cd "${path_build}" || exit 1 @@ -71,62 +58,50 @@ echo "Forcing a SHRD build" buildswitch="${path_build}/switch" -cat "${SWITCHFILE}" > "${path_build}/tempswitch" - -sed -e "s/DIST/SHRD/g"\ - -e "s/OMPG / /g"\ - -e "s/OMPH / /g"\ - -e "s/MPIT / /g"\ - -e "s/MPI / /g"\ - -e "s/PIO / /g"\ - -e "s/B4B / /g"\ - -e "s/PDLIB / /g"\ - -e "s/SCOTCH / /g"\ - -e "s/METIS / /g"\ - -e "s/NOGRB/NCEP2/g"\ - "${path_build}/tempswitch" > "${path_build}/switch" +cat "${SWITCHFILE}" >"${path_build}/tempswitch" + +sed -e "s/DIST/SHRD/g" \ + -e "s/OMPG / /g" \ + -e "s/OMPH / /g" \ + -e "s/MPIT / /g" \ + -e "s/MPI / /g" \ + -e "s/PIO / /g" \ + -e "s/B4B / /g" \ + -e "s/PDLIB / /g" \ + -e "s/SCOTCH / /g" \ + -e "s/METIS / /g" \ + -e "s/NOGRB/NCEP2/g" \ + "${path_build}/tempswitch" >"${path_build}/switch" rm "${path_build}/tempswitch" echo "Switch file is ${buildswitch} with switches:" cat "${buildswitch}" #define cmake build options -MAKE_OPT="-DCMAKE_INSTALL_PREFIX=install" +MAKE_OPT="-DCMAKE_INSTALL_PREFIX=${path_install}" [[ ${BUILD_TYPE:-"Release"} = "Debug" ]] && MAKE_OPT+=" -DCMAKE_BUILD_TYPE=Debug" #Build executables: # shellcheck disable=SC2086 cmake "${WW3_DIR}" -DSWITCH="${buildswitch}" ${MAKE_OPT} rc=$? -if (( rc != 0 )); then +if ((rc != 0)); then echo "Fatal error in cmake." exit "${rc}" fi + make -j "${BUILD_JOBS:-8}" rc=$? -if (( rc != 0 )); then +if ((rc != 0)); then echo "Fatal error in make." exit "${rc}" fi + make install -if (( rc != 0 )); then +rc=$? +if ((rc != 0)); then echo "Fatal error in make install." exit "${rc}" fi -# Copy to top-level exe directory -for prog in ${prep_exes} ${post_exes}; do - cp "${path_build}/install/bin/${prog}" "${finalexecdir}/" - rc=$? - if (( rc != 0 )); then - echo "FATAL: Unable to copy ${path_build}/${prog} to ${finalexecdir} (Error code ${rc})" - exit "${rc}" - fi -done - -#clean-up build directory: -echo "executables are in ${finalexecdir}" -echo "cleaning up ${path_build}" -rm -rf "${path_build}" - exit 0 diff --git a/sorc/link_workflow.sh b/sorc/link_workflow.sh index a43fd5b3f4..a89f070d41 100755 --- a/sorc/link_workflow.sh +++ b/sorc/link_workflow.sh @@ -2,11 +2,11 @@ #--make symbolic links for EMC installation and hardcopies for NCO delivery -HOMEgfs="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." >/dev/null 2>&1 && pwd )" +HOMEgfs="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." >/dev/null 2>&1 && pwd)" TRACE=NO source "${HOMEgfs}/ush/preamble.sh" function usage() { - cat << EOF + cat < "grib2_${grdnam}_${FH3}.out" 2>&1 + "${EXECgfs}/${pgm}" > "grib2_${grdnam}_${FH3}.out" 2>&1 export err=$?;err_chk - if [ ! -s gribfile ]; then set +x echo ' ' echo '************************************************ ' - echo '*** FATAL ERROR : ERROR IN ww3_grib encoding *** ' + echo "*** FATAL ERROR : ERROR IN ${pgm} encoding *** " echo '************************************************ ' echo ' ' set_trace exit 3 fi - if (( fhr > 0 )); then + if (( fhr > 0 )); then ${WGRIB2} gribfile -set_date "${PDY}${cyc}" -set_ftime "${fhr} hour fcst" -grib "${COMOUT_WAVE_GRID}/${outfile}" err=$? else @@ -169,7 +170,7 @@ if [[ ! -s "${COMOUT_WAVE_GRID}/${outfile}.idx" ]]; then set +x echo ' ' echo '********************************************* ' - echo '*** FATAL ERROR : ERROR IN ww3_grib2 *** ' + echo "*** FATAL ERROR : ERROR IN ${pgm} *** " # FIXME: This is not an error in $pgm, but in WGRIB2 echo '********************************************* ' echo ' ' set_trace @@ -197,7 +198,7 @@ if [[ ! -s "${COMOUT_WAVE_GRID}/${outfile}.idx" ]]; then set +x echo ' ' echo '********************************************* ' - echo '*** FATAL ERROR : ERROR IN ww3_grib2 *** ' + echo "*** FATAL ERROR : ERROR IN ${pgm} *** " echo '********************************************* ' echo ' ' echo " Error in moving grib file ${outfile} to com" @@ -209,7 +210,7 @@ if [[ ! -s "${COMOUT_WAVE_GRID}/${outfile}.idx" ]]; then set +x echo ' ' echo '*************************************************** ' - echo '*** FATAL ERROR : ERROR IN ww3_grib2 INDEX FILE *** ' + echo "*** FATAL ERROR : ERROR IN ${pgm} INDEX FILE *** " echo '*************************************************** ' echo ' ' echo " Error in moving grib file ${outfile}.idx to com" diff --git a/ush/wave_grid_interp_sbs.sh b/ush/wave_grid_interp_sbs.sh index 31b7808c16..d56c5d0763 100755 --- a/ush/wave_grid_interp_sbs.sh +++ b/ush/wave_grid_interp_sbs.sh @@ -133,17 +133,18 @@ source "${USHgfs}/preamble.sh" # 1.b Run interpolation code + export pgm="${NET,,}_ww3_gint.x" + source prep_step + set +x - echo " Run ww3_gint - echo " Executing ${EXECgfs}/ww3_gint + echo " Executing ${pgm}" set_trace - export pgm=ww3_gint;. prep_step - ${EXECgfs}/ww3_gint 1> gint.${grdID}.out 2>&1 + "${EXECgfs}/${pgm}" 1> gint.${grdID}.out 2>&1 export err=$?;err_chk # Write interpolation file to main TEMP dir area if not there yet - if [ "wht_OK" = 'no' ] + if [ "wht_OK" = 'no' ] # FIXME: This is never going to evaluate to true, wht_OK is a string and needs to be ${wht_OK}. With ${wht_OK}, the next line is trying to copy into ${FIXgfs} space. This leads to a Permission denied error. The logic here needs to be evaluated and recoded. #TODO then cp -f ./WHTGRIDINT.bin ${DATA}/ww3_gint.WHTGRIDINT.bin.${grdID} cp -f ./WHTGRIDINT.bin ${FIXgfs}/wave/ww3_gint.WHTGRIDINT.bin.${grdID} @@ -155,7 +156,7 @@ source "${USHgfs}/preamble.sh" set +x echo ' ' echo '*************************************************** ' - echo '*** FATAL ERROR : ERROR IN ww3_gint interpolation * ' + echo "*** FATAL ERROR : ERROR IN ${pgm} interpolation * " echo '*************************************************** ' echo ' ' set_trace diff --git a/ush/wave_grid_moddef.sh b/ush/wave_grid_moddef.sh index 1e8c44054a..dd0ee204f6 100755 --- a/ush/wave_grid_moddef.sh +++ b/ush/wave_grid_moddef.sh @@ -1,5 +1,5 @@ #! /usr/bin/env bash - + ################################################################################ # # UNIX Script Documentation Block @@ -72,27 +72,28 @@ source "${USHgfs}/preamble.sh" fi # --------------------------------------------------------------------------- # -# 2. Create mod_def file +# 2. Create mod_def file set +x echo ' ' echo ' Creating mod_def file ...' - echo " Executing ${EXECgfs}/ww3_grid" + echo " Executing ${EXECgfs}/${NET,,}_ww3_grid.x" echo ' ' set_trace - - rm -f ww3_grid.inp + + rm -f ww3_grid.inp ${NLN} ../ww3_grid.inp.$grdID ww3_grid.inp if [ -f ../${grdID}.msh ] then - rm -f ${grdID}.msh + rm -f ${grdID}.msh ${NLN} ../${grdID}.msh ${grdID}.msh fi - - "${EXECgfs}/ww3_grid" 1> "grid_${grdID}.out" 2>&1 + export pgm="${NET,,}_ww3_grid.x" + + "${EXECgfs}/${pgm}" 1> "grid_${grdID}.out" 2>&1 err=$? if [ "$err" != '0' ] @@ -100,13 +101,13 @@ source "${USHgfs}/preamble.sh" set +x echo ' ' echo '******************************************** ' - echo '*** FATAL ERROR : ERROR IN ww3_grid *** ' + echo "*** FATAL ERROR : ERROR IN ${pgm} *** " echo '******************************************** ' echo ' ' set_trace exit 3 fi - + if [[ -f mod_def.ww3 ]] then cp mod_def.ww3 "${COMOUT_WAVE_PREP}/${RUN}wave.mod_def.${grdID}" diff --git a/ush/wave_outp_spec.sh b/ush/wave_outp_spec.sh index 37accbae49..929979bbf9 100755 --- a/ush/wave_outp_spec.sh +++ b/ush/wave_outp_spec.sh @@ -161,21 +161,21 @@ source "${USHgfs}/preamble.sh" # 2.b Run the postprocessor + export pgm="${NET,,}_ww3_outp.x" + source prep_step + set +x - echo " Executing ${EXECgfs}/ww3_outp" + echo " Executing ${EXECgfs}/${pgm}" set_trace - export pgm=ww3_outp;. prep_step - ${EXECgfs}/ww3_outp 1> outp_${specdir}_${buoy}.out 2>&1 + "${EXECgfs}/${pgm}" 1> outp_${specdir}_${buoy}.out 2>&1 export err=$?;err_chk - - if [ "$err" != '0' ] then set +x echo ' ' echo '******************************************** ' - echo '*** FATAL ERROR : ERROR IN ww3_outp *** ' + echo '*** FATAL ERROR : ERROR IN ${pgm} *** ' echo '******************************************** ' echo ' ' set_trace @@ -219,7 +219,7 @@ source "${USHgfs}/preamble.sh" set +x echo ' ' echo '***************************************************************** ' - echo '*** FATAL ERROR : OUTPUT DATA FILE FOR BOUY $bouy NOT FOUND *** ' + echo "*** FATAL ERROR : OUTPUT DATA FILE FOR BOUY ${bouy} NOT FOUND *** " echo '***************************************************************** ' echo ' ' set_trace diff --git a/ush/wave_prnc_cur.sh b/ush/wave_prnc_cur.sh index 927710c581..cfd499330f 100755 --- a/ush/wave_prnc_cur.sh +++ b/ush/wave_prnc_cur.sh @@ -74,22 +74,22 @@ rm -f cur.nc ${NLN} "cur_glo_uv_${PDY}_${fext}${fh3}_5min.nc" "cur.nc" ${NLN} "${DATA}/mod_def.${WAVECUR_FID}" ./mod_def.ww3 -export pgm=ww3_prnc;. prep_step -${EXECgfs}/ww3_prnc 1> prnc_${WAVECUR_FID}_${ymdh_rtofs}.out 2>&1 +export pgm="${NET,,}_ww3_prnc.x" +source prep_step +"${EXECgfs}/${pgm}" 1> prnc_${WAVECUR_FID}_${ymdh_rtofs}.out 2>&1 export err=$?; err_chk - if [ "$err" != '0' ] then cat prnc_${WAVECUR_FID}_${ymdh_rtofs}.out set $setoff echo ' ' echo '******************************************** ' - echo '*** WARNING: NON-FATAL ERROR IN ww3_prnc *** ' + echo "*** WARNING: NON-FATAL ERROR IN ${pgm} *** " echo '******************************************** ' echo ' ' set $seton - echo "WARNING: NON-FATAL ERROR IN ww3_prnc." + echo "WARNING: NON-FATAL ERROR IN ${pgm}." exit 4 fi diff --git a/ush/wave_prnc_ice.sh b/ush/wave_prnc_ice.sh index be089c30bd..d812bccd10 100755 --- a/ush/wave_prnc_ice.sh +++ b/ush/wave_prnc_ice.sh @@ -32,7 +32,7 @@ source "${USHgfs}/preamble.sh" # 0.a Basic modes of operation cd $DATA - + rm -rf ice mkdir ice cd ice @@ -57,7 +57,7 @@ source "${USHgfs}/preamble.sh" if [[ -z "${YMDH}" ]] || [[ -z "${cycle}" ]] || \ [[ -z "${COMOUT_WAVE_PREP}" ]] || [[ -z "${FIXgfs}" ]] || [[ -z "${EXECgfs}" ]] || \ [[ -z "${WAV_MOD_TAG}" ]] || [[ -z "${WAVEICE_FID}" ]] || [[ -z "${COMIN_OBS}" ]]; then - + set +x echo ' ' echo '**************************************************' @@ -129,7 +129,7 @@ source "${USHgfs}/preamble.sh" fi rm -f wgrib.out - rm -f ice.grib + rm -f ice.grib rm -f ice.index @@ -142,14 +142,14 @@ source "${USHgfs}/preamble.sh" cp -f ${DATA}/ww3_prnc.ice.$WAVEICE_FID.inp.tmpl ww3_prnc.inp - export pgm=ww3_prnc;. prep_step + export pgm="${NET,,}_ww3_prnc.x" + source prep_step - ${EXECgfs}/ww3_prnc 1> prnc_${WAVEICE_FID}_${cycle}.out 2>&1 + "${EXECgfs}/${pgm}" 1> prnc_${WAVEICE_FID}_${cycle}.out 2>&1 export err=$?; err_chk - if [ "$err" != '0' ] then - cat prnc_${WAVEICE_FID}_${cycle}.out + cat prnc_${WAVEICE_FID}_${cycle}.out set +x echo ' ' echo '******************************************** ' @@ -170,13 +170,13 @@ source "${USHgfs}/preamble.sh" # and only WAV_MOD_ID if WW3ATMIENS=F # if [ "${WW3ATMIENS}" = "T" ] - then + then icefile=${WAV_MOD_TAG}.${WAVEICE_FID}.$cycle.ice elif [ "${WW3ATMIENS}" = "F" ] - then + then icefile=${RUN}wave.${WAVEICE_FID}.$cycle.ice fi - + set +x echo " Saving ice.ww3 as ${COMOUT_WAVE_PREP}/${icefile}" set_trace From b6936ee558b9b93cba1cbfd2a080f85f78774c48 Mon Sep 17 00:00:00 2001 From: David Huber <69919478+DavidHuber-NOAA@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:44:23 -0500 Subject: [PATCH 08/10] Hotfix for gdas_arch div/0 (#3169) This fixes a div/0 error when `ARCH_EXPDIR_FREQ=0`. Resolves #3168 --- ush/python/pygfs/task/archive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ush/python/pygfs/task/archive.py b/ush/python/pygfs/task/archive.py index c6376206b3..ed63a22230 100644 --- a/ush/python/pygfs/task/archive.py +++ b/ush/python/pygfs/task/archive.py @@ -487,7 +487,7 @@ def _archive_expdir(self, arch_dict: Dict[str, Any]) -> bool: if current_cycle in [first_full, edate]: # Always save the first and last return True - elif (current_cycle - first_full).total_seconds() % freq == 0: + elif freq != 0 and (current_cycle - first_full).total_seconds() % freq == 0: # Otherwise, the frequency is in hours return True else: From ef37fe33c215ee604bfb1bd7903b83d1efd20daf Mon Sep 17 00:00:00 2001 From: DavidNew-NOAA <134300700+DavidNew-NOAA@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:40:07 -0500 Subject: [PATCH 09/10] Turn DO_TEST_MODE off (#3177) # Description This PR turns off the DO_TEST_MODE flag in the CI tests, which will turn off regression testing for now. We need to discuss our testing strategy, but in the meantime regression testing is holding up other PRs. --- ci/cases/yamls/atmaerosnowDA_defaults_ci.yaml | 2 +- ci/cases/yamls/gfs_defaults_ci.yaml | 2 +- ci/cases/yamls/gfs_extended_ci.yaml | 2 +- ci/cases/yamls/soca_gfs_defaults_ci.yaml | 2 +- ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ci/cases/yamls/atmaerosnowDA_defaults_ci.yaml b/ci/cases/yamls/atmaerosnowDA_defaults_ci.yaml index 24f629128a..7e88abb1a0 100644 --- a/ci/cases/yamls/atmaerosnowDA_defaults_ci.yaml +++ b/ci/cases/yamls/atmaerosnowDA_defaults_ci.yaml @@ -3,4 +3,4 @@ defaults: base: DO_JEDISNOWDA: "YES" ACCOUNT: {{ 'HPC_ACCOUNT' | getenv }} - DO_TEST_MODE: "YES" + DO_TEST_MODE: "NO" diff --git a/ci/cases/yamls/gfs_defaults_ci.yaml b/ci/cases/yamls/gfs_defaults_ci.yaml index 65d440ac93..d3dacfb271 100644 --- a/ci/cases/yamls/gfs_defaults_ci.yaml +++ b/ci/cases/yamls/gfs_defaults_ci.yaml @@ -2,4 +2,4 @@ defaults: !INC {{ HOMEgfs }}/parm/config/gfs/yaml/defaults.yaml base: ACCOUNT: {{ 'HPC_ACCOUNT' | getenv }} - DO_TEST_MODE: "YES" + DO_TEST_MODE: "NO" diff --git a/ci/cases/yamls/gfs_extended_ci.yaml b/ci/cases/yamls/gfs_extended_ci.yaml index e60350ad8a..2e7a173994 100644 --- a/ci/cases/yamls/gfs_extended_ci.yaml +++ b/ci/cases/yamls/gfs_extended_ci.yaml @@ -12,4 +12,4 @@ base: FCST_BREAKPOINTS: 192 FHMAX_GFS: 384 FHMAX_HF_GFS: 120 - DO_TEST_MODE: "YES" + DO_TEST_MODE: "NO" diff --git a/ci/cases/yamls/soca_gfs_defaults_ci.yaml b/ci/cases/yamls/soca_gfs_defaults_ci.yaml index 69971537c2..dbddcf23bb 100644 --- a/ci/cases/yamls/soca_gfs_defaults_ci.yaml +++ b/ci/cases/yamls/soca_gfs_defaults_ci.yaml @@ -6,6 +6,6 @@ base: marineanl: SOCA_NINNER: 1 - DO_TEST_MODE: "YES" + DO_TEST_MODE: "NO" marineanl: JCB_ALGO_YAML_VAR: "{{ HOMEgfs }}/sorc/gdas.cd/test/gw-ci/soca/jcb-prototype_3dfgat_3DVarAOWCDA.yaml.j2" diff --git a/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml b/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml index b7344e8e35..ca16545399 100644 --- a/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml +++ b/ci/cases/yamls/ufs_hybatmDA_defaults.ci.yaml @@ -5,7 +5,7 @@ base: DO_JEDIATMVAR: "YES" DO_JEDIATMENS: "YES" ACCOUNT: {{ 'HPC_ACCOUNT' | getenv }} - DO_TEST_MODE: "YES" + DO_TEST_MODE: "NO" atmanl: JCB_ALGO_YAML_VAR: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jcb-prototype_3dvar_ufs_hybatmDA.yaml.j2" JCB_ALGO_YAML_FV3INC: "${HOMEgfs}/sorc/gdas.cd/test/gw-ci/atm/jcb-prototype_3dvar-fv3inc_ufs_hybatmDA.yaml.j2" From 2595e607fd905306939166a5e550e60683091bb0 Mon Sep 17 00:00:00 2001 From: CatherineThomas-NOAA <59020064+CatherineThomas-NOAA@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:45:03 -0500 Subject: [PATCH 10/10] Update compression options for high res history files (#3178) Different compression options are applied for the high resolution history files. The value of `quantize_nsd` will be different depending on the value of `quantize_mode`, so a fix is required to obtain the same behavior as the v16 compression options. Resolves: #3129 Co-authored-by: Rahul Mahajan --- parm/config/gfs/config.ufs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parm/config/gfs/config.ufs b/parm/config/gfs/config.ufs index 6309c4073b..3f8e7022fa 100644 --- a/parm/config/gfs/config.ufs +++ b/parm/config/gfs/config.ufs @@ -369,7 +369,7 @@ case ${fv3_res} in "C384" | "C768" | "C1152" | "C3072") zstandard_level=0 ideflate=1 - quantize_nsd=5 + quantize_nsd=14 OUTPUT_FILETYPE_ATM="netcdf_parallel" if [[ "${fv3_res}" == "C384" ]]; then OUTPUT_FILETYPE_SFC="netcdf" # For C384, the write grid component is better off with serial netcdf