Skip to content

Progressive Tutorials

This section contains a series of progressive tutorials that gradually introduce more complex concepts. Each tutorial builds on the previous one, creating a learning path from basic usage to advanced features. If you're new to Rompy, you may want to start with the User Guide.

Understanding Rompy Components

Rompy is a python package for generating configuration files and forcing data for numerical wave and wave-climate models. The core architecture consists of several key components:

  1. ModelRun: Combines all components and generates a simulation workspace ready to run
  2. Key Attributes: run_id, period (TimeRange), config, output_dir
  3. Methods: run(): Executes the model simulation

  4. Grid: Defines the spatial domain and resolution

  5. Types: RegularGrid: Uniform spacing in x and y directions, UnstructuredGrid: Non-uniform mesh (if supported)
  6. Key Attributes: x0, y0, nx, ny, dx, dy

  7. TimeRange: Specifies the temporal domain of the simulation

  8. Key Attributes: start, end, interval

  9. Data Sources: Provides input data for the model

  10. Types: SwanDataGrid: For SWAN model inputs, Other model-specific data types
  11. Components: Bathymetry, Wind, Boundary conditions, Other environmental variables

  12. Config: Holds model-specific configuration settings

  13. Types: SwanConfig: For SWAN model, Other model-specific configs
  14. Key Components: Physics parameters, Numerical scheme settings, Output specifications

  15. Output: Defines what data to save from the model run

  16. Components: Variables to output, Output locations, Output frequency

Tutorial 1: Grid Configuration and Visualization

In this first tutorial, we'll explore grid configuration and visualization capabilities of Rompy:

from rompy.core.grid import RegularGrid
from pathlib import Path

# Create a RegularGrid for an area off the west coast of Australia
grid = RegularGrid(
    x0=110.0,  # Longitude of the lower-left corner
    y0=-35.2,  # Latitude of the lower-left corner
    rot=4.0,   # Rotation angle in degrees
    dx=0.5,    # Grid spacing in the x-direction (degrees)
    dy=0.5,    # Grid spacing in the y-direction (degrees)
    nx=15,     # Number of grid points in the x-direction
    ny=25,     # Number of grid points in the y-direction
)

# Each grid has a bbox and a plot method
print("Grid bounding box:", grid.bbox())

# The grid can be plotted directly
# grid.plot()  # Uncomment to visualize

Tutorial 2: Working with Data Sources

Now let's work with data sources to extract relevant oceanographic data:

from rompy.core.data import DataGrid
from rompy.core.source import SourceFile
from rompy.core.time import TimeRange

# Define a data source for bathymetry
# For this example, we'll use a sample GEBCO file (you would replace with your actual path)
bathymetry_source = SourceFile(uri="path/to/gebco_bathymetry.nc")

# Create a DataGrid object for bathymetry
gebco_grid = DataGrid(
    id="gebco_bathymetry",
    source=bathymetry_source,
    variables=["elevation"],
    coords={"y": "lat", "x": "lon"},
)

# Extract bathymetry data for our grid
workdir = Path("./output_bathymetry")
workdir.mkdir(exist_ok=True)

# Output will be the path to the extracted data file
output = gebco_grid.get(grid=grid, destdir=workdir)
print(f"Bathymetry data extracted to: {output}")

Tutorial 3: Time-Series Data Extraction

Let's work with time-series data, such as atmospheric forcing:

# Create a TimeRange for our simulation period
timerange = TimeRange(
    start="2023-01-01T00:00:00",
    end="2023-01-02T00:00:00",
    interval="1H",  # Hourly intervals
)

# Define a source for time-varying data (e.g., ERA5 wind data)
wind_source = SourceFile(uri="path/to/era5_wind.nc")

# Create a DataGrid for wind forcing
from rompy.core.filters import Filter

era5_forcing = DataGrid(
    id="era5_wind",
    source=wind_source,
    variables=["u10", "v10"],  # 10m wind components
    coords={"t": "time", "y": "latitude", "x": "longitude"},
    # Use filter to handle coordinate issues (like reversed latitude)
    filter=Filter(sort=dict(coords=["latitude"])),
)

# Extract wind data for our grid and time range
wind_output = era5_forcing.get(grid=grid, time=timerange, destdir=workdir)
print(f"Wind data extracted to: {wind_output}")

Tutorial 4: Boundary Condition Data

For wave models, we often need boundary conditions from spectral data:

from rompy.core.boundary import BoundaryWaveStation

# Create a boundary dataset from spectra data
boundary_stations = BoundaryWaveStation(
    id="ww3_boundary",
    source=SourceFile(uri="path/to/spec_data.nc"),
    sel_method="idw",  # Inverse distance weighting selection method
    sel_method_kwargs={
        "tolerance": 4  # Distance tolerance for selection
    },
)

# Extract boundary condition data along the grid boundary
boundary_output = boundary_stations.get(grid=grid, time=timerange, destdir=workdir)
print(f"Boundary data extracted to: {boundary_output}")

Tutorial 5: Basic ModelRun Configuration

Now let's create a basic model configuration using Rompy's core components:

from rompy.model import ModelRun
from rompy.core.config import BaseConfig

# Create a basic configuration
config = BaseConfig(
    template="path/to/model_template",
    checkout="path/to/model_checkout",
    grid=grid,  # Include the grid we defined earlier
)

# Create a model run
model_run = ModelRun(
    run_id="progressive_tutorial_run",
    period=timerange,  # Use the time range we defined earlier
    config=config,
    output_dir="./model_output",
)

# Generate the model input files
staging_dir = model_run.generate()
print(f"Model files generated at: {staging_dir}")

Tutorial 6: Complete Workflow with Data Integration

Let's create a more complete example that integrates multiple data sources:

from pathlib import Path
import tempfile

# Create a temporary workspace
workdir = Path("./integrated_output")
workdir.mkdir(exist_ok=True)

# Define our area and time range
grid = RegularGrid(
    x0=110.0,
    y0=-35.2,
    rot=4.0,
    dx=0.5,
    dy=0.5,
    nx=15,
    ny=25,
)

timerange = TimeRange(
    start="2023-01-01T00:00:00",
    end="2023-01-02T00:00:00",
    interval="1H",
)

# Create multiple data sources
bathy_source = DataGrid(
    id="gebco_bathy",
    source=SourceFile(uri="path/to/bathy.nc"),
    variables=["elevation"],
    coords={"y": "lat", "x": "lon"},
)

wind_source = DataGrid(
    id="era5_wind",
    source=SourceFile(uri="path/to/wind.nc"),
    variables=["u10", "v10"],
    coords={"t": "time", "y": "latitude", "x": "longitude"},
    filter=Filter(sort=dict(coords=["latitude"])),
)

# Extract data for our model domain
bathy_output = bathy_source.get(grid=grid, destdir=workdir)
wind_output = wind_source.get(grid=grid, time=timerange, destdir=workdir)

print(f"Bathymetry data: {bathy_output}")
print(f"Wind data: {wind_output}")

# Now create a model configuration that uses this data
config = BaseConfig(
    template="path/to/model_template",
    checkout="path/to/model_checkout",
    grid=grid,
)

model_run = ModelRun(
    run_id="integrated_workflow",
    period=timerange,
    config=config,
    output_dir=workdir / "model_outputs",
)

# Generate inputs
staging_dir = model_run.generate()
print(f"Generated model files at: {staging_dir}")

Tutorial 7: Model Execution with Different Backends

Now let's run our model using different execution backends:

from rompy.backends import LocalConfig

# Execute with local backend
local_config = LocalConfig(
    timeout=3600,
    command="your_model_executable",
    env_vars={"OMP_NUM_THREADS": "4"},
)

# Run the model
success = model_run.run(backend=local_config)
print(f"Execution status: {'Success' if success else 'Failed'}")

Tutorial 8: Using YAML Configuration Files

One of the key advantages of Rompy's schema-based approach is the ability to represent complex model configurations as transportable YAML files.

Exporting to YAML

You can programmatically generate YAML from a Python configuration:

# Export the complete model configuration to YAML
yaml_content = model_run.model_dump_yaml()
print("YAML Configuration:")
print(yaml_content)

# Or save directly to a file
config_file = workdir / "model_config.yaml"
with open(config_file, "w") as f:
    f.write(yaml_content)
print(f"Configuration saved to: {config_file}")

Loading from YAML

To use a YAML configuration in Python:

from rompy.model import ModelRun

# Load the configuration from YAML
with open(config_file, "r") as f:
    yaml_content = f.read()

# Create the model run from YAML
loaded_model_run = ModelRun.model_validate_yaml(yaml_content)

# Use it just like the original
staging_dir = loaded_model_run.generate()
print(f"Generated from YAML at: {staging_dir}")

Running with Command Line Interface

Once you have your YAML configuration, you can run it using Rompy's CLI:

rompy run --config model_config.yaml

To specify a different backend:

rompy run --config model_config.yaml --backend-config local_backend.yml

For more information about available CLI options, see the CLI Reference.

Tutorial 9: Advanced Data Processing

Working with real-world data often requires more sophisticated data processing techniques:

# For boundary condition data, you can extract and interpolate
# data to specific grid boundary points using various methods

boundary_data = BoundaryWaveStation(
    id="boundary_conditions",
    source=SourceFile(uri="path/to/boundary_data.nc"),
    sel_method="idw",  # Use inverse distance weighting
    sel_method_kwargs={"tolerance": 4.0},
)

# Extract boundary data for our grid and time period
boundary_output = boundary_data.get(
    grid=grid,
    time=timerange,
    destdir=workdir
)

print(f"Boundary conditions extracted to: {boundary_output}")

Model-Specific Tutorials

For model-specific tutorials on SWAN, SCHISM, and other supported models, see the Model Guides.

Next Steps