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.

ModelSpec Example

This notebook illustrates how the ModelSpec works with model.yaml to curate and access model attributes.

Overview

The ModelSpec class defines the complete specification for an ocean model configuration, including:

  • Code: repository refs for ROMS, MARBL, and PIO, plus compile-/run-time template refs

  • Build-mode toggles: bgc_mode (marbl|none) and use_pio

  • Model settings: a flat model_settings dict of model-specific physics/numerics defaults (mirrors ForgeBlueprint.model_settings 1:1)

Model specifications are stored one-per-model in catalog/ModelSpec/<model>/model.yaml and loaded via the domain catalog.

Setup

Import the necessary modules and enable autoreload for development.

%load_ext autoreload
%autoreload 2

from cstar_forge.domain_catalog import default_catalog

Load ModelSpec

Load a model specification by name using the domain catalog’s load_model_spec, which reads catalog/ModelSpec/<model_name>/model.yaml.

# Load a model specification
model_name = "cson_roms-marbl_v0.1"
model_spec = default_catalog.load_model_spec(model_name)

print(f"Loaded ModelSpec: {model_spec.name}")
print(f"Type: {type(model_spec)}")

Inspect ModelSpec Structure

The ModelSpec is a Pydantic model with a few top-level fields. Let’s explore each one:

# View all ModelSpec attributes
print("ModelSpec attributes:")
# Use the class to access model_fields (not the instance) to avoid deprecation warning
for attr in model_spec.__class__.model_fields.keys():
    value = getattr(model_spec, attr)
    if isinstance(value, (list, dict)) and len(str(value)) > 100:
        print(f"  - {attr}: {type(value).__name__} (length: {len(value)})")
    else:
        print(f"  - {attr}: {value}")

Code & Template Specification

The code field pins the ROMS/MARBL/PIO source repositories and references the compile-time and run-time Jinja2 templates. Template directory paths are relative to the forge repo root (the templates live in the forge repo’s own templates/ tree, decoupled from any one ModelSpec); code.templates_commit pins the forge commit they’re fetched from (defaults to branch main if omitted).

print("Code Repository Specification:")
print(f"  ROMS location: {model_spec.code.roms.location}")
print(f"  ROMS commit: {model_spec.code.roms.commit}")
print(f"  ROMS branch: {model_spec.code.roms.branch}")

if model_spec.code.marbl:
    print(f"  MARBL location: {model_spec.code.marbl.location}")
    print(f"  MARBL commit: {model_spec.code.marbl.commit}")
else:
    print("  MARBL: Not specified")

if model_spec.code.pio:
    print(f"  PIO location: {model_spec.code.pio.location}")
    print(f"  PIO commit: {model_spec.code.pio.commit}")
else:
    print("  PIO: Not specified")

print("\nTemplates Specification:")
print(f"  Compile-time directory: {model_spec.code.templates_compile_time.directory}")
print(f"  Compile-time files: {model_spec.code.templates_compile_time.files}")
print(f"  Run-time directory: {model_spec.code.templates_run_time.directory}")
print(f"  Run-time files: {model_spec.code.templates_run_time.files}")

Model Settings

The model_settings field is a flat dict of model-specific physics/numerics defaults, one section per namelist block (cppdefs, param, tides, marbl_bgc, ...) or scalar namelist value (gamma2, ubind).

print("model_settings top-level sections:")
for key in model_spec.model_settings:
    print(f"  - {key}")

print("\ncppdefs section:")
print(model_spec.model_settings["cppdefs"])

Build-mode Toggles

bgc_mode and use_pio are per-run toggles, not part of model_settings -- they prepopulate the wizard’s BGC dropdown / PIO checkbox, and the resolver (build_forge_blueprint) derives the corresponding cppdefs flags from them.

print(f"bgc_mode: {model_spec.bgc_mode}")
print(f"use_pio: {model_spec.use_pio}")

Accessing Nested Fields

You can access nested fields using dot notation. Here are some examples:

# Examples of accessing nested fields
print(f"ROMS repository URL: {model_spec.code.roms.location}")
print(f"BGC tracer count (ntrc_bio): {model_spec.model_settings['param']['ntrc_bio']}")
print(f"Compile-time template files: {model_spec.code.templates_compile_time.files}")

ModelSpec as Dictionary

You can convert the ModelSpec to a dictionary for inspection or serialization:

# Convert to dictionary (Pydantic model_dump)
model_dict = model_spec.model_dump()

print("ModelSpec as dictionary (top-level keys):")
for key in model_dict.keys():
    print(f"  - {key}")

# You can also use model_dump_json() for JSON serialization
# import json
# json_str = model_spec.model_dump_json(indent=2)

Summary

The ModelSpec provides a structured, validated representation of model configurations:

  • Type-safe: Pydantic models provide validation and type checking

  • Accessible: Use dot notation to access nested fields

  • Serializable: Convert to dict/JSON for storage or inspection

  • Complete: Contains code refs, template refs, build-mode toggles, and model-specific settings defaults

This specification is consumed by the wizard/resolver (cstar_forge.forge_blueprint_resolve.build_forge_blueprint), which merges it with a selected Domain/Forcing/Output spec to assemble a ForgeBlueprint, and by the forge application that executes that blueprint.