From 8c11eeb8556619e8db4e0efb6394ce5a2c1aae0f Mon Sep 17 00:00:00 2001 From: "Henry R. Winterbottom" <49202169+HenryWinterbottom-NOAA@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:31:32 -0700 Subject: [PATCH] Adds FBWINDS support to global-workflow (#2082) This PR addresses issue #1221. The following was accomplished: - A new Rocoto job is added; `jobs/rocoto/fbwinds.sh`; - `workflow/applications/gfs_cycled.py` is updated to include the `fbwinds` task; - `workflow/applications/gfs_forecast_only.py` is updated to include the `fbwinds` task; - A new function is added to `workflow/rocoto/gfs_tasks.py`, `fbwinds` is added as new GFS (only) task; - `workflow/rocoto/tasks.py` is updated to include the `fbwinds` task. Resolves #1221 --- jobs/rocoto/fbwinds.sh | 17 ++++++++++++++ workflow/applications/gfs_cycled.py | 1 + workflow/applications/gfs_forecast_only.py | 1 + workflow/rocoto/gfs_tasks.py | 26 ++++++++++++++++++++++ workflow/rocoto/rocoto.py | 6 ++++- workflow/rocoto/tasks.py | 2 +- 6 files changed, 51 insertions(+), 2 deletions(-) create mode 100755 jobs/rocoto/fbwinds.sh diff --git a/jobs/rocoto/fbwinds.sh b/jobs/rocoto/fbwinds.sh new file mode 100755 index 0000000000..078e71586f --- /dev/null +++ b/jobs/rocoto/fbwinds.sh @@ -0,0 +1,17 @@ +#! /usr/bin/env bash + +source "${HOMEgfs}/ush/preamble.sh" + +############################################################### +. "${HOMEgfs}/ush/load_fv3gfs_modules.sh" +status=$? +if (( status != 0 )); then exit "${status}"; fi + +export job="fbwinds" +export jobid="${job}.$$" + +# Execute the JJOB +"${HOMEgfs}/jobs/JGFS_ATMOS_FBWINDS" + +status=$? +exit "${status}" diff --git a/workflow/applications/gfs_cycled.py b/workflow/applications/gfs_cycled.py index dbb945225c..2438a8244e 100644 --- a/workflow/applications/gfs_cycled.py +++ b/workflow/applications/gfs_cycled.py @@ -235,6 +235,7 @@ def get_task_names(self): if self.do_awips: gfs_tasks += ['awips'] + gfs_tasks += ['fbwinds'] if self.do_npoess: gfs_tasks += ['npoess'] diff --git a/workflow/applications/gfs_forecast_only.py b/workflow/applications/gfs_forecast_only.py index c1141c8eb6..01d31b08ca 100644 --- a/workflow/applications/gfs_forecast_only.py +++ b/workflow/applications/gfs_forecast_only.py @@ -120,6 +120,7 @@ def get_task_names(self): if self.do_awips: tasks += ['awips'] + tasks += ['fbwinds'] if self.do_wafs: tasks += ['wafs', 'wafsgcip', 'wafsgrib2', 'wafsgrib20p25', 'wafsblending', 'wafsblending0p25'] diff --git a/workflow/rocoto/gfs_tasks.py b/workflow/rocoto/gfs_tasks.py index b4635f4a04..a842b4704b 100644 --- a/workflow/rocoto/gfs_tasks.py +++ b/workflow/rocoto/gfs_tasks.py @@ -796,6 +796,32 @@ def postsnd(self): return task + def fbwinds(self): + + atmos_prod_path = self._template_to_rocoto_cycstring(self._base["COM_ATMOS_GRIB_GRID_TMPL"], {'RUN': self.cdump, 'GRID': '0p25'}) + deps = [] + data = f'{atmos_prod_path}/{self.cdump}.t@Hz.pgrb2.0p25.f006' + dep_dict = {'type': 'data', 'data': data, 'age': 120} + deps.append(rocoto.add_dependency(dep_dict)) + data = f'{atmos_prod_path}/{self.cdump}.t@Hz.pgrb2.0p25.f012' + dep_dict = {'type': 'data', 'data': data, 'age': 120} + deps.append(rocoto.add_dependency(dep_dict)) + data = f'{atmos_prod_path}/{self.cdump}.t@Hz.pgrb2.0p25.f024' + dep_dict = {'type': 'data', 'data': data, 'age': 120} + deps.append(rocoto.add_dependency(dep_dict)) + dependencies = rocoto.create_dependency(dep=deps, dep_condition='and') + + resources = self.get_resource('awips') + + # TODO: It would be better to use task dependencies on the + # individual post jobs rather than data dependencies to avoid + # prematurely starting with partial files. Unfortunately, the + # ability to "group" post would make this more convoluted than + # it should be and not worth the complexity. + task = create_wf_task('fbwinds', resources, cdump=self.cdump, envar=self.envars, dependency=dependencies) + + return task + def awips(self): def _get_awipsgroups(cdump, config): diff --git a/workflow/rocoto/rocoto.py b/workflow/rocoto/rocoto.py index b3f88f01d3..153ff71475 100644 --- a/workflow/rocoto/rocoto.py +++ b/workflow/rocoto/rocoto.py @@ -193,6 +193,7 @@ def _add_data_tag(dep_dict: Dict[str, Any]) -> str: dep_type = dep_dict.get('type', None) dep_data = dep_dict.get('data', None) dep_offset = dep_dict.get('offset', None) + dep_age = dep_dict.get('age', None) if dep_data is None: msg = f'a data value is necessary for {dep_type} dependency' @@ -206,7 +207,10 @@ def _add_data_tag(dep_dict: Dict[str, Any]) -> str: assert len(dep_data) == len(dep_offset) - strings = [''] + if dep_age is None: + strings = [''] + else: + strings = [f''] for data, offset in zip(dep_data, dep_offset): if '@' in data: offset_str = '' if offset in [None, ''] else f' offset="{offset}"' diff --git a/workflow/rocoto/tasks.py b/workflow/rocoto/tasks.py index 21f8af85bb..dea351ac12 100644 --- a/workflow/rocoto/tasks.py +++ b/workflow/rocoto/tasks.py @@ -22,7 +22,7 @@ class Tasks: 'fcst', 'post', 'ocnpost', 'verfozn', 'verfrad', 'vminmon', 'metp', 'tracker', 'genesis', 'genesis_fsu', - 'postsnd', 'awips', 'gempak', + 'postsnd', 'awips', 'fbwinds', 'gempak', 'waveawipsbulls', 'waveawipsgridded', 'wavegempak', 'waveinit', 'wavepostbndpnt', 'wavepostbndpntbll', 'wavepostpnt', 'wavepostsbs', 'waveprep', 'npoess']