From 8c2a5151754e7262cef5b7c3c6aab4526972d0b0 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Thu, 4 May 2023 11:36:22 -0400 Subject: [PATCH 01/13] update setup_expt.py to link ocean/ice ics for ensemble members --- workflow/setup_expt.py | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/workflow/setup_expt.py b/workflow/setup_expt.py index e948a29528..935ed58c9b 100755 --- a/workflow/setup_expt.py +++ b/workflow/setup_expt.py @@ -86,7 +86,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: @@ -101,14 +101,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): @@ -132,7 +132,35 @@ def link_files_from_src_to_dst(src_dir, dst_dir): src_dir = os.path.join(inputs.icsdir, enkfdir, 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, enkfdir, memdir, dst_ocn_rst_dir) + src_dir = os.path.join(inputs.icsdir, enkfdir, 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 + incdir = f'enkf{inputs.cdump}.{idatestr[:8]}/{idatestr[8:]}' + incfile = f'{inputs.cdump}.t{idatestr[8:]}z.ocninc.nc' # TODO: this file should be enkfgdas.tHHz.ocninc.nc + src_file = os.path.join(inputs.icsdir, incdir, memdir, src_ocn_anl_dir, incfile) + dst_file = os.path.join(comrot, incdir, memdir, dst_ocn_anl_dir, incfile) + makedirs_if_missing(os.path.join(comrot, incdir, memdir, dst_ocn_anl_dir)) + os.symlink(src_file, dst_file) + + # Link ice files + if do_ice: + dst_dir = os.path.join(comrot, enkfdir, memdir, dst_ice_rst_dir) + src_dir = os.path.join(inputs.icsdir, enkfdir, 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, enkfdir, memdir, dst_med_dir) + src_dir = os.path.join(inputs.icsdir, enkfdir, memdir, src_med_dir) + makedirs_if_missing(dst_dir) + link_files_from_src_to_dst(src_dir, dst_dir) # Link deterministic initial conditions @@ -166,8 +194,8 @@ def link_files_from_src_to_dst(src_dir, dst_dir): # 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, detdir, dst_ice_rst_dir) + src_dir = os.path.join(inputs.icsdir, detdir, src_ice_rst_dir) makedirs_if_missing(dst_dir) link_files_from_src_to_dst(src_dir, dst_dir) From c6d393571108fbbd03695a2c9575252af717ff12 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Fri, 16 Jun 2023 17:01:29 -0400 Subject: [PATCH 02/13] wip --- parm/config/gfs/config.base.emc.dyn | 4 +- parm/config/gfs/config.base.nco.static | 248 ------------------------- parm/config/gfs/config.efcs | 58 ++---- parm/config/gfs/config.fv3.nco.static | 145 --------------- scripts/exgdas_enkf_fcst.sh | 110 +++++------ ush/forecast_det.sh | 7 +- ush/forecast_postdet.sh | 46 ++--- ush/forecast_predet.sh | 5 +- workflow/setup_expt.py | 72 ++++--- 9 files changed, 122 insertions(+), 573 deletions(-) delete mode 100644 parm/config/gfs/config.base.nco.static delete mode 100644 parm/config/gfs/config.fv3.nco.static diff --git a/parm/config/gfs/config.base.emc.dyn b/parm/config/gfs/config.base.emc.dyn index 8f48f932b9..bc7348f327 100644 --- a/parm/config/gfs/config.base.emc.dyn +++ b/parm/config/gfs/config.base.emc.dyn @@ -166,7 +166,7 @@ case "${CASE}" in export waveGRD='glo_500' ;; "C96") - export OCNRES=100 + export OCNRES=500 export waveGRD='glo_200' ;; "C192") @@ -181,7 +181,7 @@ case "${CASE}" in export OCNRES=025 export waveGRD='mx025' ;; - *) + *) export OCNRES=025 export waveGRD='mx025' ;; diff --git a/parm/config/gfs/config.base.nco.static b/parm/config/gfs/config.base.nco.static deleted file mode 100644 index 5b9b373567..0000000000 --- a/parm/config/gfs/config.base.nco.static +++ /dev/null @@ -1,248 +0,0 @@ -#! /usr/bin/env bash - -########## config.base ########## -# Common to all steps - -echo "BEGIN: config.base" - -# Machine environment -export machine="WCOSS2" - -# EMC parallel or NCO production -export RUN_ENVIR="nco" - -# Account, queue, etc. -export ACCOUNT="GFS-T2O" -export QUEUE="prod" -export QUEUE_SERVICE="dev_transfer" - -# Project to use in mass store: -HPSS_PROJECT=emc-global - -# Directories relative to installation areas: -export PARMgfs=$HOMEgfs/parm -export FIXgfs=$HOMEgfs/fix -export USHgfs=$HOMEgfs/ush -export UTILgfs=$HOMEgfs/util -export EXECgfs=$HOMEgfs/exec -export SCRgfs=$HOMEgfs/scripts - -######################################################################## - -# GLOBAL static environment parameters - -export PACKAGEROOT="/lfs/h1/ops/prod/packages" -export RTMFIX=$CRTM_FIX - -# Machine specific paths used everywhere - -# USER specific paths -export HOMEDIR=$EXPDIR/HOMEDIR -export STMP=$DATAROOT -export PTMP=$ROTDIR -export NOSCRUB=$EXPDIR/NOSCRUB - -# Base directories for various builds -export BASE_GIT="/gpfs/dell2/emc/modeling/noscrub/emc.glopara/git" - -# Toggle to turn on/off GFS downstream processing. -export DO_BUFRSND="YES" # BUFR sounding products -export DO_GEMPAK="YES" # GEMPAK products -export DO_AWIPS="YES" # AWIPS products -export DO_VRFY="NO" # VRFY step - -# NO for retrospective parallel; YES for real-time parallel -export REALTIME="YES" - -#################################################### -# DO NOT ADD MACHINE DEPENDENT STUFF BELOW THIS LINE -# IF YOU HAVE TO MAKE MACHINE SPECIFIC CHANGES BELOW -# FEEL FREE TO MOVE THEM ABOVE THIS LINE TO KEEP IT -# CLEAR -#################################################### -# Build paths relative to $HOMEgfs -export FIXgsi="$HOMEgfs/fix/gsi" -export HOMEfv3gfs="$HOMEgfs/sorc/fv3gfs.fd" -export HOMEpost="$HOMEgfs" -export HOMEobsproc="/lfs/h1/ops/prod/packages/obsproc.v1.1.2" - -# CONVENIENT utility scripts and other environment parameters -export NCP="/bin/cp -p" -export NMV="/bin/mv" -export NLN="/bin/ln -sf" -export VERBOSE="YES" -export CHGRP_CMD="chgrp rstprod" -export NEMSIOGET="$HOMEgfs/exec/nemsio_get" -export NCDUMP="$NETCDF/bin/ncdump" -export NCLEN="$HOMEgfs/ush/getncdimlen" - -# Machine environment, jobs, and other utility scripts -export BASE_ENV="$HOMEgfs/env" -export BASE_JOB="$HOMEgfs/jobs/rocoto" - -# EXPERIMENT specific environment parameters -export SDATE=2018080600 -export EDATE=2039123100 -export assim_freq=6 -export PSLOT="test" -export EXPDIR="$EXPDIR" -export ROTDIR="$(compath.py ${envir}/${NET}/${gfs_ver})" -export ROTDIR_DUMP="YES" -export DUMP_SUFFIX="" -export RUNDIR="$DATAROOT" -export ARCDIR="$NOSCRUB/archive/$PSLOT" -export ATARDIR="/NCEPDEV/$HPSS_PROJECT/1year/$USER/$machine/scratch/$PSLOT" - -# Commonly defined parameters in JJOBS -export envir=${envir:-"prod"} -export NET="gfs" -export RUN=${RUN:-${CDUMP:-"gfs"}} -export COMINatmos=${ROTDIR}/${CDUMP}.${PDY}/${cyc}/atmos -export COMOUTatmos=${ROTDIR}/${CDUMP}.${PDY}/${cyc}/atmos -export COMINwave=${ROTDIR}/${CDUMP}.${PDY}/${cyc}/wave -export COMOUTwave=${ROTDIR}/${CDUMP}.${PDY}/${cyc}/wave - -export ERRSCRIPT=${ERRSCRIPT:-'eval [[ $err = 0 ]]'} -export LOGSCRIPT=${LOGSCRIPT:-""} -#export ERRSCRIPT=${ERRSCRIPT:-"err_chk"} -#export LOGSCRIPT=${LOGSCRIPT:-"startmsg"} -export REDOUT="1>" -export REDERR="2>" - -export SENDECF=${SENDECF:-"YES"} -export SENDCOM=${SENDCOM:-"YES"} -export SENDSDM=${SENDSDM:-"YES"} -export SENDDBN_NTC=${SENDDBN_NTC:-"YES"} -export SENDDBN=${SENDDBN:-"YES"} -export DBNROOT=${DBNROOT:-${UTILROOT}/fakedbn} - -# Resolution specific parameters -export LEVS=128 -export CASE="C768" -export CASE_ENKF="C384" - -# Run with CCPP physics -export RUN_CCPP="YES" -export CCPP_SUITE="FV3_GFS_v16" - -# Surface cycle update frequency -if [[ "$CDUMP" == "gdas" ]] ; then - export FHCYC=1 - export FTSFS=10 -elif [[ "$CDUMP" == "gfs" ]] ; then - export FHCYC=24 -fi - -# Output frequency of the forecast model (for cycling) -export FHMIN=0 -export FHMAX=9 -export FHOUT=3 - -# Cycle to run EnKF (set to BOTH for both gfs and gdas) -export EUPD_CYC="gdas" - -# GFS cycle info -export gfs_cyc=4 # 0: no GFS cycle, 1: 00Z only, 2: 00Z and 12Z only, 4: all 4 cycles. - -# GFS output and frequency -export FHMIN_GFS=0 - -export FHMAX_GFS_00=384 -export FHMAX_GFS_06=384 -export FHMAX_GFS_12=384 -export FHMAX_GFS_18=384 -export FHMAX_GFS=$(eval echo \${FHMAX_GFS_$cyc}) - -export FHOUT_GFS=3 -export FHMAX_HF_GFS=120 -export FHOUT_HF_GFS=1 -export ILPOST=1 # gempak output frequency up to F120 - -# frequency for saving restart files. set to 6,12,24,48 etc -export restart_interval_gfs=12 - -# I/O QUILTING, true--use Write Component; false--use GFDL FMS -# if quilting=true, choose OUTPUT_GRID as cubed_sphere_grid in netcdf or gaussian_grid -# WRITE_DOPOST=true, use inline POST -export QUILTING=".true." -export OUTPUT_GRID="gaussian_grid" -export WRITE_DOPOST=".true." # WRITE_DOPOST=true, use inline POST -export WRITE_NSFLIP=".true." - -# IAU related parameters -export DOIAU="YES" # Enable 4DIAU for control with 3 increments -export IAUFHRS="3,6,9" -export IAU_FHROT=$(echo $IAUFHRS | cut -c1) -export IAU_DELTHRS=6 -export IAU_OFFSET=6 -export DOIAU_ENKF=${DOIAU:-"YES"} # Enable 4DIAU for EnKF ensemble -export IAUFHRS_ENKF="3,6,9" -export IAU_DELTHRS_ENKF=6 - -# Use Jacobians in eupd and thereby remove need to run eomg -export lobsdiag_forenkf=".true." - -# run wave component -export DO_WAVE=YES -export WAVE_CDUMP="both" -export DOBNDPNT_WAVE="YES" - -# Microphysics Options: 99-ZhaoCarr, 8-Thompson; 6-WSM6, 10-MG, 11-GFDL -export imp_physics=8 - -# Shared parameters -# DA engine -export DO_JEDIATMVAR="NO" -export DO_JEDIATMENS="NO" - -# Hybrid related -export DOHYBVAR="YES" -export NMEM_ENKF="80" -export SMOOTH_ENKF="NO" -export l4densvar=".true." -export lwrite4danl=".true." - -# EnKF output frequency -if [ $DOHYBVAR = "YES" ]; then - export FHMIN_ENKF=3 - export FHMAX_ENKF=9 - if [ $l4densvar = ".true." ]; then - export FHOUT=1 - export FHOUT_ENKF=1 - else - export FHOUT_ENKF=3 - fi -fi - -# turned on nsst in anal and/or fcst steps, and turn off rtgsst - -export DONST="YES" -if [ $DONST = "YES" ]; then export FNTSFA=" "; fi - -# The switch to apply SST elevation correction or not -export nst_anl=.true. - -# Analysis increments to zero in CALCINCEXEC -export INCREMENTS_TO_ZERO="'liq_wat_inc','icmr_inc','rwmr_inc','snmr_inc','grle_inc'" - -# Stratospheric increments to zero -export INCVARS_ZERO_STRAT="'sphum_inc','liq_wat_inc','icmr_inc','rwmr_inc','snmr_inc','grle_inc'" -export INCVARS_EFOLD="5" - -# Swith to generate netcdf or binary diagnostic files. If not specified, -# script default to binary diagnostic files. Set diagnostic file -# variables here since used in both DA and vrfy jobs -export netcdf_diag=".true." -export binary_diag=".false." - -# Verification options -export DO_METP="NO" # Run MET+ jobs - -# Archiving options -export HPSSARCH="NO" # save data to HPSS archive -export ARCH_CYC=00 # Archive data at this cycle for warm_start capability -export ARCH_WARMICFREQ=1 # Archive frequency in days for warm_start capability -export ARCH_FCSTICFREQ=1 # Archive frequency in days for gdas and gfs forecast-only capability -export DELETE_COM_IN_ARCHIVE_JOB="YES" # NO=retain ROTDIR. YES default in arch.sh and earc.sh. - -echo "END: config.base" diff --git a/parm/config/gfs/config.efcs b/parm/config/gfs/config.efcs index 95c2cb58de..319f1cd6c2 100644 --- a/parm/config/gfs/config.efcs +++ b/parm/config/gfs/config.efcs @@ -5,35 +5,23 @@ echo "BEGIN: config.efcs" -# TODO: the _ENKF counterparts need to be defined in config.base -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"} - -# 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;; - "C192") export OCNRES=050;; - "C384") export OCNRES=025;; - "C768") export OCNRES=025;; - *) export OCNRES=025;; - esac -fi -[[ ${DO_ICE} == "YES" ]] && export ICERES=$OCNRES -[[ ${DO_WAVE} == "YES" ]] && export waveGRD=${waveGRD_ENKF:-$waveGRD} # TODO: will we run waves with a different resolution in the ensemble? +# TODO: the _ENKF counterparts need to be defined in config.base; for now inherit from config.base +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"}} # Source model specific information that is resolution dependent string="--fv3 ${CASE_ENS}" -[[ ${DO_OCN} == "YES" ]] && string="$string --mom6 $OCNRES" -[[ ${DO_ICE} == "YES" ]] && string="$string --cice6 $ICERES" -[[ ${DO_WAVE} == "YES" ]] && string="$string --ww3 ${waveGRD// /;}" -source $EXPDIR/config.ufs ${string} +[[ ${DO_OCN} == "YES" ]] && string="${string} --mom6 ${OCNRES}" +[[ ${DO_ICE} == "YES" ]] && string="${string} --cice6 ${ICERES}" +[[ ${DO_WAVE} == "YES" ]] && string="${string} --ww3 ${waveGRD// /;}" +# We are counting on $string being multiple arguments +# shellcheck disable=SC2086 +source "${EXPDIR}/config.ufs" ${string} # Get task specific resources -. $EXPDIR/config.resources efcs +. "${EXPDIR}/config.resources" efcs # Use serial I/O for ensemble (lustre?) export OUTPUT_FILETYPE_ATM="netcdf" @@ -66,32 +54,18 @@ export SPPT_LSCALE=500000. export SPPT_LOGIT=".true." export SPPT_SFCLIMIT=".true." -if [ $QUILTING = ".true." -a $OUTPUT_GRID = "gaussian_grid" ]; then - export DIAG_TABLE="$HOMEgfs/parm/parm_fv3diag/diag_table_da" +if [ "${QUILTING}" = ".true." -a "${OUTPUT_GRID}" = "gaussian_grid" ]; then + export DIAG_TABLE="${HOMEgfs}/parm/parm_fv3diag/diag_table_da" else - export DIAG_TABLE="$HOMEgfs/parm/parm_fv3diag/diag_table_da_orig" + export DIAG_TABLE="${HOMEgfs}/parm/parm_fv3diag/diag_table_da_orig" fi # FV3 model namelist parameters to over-ride export restart_interval=${restart_interval:-6} # For IAU, write restarts at beginning of window also -if [ $DOIAU_ENKF = "YES" ]; then +if [[ "${DOIAU_ENKF}" = "YES" ]]; then export restart_interval="3 -1" 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/parm/config/gfs/config.fv3.nco.static b/parm/config/gfs/config.fv3.nco.static deleted file mode 100644 index dc60b2ef03..0000000000 --- a/parm/config/gfs/config.fv3.nco.static +++ /dev/null @@ -1,145 +0,0 @@ -#! /usr/bin/env bash - -########## config.fv3 ########## -# FV3 model resolution specific parameters -# e.g. time-step, processor layout, physics and dynamics parameters -# This config sets default variables for FV3 for a given resolution -# User can over-ride after sourcing this config file - -if [ $# -ne 1 ]; then - - echo "Must specify an input resolution argument to set variables!" - echo "argument can be any one of the following:" - echo "C48 C96 C192 C384 C768 C1152 C3072" - exit 1 - -fi - -case_in=$1 - -echo "BEGIN: config.fv3" - -export npe_node_max=128 - -# (Standard) Model resolution dependent variables -case $case_in in - "C48") - export DELTIM=450 - export layout_x=2 - export layout_y=4 - export layout_x_gfs=2 - export layout_y_gfs=4 - export npe_wav=14 - export npe_wav_gfs=14 - export nth_fv3=1 - export cdmbgwd="0.071,2.1,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling - export WRITE_GROUP=1 - export WRTTASK_PER_GROUP=$npe_node_max - export WRITE_GROUP_GFS=1 - export WRTTASK_PER_GROUP_GFS=$npe_node_max - export WRTIOBUF="4M" - ;; - "C96") - export DELTIM=450 - export layout_x=4 - export layout_y=4 - export layout_x_gfs=4 - export layout_y_gfs=4 - export npe_wav=14 - export npe_wav_gfs=14 - export nth_fv3=1 - export cdmbgwd="0.14,1.8,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling - export WRITE_GROUP=1 - export WRTTASK_PER_GROUP=$npe_node_max - export WRITE_GROUP_GFS=1 - export WRTTASK_PER_GROUP_GFS=$npe_node_max - export WRTIOBUF="4M" - ;; - "C192") - export DELTIM=450 - export layout_x=4 - export layout_y=6 - export layout_x_gfs=4 - export layout_y_gfs=6 - export npe_wav=21 - export npe_wav_gfs=21 - export nth_fv3=2 - export cdmbgwd="0.23,1.5,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling - export WRITE_GROUP=1 - export WRTTASK_PER_GROUP=$npe_node_max - export WRITE_GROUP_GFS=2 - export WRTTASK_PER_GROUP_GFS=$npe_node_max - export WRTIOBUF="8M" - ;; - "C384") - export DELTIM=200 - export layout_x=8 - export layout_y=8 - export layout_x_gfs=6 - export layout_y_gfs=6 - export npe_wav=35 - export npe_wav_gfs=35 - export nth_fv3=1 - export cdmbgwd="1.1,0.72,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling - export WRITE_GROUP=2 - export WRTTASK_PER_GROUP=64 - export WRITE_GROUP_GFS=1 - export WRTTASK_PER_GROUP_GFS=64 - export WRTIOBUF="16M" - ;; - "C768") - export DELTIM=150 - export layout_x=8 - export layout_y=12 - export layout_x_gfs=12 - export layout_y_gfs=24 - export npe_wav=140 - export npe_wav_gfs=448 - export nth_fv3=3 - export nth_fv3_gfs=5 - export cdmbgwd="4.0,0.15,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling - export WRITE_GROUP=2 - export WRTTASK_PER_GROUP=64 - export WRITE_GROUP_GFS=8 - export WRTTASK_PER_GROUP_GFS=64 - export WRTIOBUF="32M" - ;; - "C1152") - export DELTIM=120 - export layout_x=8 - export layout_y=16 - export layout_x_gfs=8 - export layout_y_gfs=16 - export npe_wav=140 - export npe_wav_gfs=140 - export nth_fv3=4 - export cdmbgwd="4.0,0.10,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling - export WRITE_GROUP=4 - export WRTTASK_PER_GROUP=$(echo "2*$npe_node_max" |bc) - export WRITE_GROUP_GFS=4 - export WRTTASK_PER_GROUP_GFS=$(echo "2*$npe_node_max" |bc) - export WRTIOBUF="48M" - ;; - "C3072") - export DELTIM=90 - export layout_x=16 - export layout_y=32 - export layout_x_gfs=16 - export layout_y_gfs=32 - export npe_wav=140 - export npe_wav_gfs=140 - export nth_fv3=4 - export cdmbgwd="4.0,0.05,1.0,1.0" # mountain blocking, ogwd, cgwd, cgwd src scaling - export WRITE_GROUP=4 - export WRTTASK_PER_GROUP=$(echo "3*$npe_node_max" |bc) - export WRITE_GROUP_GFS=4 - export WRTTASK_PER_GROUP_GFS=$(echo "3*$npe_node_max" |bc) - export WRTIOBUF="64M" - ;; - *) - echo "grid $case_in not supported, ABORT!" - exit 1 - ;; -esac - -echo "END: config.fv3" diff --git a/scripts/exgdas_enkf_fcst.sh b/scripts/exgdas_enkf_fcst.sh index bc126d5906..b448cb7cf3 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 @@ -105,8 +81,6 @@ if [[ ${RUN} == "enkfgfs" ]]; then export FHMAX=${FHMAX_ENKF_GFS:-${FHMAX_ENKF:-${FHMAX}}} fi -export restart_interval=${restart_interval_ENKF:-${restart_interval:-6}} - # gfs_physics_nml export FHSWR=${FHSWR_ENKF:-${FHSWR:-3600.}} export FHLWR=${FHLWR_ENKF:-${FHLWR:-3600.}} @@ -121,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 @@ -134,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=$(cat "${EFCSGRP}".fail | grep "MEMBER ${cmem}" | grep "PASS" | wc -l) + [[ ${memstat} -eq 1 ]] && skip_mem="YES" fi # Construct COM variables from templates (see config.com) @@ -179,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 [[ $(expr "${fhr}" % 3) -eq 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_det.sh b/ush/forecast_det.sh index 06329e0762..a9733ba9d1 100755 --- a/ush/forecast_det.sh +++ b/ush/forecast_det.sh @@ -41,7 +41,10 @@ FV3_GFS_det(){ # determine if restart IC exists to continue from a previous forecast RERUN=${RERUN:-"NO"} filecount=$(find "${COM_ATMOS_RESTART:-/dev/null}" -type f | wc -l) - if [[ ( ${CDUMP} = "gfs" || ( ${RUN} = "gefs" && ${CDATE_RST} = "" )) && ${rst_invt1} -gt 0 && ${FHMAX} -gt ${rst_invt1} && ${filecount} -gt 10 ]]; then + if [[ ( ${CDUMP} = "gfs" || ( ${RUN} = "gefs" && ${CDATE_RST} = "" )) && ${restart_interval} -gt 0 && ${FHMAX} -gt ${restart_interval} && ${filecount} -gt 10 ]]; then + filelist=$(ls -1 ${COM_ATMOS_RESTART}/????????.??0000.coupler.res) + filelist=$(ls -1 ${COM_ATMOS_RESTART}/????????.??0000.coupler.res) + flag2=${COM_ATMOS_RESTART}/coupler.res reverse=$(echo "${restart_interval[@]} " | tac -s ' ') for xfh in ${reverse} ; do yfh=$((xfh-(IAU_OFFSET/2))) @@ -67,7 +70,7 @@ FV3_GFS_det(){ mv "${flag1}" "${flag1}.old" if [[ -s "${flag2}" ]]; then mv "${flag2}" "${flag2}.old" ;fi RERUN="YES" - [[ ${xfh} = ${rst_invt1} ]] && RERUN="NO" + [[ ${xfh} = ${restart_interval} ]] && RERUN="NO" fi done fi diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index ec210df648..30356f853e 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -590,8 +590,8 @@ WW3_postdet() { for wavGRD in ${grdALL}; do ${NCP} "${COM_WAVE_PREP}/${COMPONENTwave}.mod_def.${wavGRD}" "${DATA}/mod_def.${wavGRD}" done - else - #if shel, only 1 waveGRD which is linked to mod_def.ww3 + else + #if shel, only 1 waveGRD which is linked to mod_def.ww3 ${NCP} "${COM_WAVE_PREP}/${COMPONENTwave}.mod_def.${waveGRD}" "${DATA}/mod_def.ww3" fi @@ -611,10 +611,10 @@ WW3_postdet() { if [ $warm_start = ".true." -o $RERUN = "YES" ]; then if [ $RERUN = "NO" ]; then waverstfile=${COM_WAVE_RESTART_PREV}/${sPDY}.${scyc}0000.restart.${wavGRD} - else + else waverstfile=${COM_WAVE_RESTART}/${PDYT}.${cyct}0000.restart.${wavGRD} fi - else + else waverstfile=${COM_WAVE_RESTART}/${sPDY}.${scyc}0000.restart.${wavGRD} fi if [ ! -f ${waverstfile} ]; then @@ -637,7 +637,7 @@ WW3_postdet() { for wavGRD in $waveGRD ; do ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.log.${wavGRD}.${PDY}${cyc}" "log.${wavGRD}" done - else + else ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.log.${waveGRD}.${PDY}${cyc}" "log.ww3" fi @@ -679,7 +679,7 @@ WW3_postdet() { for wavGRD in ${waveGRD} ; do ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_grd.${wavGRD}.${YMD}.${HMS}" "${DATA}/${YMD}.${HMS}.out_grd.${wavGRD}" done - else + else ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_grd.${waveGRD}.${YMD}.${HMS}" "${DATA}/${YMD}.${HMS}.out_grd.ww3" fi FHINC=$FHOUT_WAV @@ -697,7 +697,7 @@ WW3_postdet() { HMS="$(echo $YMDH | cut -c9-10)0000" if [ $waveMULTIGRID = ".true." ]; then ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_pnt.${waveuoutpGRD}.${YMD}.${HMS}" "${DATA}/${YMD}.${HMS}.out_pnt.${waveuoutpGRD}" - else + else ${NLN} "${COM_WAVE_HISTORY}/${wavprfx}.out_pnt.${waveuoutpGRD}.${YMD}.${HMS}" "${DATA}/${YMD}.${HMS}.out_pnt.ww3" fi @@ -990,35 +990,29 @@ 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 -sf $FIXcice/$ICERES/${ice_grid_file} $DATA/ - $NLN -sf $FIXcice/$ICERES/${ice_kmt_file} $DATA/ - $NLN -sf $FIXcice/$ICERES/$MESH_OCN_ICE $DATA/ + ${NLN} "${FIXcice}/${ICERES}/${ice_grid_file}" "${DATA}/" + ${NLN} "${FIXcice}/${ICERES}/${ice_kmt_file}" "${DATA}/" + ${NLN} "${FIXcice}/${ICERES}/${MESH_OCN_ICE}" "${DATA}/" # Link CICE output files - if [[ ! -d "${COM_ICE_HISTORY}" ]]; then mkdir -p "${COM_ICE_HISTORY}"; fi + if [[ ! -d "${COM_ICE_HISTORY}" ]]; then mkdir -p "${COM_ICE_HISTORY}"; fi mkdir -p ${COM_ICE_RESTART} if [[ "${RUN}" =~ "gfs" ]]; then diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index 334eacedef..d05ba9edc0 100755 --- a/ush/forecast_predet.sh +++ b/ush/forecast_predet.sh @@ -72,7 +72,6 @@ FV3_GFS_predet(){ if [ $FHMAX_HF -gt 0 -a $FHOUT_HF -gt 0 ]; then FDIAG=$FHOUT_HF; fi WRITE_DOPOST=${WRITE_DOPOST:-".false."} restart_interval=${restart_interval:-0} - rst_invt1=$(echo $restart_interval |cut -d " " -f 1) # Convert output settings into an explicit list OUTPUT_FH="" @@ -213,12 +212,12 @@ FV3_GFS_predet(){ print_freq=${print_freq:-6} #------------------------------------------------------- - if [[ ${RUN} =~ "gfs" || ${RUN} = "gefs" ]] && (( rst_invt1 > 0 )); then + if [[ ${RUN} =~ "gfs" || ${RUN} = "gefs" ]]; then if [[ ! -d ${COM_ATMOS_RESTART} ]]; then mkdir -p "${COM_ATMOS_RESTART}" ; fi ${NLN} "${COM_ATMOS_RESTART}" RESTART # The final restart written at the end doesn't include the valid date # Create links that keep the same name pattern for these files - VDATE=$($NDATE +$FHMAX_GFS $CDATE) + VDATE=$($NDATE +$FHMAX_GFS ${CDATE}) vPDY=$(echo $VDATE | cut -c1-8) vcyc=$(echo $VDATE | cut -c9-10) files="coupler.res fv_core.res.nc" diff --git a/workflow/setup_expt.py b/workflow/setup_expt.py index f79671c1aa..2da6c8a820 100755 --- a/workflow/setup_expt.py +++ b/workflow/setup_expt.py @@ -121,97 +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) # Link ocean files if do_ocean: - dst_dir = os.path.join(comrot, enkfdir, memdir, dst_ocn_rst_dir) - src_dir = os.path.join(inputs.icsdir, enkfdir, memdir, src_ocn_rst_dir) + 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 - incdir = f'enkf{inputs.cdump}.{idatestr[:8]}/{idatestr[8:]}' - incfile = f'{inputs.cdump}.t{idatestr[8:]}z.ocninc.nc' # TODO: this file should be enkfgdas.tHHz.ocninc.nc - src_file = os.path.join(inputs.icsdir, incdir, memdir, src_ocn_anl_dir, incfile) - dst_file = os.path.join(comrot, incdir, memdir, dst_ocn_anl_dir, incfile) - makedirs_if_missing(os.path.join(comrot, incdir, memdir, dst_ocn_anl_dir)) + 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, enkfdir, memdir, dst_ice_rst_dir) - src_dir = os.path.join(inputs.icsdir, enkfdir, memdir, src_ice_rst_dir) + 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, enkfdir, memdir, dst_med_dir) - src_dir = os.path.join(inputs.icsdir, enkfdir, memdir, src_med_dir) + 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_rst_dir) - src_dir = os.path.join(inputs.icsdir, detdir, src_ice_rst_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}' From 2c802565739e65a2c49aea1f0e658109a791f2d4 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Wed, 28 Jun 2023 17:17:26 -0400 Subject: [PATCH 03/13] cycled for 3 cycles with coupled ensemble --- jobs/JGLOBAL_ARCHIVE | 5 +- jobs/JGLOBAL_FORECAST | 6 +- jobs/rocoto/coupled_ic.sh | 49 ++---- ush/forecast_det.sh | 3 +- ush/forecast_postdet.sh | 266 +++++++++++------------------ ush/forecast_predet.sh | 57 ++++--- ush/parsing_model_configure_FV3.sh | 2 +- ush/parsing_namelists_CICE.sh | 12 +- ush/parsing_namelists_FV3.sh | 189 ++++++++++---------- 9 files changed, 263 insertions(+), 326 deletions(-) diff --git a/jobs/JGLOBAL_ARCHIVE b/jobs/JGLOBAL_ARCHIVE index 3bb8b414d4..2e16b12dc5 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_DAILY COM_OCEAN_HISTORY COM_OCEAN_INPUT COM_OCEAN_XSECT \ + COM_OCEAN_DAILY COM_OCEAN_RESTART COM_OCEAN_HISTORY COM_OCEAN_INPUT COM_OCEAN_XSECT \ 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..ed3f7a6f96 100755 --- a/jobs/JGLOBAL_FORECAST +++ b/jobs/JGLOBAL_FORECAST @@ -30,10 +30,10 @@ fi # Ignore possible spelling error (nothing is misspelled) # shellcheck disable=SC2153 -GDATE=$(${NDATE} -"${assim_freq}" "${PDY}${cyc}") +declare -rx GDATE=$(date -d "${PDY} ${cyc} - ${assim_freq} hours" +%Y%m%d%H) # 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/ush/forecast_det.sh b/ush/forecast_det.sh index ab4fadebdf..bf1b94ca8c 100755 --- a/ush/forecast_det.sh +++ b/ush/forecast_det.sh @@ -99,7 +99,8 @@ FV3_det(){ SDATE="${PDYS}${cycs}" CDATE_RST="${SDATE}" RERUN="YES" - [[ ${xfh} = ${rst_invt1} ]] && RERUN="NO" + echo "Restarts have been found for CDATE_RST=${CDATE_RST}, returning with 'RERUN=YES'" + break fi done diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index 71212b8d04..d2bb3faf5c 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,39 +602,35 @@ WW3_postdet() { fi # Loop for gridded output (uses FHINC) - fhr=${FHMIN_WAV} + local fhr=${FHMIN_WAV} while [[ ${fhr} -le ${FHMAX_WAV} ]]; do - YMDH=$(${NDATE} "${fhr}" "${CDATE}") - YMD="${YMDH:0:8}" - HMS="${YMDH:8:2}0000" + local 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} + local FHINC=${FHOUT_WAV} if (( FHMAX_HF_WAV > 0 && FHOUT_HF_WAV > 0 && fhr < FHMAX_HF_WAV )); then - FHINC=${FHOUT_HF_WAV} + local FHINC=${FHOUT_HF_WAV} fi - fhr=$((fhr+FHINC)) + local fhr=$((fhr+FHINC)) done # Loop for point output (uses DTPNT) - fhr=${FHMIN_WAV} + local fhr=${FHMIN_WAV} while [[ ${fhr} -le ${FHMAX_WAV} ]]; do - YMDH=$(${NDATE} "${fhr}" "${CDATE}") - YMD="${YMDH:0:8}" - HMS="${YMDH:8:2}0000" + local 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} - fhr=$((fhr+FHINC)) + local FHINC=${FHINCP_WAV} + local fhr=$((fhr+FHINC)) done } @@ -703,12 +688,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 +724,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 +740,41 @@ 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) + + 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 +818,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 +848,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 +865,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 @@ -950,7 +909,7 @@ CICE_postdet() { # Link CICE output files if [[ ! -d "${COM_ICE_HISTORY}" ]]; then mkdir -p "${COM_ICE_HISTORY}"; fi - mkdir -p ${COM_ICE_RESTART} + mkdir -p "${COM_ICE_RESTART}" if [[ "${RUN}" =~ "gfs" ]]; then # Link output files for RUN = gfs @@ -959,27 +918,18 @@ 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)) + 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) + local seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds + local sec5=$(printf "%5.5d" "${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.${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${sec5}.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.${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${sec5}.nc" fi last_fhr=${fhr} done @@ -988,13 +938,13 @@ 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=$(to_seconds "${current_cycle:8:2}0000") # convert HHMMSS to seconds + ${NLN} "${COM_ICE_HISTORY}/${RUN}.t${cyc}z.iceic.nc" "${DATA}/CICE_OUTPUT/iceh_ic.${current_cycle:0:4}-${current_cycle:4:2}-${current_cycle:6:2}-${seconds}.nc" # Link instantaneous CICE forecast output files from DATA/CICE_OUTPUT to COMOUTice local fhr="${FHOUT}" while [[ "${fhr}" -le "${FHMAX}" ]]; do - local idate=$(date -d "${CDATE:0:8} ${CDATE:8:2} + ${fhr} hours" +%Y%m%d%H) + local idate=$(date -d "${current_cycle:0:8} ${current_cycle: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" @@ -1064,25 +1014,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:4}${vdate:4:2}${vdate:6:2}_${vdate:8:2}00z.nc4" ]]; then + rm -f "${COM_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:4}${vdate:4:2}${vdate:6:2}_${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:4}${vdate:4:2}${vdate:6:2}_${vdate:8:2}00z.nc4" \ + "${DATA}/gocart.inst_aod.${vdate:0:4}${vdate:4:2}${vdate:6:2}_${vdate:8:2}00z.nc4" done } diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index d6aad1f550..8d86b734dd 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} + local 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 @@ -193,9 +203,6 @@ FV3_predet(){ ${NLN} "${COM_ATMOS_RESTART}" RESTART # The final restart written at the end doesn't include the valid date # Create links that keep the same name pattern for these files - VDATE=$($NDATE +$FHMAX_GFS $CDATE) - vPDY=$(echo $VDATE | cut -c1-8) - vcyc=$(echo $VDATE | cut -c9-10) files="coupler.res fv_core.res.nc" for n in $(seq 1 "${ntiles}"); do for base in ca_data fv_core.res fv_srf_wnd.res fv_tracer.res phy_data sfc_data; do 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..638297d3b4 100755 --- a/ush/parsing_namelists_CICE.sh +++ b/ush/parsing_namelists_CICE.sh @@ -39,13 +39,19 @@ else fi local max_blocks=-1 +local sec=$(to_seconds "${current_cycle:8:2}0000") +local stepsperhr=$((3600/${ICETIM})) +local nhours=$(nhour "${current_cycle}" "${current_cycle:0:4}010100") +local steps=$((nhours*stepsperhr)) +local 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 with the experiment name and base date +if [[ ${DOIAU} = "YES" ]]; then + local model_start_time_str="${previous_cycle:0:4} ${previous_cycle:4:2} ${previous_cycle:6:2} ${previous_cycle:8:2} 0 0" else + local model_start_time_str="${current_cycle:0:4} ${current_cycle:4:2} ${current_cycle:6:2} ${current_cycle:8:2} 0 0" +fi cat > diag_table << EOF -FV3 Forecast -${sPDY:0:4} ${sPDY:4:2} ${sPDY:6:2} ${scyc} 0 0 +UFS_Weather_Model_Forecast +${model_start_time_str} EOF -cat $DIAG_TABLE >> diag_table -fi +cat "${DIAG_TABLE}" >> diag_table -if [ ! -z "${AERO_DIAG_TABLE:-}" ]; then - cat ${AERO_DIAG_TABLE} >> diag_table +if [[ ! -z "${AERO_DIAG_TABLE:-}" ]]; then + cat "${AERO_DIAG_TABLE}" >> 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 [[ ! -z "${AERO_FIELD_TABLE:-}" ]]; then + nrec=$( cat "${FIELD_TABLE}" | wc -l ) 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 <> input.nml <> input.nml <> input.nml <> input.nml << EOF fscav_aero = ${fscav_aero:-'*:0.0'} EOF @@ -385,13 +382,13 @@ cat >> input.nml <> input.nml << EOF iaufhrs = ${IAUFHRS} iau_delthrs = ${IAU_DELTHRS} @@ -401,7 +398,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 +415,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 +441,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 +454,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} @@ -585,16 +582,16 @@ EOF # Add namelist for stochastic physics options echo "" >> 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" -o "${DO_SHUM}" = "YES" -o "${DO_SKEB}" = "YES" -o "${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 +600,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 +626,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 +657,9 @@ EOF fi -echo "$(cat input.nml)" +# Echo out formatted "input.nml" +echo "====================================" +echo "FV3_namelists(): 'input.nml'" +cat input.nml +echo "====================================" } From eb57158b4d158a921c2a68809cb8e83dcc26fe17 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Wed, 28 Jun 2023 21:55:16 -0400 Subject: [PATCH 04/13] Apply suggestions from code review Co-authored-by: Walter Kolczynski - NOAA --- scripts/exgdas_enkf_fcst.sh | 6 +++--- ush/forecast_postdet.sh | 6 +++--- ush/forecast_predet.sh | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/exgdas_enkf_fcst.sh b/scripts/exgdas_enkf_fcst.sh index b448cb7cf3..99918ccfbf 100755 --- a/scripts/exgdas_enkf_fcst.sh +++ b/scripts/exgdas_enkf_fcst.sh @@ -45,7 +45,7 @@ if [[ -f ${EFCSGRP} ]]; then rm -f "${EFCSGRP}" else echo "RERUN_EFCSGRP = ${RERUN_EFCSGRP}, will re-run FAILED members only!" - ${NMV} "${EFCSGRP}" "${EFCSGRP}".fail + ${NMV} "${EFCSGRP}" "${EFCSGRP}.fail" fi fi @@ -121,7 +121,7 @@ for imem in $(seq "${ENSBEG}" "${ENSEND}"); do skip_mem="NO" if [[ -f ${EFCSGRP}.fail ]]; then - memstat=$(cat "${EFCSGRP}".fail | grep "MEMBER ${cmem}" | grep "PASS" | wc -l) + memstat=$(cat "${EFCSGRP}.fail" | grep "MEMBER ${cmem}" | grep "PASS" | wc -l) [[ ${memstat} -eq 1 ]] && skip_mem="YES" fi @@ -177,7 +177,7 @@ for imem in $(seq "${ENSBEG}" "${ENSEND}"); do fhr=${FHOUT} while [[ ${fhr} -le ${FHMAX} ]]; do FH3=$(printf %03i "${fhr}") - if [[ $(expr "${fhr}" % 3) -eq 0 ]]; then + 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)) diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index d2bb3faf5c..48c71de6be 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -542,12 +542,12 @@ WW3_postdet() { for wavGRD in ${waveGRD} ; do if [[ "${warm_start}" = ".true." ]] || [[ "${RERUN}" = "YES" ]]; then if [[ ${RERUN} = "NO" ]]; then - local waverstfile=${COM_WAVE_RESTART_PREV}/${sPDY}.${scyc}0000.restart.${wavGRD} + local waverstfile="${COM_WAVE_RESTART_PREV}/${sPDY}.${scyc}0000.restart.${wavGRD}" else - local waverstfile=${COM_WAVE_RESTART}/${PDYT}.${cyct}0000.restart.${wavGRD} + local waverstfile="${COM_WAVE_RESTART}/${PDYT}.${cyct}0000.restart.${wavGRD}" fi else - local 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 diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index 8d86b734dd..c9455e2cc2 100755 --- a/ush/forecast_predet.sh +++ b/ush/forecast_predet.sh @@ -102,7 +102,7 @@ FV3_predet(){ for (( fh = FHMIN; fh < FHMAX_HF; fh = fh + FHOUT_HF )); do FV3_OUTPUT_FH="${FV3_OUTPUT_FH} ${fh}" done - local fhr=${FHMAX_HF} + fhr=${FHMAX_HF} fi for (( fh = fhr; fh <= FHMAX; fh = fh + FHOUT )); do FV3_OUTPUT_FH="${FV3_OUTPUT_FH} ${fh}" From 10503ec8af0057fc36073b64e007ac97a3a59f6b Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Wed, 28 Jun 2023 21:57:20 -0400 Subject: [PATCH 05/13] Update ush/forecast_postdet.sh Co-authored-by: Walter Kolczynski - NOAA --- ush/forecast_postdet.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index 48c71de6be..e6f67fbbca 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -756,6 +756,8 @@ MOM6_postdet() { 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}" From 4243202c9146411b144ab9c6e04e6096989216b7 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Wed, 28 Jun 2023 21:58:47 -0400 Subject: [PATCH 06/13] Update ush/forecast_postdet.sh Co-authored-by: Walter Kolczynski - NOAA --- ush/forecast_postdet.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index e6f67fbbca..fd39e939c0 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -1020,8 +1020,8 @@ GOCART_postdet() { 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.${vdate:0:4}${vdate:4:2}${vdate:6:2}_${vdate:8:2}00z.nc4" ]]; then - rm -f "${COM_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:4}${vdate:4:2}${vdate:6:2}_${vdate:8:2}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.${vdate:0:4}${vdate:4:2}${vdate:6:2}_${vdate:8:2}00z.nc4" \ From 4a6b0c19b1c175305bdd5a5d1f88dc9735c91b45 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Wed, 28 Jun 2023 21:59:14 -0400 Subject: [PATCH 07/13] Update ush/forecast_postdet.sh Co-authored-by: Walter Kolczynski - NOAA --- ush/forecast_postdet.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index fd39e939c0..5545d007ff 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -1024,7 +1024,7 @@ GOCART_postdet() { rm -f "${COM_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" fi - ${NLN} "${COM_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:4}${vdate:4:2}${vdate:6:2}_${vdate:8:2}00z.nc4" \ - "${DATA}/gocart.inst_aod.${vdate:0:4}${vdate:4:2}${vdate:6:2}_${vdate:8:2}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 } From 711a0889a1d5d6dc1443dbce65bb58f6ad0ebbf2 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Wed, 28 Jun 2023 21:59:36 -0400 Subject: [PATCH 08/13] Update ush/parsing_namelists_FV3.sh Co-authored-by: Walter Kolczynski - NOAA --- ush/parsing_namelists_FV3.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ush/parsing_namelists_FV3.sh b/ush/parsing_namelists_FV3.sh index 31c9ee864e..20d6e312a7 100755 --- a/ush/parsing_namelists_FV3.sh +++ b/ush/parsing_namelists_FV3.sh @@ -582,7 +582,7 @@ EOF # Add namelist for stochastic physics options echo "" >> 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 From 5398408c6af2f79d74d0111e333f18bf12151456 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Thu, 29 Jun 2023 15:02:31 -0400 Subject: [PATCH 09/13] address shellcheck errors --- jobs/JGLOBAL_FORECAST | 3 ++- scripts/exgdas_enkf_fcst.sh | 2 +- ush/parsing_namelists_CICE.sh | 10 +++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/jobs/JGLOBAL_FORECAST b/jobs/JGLOBAL_FORECAST index ed3f7a6f96..46d7d55dc7 100755 --- a/jobs/JGLOBAL_FORECAST +++ b/jobs/JGLOBAL_FORECAST @@ -30,7 +30,8 @@ fi # Ignore possible spelling error (nothing is misspelled) # shellcheck disable=SC2153 -declare -rx GDATE=$(date -d "${PDY} ${cyc} - ${assim_freq} hours" +%Y%m%d%H) +GDATE=$(date -d "${PDY} ${cyc} - ${assim_freq} hours" +%Y%m%d%H) +declare -rx GDATE # shellcheck disable= declare -rx gPDY="${GDATE:0:8}" declare -rx gcyc="${GDATE:8:2}" diff --git a/scripts/exgdas_enkf_fcst.sh b/scripts/exgdas_enkf_fcst.sh index 99918ccfbf..d2e3b9f73c 100755 --- a/scripts/exgdas_enkf_fcst.sh +++ b/scripts/exgdas_enkf_fcst.sh @@ -121,7 +121,7 @@ for imem in $(seq "${ENSBEG}" "${ENSEND}"); do skip_mem="NO" if [[ -f ${EFCSGRP}.fail ]]; then - memstat=$(cat "${EFCSGRP}.fail" | grep "MEMBER ${cmem}" | grep "PASS" | wc -l) + memstat=$(grep "MEMBER ${cmem}" "${EFCSGRP}.fail" | grep -c "PASS") [[ ${memstat} -eq 1 ]] && skip_mem="YES" fi diff --git a/ush/parsing_namelists_CICE.sh b/ush/parsing_namelists_CICE.sh index 638297d3b4..2af8f1c810 100755 --- a/ush/parsing_namelists_CICE.sh +++ b/ush/parsing_namelists_CICE.sh @@ -39,11 +39,11 @@ else fi local max_blocks=-1 -local sec=$(to_seconds "${current_cycle:8:2}0000") -local stepsperhr=$((3600/${ICETIM})) -local nhours=$(nhour "${current_cycle}" "${current_cycle:0:4}010100") -local steps=$((nhours*stepsperhr)) -local npt=$((FHMAX*stepsperhr)) # Need this in order for dump_last to work +local sec stepsperhr nhours steps npt +sec=$(to_seconds "${current_cycle:8:2}0000") +stepsperhr=$((3600/ICETIM)) +nhours=$(nhour "${current_cycle}" "${current_cycle:0:4}010100") +npt=$((FHMAX*stepsperhr)) # Need this in order for dump_last to work cat > ice_in < Date: Thu, 29 Jun 2023 15:12:09 -0400 Subject: [PATCH 10/13] more shellcheck findings --- ush/parsing_namelists_CICE.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ush/parsing_namelists_CICE.sh b/ush/parsing_namelists_CICE.sh index 2af8f1c810..6ef743ebc9 100755 --- a/ush/parsing_namelists_CICE.sh +++ b/ush/parsing_namelists_CICE.sh @@ -39,10 +39,9 @@ else fi local max_blocks=-1 -local sec stepsperhr nhours steps npt +local sec stepsperhr npt sec=$(to_seconds "${current_cycle:8:2}0000") stepsperhr=$((3600/ICETIM)) -nhours=$(nhour "${current_cycle}" "${current_cycle:0:4}010100") npt=$((FHMAX*stepsperhr)) # Need this in order for dump_last to work cat > ice_in < Date: Thu, 29 Jun 2023 15:33:35 -0400 Subject: [PATCH 11/13] some more shellcheck fixes --- ush/forecast_postdet.sh | 44 +++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index 5545d007ff..70669e6708 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -922,16 +922,17 @@ CICE_postdet() { export ENSMEM=${ENSMEM:-01} # 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 + local vdate seconds vdatestr fhr last_fhr 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) - local seconds=$(to_seconds "${vdate:8:2}0000") # convert HHMMSS to seconds - local sec5=$(printf "%5.5d" "${seconds}") + 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}.${current_cycle}.nc" "${DATA}/CICE_OUTPUT/iceh_ic.${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${sec5}.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}.${current_cycle}.nc" "${DATA}/CICE_OUTPUT/iceh_$(printf "%0.2d" "${interval}")h.${vdate:0:4}-${vdate:4:2}-${vdate:6:2}-${sec5}.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 @@ -940,29 +941,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 "${current_cycle:8:2}0000") # convert HHMMSS to seconds - ${NLN} "${COM_ICE_HISTORY}/${RUN}.t${cyc}z.iceic.nc" "${DATA}/CICE_OUTPUT/iceh_ic.${current_cycle:0:4}-${current_cycle:4:2}-${current_cycle: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 "${current_cycle:0:8} ${current_cycle: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 } From a41c0aa3cb7639fc0846133f39f15922ce3fb8b1 Mon Sep 17 00:00:00 2001 From: Rahul Mahajan Date: Thu, 29 Jun 2023 16:55:11 -0400 Subject: [PATCH 12/13] more fixes --- ush/parsing_namelists_FV3.sh | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/ush/parsing_namelists_FV3.sh b/ush/parsing_namelists_FV3.sh index 20d6e312a7..372078acea 100755 --- a/ush/parsing_namelists_FV3.sh +++ b/ush/parsing_namelists_FV3.sh @@ -20,30 +20,28 @@ FIELD_TABLE=${FIELD_TABLE:-${PARM_FV3DIAG}/field_table} # ensure non-prognostic tracers are set dnats=${dnats:-0} -# build the diag_table with the experiment name and base date -if [[ ${DOIAU} = "YES" ]]; then - local model_start_time_str="${previous_cycle:0:4} ${previous_cycle:4:2} ${previous_cycle:6:2} ${previous_cycle:8:2} 0 0" +# 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 - local model_start_time_str="${current_cycle:0:4} ${current_cycle:4:2} ${current_cycle:6:2} ${current_cycle:8:2} 0 0" + echo "${current_cycle:0:4} ${current_cycle:4:2} ${current_cycle:6:2} ${current_cycle:8:2} 0 0" fi -cat > diag_table << EOF -UFS_Weather_Model_Forecast -${model_start_time_str} -EOF -cat "${DIAG_TABLE}" >> diag_table - -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 # 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 ) @@ -256,12 +254,13 @@ EOF EOF ;; FV3_GFS_v17*) + local default_dt_inner=$(( DELTIM/2 )) cat >> 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."} @@ -467,8 +466,6 @@ if [[ ${knob_ugwp_version} -eq 1 ]]; then EOF fi - - echo "" >> input.nml cat >> input.nml < Date: Thu, 29 Jun 2023 17:04:31 -0400 Subject: [PATCH 13/13] some more of the fixes --- ush/forecast_postdet.sh | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index 70669e6708..d3fd5c2a97 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -93,7 +93,7 @@ EOF ${NLN} "${file}" "${DATA}/INPUT/${file2}" done - local hour_rst=$(nhour ${CDATE_RST} ${current_cycle}) + local hour_rst=$(nhour "${CDATE_RST}" "${current_cycle}") IAU_FHROT=$((IAU_OFFSET+hour_rst)) if [[ ${DOIAU} = "YES" ]]; then IAUFHRS=-1 @@ -602,9 +602,10 @@ WW3_postdet() { fi # Loop for gridded output (uses FHINC) - local fhr=${FHMIN_WAV} + local fhr vdate FHINC wavGRD + fhr=${FHMIN_WAV} while [[ ${fhr} -le ${FHMAX_WAV} ]]; do - local vdate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + 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}.${vdate:0:8}.${vdate:8:2}0000" "${DATA}/${vdate:0:8}.${vdate:8:2}0000.out_grd.${wavGRD}" @@ -612,25 +613,25 @@ WW3_postdet() { else ${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 - local FHINC=${FHOUT_WAV} + FHINC=${FHOUT_WAV} if (( FHMAX_HF_WAV > 0 && FHOUT_HF_WAV > 0 && fhr < FHMAX_HF_WAV )); then - local FHINC=${FHOUT_HF_WAV} + FHINC=${FHOUT_HF_WAV} fi - local fhr=$((fhr+FHINC)) + fhr=$((fhr+FHINC)) done # Loop for point output (uses DTPNT) - local fhr=${FHMIN_WAV} + fhr=${FHMIN_WAV} while [[ ${fhr} -le ${FHMAX_WAV} ]]; do - local vdate=$(date -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) + 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}.${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}.${vdate:0:8}.${vdate:8:2}0000" "${DATA}/${vdate:0:8}.${vdate:8:2}0000.out_pnt.ww3" fi - local FHINC=${FHINCP_WAV} - local fhr=$((fhr+FHINC)) + FHINC=${FHINCP_WAV} + fhr=$((fhr+FHINC)) done }