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) anduse_pioModel settings: a flat
model_settingsdict of model-specific physics/numerics defaults (mirrorsForgeBlueprint.model_settings1: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_catalogLoad 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.