diff --git a/pyproject.toml b/pyproject.toml index 07f1a298..7b706a76 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools", "setuptools-scm", "cython"] +requires = ["setuptools", "setuptools-scm"] build-backend = "setuptools.build_meta" [project] @@ -24,12 +24,6 @@ dependencies = [ "pyyaml", "xarray[io]", - # Workflow Planner - "jinja2", - "networkx", - "printree", - "pyvis", - # Numerics "numexpr", "numpy", @@ -67,13 +61,11 @@ generate-rupture-propagation = "workflow.scripts.generate_rupture_propagation:ap copy-domain-parameters = "workflow.scripts.copy_velocity_model_parameters:app" create-e3d-par = "workflow.scripts.create_e3d_par:app" generate-stoch = "workflow.scripts.generate_stoch:app" -merge-ts = "workflow.scripts.merge_ts:app" hf-sim = "workflow.scripts.hf_sim:app" bb-sim = "workflow.scripts.bb_sim:app" im-calc = "workflow.scripts.im_calc:app" check-srf = "workflow.scripts.check_srf:app" check-domain = "workflow.scripts.check_domain:app" -plan-workflow = "workflow.scripts.plan_workflow:app" gcmt-auto-simulate = "workflow.scripts.gcmt_auto_simulate:app" import-realisation = "workflow.scripts.import_realisation:app" lf-to-xarray = "workflow.scripts.lf_to_xarray:app" diff --git a/setup.py b/setup.py deleted file mode 100644 index 9a458991..00000000 --- a/setup.py +++ /dev/null @@ -1,14 +0,0 @@ -from Cython.Build import cythonize -from setuptools import Extension, setup - -extensions = [ - Extension( - "workflow.scripts.merge_ts_loop", - ["workflow/scripts/merge_ts_loop.pyx"], - ), -] - -setup( - name="workflow", - ext_modules=cythonize(extensions), -) diff --git a/tests/test_cli.py b/tests/test_cli.py index 066f8956..4b466473 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -22,7 +22,6 @@ import_realisation, lf_to_xarray, nshm2022_to_realisation, - plan_workflow, realisation_to_srf, ) @@ -47,7 +46,6 @@ im_calc, import_realisation, nshm2022_to_realisation, - plan_workflow, realisation_to_srf, ], ) diff --git a/wiki/Stages.md b/wiki/Stages.md index af14ecaf..49a54d40 100644 --- a/wiki/Stages.md +++ b/wiki/Stages.md @@ -219,20 +219,6 @@ Can be run in the cybershake container. Can also be run from your own computer u See the output of `create-e3d-par --help` or [create_e3d_par.py](https://github.com/ucgmsim/workflow/blob/pegasus/workflow/scripts/create_e3d_par.py). See our description of the [EMOD3D Parameters](https://wiki.canterbury.ac.nz/pages/viewpage.action?pageId=100794983) for documentation on the EMOD3D parameter file format. -## Merge Timeslices -### Description -Merge the output timeslice files of EMOD3D. -### Inputs -1. A directory containing EMOD3D timeslice files. -### Outputs -1. A merged output timeslice file. -### Environment -Can be run in the cybershake container. Can also be run from your own computer using the `merge-ts` command which is installed after running `pip install workflow@git+https://github.com/ucgmsim/workflow`. -### Usage -`merge_ts XYTS_DIRECTORY XYTS_DIRECTORY/output.e3d` -### For More Help -See the output of `merge-ts --help` or [merge_ts.py](https://github.com/ucgmsim/workflow/blob/pegasus/merge_ts/merge_ts.py). - ## Create Simulation Video ### Description Create a simulation video from the low frequency simulation output. diff --git a/workflow/__init__.py b/workflow/__init__.py index 26c75bf3..a8e2b769 100644 --- a/workflow/__init__.py +++ b/workflow/__init__.py @@ -70,7 +70,6 @@ | EMOD3D | See below. | | High Frequency Simulation | `workflow.scripts.hf_sim` | | Broadband Simulation | `workflow.scripts.bb_sim` | -| Merge Timeslices | `merge_ts.merge_ts` | | Create Simulation Video | `workflow.scripts.plot_ts` | | Intensity Measure Calculation | `workflow.scripts.im_calc` | diff --git a/workflow/scripts/merge_ts.py b/workflow/scripts/merge_ts.py deleted file mode 100644 index 3e37f82e..00000000 --- a/workflow/scripts/merge_ts.py +++ /dev/null @@ -1,288 +0,0 @@ -#!/usr/bin/env python3 -"""Merge EMOD3D Timeslices. - -Description ------------ -Merge the output timeslice files of EMOD3D. - -Inputs ------- -1. A directory containing EMOD3D timeslice files. - -Outputs -------- -1. A merged output timeslice file. - -Environment ------------ -Can be run in the cybershake container. Can also be run from your own computer using the `merge-ts` command which is installed after running `pip install workflow@git+https://github.com/ucgmsim/workflow`. - -Usage ------ -`merge_ts XYTS_DIRECTORY XYTS_DIRECTORY/output.e3d` - -For More Help -------------- -See the output of `merge-ts --help`. -""" - -import os -from pathlib import Path -from typing import Annotated - -import numpy as np -import tqdm -import typer -import xarray as xr - -from qcore import cli, coordinates, xyts -from workflow.scripts import merge_ts_loop # type: ignore - -app = typer.Typer() - - -def merge_ts_xyts( - component_xyts_directory: Annotated[ - Path, - typer.Argument( - dir_okay=True, - file_okay=False, - exists=True, - readable=True, - ), - ], - output: Annotated[ - Path, - typer.Argument(dir_okay=False, writable=True), - ], - glob_pattern: str = "*xyts-*.e3d", -) -> None: - """Merge XYTS files. - - Parameters - ---------- - component_xyts_directory : Path - The input xyts directory containing files to merge. - output : Path - The output xyts file. - glob_pattern : str, optional - Set a custom glob pattern for merging the xyts files, by default "*xyts-*.e3d". - """ - component_xyts_files = sorted( - [ - xyts.XYTSFile( - xyts_file_path, proc_local_file=True, meta_only=True, round_dt=False - ) - for xyts_file_path in component_xyts_directory.glob(glob_pattern) - ], - key=lambda xyts_file: (xyts_file.y0, xyts_file.x0), - ) - top_left = component_xyts_files[0] - merged_ny = top_left.ny - merged_nt = top_left.nt - - xyts_proc_header_size = 72 - - xyts_file_descriptors: list[int] = [] - for xyts_file in component_xyts_files: - xyts_file_descriptor = os.open(xyts_file.xyts_path, os.O_RDONLY) - # Skip the header for each file descriptor - head_skip = os.lseek(xyts_file_descriptor, xyts_proc_header_size, os.SEEK_SET) - if head_skip != xyts_proc_header_size: - raise ValueError( - f"Failed to skip header for {xyts_file.xyts_path} at {head_skip}" - ) - xyts_file_descriptors.append(xyts_file_descriptor) - - # If output doesn't exist when we os.open it, we'll get an error. - output.touch() - merged_fd = os.open(output, os.O_WRONLY) - # The following type: ignores can be removed once qcore updates - xyts_header: bytes = ( - top_left.x0.tobytes() # type: ignore - + top_left.y0.tobytes() # type: ignore - + top_left.z0.tobytes() # type: ignore - + top_left.t0.tobytes() # type: ignore - + top_left.nx.tobytes() # type: ignore - + top_left.ny.tobytes() # type: ignore - + top_left.nz.tobytes() # type: ignore - + top_left.nt.tobytes() # type: ignore - + top_left.dx.tobytes() # type: ignore - + top_left.dy.tobytes() # type: ignore - + top_left.hh.tobytes() # type: ignore - + top_left.dt.tobytes() # type: ignore - + top_left.mrot.tobytes() # type: ignore - + top_left.mlat.tobytes() # type: ignore - + top_left.mlon.tobytes() # type: ignore - ) - - written = os.write(merged_fd, xyts_header) - if written != len(xyts_header): - raise ValueError( - f"Failed to write header for {output} at {written} bytes written" - ) - - merge_ts_loop.merge_fds( - merged_fd, - xyts_file_descriptors, - merged_nt, - merged_ny, - [f.local_nx for f in component_xyts_files], - [f.local_ny for f in component_xyts_files], - [f.y0 for f in component_xyts_files], - ) - - for xyts_file_descriptor in xyts_file_descriptors: - os.close(xyts_file_descriptor) - - os.close(merged_fd) - - -@cli.from_docstring(app, name="hdf5") # type: ignore -def merge_ts_hdf5( - component_xyts_directory: Annotated[ - Path, - typer.Argument( - dir_okay=True, - file_okay=False, - exists=True, - readable=True, - ), - ], - output: Annotated[ - Path, - typer.Argument(dir_okay=False, writable=True), - ], - glob_pattern: str = "*xyts-*.e3d", - complevel: int = 4, -) -> None: - """Merge XYTS files. - - Parameters - ---------- - component_xyts_directory : Path - The input xyts directory containing files to merge. - output : Path - The output xyts file. - glob_pattern : str, optional - Set a custom glob pattern for merging the xyts files, by default "*xyts-*.e3d". - complevel : int, optional - Set the compression level for the output HDF5 file. Range - between 1-9 (9 being the highest level of compression). - Defaults to 4. - """ - component_xyts_files = sorted( - [ - xyts.XYTSFile( - xyts_file_path, proc_local_file=True, meta_only=True, round_dt=False - ) - for xyts_file_path in component_xyts_directory.glob(glob_pattern) - ], - key=lambda xyts_file: (xyts_file.y0, xyts_file.x0), - ) - top_left = component_xyts_files[0] - nt = top_left.nt - nx = top_left.nx - ny = top_left.ny - components = 3 - - xyts_proc_header_size = 72 - - waveform_data = np.empty((nt, ny, nx), dtype=np.uint16) - for xyts_file in tqdm.tqdm(component_xyts_files, unit="files"): - x0 = xyts_file.x0 - y0 = xyts_file.y0 - x1 = x0 + xyts_file.local_nx - y1 = y0 + xyts_file.local_ny - data = np.fromfile( - xyts_file.xyts_path, dtype=np.float32, offset=xyts_proc_header_size - ).reshape((nt, components, xyts_file.local_ny, xyts_file.local_nx)) - magnitude = np.linalg.norm(data, axis=1) / 0.1 - np.round(magnitude, out=magnitude) - waveform_data[:, y0:y1, x0:x1] = magnitude.astype(np.uint16) - - proj = coordinates.SphericalProjection( - mlon=top_left.mlon, mlat=top_left.mlat, mrot=top_left.mrot - ) - dx = top_left.hh - dt = top_left.dt - y, x = np.meshgrid( - np.arange(ny, dtype=np.float64), np.arange(nx, dtype=np.float64), indexing="ij" - ) - lat, lon = proj.inverse(x.flatten(), y.flatten()).T - lat = lat.reshape(y.shape) - lon = lon.reshape(y.shape) - time = np.arange(nt) * dt - dset = xr.Dataset( - { - "waveform": (("time", "y", "x"), waveform_data), - }, - coords={ - "time": ("time", time), - "y": ("y", np.arange(ny)), - "x": ("x", np.arange(nx)), - "latitude": (("y", "x"), lat), - "longitude": (("y", "x"), lon), - }, - attrs={ - "dx": dx, - "dy": dx, - "dt": dt, - "mlon": top_left.mlon, - "mlat": top_left.mlat, - "mrot": top_left.mrot, - }, - ) - - dset["waveform"].attrs.update( - { - "scale_factor": 0.1, - "add_offset": 0.0, - "units": "cm/s", - "_FillValue": -9999, - } - ) - - dset.to_netcdf( - output, - engine="h5netcdf", - encoding={ - "waveform": { - "dtype": "int16", - "compression": "zlib", - "complevel": complevel, - "shuffle": True, - } - }, - ) - - -@cli.from_docstring(app, name="xyts") # type: ignore -def merge_ts( - component_xyts_directory: Annotated[ - Path, - typer.Argument( - dir_okay=True, - file_okay=False, - exists=True, - readable=True, - ), - ], - output: Annotated[ - Path, - typer.Argument(dir_okay=False, writable=True), - ], - glob_pattern: str = "*xyts-*.e3d", -) -> None: - """Merge XYTS files. - - Parameters - ---------- - component_xyts_directory : Path - The input xyts directory containing files to merge. - output : Path - The output xyts file. - glob_pattern : str, optional - Set a custom glob pattern for merging the xyts files, by default "*xyts-*.e3d". - """ - merge_ts_xyts(component_xyts_directory, output, glob_pattern) diff --git a/workflow/scripts/merge_ts_loop.pyx b/workflow/scripts/merge_ts_loop.pyx deleted file mode 100644 index d83a57c3..00000000 --- a/workflow/scripts/merge_ts_loop.pyx +++ /dev/null @@ -1,79 +0,0 @@ -import os - -import cython - -from libc.stdlib cimport free, malloc - -cdef extern from "sys/types.h": - ctypedef long off_t -cdef extern from "sys/sendfile.h": - ssize_t sendfile(int out_fd, int in_fd, off_t * offset, size_t count) - -def merge_fds( - int merged_fd, _component_xyts_files, int merged_nt, int merged_ny, _local_nxs, _local_nys, _y0s -): - ''' Merge a list of XYTS files by copying their values in order. - - To merge the files we copy the velocity values in each component, for each - timestep, in the order they would fit in the merged domain. That is if four - files tile the domain like so: - - ┌───────────┬──────────┐ - │***********│##########│ - │!!!!!!!!!!!│++++++++++│ - │ f1 │ f2 │ - │ │ │ - ├───────────┼──────────┤ - │$$$$$$$$$$$│%%%%%%%%%%│ - │ │ │ - │ f3 │ f4 │ - │ │ │ - │ │ │ - └───────────┴──────────┘ - - Then they are concatenated in the output domain as: - - ***********##########!!!!!!!!!!!++++++++++ ... $$$$$$$$$$$%%%%%%%%%% - - It is assumed _component_xyts_files is a list of xyts files sorted by their - top left corner. - ''' - cdef int float_size, cur_timestep, cur_component, cur_y, i, y0, local_ny, local_nx, xyts_fd, n_files - cdef int *component_xyts_files, *local_nxs, *local_nys, *y0s - - n_files = len(_component_xyts_files) - - # The lists _component_xyts_files, ... are CPython lists. - # If we access these inside our copying loop everything becomes very slow - # because we need to go to the Python interpreter. So we first copy each - # list into an equivalent C list. - component_xyts_files = malloc(len(_component_xyts_files) * cython.sizeof(int)) - local_nxs = malloc(len(_local_nxs) * cython.sizeof(int)) - local_nys = malloc(len(_local_nys) * cython.sizeof(int)) - y0s = malloc(len(_y0s) * cython.sizeof(int)) - # NOTE: we cannot use memcpy() here because CPython lists are not continuous - # chunks of memory as they are in C. - for i in range(len(_component_xyts_files)): - component_xyts_files[i] = _component_xyts_files[i] - local_nxs[i] = _local_nxs[i] - local_nys[i] = _local_nys[i] - y0s[i] = _y0s[i] - for cur_timestep in range(merged_nt): - for cur_component in range(3): # for each component - for cur_y in range(merged_ny): - for i in range(n_files): - y0 = y0s[i] - local_ny = local_nys[i] - local_nx = local_nxs[i] - xyts_fd = component_xyts_files[i] - if y0 > cur_y: - break - if cur_y >= y0 + local_ny: - continue - # By passing NULL as the offset, sendfile() will read from - # the current position in xyts_fd - sendfile(merged_fd, xyts_fd, NULL, local_nx * 4) - free(component_xyts_files) - free(local_nxs) - free(local_nys) - free(y0s) diff --git a/workflow/scripts/plan_workflow.py b/workflow/scripts/plan_workflow.py deleted file mode 100644 index 27df5fb5..00000000 --- a/workflow/scripts/plan_workflow.py +++ /dev/null @@ -1,825 +0,0 @@ -"""Create a Cylc workflow plan from a list of goals and stages to exclude. - -This is the starting point for most workflow usages, and can be used -to generate a base Cylc workflow to modify and extend. -""" - -import dataclasses -import tempfile -from collections.abc import Iterable -from enum import StrEnum -from pathlib import Path, PurePath -from typing import Annotated, Any, Optional, Self - -import jinja2 -import networkx as nx -import printree -import tqdm -import typer -from pyvis.network import Network - -from qcore import cli -from workflow import realisations -from workflow.defaults import DefaultsVersion - -app = typer.Typer() - - -class WorkflowTarget(StrEnum): - """Enumeration of possible workflow targets.""" - - NeSI = "nesi" - Hypocentre = "hypocentre" - - -class StageIdentifier(StrEnum): - """Valid stage identifier in the workflow plan.""" - - CopyInput = "copy_input" - Archive = "archive" - GCMTToRealisation = "gcmt_to_realisation" - DomainGeneration = "generate_velocity_model_parameters" - VelocityModelGeneration = "generate_velocity_model" - StationSelection = "generate_station_coordinates" - ModelCoordinates = "write_model_coordinates" - SRFGeneration = "realisation_to_srf" - CheckSRF = "check_srf" - CopyDomainParameters = "copy_domain_parameters" - EMOD3DParameters = "create_e3d_par" - CheckDomain = "check_domain" - StochGeneration = "generate_stoch" - HighFrequency = "hf_sim" - LowFrequency = "emod3d" - Broadband = "bb_sim" - IntensityMeasureCalculation = "im_calc" - MergeTimeslices = "merge_ts" - NSHMToRealisation = "nshm_to_realisation" - - -class Source(StrEnum): - """Realisation source options.""" - - GCMT = "gcmt" - NSHM = "nshm" - - -class GroupIdentifier(StrEnum): - """Group identifiers to use to bulk target or exclude in workflow planning.""" - - Preprocessing = "preprocessing" - """Alias for all preprocessing stages.""" - HighFrequency = "high_frequency" - """Alias for the high frequency workflow.""" - LowFrequency = "low_frequency" - """Alias for the low frequency workflow.""" - Domain = "domain" - - -GROUP_STAGES = { - GroupIdentifier.Preprocessing: { - StageIdentifier.DomainGeneration, - StageIdentifier.VelocityModelGeneration, - StageIdentifier.StationSelection, - StageIdentifier.ModelCoordinates, - StageIdentifier.SRFGeneration, - StageIdentifier.EMOD3DParameters, - StageIdentifier.NSHMToRealisation, - StageIdentifier.GCMTToRealisation, - StageIdentifier.StochGeneration, - StageIdentifier.CopyDomainParameters, - }, - GroupIdentifier.HighFrequency: { - StageIdentifier.HighFrequency, - }, - GroupIdentifier.LowFrequency: {StageIdentifier.LowFrequency}, - GroupIdentifier.Domain: { - StageIdentifier.VelocityModelGeneration, - StageIdentifier.StationSelection, - StageIdentifier.DomainGeneration, - StageIdentifier.CopyDomainParameters, - StageIdentifier.ModelCoordinates, - }, -} - -GROUP_GOALS = { - GroupIdentifier.Preprocessing: { - StageIdentifier.EMOD3DParameters, - StageIdentifier.StochGeneration, - }, - GroupIdentifier.LowFrequency: {StageIdentifier.LowFrequency}, - GroupIdentifier.HighFrequency: {StageIdentifier.HighFrequency}, - GroupIdentifier.Domain: { - StageIdentifier.VelocityModelGeneration, - StageIdentifier.StationSelection, - StageIdentifier.ModelCoordinates, - StageIdentifier.CopyDomainParameters, - }, -} - -CONTAINER_PATHS = { - WorkflowTarget.NeSI: Path("/nesi/nobackup/nesi00213/containers/runner_latest.sif"), - WorkflowTarget.Hypocentre: Path("/mnt/hypo_scratch/containers/runner_latest.sif"), -} - -EMOD3D_PATHS = { - WorkflowTarget.NeSI: Path( - "/nesi/project/nesi00213/opt/EMOD3D_cylc/tools/emod3d-mpi_v3.0.8" - ), - WorkflowTarget.Hypocentre: Path("/mnt/hypo_scratch/EMOD3D/tools/emod3d-mpi_v3.0.8"), -} - - -@dataclasses.dataclass -class Stage: - """Representation of a workflow stage in the output Cylc file.""" - - identifier: StageIdentifier - """The stage identifier.""" - event: str | None - """The event the stage is running for.""" - sample: int | None - """The sample number of the realisation.""" - - @property - def parent(self) -> Self: # numpydoc ignore=RT01 - """Stage: the parent stage of this stage.""" - return dataclasses.replace(self, sample=None) - - @property - def directory(self) -> PurePath | None: # numpydoc ignore=RT01 - """PurePath: the directory for this stage.""" - if not self.event: - return None - directory = self.event - if self.sample: - directory += f"_{self.sample}" - return PurePath(directory) - - @property - def outputs(self) -> set[PurePath]: # numpydoc ignore=RT01 - """set[PurePath]: the outputs for this stage.""" - directory = self.directory - if not directory: - return set() - return {directory / output for output in stage_outputs(self.identifier)} - - @property - def inputs(self) -> set[PurePath]: # numpydoc ignore=RT01 - """set[PurePath]: the inputs for this stage.""" - directory = self.directory - if not self.event or not directory: - return set() - workflow_plan = realisation_workflow(self.event, self.sample) - try: - input_stages = list(workflow_plan.predecessors(self)) - inputs = set() - for stage in input_stages: - inputs |= stage.outputs - return inputs - except nx.NetworkXError: - return set() - - def __hash__(self) -> int: - """Hash the stage identifier, event and sample number. - - Returns - ------- - int - The hash of the stage. - """ - return hash((self.identifier, self.event, self.sample)) - - def __str__(self) -> str: - """The string representation of the stage. - - Returns - ------- - str - The string representation of the stage.""" - _str = str(self.identifier) - if self.event: - _str += f"_{self.event}" - if self.sample: - _str += f"_{self.sample}" - return _str - - -def stage_config_outputs(identifier: StageIdentifier) -> set[str]: - """Get the realisation configuration outputs for a given stage. - - Parameters - ---------- - identifier : StageIdentifier - The stage to get outputs for. - - - Returns - ------- - set[str] - The output config sections for this stage. - """ - output_dictionary = { - StageIdentifier.NSHMToRealisation: { - realisations.SourceConfig._config_key, - realisations.RupturePropagationConfig._config_key, - realisations.RealisationMetadata._config_key, - }, - StageIdentifier.GCMTToRealisation: { - realisations.SourceConfig._config_key, - realisations.RupturePropagationConfig._config_key, - realisations.RealisationMetadata._config_key, - }, - StageIdentifier.EMOD3DParameters: {realisations.EMOD3DParameters._config_key}, - StageIdentifier.Broadband: {realisations.BroadbandParameters._config_key}, - StageIdentifier.VelocityModelGeneration: { - realisations.VelocityModelParameters._config_key - }, - StageIdentifier.HighFrequency: {realisations.HFConfig._config_key}, - StageIdentifier.IntensityMeasureCalculation: { - realisations.IntensityMeasureCalculationParameters._config_key - }, - StageIdentifier.CopyDomainParameters: { - realisations.VelocityModelParameters._config_key, - realisations.DomainParameters._config_key, - }, - StageIdentifier.DomainGeneration: { - realisations.VelocityModelParameters._config_key, - realisations.DomainParameters._config_key, - }, - StageIdentifier.SRFGeneration: {realisations.SRFConfig._config_key}, - StageIdentifier.StochGeneration: {realisations.HFConfig._config_key}, - } - return output_dictionary.get(identifier, set()) - - -def stage_outputs( - identifier: StageIdentifier, include_config_outputs: bool = True -) -> set[PurePath]: - """Return a set of stage outputs for the given stage identifier. - - Parameters - ---------- - identifier : StageIdentifier - The stage identifier to get outputs for. - include_config_outputs : bool, optional - Whether to include configuration outputs (default is True). - - Returns - ------- - set[PurePath] - A set of output paths for the stage. - """ - output_dictionary = { - StageIdentifier.SRFGeneration: { - PurePath("realisation.srf"), - }, - StageIdentifier.ModelCoordinates: { - PurePath("model") / "model_params", - PurePath("model") / "grid_file", - }, - StageIdentifier.StationSelection: { - PurePath("stations") / "stations.ll", - PurePath("stations") / "stations.statcords", - }, - StageIdentifier.VelocityModelGeneration: { - PurePath("Velocity_Model") / "rho3dfile.d", - PurePath("Velocity_Model") / "vp3dfile.p", - PurePath("Velocity_Model") / "vs3dfile.s", - PurePath("Velocity_Model") / "in_basin_mask.b", - }, - StageIdentifier.EMOD3DParameters: { - PurePath("LF"), - PurePath("LF") / "e3d.par", - }, - StageIdentifier.LowFrequency: {PurePath("LF")}, - StageIdentifier.StochGeneration: { - PurePath("realisation.stoch"), - }, - StageIdentifier.HighFrequency: {PurePath("realisation.hf")}, - StageIdentifier.Broadband: {PurePath("realisation.bb")}, - StageIdentifier.IntensityMeasureCalculation: { - PurePath("intensity_measures.parquet") - }, - StageIdentifier.MergeTimeslices: {PurePath("LF") / "OutBin" / "output.e3d"}, - } - file_outputs = output_dictionary.get(identifier, set()) - if include_config_outputs: - for output in stage_config_outputs(identifier): - file_outputs.add(PurePath("realisation.json") / output) - - return file_outputs - - -def realisation_workflow(event: str, sample: int | None) -> nx.DiGraph: - """Add a realisation to a workflow plan. - - Adds all stages for the realisation to run, and links to event - stages for shared resources (i.e. the velocity model). - - Parameters - ---------- - event : str - The event to add. - sample : int or None - The sample number (or None, if the original event). - - Returns - ------- - nx.DiGraph - The workflow plan with the added realisation. - """ - requires_base = [ - StageIdentifier.SRFGeneration, - StageIdentifier.StochGeneration, - StageIdentifier.CheckSRF, - StageIdentifier.VelocityModelGeneration, - StageIdentifier.DomainGeneration, - StageIdentifier.EMOD3DParameters, - StageIdentifier.IntensityMeasureCalculation, - StageIdentifier.HighFrequency, - StageIdentifier.Broadband, - ] - requires_domain = [ - StageIdentifier.ModelCoordinates, - StageIdentifier.Broadband, - StageIdentifier.StationSelection, - StageIdentifier.CheckDomain, - StageIdentifier.CopyDomainParameters, - StageIdentifier.VelocityModelGeneration, - StageIdentifier.HighFrequency, - StageIdentifier.EMOD3DParameters, - ] - workflow_plan = nx.from_dict_of_lists( - { - Stage(StageIdentifier.NSHMToRealisation, event, sample): [ - Stage(id, event, sample) for id in requires_base - ], - Stage(StageIdentifier.GCMTToRealisation, event, sample): [ - Stage(id, event, sample) for id in requires_base - ], - Stage(StageIdentifier.SRFGeneration, event, sample): [ - Stage(StageIdentifier.CheckSRF, event, sample), - Stage(StageIdentifier.LowFrequency, event, sample), - ], - Stage(StageIdentifier.CheckSRF, event, sample): [ - Stage(StageIdentifier.StochGeneration, event, sample), - Stage(StageIdentifier.EMOD3DParameters, event, sample), - ], - Stage(StageIdentifier.VelocityModelGeneration, event, None): [ - Stage(StageIdentifier.EMOD3DParameters, event, sample), - Stage(StageIdentifier.HighFrequency, event, sample), - Stage( - StageIdentifier.Broadband, event, sample - ), # This is a transitive dependency, but is useful for determining stage inputs - ], - Stage(StageIdentifier.StationSelection, event, None): [ - Stage(StageIdentifier.EMOD3DParameters, event, sample), - Stage(StageIdentifier.HighFrequency, event, sample), - ], - Stage(StageIdentifier.ModelCoordinates, event, None): [ - Stage(StageIdentifier.EMOD3DParameters, event, sample) - ], - Stage(StageIdentifier.EMOD3DParameters, event, sample): [ - Stage(StageIdentifier.CheckDomain, event, sample), - Stage(StageIdentifier.LowFrequency, event, sample), - ], - Stage(StageIdentifier.CheckDomain, event, sample): [ - Stage(StageIdentifier.LowFrequency, event, sample) - ], - Stage(StageIdentifier.LowFrequency, event, sample): [ - Stage(StageIdentifier.Broadband, event, sample), - Stage(StageIdentifier.MergeTimeslices, event, sample), - ], - Stage(StageIdentifier.StochGeneration, event, sample): [ - Stage(StageIdentifier.HighFrequency, event, sample) - ], - Stage(StageIdentifier.HighFrequency, event, sample): [ - Stage(StageIdentifier.Broadband, event, sample) - ], - Stage(StageIdentifier.Broadband, event, sample): [ - Stage(StageIdentifier.IntensityMeasureCalculation, event, sample) - ], - }, - create_using=nx.DiGraph, - ) - if not sample: - workflow_plan.add_edges_from( - [ - ( - Stage(StageIdentifier.NSHMToRealisation, event, sample), - Stage(StageIdentifier.DomainGeneration, event, sample), - ), - ( - Stage(StageIdentifier.GCMTToRealisation, event, sample), - Stage(StageIdentifier.DomainGeneration, event, sample), - ), - ( - Stage(StageIdentifier.DomainGeneration, event, sample), - Stage(StageIdentifier.EMOD3DParameters, event, sample), - ), - ( - Stage(StageIdentifier.DomainGeneration, event, sample), - Stage(StageIdentifier.VelocityModelGeneration, event, sample), - ), - ( - Stage(StageIdentifier.DomainGeneration, event, sample), - Stage(StageIdentifier.StationSelection, event, sample), - ), - ( - Stage(StageIdentifier.DomainGeneration, event, sample), - Stage(StageIdentifier.ModelCoordinates, event, sample), - ), - ] - ) - workflow_plan.add_edges_from( - [ - ( - Stage(StageIdentifier.DomainGeneration, event, sample), - Stage(id, event, sample), - ) - for id in requires_domain - ] - ) - else: - workflow_plan.add_edges_from( - [ - ( - Stage(StageIdentifier.DomainGeneration, event, None), - Stage(StageIdentifier.CopyDomainParameters, event, sample), - ), - ] - ) - workflow_plan.add_edges_from( - [ - ( - Stage(StageIdentifier.CopyDomainParameters, event, sample), - Stage(id, event, sample), - ) - for id in requires_domain - if id != StageIdentifier.CopyDomainParameters - ] - ) - return workflow_plan - - -def create_abstract_workflow_plan( - realisations: set[tuple[str, int | None]], - goals: Iterable[StageIdentifier], - excluding: Iterable[StageIdentifier], -) -> nx.DiGraph: - """Create an abstract workflow graph from a list of goals and excluded stages. - - Parameters - ---------- - realisations : set[tuple[str, int | None]] - The realisations to generate the workflow for. - goals : Iterable[StageIdentifier] - The goal stages for the workflow. - excluding : Iterable[StageIdentifier] - The excluded stages for the workflow. - - Returns - ------- - nx.DiGraph - A abstract workflow plan. This workflow plan contains only - included stages that are required to reach the goals. If two - workflow stages depend on each other only through paths - consisting entirely of excluded nodes, then they are adjacent - directly in the abstract plan by edges. - """ - - excluding_stages = { - Stage(excluded, *realisation) - for excluded in excluding - for realisation in realisations - } - - output_graph = nx.DiGraph() - realisation_iteration = ( - realisations if len(realisations) < 100 else tqdm.tqdm(realisations) - ) - - for event, realisation in realisation_iteration: - workflow_plan = realisation_workflow(event, realisation) - workflow_plan = nx.transitive_closure_dag(workflow_plan) - - for goal in goals: - reduced_graph = nx.transitive_reduction( - workflow_plan.subgraph( - ( - set(workflow_plan.predecessors(Stage(goal, *realisation))) - | {Stage(goal, *realisation)} - ) - - excluding_stages - ) - ) - output_graph.update( - edges=reduced_graph.edges(), nodes=reduced_graph.nodes() - ) - - roots = [node for node, degree in output_graph.in_degree() if degree == 0] - ends = [node for node, degree in output_graph.out_degree() if degree == 0] - copy_input_stage = Stage(StageIdentifier.CopyInput, "", None) - archive_output_stage = Stage(StageIdentifier.Archive, "", None) - - output_graph.add_node(copy_input_stage) - output_graph.add_node(archive_output_stage) - for root in roots: - output_graph.add_edge(copy_input_stage, root) - for end in ends: - output_graph.add_edge(end, archive_output_stage) - return output_graph - - -def pyvis_graph(workflow_plan: nx.DiGraph) -> Network: - """Convert a workflow plan into a pyvis diagram for visualisation. - - Parameters - ---------- - workflow_plan : nx.DiGraph - The workflow plan to visualise. - - - Returns - ------- - Network - A pyvis rendering for this workflow plan. - """ - network = Network( - width="100%", height="1500px", directed=True, layout="hierarchical" - ) - network.show_buttons(filter_=["physics"]) - roots = [node for node, degree in workflow_plan.in_degree() if degree == 0] - reversed_workflow = workflow_plan.reverse() - stage: Stage - for stage in workflow_plan.nodes(): - network.add_node( - str(stage), - group=f"{stage.event}_{stage.sample or ''}", - size=20, - level=max( - ( - len(path) - 1 - for root in roots - for path in nx.all_simple_paths(reversed_workflow, stage, root) - ), - default=0, - ), - ) - for stage, next_stage in workflow_plan.edges(): - network.add_edge(str(stage), str(next_stage)) - return network - - -def parse_realisation(realisation_id: str) -> set[tuple[str, int | None]]: - """Parse a realisation identifier string from the command line into a realisation identifier. - - Parameters - ---------- - realisation_id : str - The realisation identifier string to parse. - - Returns - ------- - tuple[str, int | None] - The parsed realisation event and sample number. - """ - try: - index = realisation_id.rindex(":") - event, num_samples = realisation_id[:index], realisation_id[index + 1 :] - - return {(event, sample or None) for sample in range(int(num_samples))} - except ValueError: - return {(realisation_id, None)} - - -def build_filetree(root_path: PurePath, files: set[PurePath]) -> dict[str, Any]: - """Build a file tree from a set of file paths. - - Parameters - ---------- - root_path : PurePath - The root path for the file tree. - files : set[PurePath] - The set of files to construct a tree for. - - - Returns - ------- - dict[str, Any] - A file tree. - """ - file_descriptions = { - "realisation.srf": "Contains the slip model for the realisation.", - "model_params": "Parameters for the model used in the simulation.", - "grid_file": "Grid file for the model coordinates.", - "stations.ll": "Station coordinates (lat, lon) in the simulation domain.", - "stations.statcords": "Station coordinates (x, y) in the simulation domain.", - "rho3dfile.d": "3D density model file.", - "vp3dfile.p": "3D P-wave velocity model file.", - "vs3dfile.s": "3D S-wave velocity model file.", - "in_basin_mask.b": "In-basin mask file for the velocity model.", - "LF": "Directory containing low frequency simulation files.", - "e3d.par": "EMOD3D parameter file.", - "realisation.stoch": "Stochastic file for the realisation.", - "realisation.hf": "High frequency waveform file for the realisation.", - "realisation.bb": "Broadband waveform file for the realisation.", - "intensity_measures.parquet": "Parquet file containing intensity measures.", - "animation.mp4": "Animation of the timeslices.", - "output.e3d": "Merged output file from the low frequency simulation.", - } - config_descriptions = { - realisations.RealisationMetadata._config_key: "Metadata for describing a realisation.", - realisations.SRFConfig._config_key: "Configuration for SRF generation.", - realisations.SourceConfig._config_key: "Configuration for defining sources.", - realisations.RupturePropagationConfig._config_key: "Configuration for rupture propagation.", - realisations.DomainParameters._config_key: "Parameters defining the spatial and temporal domain for simulation.", - realisations.VelocityModelParameters._config_key: "Parameters defining the velocity model.", - realisations.VelocityModel1D._config_key: "1D Velocity Model for SRF and HF.", - realisations.HFConfig._config_key: "High frequency simulation configuration.", - realisations.EMOD3DParameters._config_key: "Parameters for EMOD3D LF simulation.", - realisations.BroadbandParameters._config_key: "Parameters for broadband waveform merger.", - realisations.IntensityMeasureCalculationParameters._config_key: "Intensity measure calculation parameters.", - } - filetree: dict[str, Any] = {} - - root = filetree - for part in root_path.parts: - root[part] = {} - root = root[part] - - for file in sorted(files): - cur = root - for part in file.parts[:-1]: - if part not in cur: - cur[part] = {} - cur = cur[part] - - if file.parent.name == "realisation.json": - cur[file.parts[-1]] = config_descriptions.get(file.name, {}) - else: - cur[file.parts[-1]] = file_descriptions.get(file.name, {}) - - return filetree - - -@cli.from_docstring(app) -def plan_workflow( - realisation_ids: Annotated[list[str], typer.Argument()], - flow_file: Annotated[Path, typer.Argument(writable=True, dir_okay=False)], - goal: Annotated[ - list[StageIdentifier], - typer.Option(default_factory=lambda: [], rich_help_panel="Planning Workflows"), - ], - group_goal: Annotated[ - list[GroupIdentifier], - typer.Option(default_factory=lambda: [], rich_help_panel="Planning Workflows"), - ], - excluding: Annotated[ - list[StageIdentifier], - typer.Option(default_factory=lambda: [], rich_help_panel="Planning Workflows"), - ], - excluding_group: Annotated[ - list[GroupIdentifier], - typer.Option(default_factory=lambda: [], rich_help_panel="Planning Workflows"), - ], - archive: Annotated[ - list[StageIdentifier], - typer.Option( - default_factory=lambda: [ - StageIdentifier.Broadband, - StageIdentifier.IntensityMeasureCalculation, - ], - rich_help_panel="Archiving", - ), - ], - visualise: Annotated[ - bool, typer.Option(rich_help_panel="Visualising Workflows") - ] = False, - show_required_files: Annotated[ - bool, typer.Option(rich_help_panel="Visualising Workflows") - ] = True, - target_host: Annotated[ - WorkflowTarget, typer.Option(rich_help_panel="Planning Workflows") - ] = WorkflowTarget.NeSI, - source: Annotated[Optional[Source], typer.Option(rich_help_panel="Sources")] = None, - defaults_version: Annotated[ - Optional[DefaultsVersion], typer.Option(rich_help_panel="Sources") - ] = None, - container: Annotated[Optional[Path], typer.Option()] = None, - emod3d_path: Annotated[Optional[Path], typer.Option()] = None, -) -> None: - """Plan and generate a Cylc workflow file for a number of realisations. - - Parameters - ---------- - realisation_ids : list[str] - List of realisations to generate workflows for. Realisations have the format event:realisation_count, such as Darfield:4. - flow_file : Path - Path to output flow file (e.g. ~/cylc-src/my-workflow/flow.cylc). - goal : list[StageIdentifier] - List of workflow outputs to generate. - group_goal : list[GroupIdentifier] - List of group goals to generate. - excluding : list[StageIdentifier] - List of stages to exclude. - excluding_group : list[GroupIdentifier] - List of stage groups to exclude. - archive : list[StageIdentifier] - Add stage outputs to the archive tarball. - visualise : bool - Visualise the planned workflow as a graph. - show_required_files : bool - Print the expected directory tree at the start of the simulation. - target_host : WorkflowTarget - Select the target host where the workflow will be run. - source : Optional[Source] - If given, set the source of the realisation. For NSHM and GCMT, the realisation id corresponds to the rupture id and GCMT PublicID respectively. - defaults_version : Optional[DefaultsVersion] - The simulation defaults to apply for all realisations. Required if source is specified. - container : Optional[Path] - The container to use for the workflow. If not specified, the default container for the target environment will be used. - emod3d_path : Optional[Path] - The path to the EMOD3D installation. If not specified, the default path for the target environment will be used. - """ - container = container or CONTAINER_PATHS[target_host] - emod3d_path = emod3d_path or EMOD3D_PATHS[target_host] - realisations = set.union( - *[parse_realisation(realisation_id) for realisation_id in realisation_ids] - ) - if source and not defaults_version: - print( - "You must specify a defaults version if you specify a source. See the help text for options." - ) - raise typer.Exit(code=1) - excluding_set = set(excluding) - goal_set = set(goal) - if group_goal: - goal_set |= set.union(*[GROUP_GOALS[group] for group in group_goal]) - if excluding_group: - excluding_set |= set.union(*[GROUP_STAGES[group] for group in excluding_group]) - - excluding_source_map: dict[Optional[Source], set[StageIdentifier]] = { - Source.GCMT: {StageIdentifier.GCMTToRealisation}, - Source.NSHM: {StageIdentifier.NSHMToRealisation}, - } - excluding_set |= set.union( - *excluding_source_map.values() - ) - excluding_source_map.get(source, set()) - workflow_plan = create_abstract_workflow_plan(realisations, goal_set, excluding_set) - env = jinja2.Environment( - loader=jinja2.PackageLoader("workflow"), - ) - archiving = set() - for stage_id in archive: - archiving |= { - file.name for file in stage_outputs(stage_id, include_config_outputs=False) - } - - template = env.get_template("flow.cylc") - flow_template = template.render( - container=container, - emod3d_path=emod3d_path, - defaults_version=defaults_version, - realisations=realisations, - target_host=target_host, - archiving=archiving, - workflow_plan={ - node: sorted(dependents, key=lambda stage: str(stage)) - for node, dependents in sorted( - nx.to_dict_of_lists(workflow_plan).items(), - key=lambda kv: str(kv[0]), - ) - }, - ) - flow_file.write_text( - # strip empty lines from the output flow template - "\n".join(line for line in flow_template.split("\n") if line.strip()) - ) - if show_required_files: - root_path = Path("cylc-src") / "WORKFLOW_NAME" / "input" - inputs = { - PurePath( - Path("cylc-src") / "WORKFLOW_NAME" / "flow.cylc", - ) - } - outputs = set() - inputs = set() - for stage in workflow_plan.nodes: - inputs |= stage.inputs - outputs |= stage.outputs - - missing_file_tree = build_filetree(root_path, inputs - outputs) - - if missing_file_tree: - print("You require the following files for your simulation:") - print() - printree.ptree(missing_file_tree) - print() - print( - "You can find documentation for the output files at https://wiki.canterbury.ac.nz/display/QuakeCore/File+Formats+Used+In+Ground+Motion+Simulation." - ) - if visualise: - network = pyvis_graph(workflow_plan) - with tempfile.NamedTemporaryFile(suffix=".html", delete=False) as graph_render: - network.show(graph_render.name, notebook=False) diff --git a/workflow/templates/flow.cylc b/workflow/templates/flow.cylc deleted file mode 100644 index cfa9b6c6..00000000 --- a/workflow/templates/flow.cylc +++ /dev/null @@ -1,23 +0,0 @@ -{% macro stage_node_identifier(stage) -%} -{{stage.identifier}}{% if stage.event %}_{{stage.event}}{% if stage.sample %}_{{stage.sample}}{% endif %}{% endif %} -{%- endmacro -%} - -{% macro realisation_identifier(stage) -%} -{{stage.event}}{% if stage.sample %}_{{stage.sample}}{% endif %} -{%- endmacro -%} - -[scheduling] - [[graph]] - R1 = """ - {% for stage, next_stages in workflow_plan.items() -%} - {% for next_stage in next_stages %} - {{ stage_node_identifier(stage) }} => {{ stage_node_identifier(next_stage) }} - {% endfor -%} - {% endfor -%} - """ - {% include target_host + '/queue.cylc' %} -[runtime] - {% include target_host + '/root.cylc' %} - {% for stage, next_stages in workflow_plan.items() -%} - {% include target_host + '/' + stage.identifier + '.cylc' %} - {% endfor %} diff --git a/workflow/templates/hypocentre/archive.cylc b/workflow/templates/hypocentre/archive.cylc deleted file mode 100644 index 282348c4..00000000 --- a/workflow/templates/hypocentre/archive.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = timestamp=$(date +%Y%m%d%H%M%S) && tar -caf "$timestamp.tar.xz" --files-from=<(find $CYLC_WORKFLOW_SHARE_DIR -type f \( -name "realisation.json" {%- for pattern in archiving %} -o -name "{{pattern}}" {%- endfor %} \)) && rclone copy "$timestamp.tar.xz" dropbox:/QuakeCoRE/Simulation\ Results\ Inbox/$USER/ diff --git a/workflow/templates/hypocentre/bb_sim.cylc b/workflow/templates/hypocentre/bb_sim.cylc deleted file mode 100644 index ecf8254f..00000000 --- a/workflow/templates/hypocentre/bb_sim.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,$CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}:/parent" {{container}} bb-sim /share/realisation.json /stations.vs30 /share/LF/OutBin /share/realisation.hf /parent/Velocity_Model /share/realisation.bb - inherit = large_job diff --git a/workflow/templates/hypocentre/check_domain.cylc b/workflow/templates/hypocentre/check_domain.cylc deleted file mode 100644 index 1aa04d7e..00000000 --- a/workflow/templates/hypocentre/check_domain.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,$CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}:/parent" {{container}} check-domain /share/realisation.json /share/realisation.srf /parent/Velocity_Model diff --git a/workflow/templates/hypocentre/check_srf.cylc b/workflow/templates/hypocentre/check_srf.cylc deleted file mode 100644 index 9fea5766..00000000 --- a/workflow/templates/hypocentre/check_srf.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} check-srf /share/realisation.json /share/realisation.srf diff --git a/workflow/templates/hypocentre/copy_domain_parameters.cylc b/workflow/templates/hypocentre/copy_domain_parameters.cylc deleted file mode 100644 index de0d7d70..00000000 --- a/workflow/templates/hypocentre/copy_domain_parameters.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,$CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}:/parent" {{container}} copy-domain-parameters /parent/realisation.json /share/realisation.json diff --git a/workflow/templates/hypocentre/copy_input.cylc b/workflow/templates/hypocentre/copy_input.cylc deleted file mode 100644 index d33d2ab4..00000000 --- a/workflow/templates/hypocentre/copy_input.cylc +++ /dev/null @@ -1,5 +0,0 @@ -[[copy_input]] - script = """ - mkdir -p {% for realisation in realisations %}$CYLC_WORKFLOW_SHARE_DIR/{{realisation[0]}}{% if realisation[1] %}_{{realisation[1]}}{% endif %} {% endfor %} - [[ ! -d $CYLC_WORKFLOW_RUN_DIR/input ]] || cp -rn $CYLC_WORKFLOW_RUN_DIR/input/. $CYLC_WORKFLOW_SHARE_DIR - """ diff --git a/workflow/templates/hypocentre/create_e3d_par.cylc b/workflow/templates/hypocentre/create_e3d_par.cylc deleted file mode 100644 index 90a29675..00000000 --- a/workflow/templates/hypocentre/create_e3d_par.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec --bind "/mnt:/mnt" {{container}} create-e3d-par $CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/realisation.json $CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/realisation.srf $CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}/Velocity_Model $CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}/stations $CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}/model $CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/LF --emod3d-path {{emod3d_path}} --scratch-ffp $CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/LF diff --git a/workflow/templates/hypocentre/emod3d.cylc b/workflow/templates/hypocentre/emod3d.cylc deleted file mode 100644 index 5159f16c..00000000 --- a/workflow/templates/hypocentre/emod3d.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = mpirun --use-hwthread-cpus -n 48 {{emod3d_path}} -args "par=$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/LF/e3d.par" - inherit = large_job diff --git a/workflow/templates/hypocentre/gcmt_to_realisation.cylc b/workflow/templates/hypocentre/gcmt_to_realisation.cylc deleted file mode 100644 index 1ea59f29..00000000 --- a/workflow/templates/hypocentre/gcmt_to_realisation.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} gcmt-to-realisation {{stage.event}} {{defaults_version}} /share/realisation.json diff --git a/workflow/templates/hypocentre/generate_station_coordinates.cylc b/workflow/templates/hypocentre/generate_station_coordinates.cylc deleted file mode 100644 index 2c3c2ea2..00000000 --- a/workflow/templates/hypocentre/generate_station_coordinates.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} generate-station-coordinates /share/realisation.json /share/stations --stat-file /stations.ll diff --git a/workflow/templates/hypocentre/generate_stoch.cylc b/workflow/templates/hypocentre/generate_stoch.cylc deleted file mode 100644 index 93aedd2c..00000000 --- a/workflow/templates/hypocentre/generate_stoch.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} generate-stoch /share/realisation.json /share/realisation.srf /share/realisation.stoch diff --git a/workflow/templates/hypocentre/generate_velocity_model.cylc b/workflow/templates/hypocentre/generate_velocity_model.cylc deleted file mode 100644 index 261d4159..00000000 --- a/workflow/templates/hypocentre/generate_velocity_model.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} sh -c 'generate-velocity-model /share/realisation.json /share/Velocity_Model --num-threads $(nproc) --velocity-model-bin-path /Velocity-Model/NZVM' - inherit = large_job diff --git a/workflow/templates/hypocentre/generate_velocity_model_parameters.cylc b/workflow/templates/hypocentre/generate_velocity_model_parameters.cylc deleted file mode 100644 index 662608da..00000000 --- a/workflow/templates/hypocentre/generate_velocity_model_parameters.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} generate-velocity-model-parameters /share/realisation.json diff --git a/workflow/templates/hypocentre/hf_sim.cylc b/workflow/templates/hypocentre/hf_sim.cylc deleted file mode 100644 index 434a956e..00000000 --- a/workflow/templates/hypocentre/hf_sim.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,$CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}/stations:/stations" {{container}} hf-sim /share/realisation.json /share/realisation.stoch /stations/stations.ll /share/realisation.hf - inherit = large_job diff --git a/workflow/templates/hypocentre/im_calc.cylc b/workflow/templates/hypocentre/im_calc.cylc deleted file mode 100644 index c305c7d8..00000000 --- a/workflow/templates/hypocentre/im_calc.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,/mnt/hypo_scratch/ko_matrices:/ko_matrices" {{container}} im-calc /share/realisation.json /share/realisation.bb /share/intensity_measures.parquet --ko-directory /ko_matrices - inherit = large_job diff --git a/workflow/templates/hypocentre/merge_ts.cylc b/workflow/templates/hypocentre/merge_ts.cylc deleted file mode 100644 index 284f91d7..00000000 --- a/workflow/templates/hypocentre/merge_ts.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR:/share/{{realisation_identifier(stage)}}" merge-ts /share/LF/OutBin /share/LF/OutBin/output.e3d diff --git a/workflow/templates/hypocentre/nshm_to_realisation.cylc b/workflow/templates/hypocentre/nshm_to_realisation.cylc deleted file mode 100644 index 81f730d9..00000000 --- a/workflow/templates/hypocentre/nshm_to_realisation.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} nshm2022-to-realisation /nshmdb.db {{stage.event}} /share/realisation.json {{defaults_version}} diff --git a/workflow/templates/hypocentre/queue.cylc b/workflow/templates/hypocentre/queue.cylc deleted file mode 100644 index 2266ef98..00000000 --- a/workflow/templates/hypocentre/queue.cylc +++ /dev/null @@ -1,4 +0,0 @@ - [[queues]] - [[[large_job]]] - limit = 1 - members = large_job diff --git a/workflow/templates/hypocentre/realisation_to_srf.cylc b/workflow/templates/hypocentre/realisation_to_srf.cylc deleted file mode 100644 index 3d0c704b..00000000 --- a/workflow/templates/hypocentre/realisation_to_srf.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} realisation-to-srf /share/realisation.json /share/realisation.srf diff --git a/workflow/templates/hypocentre/root.cylc b/workflow/templates/hypocentre/root.cylc deleted file mode 100644 index 265bbcbd..00000000 --- a/workflow/templates/hypocentre/root.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[root]] - platform = localhost -[[large_job]] diff --git a/workflow/templates/hypocentre/write_model_coordinates.cylc b/workflow/templates/hypocentre/write_model_coordinates.cylc deleted file mode 100644 index c624bdc1..00000000 --- a/workflow/templates/hypocentre/write_model_coordinates.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} generate-model-coordinates /share/realisation.json /share/model diff --git a/workflow/templates/nesi/archive.cylc b/workflow/templates/nesi/archive.cylc deleted file mode 100644 index 69204cab..00000000 --- a/workflow/templates/nesi/archive.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - platform = localhost - script = timestamp=$(date +%Y%m%d%H%M%S) && tar -caf "$timestamp.tar.xz" --files-from=<(find $CYLC_WORKFLOW_SHARE_DIR -type f \( -name "realisation.json" {%- for pattern in archiving %} -o -name "{{pattern}}" {%- endfor %} \)) && rclone copy "$timestamp.tar.xz" dropbox:/QuakeCoRE/Simulation\ Results\ Inbox/$USER/ diff --git a/workflow/templates/nesi/bb_sim.cylc b/workflow/templates/nesi/bb_sim.cylc deleted file mode 100644 index 2eaa52ba..00000000 --- a/workflow/templates/nesi/bb_sim.cylc +++ /dev/null @@ -1,6 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,$CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}:/parent" {{container}} bb-sim /share/realisation.json /stations.vs30 /share/LF/OutBin /share/realisation.hf /parent/Velocity_Model /share/realisation.bb - [[[directives]]] - --cpus-per-task = 32 - --time = 01:00:00 - --partition = milan diff --git a/workflow/templates/nesi/check_domain.cylc b/workflow/templates/nesi/check_domain.cylc deleted file mode 100644 index 1aa04d7e..00000000 --- a/workflow/templates/nesi/check_domain.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,$CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}:/parent" {{container}} check-domain /share/realisation.json /share/realisation.srf /parent/Velocity_Model diff --git a/workflow/templates/nesi/check_srf.cylc b/workflow/templates/nesi/check_srf.cylc deleted file mode 100644 index 9fea5766..00000000 --- a/workflow/templates/nesi/check_srf.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} check-srf /share/realisation.json /share/realisation.srf diff --git a/workflow/templates/nesi/copy_domain_parameters.cylc b/workflow/templates/nesi/copy_domain_parameters.cylc deleted file mode 100644 index 411873dd..00000000 --- a/workflow/templates/nesi/copy_domain_parameters.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - platform = localhost - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,$CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}:/parent" {{container}} copy-domain-parameters /parent/realisation.json /share/realisation.json diff --git a/workflow/templates/nesi/copy_input.cylc b/workflow/templates/nesi/copy_input.cylc deleted file mode 100644 index 017ff1c9..00000000 --- a/workflow/templates/nesi/copy_input.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[copy_input]] - platform = localhost - script = "[[ ! -d $CYLC_WORKFLOW_RUN_DIR/input ]] || cp -rn $CYLC_WORKFLOW_RUN_DIR/input/. $CYLC_WORKFLOW_SHARE_DIR" diff --git a/workflow/templates/nesi/create_e3d_par.cylc b/workflow/templates/nesi/create_e3d_par.cylc deleted file mode 100644 index 4bd37962..00000000 --- a/workflow/templates/nesi/create_e3d_par.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - platform = localhost - script = apptainer exec {{container}} create-e3d-par $CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/realisation.json $CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/realisation.srf $CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}/Velocity_Model $CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}/stations $CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}/model $CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/LF --emod3d-path /nesi/project/nesi00213/opt/maui/hybrid_sim_tools/emod3d-mpi_v3.0.8 --scratch-ffp $CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/LF diff --git a/workflow/templates/nesi/emod3d.cylc b/workflow/templates/nesi/emod3d.cylc deleted file mode 100644 index 90f7f115..00000000 --- a/workflow/templates/nesi/emod3d.cylc +++ /dev/null @@ -1,9 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - pre-script = module load foss/2023a - script = srun {{emod3d_path}} -args "par=$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}/LF/e3d.par" - [[[directives]]] - --partition = milan - --ntasks = 160 - --mem-per-cpu = 2000MB - --nodes = 2 - --time = 06:00:00 diff --git a/workflow/templates/nesi/gcmt_to_realisation.cylc b/workflow/templates/nesi/gcmt_to_realisation.cylc deleted file mode 100644 index 1ecb56d6..00000000 --- a/workflow/templates/nesi/gcmt_to_realisation.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - platform = localhost - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} gcmt-to-realisation {{stage.event}} {{defaults_version}} /share/realisation.json diff --git a/workflow/templates/nesi/generate_station_coordinates.cylc b/workflow/templates/nesi/generate_station_coordinates.cylc deleted file mode 100644 index 393ff70c..00000000 --- a/workflow/templates/nesi/generate_station_coordinates.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - platform = localhost - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} generate-station-coordinates /share/realisation.json /share/stations --stat-file /stations.ll diff --git a/workflow/templates/nesi/generate_stoch.cylc b/workflow/templates/nesi/generate_stoch.cylc deleted file mode 100644 index 93aedd2c..00000000 --- a/workflow/templates/nesi/generate_stoch.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} generate-stoch /share/realisation.json /share/realisation.srf /share/realisation.stoch diff --git a/workflow/templates/nesi/generate_velocity_model.cylc b/workflow/templates/nesi/generate_velocity_model.cylc deleted file mode 100644 index 60be0e20..00000000 --- a/workflow/templates/nesi/generate_velocity_model.cylc +++ /dev/null @@ -1,6 +0,0 @@ -[[ {{stage_node_identifier(stage)}} ]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} sh -c 'generate-velocity-model /share/realisation.json /share/Velocity_Model --num-threads $(nproc) --velocity-model-bin-path /Velocity-Model/NZVM' - [[[directives]]] - --cpus-per-task = 32 - --time = 01:00:00 - --partition = milan diff --git a/workflow/templates/nesi/generate_velocity_model_parameters.cylc b/workflow/templates/nesi/generate_velocity_model_parameters.cylc deleted file mode 100644 index 662608da..00000000 --- a/workflow/templates/nesi/generate_velocity_model_parameters.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} generate-velocity-model-parameters /share/realisation.json diff --git a/workflow/templates/nesi/hf_sim.cylc b/workflow/templates/nesi/hf_sim.cylc deleted file mode 100644 index bda2cc29..00000000 --- a/workflow/templates/nesi/hf_sim.cylc +++ /dev/null @@ -1,6 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,$CYLC_WORKFLOW_SHARE_DIR/{{stage.event}}/stations:/stations" {{container}} hf-sim /share/realisation.json /share/realisation.stoch /stations/stations.ll /share/realisation.hf - [[[directives]]] - --cpus-per-task = 32 - --time = 01:00:00 - --partition = milan diff --git a/workflow/templates/nesi/im_calc.cylc b/workflow/templates/nesi/im_calc.cylc deleted file mode 100644 index f67582bf..00000000 --- a/workflow/templates/nesi/im_calc.cylc +++ /dev/null @@ -1,7 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share,/nesi/project/nesi00213/ko_matrices:/ko_matrices" {{container}} im-calc /share/realisation.json /share/realisation.bb /share/intensity_measures.h5 --num-processes 64 --psa-rotd-maximum-memory-allocation 40 --ko-directory /ko_matrices - [[[directives]]] - --cpus-per-task = 64 - --time = 01:00:00 - --mem = 100G - --partition = milan diff --git a/workflow/templates/nesi/merge_ts.cylc b/workflow/templates/nesi/merge_ts.cylc deleted file mode 100644 index 284f91d7..00000000 --- a/workflow/templates/nesi/merge_ts.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR:/share/{{realisation_identifier(stage)}}" merge-ts /share/LF/OutBin /share/LF/OutBin/output.e3d diff --git a/workflow/templates/nesi/nshm_to_realisation.cylc b/workflow/templates/nesi/nshm_to_realisation.cylc deleted file mode 100644 index 278fa9e4..00000000 --- a/workflow/templates/nesi/nshm_to_realisation.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - platform = localhost - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} nshm2022-to-realisation /nshmdb.db {{stage.event}} /share/realisation.json {{defaults_version}} diff --git a/workflow/templates/nesi/queue.cylc b/workflow/templates/nesi/queue.cylc deleted file mode 100644 index e69de29b..00000000 diff --git a/workflow/templates/nesi/realisation_to_srf.cylc b/workflow/templates/nesi/realisation_to_srf.cylc deleted file mode 100644 index 3d0c704b..00000000 --- a/workflow/templates/nesi/realisation_to_srf.cylc +++ /dev/null @@ -1,2 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} realisation-to-srf /share/realisation.json /share/realisation.srf diff --git a/workflow/templates/nesi/root.cylc b/workflow/templates/nesi/root.cylc deleted file mode 100644 index 79ee4c35..00000000 --- a/workflow/templates/nesi/root.cylc +++ /dev/null @@ -1,7 +0,0 @@ -[[root]] - platform = mahuika-slurm - pre-script = """ - module load Apptainer - """ - [[[directives]]] - --account = nesi00213 diff --git a/workflow/templates/nesi/write_model_coordinates.cylc b/workflow/templates/nesi/write_model_coordinates.cylc deleted file mode 100644 index 8ba03376..00000000 --- a/workflow/templates/nesi/write_model_coordinates.cylc +++ /dev/null @@ -1,3 +0,0 @@ -[[{{stage_node_identifier(stage)}}]] - platform = localhost - script = apptainer exec -c --bind "$PWD:/out,$CYLC_WORKFLOW_SHARE_DIR/{{realisation_identifier(stage)}}:/share" {{container}} generate-model-coordinates /share/realisation.json /share/model