diff --git a/ci/cases/gfsv17/C384mx025_3DVarAOWCDA.yaml b/ci/cases/gfsv17/C384mx025_3DVarAOWCDA.yaml index 99ba7c3661..4147249a4c 100644 --- a/ci/cases/gfsv17/C384mx025_3DVarAOWCDA.yaml +++ b/ci/cases/gfsv17/C384mx025_3DVarAOWCDA.yaml @@ -9,10 +9,11 @@ arguments: resdetocean: 0.25 nens: 0 interval: 6 - start: cold + start: warm comroot: {{ 'RUNTESTS' | getenv }}/COMROOT expdir: {{ 'RUNTESTS' | getenv }}/EXPDIR - idate: 2021063000 + idate: 2021063018 edate: 2021070306 - icsdir: /scratch1/NCEPDEV/climate/Jessica.Meixner/cycling/IC_2021063000_V2 - yaml: {{ HOMEgfs }}/ci/cases/gfsv17/ocnanal.yaml + #icsdir: /scratch1/NCEPDEV/climate/Jessica.Meixner/cycling/IC_2021063000_V2 + icsdir: /work/noaa/da/gvernier/ensda/ictest/1440x1080x75/ + yaml: {{ HOMEgfs }}/ci/cases/gfsv17/marine3dvar.yaml diff --git a/ci/cases/gfsv17/C384mx025_hybAOWCDA.yaml b/ci/cases/gfsv17/C384mx025_hybAOWCDA.yaml new file mode 100644 index 0000000000..f0e0b42c28 --- /dev/null +++ b/ci/cases/gfsv17/C384mx025_hybAOWCDA.yaml @@ -0,0 +1,19 @@ +experiment: + system: gfs + mode: cycled + +arguments: + pslot: {{ 'pslot' | getenv }} + app: S2S + resdetatmos: 384 + resensatmos: 192 + resdetocean: 0.25 + nens: 30 + interval: 0 + start: warm + comroot: {{ 'RUNTESTS' | getenv }}/COMROOT + expdir: {{ 'RUNTESTS' | getenv }}/EXPDIR + idate: 2021063018 + edate: 2021070306 + icsdir: /work/noaa/da/gvernier/ensda/ictest/1440x1080x75/ + yaml: {{ HOMEgfs }}/ci/cases/gfsv17/marinehyb.yaml diff --git a/ci/cases/gfsv17/ocnanal.yaml b/ci/cases/gfsv17/marine3dvar.yaml similarity index 72% rename from ci/cases/gfsv17/ocnanal.yaml rename to ci/cases/gfsv17/marine3dvar.yaml index b0605c9c16..abf86f0aa8 100644 --- a/ci/cases/gfsv17/ocnanal.yaml +++ b/ci/cases/gfsv17/marine3dvar.yaml @@ -21,8 +21,3 @@ marineanl: SOCA_INPUT_FIX_DIR: {{ HOMEgfs }}/fix/gdas/soca/1440x1080x75/soca SOCA_OBS_LIST: {{ HOMEgfs }}/sorc/gdas.cd/parm/soca/obs/obs_list.yaml SOCA_NINNER: 100 - -prepoceanobs: - SOCA_OBS_LIST: {{ HOMEgfs }}/sorc/gdas.cd/parm/soca/obs/obs_list.yaml - OBSPREP_YAML: {{ HOMEgfs }}/sorc/gdas.cd/parm/soca/obsprep/obsprep_config.yaml - DMPDIR: /scratch1/NCEPDEV/da/common/ diff --git a/ci/cases/gfsv17/marinehyb.yaml b/ci/cases/gfsv17/marinehyb.yaml new file mode 100644 index 0000000000..ed62e607a8 --- /dev/null +++ b/ci/cases/gfsv17/marinehyb.yaml @@ -0,0 +1,21 @@ +defaults: + !INC {{ HOMEgfs }}/parm/config/gfs/yaml/defaults.yaml + +base: + DOIAU: "YES" + DO_JEDIATMVAR: "NO" + DO_JEDIATMENS: "NO" + DO_JEDIOCNVAR: "YES" + DO_JEDISNOWDA: "NO" + DO_MERGENSST: "NO" + DOHYBVAR_OCN: "YES" + DO_FIT2OBS: "YES" + DO_VERFOZN: "YES" + DO_VERFRAD: "YES" + DO_VRFY_OCEANDA: "NO" + FHMAX_GFS: 240 + ACCOUNT: {{ 'HPC_ACCOUNT' | getenv }} + +marineanl: + SOCA_INPUT_FIX_DIR: {{ HOMEgfs }}/fix/gdas/soca/1440x1080x75/soca + SOCA_NINNER: 20 # revert to ~100 after the memory leak is fixed diff --git a/ci/cases/pr/C48mx500_3DVarAOWCDA.yaml b/ci/cases/pr/C48mx500_3DVarAOWCDA.yaml index 762d2c3fbe..9cc3d3c03a 100644 --- a/ci/cases/pr/C48mx500_3DVarAOWCDA.yaml +++ b/ci/cases/pr/C48mx500_3DVarAOWCDA.yaml @@ -10,8 +10,8 @@ arguments: comroot: {{ 'RUNTESTS' | getenv }}/COMROOT expdir: {{ 'RUNTESTS' | getenv }}/EXPDIR icsdir: {{ 'ICSDIR_ROOT' | getenv }}/C48mx500/20241120 - idate: 2021032412 - edate: 2021032418 + idate: 2021032418 + edate: 2021032500 nens: 0 interval: 0 start: warm @@ -21,4 +21,3 @@ skip_ci_on_hosts: - wcoss2 - gaea - orion - - hercules diff --git a/ci/cases/pr/C48mx500_hybAOWCDA.yaml b/ci/cases/pr/C48mx500_hybAOWCDA.yaml index ca477b5fba..d0fe13a689 100644 --- a/ci/cases/pr/C48mx500_hybAOWCDA.yaml +++ b/ci/cases/pr/C48mx500_hybAOWCDA.yaml @@ -6,21 +6,19 @@ arguments: pslot: {{ 'pslot' | getenv }} app: S2S resdetatmos: 48 - resdetocean: 5.0 resensatmos: 48 + resdetocean: 5.0 comroot: {{ 'RUNTESTS' | getenv }}/COMROOT expdir: {{ 'RUNTESTS' | getenv }}/EXPDIR icsdir: {{ 'ICSDIR_ROOT' | getenv }}/C48mx500/20241120 - idate: 2021032412 - edate: 2021032418 - nens: 3 + idate: 2021032418 + edate: 2021032500 + nens: 2 interval: 0 start: warm - yaml: {{ HOMEgfs }}/ci/cases/yamls/soca_gfs_defaults_ci.yaml + yaml: {{ HOMEgfs }}/ci/cases/yamls/soca_hyb_gfs_defaults_ci.yaml skip_ci_on_hosts: - wcoss2 - - orion - - hercules - - hera - gaea + - orion diff --git a/ci/cases/yamls/soca_gfs_defaults_ci.yaml b/ci/cases/yamls/soca_gfs_defaults_ci.yaml index 38d55e3574..c18eac9196 100644 --- a/ci/cases/yamls/soca_gfs_defaults_ci.yaml +++ b/ci/cases/yamls/soca_gfs_defaults_ci.yaml @@ -3,4 +3,7 @@ defaults: base: ACCOUNT: {{ 'HPC_ACCOUNT' | getenv }} DO_JEDIOCNVAR: "YES" + +marineanl: + SOCA_NINNER: 1 DO_TEST_MODE: "YES" diff --git a/ci/cases/yamls/soca_hyb_gfs_defaults_ci.yaml b/ci/cases/yamls/soca_hyb_gfs_defaults_ci.yaml new file mode 100644 index 0000000000..bad760aca0 --- /dev/null +++ b/ci/cases/yamls/soca_hyb_gfs_defaults_ci.yaml @@ -0,0 +1,8 @@ +defaults: + !INC {{ HOMEgfs }}/parm/config/gfs/yaml/defaults.yaml +base: + ACCOUNT: {{ 'HPC_ACCOUNT' | getenv }} + DO_JEDIOCNVAR: "YES" + DOHYBVAR_OCN: "YES" +marineanl: + SOCA_NINNER: 1 diff --git a/env/HERCULES.env b/env/HERCULES.env index fccc2f87a5..3a59b1992d 100755 --- a/env/HERCULES.env +++ b/env/HERCULES.env @@ -138,14 +138,9 @@ case ${step} in ;; "ocnanalecen") - export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}" - - max_threads_per_task=$((max_tasks_per_node / tasks_per_node_ocnanalecen)) + export APRUN_OCNANALECEN="${APRUN_default}" +;; - export NTHREADS_OCNANALECEN=${threads_per_task_ocnanalecen:-${max_threads_per_task}} - [[ ${NTHREADS_OCNANALECEN} -gt ${max_threads_per_task} ]] && export NTHREADS_OCNANALECEN=${max_threads_per_task} - export APRUN_OCNANALECEN="${launcher} -n ${ntasks_ocnanalecen} --cpus-per-task=${NTHREADS_OCNANALECEN}" - ;; "marineanlchkpt") export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}" diff --git a/env/WCOSS2.env b/env/WCOSS2.env index 27001bebd7..4e8d1ddfea 100755 --- a/env/WCOSS2.env +++ b/env/WCOSS2.env @@ -115,6 +115,7 @@ elif [[ "${step}" = "marineanlvar" ]]; then elif [[ "${step}" = "marineanlchkpt" ]]; then export APRUNCFP="${launcher} -n \$ncmd --multi-prog" + export APRUN_MARINEANLCHKPT="${APRUN_default}" elif [[ "${step}" = "ocnanalecen" ]]; then @@ -126,7 +127,7 @@ elif [[ "${step}" = "marineanlletkf" ]]; then export NTHREADS_MARINEANLLETKF=${NTHREADSmax} export APRUN_MARINEANLLETKF="${APRUN_default}" - + elif [[ "${step}" = "atmanlfv3inc" ]]; then export NTHREADS_ATMANLFV3INC=${NTHREADSmax} diff --git a/jobs/JGDAS_GLOBAL_OCEAN_ANALYSIS_ECEN b/jobs/JGDAS_GLOBAL_OCEAN_ANALYSIS_ECEN index 7b8bb84809..098ad0d06c 100755 --- a/jobs/JGDAS_GLOBAL_OCEAN_ANALYSIS_ECEN +++ b/jobs/JGDAS_GLOBAL_OCEAN_ANALYSIS_ECEN @@ -1,6 +1,6 @@ #!/bin/bash source "${HOMEgfs}/ush/preamble.sh" -source "${HOMEgfs}/ush/jjob_header.sh" -e "ocnanalecen" -c "base ocnanal ocnanalecen" +source "${HOMEgfs}/ush/jjob_header.sh" -e "ocnanalecen" -c "base marineanl ocnanalecen" ############################################## # Set variables used in the script @@ -12,8 +12,13 @@ export gPDY=${GDATE:0:8} export gcyc=${GDATE:8:2} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ - COM_OCEAN_HISTORY_PREV:COM_OCEAN_HISTORY_TMPL \ - COM_ICE_HISTORY_PREV:COM_ICE_HISTORY_TMPL + COMIN_OCEAN_HISTORY_PREV:COM_OCEAN_HISTORY_TMPL \ + COMIN_ICE_HISTORY_PREV:COM_ICE_HISTORY_TMPL + +YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ + COMOUT_OCEAN_ANALYSIS:COM_OCEAN_ANALYSIS_TMPL \ + COMIN_ICE_RESTART:COM_ICE_RESTART_TMPL \ + COMOUT_ICE_ANALYSIS:COM_ICE_ANALYSIS_TMPL ############################################## # Begin JOB SPECIFIC work diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT b/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT index 8cd7b1ab7c..7537937f82 100755 --- a/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT @@ -2,6 +2,7 @@ source "${HOMEgfs}/ush/preamble.sh" export WIPE_DATA="NO" export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAens="${DATAjob}/ensdata" export DATA="${DATAjob}/marinevariational" source "${HOMEgfs}/ush/jjob_header.sh" -e "marineanlchkpt" -c "base marineanl marineanlchkpt" diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE b/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE index 2614639184..cdc6dfecc8 100755 --- a/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE @@ -2,6 +2,7 @@ source "${HOMEgfs}/ush/preamble.sh" export WIPE_DATA="NO" export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAens="${DATAjob}/ensdata" export DATA="${DATAjob}/marinevariational" source "${HOMEgfs}/ush/jjob_header.sh" -e "marineanlfinal" -c "base marineanl marineanlfinal" diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE b/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE index eb167af94d..14f5490a70 100755 --- a/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE @@ -2,6 +2,7 @@ source "${HOMEgfs}/ush/preamble.sh" export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAens="${DATAjob}/ensdata" export DATA="${DATAjob}/marinevariational" source "${HOMEgfs}/ush/jjob_header.sh" -e "marineanlinit" -c "base marineanl marineanlinit" diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL b/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL index 7780353294..1bc476bffc 100755 --- a/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL @@ -3,6 +3,7 @@ source "${HOMEgfs}/ush/preamble.sh" export WIPE_DATA="NO" export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAens="${DATAjob}/ensdata" export DATA="${DATAjob}/marinevariational" source "${HOMEgfs}/ush/jjob_header.sh" -e "marineanlvar" -c "base marineanl marineanlvar" diff --git a/parm/archive/gdas.yaml.j2 b/parm/archive/gdas.yaml.j2 index fa8919a589..140631feb5 100644 --- a/parm/archive/gdas.yaml.j2 +++ b/parm/archive/gdas.yaml.j2 @@ -26,7 +26,7 @@ gdas: - "logs/{{ cycle_YMDH }}/{{ RUN }}_marineanlvar.log" - "logs/{{ cycle_YMDH }}/{{ RUN }}_marineanlfinal.log" - "logs/{{ cycle_YMDH }}/{{ RUN }}_marineanlchkpt.log" - {% if DOHYBVAR %} + {% if DOHYBVAR_OCN %} - "logs/{{ cycle_YMDH }}/{{ RUN }}_ocnanalecen.log" {% endif %} {% endif %} diff --git a/parm/config/gfs/config.base b/parm/config/gfs/config.base index 46e27b4541..ffd6db86db 100644 --- a/parm/config/gfs/config.base +++ b/parm/config/gfs/config.base @@ -368,9 +368,11 @@ export DO_JEDIATMENS="@DO_JEDIATMENS@" export DO_JEDIOCNVAR="@DO_JEDIOCNVAR@" export DO_JEDISNOWDA="@DO_JEDISNOWDA@" export DO_MERGENSST="@DO_MERGENSST@" +export DO_STARTMEM_FROM_JEDIICE="@DO_STARTMEM_FROM_JEDIICE@" # Hybrid related export DOHYBVAR="@DOHYBVAR@" +export DOHYBVAR_OCN="@DOHYBVAR_OCN@" export NMEM_ENS=@NMEM_ENS@ export SMOOTH_ENKF="NO" export l4densvar=".true." @@ -482,7 +484,7 @@ export ARCH_FCSTICFREQ=1 # Archive frequency in days for gdas and gfs foreca # The monitor jobs are not yet supported for JEDIATMVAR. if [[ ${DO_JEDIATMVAR} = "YES" ]]; then - export DO_FIT2OBS="NO" # Run fit to observations package + export DO_FIT2OBS="NO" # Run fit to observations package export DO_VERFOZN="NO" # Ozone data assimilation monitoring export DO_VERFRAD="NO" # Radiance data assimilation monitoring export DO_VMINMON="NO" # GSI minimization monitoring diff --git a/parm/config/gfs/yaml/defaults.yaml b/parm/config/gfs/yaml/defaults.yaml index 05dfc90332..c9ecd11f5b 100644 --- a/parm/config/gfs/yaml/defaults.yaml +++ b/parm/config/gfs/yaml/defaults.yaml @@ -5,6 +5,7 @@ base: DO_JEDIOCNVAR: "NO" DO_JEDISNOWDA: "NO" DO_MERGENSST: "NO" + DO_STARTMEM_FROM_JEDIICE: "NO" DO_GOES: "NO" DO_BUFRSND: "NO" DO_GEMPAK: "NO" @@ -21,6 +22,7 @@ base: GSI_SOILANAL: "NO" EUPD_CYC: "gdas" FHMAX_ENKF_GFS: 12 + DOHYBVAR_OCN: "NO" DO_TEST_MODE: "NO" atmanl: @@ -39,7 +41,7 @@ atmensanl: LAYOUT_Y_ATMENSANL: 8 IO_LAYOUT_X: 1 IO_LAYOUT_Y: 1 - + aeroanl: IO_LAYOUT_X: 1 IO_LAYOUT_Y: 1 diff --git a/parm/stage/ice.yaml.j2 b/parm/stage/ice.yaml.j2 index 0e0aa40c7f..241f45a35b 100644 --- a/parm/stage/ice.yaml.j2 +++ b/parm/stage/ice.yaml.j2 @@ -1,5 +1,12 @@ +{% set START_ICE_FROM_ANA = False %} +{% if DO_JEDIOCNVAR == True and RUN == 'gdas' %} + {% set START_ICE_FROM_ANA = True %} +{% endif %} +{% if DO_STARTMEM_FROM_JEDIICE == False and RUN == 'enkfgdas' %} + {% set START_ICE_FROM_ANA = False %} +{% endif %} ice: - {% if DO_JEDIOCNVAR == True %} + {% if START_ICE_FROM_ANA == True %} mkdir: {% for mem in range(first_mem, last_mem + 1) %} {% set imem = mem - first_mem %} diff --git a/scripts/exglobal_stage_ic.py b/scripts/exglobal_stage_ic.py index 1a49c4f64d..0a5bc97344 100755 --- a/scripts/exglobal_stage_ic.py +++ b/scripts/exglobal_stage_ic.py @@ -21,7 +21,7 @@ def main(): keys = ['RUN', 'MODE', 'EXP_WARM_START', 'NMEM_ENS', 'assim_freq', 'current_cycle', 'previous_cycle', 'ROTDIR', 'ICSDIR', 'STAGE_IC_YAML_TMPL', 'DO_JEDIATMVAR', - 'OCNRES', 'waveGRD', 'ntiles', 'DOIAU', 'DO_JEDIOCNVAR', + 'OCNRES', 'waveGRD', 'ntiles', 'DOIAU', 'DO_JEDIOCNVAR', 'DO_STARTMEM_FROM_JEDIICE', 'REPLAY_ICS', 'DO_WAVE', 'DO_OCN', 'DO_ICE', 'DO_NEST', 'USE_ATM_ENS_PERTURB_FILES', 'USE_OCN_ENS_PERTURB_FILES'] diff --git a/sorc/gdas.cd b/sorc/gdas.cd index 9ab7994a0c..d91663bb58 160000 --- a/sorc/gdas.cd +++ b/sorc/gdas.cd @@ -1 +1 @@ -Subproject commit 9ab7994a0caf6b201613dd7e7ceae482ffa600e0 +Subproject commit d91663bb585fbfa30db99d6126a1d4f24906b69b diff --git a/ush/forecast_postdet.sh b/ush/forecast_postdet.sh index aade469ddc..3deac59e37 100755 --- a/ush/forecast_postdet.sh +++ b/ush/forecast_postdet.sh @@ -460,13 +460,10 @@ MOM6_postdet() { fi # GEFS perturbations - if [[ "${RUN}" == "gefs" ]]; then - # to ensure it does not interfere with the GFS - if (( MEMBER > 0 )) && [[ "${ODA_INCUPD:-False}" == "True" ]]; then - ${NCP} "${COMIN_OCEAN_ANALYSIS}/${RUN}.t${cyc}z.ocninc.nc" "${DATA}/INPUT/mom6_increment.nc" \ - || ( echo "FATAL ERROR: Unable to copy ensemble MOM6 increment, ABORT!"; exit 1 ) - fi - fi # if [[ "${RUN}" == "gefs" ]]; then + if (( MEMBER > 0 )) && [[ "${ODA_INCUPD:-False}" == "True" ]]; then + ${NCP} "${COMIN_OCEAN_ANALYSIS}/${RUN}.t${cyc}z.ocninc.nc" "${DATA}/INPUT/mom6_increment.nc" \ + || ( echo "FATAL ERROR: Unable to copy ensemble MOM6 increment, ABORT!"; exit 1 ) + fi fi # if [[ "${RERUN}" == "NO" ]]; then # Link output files @@ -587,7 +584,13 @@ CICE_postdet() { restart_date="${model_start_date_current_cycle}" cice_restart_file="${COMIN_ICE_RESTART_PREV}/${restart_date:0:8}.${restart_date:8:2}0000.cice_model.res.nc" if [[ "${DO_JEDIOCNVAR:-NO}" == "YES" ]]; then - cice_restart_file="${COMIN_ICE_ANALYSIS}/${restart_date:0:8}.${restart_date:8:2}0000.cice_model_anl.res.nc" + if (( MEMBER == 0 )); then + # Start the deterministic from the JEDI/SOCA analysis if the Marine DA in ON + cice_restart_file="${COMIN_ICE_ANALYSIS}/${restart_date:0:8}.${restart_date:8:2}0000.cice_model_anl.res.nc" + elif (( MEMBER > 0 )) && [[ "${DO_STARTMEM_FROM_JEDIICE:-NO}" == "YES" ]]; then + # Ignore the JEDI/SOCA ensemble analysis for the ensemble members if DO_START_FROM_JEDIICE is OFF + cice_restart_file="${COMIN_ICE_ANALYSIS}/${restart_date:0:8}.${restart_date:8:2}0000.cice_model_anl.res.nc" + fi fi fi diff --git a/ush/python/pygfs/task/marine_analysis.py b/ush/python/pygfs/task/marine_analysis.py index 4f8fa760c0..ebb1502634 100644 --- a/ush/python/pygfs/task/marine_analysis.py +++ b/ush/python/pygfs/task/marine_analysis.py @@ -51,9 +51,9 @@ def __init__(self, config): _window_begin = add_to_datetime(self.task_config.current_cycle, -to_timedelta(f"{self.task_config.assim_freq}H") / 2) _window_end = add_to_datetime(self.task_config.current_cycle, to_timedelta(f"{self.task_config.assim_freq}H") / 2) - # compute the relative path from self.task_config.DATA to self.task_config.DATAenspert + # compute the relative path from self.task_config.DATA to self.task_config.DATAens if self.task_config.NMEM_ENS > 0: - _enspert_relpath = os.path.relpath(self.task_config.DATAenspert, self.task_config.DATA) + _enspert_relpath = os.path.relpath(self.task_config.DATAens, self.task_config.DATA) else: _enspert_relpath = None @@ -69,7 +69,8 @@ def __init__(self, config): 'MARINE_WINDOW_MIDDLE_ISO': self.task_config.current_cycle.strftime('%Y-%m-%dT%H:%M:%SZ'), 'ENSPERT_RELPATH': _enspert_relpath, 'CALC_SCALE_EXEC': _calc_scale_exec, - 'OPREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z." + 'OPREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z.", + 'APREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z." } ) @@ -110,10 +111,13 @@ def initialize(self: Task) -> None: os.symlink('../staticb', 'staticb') # hybrid EnVAR case - if self.task_config.DOHYBVAR == "YES" or self.task_config.NMEM_ENS > 2: - # stage ensemble membersfiles for use in hybrid background error - logger.debug(f"Stage ensemble members for the hybrid background error") - mdau.stage_ens_mem(self.task_config) + if self.task_config.DOHYBVAR_OCN == "YES" or self.task_config.NMEM_ENS >= 2: + # stage the ensemble weights + logger.debug(f"Stage ensemble weights for the hybrid background error") + FileHandler({'copy': [[os.path.join(self.task_config.COMIN_OCEAN_BMATRIX, f'{self.task_config.APREFIX}ocean.ens_weights.nc'), + os.path.join(self.task_config.DATA, 'ocean.ens_weights.nc')], + [os.path.join(self.task_config.COMIN_ICE_BMATRIX, f'{self.task_config.APREFIX}ice.ens_weights.nc'), + os.path.join(self.task_config.DATA, 'ice.ens_weights.nc')]]}).sync() # prepare the yaml configuration to run the SOCA variational application self._prep_variational_yaml() @@ -137,8 +141,8 @@ def _fetch_observations(self: Task) -> None: obs_files = [] for ob in obs_list_config['observations']['observers']: - logger.info(f"******** {self.task_config.OPREFIX}{ob['obs space']['name'].lower()}.{to_YMD(self.task_config.PDY)}{self.task_config.cyc}.nc4") - obs_files.append(f"{self.task_config.OPREFIX}{ob['obs space']['name'].lower()}.{to_YMD(self.task_config.PDY)}{self.task_config.cyc}.nc4") + logger.info(f"******** {self.task_config.OPREFIX}{ob['obs space']['name'].lower()}.{to_YMD(self.task_config.PDY)}{self.task_config.cyc:02d}.nc4") + obs_files.append(f"{self.task_config.OPREFIX}{ob['obs space']['name'].lower()}.{to_YMD(self.task_config.PDY)}{self.task_config.cyc:02d}.nc4") obs_list = [] # copy obs from COM_OBS to DATA/obs @@ -202,7 +206,7 @@ def _prep_variational_yaml(self: Task) -> None: envconfig_jcb['PARMgfs'] = self.task_config.PARMgfs envconfig_jcb['NMEM_ENS'] = self.task_config.NMEM_ENS envconfig_jcb['berror_model'] = 'marine_background_error_static_diffusion' - if self.task_config.NMEM_ENS > 3: + if self.task_config.NMEM_ENS >= 3: envconfig_jcb['berror_model'] = 'marine_background_error_hybrid_diffusion_diffusion' envconfig_jcb['DATA'] = self.task_config.DATA envconfig_jcb['OPREFIX'] = self.task_config.OPREFIX @@ -210,7 +214,7 @@ def _prep_variational_yaml(self: Task) -> None: envconfig_jcb['cyc'] = os.getenv('cyc') envconfig_jcb['SOCA_NINNER'] = self.task_config.SOCA_NINNER envconfig_jcb['obs_list'] = ['adt_rads_all'] - envconfig_jcb['MOM6_LEVS'] = mdau.get_mom6_levels(str(self.task_config.OCNRES)) + envconfig_jcb['MOM6_LEVS'] = mdau.get_mom6_levels(str(self.task_config.OCNRES).zfill(3)) # Write obs_list_short save_as_yaml(parse_obs_list_file(self.task_config.MARINE_OBS_LIST_YAML), 'obs_list_short.yaml') @@ -220,12 +224,8 @@ def _prep_variational_yaml(self: Task) -> None: jcb_base_yaml = os.path.join(self.task_config.PARMsoca, 'marine-jcb-base.yaml') jcb_algo_yaml = os.path.join(self.task_config.PARMsoca, 'marine-jcb-3dfgat.yaml.j2') - jcb_base_config = YAMLFile(path=jcb_base_yaml) - jcb_base_config = Template.substitute_structure(jcb_base_config, TemplateConstants.DOUBLE_CURLY_BRACES, envconfig_jcb.get) - jcb_base_config = Template.substitute_structure(jcb_base_config, TemplateConstants.DOLLAR_PARENTHESES, envconfig_jcb.get) - jcb_algo_config = YAMLFile(path=jcb_algo_yaml) - jcb_algo_config = Template.substitute_structure(jcb_algo_config, TemplateConstants.DOUBLE_CURLY_BRACES, envconfig_jcb.get) - jcb_algo_config = Template.substitute_structure(jcb_algo_config, TemplateConstants.DOLLAR_PARENTHESES, envconfig_jcb.get) + jcb_base_config = parse_j2yaml(path=jcb_base_yaml, data=envconfig_jcb) + jcb_algo_config = parse_j2yaml(path=jcb_algo_yaml, data=envconfig_jcb) # Override base with the application specific config jcb_config = {**jcb_base_config, **jcb_algo_config} @@ -385,12 +385,10 @@ def list_all_files(dir_in, dir_out, wc='*', fh_list=[]): os.path.join(com_ocean_analysis, f'{RUN}.t{cyc}z.{domain}ana.nc')]) # Copy of the ssh diagnostics - ''' if nmem_ens > 2: for string in ['ssh_steric_stddev', 'ssh_unbal_stddev', 'ssh_total_stddev', 'steric_explained_variance']: - post_file_list.append([os.path.join(anl_dir, 'static_ens', f'ocn.{string}.incr.{bdate}.nc'), + post_file_list.append([os.path.join(anl_dir, 'staticb', f'ocn.{string}.incr.{bdate}.nc'), os.path.join(com_ocean_analysis, f'{RUN}.t{cyc}z.ocn.{string}.nc')]) - ''' # Copy DA grid (computed for the start of the window) post_file_list.append([os.path.join(anl_dir, 'soca_gridspec.nc'), @@ -460,7 +458,7 @@ def create_obs_space(data): # get the variable name, assume 1 variable per file nc = netCDF4.Dataset(obsfile, 'r') - variable = next(iter(nc.groups["ObsValue"].variables)) + variable = next(iter(nc.groups["ombg"].variables)) nc.close() # filling values for the templated yaml diff --git a/ush/python/pygfs/task/marine_bmat.py b/ush/python/pygfs/task/marine_bmat.py index a21699227b..8e2b84a673 100644 --- a/ush/python/pygfs/task/marine_bmat.py +++ b/ush/python/pygfs/task/marine_bmat.py @@ -63,9 +63,9 @@ def __init__(self, config): 'MARINE_WINDOW_END': _window_end, 'MARINE_WINDOW_LENGTH': f"PT{self.task_config['assim_freq']}H", 'ENSPERT_RELPATH': _enspert_relpath, - 'MOM6_LEVS': mdau.get_mom6_levels(str(self.task_config.OCNRES)), + 'CALC_SCALE_EXEC': _calc_scale_exec, 'APREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z.", - 'OPREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z." + 'MOM6_LEVS': mdau.get_mom6_levels(str(self.task_config.OCNRES)) } ) @@ -130,12 +130,12 @@ def initialize(self: Task) -> None: self.jedi_dict['soca_parameters_diffusion_vt'].initialize(self.task_config) self.jedi_dict['soca_setcorscales'].initialize(self.task_config) self.jedi_dict['soca_parameters_diffusion_hz'].initialize(self.task_config) - if self.task_config.DOHYBVAR == "YES" or self.task_config.NMEM_ENS > 2: + if self.task_config.DOHYBVAR_OCN == "YES" or self.task_config.NMEM_ENS >= 2: self.jedi_dict['soca_ensb'].initialize(self.task_config) self.jedi_dict['soca_ensweights'].initialize(self.task_config) # stage ensemble members for the hybrid background error - if self.task_config.DOHYBVAR == "YES" or self.task_config.NMEM_ENS > 2: + if self.task_config.DOHYBVAR_OCN == "YES" or self.task_config.NMEM_ENS >= 2: logger.debug(f"Stage ensemble members for the hybrid background error") mdau.stage_ens_mem(self.task_config) @@ -182,7 +182,7 @@ def execute(self) -> None: self.jedi_dict['soca_parameters_diffusion_vt'].execute() # hybrid EnVAR case - if self.task_config.DOHYBVAR == "YES" or self.task_config.NMEM_ENS > 2: + if self.task_config.DOHYBVAR_OCN == "YES" or self.task_config.NMEM_ENS >= 2: self.jedi_dict['soca_ensb'].execute() self.jedi_dict['soca_ensweights'].execute() @@ -221,11 +221,6 @@ def finalize(self: Task) -> None: f"{self.task_config.APREFIX}{diff_type}_ocean.nc") diffusion_coeff_list.append([src, dest]) - src = os.path.join(self.task_config.DATAstaticb, f"hz_ice.nc") - dest = os.path.join(self.task_config.COMOUT_ICE_BMATRIX, - f"{self.task_config.APREFIX}hz_ice.nc") - diffusion_coeff_list.append([src, dest]) - FileHandler({'copy': diffusion_coeff_list}).sync() # Copy diag B files to ROTDIR @@ -252,7 +247,7 @@ def finalize(self: Task) -> None: FileHandler({'copy': diagb_list}).sync() # Copy the ensemble perturbation diagnostics to the ROTDIR - if self.task_config.DOHYBVAR == "YES" or self.task_config.NMEM_ENS > 2: + if self.task_config.DOHYBVAR_OCN == "YES" or self.task_config.NMEM_ENS >= 2: window_middle_iso = self.task_config.MARINE_WINDOW_MIDDLE.strftime('%Y-%m-%dT%H:%M:%SZ') weight_list = [] src = os.path.join(self.task_config.DATA, f"ocn.ens_weights.incr.{window_middle_iso}.nc") diff --git a/ush/python/pygfs/task/marine_letkf.py b/ush/python/pygfs/task/marine_letkf.py index 54d40f8d66..98c4f29085 100644 --- a/ush/python/pygfs/task/marine_letkf.py +++ b/ush/python/pygfs/task/marine_letkf.py @@ -112,7 +112,7 @@ def initialize(self): # TODO(AFE) - this should be removed when the obs config yamls are jinjafied if 'distribution' not in ob['obs space']: ob['obs space']['distribution'] = {'name': 'Halo', 'halo size': self.task_config['DIST_HALO_SIZE']} - obs_filename = f"{self.task_config.RUN}.t{self.task_config.cyc}z.{obs_name}.{to_YMDH(self.task_config.current_cycle)}.nc4" + obs_filename = f"{self.task_config.OPREFIX}{obs_name}.{to_YMDH(self.task_config.current_cycle)}.nc4" obs_files.append((obs_filename, ob)) obs_files_to_copy = [] diff --git a/workflow/applications/gfs_cycled.py b/workflow/applications/gfs_cycled.py index 2d16b6a59c..e11f708aa6 100644 --- a/workflow/applications/gfs_cycled.py +++ b/workflow/applications/gfs_cycled.py @@ -37,6 +37,7 @@ def _get_run_options(self, conf: Configuration) -> Dict[str, Any]: base = conf.parse_config('config.base', RUN=run) run_options[run]['do_hybvar'] = base.get('DOHYBVAR', False) + run_options[run]['do_hybvar_ocn'] = base.get('DOHYBVAR_OCN', False) run_options[run]['nens'] = base.get('NMEM_ENS', 0) if run_options[run]['do_hybvar']: run_options[run]['lobsdiag_forenkf'] = base.get('lobsdiag_forenkf', False) diff --git a/workflow/rocoto/gfs_tasks.py b/workflow/rocoto/gfs_tasks.py index 535f5ce844..244c6b6a15 100644 --- a/workflow/rocoto/gfs_tasks.py +++ b/workflow/rocoto/gfs_tasks.py @@ -672,7 +672,11 @@ def marinebmat(self): data = f'{ocean_hist_path}/gdas.ocean.t@Hz.inst.f009.nc' dep_dict = {'type': 'data', 'data': data, 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} deps.append(rocoto.add_dependency(dep_dict)) - dependencies = rocoto.create_dependency(dep=deps) + if self.options['do_hybvar_ocn']: + dep_dict = {'type': 'metatask', 'name': 'enkfgdas_fcst', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) + dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) resources = self.get_resource('marinebmat') task_name = f'{self.run}_marinebmat' @@ -770,7 +774,7 @@ def ocnanalecen(self): def marineanlchkpt(self): deps = [] - if self.options['do_hybvar']: + if self.options['do_hybvar_ocn']: dep_dict = {'type': 'task', 'name': f'{self.run}_ocnanalecen'} else: dep_dict = {'type': 'task', 'name': f'{self.run}_marineanlvar'} @@ -2756,6 +2760,9 @@ def efcs(self): deps.append(rocoto.add_dependency(dep_dict)) dep_dict = {'type': 'task', 'name': f'{self.run}_esfc'} deps.append(rocoto.add_dependency(dep_dict)) + if self.options['do_hybvar_ocn']: + dep_dict = {'type': 'task', 'name': f'{self.run.replace("enkf", "")}_ocnanalecen'} + deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) dep_dict = {'type': 'task', 'name': f'{self.run}_stage_ic'} dependencies.append(rocoto.add_dependency(dep_dict))