Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Input Data Generation Overview

This subsystem is driven by the forge application (cstar forge run <forge_blueprint.yaml>, or equivalently python -m cstar_forge.run), which loads a ForgeBlueprint and calls ForgeExecutor.generate_inputs() (cstar_forge/forge/executor.py). That method constructs a RomsMarblInputData instance and calls generate_all() on it. Constructing RomsMarblInputData directly (as shown later in this doc) is for developers debugging or extending input generation — normal usage goes through the forge application.

The input_data module (cstar_forge/forge/input_data.py) provides classes and utilities for generating input data files for ocean models. It uses a registry-based framework similar to the source_data module, allowing extensible input generation through decorator-based registration.

Module Purpose

The input data generation process transforms prepared source datasets into model-ready input files:

Core Components

Base Class: InputData

Abstract dataclass defining the interface for input data generation:

@dataclass
class InputData:
    domain_name: str
    start_date: Any
    end_date: Any
    input_data_dir: Path = field(kw_only=True)  # Output directory, injected by the caller

    def generate_all(self):
        """Generate all input files. Must be implemented by subclasses."""
        raise NotImplementedError

input_data_dir is injected by the caller (the executor) rather than derived from cstar_forge.config — this keeps the class host-independent.

Key Features:

Registry System

Input generation steps are registered using the @register_input decorator:

@register_input(name="grid", order=10, label="Writing ROMS grid")
def _generate_grid(self, key: str = "grid", **kwargs):
    """Generate grid input file."""
    # Implementation...

Registry Components:

Execution Order: Steps are executed in order (lowest order value first):

ROMS-MARBL Implementation: RomsMarblInputData

The RomsMarblInputData class provides ROMS-MARBL specific input generation:

Key Attributes (dataclass fields; see docs/InputData-RomsMarblInputData.md for the full list):

Workflow:

  1. Initialization: Builds input_list from forcing_override (plus the always-present grid entry and any cdr_forcing), validates against registry

  2. Generation: generate_all() executes registered handlers in order

  3. Blueprint Updates: Each handler appends Resource objects to roms_marbl_blueprint_elements

  4. Settings Updates: Handlers populate compile-time and run-time settings dictionaries

  5. Partitioning: Optional step to partition files across tiles

Input Generation Process

Step 1: Build Input List

__post_init__ derives input_list from forcing_override (the resolved initial-conditions + forcing selection injected by the caller — see cstar_forge.forge.forge_blueprint_engine / sources_to_forcing_override), not from a model spec:

Step 2: Execute Handlers

For each item in input_list:

  1. Look up handler in INPUT_REGISTRY

  2. Build input arguments from defaults + kwargs

  3. Resolve source paths via SourceData

  4. Call handler function

  5. Update blueprint and settings

Step 3: Source Resolution

Source blocks (e.g., {"name": "GLORYS"}) are resolved:

Step 4: Settings Population

Handlers populate settings dictionaries:

These settings are used later to render configuration templates.

Input Types

Grid (grid)

Initial Conditions (initial_conditions)

Surface Forcing (forcing.surface)

Boundary Forcing (forcing.boundary)

Tidal Forcing (forcing.tidal)

River Forcing (forcing.river)

CDR Forcing (cdr_forcing)

Blueprint Integration

Each input handler updates roms_marbl_blueprint_elements (a RomsMarblBlueprintInputData), a subset of the blueprint containing:

Resource Objects: Each generated file is represented as a Resource object with:

Settings Integration

Handlers populate two settings dictionaries:

Compile-Time Settings (_settings_compile_time)

This is the only compile-time section this class populates — grid dimensions, tides, and river settings are all run-time (see below), not compile-time.

Run-Time Settings (_settings_run_time)

These settings are later merged with template defaults and used to render configuration files.

File Outputs

All input files are written to:

{input_data_dir}/{domain_name}_{input_name}.nc

domain_name has any . replaced with _ (via netcdf_filename_component()), since generated NetCDF basenames must not contain a . except the final .nc suffix. For example, a domain named cson_roms-marbl_v0.1_test-tiny produces:

Usage Pattern

Direct construction is for developers; normal usage goes through the forge application (cstar forge run, see the note at the top of this document).

from cstar_forge.forge.input_data import RomsMarblInputData

# Create input data generator — host-independent: paths and the resolved forcing
# selection are injected by the caller (ForgeExecutor), not derived from a model_spec.
input_gen = RomsMarblInputData(
    domain_name="test-tiny",
    start_date=datetime(2012, 1, 1),
    end_date=datetime(2012, 1, 2),
    input_data_dir=input_data_dir,
    grid=grid,
    boundaries=boundaries,
    source_data=source_data,
    roms_marbl_blueprint_dir=roms_marbl_blueprint_dir,
    partitioning=partitioning,
    forcing_override=forcing_override,  # from ForgeBlueprint.forcing via sources_to_forcing_override
)

# Generate all inputs. Settings dicts are executor-owned: pass them in (or omit
# for fresh empty dicts, as here) and they are mutated in place by generation --
# no return value carries them back.
roms_marbl_blueprint_elements = input_gen.generate_all(
    clobber=False,
    partition_files=False,
    test=False,
)

Integration with ForgeExecutor

The RomsMarblInputData class is used internally by ForgeExecutor.generate_inputs() (cstar_forge/forge/executor.py; see docs/architecture-details.md for the architecture). That method is in turn called by process_forge_blueprint() (cstar_forge/forge/forge_blueprint_engine.py), which is what cstar forge run invokes:

  1. Creates RomsMarblInputData instance, passing self.forcing_override, the other executor-resolved fields, and self._settings_compile_time/self._settings_run_time BY REFERENCE (as settings_compile_time=/settings_run_time=) and has_bgc=self._has_bgc

  2. Calls generate_all() to create input files -- generation steps mutate the executor’s settings dicts in place; the executor already holds the up-to-date values through its own reference, so there is no merge-back step

  3. Updates the in-memory blueprint with roms_marbl_blueprint_elements

  4. Persists blueprint and settings to disk (in configure_build())

This completes the generate_inputs stage; the blueprint and settings are persisted in configure_build().