diff --git a/jobs/JOBSFORGE_GLOBAL_MARINE_BUFR_DUMP b/jobs/JOBSFORGE_GLOBAL_MARINE_BUFR_DUMP new file mode 100755 index 00000000..5e49e4ab --- /dev/null +++ b/jobs/JOBSFORGE_GLOBAL_MARINE_BUFR_DUMP @@ -0,0 +1,45 @@ +#! /usr/bin/env bash + +source "${HOMEobsforge}/ush/preamble.sh" +source "${HOMEobsforge}/ush/jjob_header.sh" + +############################################## +# Set variables used in the script +############################################## + + +############################################## +# Begin JOB SPECIFIC work +############################################## + +############################################################### +# Run relevant script + +EXSCRIPT=${DUMPMARINEBUFRPY:-${HOMEobsforge}/scripts/exobsforge_global_marine_bufr_dump.py} +${EXSCRIPT} +status=$? +if [[ ${status} -ne 0 ]]; then + exit "${status}" +fi + + +############################################## +# End JOB SPECIFIC work +############################################## + +############################################## +# Final processing +############################################## +if [[ -e "${pgmout}" ]] ; then + cat "${pgmout}" +fi + +########################################## +# Remove the Temporary working directory +########################################## +cd "${DATAROOT}" || exit +if [[ "${KEEPDATA}" == "NO" ]]; then + rm -rf "${DATA}" +fi + +exit 0 diff --git a/jobs/rocoto/marinebufrdump.sh b/jobs/rocoto/marinebufrdump.sh new file mode 100755 index 00000000..977ab1e6 --- /dev/null +++ b/jobs/rocoto/marinebufrdump.sh @@ -0,0 +1,20 @@ +#! /usr/bin/env bash + +source "${HOMEobsforge}/ush/preamble.sh" + +############################################################### +# Source UFSDA workflow modules +. "${HOMEobsforge}/ush/load_obsforge_modules.sh" +status=$? +if [[ ${status} -ne 0 ]]; then + exit "${status}" +fi + +export job="marinebufrdump" +export jobid="${job}.$$" + +############################################################### +# Execute the JJOB +"${HOMEobsforge}/jobs/JOBSFORGE_GLOBAL_MARINE_BUFR_DUMP" +status=$? +exit "${status}" diff --git a/parm/config.hera.yaml b/parm/config.hera.yaml index 1dee5c59..e230faee 100644 --- a/parm/config.hera.yaml +++ b/parm/config.hera.yaml @@ -90,3 +90,10 @@ marinedump: WALLTIME_MARINE_DUMP: '00:10:00' TASK_GEOM_MARINE_DUMP: '1:ppn=20:tpp=2' MEMORY_MARINE_DUMP: 32GB + +marinebufrdump: + + WALLTIME_MARINE_BUFR_DUMP: '00:10:00' + TASK_GEOM_MARINE_BUFR_DUMP: '1:ppn=1:tpp=1' + MEMORY_MARINE_BUFR_DUMP: 32GB + diff --git a/parm/obsforge_rocoto_template.xml.j2 b/parm/obsforge_rocoto_template.xml.j2 index 65193496..613ec09f 100644 --- a/parm/obsforge_rocoto_template.xml.j2 +++ b/parm/obsforge_rocoto_template.xml.j2 @@ -136,5 +136,44 @@ --> + + + + {{ HOMEobsforge }}/jobs/rocoto/marinebufrdump.sh + + obsforge_gfs_marine_bufr_dump_@H + {{ ACCOUNT }} + {{ QUEUE }} + {{ PARTITION }} + {{ WALLTIME_MARINE_BUFR_DUMP }} + {{ TASK_GEOM_MARINE_BUFR_DUMP }} + {{ MEMORY_MARINE_BUFR_DUMP }} + --export=NONE + + {{ COMROOT }}/{{ PSLOT }}/logs/@Y@m@d@H/gfs_marine_bufr_dump_prep.log + + RUN_ENVIRemc + HOMEobsforge{{ HOMEobsforge }} + NETgfs + RUNgfs + CDATE@Y@m@d@H + PDY@Y@m@d + cyc@H + KEEPDATA{{ KEEPDATA }} + COMROOT{{ COMROOT }} + DCOMROOT{{ DCOMROOT }} + DATAROOT{{ DATAROOT }}/{{ PSLOT }}/gfs.@Y@m@d@H + + + + + diff --git a/scripts/exobsforge_global_marine_bufr_dump.py b/scripts/exobsforge_global_marine_bufr_dump.py new file mode 100755 index 00000000..94675edf --- /dev/null +++ b/scripts/exobsforge_global_marine_bufr_dump.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# exobsforge_global_marine_bufr_dump.py +# This script will collect and preprocess +# the ocean and seaice observations for +# global marine assimilation +import os + +from wxflow import AttrDict, Logger, cast_strdict_as_dtypedict, parse_j2yaml +from pyobsforge.task.marine_bufr_prepobs import MarineBufrObsPrep + +# Initialize root logger +logger = Logger(level='DEBUG', colored_log=True) + + +if __name__ == '__main__': + + # Take configuration from environment and cast it as python dictionary + config_env = cast_strdict_as_dtypedict(os.environ) + + # Take configuration from YAML file to augment/append config dict + config_yaml = parse_j2yaml(os.path.join(config_env['HOMEobsforge'], 'parm', 'config.yaml'), config_env) + # Extract obsforge specific configuration + obsforge_dict = {} + for key, value in config_yaml['obsforge'].items(): + if key not in config_env.keys(): + obsforge_dict[key] = value + + # Combine configs together + config = AttrDict(**config_env, **obsforge_dict) + config = AttrDict(**config, **config_yaml['marinebufrdump']) + + marineBufrObs = MarineBufrObsPrep(config) + marineBufrObs.initialize() + marineBufrObs.execute() + marineBufrObs.finalize() diff --git a/ush/python/pyobsforge/task/marine_bufr_prepobs.py b/ush/python/pyobsforge/task/marine_bufr_prepobs.py new file mode 100644 index 00000000..bed25104 --- /dev/null +++ b/ush/python/pyobsforge/task/marine_bufr_prepobs.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +from logging import getLogger +from typing import Dict, Any +from wxflow import AttrDict, Task, add_to_datetime, to_timedelta, logit + +logger = getLogger(__name__.split('.')[-1]) + + +class MarineBufrObsPrep(Task): + """ + Class for preparing and managing marine observations + """ + def __init__(self, config: Dict[str, Any]) -> 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) + + local_dict = AttrDict( + { + 'window_begin': _window_begin, + 'window_end': _window_end, + 'PREFIX': f"{self.task_config.RUN}.t{self.task_config.cyc:02d}z.", + } + ) + + # task_config is everything that this task should need + self.task_config = AttrDict(**self.task_config, **local_dict) + + @logit(logger) + def initialize(self) -> None: + """ + """ + logger.info("running init") + + @logit(logger) + def execute(self) -> None: + """ + """ + logger.info("running execute") + + @logit(logger) + def finalize(self) -> None: + """ + """ + logger.info("running finalize")