diff --git a/jobs/JGLOBAL_ARCHIVE b/jobs/JGLOBAL_ARCHIVE index e8fae44330..d802ea5a22 100755 --- a/jobs/JGLOBAL_ARCHIVE +++ b/jobs/JGLOBAL_ARCHIVE @@ -13,9 +13,10 @@ YMD=${PDY} HH=${cyc} generate_com -rx COM_ATMOS_ANALYSIS COM_ATMOS_BUFR COM_ATMO COM_ATMOS_GENESIS COM_ATMOS_HISTORY COM_ATMOS_INPUT COM_ATMOS_MASTER COM_ATMOS_RESTART \ COM_ATMOS_TRACK COM_ATMOS_WMO \ COM_CHEM_HISTORY \ - COM_ICE_HISTORY COM_ICE_INPUT \ + COM_MED_RESTART \ + COM_ICE_HISTORY COM_ICE_INPUT COM_ICE_RESTART \ COM_OBS COM_TOP \ - COM_OCEAN_HISTORY COM_OCEAN_INPUT COM_OCEAN_XSECT COM_OCEAN_2D COM_OCEAN_3D \ + COM_OCEAN_HISTORY COM_OCEAN_INPUT COM_OCEAN_RESTART COM_OCEAN_XSECT COM_OCEAN_2D COM_OCEAN_3D \ COM_WAVE_GRID COM_WAVE_HISTORY COM_WAVE_STATION for grid in "0p25" "0p50" "1p00"; do diff --git a/jobs/JGLOBAL_FORECAST b/jobs/JGLOBAL_FORECAST index 5be44a8c97..46d7d55dc7 100755 --- a/jobs/JGLOBAL_FORECAST +++ b/jobs/JGLOBAL_FORECAST @@ -30,10 +30,11 @@ fi # Ignore possible spelling error (nothing is misspelled) # shellcheck disable=SC2153 -GDATE=$(${NDATE} -"${assim_freq}" "${PDY}${cyc}") +GDATE=$(date -d "${PDY} ${cyc} - ${assim_freq} hours" +%Y%m%d%H) +declare -rx GDATE # shellcheck disable= -declare -x gPDY="${GDATE:0:8}" -declare -x gcyc="${GDATE:8:2}" +declare -rx gPDY="${GDATE:0:8}" +declare -rx gcyc="${GDATE:8:2}" # Construct COM variables from templates (see config.com) YMD=${PDY} HH=${cyc} generate_com -rx COM_ATMOS_RESTART COM_ATMOS_INPUT COM_ATMOS_ANALYSIS \ diff --git a/jobs/rocoto/coupled_ic.sh b/jobs/rocoto/coupled_ic.sh index 17a1641c82..8b0088834d 100755 --- a/jobs/rocoto/coupled_ic.sh +++ b/jobs/rocoto/coupled_ic.sh @@ -1,45 +1,27 @@ #! /usr/bin/env bash -source "$HOMEgfs/ush/preamble.sh" +source "${HOMEgfs}/ush/preamble.sh" -############################################################### -## Abstract: -## Copy initial conditions from BASE_CPLIC to ROTDIR for coupled forecast-only runs -## HOMEgfs : /full/path/to/workflow -## EXPDIR : /full/path/to/config/files -## CDUMP : cycle name (gdas / gfs) -## PDY : current date (YYYYMMDD) -## cyc : current cycle (HH) -############################################################### - -############################################################### # Source FV3GFS workflow modules . ${HOMEgfs}/ush/load_fv3gfs_modules.sh status=$? [[ ${status} -ne 0 ]] && exit ${status} -err=0 -############################################################### -# Source relevant configs -configs="base coupled_ic wave" -for config in ${configs}; do - . ${EXPDIR}/config.${config} - status=$? - [[ ${status} -ne 0 ]] && exit ${status} -done +export job="coupled_ic" +export jobid="${job}.$$" -############################################################### -# Source machine runtime environment -. ${BASE_ENV}/${machine}.env config.coupled_ic -status=$? -[[ ${status} -ne 0 ]] && exit ${status} +# Execute the JJOB + +source "${HOMEgfs}/ush/jjob_header.sh" -e "coupled_ic" -c "base coupled_ic" -############################################################### # Locally scoped variables and functions GDATE=$(date -d "${PDY} ${cyc} - ${assim_freq} hours" +%Y%m%d%H) gPDY="${GDATE:0:8}" gcyc="${GDATE:8:2}" +# Initialize return code +err=0 + error_message(){ echo "FATAL ERROR: Unable to copy ${1} to ${2} (Error code ${3})" } @@ -78,10 +60,9 @@ if [[ "${DO_OCN:-}" = "YES" ]]; then [[ ${rc} -ne 0 ]] && error_message "${source}" "${target}" "${rc}" err=$((err + rc)) case "${OCNRES}" in - "500") - echo "Do not have Mom.res_*.nc files for 5 deg ocean" - ;; - "025") + "500" | "100") # Only 5 degree or 1 degree ocean does not have MOM.res_[1-4].nc files + ;; + "025") # Only 1/4 degree ocean has MOM.res_[1-4].nc files for nn in $(seq 1 4); do source="${BASE_CPLIC}/${CPL_OCNIC}/${PDY}${cyc}/ocn/${OCNRES}/MOM.res_${nn}.nc" if [[ -f "${source}" ]]; then @@ -101,9 +82,9 @@ if [[ "${DO_OCN:-}" = "YES" ]]; then esac fi -# Stage ice initial conditions to ROTDIR (cold start as these are SIS2 generated) +# Stage ice initial conditions to ROTDIR (warm start) if [[ "${DO_ICE:-}" = "YES" ]]; then - YMD=${PDY} HH=${cyc} generate_com -r COM_ICE_RESTART + YMD=${gPDY} HH=${gcyc} generate_com -r COM_ICE_RESTART [[ ! -d "${COM_ICE_RESTART}" ]] && mkdir -p "${COM_ICE_RESTART}" ICERESdec=$(echo "${ICERES}" | awk '{printf "%0.2f", $1/100}') source="${BASE_CPLIC}/${CPL_ICEIC}/${PDY}${cyc}/ice/${ICERES}/cice5_model_${ICERESdec}.res_${PDY}${cyc}.nc" @@ -137,4 +118,4 @@ fi ############################################################## # Exit cleanly -exit 0 +exit "${err}" diff --git a/parm/config/gfs/config.base.emc.dyn b/parm/config/gfs/config.base.emc.dyn index 30f353c242..282e5a53d3 100644 --- a/parm/config/gfs/config.base.emc.dyn +++ b/parm/config/gfs/config.base.emc.dyn @@ -167,7 +167,7 @@ case "${CASE}" in export waveGRD='glo_500' ;; "C96") - export OCNRES=100 + export OCNRES=500 export waveGRD='glo_200' ;; "C192") diff --git a/parm/config/gfs/config.efcs b/parm/config/gfs/config.efcs index 556750af10..534daf470c 100644 --- a/parm/config/gfs/config.efcs +++ b/parm/config/gfs/config.efcs @@ -5,20 +5,20 @@ echo "BEGIN: config.efcs" -# TODO: the _ENKF counterparts need to be defined in config.base +# TODO: the _ENKF counterparts need to be defined in config.base; for now inherit from config.base # TODO: Using different values for ensemble doesn't work because # config.fcst sets a bunch of derived values based on these # that is not duplicated here. [#1692] -# export DO_AERO=${DO_AERO_ENKF:-"NO"} -# export DO_OCN=${DO_OCN_ENKF:-"NO"} -# export DO_ICE=${DO_ICE_ENKF:-"NO"} -# export DO_WAVE=${DO_WAVE_ENKF:-"NO"} +export DO_AERO=${DO_AERO_ENKF:-${DO_AERO:-"NO"}} +export DO_OCN=${DO_OCN_ENKF:-${DO_OCN:-"NO"}} +export DO_ICE=${DO_ICE_ENKF:-${DO_ICE:-"NO"}} +export DO_WAVE=${DO_WAVE_ENKF:-${DO_WAVE:-"NO"}} # TODO: Possibly need OCNRES_ENKF, ICERES_ENKF, WAVRES_ENKF too if [[ ${DO_OCN} == "YES" ]]; then case "${CASE_ENS}" in "C48") export OCNRES=500;; - "C96") export OCNRES=100;; + "C96") export OCNRES=500;; "C192") export OCNRES=050;; "C384") export OCNRES=025;; "C768") export OCNRES=025;; @@ -84,18 +84,4 @@ else export restart_interval="6" fi -# wave model -export cplwav=.false. - -# ocean model resolution -case "${CASE_ENS}" in - "C48") export OCNRES=500;; - "C96") export OCNRES=100;; - "C192") export OCNRES=050;; - "C384") export OCNRES=025;; - "C768") export OCNRES=025;; - *) export OCNRES=025;; -esac -export ICERES=${OCNRES} - echo "END: config.efcs" diff --git a/scripts/exgdas_enkf_fcst.sh b/scripts/exgdas_enkf_fcst.sh index 80c76f5863..d2e3b9f73c 100755 --- a/scripts/exgdas_enkf_fcst.sh +++ b/scripts/exgdas_enkf_fcst.sh @@ -18,33 +18,13 @@ #### ################################################################################ -source "$HOMEgfs/ush/preamble.sh" - -# Directories. -export FIX_DIR=${FIX_DIR:-$HOMEgfs/fix} -export FIX_AM=${FIX_AM:-$FIX_DIR/am} - -# Utilities -export NCP=${NCP:-"/bin/cp -p"} -export NMV=${NMV:-"/bin/mv"} -export NLN=${NLN:-"/bin/ln -sf"} - -# Scripts. -FORECASTSH=${FORECASTSH:-$HOMEgfs/scripts/exglobal_forecast.sh} +source "${HOMEgfs}/ush/preamble.sh" # Enemble group, begin and end ENSGRP=${ENSGRP:-1} ENSBEG=${ENSBEG:-1} ENSEND=${ENSEND:-1} -# Model builds -export FCSTEXECDIR=${FCSTEXECDIR:-$HOMEgfs/sorc/fv3gfs.fd/BUILD/bin} -export FCSTEXEC=${FCSTEXEC:-fv3gfs.x} - -# Get DA specific diag table. -export PARM_FV3DIAG=${PARM_FV3DIAG:-$HOMEgfs/parm/parm_fv3diag} -export DIAG_TABLE=${DIAG_TABLE_ENKF:-${DIAG_TABLE:-$PARM_FV3DIAG/diag_table_da}} - # Re-run failed members, or entire group RERUN_EFCSGRP=${RERUN_EFCSGRP:-"YES"} @@ -52,24 +32,20 @@ RERUN_EFCSGRP=${RERUN_EFCSGRP:-"YES"} RECENTER_ENKF=${RECENTER_ENKF:-"YES"} export PREFIX_ATMINC=${PREFIX_ATMINC:-""} -# Ops related stuff -SENDECF=${SENDECF:-"NO"} -SENDDBN=${SENDDBN:-"NO"} - ################################################################################ # Preprocessing -cd $DATA || exit 99 -DATATOP=$DATA +cd "${DATA}" || exit 99 +DATATOP=${DATA} ################################################################################ # Set output data EFCSGRP="${COM_TOP}/efcs.grp${ENSGRP}" -if [ -f $EFCSGRP ]; then - if [ $RERUN_EFCSGRP = "YES" ]; then - rm -f $EFCSGRP +if [[ -f ${EFCSGRP} ]]; then + if [[ ${RERUN_EFCSGRP} = "YES" ]]; then + rm -f "${EFCSGRP}" else - echo "RERUN_EFCSGRP = $RERUN_EFCSGRP, will re-run FAILED members only!" - $NMV $EFCSGRP ${EFCSGRP}.fail + echo "RERUN_EFCSGRP = ${RERUN_EFCSGRP}, will re-run FAILED members only!" + ${NMV} "${EFCSGRP}" "${EFCSGRP}.fail" fi fi @@ -119,7 +95,7 @@ export FHZER=${FHZER_ENKF:-${FHZER:-6}} export FHCYC=${FHCYC_ENKF:-${FHCYC:-6}} # Set PREFIX_ATMINC to r when recentering on -if [ $RECENTER_ENKF = "YES" ]; then +if [[ ${RECENTER_ENKF} = "YES" ]]; then export PREFIX_ATMINC="r" fi @@ -132,21 +108,21 @@ declare -x gcyc="${GDATE:8:2}" ################################################################################ # Run forecast for ensemble member rc=0 -for imem in $(seq $ENSBEG $ENSEND); do +for imem in $(seq "${ENSBEG}" "${ENSEND}"); do - cd $DATATOP + cd "${DATATOP}" - cmem=$(printf %03i $imem) + cmem=$(printf %03i "${imem}") memchar="mem${cmem}" - echo "Processing MEMBER: $cmem" + echo "Processing MEMBER: ${cmem}" ra=0 skip_mem="NO" - if [ -f ${EFCSGRP}.fail ]; then - memstat=$(cat ${EFCSGRP}.fail | grep "MEMBER $cmem" | grep "PASS" | wc -l) - [[ $memstat -eq 1 ]] && skip_mem="YES" + if [[ -f ${EFCSGRP}.fail ]]; then + memstat=$(grep "MEMBER ${cmem}" "${EFCSGRP}.fail" | grep -c "PASS") + [[ ${memstat} -eq 1 ]] && skip_mem="YES" fi # Construct COM variables from templates (see config.com) @@ -177,70 +153,70 @@ for imem in $(seq $ENSBEG $ENSEND); do fi - if [ $skip_mem = "NO" ]; then + if [[ ${skip_mem} = "NO" ]]; then ra=0 - export MEMBER=$imem + export MEMBER=${imem} export DATA="${DATATOP}/${memchar}" - if [ -d $DATA ]; then rm -rf $DATA; fi - mkdir -p $DATA - $FORECASTSH + if [[ -d ${DATA} ]]; then rm -rf "${DATA}"; fi + mkdir -p "${DATA}" + ${FORECASTSH} ra=$? # Notify a member forecast failed and abort - if [ $ra -ne 0 ]; then - err_exit "FATAL ERROR: forecast of member $cmem FAILED. Aborting job" + if [[ ${ra} -ne 0 ]]; then + err_exit "FATAL ERROR: forecast of member ${cmem} FAILED. Aborting job" fi rc=$((rc+ra)) fi - if [ $SENDDBN = YES ]; then - fhr=$FHOUT - while [ $fhr -le $FHMAX ]; do - FH3=$(printf %03i $fhr) - if [ $(expr $fhr % 3) -eq 0 ]; then + if [[ ${SENDDBN} = YES ]]; then + fhr=${FHOUT} + while [[ ${fhr} -le ${FHMAX} ]]; do + FH3=$(printf %03i "${fhr}") + if (( fhr % 3 == 0 )); then "${DBNROOT}/bin/dbn_alert" MODEL GFS_ENKF "${job}" "${COM_ATMOS_HISTORY}/${RUN}.t${cyc}z.sfcf${FH3}.nc" fi fhr=$((fhr+FHOUT)) done fi - cd $DATATOP + cd "${DATATOP}" - if [ -s $EFCSGRP ]; then - $NCP $EFCSGRP log_old + if [[ -s ${EFCSGRP} ]]; then + ${NCP} "${EFCSGRP}" log_old fi [[ -f log ]] && rm log [[ -f log_new ]] && rm log_new - if [ $ra -ne 0 ]; then - echo "MEMBER $cmem : FAIL" > log + if [[ ${ra} -ne 0 ]]; then + echo "MEMBER ${cmem} : FAIL" > log else - echo "MEMBER $cmem : PASS" > log + echo "MEMBER ${cmem} : PASS" > log fi - if [ -s log_old ] ; then + if [[ -s log_old ]] ; then cat log_old log > log_new else cat log > log_new fi - $NCP log_new $EFCSGRP + ${NCP} log_new "${EFCSGRP}" done ################################################################################ # Echo status of ensemble group -cd $DATATOP -echo "Status of ensemble members in group $ENSGRP:" -cat $EFCSGRP -[[ -f ${EFCSGRP}.fail ]] && rm ${EFCSGRP}.fail +cd "${DATATOP}" +echo "Status of ensemble members in group ${ENSGRP}:" +cat "${EFCSGRP}" +[[ -f ${EFCSGRP}.fail ]] && rm "${EFCSGRP}".fail ################################################################################ # If any members failed, error out -export err=$rc; err_chk +export err=${rc}; err_chk ################################################################################ # Postprocessing -exit $err +exit "${err}" diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index 3e509d0e06..d3fd5c2a97 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -93,7 +93,7 @@ EOF ${NLN} "${file}" "${DATA}/INPUT/${file2}" done - hour_rst=$(${NHOUR} "${CDATE_RST}" "${CDATE}") + local hour_rst=$(nhour "${CDATE_RST}" "${current_cycle}") IAU_FHROT=$((IAU_OFFSET+hour_rst)) if [[ ${DOIAU} = "YES" ]]; then IAUFHRS=-1 @@ -134,9 +134,9 @@ EOF # Grid and orography data if [[ ${cplflx} = ".false." ]] ; then - ${NLN} "${FIXfv3}/${CASE}/${CASE}_mosaic.nc" "${DATA}/INPUT/grid_spec.nc" + ${NLN} "${FIX_DIR}/orog/${CASE}/${CASE}_mosaic.nc" "${DATA}/INPUT/grid_spec.nc" else - ${NLN} "${FIXfv3}/${CASE}/${CASE}_mosaic.nc" "${DATA}/INPUT/${CASE}_mosaic.nc" + ${NLN} "${FIX_DIR}/orog/${CASE}/${CASE}_mosaic.nc" "${DATA}/INPUT/${CASE}_mosaic.nc" fi OROFIX=${OROFIX:-"${FIX_DIR}/orog/${CASE}.mx${OCNRES}_frac"} @@ -217,41 +217,41 @@ EOF # imp_physics should be 8: #### if [[ ${imp_physics} -eq 8 ]]; then - ${NLN} "${FIX_AM}/CCN_ACTIVATE.BIN" "${DATA}/CCN_ACTIVATE.BIN" - ${NLN} "${FIX_AM}/freezeH2O.dat" "${DATA}/freezeH2O.dat" - ${NLN} "${FIX_AM}/qr_acr_qgV2.dat" "${DATA}/qr_acr_qgV2.dat" - ${NLN} "${FIX_AM}/qr_acr_qsV2.dat" "${DATA}/qr_acr_qsV2.dat" + ${NLN} "${FIX_DIR}/am/CCN_ACTIVATE.BIN" "${DATA}/CCN_ACTIVATE.BIN" + ${NLN} "${FIX_DIR}/am/freezeH2O.dat" "${DATA}/freezeH2O.dat" + ${NLN} "${FIX_DIR}/am/qr_acr_qgV2.dat" "${DATA}/qr_acr_qgV2.dat" + ${NLN} "${FIX_DIR}/am/qr_acr_qsV2.dat" "${DATA}/qr_acr_qsV2.dat" fi - ${NLN} "${FIX_AM}/${O3FORC}" "${DATA}/global_o3prdlos.f77" - ${NLN} "${FIX_AM}/${H2OFORC}" "${DATA}/global_h2oprdlos.f77" - ${NLN} "${FIX_AM}/global_solarconstant_noaa_an.txt" "${DATA}/solarconstant_noaa_an.txt" - ${NLN} "${FIX_AM}/global_sfc_emissivity_idx.txt" "${DATA}/sfc_emissivity_idx.txt" + ${NLN} "${FIX_DIR}/am/${O3FORC}" "${DATA}/global_o3prdlos.f77" + ${NLN} "${FIX_DIR}/am/${H2OFORC}" "${DATA}/global_h2oprdlos.f77" + ${NLN} "${FIX_DIR}/am/global_solarconstant_noaa_an.txt" "${DATA}/solarconstant_noaa_an.txt" + ${NLN} "${FIX_DIR}/am/global_sfc_emissivity_idx.txt" "${DATA}/sfc_emissivity_idx.txt" ## merra2 aerosol climo if [[ ${IAER} -eq "1011" ]]; then for month in $(seq 1 12); do MM=$(printf %02d "${month}") - ${NLN} "${FIX_AER}/merra2.aerclim.2003-2014.m${MM}.nc" "aeroclim.m${MM}.nc" + ${NLN} "${FIX_DIR}/aer/merra2.aerclim.2003-2014.m${MM}.nc" "aeroclim.m${MM}.nc" done - ${NLN} "${FIX_LUT}/optics_BC.v1_3.dat" "${DATA}/optics_BC.dat" - ${NLN} "${FIX_LUT}/optics_OC.v1_3.dat" "${DATA}/optics_OC.dat" - ${NLN} "${FIX_LUT}/optics_DU.v15_3.dat" "${DATA}/optics_DU.dat" - ${NLN} "${FIX_LUT}/optics_SS.v3_3.dat" "${DATA}/optics_SS.dat" - ${NLN} "${FIX_LUT}/optics_SU.v1_3.dat" "${DATA}/optics_SU.dat" + ${NLN} "${FIX_DIR}/lut/optics_BC.v1_3.dat" "${DATA}/optics_BC.dat" + ${NLN} "${FIX_DIR}/lut/optics_OC.v1_3.dat" "${DATA}/optics_OC.dat" + ${NLN} "${FIX_DIR}/lut/optics_DU.v15_3.dat" "${DATA}/optics_DU.dat" + ${NLN} "${FIX_DIR}/lut/optics_SS.v3_3.dat" "${DATA}/optics_SS.dat" + ${NLN} "${FIX_DIR}/lut/optics_SU.v1_3.dat" "${DATA}/optics_SU.dat" fi - ${NLN} "${FIX_AM}/global_co2historicaldata_glob.txt" "${DATA}/co2historicaldata_glob.txt" - ${NLN} "${FIX_AM}/co2monthlycyc.txt" "${DATA}/co2monthlycyc.txt" + ${NLN} "${FIX_DIR}/am/global_co2historicaldata_glob.txt" "${DATA}/co2historicaldata_glob.txt" + ${NLN} "${FIX_DIR}/am/co2monthlycyc.txt" "${DATA}/co2monthlycyc.txt" if [[ ${ICO2} -gt 0 ]]; then - for file in $(ls "${FIX_AM}/fix_co2_proj/global_co2historicaldata"*) ; do + for file in $(ls "${FIX_DIR}/am/fix_co2_proj/global_co2historicaldata"*) ; do ${NLN} "${file}" "${DATA}/$(basename "${file//global_}")" done fi - ${NLN} "${FIX_AM}/global_climaeropac_global.txt" "${DATA}/aerosol.dat" + ${NLN} "${FIX_DIR}/am/global_climaeropac_global.txt" "${DATA}/aerosol.dat" if [[ ${IAER} -gt 0 ]] ; then - for file in $(ls "${FIX_AM}/global_volcanic_aerosols"*) ; do + for file in $(ls "${FIX_DIR}/am/global_volcanic_aerosols"*) ; do ${NLN} "${file}" "${DATA}/$(basename "${file//global_}")" done fi @@ -288,16 +288,16 @@ EOF LATB_JMO=${LATB_JMO:-${LATB_CASE}} # Fix files - FNGLAC=${FNGLAC:-"${FIX_AM}/global_glacier.2x2.grb"} - FNMXIC=${FNMXIC:-"${FIX_AM}/global_maxice.2x2.grb"} - FNTSFC=${FNTSFC:-"${FIX_AM}/RTGSST.1982.2012.monthly.clim.grb"} - FNSNOC=${FNSNOC:-"${FIX_AM}/global_snoclim.1.875.grb"} + FNGLAC=${FNGLAC:-"${FIX_DIR}/am/global_glacier.2x2.grb"} + FNMXIC=${FNMXIC:-"${FIX_DIR}/am/global_maxice.2x2.grb"} + FNTSFC=${FNTSFC:-"${FIX_DIR}/am/RTGSST.1982.2012.monthly.clim.grb"} + FNSNOC=${FNSNOC:-"${FIX_DIR}/am/global_snoclim.1.875.grb"} FNZORC=${FNZORC:-"igbp"} - FNAISC=${FNAISC:-"${FIX_AM}/IMS-NIC.blended.ice.monthly.clim.grb"} + FNAISC=${FNAISC:-"${FIX_DIR}/am/IMS-NIC.blended.ice.monthly.clim.grb"} FNALBC2=${FNALBC2:-"${FIX_SFC}/${CASE}.facsf.tileX.nc"} FNTG3C=${FNTG3C:-"${FIX_SFC}/${CASE}.substrate_temperature.tileX.nc"} FNVEGC=${FNVEGC:-"${FIX_SFC}/${CASE}.vegetation_greenness.tileX.nc"} - FNMSKH=${FNMSKH:-"${FIX_AM}/global_slmask.t1534.3072.1536.grb"} + FNMSKH=${FNMSKH:-"${FIX_DIR}/am/global_slmask.t1534.3072.1536.grb"} FNVMNC=${FNVMNC:-"${FIX_SFC}/${CASE}.vegetation_greenness.tileX.nc"} FNVMXC=${FNVMXC:-"${FIX_SFC}/${CASE}.vegetation_greenness.tileX.nc"} FNSLPC=${FNSLPC:-"${FIX_SFC}/${CASE}.slope_type.tileX.nc"} @@ -305,10 +305,10 @@ EOF FNVETC=${FNVETC:-"${FIX_SFC}/${CASE}.vegetation_type.tileX.nc"} FNSOTC=${FNSOTC:-"${FIX_SFC}/${CASE}.soil_type.tileX.nc"} FNABSC=${FNABSC:-"${FIX_SFC}/${CASE}.maximum_snow_albedo.tileX.nc"} - FNSMCC=${FNSMCC:-"${FIX_AM}/global_soilmgldas.statsgo.t${JCAP}.${LONB}.${LATB}.grb"} + FNSMCC=${FNSMCC:-"${FIX_DIR}/am/global_soilmgldas.statsgo.t${JCAP}.${LONB}.${LATB}.grb"} # If the appropriate resolution fix file is not present, use the highest resolution available (T1534) - [[ ! -f ${FNSMCC} ]] && FNSMCC="${FIX_AM}/global_soilmgldas.statsgo.t1534.3072.1536.grb" + [[ ! -f ${FNSMCC} ]] && FNSMCC="${FIX_DIR}/am/global_soilmgldas.statsgo.t1534.3072.1536.grb" # NSST Options # nstf_name contains the NSST related parameters @@ -424,11 +424,11 @@ EOF # Stochastic Physics Options if [[ ${SET_STP_SEED:-"YES"} = "YES" ]]; then - ISEED_SKEB=$((CDATE*1000 + MEMBER*10 + 1)) - ISEED_SHUM=$((CDATE*1000 + MEMBER*10 + 2)) - ISEED_SPPT=$((CDATE*1000 + MEMBER*10 + 3)) - ISEED_CA=$(( (CDATE*1000 + MEMBER*10 + 4) % 2147483647 )) - ISEED_LNDP=$(( (CDATE*1000 + MEMBER*10 + 5) % 2147483647 )) + ISEED_SKEB=$((current_cycle*1000 + MEMBER*10 + 1)) + ISEED_SHUM=$((current_cycle*1000 + MEMBER*10 + 2)) + ISEED_SPPT=$((current_cycle*1000 + MEMBER*10 + 3)) + ISEED_CA=$(( (current_cycle*1000 + MEMBER*10 + 4) % 2147483647 )) + ISEED_LNDP=$(( (current_cycle*1000 + MEMBER*10 + 5) % 2147483647 )) else ISEED=${ISEED:-0} fi @@ -457,29 +457,18 @@ EOF if [[ ! -d ${COM_ATMOS_HISTORY} ]]; then mkdir -p "${COM_ATMOS_HISTORY}"; fi if [[ ! -d ${COM_ATMOS_MASTER} ]]; then mkdir -p "${COM_ATMOS_MASTER}"; fi if [[ "${QUILTING}" = ".true." ]] && [[ "${OUTPUT_GRID}" = "gaussian_grid" ]]; then - fhr=${FHMIN} - for fhr in ${OUTPUT_FH}; do - FH3=$(printf %03i "${fhr}") - FH2=$(printf %02i "${fhr}") - atmi=atmf${FH3}.nc - sfci=sfcf${FH3}.nc - logi=log.atm.f${FH3} - pgbi=GFSPRS.GrbF${FH2} - flxi=GFSFLX.GrbF${FH2} - atmo=${COM_ATMOS_HISTORY}/${RUN}.t${cyc}z.atmf${FH3}.nc - sfco=${COM_ATMOS_HISTORY}/${RUN}.t${cyc}z.sfcf${FH3}.nc - logo=${COM_ATMOS_HISTORY}/${RUN}.t${cyc}z.atm.logf${FH3}.txt - pgbo=${COM_ATMOS_MASTER}/${RUN}.t${cyc}z.master.grb2f${FH3} - flxo=${COM_ATMOS_MASTER}/${RUN}.t${cyc}z.sfluxgrbf${FH3}.grib2 - ${NLN} "${atmo}" "${atmi}" - ${NLN} "${sfco}" "${sfci}" - ${NLN} "${logo}" "${logi}" + for fhr in ${FV3_OUTPUT_FH}; do + local FH3=$(printf %03i "${fhr}") + local FH2=$(printf %02i "${fhr}") + ${NLN} "${COM_ATMOS_HISTORY}/${RUN}.t${cyc}z.atmf${FH3}.nc" "atmf${FH3}.nc" + ${NLN} "${COM_ATMOS_HISTORY}/${RUN}.t${cyc}z.sfcf${FH3}.nc" "sfcf${FH3}.nc" + ${NLN} "${COM_ATMOS_HISTORY}/${RUN}.t${cyc}z.atm.logf${FH3}.txt" "log.atm.f${FH3}" if [[ ${WRITE_DOPOST} = ".true." ]]; then - ${NLN} "${pgbo}" "${pgbi}" - ${NLN} "${flxo}" "${flxi}" + ${NLN} "${COM_ATMOS_MASTER}/${RUN}.t${cyc}z.master.grb2f${FH3}" "GFSPRS.GrbF${FH2}" + ${NLN} "${COM_ATMOS_MASTER}/${RUN}.t${cyc}z.sfluxgrbf${FH3}.grib2" "GFSFLX.GrbF${FH2}" fi done - else + else # TODO: Is this even valid anymore? for n in $(seq 1 "${ntiles}"); do ${NLN} "nggps2d.tile${n}.nc" "${COM_ATMOS_HISTORY}/nggps2d.tile${n}.nc" ${NLN} "nggps3d.tile${n}.nc" "${COM_ATMOS_HISTORY}/nggps3d.tile${n}.nc" @@ -526,9 +515,9 @@ WW3_postdet() { #Link mod_def files for wave grids if [[ ${waveMULTIGRID} = ".true." ]]; then - array=(${WAVECUR_FID} ${WAVEICE_FID} ${WAVEWND_FID} ${waveuoutpGRD} ${waveGRD} ${waveesmfGRD}) + local array=(${WAVECUR_FID} ${WAVEICE_FID} ${WAVEWND_FID} ${waveuoutpGRD} ${waveGRD} ${waveesmfGRD}) echo "Wave Grids: ${WAVECUR_FID} ${WAVEICE_FID} ${WAVEWND_FID} ${waveuoutpGRD} ${waveGRD} ${waveesmfGRD}" - grdALL=$(printf "%s\n" "${array[@]}" | sort -u | tr '\n' ' ') + local grdALL=$(printf "%s\n" "${array[@]}" | sort -u | tr '\n' ' ') for wavGRD in ${grdALL}; do ${NCP} "${COM_WAVE_PREP}/${COMPONENTwave}.mod_def.${wavGRD}" "${DATA}/mod_def.${wavGRD}" @@ -540,7 +529,7 @@ WW3_postdet() { #if wave mesh is not the same as the ocn/ice mesh, linkk it in the file - comparemesh=${MESH_OCN_ICE:-"mesh.mx${ICERES}.nc"} + local comparemesh=${MESH_OCN_ICE:-"mesh.mx${ICERES}.nc"} if [[ "${MESH_WAV}" = "${comparemesh}" ]]; then echo "Wave is on same mesh as ocean/ice" else @@ -553,12 +542,12 @@ WW3_postdet() { for wavGRD in ${waveGRD} ; do if [[ "${warm_start}" = ".true." ]] || [[ "${RERUN}" = "YES" ]]; then if [[ ${RERUN} = "NO" ]]; then - waverstfile=${COM_WAVE_RESTART_PREV}/${sPDY}.${scyc}0000.restart.${wavGRD} + local waverstfile="${COM_WAVE_RESTART_PREV}/${sPDY}.${scyc}0000.restart.${wavGRD}" else - waverstfile=${COM_WAVE_RESTART}/${PDYT}.${cyct}0000.restart.${wavGRD} + local waverstfile="${COM_WAVE_RESTART}/${PDYT}.${cyct}0000.restart.${wavGRD}" fi else - waverstfile=${COM_WAVE_RESTART}/${sPDY}.${scyc}0000.restart.${wavGRD} + local waverstfile="${COM_WAVE_RESTART}/${sPDY}.${scyc}0000.restart.${wavGRD}" fi if [[ ! -f ${waverstfile} ]]; then if [[ ${RERUN} = "NO" ]]; then @@ -585,7 +574,7 @@ WW3_postdet() { fi if [[ "${WW3ICEINP}" = "YES" ]]; then - wavicefile="${COM_WAVE_PREP}/${RUNwave}.${WAVEICE_FID}.${cycle}.ice" + local wavicefile="${COM_WAVE_PREP}/${RUNwave}.${WAVEICE_FID}.${cycle}.ice" if [[ ! -f ${wavicefile} ]]; then echo "ERROR: WW3ICEINP = ${WW3ICEINP}, but missing ice file" echo "Abort!" @@ -595,7 +584,7 @@ WW3_postdet() { fi if [[ "${WW3CURINP}" = "YES" ]]; then - wavcurfile="${COM_WAVE_PREP}/${RUNwave}.${WAVECUR_FID}.${cycle}.cur" + local wavcurfile="${COM_WAVE_PREP}/${RUNwave}.${WAVECUR_FID}.${cycle}.cur" if [[ ! -f ${wavcurfile} ]]; then echo "ERROR: WW3CURINP = ${WW3CURINP}, but missing current file" echo "Abort!" @@ -613,17 +602,16 @@ WW3_postdet() { fi # Loop for gridded output (uses FHINC) + local fhr vdate FHINC wavGRD fhr=${FHMIN_WAV} while [[ ${fhr} -le ${FHMAX_WAV} ]]; do - YMDH=$(${NDATE} "${fhr}" "${CDATE}") - YMD="${YMDH:0:8}" - HMS="${YMDH:8:2}0000" + vdate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) if [[ ${waveMULTIGRID} = ".true." ]]; then for wavGRD in ${waveGRD} ; do - ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_grd.${wavGRD}.${YMD}.${HMS}" "${DATA}/${YMD}.${HMS}.out_grd.${wavGRD}" + ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_grd.${wavGRD}.${vdate:0:8}.${vdate:8:2}0000" "${DATA}/${vdate:0:8}.${vdate:8:2}0000.out_grd.${wavGRD}" done else - ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_grd.${waveGRD}.${YMD}.${HMS}" "${DATA}/${YMD}.${HMS}.out_grd.ww3" + ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_grd.${waveGRD}.${vdate:0:8}.${vdate:8:2}0000" "${DATA}/${vdate:0:8}.${vdate:8:2}0000.out_grd.ww3" fi FHINC=${FHOUT_WAV} if (( FHMAX_HF_WAV > 0 && FHOUT_HF_WAV > 0 && fhr < FHMAX_HF_WAV )); then @@ -635,13 +623,11 @@ WW3_postdet() { # Loop for point output (uses DTPNT) fhr=${FHMIN_WAV} while [[ ${fhr} -le ${FHMAX_WAV} ]]; do - YMDH=$(${NDATE} "${fhr}" "${CDATE}") - YMD="${YMDH:0:8}" - HMS="${YMDH:8:2}0000" + vdate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) if [[ ${waveMULTIGRID} = ".true." ]]; then - ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_pnt.${waveuoutpGRD}.${YMD}.${HMS}" "${DATA}/${YMD}.${HMS}.out_pnt.${waveuoutpGRD}" + ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_pnt.${waveuoutpGRD}.${vdate:0:8}.${vdate:8:2}0000" "${DATA}/${vdate:0:8}.${vdate:8:2}0000.out_pnt.${waveuoutpGRD}" else - ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_pnt.${waveuoutpGRD}.${YMD}.${HMS}" "${DATA}/${YMD}.${HMS}.out_pnt.ww3" + ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_pnt.${waveuoutpGRD}.${vdate:0:8}.${vdate:8:2}0000" "${DATA}/${vdate:0:8}.${vdate:8:2}0000.out_pnt.ww3" fi FHINC=${FHINCP_WAV} @@ -703,12 +689,12 @@ MOM6_postdet() { fi # Copy MOM6 fixed files - ${NCP} -pf "${FIXmom}/${OCNRES}/"* "${DATA}/INPUT/" + ${NCP} "${FIXmom}/${OCNRES}/"* "${DATA}/INPUT/" # Copy coupled grid_spec spec_file="${FIX_DIR}/cpl/a${CASE}o${OCNRES}/grid_spec.nc" if [[ -s ${spec_file} ]]; then - ${NCP} -pf "${spec_file}" "${DATA}/INPUT/" + ${NCP} "${spec_file}" "${DATA}/INPUT/" else echo "FATAL ERROR: grid_spec file '${spec_file}' does not exist" exit 3 @@ -739,8 +725,8 @@ MOM6_postdet() { # largest signed integer if [[ "${DO_OCN_SPPT}" = "YES" ]] || [[ "${DO_OCN_PERT_EPBL}" = "YES" ]]; then if [[ ${SET_STP_SEED:-"YES"} = "YES" ]]; then - ISEED_OCNSPPT=$(( (CDATE*1000 + MEMBER*10 + 6) % 2147483647 )) - ISEED_EPBL=$(( (CDATE*1000 + MEMBER*10 + 7) % 2147483647 )) + ISEED_OCNSPPT=$(( (current_cycle*1000 + MEMBER*10 + 6) % 2147483647 )) + ISEED_EPBL=$(( (current_cycle*1000 + MEMBER*10 + 7) % 2147483647 )) else ISEED=${ISEED:-0} fi @@ -755,54 +741,43 @@ MOM6_postdet() { # TODO: get requirements on what files need to be written out and what these dates here are and what they mean export ENSMEM=${ENSMEM:-01} - export IDATE=${CDATE} - fhrlst=${OUTPUT_FH} if [[ ! -d ${COM_OCEAN_HISTORY} ]]; then mkdir -p "${COM_OCEAN_HISTORY}"; fi - for fhr in ${fhrlst}; do - if [[ ${fhr} = 'anl' ]]; then # Looking at OUTPUT_FH, this is never true, TODO: remove this block - continue - fi + # Looping over FV3 output hours + # TODO: Need to define MOM6_OUTPUT_FH and control at some point for issue #1629 + for fhr in ${FV3_OUTPUT_FH}; do if [[ -z ${last_fhr:-} ]]; then - last_fhr=${fhr} + local last_fhr=${fhr} continue fi (( interval = fhr - last_fhr )) (( midpoint = last_fhr + interval/2 )) - VDATE=$(${NDATE} "${fhr}" "${IDATE}") - YYYY="${VDATE:0:4}" - MM="${VDATE:4:2}" - DD="${VDATE:6:2}" - HH="${VDATE:8:2}" - SS=$((10#${HH}*3600)) - - VDATE_MID=$(${NDATE} "${midpoint}" "${IDATE}") - YYYY_MID="${VDATE_MID:0:4}" - MM_MID="${VDATE_MID:4:2}" - DD_MID="${VDATE_MID:6:2}" - HH_MID="${VDATE_MID:8:2}" - SS_MID=$((10#${HH_MID}*3600)) - - source_file="ocn_${YYYY_MID}_${MM_MID}_${DD_MID}_${HH_MID}.nc" - dest_file="ocn${VDATE}.${ENSMEM}.${IDATE}.nc" + + local vdate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + local vdate_mid=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${midpoint} hours" +%Y%m%d%H) + + + # Native model output uses window midpoint in the filename, but we are mapping that to the end of the period for COM + local source_file="ocn_${vdate_mid:0:4}_${vdate_mid:4:2}_${vdate_mid:6:2}_${vdate_mid:8:2}.nc" + local dest_file="ocn${vdate}.${ENSMEM}.${current_cycle}.nc" ${NLN} "${COM_OCEAN_HISTORY}/${dest_file}" "${DATA}/${source_file}" - source_file="ocn_daily_${YYYY}_${MM}_${DD}.nc" - dest_file=${source_file} + local source_file="ocn_daily_${vdate:0:4}_${vdate:4:2}_${vdate:6:2}.nc" + local dest_file=${source_file} if [[ ! -a "${DATA}/${source_file}" ]]; then ${NLN} "${COM_OCEAN_HISTORY}/${dest_file}" "${DATA}/${source_file}" fi - last_fhr=${fhr} + local last_fhr=${fhr} done elif [[ "${RUN}" =~ "gdas" ]]; then # Link output files for RUN = gdas # Save MOM6 backgrounds - for fhr in ${OUTPUT_FH}; do - local idatestr=$(date -d "${CDATE:0:8} ${CDATE:8:2} + ${fhr} hours" +%Y_%m_%d_%H) + for fhr in ${FV3_OUTPUT_FH}; do + local idatestr=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y_%m_%d_%H) local fhr3=$(printf %03i "${fhr}") ${NLN} "${COM_OCEAN_HISTORY}/${RUN}.t${cyc}z.ocnf${fhr3}.nc" "${DATA}/ocn_da_${idatestr}.nc" done @@ -846,7 +821,7 @@ MOM6_postdet() { # Instead of linking, copy the mediator files after the model finishes #local COMOUTmed="${ROTDIR}/${RUN}.${PDY}/${cyc}/med" #mkdir -p "${COMOUTmed}/RESTART" - #local idate=$(date -d "${CDATE:0:8} ${CDATE:8:2} + ${restart_interval} hours" +%Y%m%d%H) + #local idate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${restart_interval} hours" +%Y%m%d%H) #while [[ ${idate} -le ${forecast_end_cycle} ]]; do # local seconds=$(to_seconds ${idate:8:2}0000) # use function to_seconds from forecast_predet.sh to convert HHMMSS to seconds # local idatestr="${idate:0:4}-${idate:4:2}-${idate:6:2}-${seconds}" @@ -876,7 +851,7 @@ MOM6_out() { # Linking mediator restarts to COM causes the model to fail with a message. # See MOM6_postdet() function for error message mkdir -p "${COM_MED_RESTART}" - local idate=$(date -d "${CDATE:0:8} ${CDATE:8:2} + ${restart_interval} hours" +%Y%m%d%H) + local idate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${restart_interval} hours" +%Y%m%d%H) while [[ ${idate} -le ${forecast_end_cycle} ]]; do local seconds=$(to_seconds "${idate:8:2}"0000) # use function to_seconds from forecast_predet.sh to convert HHMMSS to seconds local idatestr="${idate:0:4}-${idate:4:2}-${idate:6:2}-${seconds}" @@ -893,19 +868,6 @@ MOM6_out() { CICE_postdet() { echo "SUB ${FUNCNAME[0]}: CICE after run type determination" - # TODO: move configuration settings to config.ice - - # TODO: These need to be calculated in the parsing_namelists_CICE.sh script CICE_namelists() function and set as local - year="${CDATE:0:4}" - month="${CDATE:4:2}" - day="${CDATE:6:2}" - hour="${CDATE:8:2}" - sec=$((10#${hour}*3600)) - stepsperhr=$((3600/${ICETIM})) - nhours=$(${NHOUR} "${CDATE}" "${year}010100") - steps=$((nhours*stepsperhr)) - npt=$((FHMAX*stepsperhr)) # Need this in order for dump_last to work - # TODO: These settings should be elevated to config.ice histfreq_n=${histfreq_n:-6} dumpfreq_n=${dumpfreq_n:-1000} # Set this to a really large value, as cice, mom6 and cmeps restart interval is controlled by nems.configure @@ -927,27 +889,21 @@ CICE_postdet() { # -- if false, re-initialize level ponds to zero (if runtype=initial or continue) restart_pond_lvl=${restart_pond_lvl:-".false."} - ICERES=${ICERES:-"025"} # TODO: similar to MOM_out, lift this higher - ice_grid_file=${ice_grid_file:-"grid_cice_NEMS_mx${ICERES}.nc"} ice_kmt_file=${ice_kmt_file:-"kmtu_cice_NEMS_mx${ICERES}.nc"} export MESH_OCN_ICE=${MESH_OCN_ICE:-"mesh.mx${ICERES}.nc"} - # Copy/link CICE IC to DATA - if [[ "${warm_start}" = ".true." ]]; then - cice_ana="${COM_ICE_RESTART}/${PDY}.${cyc}0000.cice_model_anl.res.nc" - if [[ -e ${cice_ana} ]]; then - ${NLN} "${cice_ana}" "${DATA}/cice_model.res.nc" - else - ${NLN} "${COM_ICE_RESTART_PREV}/${PDY}.${cyc}0000.cice_model.res.nc" "${DATA}/cice_model.res.nc" - fi - else # cold start are typically SIS2 restarts obtained from somewhere else e.g. CPC - ${NLN} "${COM_ICE_RESTART}/${PDY}.${cyc}0000.cice_model.res.nc" "${DATA}/cice_model.res.nc" + # Copy CICE ICs + echo "Link CICE ICs" + cice_restart_file="${COM_ICE_RESTART_PREV}/${PDY}.${cyc}0000.cice_model.res.nc" + if [[ ! -f "${cice_restart_file}" ]]; then + echo "FATAL ERROR: CICE restart file not found at '${cice_restart_file}', ABORT!" + exit 112 + else + ${NLN} "${cice_restart_file}" "${DATA}/cice_model.res.nc" fi - # TODO: add a check for the restarts to exist, if not, exit eloquently rm -f "${DATA}/ice.restart_file" - touch "${DATA}/ice.restart_file" - echo "${DATA}/cice_model.res.nc" >> "${DATA}/ice.restart_file" + echo "${DATA}/cice_model.res.nc" > "${DATA}/ice.restart_file" echo "Link CICE fixed files" ${NLN} "${FIXcice}/${ICERES}/${ice_grid_file}" "${DATA}/" @@ -965,27 +921,19 @@ CICE_postdet() { # TODO: Work w/ NB to determine appropriate naming convention for these files export ENSMEM=${ENSMEM:-01} - export IDATE=${CDATE} - - fhrlst=${OUTPUT_FH} # TODO: consult w/ NB on how to improve on this. Gather requirements and more information on what these files are and how they are used to properly catalog them - for fhr in ${fhrlst}; do - if [[ ${fhr} = 'anl' ]]; then # Looking at OUTPUT_FH, this is never true. TODO: remove this block - continue - fi - VDATE=$(${NDATE} "${fhr}" "${IDATE}") - YYYY="${VDATE:0:4}" - MM="${VDATE:4:2}" - DD="${VDATE:6:2}" - HH="${VDATE:8:2}" - SS=$((10#${HH}*3600)) + local vdate seconds vdatestr fhr last_fhr + for fhr in ${FV3_OUTPUT_FH}; do + vdate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds + vdatestr="${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${seconds}" if [[ 10#${fhr} -eq 0 ]]; then - ${NLN} "${COM_ICE_HISTORY}/iceic${VDATE}.${ENSMEM}.${IDATE}.nc" "${DATA}/CICE_OUTPUT/iceh_ic.${YYYY}-${MM}-${DD}-$(printf "%5.5d" "${SS}").nc" + ${NLN} "${COM_ICE_HISTORY}/iceic${vdate}.${ENSMEM}.${current_cycle}.nc" "${DATA}/CICE_OUTPUT/iceh_ic.${vdatestr}.nc" else (( interval = fhr - last_fhr )) # Umm.. isn't this histfreq_n? - ${NLN} "${COM_ICE_HISTORY}/ice${VDATE}.${ENSMEM}.${IDATE}.nc" "${DATA}/CICE_OUTPUT/iceh_$(printf "%0.2d" "${interval}")h.${YYYY}-${MM}-${DD}-$(printf "%5.5d" "${SS}").nc" + ${NLN} "${COM_ICE_HISTORY}/ice${vdate}.${ENSMEM}.${current_cycle}.nc" "${DATA}/CICE_OUTPUT/iceh_$(printf "%0.2d" "${interval}")h.${vdatestr}.nc" fi last_fhr=${fhr} done @@ -994,29 +942,34 @@ CICE_postdet() { # Link CICE generated initial condition file from DATA/CICE_OUTPUT to COMOUTice # This can be thought of as the f000 output from the CICE model - local seconds=$(to_seconds "${CDATE:8:2}0000") # convert HHMMSS to seconds - ${NLN} "${COM_ICE_HISTORY}/${RUN}.t${cyc}z.iceic.nc" "${DATA}/CICE_OUTPUT/iceh_ic.${CDATE:0:4}-${CDATE:4:2}-${CDATE:6:2}-${seconds}.nc" + local seconds vdatestr + seconds=$(to_seconds "${current_cycle:8:2}0000") # convert HHMMSS to seconds + vdatestr="${current_cycle:0:4}-${current_cycle:4:2}-${current_cycle:6:2}-${seconds}" + ${NLN} "${COM_ICE_HISTORY}/${RUN}.t${cyc}z.iceic.nc" "${DATA}/CICE_OUTPUT/iceh_ic.${vdatestr}.nc" # Link instantaneous CICE forecast output files from DATA/CICE_OUTPUT to COMOUTice - local fhr="${FHOUT}" + local vdate vdatestr seconds fhr fhr3 + fhr="${FHOUT}" while [[ "${fhr}" -le "${FHMAX}" ]]; do - local idate=$(date -d "${CDATE:0:8} ${CDATE:8:2} + ${fhr} hours" +%Y%m%d%H) - local seconds=$(to_seconds "${idate:8:2}0000") # convert HHMMSS to seconds - local fhr3=$(printf %03i "${fhr}") - ${NLN} "${COM_ICE_HISTORY}/${RUN}.t${cyc}z.icef${fhr3}.nc" "${DATA}/CICE_OUTPUT/iceh_inst.${idate:0:4}-${idate:4:2}-${idate:6:2}-${seconds}.nc" - local fhr=$((fhr + FHOUT)) + vdate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds + vdatestr="${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${seconds}" + fhr3=$(printf %03i "${fhr}") + ${NLN} "${COM_ICE_HISTORY}/${RUN}.t${cyc}z.icef${fhr3}.nc" "${DATA}/CICE_OUTPUT/iceh_inst.-${vdatestr}.nc" + fhr=$((fhr + FHOUT)) done fi # Link CICE restarts from CICE_RESTART to COMOUTice/RESTART # Loop over restart_interval and link restarts from DATA to COM - local idate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${restart_interval} hours" +%Y%m%d%H) - while [[ ${idate} -le ${forecast_end_cycle} ]]; do - local seconds=$(to_seconds "${idate:8:2}0000") # convert HHMMSS to seconds - local idatestr="${idate:0:4}-${idate:4:2}-${idate:6:2}-${seconds}" - ${NLN} "${COM_ICE_RESTART}/${idate:0:8}.${idate:8:2}0000.cice_model.res.nc" "${DATA}/CICE_RESTART/cice_model.res.${idatestr}.nc" - local idate=$(date -d "${idate:0:8} ${idate:8:2} + ${restart_interval} hours" +%Y%m%d%H) + local vdate vdatestr seconds + vdate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${restart_interval} hours" +%Y%m%d%H) + while [[ ${vdate} -le ${forecast_end_cycle} ]]; do + seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds + vdatestr="${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${seconds}" + ${NLN} "${COM_ICE_RESTART}/${vdate:0:8}.${vdate:8:2}0000.cice_model.res.nc" "${DATA}/CICE_RESTART/cice_model.res.${vdatestr}.nc" + vdate=$(date -d "${vdate:0:8} ${vdate:8:2} + ${restart_interval} hours" +%Y%m%d%H) done } @@ -1070,25 +1023,15 @@ GOCART_postdet() { if [[ ! -d "${COM_CHEM_HISTORY}" ]]; then mkdir -p "${COM_CHEM_HISTORY}"; fi - fhrlst=${OUTPUT_FH} - for fhr in ${fhrlst}; do - if [[ ${fhr} = 'anl' ]]; then - continue - fi - VDATE=$(${NDATE} "${fhr}" "${CDATE}") - YYYY="${VDATE:0:4}" - MM="${VDATE:4:2}" - DD="${VDATE:6:2}" - HH="${VDATE:8:2}" - SS=$((10#${HH}*3600)) - - # + for fhr in ${FV3_OUTPUT_FH}; do + local vdate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + # Temporarily delete existing files due to noclobber in GOCART - # - if [[ -e "${COM_CHEM_HISTORY}/gocart.inst_aod.${YYYY}${MM}${DD}_${HH}00z.nc4" ]]; then - rm "${COM_CHEM_HISTORY}/gocart.inst_aod.${YYYY}${MM}${DD}_${HH}00z.nc4" + if [[ -e "${COM_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" ]]; then + rm -f "${COM_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" fi - ${NLN} "${COM_CHEM_HISTORY}/gocart.inst_aod.${YYYY}${MM}${DD}_${HH}00z.nc4" "${DATA}/gocart.inst_aod.${YYYY}${MM}${DD}_${HH}00z.nc4" + ${NLN} "${COM_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" \ + "${DATA}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" done } diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index 3bab376458..c9455e2cc2 100755 --- a/ush/forecast_predet.sh +++ b/ush/forecast_predet.sh @@ -1,7 +1,7 @@ #! /usr/bin/env bash ##### -## "forecast_def.sh" +## "forecast_predet.sh" ## This script sets value of all variables ## ## This is the child script of ex-global forecast, @@ -26,15 +26,26 @@ middle_date(){ # Function to calculate mid-point date in YYYYMMDDHH between two dates also in YYYYMMDDHH local date1=${1:?} local date2=${2:?} - local date1s=$(date -d "${date1:0:8} ${date1:8:2}" +%s) - local date2s=$(date -d "${date2:0:8} ${date2:8:2}" +%s) + local date1s=$(date --utc -d "${date1:0:8} ${date1:8:2}:00:00" +%s) + local date2s=$(date --utc -d "${date2:0:8} ${date2:8:2}:00:00" +%s) local dtsecsby2=$(( $((date2s - date1s)) / 2 )) local mid_date=$(date -d "${date1:0:8} ${date1:8:2} + ${dtsecsby2} seconds" +%Y%m%d%H%M%S) echo "${mid_date:0:10}" } +nhour(){ + # Function to calculate hours between two dates (This replicates prod-util NHOUR) + local date1=${1:?} + local date2=${2:?} + # Convert dates to UNIX timestamps + seconds1=$(date --utc -d "${date1:0:8} ${date1:8:2}:00:00" +%s) + seconds2=$(date --utc -d "${date2:0:8} ${date2:8:2}:00:00" +%s) + hours=$(( $((seconds1 - seconds2)) / 3600 )) # Calculate the difference in seconds and convert to hours + echo "${hours}" +} + common_predet(){ - echo "SUB ${FUNCNAME[0]}: Defining variables for shared through models" + echo "SUB ${FUNCNAME[0]}: Defining variables for shared through model components" # Ignore "not used" warning # shellcheck disable=SC2034 pwd=$(pwd) @@ -45,6 +56,13 @@ common_predet(){ FCSTEXECDIR=${FCSTEXECDIR:-${HOMEgfs}/exec} FCSTEXEC=${FCSTEXEC:-ufs_model.x} + # Directories. + FIX_DIR=${FIX_DIR:-${HOMEgfs}/fix} + + # Model specific stuff + PARM_FV3DIAG=${PARM_FV3DIAG:-${HOMEgfs}/parm/parm_fv3diag} + PARM_POST=${PARM_POST:-${HOMEgfs}/parm/post} + # Define significant cycles current_cycle=${CDATE} previous_cycle=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} - ${assim_freq} hours" +%Y%m%d%H) @@ -53,7 +71,7 @@ common_predet(){ next_cycle=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${assim_freq} hours" +%Y%m%d%H) forecast_end_cycle=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${FHMAX} hours" +%Y%m%d%H) - cd "${DATA}" || exit 8 + cd "${DATA}" || ( echo "FATAL ERROR: Unable to 'cd ${DATA}', ABORT!"; exit 8 ) } FV3_predet(){ @@ -75,25 +93,21 @@ FV3_predet(){ restart_interval=${FHMAX} fi - # Convert output settings into an explicit list - OUTPUT_FH="" - FHMIN_LF=${FHMIN} + # Convert output settings into an explicit list for FV3 + # NOTE: FV3_OUTPUT_FH is also currently used in other components + # TODO: Have a seperate control for other components to address issue #1629 + FV3_OUTPUT_FH="" + local fhr=${FHMIN} if (( FHOUT_HF > 0 && FHMAX_HF > 0 )); then for (( fh = FHMIN; fh < FHMAX_HF; fh = fh + FHOUT_HF )); do - OUTPUT_FH="${OUTPUT_FH} ${fh}" + FV3_OUTPUT_FH="${FV3_OUTPUT_FH} ${fh}" done - FHMIN_LF=${FHMAX_HF} + fhr=${FHMAX_HF} fi - for (( fh = FHMIN_LF; fh <= FHMAX; fh = fh + FHOUT )); do - OUTPUT_FH="${OUTPUT_FH} ${fh}" + for (( fh = fhr; fh <= FHMAX; fh = fh + FHOUT )); do + FV3_OUTPUT_FH="${FV3_OUTPUT_FH} ${fh}" done - # Directories. - FIX_DIR=${FIX_DIR:-${HOMEgfs}/fix} - FIX_AM=${FIX_AM:-${FIX_DIR}/am} - FIX_AER=${FIX_AER:-${FIX_DIR}/aer} - FIX_LUT=${FIX_LUT:-${FIX_DIR}/lut} - FIXfv3=${FIXfv3:-${FIX_DIR}/orog} # Model resolution specific parameters DELTIM=${DELTIM:-225} @@ -112,10 +126,6 @@ FV3_predet(){ IAU_DELTHRS=${IAU_DELTHRS:-0} IAU_OFFSET=${IAU_OFFSET:-0} - # Model specific stuff - PARM_FV3DIAG=${PARM_FV3DIAG:-${HOMEgfs}/parm/parm_fv3diag} - PARM_POST=${PARM_POST:-${HOMEgfs}/parm/post} - # Model config options ntiles=6 diff --git a/ush/parsing_model_configure_FV3.sh b/ush/parsing_model_configure_FV3.sh index 432ec36fd4..bff9e0fc69 100755 --- a/ush/parsing_model_configure_FV3.sh +++ b/ush/parsing_model_configure_FV3.sh @@ -56,7 +56,7 @@ ideflate: ${ideflate:-1} nbits: ${nbits:-14} imo: ${LONB_IMO} jmo: ${LATB_JMO} -output_fh: ${OUTPUT_FH} +output_fh: ${FV3_OUTPUT_FH} iau_offset: ${IAU_OFFSET:-0} EOF diff --git a/ush/parsing_namelists_CICE.sh b/ush/parsing_namelists_CICE.sh index 6fc8b143cc..6ef743ebc9 100755 --- a/ush/parsing_namelists_CICE.sh +++ b/ush/parsing_namelists_CICE.sh @@ -39,13 +39,18 @@ else fi local max_blocks=-1 +local sec stepsperhr npt +sec=$(to_seconds "${current_cycle:8:2}0000") +stepsperhr=$((3600/ICETIM)) +npt=$((FHMAX*stepsperhr)) # Need this in order for dump_last to work + cat > ice_in < diag_table << EOF -FV3 Forecast -${gPDY:0:4} ${gPDY:4:2} ${gPDY:6:2} ${gcyc} 0 0 -EOF -cat $DIAG_TABLE >> diag_table +# build the diag_table +{ +echo "UFS_Weather_Model_Forecast" +if [[ "${DOIAU}" = "YES" ]]; then + echo "${previous_cycle:0:4} ${previous_cycle:4:2} ${previous_cycle:6:2} ${previous_cycle:8:2} 0 0" else -cat > diag_table << EOF -FV3 Forecast -${sPDY:0:4} ${sPDY:4:2} ${sPDY:6:2} ${scyc} 0 0 -EOF -cat $DIAG_TABLE >> diag_table + echo "${current_cycle:0:4} ${current_cycle:4:2} ${current_cycle:6:2} ${current_cycle:8:2} 0 0" fi - -if [ ! -z "${AERO_DIAG_TABLE:-}" ]; then - cat ${AERO_DIAG_TABLE} >> diag_table +cat "${DIAG_TABLE}" +if [[ -n "${AERO_DIAG_TABLE:-}" ]]; then + cat "${AERO_DIAG_TABLE}" fi +cat "${DIAG_TABLE_APPEND}" +} >> diag_table -cat $DIAG_TABLE_APPEND >> diag_table # copy data table -$NCP $DATA_TABLE data_table +${NCP} "${DATA_TABLE}" data_table # build field_table -if [ ! -z "${AERO_FIELD_TABLE:-}" ]; then - nrec=$( cat ${FIELD_TABLE} | wc -l ) +if [[ -n "${AERO_FIELD_TABLE:-}" ]]; then + nrec=$(wc -l < "${FIELD_TABLE}") prec=${nrec} if (( dnats > 0 )); then - prec=$( grep -F -n TRACER ${FIELD_TABLE} 2> /dev/null | tail -n ${dnats} | head -1 | cut -d: -f1 ) + prec=$( grep -F -n TRACER "${FIELD_TABLE}" 2> /dev/null | tail -n "${dnats}" | head -1 | cut -d: -f1 ) prec=${prec:-0} prec=$(( prec > 0 ? prec - 1 : prec )) fi { \ - head -n ${prec} ${FIELD_TABLE} ; \ - cat ${AERO_FIELD_TABLE} ; \ - tail -n $(( nrec - prec )) ${FIELD_TABLE} ; \ + head -n "${prec}" "${FIELD_TABLE}" ; \ + cat "${AERO_FIELD_TABLE}" ; \ + tail -n $(( nrec - prec )) "${FIELD_TABLE}" ; \ } > field_table # add non-prognostic tracers from additional table dnats=$(( dnats + dnats_aero )) else - $NCP $FIELD_TABLE field_table + ${NCP} "${FIELD_TABLE}" field_table fi cat > input.nml < input.nml < input.nml < input.nml <> input.nml << EOF iovr = ${iovr:-"3"} ltaerosol = ${ltaerosol:-".false."} lradar = ${lradar:-".false."} ttendlim = ${ttendlim:-"-999"} - dt_inner = ${dt_inner:-"$(echo "$DELTIM/2" |bc)"} + dt_inner = ${dt_inner:-"${default_dt_inner}"} sedi_semi = ${sedi_semi:-".true."} decfl = ${decfl:-"10"} oz_phys = ${oz_phys:-".false."} @@ -305,9 +301,9 @@ cat >> input.nml <> input.nml <> input.nml <> input.nml <> input.nml << EOF fscav_aero = ${fscav_aero:-'*:0.0'} EOF @@ -385,13 +381,13 @@ cat >> input.nml <> input.nml << EOF iaufhrs = ${IAUFHRS} iau_delthrs = ${IAU_DELTHRS} @@ -401,7 +397,7 @@ if [ $DOIAU = "YES" ]; then EOF fi -if [ ${DO_CA:-"NO"} = "YES" ]; then +if [[ ${DO_CA:-"NO"} = "YES" ]]; then cat >> input.nml << EOF do_ca = .true. ca_global = ${ca_global:-".false."} @@ -418,14 +414,14 @@ if [ ${DO_CA:-"NO"} = "YES" ]; then EOF fi -if [ ${DO_LAND_PERT:-"NO"} = "YES" ]; then +if [[ ${DO_LAND_PERT:-"NO"} = "YES" ]]; then cat >> input.nml << EOF lndp_type = ${lndp_type:-2} n_var_lndp = ${n_var_lndp:-0} EOF fi -if [ $knob_ugwp_version -eq 0 ]; then +if [[ ${knob_ugwp_version} -eq 0 ]]; then cat >> input.nml << EOF &cires_ugwp_nml knob_ugwp_solver = ${knob_ugwp_solver:-2} @@ -444,7 +440,7 @@ if [ $knob_ugwp_version -eq 0 ]; then EOF fi -if [ $knob_ugwp_version -eq 1 ]; then +if [[ ${knob_ugwp_version} -eq 1 ]]; then cat >> input.nml << EOF &cires_ugwp_nml knob_ugwp_solver = ${knob_ugwp_solver:-2} @@ -457,7 +453,7 @@ if [ $knob_ugwp_version -eq 1 ]; then knob_ugwp_doheat = ${knob_ugwp_doheat:-1} knob_ugwp_dokdis = ${knob_ugwp_dokdis:-2} knob_ugwp_ndx4lh = ${knob_ugwp_ndx4lh:-4} - knob_ugwp_palaunch = ${knob_ugwp_palaunch:-275.0e2} + knob_ugwp_palaunch = ${knob_ugwp_palaunch:-275.0e2} knob_ugwp_nslope = ${knob_ugwp_nslope:-1} knob_ugwp_lzmax = ${knob_ugwp_lzmax:-15.750e3} knob_ugwp_lzmin = ${knob_ugwp_lzmin:-0.75e3} @@ -470,8 +466,6 @@ if [ $knob_ugwp_version -eq 1 ]; then EOF fi - - echo "" >> input.nml cat >> input.nml <> input.nml #if [ $MEMBER -gt 0 ]; then -if [ $DO_SPPT = "YES" -o $DO_SHUM = "YES" -o $DO_SKEB = "YES" -o $DO_LAND_PERT = "YES" ]; then +if [[ "${DO_SPPT}" = "YES" || "${DO_SHUM}" = "YES" || "${DO_SKEB}" = "YES" || "${DO_LAND_PERT}" = "YES" ]]; then cat >> input.nml << EOF &nam_stochy EOF - if [ $DO_SKEB = "YES" ]; then + if [[ ${DO_SKEB} = "YES" ]]; then cat >> input.nml << EOF - skeb = $SKEB - iseed_skeb = ${ISEED_SKEB:-$ISEED} + skeb = ${SKEB} + iseed_skeb = ${ISEED_SKEB:-${ISEED}} skeb_tau = ${SKEB_TAU:-"-999."} skeb_lscale = ${SKEB_LSCALE:-"-999."} skebnorm = ${SKEBNORM:-"1"} @@ -603,19 +597,19 @@ EOF EOF fi - if [ $DO_SHUM = "YES" ]; then + if [[ ${DO_SHUM} = "YES" ]]; then cat >> input.nml << EOF - shum = $SHUM - iseed_shum = ${ISEED_SHUM:-$ISEED} + shum = ${SHUM} + iseed_shum = ${ISEED_SHUM:-${ISEED}} shum_tau = ${SHUM_TAU:-"-999."} shum_lscale = ${SHUM_LSCALE:-"-999."} EOF fi - if [ $DO_SPPT = "YES" ]; then + if [[ ${DO_SPPT} = "YES" ]]; then cat >> input.nml << EOF - sppt = $SPPT - iseed_sppt = ${ISEED_SPPT:-$ISEED} + sppt = ${SPPT} + iseed_sppt = ${ISEED_SPPT:-${ISEED}} sppt_tau = ${SPPT_TAU:-"-999."} sppt_lscale = ${SPPT_LSCALE:-"-999."} sppt_logit = ${SPPT_LOGIT:-".true."} @@ -629,13 +623,13 @@ EOF / EOF - if [ $DO_LAND_PERT = "YES" ]; then + if [[ ${DO_LAND_PERT} = "YES" ]]; then cat >> input.nml << EOF &nam_sfcperts lndp_type = ${lndp_type} LNDP_TAU = ${LNDP_TAU} LNDP_SCALE = ${LNDP_SCALE} - ISEED_LNDP = ${ISEED_LNDP:-$ISEED} + ISEED_LNDP = ${ISEED_LNDP:-${ISEED}} lndp_var_list = ${lndp_var_list} lndp_prt_list = ${lndp_prt_list} ${nam_sfcperts_nml:-} @@ -660,5 +654,9 @@ EOF fi -echo "$(cat input.nml)" +# Echo out formatted "input.nml" +echo "====================================" +echo "FV3_namelists(): 'input.nml'" +cat input.nml +echo "====================================" } diff --git a/workflow/setup_expt.py b/workflow/setup_expt.py index bda1b32786..b127367220 100755 --- a/workflow/setup_expt.py +++ b/workflow/setup_expt.py @@ -87,7 +87,7 @@ def fill_COMROT_cycled(host, inputs): do_med = False dst_ocn_rst_dir = os.path.join('model_data', 'ocean', 'restart') dst_ocn_anl_dir = os.path.join('analysis', 'ocean') - dst_ice_dir = os.path.join('model_data', 'ice', 'restart') + dst_ice_rst_dir = os.path.join('model_data', 'ice', 'restart') dst_atm_anl_dir = os.path.join('analysis', 'atmos') if flat_structure: @@ -102,14 +102,14 @@ def fill_COMROT_cycled(host, inputs): # ocean and ice have the same filenames for warm and cold src_ocn_rst_dir = os.path.join('ocean', 'RESTART') src_ocn_anl_dir = 'ocean' - src_ice_dir = os.path.join('ice', 'RESTART') + src_ice_rst_dir = os.path.join('ice', 'RESTART') src_atm_anl_dir = 'atmos' else: src_atm_dir = dst_atm_dir src_med_dir = dst_med_dir src_ocn_rst_dir = dst_ocn_rst_dir src_ocn_anl_dir = dst_ocn_anl_dir - src_ice_dir = dst_ice_dir + src_ice_rst_dir = dst_ice_rst_dir src_atm_anl_dir = dst_atm_anl_dir def link_files_from_src_to_dst(src_dir, dst_dir): @@ -121,69 +121,95 @@ def link_files_from_src_to_dst(src_dir, dst_dir): # Link ensemble member initial conditions if inputs.nens > 0: - if inputs.start in ['warm']: - enkfdir = f'enkf{inputs.cdump}.{rdatestr[:8]}/{rdatestr[8:]}' - elif inputs.start in ['cold']: - enkfdir = f'enkf{inputs.cdump}.{idatestr[:8]}/{idatestr[8:]}' + previous_cycle_dir = f'enkf{inputs.cdump}.{rdatestr[:8]}/{rdatestr[8:]}' + current_cycle_dir = f'enkf{inputs.cdump}.{idatestr[:8]}/{idatestr[8:]}' for ii in range(1, inputs.nens + 1): memdir = f'mem{ii:03d}' # Link atmospheric files - dst_dir = os.path.join(comrot, enkfdir, memdir, dst_atm_dir) - src_dir = os.path.join(inputs.icsdir, enkfdir, memdir, src_atm_dir) + if inputs.start in ['warm']: + dst_dir = os.path.join(comrot, previous_cycle_dir, memdir, dst_atm_dir) + src_dir = os.path.join(inputs.icsdir, previous_cycle_dir, memdir, src_atm_dir) + elif inputs.start in ['cold']: + dst_dir = os.path.join(comrot, current_cycle_dir, memdir, dst_atm_dir) + src_dir = os.path.join(inputs.icsdir, current_cycle_dir, memdir, src_atm_dir) makedirs_if_missing(dst_dir) link_files_from_src_to_dst(src_dir, dst_dir) - # ocean, ice, etc. TBD ... + + # Link ocean files + if do_ocean: + dst_dir = os.path.join(comrot, previous_cycle_dir, memdir, dst_ocn_rst_dir) + src_dir = os.path.join(inputs.icsdir, previous_cycle_dir, memdir, src_ocn_rst_dir) + makedirs_if_missing(dst_dir) + link_files_from_src_to_dst(src_dir, dst_dir) + + # First 1/2 cycle needs a MOM6 increment + incfile = f'enkf{inputs.cdump}.t{idatestr[8:]}z.ocninc.nc' + src_file = os.path.join(inputs.icsdir, current_cycle_dir, memdir, src_ocn_anl_dir, incfile) + dst_file = os.path.join(comrot, current_cycle_dir, memdir, dst_ocn_anl_dir, incfile) + makedirs_if_missing(os.path.join(comrot, current_cycle_dir, memdir, dst_ocn_anl_dir)) + os.symlink(src_file, dst_file) + + # Link ice files + if do_ice: + dst_dir = os.path.join(comrot, previous_cycle_dir, memdir, dst_ice_rst_dir) + src_dir = os.path.join(inputs.icsdir, previous_cycle_dir, memdir, src_ice_rst_dir) + makedirs_if_missing(dst_dir) + link_files_from_src_to_dst(src_dir, dst_dir) + + # Link mediator files + if do_med: + dst_dir = os.path.join(comrot, previous_cycle_dir, memdir, dst_med_dir) + src_dir = os.path.join(inputs.icsdir, previous_cycle_dir, memdir, src_med_dir) + makedirs_if_missing(dst_dir) + link_files_from_src_to_dst(src_dir, dst_dir) # Link deterministic initial conditions + previous_cycle_dir = f'{inputs.cdump}.{rdatestr[:8]}/{rdatestr[8:]}' + current_cycle_dir = f'{inputs.cdump}.{idatestr[:8]}/{idatestr[8:]}' # Link atmospheric files if inputs.start in ['warm']: - detdir = f'{inputs.cdump}.{rdatestr[:8]}/{rdatestr[8:]}' + dst_dir = os.path.join(comrot, previous_cycle_dir, dst_atm_dir) + src_dir = os.path.join(inputs.icsdir, previous_cycle_dir, src_atm_dir) elif inputs.start in ['cold']: - detdir = f'{inputs.cdump}.{idatestr[:8]}/{idatestr[8:]}' + dst_dir = os.path.join(comrot, current_cycle_dir, dst_atm_dir) + src_dir = os.path.join(inputs.icsdir, current_cycle_dir, src_atm_dir) - dst_dir = os.path.join(comrot, detdir, dst_atm_dir) - src_dir = os.path.join(inputs.icsdir, detdir, src_atm_dir) makedirs_if_missing(dst_dir) link_files_from_src_to_dst(src_dir, dst_dir) # Link ocean files if do_ocean: - detdir = f'{inputs.cdump}.{rdatestr[:8]}/{rdatestr[8:]}' - dst_dir = os.path.join(comrot, detdir, dst_ocn_rst_dir) - src_dir = os.path.join(inputs.icsdir, detdir, src_ocn_rst_dir) + dst_dir = os.path.join(comrot, previous_cycle_dir, dst_ocn_rst_dir) + src_dir = os.path.join(inputs.icsdir, previous_cycle_dir, src_ocn_rst_dir) makedirs_if_missing(dst_dir) link_files_from_src_to_dst(src_dir, dst_dir) # First 1/2 cycle needs a MOM6 increment - incdir = f'{inputs.cdump}.{idatestr[:8]}/{idatestr[8:]}' incfile = f'{inputs.cdump}.t{idatestr[8:]}z.ocninc.nc' - src_file = os.path.join(inputs.icsdir, incdir, src_ocn_anl_dir, incfile) - dst_file = os.path.join(comrot, incdir, dst_ocn_anl_dir, incfile) - makedirs_if_missing(os.path.join(comrot, incdir, dst_ocn_anl_dir)) + src_file = os.path.join(inputs.icsdir, current_cycle_dir, src_ocn_anl_dir, incfile) + dst_file = os.path.join(comrot, current_cycle_dir, dst_ocn_anl_dir, incfile) + makedirs_if_missing(os.path.join(comrot, current_cycle_dir, dst_ocn_anl_dir)) os.symlink(src_file, dst_file) # Link ice files if do_ice: - detdir = f'{inputs.cdump}.{rdatestr[:8]}/{rdatestr[8:]}' - dst_dir = os.path.join(comrot, detdir, dst_ice_dir) - src_dir = os.path.join(inputs.icsdir, detdir, src_ice_dir) + dst_dir = os.path.join(comrot, previous_cycle_dir, dst_ice_rst_dir) + src_dir = os.path.join(inputs.icsdir, previous_cycle_dir, src_ice_rst_dir) makedirs_if_missing(dst_dir) link_files_from_src_to_dst(src_dir, dst_dir) # Link mediator files if do_med: - detdir = f'{inputs.cdump}.{rdatestr[:8]}/{rdatestr[8:]}' - dst_dir = os.path.join(comrot, detdir, dst_med_dir) - src_dir = os.path.join(inputs.icsdir, detdir, src_med_dir) + dst_dir = os.path.join(comrot, previous_cycle_dir, dst_med_dir) + src_dir = os.path.join(inputs.icsdir, previous_cycle_dir, src_med_dir) makedirs_if_missing(dst_dir) link_files_from_src_to_dst(src_dir, dst_dir) # Link bias correction and radiance diagnostics files - detdir = f'{inputs.cdump}.{idatestr[:8]}/{idatestr[8:]}' - src_dir = os.path.join(inputs.icsdir, detdir, src_atm_anl_dir) - dst_dir = os.path.join(comrot, detdir, dst_atm_anl_dir) + src_dir = os.path.join(inputs.icsdir, current_cycle_dir, src_atm_anl_dir) + dst_dir = os.path.join(comrot, current_cycle_dir, dst_atm_anl_dir) makedirs_if_missing(dst_dir) for ftype in ['abias', 'abias_pc', 'abias_air', 'radstat']: fname = f'{inputs.cdump}.t{idatestr[8:]}z.{ftype}'