diff --git a/.gitignore b/.gitignore index c5695330b06..f8d1fc6f340 100644 --- a/.gitignore +++ b/.gitignore @@ -143,7 +143,6 @@ sorc/ocnicepost.fd #------------------------------ # jobs symlinks # scripts symlinks -scripts/exgdas_global_marine_analysis_ecen.py scripts/exglobal_prep_ocean_obs.py # ush symlinks ush/bufr2ioda_insitu_profile_argo.py diff --git a/dev/jobs/ocnanalecen.sh b/dev/jobs/marineanlecen.sh similarity index 88% rename from dev/jobs/ocnanalecen.sh rename to dev/jobs/marineanlecen.sh index e25dd6e2741..506b67b9231 100755 --- a/dev/jobs/ocnanalecen.sh +++ b/dev/jobs/marineanlecen.sh @@ -10,7 +10,7 @@ if [[ ${status} -ne 0 ]]; then exit "${status}" fi -export job="ocnanalecen" +export job="marineanlecen" export jobid="${job}.$$" ############################################################### @@ -20,6 +20,6 @@ export PYTHONPATH ############################################################### # Execute the JJOB -"${HOMEgfs}"/jobs/JGDAS_GLOBAL_OCEAN_ANALYSIS_ECEN +"${HOMEgfs}"/jobs/JGLOBAL_MARINE_ANALYSIS_ECEN status=$? exit "${status}" diff --git a/dev/parm/config/gcafs/config.resources b/dev/parm/config/gcafs/config.resources index 674447c3986..1d32c979a4e 100644 --- a/dev/parm/config/gcafs/config.resources +++ b/dev/parm/config/gcafs/config.resources @@ -28,7 +28,7 @@ if (( $# != 1 )); then echo "waveinit waveprep wavepostsbs wavepostbndpnt wavepostbndpntbll wavepostpnt" echo "wavegempak waveawipsbulls waveawipsgridded" echo "postsnd awips gempak npoess" - echo "marineanlinit prepoceanobs marinebmat marineanlvar ocnanalecen marineanalletkf marineanlchkpt marineanlfinal ocnanalvrfy" + echo "marineanlinit prepoceanobs marinebmat marineanlvar marineanlecen marineanalletkf marineanlchkpt marineanlfinal ocnanalvrfy" exit 1 fi @@ -590,7 +590,7 @@ case ${step} in tasks_per_node=$(( max_tasks_per_node / 2 )) ;; - "ocnanalecen") + "marineanlecen") ntasks=16 case ${OCNRES} in "025") diff --git a/dev/parm/config/gfs/config.marineanl.j2 b/dev/parm/config/gfs/config.marineanl.j2 index bc16ff509ec..57c148b6402 100644 --- a/dev/parm/config/gfs/config.marineanl.j2 +++ b/dev/parm/config/gfs/config.marineanl.j2 @@ -5,7 +5,6 @@ echo "BEGIN: config.marineanl" -export JEDI_CONFIG_YAML_BMAT="${PARMgfs}/gdas/soca_bmat_jedi_config.yaml.j2" export JEDI_CONFIG_YAML_ANALYSIS="${PARMgfs}/gdas/soca_analysis_jedi_config.yaml.j2" export JCB_ALGO_YAML_VAR="{{ JCB_ALGO_YAML_VAR }}" diff --git a/dev/parm/config/gfs/config.marineanlecen b/dev/parm/config/gfs/config.marineanlecen new file mode 100644 index 00000000000..f440bd423a9 --- /dev/null +++ b/dev/parm/config/gfs/config.marineanlecen @@ -0,0 +1,15 @@ +#!/bin/bash + +########## config.marineanlecen ########## +# Ocn Analysis specific + +echo "BEGIN: config.marineanlecen" + +# Get task specific resources +source "${EXPDIR}/config.resources" marineanlecen + +export JEDI_CONFIG_YAML_ECEN="${PARMgfs}/gdas/soca/soca_ecen_jedi_config.yaml.j2" +export MARINE_ECEN_STAGE_YAML_TMPL="${PARMgfs}/gdas/soca/soca_ecen_stage.yaml.j2" +export MARINE_ECEN_FINALIZE_YAML_TMPL="${PARMgfs}/gdas/soca/soca_ecen_finalize.yaml.j2" + +echo "END: config.marineanlecen" diff --git a/dev/parm/config/gfs/config.marinebmat b/dev/parm/config/gfs/config.marinebmat index d88739dcedc..e5316c6fc2c 100644 --- a/dev/parm/config/gfs/config.marinebmat +++ b/dev/parm/config/gfs/config.marinebmat @@ -8,4 +8,7 @@ echo "BEGIN: config.marinebmat" # Get task specific resources . "${EXPDIR}/config.resources" marinebmat +export JEDI_CONFIG_YAML_BMAT="${PARMgfs}/gdas/soca_bmat_jedi_config.yaml.j2" +export MARINE_BMAT_FINALIZE_YAML_TMPL="${PARMgfs}/gdas/soca/soca_bmat_finalize.yaml.j2" + echo "END: config.marinebmat" diff --git a/dev/parm/config/gfs/config.marinebmatinit b/dev/parm/config/gfs/config.marinebmatinit index e42d10c7587..7e82ed33c53 100644 --- a/dev/parm/config/gfs/config.marinebmatinit +++ b/dev/parm/config/gfs/config.marinebmatinit @@ -8,4 +8,6 @@ echo "BEGIN: config.marinebmatinit" # Get task specific resources source "${EXPDIR}/config.resources" marinebmatinit +export JEDI_CONFIG_YAML_BMAT="${PARMgfs}/gdas/soca_bmat_jedi_config.yaml.j2" + echo "END: config.marinebmatinit" diff --git a/dev/parm/config/gfs/config.ocnanalecen b/dev/parm/config/gfs/config.ocnanalecen deleted file mode 100644 index b64c2bcf625..00000000000 --- a/dev/parm/config/gfs/config.ocnanalecen +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -########## config.ocnanalecen ########## -# Ocn Analysis specific - -echo "BEGIN: config.ocnanalecen" - -# Get task specific resources -. "${EXPDIR}/config.resources" ocnanalecen - -echo "END: config.ocnanalecen" diff --git a/dev/parm/config/gfs/config.resources b/dev/parm/config/gfs/config.resources index 5dd708d5958..5a2714dce73 100644 --- a/dev/parm/config/gfs/config.resources +++ b/dev/parm/config/gfs/config.resources @@ -26,7 +26,7 @@ if (( $# != 1 )); then echo "waveinit waveprep wavepostsbs wavepostbndpnt wavepostbndpntbll wavepostpnt" echo "wavegempak waveawipsbulls waveawipsgridded" echo "postsnd awips gempak npoess" - echo "marineanlinit prepoceanobs marinebmatinit marinebmat marineanlvar ocnanalecen marineanalletkf marineanlchkpt marineanlfinal ocnanalvrfy" + echo "marineanlinit prepoceanobs marinebmatinit marinebmat marineanlvar marineanlecen marineanalletkf marineanlchkpt marineanlfinal ocnanalvrfy" exit 1 fi @@ -568,7 +568,7 @@ case ${step} in tasks_per_node=$(( max_tasks_per_node / 2 )) ;; - "ocnanalecen") + "marineanlecen") ntasks=16 walltime="00:10:00" case ${OCNRES} in diff --git a/dev/parm/config/gfs/config.resources.GAEAC6 b/dev/parm/config/gfs/config.resources.GAEAC6 index 18441a72aea..5e955796956 100644 --- a/dev/parm/config/gfs/config.resources.GAEAC6 +++ b/dev/parm/config/gfs/config.resources.GAEAC6 @@ -76,7 +76,7 @@ case ${step} in esac ;; - "ocnanalecen") + "marineanlecen") case ${OCNRES} in "025") ntasks=288 diff --git a/dev/workflow/applications/gfs_cycled.py b/dev/workflow/applications/gfs_cycled.py index aead11a5a1f..4af35004017 100644 --- a/dev/workflow/applications/gfs_cycled.py +++ b/dev/workflow/applications/gfs_cycled.py @@ -119,7 +119,7 @@ def _get_app_configs(self, run): if options['do_letkf_ocn']: configs += ['marineanlletkf'] if options['do_hybvar']: - configs += ['ocnanalecen'] + configs += ['marineanlecen'] configs += ['marineanlchkpt', 'marineanlfinal'] if options['do_ocean'] or options['do_ice']: @@ -255,12 +255,7 @@ def get_task_names(self): task_names[run] += ['anal', 'analcalc'] if options['do_jediocnvar']: - task_names[run] += ['prepoceanobs', 'marineanlinit', 'marinebmatinit', 'marinebmat', 'marineanlvar'] - if options['do_letkf_ocn']: - task_names[run] += ['marineanlletkf'] - if options['do_hybvar']: - task_names[run] += ['ocnanalecen'] - task_names[run] += ['marineanlchkpt', 'marineanlfinal'] + task_names[run] += ['prepoceanobs', 'marineanlinit', 'marinebmatinit', 'marinebmat', 'marineanlvar', 'marineanlchkpt', 'marineanlfinal'] task_names[run] += ['sfcanl'] @@ -398,6 +393,12 @@ def get_task_names(self): task_names[run].append('echgres') if 'gdas' in run else 0 task_names[run] += ['ediag'] + if options['do_jediocnvar']: + if options['do_letkf_ocn']: + task_names[run] += ['marineanlletkf'] + if options['do_hybvar']: + task_names[run] += ['marineanlecen'] + task_names[run].append('esnowanl') if options['do_jedisnowda'] else 0 task_names[run].append('efcs') if 'gdas' in run else 0 task_names[run].append('epos') if 'gdas' in run else 0 diff --git a/dev/workflow/build_opts.yaml b/dev/workflow/build_opts.yaml index 2d983d08698..d90fd8662d3 100644 --- a/dev/workflow/build_opts.yaml +++ b/dev/workflow/build_opts.yaml @@ -36,7 +36,7 @@ build: gfs_model: command: "./build_ufs.sh -e gfs_model.x" cores: 12 - walltime: "00:30:00" + walltime: "00:40:00" gfs_ww3prepost: command: "./build_ww3prepost.sh" @@ -46,7 +46,7 @@ build: gefs_model: command: "./build_ufs.sh -w -e gefs_model.x" cores: 12 - walltime: "00:30:00" + walltime: "00:40:00" gefs_ww3_prepost: command: "./build_ww3prepost.sh -w" @@ -56,12 +56,12 @@ build: sfs_model: command: "./build_ufs.sh -y -e sfs_model.x" cores: 12 - walltime: "00:30:00" + walltime: "00:40:00" gcafs_model: command: "./build_ufs.sh -a ATMAERO -e gcafs_model.x" cores: 12 - walltime: "00:30:00" + walltime: "00:40:00" upp: command: "./build_upp.sh" diff --git a/dev/workflow/rocoto/gfs_tasks.py b/dev/workflow/rocoto/gfs_tasks.py index a9af466ef75..a8c8ba55d5e 100644 --- a/dev/workflow/rocoto/gfs_tasks.py +++ b/dev/workflow/rocoto/gfs_tasks.py @@ -707,9 +707,9 @@ def prepoceanobs(self): def marineanlletkf(self): deps = [] - dep_dict = {'type': 'task', 'name': f'{self.run}_prepoceanobs'} + dep_dict = {'type': 'task', 'name': f"{self.run.replace('enkf','')}_prepoceanobs"} deps.append(rocoto.add_dependency(dep_dict)) - dep_dict = {'type': 'task', 'name': f'{self.run}_marinebmat'} + dep_dict = {'type': 'task', 'name': f"{self.run.replace('enkf','')}_marinebmat"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep_condition='and', dep=deps) @@ -836,22 +836,22 @@ def marineanlvar(self): return task - def ocnanalecen(self): + def marineanlecen(self): # can run in parallel with marinebmat deps = [] - dep_dict = {'type': 'task', 'name': f'{self.run}_marinebmatinit'} + dep_dict = {'type': 'task', 'name': f"{self.run.replace('enkf','')}_marinebmatinit"} deps.append(rocoto.add_dependency(dep_dict)) dependencies = rocoto.create_dependency(dep=deps) - resources = self.get_resource('ocnanalecen') - task_name = f'{self.run}_ocnanalecen' + resources = self.get_resource('marineanlecen') + task_name = f'{self.run}_marineanlecen' task_dict = {'task_name': task_name, 'resources': resources, 'dependency': dependencies, 'envars': self.envars, 'cycledef': self.run.replace('enkf', ''), - 'command': f'{self.HOMEgfs}/dev/jobs/ocnanalecen.sh', + 'command': f'{self.HOMEgfs}/dev/jobs/marineanlecen.sh', 'job_name': f'{self.pslot}_{task_name}_@H', 'log': f'{self.rotdir}/logs/@Y@m@d@H/{task_name}.log', 'maxtries': '&MAXTRIES;' @@ -867,7 +867,7 @@ def marineanlchkpt(self): dep_dict = {'type': 'task', 'name': f'{self.run}_marineanlvar'} deps.append(rocoto.add_dependency(dep_dict)) if self.options['do_hybvar_ocn']: - dep_dict = {'type': 'task', 'name': f'{self.run}_ocnanalecen'} + dep_dict = {'type': 'task', 'name': f'enkf{self.run}_marineanlecen'} deps.append(rocoto.add_dependency(dep_dict)) if self.options['do_mergensst']: data = f'&ROTDIR;/{self.run}.@Y@m@d/@H/atmos/{self.run}.t@Hz.sfcanl.nc' @@ -2809,7 +2809,7 @@ def efcs(self): 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'} + dep_dict = {'type': 'task', 'name': f'{self.run}_marineanlecen'} 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'} @@ -2993,7 +2993,7 @@ def earc_tars(self): dep_dict = {'type': 'metatask', 'name': f'{self.run}_ecmn'} deps.append(rocoto.add_dependency(dep_dict)) if self._base.get('DOHYBVAR_OCN', True): - dep_dict = {'type': 'task', 'name': f'gfs_ocnanalecen'} + dep_dict = {'type': 'task', 'name': f'enkfgfs_marineanlecen'} deps.append(rocoto.add_dependency(dep_dict)) dep_dict = {'type': 'task', 'name': f'gfs_marineanlfinal'} deps.append(rocoto.add_dependency(dep_dict)) diff --git a/dev/workflow/rocoto/tasks.py b/dev/workflow/rocoto/tasks.py index de3c351a22b..37dc943e7aa 100644 --- a/dev/workflow/rocoto/tasks.py +++ b/dev/workflow/rocoto/tasks.py @@ -19,7 +19,7 @@ class Tasks: 'prepatmiodaobs', 'atmanlinit', 'atmanlvar', 'atmanlfv3inc', 'atmanlfinal', 'prep_emissions', 'prepoceanobs', 'marineanlinit', 'marineanlletkf', 'marinebmatinit', 'marinebmat', 'marineanlvar', - 'ocnanalecen', 'marineanlchkpt', 'marineanlfinal', 'ocnanalvrfy', + 'marineanlecen', 'marineanlchkpt', 'marineanlfinal', 'ocnanalvrfy', 'eobs', 'epos', 'esfc', 'eupd', 'earc_vrfy', 'earc_tars', 'ecen', 'echgres', 'ediag', 'efcs', 'atmensanlinit', 'atmensanlobs', 'atmensanlsol', 'atmensanlletkf', 'atmensanlfv3inc', 'atmensanlfinal', 'atmos_ensstat', diff --git a/env/GAEAC5.env b/env/GAEAC5.env index ab27864848a..b2db810b525 100755 --- a/env/GAEAC5.env +++ b/env/GAEAC5.env @@ -135,9 +135,9 @@ case ${step} in export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}" export APRUN_MARINEANLVAR="${APRUN_default}" ;; - "ocnanalecen") + "marineanlecen") - export APRUN_OCNANALECEN="${APRUN_default}" + export APRUN_MARINEANLECEN="${APRUN_default}" ;; "marineanlchkpt") diff --git a/env/GAEAC6.env b/env/GAEAC6.env index 2a5b93d7ee9..4920f15695a 100755 --- a/env/GAEAC6.env +++ b/env/GAEAC6.env @@ -135,9 +135,9 @@ case ${step} in export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}" export APRUN_MARINEANLVAR="${APRUN_default}" ;; - "ocnanalecen") + "marineanlecen") - export APRUN_OCNANALECEN="${APRUN_default}" + export APRUN_MARINEANLECEN="${APRUN_default}" ;; "marineanlchkpt") diff --git a/env/HERA.env b/env/HERA.env index 065f5dbc469..c1e3edd196a 100755 --- a/env/HERA.env +++ b/env/HERA.env @@ -154,10 +154,9 @@ elif [[ "${step}" = "marineanlchkpt" ]]; then export APRUN_MARINEANLOBSSTATS="${launcher} -n 1" -elif [[ "${step}" = "ocnanalecen" ]]; then +elif [[ "${step}" = "marineanlecen" ]]; then - export NTHREADS_OCNANALECEN=${NTHREADSmax} - export APRUN_OCNANALECEN="${APRUN_default} --cpus-per-task=${NTHREADS_OCNANALECEN}" + export APRUN_MARINEANLECEN=${APRUN_default} elif [[ "${step}" = "marineanlletkf" ]]; then diff --git a/env/HERCULES.env b/env/HERCULES.env index 65d18b0cc39..bbbfb6e6a52 100755 --- a/env/HERCULES.env +++ b/env/HERCULES.env @@ -141,9 +141,9 @@ case ${step} in export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}" export APRUN_MARINEANLVAR="${APRUN_default}" ;; - "ocnanalecen") + "marineanlecen") - export APRUN_OCNANALECEN="${APRUN_default}" + export APRUN_MARINEANLECEN="${APRUN_default}" ;; "marineanlchkpt") diff --git a/env/ORION.env b/env/ORION.env index 8da8d43b338..1cc6dde1777 100755 --- a/env/ORION.env +++ b/env/ORION.env @@ -150,10 +150,9 @@ elif [[ "${step}" = "marineanlchkpt" ]]; then export APRUN_MARINEANLOBSSTATS="${launcher} -n 1" -elif [[ "${step}" = "ocnanalecen" ]]; then +elif [[ "${step}" = "marineanlecen" ]]; then - export NTHREADS_OCNANALECEN=${NTHREADSmax} - export APRUN_OCNANALECEN="${APRUN_default} --cpus-per-task=${NTHREADS_OCNANALECEN}" + export APRUN_MARINEANLECEN=${APRUN_default} elif [[ "${step}" = "marineanlletkf" ]]; then diff --git a/env/WCOSS2.env b/env/WCOSS2.env index 35d3fdfc889..4c4d1ce2975 100755 --- a/env/WCOSS2.env +++ b/env/WCOSS2.env @@ -126,10 +126,10 @@ elif [[ "${step}" = "marineanlchkpt" ]]; then export APRUN_MARINEANLOBSSTATS="${launcher} -n 1" -elif [[ "${step}" = "ocnanalecen" ]]; then +elif [[ "${step}" = "marineanlecen" ]]; then - export NTHREADS_OCNANALECEN=${NTHREADSmax} - export APRUN_OCNANALECEN="${APRUN_default}" + export NTHREADS_MARINEANLECEN=${NTHREADSmax} + export APRUN_MARINEANLECEN="${APRUN_default}" elif [[ "${step}" = "marineanlletkf" ]]; then diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT b/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT index 092a3aafd2e..50bb03e1258 100755 --- a/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_CHECKPOINT @@ -1,8 +1,8 @@ #!/bin/bash export WIPE_DATA="NO" -export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAjob="${DATAROOT}/marineanalysis.${PDY:-}${cyc}" export DATAens="${DATAjob}/ensdata" -export DATA="${DATAjob}/marinevariational" +export DATA="${DATAjob}/marineanlvar" source "${HOMEgfs}/ush/jjob_header.sh" -e "marineanlchkpt" -c "base marineanl marineanlchkpt" diff --git a/jobs/JGDAS_GLOBAL_OCEAN_ANALYSIS_ECEN b/jobs/JGLOBAL_MARINE_ANALYSIS_ECEN similarity index 77% rename from jobs/JGDAS_GLOBAL_OCEAN_ANALYSIS_ECEN rename to jobs/JGLOBAL_MARINE_ANALYSIS_ECEN index 63b5775e85c..9b409155000 100755 --- a/jobs/JGDAS_GLOBAL_OCEAN_ANALYSIS_ECEN +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_ECEN @@ -1,10 +1,10 @@ #!/bin/bash -export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" -export DATA="${DATAjob}/${jobid}" +export DATAjob="${DATAROOT/enkf}/marineanalysis.${PDY:-}${cyc}" +export DATA="${DATAjob}/marineanlecen" export DATAens="${DATAjob}/ensdata" -source "${HOMEgfs}/ush/jjob_header.sh" -e "ocnanalecen" -c "base marineanl ocnanalecen" +source "${HOMEgfs}/ush/jjob_header.sh" -e "marineanlecen" -c "base marineanl marineanlecen" ############################################## # Set variables used in the script @@ -15,17 +15,16 @@ GDATE=$(date --utc +%Y%m%d%H -d "${PDY} ${cyc} - ${assim_freq} hours") export gPDY=${GDATE:0:8} export gcyc=${GDATE:8:2} export GDUMP="gdas" -export GDUMP_ENS="enkf${GDUMP}" RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ COMIN_OCEAN_HISTORY_PREV:COM_OCEAN_HISTORY_TMPL \ COMIN_ICE_HISTORY_PREV:COM_ICE_HISTORY_TMPL -RUN=${GDUMP_ENS} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ +YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ COMIN_OCEAN_HISTORY_ENS_PREV:COM_OCEAN_HISTORY_TMPL \ COMIN_ICE_HISTORY_ENS_PREV:COM_ICE_HISTORY_TMPL -YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ +RUN=${GDUMP} 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 @@ -42,7 +41,7 @@ fi ############################################################### # Run relevant script -EXSCRIPT=${GDASOCNCENPY:-${HOMEgfs}/scripts/exgdas_global_marine_analysis_ecen.py} +EXSCRIPT=${GDASOCNCENPY:-${HOMEgfs}/scripts/exglobal_marine_analysis_ecen.py} ${EXSCRIPT} && true export err=$? if [[ ${err} -ne 0 ]]; then @@ -63,14 +62,10 @@ fi ########################################## # Remove the Temporary working directory ########################################## -cd "${DATAROOT}" && true +cd "${DATAROOT/enkf}" && true export err=$? if [[ ${err} -ne 0 ]]; then err_exit fi -if [[ "${KEEPDATA}" == "NO" ]]; then - rm -rf "${DATA}" -fi - exit 0 diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE b/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE index 4ad08f5e0cd..d75f4a21b39 100755 --- a/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_FINALIZE @@ -1,8 +1,8 @@ #!/bin/bash export WIPE_DATA="NO" -export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAjob="${DATAROOT}/marineanalysis.${PDY:-}${cyc}" export DATAens="${DATAjob}/ensdata" -export DATA="${DATAjob}/marinevariational" +export DATA="${DATAjob}/marineanlvar" source "${HOMEgfs}/ush/jjob_header.sh" -e "marineanlfinal" -c "base marineanl marineanlfinal" ############################################## @@ -48,7 +48,7 @@ if [[ ${err} -ne 0 ]]; then fi if [[ "${KEEPDATA}" == "NO" ]]; then - rm -rf "${DATA}" + rm -rf "${DATAjob}" fi exit 0 diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE b/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE index 0c851459f5f..95e5ab12385 100755 --- a/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_INITIALIZE @@ -1,8 +1,8 @@ #!/bin/bash -export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAjob="${DATAROOT}/marineanalysis.${PDY:-}${cyc}" export DATAens="${DATAjob}/ensdata" -export DATA="${DATAjob}/marinevariational" +export DATA="${DATAjob}/marineanlvar" source "${HOMEgfs}/ush/jjob_header.sh" -e "marineanlinit" -c "base marineanl marineanlinit" diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_LETKF b/jobs/JGLOBAL_MARINE_ANALYSIS_LETKF index e8c3b1f1c2e..0c62809c5e0 100755 --- a/jobs/JGLOBAL_MARINE_ANALYSIS_LETKF +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_LETKF @@ -1,8 +1,8 @@ #!/bin/bash -export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" -export DATA="${DATAjob}/${jobid}" -# Create the directory to hold ensemble perturbations +# Use ${DATAROOT/enkf} because DATAjob is created by a gdas_marineanlinit job +export DATAjob="${DATAROOT/enkf}/marineanalysis.${PDY:-}${cyc}" +export DATA="${DATAjob}/marineanlletkf" export DATAens="${DATAjob}/ensdata" if [[ ! -d "${DATAens}" ]]; then mkdir -p "${DATAens}"; fi @@ -19,11 +19,10 @@ gPDY=${GDATE:0:8} gcyc=${GDATE:8:2} export GDUMP="gdas" export GDUMP_ENS="enkf${GDUMP}" -export OPREFIX="${RUN}.t${cyc}z." ec_offset=${NMEM_ENS_GFS_OFFSET:-20} export NMEM_ENS_MAX=${NMEM_ENS} -if [[ "${RUN}" == "gfs" && "${DOHYBVAR_OCN}" == "YES" ]]; then +if [[ "${RUN/enkf}" == "gfs" && "${DOHYBVAR_OCN}" == "YES" ]]; then NMEM_ENS=${NMEM_ENS_GFS} export mem_offset=$((ec_offset * cyc/6)) else @@ -34,13 +33,14 @@ RUN="${GDUMP}" YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \ COMIN_OCEAN_HISTORY_PREV:COM_OCEAN_HISTORY_TMPL \ COMIN_ICE_HISTORY_PREV:COM_ICE_HISTORY_TMPL -YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ +RUN="${GDUMP}" YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ COMIN_OBS:COM_OBS_TMPL \ + +YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \ COMOUT_OCEAN_LETKF:COM_OCEAN_LETKF_TMPL \ COMOUT_ICE_LETKF:COM_ICE_LETKF_TMPL -# TODO: remove explicit RUN specification once https://github.com/NOAA-EMC/global-workflow/issues/3767 is fixed -RUN=${GDUMP_ENS} YMD=${PDY} HH=${cyc} MEMDIR="ensstat" declare_from_tmpl -rx \ +YMD=${PDY} HH=${cyc} MEMDIR="ensstat" declare_from_tmpl -rx \ COMOUT_CONF:COM_CONF_TMPL if [[ ! -d ${COMOUT_CONF} ]]; then mkdir -p "${COMOUT_CONF}"; fi @@ -72,13 +72,11 @@ fi ########################################## # Remove the Temporary working directory ########################################## -cd "${DATAROOT}" && true +# Use ${DATAROOT/enkf} because DATAjob is created by a gdas_marineanlinit job +cd "${DATAROOT/enkf}" && true export err=$? if [[ ${err} -ne 0 ]]; then err_exit fi -if [[ "${KEEPDATA}" == "NO" ]]; then - rm -rf "${DATA}" -fi exit 0 diff --git a/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL b/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL index 18a872aa9a3..9a97107efa4 100755 --- a/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL +++ b/jobs/JGLOBAL_MARINE_ANALYSIS_VARIATIONAL @@ -1,9 +1,9 @@ #! /usr/bin/env bash export WIPE_DATA="NO" -export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAjob="${DATAROOT}/marineanalysis.${PDY:-}${cyc}" export DATAens="${DATAjob}/ensdata" -export DATA="${DATAjob}/marinevariational" +export DATA="${DATAjob}/marineanlvar" source "${HOMEgfs}/ush/jjob_header.sh" -e "marineanlvar" -c "base marineanl marineanlvar" ############################################## diff --git a/jobs/JGLOBAL_MARINE_BMAT b/jobs/JGLOBAL_MARINE_BMAT index 0e0c614d2d6..7d74fac16e2 100755 --- a/jobs/JGLOBAL_MARINE_BMAT +++ b/jobs/JGLOBAL_MARINE_BMAT @@ -1,7 +1,7 @@ #!/bin/bash export WIPE_DATA="NO" -export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAjob="${DATAROOT}/marineanalysis.${PDY:-}${cyc}" # DATA is pre-populated by the MARINE_BMAT_INIT job export DATA="${DATAjob}/marinebmat" # Create the directory to hold ensemble perturbations diff --git a/jobs/JGLOBAL_MARINE_BMAT_INITIALIZE b/jobs/JGLOBAL_MARINE_BMAT_INITIALIZE index 490fbf25152..043535ce044 100755 --- a/jobs/JGLOBAL_MARINE_BMAT_INITIALIZE +++ b/jobs/JGLOBAL_MARINE_BMAT_INITIALIZE @@ -1,7 +1,7 @@ #!/bin/bash -export DATAjob="${DATAROOT}/${RUN}marineanalysis.${PDY:-}${cyc}" +export DATAjob="${DATAROOT}/marineanalysis.${PDY:-}${cyc}" # Create the directory to hold the BMAT initialization data export DATA="${DATAjob}/marinebmat" # Create the directory to hold ensemble perturbations diff --git a/parm/archive/enkf.yaml.j2 b/parm/archive/enkf.yaml.j2 index 63e4dc3c855..4c1030da17a 100644 --- a/parm/archive/enkf.yaml.j2 +++ b/parm/archive/enkf.yaml.j2 @@ -34,6 +34,9 @@ enkf: {% set steps = ["eobs", "eupd"] %} {% endif %} {% endif %} + {% if DOHYBVAR_OCN %} + {% set steps = steps + ["marineanlecen"] %} + {% endif %} {% for step in steps %} - "logs/{{ cycle_YMDH }}/{{ RUN }}_{{ step }}.log" diff --git a/parm/archive/gdas.yaml.j2 b/parm/archive/gdas.yaml.j2 index bc4b4009fe9..a1fac1b3718 100644 --- a/parm/archive/gdas.yaml.j2 +++ b/parm/archive/gdas.yaml.j2 @@ -27,9 +27,6 @@ gdas: - "logs/{{ cycle_YMDH }}/{{ RUN }}_marineanlvar.log" - "logs/{{ cycle_YMDH }}/{{ RUN }}_marineanlfinal.log" - "logs/{{ cycle_YMDH }}/{{ RUN }}_marineanlchkpt.log" - {% if DOHYBVAR_OCN %} - - "logs/{{ cycle_YMDH }}/{{ RUN }}_ocnanalecen.log" - {% endif %} {% endif %} {% if DO_AERO_ANL %} - "logs/{{ cycle_YMDH }}/gdas_aeroanlgenb.log" diff --git a/scripts/exglobal_marine_analysis_ecen.py b/scripts/exglobal_marine_analysis_ecen.py new file mode 100755 index 00000000000..e339d790016 --- /dev/null +++ b/scripts/exglobal_marine_analysis_ecen.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# exgdas_global_marine_analysis_ecen.py +# This script creates an MarineRecenter class +# and runs the initialize, run, and finalize methods +import os + +from wxflow import Logger, cast_strdict_as_dtypedict +from pygfs.task.marine_recenter import MarineRecenter + +# Initialize root logger +logger = Logger(level='DEBUG', colored_log=True) + + +if __name__ == '__main__': + + # Take configuration from environment and cast it as python dictionary + config = cast_strdict_as_dtypedict(os.environ) + + # + MarineRecen = MarineRecenter(config) + MarineRecen.initialize() + MarineRecen.execute('gridgen') + MarineRecen.execute('ens_handler') + MarineRecen.finalize() diff --git a/sorc/gdas.cd b/sorc/gdas.cd index 65466562499..41a5edc4a13 160000 --- a/sorc/gdas.cd +++ b/sorc/gdas.cd @@ -1 +1 @@ -Subproject commit 65466562499d9d2d640559bd1148b21435274128 +Subproject commit 41a5edc4a135f5b25e469e0650a4e857fa00b219 diff --git a/sorc/link_workflow.sh b/sorc/link_workflow.sh index 12054acfa7f..bc69ddabeb3 100755 --- a/sorc/link_workflow.sh +++ b/sorc/link_workflow.sh @@ -160,9 +160,7 @@ done cd "${HOMEgfs}/scripts" || exit 8 if [[ -d "${HOMEgfs}/sorc/gdas.cd" ]]; then - declare -a gdas_scripts=(exglobal_prep_ocean_obs.py - exgdas_global_marine_analysis_ecen.py - ) + declare -a gdas_scripts=(exglobal_prep_ocean_obs.py) for gdas_script in "${gdas_scripts[@]}"; do ${LINK_OR_COPY} "${HOMEgfs}/sorc/gdas.cd/scripts/${gdas_script}" . done diff --git a/ush/python/pygfs/__init__.py b/ush/python/pygfs/__init__.py index d718c6c0c93..394a93e8a47 100644 --- a/ush/python/pygfs/__init__.py +++ b/ush/python/pygfs/__init__.py @@ -18,6 +18,7 @@ from .task.gfs_forecast import GFSForecast from .utils import marine_da_utils from .task.fetch import Fetch +from .task.marine_recenter import MarineRecenter __docformat__ = "restructuredtext" __version__ = "0.1.0" diff --git a/ush/python/pygfs/task/marine_analysis.py b/ush/python/pygfs/task/marine_analysis.py index 537b3d0d95e..539a69466af 100644 --- a/ush/python/pygfs/task/marine_analysis.py +++ b/ush/python/pygfs/task/marine_analysis.py @@ -197,7 +197,7 @@ def finalize(self: Task) -> None: """ # Save output files to COM - logger.info(f"Copy files from {self.task_config.DATA} to {self.task_config.COMOUT_OCEAN_ANALYSIS}") + logger.info(f"Copy files to ROTDIR") soca_finalize_list = parse_j2yaml(self.task_config.MARINE_DET_FINALIZE_YAML_TMPL, self.task_config) FileHandler(soca_finalize_list).sync() diff --git a/ush/python/pygfs/task/marine_bmat.py b/ush/python/pygfs/task/marine_bmat.py index 455df977497..835f5382900 100644 --- a/ush/python/pygfs/task/marine_bmat.py +++ b/ush/python/pygfs/task/marine_bmat.py @@ -5,14 +5,11 @@ from logging import getLogger import pygfs.utils.marine_da_utils as mdau -from wxflow import (AttrDict, - FileHandler, - add_to_datetime, to_timedelta, +from wxflow import (AttrDict, FileHandler, Executable, Task, + add_to_datetime, to_timedelta, to_isotime, chdir, parse_j2yaml, save_as_yaml, - logit, - Executable, - Task) + logit) from pygfs.jedi import Jedi @@ -62,6 +59,9 @@ def __init__(self, config): 'MARINE_WINDOW_MIDDLE': self.task_config.current_cycle, 'MARINE_WINDOW_END': _window_end, 'MARINE_WINDOW_LENGTH': f"PT{self.task_config['assim_freq']}H", + 'MARINE_WINDOW_BEGIN_ISO': to_isotime(_window_begin), + 'MARINE_WINDOW_MIDDLE_ISO': to_isotime(self.task_config.current_cycle), + 'MARINE_WINDOW_END_ISO': to_isotime(_window_end), 'ENSPERT_RELPATH': _enspert_relpath, 'CALC_SCALE_EXEC': _calc_scale_exec, 'APREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z.", @@ -114,6 +114,7 @@ def initialize(self: Task) -> None: # stage backgrounds # TODO(G): Check ocean backgrounds dates for consistency + logger.info(f"Staging SOCA backgrounds") bkg_list = parse_j2yaml(self.task_config.MARINE_DET_STAGE_BKG_YAML_TMPL, self.task_config) FileHandler(bkg_list).sync() @@ -125,8 +126,6 @@ def initialize(self: Task) -> None: # initialize vtscales python script vtscales_config = self.jedi_dict['soca_parameters_diffusion_vt'].render_jcb(self.task_config, 'soca_vtscales') save_as_yaml(vtscales_config, os.path.join(self.task_config.DATA, 'soca_vtscales.yaml')) - FileHandler({'copy': [[os.path.join(self.task_config.CALC_SCALE_EXEC), - os.path.join(self.task_config.DATA, 'calc_scales.x')]]}).sync() # initialize JEDI applications self.jedi_dict['gridgen'].initialize(self.task_config) @@ -142,14 +141,12 @@ def initialize(self: Task) -> None: # stage ensemble members for the hybrid background error 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) + letkf_stage_list = parse_j2yaml(self.task_config.MARINE_ENSDA_STAGE_BKG_YAML_TMPL, self.task_config) + FileHandler(letkf_stage_list).sync() # create the symbolic link to the static B-matrix directory - link_target = os.path.join(self.task_config.DATAstaticb) - link_name = os.path.join(self.task_config.DATA, 'staticb') - if os.path.exists(link_name): - os.remove(link_name) - os.symlink(link_target, link_name) + FileHandler({'link': [[self.task_config.DATAstaticb, + os.path.join(self.task_config.DATA, 'staticb')]]}).sync() @logit(logger) def execute(self) -> None: @@ -183,7 +180,7 @@ def execute(self) -> None: # vertical diffusion exec_cmd = Executable("python") - exec_name = os.path.join(self.task_config.DATA, 'calc_scales.x') + exec_name = self.task_config.CALC_SCALE_EXEC exec_cmd.add_default_arg(exec_name) exec_cmd.add_default_arg('soca_vtscales.yaml') mdau.run(exec_cmd) @@ -215,84 +212,14 @@ def finalize(self: Task) -> None: None """ - APREFIX = self.task_config.APREFIX - window_begin_iso = self.task_config.MARINE_WINDOW_BEGIN.strftime('%Y-%m-%dT%H:%M:%SZ') - window_middle_iso = self.task_config.MARINE_WINDOW_MIDDLE.strftime('%Y-%m-%dT%H:%M:%SZ') - window_end_iso = self.task_config.MARINE_WINDOW_END.strftime('%Y-%m-%dT%H:%M:%SZ') - - # Copy the soca grid if it was created - grid_file = os.path.join(self.task_config.DATA, 'soca_gridspec.nc') - if os.path.exists(grid_file): - logger.info(f"Copying the soca grid file to the ROTDIR") - FileHandler({'copy': [[grid_file, - os.path.join(self.task_config.COMOUT_OCEAN_BMATRIX, 'soca_gridspec.nc')]]}).sync() - - # Copy the diffusion coefficient files to the ROTDIR - logger.info(f"Copying the diffusion coefficient files to the ROTDIR") - diffusion_coeff_list = [] - for diff_type in ['hz', 'vt']: - src = os.path.join(self.task_config.DATAstaticb, f"{diff_type}_ocean.nc") - dest = os.path.join(self.task_config.COMOUT_OCEAN_BMATRIX, - f"{APREFIX}{diff_type}_ocean.nc") - diffusion_coeff_list.append([src, dest]) - - FileHandler({'copy': diffusion_coeff_list}).sync() - - # Copy diag B files to ROTDIR - logger.info(f"Copying diag B files to the ROTDIR") - diagb_list = [] - # TODO(AFE) the two renames are to accomodate yaml settings in var task, which should changed # ocean diag B - os.rename(os.path.join(self.task_config.DATAstaticb, f"ocn.bkgerr_stddev.incr.{window_end_iso}.nc"), + os.rename(os.path.join(self.task_config.DATAstaticb, f"ocn.bkgerr_stddev.incr.{self.task_config.MARINE_WINDOW_END_ISO}.nc"), os.path.join(self.task_config.DATAstaticb, f"ocn.bkgerr_stddev.nc")) - src = os.path.join(self.task_config.DATAstaticb, f"ocn.bkgerr_stddev.nc") - dst = os.path.join(self.task_config.COMOUT_OCEAN_BMATRIX, f"{APREFIX}ocean.bkgerr_ens_stddev.nc") - diagb_list.append([src, dst]) - - # ice diag B - os.rename(os.path.join(self.task_config.DATAstaticb, f"ice.bkgerr_stddev.incr.{window_end_iso}.nc"), + os.rename(os.path.join(self.task_config.DATAstaticb, f"ice.bkgerr_stddev.incr.{self.task_config.MARINE_WINDOW_END_ISO}.nc"), os.path.join(self.task_config.DATAstaticb, f"ice.bkgerr_stddev.nc")) - src = os.path.join(self.task_config.DATAstaticb, f"ice.bkgerr_stddev.nc") - dst = os.path.join(self.task_config.COMOUT_ICE_BMATRIX, f"{APREFIX}ice.bkgerr_ens_stddev.nc") - diagb_list.append([src, dst]) - - if self.task_config.DOHYBVAR_OCN == "YES" or self.task_config.NMEM_ENS >= 2: - src = os.path.join(self.task_config.DATAstaticb, f"ocn.ssh_recentering_error.incr.{window_begin_iso}.nc") - dst = os.path.join(self.task_config.COMOUT_OCEAN_BMATRIX, f"{APREFIX}ocean.recentering_error.nc") - diagb_list.append([src, dst]) - src = os.path.join(self.task_config.DATAstaticb, f"ice.ssh_recentering_error.incr.{window_begin_iso}.nc") - dst = os.path.join(self.task_config.COMOUT_ICE_BMATRIX, f"{APREFIX}ice.recentering_error.nc") - diagb_list.append([src, dst]) - - FileHandler({'copy': diagb_list}).sync() - - # Copy the ensemble perturbation diagnostics to the ROTDIR - if self.task_config.DOHYBVAR_OCN == "YES" or self.task_config.NMEM_ENS >= 2: - weight_list = [] - src = os.path.join(self.task_config.DATA, f"ocn.ens_weights.incr.{window_middle_iso}.nc") - dst = os.path.join(self.task_config.COMOUT_OCEAN_BMATRIX, - f"{APREFIX}ocean.ens_weights.nc") - weight_list.append([src, dst]) - - src = os.path.join(self.task_config.DATA, f"ice.ens_weights.incr.{window_middle_iso}.nc") - dst = os.path.join(self.task_config.COMOUT_ICE_BMATRIX, - f"{APREFIX}ice.ens_weights.nc") - weight_list.append([src, dst]) - - # Copy the ssh diagnostics - for string in ['ssh_steric_stddev', 'ssh_unbal_stddev', 'ssh_total_stddev', 'steric_explained_variance']: - weight_list.append([os.path.join(self.task_config.DATA, 'staticb', f'ocn.{string}.incr.{window_begin_iso}.nc'), - os.path.join(self.task_config.COMOUT_OCEAN_BMATRIX, f'{APREFIX}ocean.{string}.nc')]) - - FileHandler({'copy': weight_list}).sync() - - # Copy the YAML files to the OCEAN ROTDIR - yamls = glob.glob(os.path.join(self.task_config.DATA, '*.yaml')) - yaml_list = [] - for yaml_file in yamls: - dest = os.path.join(self.task_config.COMOUT_CONF, - f"{APREFIX}{os.path.basename(yaml_file)}") - yaml_list.append([yaml_file, dest]) - FileHandler({'copy': yaml_list}).sync() + # Save output files to COM + logger.info(f"Copy files to ROTDIR") + soca_finalize_list = parse_j2yaml(self.task_config.MARINE_BMAT_FINALIZE_YAML_TMPL, self.task_config) + FileHandler(soca_finalize_list).sync() diff --git a/ush/python/pygfs/task/marine_letkf.py b/ush/python/pygfs/task/marine_letkf.py index 4e549e6acf8..88780bfc46f 100644 --- a/ush/python/pygfs/task/marine_letkf.py +++ b/ush/python/pygfs/task/marine_letkf.py @@ -57,6 +57,7 @@ def __init__(self, config: Dict) -> None: self.task_config.PARMsoca = os.path.join(self.task_config.PARMgfs, 'gdas', 'soca') self.task_config.app_path_observations = self.task_config.MARINE_JCB_GDAS_OBS self.task_config.letkf_app = "true" + self.task_config.OPREFIX = f"{self.task_config.RUN.replace('enkf','')}.t{self.task_config.cyc:02d}z." @logit(logger) def initialize(self): @@ -102,7 +103,8 @@ def initialize(self): 'ROTDIR', 'RUN', 'WINDOW_BEGIN', - 'WINDOW_MIDDLE'] + 'WINDOW_MIDDLE', + 'DATAens'] for key in keys: stageconfig[key] = self.task_config[key] diff --git a/ush/python/pygfs/task/marine_recenter.py b/ush/python/pygfs/task/marine_recenter.py new file mode 100644 index 00000000000..78fbca00418 --- /dev/null +++ b/ush/python/pygfs/task/marine_recenter.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 + +from logging import getLogger +import os +from typing import Dict +import pygfs.utils.marine_da_utils as mdau +from pygfs.jedi import Jedi +from wxflow import (AttrDict, FileHandler, Task, + add_to_datetime, to_timedelta, to_fv3time, to_isotime, + parse_j2yaml, + logit) + +logger = getLogger(__name__.split('.')[-1]) + + +class MarineRecenter(Task): + """ + Class for global ocean analysis recentering task + """ + + @logit(logger, name="MarineRecenter") + def __init__(self, config: Dict) -> None: + """Constructor for ocean recentering task + Parameters: + ------------ + config: Dict + configuration, namely evironment variables + Returns: + -------- + None + """ + + super().__init__(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) + _enspert_relpath = os.path.relpath(self.task_config.DATAens, self.task_config.DATA) + if self.task_config.DOIAU: + # forecast initialized at the begining of the DA window + _cice_rst_date = to_fv3time(_window_begin) + else: + # forecast initialized at the middle of the DA window + _cice_rst_date = to_fv3time(self.task_config.current_cycle) + + local_dict = AttrDict( + { + 'PARMsoca': os.path.join(self.task_config.PARMgfs, 'gdas', 'soca'), + 'MARINE_WINDOW_BEGIN': _window_begin, + 'MARINE_WINDOW_END': _window_end, + 'MARINE_WINDOW_MIDDLE': self.task_config.current_cycle, + 'MARINE_WINDOW_BEGIN_ISO': to_isotime(_window_begin), + 'MARINE_WINDOW_END_ISO': to_isotime(_window_end), + 'MARINE_WINDOW_MIDDLE_ISO': to_isotime(self.task_config.current_cycle), + 'MARINE_WINDOW_LENGTH': f"PT{self.task_config['assim_freq']}H", + 'ENSPERT_RELPATH': _enspert_relpath, + '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.", + 'cice_rst_date': _cice_rst_date + } + ) + + # Extend task_config with local_dict + self.task_config.update(local_dict) + + # Construct dictionary of JEDI objects, one for each JEDI application need for the analysis + expected_keys = ['gridgen', 'ens_handler'] + self.jedi_dict = Jedi.get_jedi_dict(self.task_config.JEDI_CONFIG_YAML_ECEN, self.task_config, expected_keys) + + @logit(logger) + def initialize(self): + """Method initialize for ocean recentering task + Parameters: + ------------ + None + Returns: + -------- + None + """ + + # stage fix files + logger.info(f"Staging SOCA fix files from {self.task_config.SOCA_INPUT_FIX_DIR}") + soca_fix_list = parse_j2yaml(self.task_config.SOCA_FIX_YAML_TMPL, self.task_config) + FileHandler(soca_fix_list).sync() + + # prepare the MOM6 input.nml + mdau.prep_input_nml(self.task_config) + + # stage the soca utility yamls (gridgen, fields and ufo mapping yamls) + logger.info(f"Staging SOCA utility yaml files from {self.task_config.PARMsoca}") + soca_utility_list = parse_j2yaml(self.task_config.MARINE_UTILITY_YAML_TMPL, self.task_config) + FileHandler(soca_utility_list).sync() + + # stage backgrounds + bkg_list = parse_j2yaml(self.task_config.MARINE_DET_STAGE_BKG_YAML_TMPL, self.task_config) + FileHandler(bkg_list).sync() + + # stage the ensemble members and CICE restarts + logger.info("---------------- Stage ensemble members and CICE restarts") + soca_ens_list = parse_j2yaml(self.task_config.MARINE_ECEN_STAGE_YAML_TMPL, self.task_config) + FileHandler(soca_ens_list).sync() + + # initialize JEDI applications + logger.info(f"Initializing SOCA gridgen application") + self.jedi_dict['gridgen'].initialize(self.task_config) + + logger.info(f"Initializing SOCA ensemble handler") + self.jedi_dict['ens_handler'].initialize(self.task_config) + + @logit(logger) + def execute(self, jedi_dict_key: str) -> None: + """Execute JEDI application of marine analysis + + Parameters + ---------- + jedi_dict_key + key specifying particular Jedi object in self.jedi_dict + + Returns + ---------- + None + """ + + self.jedi_dict[jedi_dict_key].execute() + + @logit(logger) + def finalize(self): + """Method finalize for ocean recentering task + Parameters: + ------------ + None + Returns: + -------- + None + """ + + # Save recentered increments and ensemble statistics + logger.info("---------------- Save recentered increments and ensemble statistics") + soca_ens_list = parse_j2yaml(self.task_config.MARINE_ECEN_FINALIZE_YAML_TMPL, self.task_config) + FileHandler(soca_ens_list).sync()