diff --git a/parm/archive/gdas.yaml.j2 b/parm/archive/gdas.yaml.j2 index 1e9597ba1c7..7a9e4021385 100644 --- a/parm/archive/gdas.yaml.j2 +++ b/parm/archive/gdas.yaml.j2 @@ -67,7 +67,7 @@ gdas: - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}oznstat" - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}radstat" {% endif %} - {% if AERO_ANL_RUN == "gdas" or AERO_ANL_RUN == "both" %} + {% if DO_AERO and (AERO_ANL_RUN == "gdas" or AERO_ANL_RUN == "both") %} - "{{ COMIN_CHEM_ANALYSIS | relpath(ROTDIR) }}/{{ head }}aerostat" {% endif %} {% if DO_PREP_OBS_AERO %} diff --git a/parm/archive/gfs_arcdir.yaml.j2 b/parm/archive/gfs_arcdir.yaml.j2 index 57dbc78885e..58e2cdc6990 100644 --- a/parm/archive/gfs_arcdir.yaml.j2 +++ b/parm/archive/gfs_arcdir.yaml.j2 @@ -50,7 +50,7 @@ ARCDIR ~ "/snowstat." ~ RUN ~ "." ~ cycle_YMDH ~ ".tgz"]) %} {% endif %} - {% if AERO_ANL_RUN == RUN or AERO_ANL_RUN == "both" %} + {% if DO_AERO and (AERO_ANL_RUN == RUN or AERO_ANL_RUN == "both") %} {% do det_anl_files.append([COMIN_CHEM_ANALYSIS ~ "/" ~ head ~ "aerostat", ARCDIR ~ "/aerostat." ~ RUN ~ "." ~ cycle_YMDH ]) %} {% endif %} diff --git a/parm/archive/gfsa.yaml.j2 b/parm/archive/gfsa.yaml.j2 index dcf059d8715..7cb3c770fd8 100644 --- a/parm/archive/gfsa.yaml.j2 +++ b/parm/archive/gfsa.yaml.j2 @@ -38,7 +38,7 @@ gfsa: {% else %} - "{{ COMIN_ATMOS_ANALYSIS | relpath(ROTDIR) }}/{{ head }}gsistat" {% endif %} - {% if AERO_ANL_RUN == "gfs" or AERO_ANL_RUN == "both" %} + {% if DO_AERO and (AERO_ANL_RUN == "gfs" or AERO_ANL_RUN == "both") %} - "{{ COMIN_CHEM_ANALYSIS | relpath(ROTDIR) }}/{{ head }}aerostat" {% endif %} {% if DO_PREP_OBS_AERO %} diff --git a/parm/archive/master_gfs.yaml.j2 b/parm/archive/master_gfs.yaml.j2 index ab9a00c95e3..3f7c2e9d14e 100644 --- a/parm/archive/master_gfs.yaml.j2 +++ b/parm/archive/master_gfs.yaml.j2 @@ -33,7 +33,7 @@ datasets: {% endfilter %} {% endif %} -{% if AERO_FCST_RUN == "gfs" or AERO_FCST_RUN == "both" %} +{% if DO_AERO and (AERO_FCST_RUN == "gfs" or AERO_FCST_RUN == "both") %} # Aerosol forecasts {% filter indent(width=4) %} {% include "chem.yaml.j2" %} diff --git a/parm/config/gefs/config.base b/parm/config/gefs/config.base index 13f286c4947..bf34504f09a 100644 --- a/parm/config/gefs/config.base +++ b/parm/config/gefs/config.base @@ -136,9 +136,8 @@ export DO_OCN="NO" export DO_ICE="NO" export DO_AERO="NO" export DO_EXTRACTVARS="@DO_EXTRACTVARS@" # Option to process and extract a subset of products to save on disk -export AERO_FCST_RUN="" # When to run aerosol forecast: gdas, gfs, or both -export AERO_ANL_RUN="" # When to run aerosol analysis: gdas, gfs, or both -export WAVE_RUN="" # When to include wave suite: gdas, gfs, or both +export AERO_FCST_RUN="gefs" # When to run aerosol forecast: gdas, gfs, or both +export WAVE_RUN="gefs" # When to include wave suite: gdas, gfs, or both export DOBNDPNT_WAVE="NO" # The GEFS buoys file does not currently have any boundary points export DOIBP_WAV="NO" # Option to create point outputs from input boundary points export FRAC_GRID=".true." @@ -184,13 +183,10 @@ case "${APP}" in ;; ATMA) export DO_AERO="YES" - export AERO_ANL_RUN="both" - export AERO_FCST_RUN="gdas" ;; ATMW) export DO_COUPLED="YES" export DO_WAVE="YES" - export WAVE_RUN="both" ;; NG-GODAS) export DO_ATM="NO" @@ -204,13 +200,10 @@ case "${APP}" in if [[ "${APP}" =~ A$ ]]; then export DO_AERO="YES" - export AERO_ANL_RUN="both" - export AERO_FCST_RUN="gdas" fi if [[ "${APP}" =~ ^S2SW ]]; then export DO_WAVE="YES" - export WAVE_RUN="both" fi ;; *) @@ -225,6 +218,7 @@ export FHMAX=9 export FHOUT=3 # Will be changed to 1 in config.base if (DOHYBVAR set to NO and l4densvar set to false) export FHOUT_OCN=3 export FHOUT_ICE=3 +export FHOUT_AERO=3 # GFS cycle info export INTERVAL_GFS=@INTERVAL_GFS@ # Frequency of GFS forecast diff --git a/parm/config/gefs/yaml/defaults.yaml b/parm/config/gefs/yaml/defaults.yaml index f0e8772b671..cda90c54851 100644 --- a/parm/config/gefs/yaml/defaults.yaml +++ b/parm/config/gefs/yaml/defaults.yaml @@ -31,4 +31,6 @@ stage_ic: USE_ATM_ENS_PERTURB_FILES: "NO" ocn: MOM6_INTERP_ICS: "NO" - +# config.aero has just a system-specific path to add. +# This is handled by the setup_expt.py, but it has to be told to write to it. +aero: {} diff --git a/parm/config/gfs/config.base b/parm/config/gfs/config.base index 4f702f96683..b0d4fbf42af 100644 --- a/parm/config/gfs/config.base +++ b/parm/config/gfs/config.base @@ -176,9 +176,9 @@ export DO_OCN="NO" export DO_ICE="NO" export DO_AERO="NO" export DO_PREP_OBS_AERO="NO" -export AERO_FCST_RUN="" # When to run aerosol forecast: gdas, gfs, or both -export AERO_ANL_RUN="" # When to run aerosol analysis: gdas, gfs, or both -export WAVE_RUN="" # When to include wave suite: gdas, gfs, or both +export AERO_FCST_RUN="gdas" # When to run aerosol forecast: gdas, gfs, or both +export AERO_ANL_RUN="both" # When to run aerosol analysis: gdas, gfs, or both +export WAVE_RUN="both" # When to include wave suite: gdas, gfs, or both export DOBNDPNT_WAVE="NO" export DOIBP_WAV="NO" # Option to create point outputs from input boundary points export FRAC_GRID=".true." @@ -229,13 +229,10 @@ case "${APP}" in ;; ATMA) export DO_AERO="YES" - export AERO_ANL_RUN="both" - export AERO_FCST_RUN="gdas" ;; ATMW) export DO_COUPLED="YES" export DO_WAVE="YES" - export WAVE_RUN="both" ;; NG-GODAS) export DO_ATM="NO" @@ -249,13 +246,10 @@ case "${APP}" in if [[ "${APP}" =~ A$ ]]; then export DO_AERO="YES" - export AERO_ANL_RUN="both" - export AERO_FCST_RUN="gdas" fi if [[ "${APP}" =~ ^S2SW ]]; then export DO_WAVE="YES" - export WAVE_RUN="both" fi ;; *) @@ -278,6 +272,7 @@ export FHMAX=9 export FHOUT=3 # Will be changed to 1 in config.base if (DOHYBVAR set to NO and l4densvar set to false) export FHOUT_OCN=3 export FHOUT_ICE=3 +export FHOUT_AERO=3 # Cycle to run EnKF (set to BOTH for both gfs and gdas) export EUPD_CYC="@EUPD_CYC@" diff --git a/parm/ufs/gocart/AERO_HISTORY.rc b/parm/ufs/gocart/AERO_HISTORY.rc index 4c7df15b2a7..db1b934f5f3 100644 --- a/parm/ufs/gocart/AERO_HISTORY.rc +++ b/parm/ufs/gocart/AERO_HISTORY.rc @@ -58,7 +58,7 @@ PC720x361-DC.LM: 72 inst_du_ss.mode: 'instantaneous', inst_du_ss.grid_label: PC720x361-DC , inst_du_ss.splitField: 1, - inst_du_ss.frequency: 120000 , + inst_du_ss.frequency: @[inst_du_ss_freq] , inst_du_ss.duration: 010000 , inst_du_ss.ref_time: 000000 , inst_du_ss.nbits: 10, @@ -72,7 +72,7 @@ PC720x361-DC.LM: 72 tavg_du_ss.mode: 'time-averaged', tavg_du_ss.grid_label: PC720x361-DC , tavg_du_ss.splitField: 1, - tavg_du_ss.frequency: 120000 , + tavg_du_ss.frequency: @[tavg_du_ss_freq] , tavg_du_ss.duration: 010000 , tavg_du_ss.ref_time: 000000 , tavg_du_ss.nbits: 10, @@ -85,7 +85,7 @@ PC720x361-DC.LM: 72 inst_ca.template: '%y4%m2%d2_%h2%n2z.nc4', inst_ca.mode: 'instantaneous', inst_ca.grid_label: PC720x361-DC , - inst_ca.frequency: 120000 , + inst_ca.frequency: @[inst_ca_freq] , inst_ca.duration: 010000 , inst_ca.ref_time: 000000 , inst_ca.nbits: 10, @@ -100,7 +100,7 @@ PC720x361-DC.LM: 72 inst_ni.template: '%y4%m2%d2_%h2%n2z.nc4', inst_ni.mode: 'instantaneous', inst_ni.grid_label: PC720x361-DC , - inst_ni.frequency: 120000 , + inst_ni.frequency: @[inst_ni_freq] , inst_ni.duration: 010000 , inst_ni.ref_time: 000000 , inst_ni.nbits: 10, @@ -116,7 +116,7 @@ PC720x361-DC.LM: 72 inst_su.template: '%y4%m2%d2_%h2%n2z.nc4', inst_su.mode: 'instantaneous', inst_su.grid_label: PC720x361-DC , - inst_su.frequency: 120000 , + inst_su.frequency: @[inst_su_freq] , inst_su.duration: 010000 , inst_su.ref_time: 000000 , inst_su.nbits: 10, @@ -135,7 +135,7 @@ PC720x361-DC.LM: 72 inst_du_bin.mode: 'instantaneous' inst_du_bin.grid_label: PC720x361-DC , inst_du_bin.splitField: 1, - inst_du_bin.frequency: 010000 , + inst_du_bin.frequency: @[inst_du_bin_freq] , inst_du_bin.duration: 010000 , inst_du_bin.ref_time: 000000 , inst_du_bin.nbits: 10, @@ -152,7 +152,7 @@ PC720x361-DC.LM: 72 tavg_du_bin.mode: 'time-averaged' tavg_du_bin.grid_label: PC720x361-DC , tavg_du_bin.splitField: 1, - tavg_du_bin.frequency: 030000 , + tavg_du_bin.frequency: @[tavg_du_bin_freq] , tavg_du_bin.duration: 010000 , tavg_du_bin.ref_time: 000000 , tavg_du_bin.nbits: 10, @@ -169,7 +169,7 @@ PC720x361-DC.LM: 72 inst_ss_bin.mode: 'instantaneous' inst_ss_bin.grid_label: PC720x361-DC , inst_ss_bin.splitField: 1, - inst_ss_bin.frequency: 060000 , + inst_ss_bin.frequency: @[inst_ss_bin_freq] , inst_ss_bin.duration: 010000 , inst_ss_bin.ref_time: 000000 , inst_ss_bin.nbits: 10, @@ -186,7 +186,7 @@ PC720x361-DC.LM: 72 inst_ca_bin.mode: 'instantaneous' inst_ca_bin.grid_label: PC720x361-DC , inst_ca_bin.splitField: 1, - inst_ca_bin.frequency: 120000 , + inst_ca_bin.frequency: @[inst_ca_bin_freq] , inst_ca_bin.duration: 010000 , inst_ca_bin.ref_time: 000000 , inst_ca_bin.nbits: 10, @@ -208,7 +208,7 @@ PC720x361-DC.LM: 72 inst_ni_bin.mode: 'instantaneous', inst_ni_bin.grid_label: PC720x361-DC , inst_ni_bin.splitField: 1, - inst_ni_bin.frequency: 120000 , + inst_ni_bin.frequency: @[inst_ni_bin_freq] , inst_ni_bin.duration: 010000 , inst_ni_bin.ref_time: 000000 , inst_ni_bin.nbits: 10, @@ -225,7 +225,7 @@ PC720x361-DC.LM: 72 inst_su_bin.mode: 'instantaneous', inst_su_bin.grid_label: PC720x361-DC , inst_su_bin.splitField: 1, - inst_su_bin.frequency: 120000 , + inst_su_bin.frequency: @[inst_su_bin_freq] , inst_su_bin.duration: 010000 , inst_su_bin.ref_time: 000000 , inst_su_bin.nbits: 10, @@ -244,7 +244,7 @@ PC720x361-DC.LM: 72 inst_2d.template: '%y4%m2%d2_%h2%n2z.nc4', inst_2d.archive: '%c/Y%y4', inst_2d.mode: 'instantaneous' - inst_2d.frequency: 030000, + inst_2d.frequency: @[inst_2d_freq], inst_2d.duration: 030000, inst_2d.ref_time: 000000, inst_2d.grid_label: PC720x361-DC @@ -343,7 +343,7 @@ PC720x361-DC.LM: 72 inst_3d.template: '%y4%m2%d2_%h2%n2z.nc4' , inst_3d.archive: '%c/Y%y4' , inst_3d.mode: 'instantaneous' - inst_3d.frequency: 060000, + inst_3d.frequency: @[inst_3d_freq], inst_3d.duration: 010000, inst_3d.ref_time: 000000, inst_3d.grid_label: PC720x361-DC @@ -381,7 +381,7 @@ PC720x361-DC.LM: 72 inst_aod.template: '%y4%m2%d2_%h2%n2z.nc4' , inst_aod.archive: '%c/Y%y4' , inst_aod.mode: 'instantaneous' - inst_aod.frequency: 060000, + inst_aod.frequency: @[inst_aod_freq], inst_aod.duration: 010000, inst_aod.ref_time: 000000, inst_aod.grid_label: PC720x361-DC @@ -398,7 +398,7 @@ PC720x361-DC.LM: 72 tavg_2d_rad.template: '%y4%m2%d2_%h2%n2z.nc4', tavg_2d_rad.archive: '%c/Y%y4', tavg_2d_rad.mode: 'time-averaged', - tavg_2d_rad.frequency: 120000, + tavg_2d_rad.frequency: @[tavg_2d_rad_freq], tavg_2d_rad.duration: 120000, tavg_2d_rad.ref_time: 000000, tavg_2d_rad.grid_label: PC720x361-DC @@ -432,7 +432,7 @@ PC720x361-DC.LM: 72 tavg_3d_rad.template: '%y4%m2%d2_%h2%n2z.nc4', tavg_3d_rad.archive: '%c/Y%y4', tavg_3d_rad.mode: 'time-averaged', - tavg_3d_rad.frequency: 120000, + tavg_3d_rad.frequency: @[tavg_3d_rad_freq], tavg_3d_rad.duration: 120000, tavg_3d_rad.ref_time: 000000, tavg_3d_rad.grid_label: PC720x361-DC diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index 25b2e28d754..310fcf0afa8 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -689,30 +689,15 @@ GOCART_rc() { [[ ${status} -ne 0 ]] && exit "${status}" fi - # copying GOCART configuration files - if [[ -n "${AERO_CONFIG_DIR}" ]]; then - ${NCP} "${AERO_CONFIG_DIR}"/*.rc "${DATA}" - status=$? - [[ ${status} -ne 0 ]] && exit "${status}" - # attempt to generate ExtData configuration file if not provided - if [[ ! -f "${DATA}/AERO_ExtData.rc" ]]; then - { \ - echo "PrimaryExports%%" ; \ - cat "${AERO_CONFIG_DIR}/ExtData.other" ; \ - cat "${AERO_CONFIG_DIR}/ExtData.${AERO_EMIS_FIRE:-none}" ; \ - echo "%%" ; \ - } > "${DATA}/AERO_ExtData.rc" - status=$? - if (( status != 0 )); then exit "${status}"; fi - fi - fi + source "${USHgfs}/parsing_namelists_GOCART.sh" + GOCART_namelists } GOCART_postdet() { echo "SUB ${FUNCNAME[0]}: Linking output data for GOCART" local vdate - for fhr in ${GOCART_OUTPUT_FH}; do + for fhr in $(GOCART_output_fh); do vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) # Temporarily delete existing files due to noclobber in GOCART @@ -726,6 +711,18 @@ GOCART_postdet() { done } +GOCART_output_fh() { + # This has to be called during postdet after FHROT has been set + local aero_min + local gocart_output_fh + # GOCART produces no AOD files at the initial forecast time, so start the time + # after the forecast start (accounting for FHROT) + aero_min=$(( ${IAU_FHROT:-0} > FHMIN ? IAU_FHROT + FHOUT_AERO : FHMIN + FHOUT_AERO )) + gocart_output_fh=$(seq -s ' ' "$(( aero_min ))" "${FHOUT_AERO}" "${GOCART_MAX}") + + echo "${gocart_output_fh}" +} + GOCART_out() { echo "SUB ${FUNCNAME[0]}: Copying output data for GOCART" @@ -733,8 +730,8 @@ GOCART_out() { # TODO: this should be linked but there are issues where gocart crashing if it is linked local fhr local vdate - for fhr in ${GOCART_OUTPUT_FH}; do - if (( fhr == 0 )); then continue; fi + + for fhr in $(GOCART_output_fh); do vdate=$(date --utc -d "${current_cycle:0:8} ${current_cycle:8:2} + ${fhr} hours" +%Y%m%d%H) ${NCP} "${DATA}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" \ "${COMOUT_CHEM_HISTORY}/gocart.inst_aod.${vdate:0:8}_${vdate:8:2}00z.nc4" diff --git a/ush/forecast_predet.sh b/ush/forecast_predet.sh index 43c9eb968f8..3c3dd719ef1 100755 --- a/ush/forecast_predet.sh +++ b/ush/forecast_predet.sh @@ -724,6 +724,8 @@ GOCART_predet(){ if [[ ! -d "${COMOUT_CHEM_HISTORY}" ]]; then mkdir -p "${COMOUT_CHEM_HISTORY}"; fi - GOCART_OUTPUT_FH=$(seq -s ' ' "${FHMIN}" "6" "${FHMAX}") - # TODO: AERO_HISTORY.rc has hardwired output frequency to 6 hours + # FHMAX gets modified when IAU is on, so keep origianl value for GOCART output + GOCART_MAX=${FHMAX} + + # GOCART output times can't be computed here because they may depend on FHROT } diff --git a/ush/parsing_namelists_GOCART.sh b/ush/parsing_namelists_GOCART.sh new file mode 100644 index 00000000000..e39f0808ab5 --- /dev/null +++ b/ush/parsing_namelists_GOCART.sh @@ -0,0 +1,52 @@ +#! /usr/bin/env bash + +# Disable variable not used warnings +# shellcheck disable=SC2034 +GOCART_namelists() { + # copying GOCART configuration files + if [[ -n "${AERO_CONFIG_DIR}" ]]; then + + local base_in + local fhout_aero_padded + fhout_aero_padded=$(printf "%02d" "${FHOUT_AERO}") + # Only instantaneous AOD is output right now + local inst_aod_freq="${fhout_aero_padded}0000" + + # Other gocart fields not currently used + local inst_du_ss_freq="120000" + local tavg_du_ss_freq="120000" + local inst_ca_freq="120000" + local inst_ni_freq="120000" + local inst_su_freq="120000" + local inst_du_bin_freq="010000" + local tavg_du_bin_freq="030000" + local inst_ss_bin_freq="060000" + local inst_ca_bin_freq="120000" + local inst_ni_bin_freq="120000" + local inst_su_bin_freq="120000" + local inst_2d_freq="030000" + local inst_3d_freq="060000" + local tavg_2d_rad_freq="120000" + local tavg_3d_rad_freq="120000" + + for template_in in "${AERO_CONFIG_DIR}/"*.rc; do + base_in="$(basename "${template_in}")" + atparse < "${template_in}" >> "${DATA}/${base_in}" + status=$? + [[ ${status} -ne 0 ]] && exit "${status}" + done + + # attempt to generate ExtData configuration file if not provided + if [[ ! -f "${DATA}/AERO_ExtData.rc" ]]; then + { \ + echo "PrimaryExports%%" ; \ + cat "${AERO_CONFIG_DIR}/ExtData.other" ; \ + cat "${AERO_CONFIG_DIR}/ExtData.${AERO_EMIS_FIRE:-none}" ; \ + echo "%%" ; \ + } > "${DATA}/AERO_ExtData.rc" + # shellcheck disable=SC2320 + status=$? + if (( status != 0 )); then exit "${status}"; fi + fi + fi +}