Skip to content

Commit

Permalink
Add rocoto sh tag, script to check netcdf file and apply this to ch…
Browse files Browse the repository at this point in the history
…eck ocean output (#2484)

This PR:
- adds a Rocoto dependency tag that executes a shell command. The return
code of the shell expression serves as a dependency check
- adds a script that executes `ncdump` on a netCDF file. If the file is
a valid netCDF file, the return code is 0, else it is non-zero
- combines the above 2 to use as a dependency check for MOM6 output. If
the model is still in the process of writing out the ocean output, the
rocoto will execute the shell script and gather the return code.

This PR also:
- changes permissions on some `ush/` scripts that did not have
executable permissions.

Resolves #2328
  • Loading branch information
aerorahul authored Apr 17, 2024
1 parent b0c2a30 commit c679d94
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 3 deletions.
Empty file modified ush/bash_utils.sh
100644 → 100755
Empty file.
15 changes: 15 additions & 0 deletions ush/check_netcdf.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#! /usr/bin/env bash

# shellcheck disable=SC2155,SC2312
HOMEgfs=$(cd "$(dirname "$(readlink -f -n "${BASH_SOURCE[0]}" )" )/.." && pwd -P)
declare -rx HOMEgfs

source "${HOMEgfs}/ush/load_fv3gfs_modules.sh" 1>/dev/null 2>&1

ncfile=${1?}

ncdump -h "${ncfile}"
rc=$?
# If there is no error, rc=0, else rc!=0

exit "${rc}"
Empty file modified ush/file_utils.sh
100644 → 100755
Empty file.
Empty file modified ush/jjob_header.sh
100644 → 100755
Empty file.
Empty file modified ush/preamble.sh
100644 → 100755
Empty file.
8 changes: 7 additions & 1 deletion workflow/rocoto/gefs_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,13 @@ def _atmosoceaniceprod(self, component: str):
data = f'{history_path}/{history_file_tmpl}'
dep_dict = {'type': 'data', 'data': data, 'age': 120}
deps.append(rocoto.add_dependency(dep_dict))
dependencies = rocoto.create_dependency(dep=deps)
if component in ['ocean']:
command = f"{self.HOMEgfs}/ush/check_netcdf.sh {history_path}/{history_file_tmpl}"
dep_dict = {'type': 'sh', 'command': command}
deps.append(rocoto.add_dependency(dep_dict))
dependencies = rocoto.create_dependency(dep=deps, dep_condition='and')
else:
dependencies = rocoto.create_dependency(dep=deps)

postenvars = self.envars.copy()
postenvar_dict = {'ENSMEM': '#member#',
Expand Down
9 changes: 8 additions & 1 deletion workflow/rocoto/gfs_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,14 @@ def _atmosoceaniceprod(self, component: str):
data = f'{history_path}/{history_file_tmpl}'
dep_dict = {'type': 'data', 'data': data, 'age': 120}
deps.append(rocoto.add_dependency(dep_dict))
dependencies = rocoto.create_dependency(dep=deps)
if component in ['ocean']:
command = f"{self.HOMEgfs}/ush/check_netcdf.sh {history_path}/{history_file_tmpl}"
dep_dict = {'type': 'sh', 'command': command}
deps.append(rocoto.add_dependency(dep_dict))
dependencies = rocoto.create_dependency(dep=deps, dep_condition='and')
else:
dependencies = rocoto.create_dependency(dep=deps)

cycledef = 'gdas_half,gdas' if self.cdump in ['gdas'] else self.cdump
resources = self.get_resource(component_dict['config'])

Expand Down
29 changes: 28 additions & 1 deletion workflow/rocoto/rocoto.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ABOUT:
Helper module to create tasks, metatasks, and dependencies for Rocoto
Rocoto documentation is available at https://christopherwharrop.github.io/rocoto
'''

__all__ = ['create_task',
Expand Down Expand Up @@ -182,7 +183,8 @@ def add_dependency(dep_dict: Dict[str, Any]) -> str:
'data': _add_data_tag,
'cycleexist': _add_cycle_tag,
'streq': _add_streq_tag,
'strneq': _add_streq_tag}
'strneq': _add_streq_tag,
'sh': _add_sh_tag}

dep_condition = dep_dict.get('condition', None)
dep_type = dep_dict.get('type', None)
Expand Down Expand Up @@ -333,6 +335,31 @@ def _add_streq_tag(dep_dict: Dict[str, Any]) -> str:
return string


def _add_sh_tag(dep_dict: Dict[str, Any]) -> str:
"""
create a simple shell execution tag
:param: dep_dict: shell command to execute
:type dep_dict: dict
:return: Rocoto simple shell execution dependency
:rtype: str
"""

shell = dep_dict.get('shell', '/bin/sh')
command = dep_dict.get('command', 'echo "Hello World"')

if '@' in command:
offset_string_b = f'<cyclestr>'
offset_string_e = '</cyclestr>'
else:
offset_string_b = ''
offset_string_e = ''
cmd = f'{offset_string_b}{command}{offset_string_e}'

string = f'<sh shell="{shell}">{cmd}</sh>'

return string


def _traverse(o, tree_types=(list, tuple)):
"""
Traverse through a list of lists or tuples and yield the value
Expand Down

0 comments on commit c679d94

Please sign in to comment.