Configuration
Cocoa uses YAML configuration files for simulation setup. This document describes all available configuration options.
Configuration File Structure
A complete configuration file contains the following sections:
mesh:
# Mesh file and projection settings
simulation:
# Simulation time control
initial_conditions:
# Initial state
physics:
# Physical parameters
numeric:
# Numerical solver parameters
forcing:
# Forcing configuration (tides, meteorological, ramp)
output:
# Output file configuration
diagnostics:
# Logging and screen output
checkpoint:
# Checkpoint/restart (optional)
Validation
Configuration files are validated against a schema at startup, before any other input is read. Unknown keys (with “did you mean” suggestions for near-misses), missing required fields, wrong value types, and out-of-range values are reported together in a single pass.
Boolean values must be written as true or false; the YAML 1.1
spellings yes/no/on/off are rejected. A key present with no
value behaves as if the key were omitted, and the default applies.
The complete schema is reproduced in the Schema Reference at the end of this page.
Mesh Section
Specifies the mesh file, coordinate projection, and optional coordinate rotation for global meshes.
mesh:
filename: "mesh.nc" # Path to mesh file (required)
projection:
type: "EquidistantCylindrical" # Projection type (optional)
center: [-76.5, 23.2] # Projection center [lon, lat] (optional)
rotation: # Coordinate rotation (optional)
enabled: false
pole_location: [0.0, 0.0] # [longitude, latitude] of new North Pole
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
string |
(required) |
Path to mesh file (NetCDF UGRID format) |
|
string |
|
Coordinate projection type |
|
[lon, lat] |
[0.0, 0.0] |
Projection center coordinates |
Coordinate Rotation (Global Meshes)
For global ocean models, coordinate rotation moves the computational poles away from the geographic poles to avoid singularities.
mesh:
rotation:
enabled: true
pole_location: [0.0, 0.0] # [longitude, latitude] of new North Pole
Rotation Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
false |
Enable coordinate rotation |
|
[lon, lat] |
(required) |
Geographic coordinates where the new North Pole is located [degrees] |
When enabled: true, the pole_location parameter must be specified.
Pole Location Specification:
The pole_location specifies where the geographic North Pole will be relocated
to in the rotated coordinate system.
Common choices:
[0.0, 0.0]: North Pole moves to the equator at the prime meridian[180.0, 0.0]: North Pole moves to the equator at the date line[-90.0, 0.0]: North Pole moves to the equator in the Atlantic
Example: Rotate pole to equator:
mesh:
rotation:
enabled: true
pole_location: [0.0, 0.0] # Moves North Pole to equator at prime meridian
Effects of rotation:
Node coordinates are transformed to the rotated frame
Metric terms (spherical
tan(phi)correction, projection scale factors) use the rotated latitude – they belong to the frame the equations are discretized inCoriolis parameter continues to use geographic latitude; the planetary rotation term is frame-independent
Tidal potential continues to use geographic latitude
Output velocities are transformed back to geographic (east, north) frame
See Coordinate Rotation in the Theory documentation for details and Global Simulations for a complete guide.
Simulation Section
Controls simulation timing.
simulation:
start_time: 2025-01-01 # Simulation start time (required)
end_time: 2025-01-15 # Simulation end time (required)
time_step: 10s # Time step (default 1s), e.g. 10s, 1m, 0.5s
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
datetime |
(required) |
Simulation start time |
|
datetime |
(required) |
Simulation end time |
|
duration |
|
Computational time step. Accepts a duration string
(e.g. |
DateTime formats supported:
2025-01-01(date only, midnight assumed)2025-01-01T12:00:00(ISO 8601 format)
Initial Conditions Section
Sets initial state for the simulation.
initial_conditions:
water_level: 0.0 # Initial water surface elevation [m]
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
float |
0.0 |
Initial water surface elevation [m] |
Physics Section
Physical model parameters.
physics:
manning_n: 0.025 # Manning's roughness coefficient (or "mesh")
tau0: 0.005 # GWCE weighting parameter (or "mesh")
cf_lower_limit: 0.001 # Minimum friction coefficient
internal_tide_friction: 0 # Internal tide friction (0, constant, or "mesh")
smagorinsky_coefficient: 0.2 # Smagorinsky turbulence coefficient
min_viscosity: 1.0e-6 # Minimum eddy viscosity [m^2/s]
h0: 0.1 # Minimum depth threshold [m]
velmin: 0.01 # Minimum wetting velocity [m/s]
wet_dry_slope_limiter: 1.0e9 # Slope limiter coefficient
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
float or “mesh” |
0.025 |
Manning’s roughness coefficient for bottom friction |
|
float or “mesh” |
0.05 |
GWCE weighting parameter |
|
float |
0.001 |
Lower limit for the computed quadratic friction coefficient |
|
float |
0.1 |
Minimum total water depth (HBREAK) used in the bottom friction computation [m] |
|
float |
0.0 |
Minimum velocity used in the bottom friction computation [m/s] |
|
float, “mesh”, or 0 |
0 |
Internal tide friction coefficient [1/s]. Set to |
|
float |
0.1 |
Minimum depth threshold for wet elements [m] |
|
float |
0.01 |
Minimum velocity for node wetting [m/s] |
|
float |
0.2 |
Smagorinsky subgrid turbulence coefficient |
|
float |
1.0e-6 |
Minimum eddy viscosity [m^2/s] |
|
float |
0.0025 |
Maximum drag coefficient for wind stress |
|
0 or “mesh” |
0 |
Directional effective roughness lengths for wind reduction. Set to
|
|
float or “mesh” |
1.0 |
Binary canopy mask for wind reduction (0 or 1). Set to |
|
float |
1.0e9 |
Wet/dry shallow-water slope limiter coefficient (ADCIRC |
|
float or “mesh” |
(disabled) |
Optional selective post-continuity elevation-gradient limiter [m/m].
Absent/ |
Spatially-Varying Parameters
The manning_n, tau0, internal_tide_friction,
surface_directional_roughness, and surface_canopy_coefficient parameters
support spatially-varying values from the mesh file. To enable this, set the
parameter value to mesh:
physics:
manning_n: mesh # Read from "mannings_n_at_sea_floor"
tau0: mesh # Read from "primitive_weighting_in_continuity_equation"
internal_tide_friction: mesh # Read from "internal_tide_friction"
surface_directional_roughness: mesh # Read from "surface_directional_effective_roughness_length"
surface_canopy_coefficient: mesh # Read from "surface_canopy_coefficient"
When set to mesh, Cocoa will read the corresponding nodal attribute from
the NetCDF mesh file:
Parameter |
Mesh Variable Name |
Description |
|---|---|---|
|
|
Manning’s n at each node [s/m^(1/3)] |
|
|
GWCE tau0 at each node [1/s] |
|
|
Internal tide friction coefficient at each node [1/s]. Supports both scalar (1 value per node, isotropic) and tensor (3 values per node: xx, yy, xy components) storage in the mesh file. |
|
|
Directional land roughness lengths at each node [m]. Stored as a 12-component vector (one per 30-degree directional bin). |
|
|
Canopy coefficient at each node [dimensionless, 0–1]. Multiplicative reduction applied to wind velocity under forest canopy. |
If the mesh file does not contain the required variable when mesh is
specified, Cocoa will report an error and exit.
See Mesh Preparation for details on creating mesh files with nodal attributes.
Wind Reduction
When meteorological forcing is enabled, Cocoa can apply two types of overland wind reduction before computing wind stress:
Directional roughness reduction (
surface_directional_roughness: mesh): Reduces wind speed based on the ratio of upwind land surface roughness to marine roughness. Uses 12 directional bins (30-degree spacing) with linear interpolation between bins.Canopy coefficient (
surface_canopy_coefficient: mesh): Applies a simple multiplicative reduction to wind components to represent sheltering by forest canopy. A value of 1.0 means no reduction; 0.0 means complete sheltering.
Both reductions are applied in sequence before the drag law computes wind stress. The processing order within the meteorological forcing kernel is:
Apply directional roughness reduction (if enabled)
Apply canopy coefficient (if enabled)
Apply meteorological ramp
Compute kinematic wind stress from the reduced, ramped wind
Example enabling both wind reduction attributes:
physics:
surface_directional_roughness: mesh # 12-directional land roughness
surface_canopy_coefficient: mesh # Canopy sheltering factor
Bottom Friction:
The friction coefficient is computed from Manning’s n:
where \(C_{f,min}\) is cf_lower_limit.
Wetting and Drying Algorithm
The wet/dry algorithm controls how elements transition between wet and dry states.
Minimum Depth Threshold (H0):
The h0 parameter sets the minimum total water depth for a node
to be considered wet. When the total depth falls below this threshold, the
node transitions to dry. Typical values range from 0.01 to 0.5 meters.
Minimum Wetting Velocity (VELMIN):
The velmin parameter controls the minimum velocity required for
water to advance onto a dry node during the wetting process. Lower values
allow easier wetting but may cause numerical oscillations. Default is 0.01 m/s.
Slope Limiter (SLIM):
The wet_dry_slope_limiter parameter limits water surface gradients in
shallow water to prevent spurious oscillations. The limiter computes a
scaling factor \(\alpha\) for the elevation gradient:
where \(h\) is bathymetric depth and \(\zeta\) is water surface elevation. The gradient is scaled by \(\min(\alpha, 1)\).
Default (1.0e9): Effectively disables limiting
Typical active value (0.0004): Applies gradient limiting in shallow areas
Example enabling slope limiting:
physics:
h0: 0.1
velmin: 0.01
wet_dry_slope_limiter: 0.0004
Numeric Section
Numerical solver parameters.
numeric:
solver: explicit # Solver type (default: explicit)
gwce_coefficients: [0.0, 1.0, 0.0] # Temporal weights [a00, b00, c00]
linear_solver: # CG solver settings (consistent only)
type: belos_cg
tolerance: 1.0e-5
max_iterations: 50
convergence_scaling: norm_of_initial_residual
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
string |
|
GWCE solver type (see below) |
|
[a00, b00, c00] |
[0.0, 1.0, 0.0] |
GWCE temporal integration weights |
Solver Types:
The solver parameter accepts the following values:
Value |
Description |
|---|---|
|
Diagonal mass matrix with direct solve (faster, coefficients set to [0, 1, 0]) |
|
Sparse matrix with iterative CG solver (more accurate, semi-implicit) |
When using the explicit/lumped solver, the gwce_coefficients are automatically
set to [0, 1, 0] regardless of user specification. For the implicit/consistent
solver, typical values are [0.35, 0.30, 0.35].
GWCE Coefficients:
The coefficients control temporal weighting in the GWCE:
a00: Weight for time level n+1b00: Weight for time level nc00: Weight for time level n-1
Linear Solver Configuration
The linear_solver subsection controls the iterative Conjugate Gradient solver
used by the consistent (implicit) GWCE solver. These settings are ignored when
using the explicit/lumped solver.
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
string |
|
CG solver implementation (see below) |
|
float |
1.0e-5 |
Convergence tolerance for the iterative solver. The solver terminates when the (scaled) residual norm drops below this value. |
|
int |
50 |
Maximum number of CG iterations per solve. If the solver does not converge within this limit, it reports unconverged. |
|
int |
0 |
Solver output verbosity: |
|
string |
|
How the residual is scaled when testing convergence (see below) |
Solver Implementation Types:
The type parameter selects the CG algorithm variant. All variants solve
the same linear system with Jacobi preconditioning; they differ in
communication pattern and internal implementation.
Value |
Description |
|---|---|
|
Standard Belos CG. The most portable and well-tested implementation. Uses classical Belos convergence testing with configurable verbosity output. |
|
Tpetra-native pipelined CG. Overlaps communication with computation by pipelining inner products, which can reduce latency on distributed systems with many MPI ranks. |
|
Tpetra-native single-reduce CG. Combines two inner products per iteration into a single MPI allreduce, reducing synchronization points. Useful on high-latency interconnects. |
For most simulations, the default belos_cg is recommended. The Tpetra-native
variants may offer better parallel scalability on large distributed runs but
produce identical mathematical results.
Convergence Scaling:
The convergence_scaling parameter determines how the residual norm is
normalized when checking the convergence criterion.
Value |
Description |
|---|---|
|
Relative convergence: the solver converges when \(\|r_k\| / \|r_0\| < \text{tolerance}\). This is the most common choice and makes the tolerance independent of problem scaling. |
|
Like |
|
Absolute convergence: the solver converges when \(\|r_k\| < \text{tolerance}\). The tolerance must be chosen relative to the expected magnitude of the right-hand side. |
Example: Consistent solver with custom linear solver settings:
numeric:
solver: consistent
gwce_coefficients: [0.35, 0.30, 0.35]
linear_solver:
type: belos_cg
tolerance: 1.0e-6
max_iterations: 100
convergence_scaling: norm_of_initial_residual
Forcing Section
Configures tidal and meteorological forcing, along with the spinup ramp.
Ramp Configuration
forcing:
ramp:
enabled: true # Enable spinup ramp
duration: 1d # Ramp duration (e.g. 1d, 12h, 2d)
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
true |
Enable hyperbolic tangent spinup ramp |
|
duration |
|
Duration of spinup ramp. Accepts a duration string
(e.g. |
By default, the same ramp duration is applied to both tidal and meteorological
forcing. To use a different ramp for meteorological forcing, add an optional
ramp subsection under forcing.meteorological:
forcing:
ramp:
enabled: true
duration: 5d # Tidal ramp duration
meteorological:
enabled: true
format: cf_netcdf
filename: "met.nc"
ramp: # Optional: overrides forcing.ramp for met
enabled: true
duration: 1d # Shorter met ramp
When the forcing.meteorological.ramp section is absent, meteorological
forcing uses the global forcing.ramp values.
Meteorological Ramp Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
(from |
Enable met-specific spinup ramp |
|
duration |
(from |
Met ramp duration. Accepts a duration string or a bare number of seconds. |
See Meteorological Ramp for details on the ramp function.
Meteorological Forcing
Configures atmospheric wind and pressure forcing. See Meteorological Forcing for full details on file formats and usage.
forcing:
meteorological:
enabled: true
format: cf_netcdf # cf_netcdf, owi_ascii, owi_netcdf, or grib
filename: "path/to/meteo_data.nc" # Single file (cf_netcdf, owi_netcdf)
This is the flat, single-source form. Two or more sources (mixed formats,
nested grids, a reduced vs. unreduced field) are configured as a
forcing.meteorological.domains list instead; see
Meteorological Forcing for the composition rules.
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
false |
Enable meteorological forcing |
|
string |
|
File format: |
|
string |
(one of |
Path to meteorological data file (CF NetCDF, OWI NetCDF, or a single GRIB file) |
|
list |
(one of |
List of pressure/wind file pairs (OWI ASCII), or a list of GRIB files (GRIB) |
|
string |
(required for GRIB) |
Preset weather product name (e.g. |
|
string |
|
Wind drag coefficient formulation |
|
float |
100.0 |
Scale factor for pressure, OWI formats only (default converts hPa to
Pa). Rejected for |
|
float |
1.0 |
Scale factor for wind velocity |
|
bool |
true |
Opt out of overland wind reduction for this source by setting
|
CF NetCDF Variable Names:
When using the cf_netcdf format, you can override the default variable
names used to read the meteorological data:
forcing:
meteorological:
enabled: true
format: cf_netcdf
filename: "met_data.nc"
variables:
pressure: "mslp" # Default: "mslp"
wind_u: "wind_u" # Default: "wind_u"
wind_v: "wind_v" # Default: "wind_v"
time: "time" # Default: "time"
lon: "lon" # Default: "lon"
lat: "lat" # Default: "lat"
For OWI ASCII format, use filenames with paired pressure/wind files:
forcing:
meteorological:
enabled: true
format: owi_ascii
filenames:
- pressure: "basin.pre"
wind: "basin.wnd"
For GRIB2 (requires a build with cocoa_ENABLE_GRIB), name a weather
product preset and the file list; see
Meteorological Forcing for the available products,
numeric variables overrides, and multi-source composition:
forcing:
meteorological:
enabled: true
format: grib
product: gfs
filenames: ["gfs_f000.grib2", "gfs_f003.grib2"]
External File Inclusion
Two configuration blocks routinely grow long enough to be worth maintaining
as separate, reusable files: meteorological file lists (a multi-day forecast
run’s GRIB list can span hundreds of files) and the open-ocean tide boundary
block (per-node constituent data). At exactly these locations, a node’s
content may be replaced with an include mapping naming a YAML file whose
root content is spliced in place of the node before validation runs – the
result is indistinguishable from writing the same content inline:
forcing:
meteorological:
enabled: true
format: grib
product: gfs
filenames:
include: hafs_ida_files.yaml # a YAML list of file paths
tide:
boundary:
include: wnat_tide_boundary.yaml # the whole boundary block
Rules:
includeis accepted only atforcing.meteorological.filenames, adomainsentry’sfilenames,forcing.tide.boundary, andforcing.tide.boundary.constituents. Anywhere else it is a configuration error naming the allowed locations.The
includemapping must contain only theincludekey.Relative paths resolve against the directory of the file containing the
include, so a configuration and its included files move together as a portable bundle.Included files may not themselves contain
includenodes (one level only).
Flow Boundary Forcing
Configures normal-flow (discharge) boundary conditions driven by per-segment time series.
forcing:
flow_boundary:
enabled: true
ramp: # Optional spinup ramp for flow boundaries
enabled: true
duration: 1d
segments:
- segment_index: 0
time_series_file: "inflow_0.txt"
- segment_index: 1
time_series_file: "inflow_1.txt"
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
false |
Enable flow boundary forcing |
|
ramp |
(from |
Optional spinup ramp applied to flow boundaries. Accepts |
|
list |
(none) |
List of flow boundary segments. Each entry maps a flow boundary to a time series file. |
Each segments entry contains:
segment_index: Index of the flow boundary segment in the meshtime_series_file: Path to the discharge time series file for that segment
Tidal Potential Forcing
The tide potential can be computed using either harmonic constituents or the
astronomical method. The type parameter selects the method:
constituent(orharmonic): Uses pre-defined tidal constituentsastronomical(orephemeris,direct): Computes directly from Moon and Sun positionsauto(default): Selects automatically based on what is configured
Harmonic Constituent Method:
forcing:
tide:
potential:
enabled: true
type: constituent
constituents:
- name: M2
frequency: 0.000140518902509 # rad/s
amplitude: 0.242334 # m
etrf: 0.693 # Earth tide reduction factor
nodal_factor: 0.96461 # Nodal modulation
equilibrium_arg: 315.69 # degrees
Constituent Parameters:
Parameter |
Units |
Description |
|---|---|---|
|
string |
Constituent name (Q1, O1, P1, K1, N2, M2, S2, K2, etc.) |
|
rad/s |
Angular frequency |
|
m |
Tidal potential constant K |
|
Earth tide reduction factor |
|
|
Nodal modulation factor f |
|
|
degrees |
Equilibrium argument V+u |
Astronomical Method:
forcing:
tide:
potential:
enabled: true
type: astronomical
astronomical:
order: 4 # Expansion order: 2=P2, 3=P3, 4=P3 (ADCIRC alias)
include_nutation: true # Include nutation corrections
k2: 0.302 # Love number (optional)
h2: 0.609 # Love number (optional)
Astronomical Parameters:
Parameter |
Default |
Description |
|---|---|---|
|
4 |
Legendre polynomial expansion order. 2 (P2) is standard equilibrium tide; 3 (P3) adds degree-3 corrections; 4 (named for ADCIRC’s TIPOrder=4) evaluates the same degree-2 + degree-3 expansion as 3. |
|
true |
Include nutation corrections in celestial position calculations. |
|
0.302 |
Second-degree Love number for body tide. |
|
0.609 |
Second-degree Love number for vertical displacement. |
When using the astronomical method, individual constituent specification is not needed. See Tidal Forcing for details.
Tidal Boundary Forcing
Elevation-specified tidal boundary conditions.
forcing:
tide:
boundary:
enabled: true
constituents:
- name: M2
frequency: 0.000140518902509 # rad/s
nodal_factor: 0.96461 #
equilibrium_arg: 315.69 # degrees
boundary_values: # Per-node amplitude/phase
- { amplitude: 0.52, phase: 344.17 }
- { amplitude: 0.51, phase: 345.15 }
# ... one entry per open boundary node
Constituent Parameters:
Parameter |
Units |
Description |
|---|---|---|
|
string |
Constituent name |
|
rad/s |
Angular frequency |
|
Nodal modulation factor |
|
|
degrees |
Equilibrium argument |
|
list |
Per-node amplitude [m] and phase [degrees] |
Each boundary_values entry contains:
amplitude: Tidal amplitude in metersphase: Tidal phase in degrees
Self-Attraction and Loading (SAL)
SAL corrections account for the ocean’s gravitational self-attraction and Earth deformation under tidal loads. SAL data must be pre-computed and embedded in the mesh file (see Tidal Forcing).
forcing:
tide:
sal:
enabled: true
parameter_source: "auto" # or "manual"
Parameters:
Parameter |
Default |
Description |
|---|---|---|
|
false |
Enable SAL forcing |
|
“auto” |
How to determine constituent parameters. |
In manual mode, provide constituent parameters explicitly:
forcing:
tide:
sal:
enabled: true
parameter_source: "manual"
constituents:
- name: M2
frequency: 1.405189028e-04 # rad/s
nodal_factor: 1.026777
equilibrium_arg: 26.668130 # degrees
Output Section
Controls simulation output. By default the output file is named
cocoa_output.nc in the working directory. Use the filename parameter
to specify a different name.
output:
filename: "cocoa_output.nc" # Output file name (optional, default: cocoa_output.nc)
step_interval: 1h # Output every hour (duration or integer step count)
mode: split # "split" (default) or "combined"
variables: # Selectively disable time-series variables
pressure: false
wind: false
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
string |
|
Output file name (NetCDF format) |
|
int or duration |
100 |
Interval between output writes. Accepts a plain integer (number of
time steps) or a duration string with suffix: |
|
string |
|
Controls where peak variables are written. In |
|
map |
(all enabled) |
Selectively disable time-series output variables. List variable names
with |
|
map |
|
NetCDF deflate settings: |
Diagnostics Section
Controls logging and screen output.
diagnostics:
screen_interval: 2h # Screen output every 2 hours (duration or integer step count)
log_file: "simulation.log" # Structured log file path (optional)
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
int or duration |
100 |
Interval between screen output. Accepts a plain integer (number of
time steps) or a duration string (e.g., |
|
string |
(none) |
Path to log file (JSON structured log format) |
Checkpoint Section
Configures checkpoint/restart for long-running simulations. See Checkpoint / Restart for a complete guide.
checkpoint:
enabled: true
write_interval: 12h # Write checkpoint every 12 hours
file_prefix: "cocoa_checkpoint" # Prefix for checkpoint files
restart_file: "" # Path to checkpoint file to restart from
Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
false |
Enable the checkpoint/restart system |
|
int or duration |
0 |
How often to write checkpoints. |
|
string |
|
Filename prefix. Each write produces a timestamped file
|
|
string |
(none) |
Path to a checkpoint file to restart from. When set, the simulation resumes from the saved state. |
Writing checkpoints:
checkpoint:
enabled: true
write_interval: 12h
file_prefix: "cocoa_checkpoint"
Restarting from a checkpoint:
checkpoint:
enabled: true
restart_file: "cocoa_checkpoint.20250101T120000.nc"
Complete Example
A complete configuration file for a tidal simulation:
mesh:
filename: "gulf_mesh.nc"
projection:
type: "EquidistantCylindrical"
center: [-90.0, 25.0]
simulation:
start_time: 2025-01-01
end_time: 2025-01-15
time_step: 10s
initial_conditions:
water_level: 0.0
physics:
manning_n: 0.025
tau0: 0.005
cf_lower_limit: 0.001
numeric:
solver: implicit
gwce_coefficients: [0.35, 0.30, 0.35]
linear_solver:
type: belos_cg
tolerance: 1.0e-5
max_iterations: 50
forcing:
ramp:
enabled: true
duration: 1d
tide:
potential:
enabled: false
boundary:
enabled: true
constituents:
- name: M2
frequency: 1.405189028e-04
nodal_factor: 0.964
equilibrium_arg: 23.06
boundary_values:
- { amplitude: 0.50, phase: 340.0 }
- { amplitude: 0.48, phase: 342.0 }
# ... additional boundary nodes
output:
filename: "gulf_output.nc"
step_interval: 10m
diagnostics:
screen_interval: 1h
Duration Syntax
Time-based fields share a common duration grammar. A duration string consists of a numeric value followed by a unit suffix:
Suffix |
Unit |
Example |
|---|---|---|
|
seconds |
|
|
minutes |
|
|
hours |
|
|
days |
|
The grammar is used by two groups of fields with slightly different handling of a bare number (one with no suffix):
Pure durations –
simulation.time_stepand the rampdurationfields (forcing.ramp.duration,forcing.meteorological.ramp.duration,forcing.flow_boundary.ramp.duration). A bare number is interpreted as seconds (time_step: 2.0is identical totime_step: 2s).Step intervals –
output.step_interval,diagnostics.screen_intervalandcheckpoint.write_interval. A bare integer is interpreted as a count of time steps (step_interval: 3600means every 3600 steps). A suffixed duration must be evenly divisible bytime_step; for example20mwithtime_step: 7serrors because 1200 s is not a multiple of 7 s.
Rules:
Fractional values are allowed:
0.5h= 30 minutes,0.25d= 6 hours.0is legal only forcheckpoint.write_interval, where it means “write a single checkpoint at the end of the run” (see Checkpoint Section); the other intervals must be positive.
Examples:
simulation:
time_step: 2s # 2-second time step (or: 2.0)
forcing:
ramp:
duration: 12h # 12-hour spinup ramp (or: 43200)
output:
step_interval: 15m # Every 15 minutes (= 450 steps)
diagnostics:
screen_interval: 2h # Every 2 hours (= 3600 steps)
checkpoint:
enabled: true
write_interval: 12h # Every 12 hours (= 21600 steps)
Unit Conventions
Cocoa follows the following conventions for input units:
Quantity |
Input Units |
Internal Units |
|---|---|---|
Tidal frequency |
rad/s |
rad/hr |
Angles (phase, equilibrium_arg) |
degrees |
radians |
Amplitude |
meters |
meters |
Time step |
seconds |
seconds |
Ramp duration |
duration string or seconds |
seconds |
Environment Variables
Cocoa uses standard environment variables for runtime configuration:
Variable |
Description |
Default |
|---|---|---|
|
Number of OpenMP threads (CPU backend) |
All available |
|
GPU device selection (CUDA backend) |
(unset; all devices visible) |
Schema Reference
The schema below is the exact document the model validates against: it is
included here directly from the source tree
(src/cocoa_kernel/core/config/cocoa_config.schema.yaml), the same file
embedded into the binary at build time, so this reference cannot drift from
the running code. It is a JSON Schema (draft-07) document authored as YAML; the
conventions (null handling, weak scalar typing, closed key sets) are
documented in its header comment.
# SPDX-License-Identifier: LicenseRef-Proprietary
# Copyright (c) 2026 Zach Cobell
#
# JSON Schema (draft-07) for the Cocoa model configuration, authored as YAML
# and embedded into the binary at configure time (CocoaConfigSchemaText.hpp
# is generated from this file; see src/cocoa_kernel/CMakeLists.txt).
#
# Conventions:
# - Optional keys accept null: "key:" with no value behaves as absent and the
# parser applies the struct default. Required keys are strict. The engine
# also treats a quoted empty string as null, so 'key: ""' behaves as absent
# on optional keys too.
# - Scalar typing is weak (yaml-cpp discards scalar type information):
# "type: string" accepts any scalar; numbers validate by string parse. The
# engine details live in cocoa_io/SchemaValidation.cpp.
# - Enum VALUES (solver names, meteo formats, vortex models, ...) validate in
# the parser's EnumTables, not here; the schema declares plain strings.
# - Closed key sets everywhere (additionalProperties: false) except tidal
# constituents: a typo must be a schema error, not a silently ignored key.
# - anyOf alternatives stay scalar-shaped except the two genuinely structured
# unions (meteo filenames, meteo variables), which mirror the two legal
# input shapes; their failures report more verbosely than scalar unions.
# - Schema/parser drift is guarded in one direction only: the kitchen-sink
# test in test_cocoa_config_schema.cpp fails when a parser-read key is
# missing here. The converse -- a key declared here that no parser reads --
# validates and is silently ignored; the keep-in-sync comments below are
# the accepted defense for that direction.
"$schema": "http://json-schema.org/draft-07/schema#"
type: object
additionalProperties: false
required: [mesh, simulation]
properties:
mesh:
type: object
additionalProperties: false
required: [filename]
properties:
filename: {type: string}
projection:
type: [object, "null"]
additionalProperties: false
properties:
type: {$ref: "#/definitions/string_or_null"}
center: {$ref: "#/definitions/coordinate_pair"}
rotation:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
pole_location: {$ref: "#/definitions/coordinate_pair"}
simulation:
type: object
additionalProperties: false
# start_time is required too, UNLESS checkpoint.restart_file is set
# (the checkpoint then supplies it) -- a cross-section conditional this
# schema cannot express, enforced by parse_simulation_section instead.
required: [end_time]
properties:
start_time: {type: string}
end_time: {type: string}
time_step: {$ref: "#/definitions/positive_duration"}
initial_conditions:
type: [object, "null"]
additionalProperties: false
properties:
water_level: {$ref: "#/definitions/number_or_null"}
physics:
type: [object, "null"]
additionalProperties: false
properties:
manning_n: {$ref: "#/definitions/mesh_or_numeric"}
tau0: {$ref: "#/definitions/mesh_or_numeric"}
cf_lower_limit: {$ref: "#/definitions/non_negative_number"}
smagorinsky_coefficient: {$ref: "#/definitions/non_negative_number"}
min_viscosity: {$ref: "#/definitions/non_negative_number"}
min_depth_friction: {$ref: "#/definitions/non_negative_number"}
min_velocity_friction: {$ref: "#/definitions/non_negative_number"}
internal_tide_friction: {$ref: "#/definitions/mesh_or_numeric"}
h0: {$ref: "#/definitions/positive_number"}
velmin: {$ref: "#/definitions/non_negative_number"}
wet_dry_slope_limiter: {$ref: "#/definitions/positive_number"}
wind_drag_limit: {$ref: "#/definitions/non_negative_number"}
surface_directional_roughness: {$ref: "#/definitions/mesh_or_numeric"}
surface_canopy_coefficient: {$ref: "#/definitions/mesh_or_numeric"}
elemental_slope_limiter: {$ref: "#/definitions/mesh_or_numeric"}
numeric:
type: [object, "null"]
additionalProperties: false
properties:
solver: {$ref: "#/definitions/string_or_null"}
gwce_coefficients:
type: [array, "null"]
items: {type: number}
minItems: 3
maxItems: 3
linear_solver:
type: [object, "null"]
additionalProperties: false
properties:
type: {$ref: "#/definitions/string_or_null"}
tolerance: {$ref: "#/definitions/positive_number"}
max_iterations: {$ref: "#/definitions/positive_number"}
verbosity: {$ref: "#/definitions/non_negative_number"}
convergence_scaling: {$ref: "#/definitions/string_or_null"}
forcing:
type: [object, "null"]
additionalProperties: false
properties:
tide:
type: [object, "null"]
additionalProperties: false
properties:
potential:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
type: {$ref: "#/definitions/string_or_null"}
constituents:
type: [array, "null"]
items: {$ref: "#/definitions/tidal_constituent"}
astronomical:
type: [object, "null"]
additionalProperties: false
properties:
order: {$ref: "#/definitions/number_or_null"}
include_nutation: {$ref: "#/definitions/boolean_or_null"}
k2: {$ref: "#/definitions/number_or_null"}
h2: {$ref: "#/definitions/number_or_null"}
boundary:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
constituents:
type: [array, "null"]
items: {$ref: "#/definitions/tide_boundary_constituent"}
sal:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
parameter_source: {$ref: "#/definitions/string_or_null"}
constituents:
type: [array, "null"]
items: {$ref: "#/definitions/sal_constituent"}
meteorological:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
format: {$ref: "#/definitions/string_or_null"}
filename: {$ref: "#/definitions/string_or_null"}
filenames: {$ref: "#/definitions/meteo_filenames"}
variables: {$ref: "#/definitions/meteo_variables_selector"}
product: {$ref: "#/definitions/string_or_null"}
domains:
type: [array, "null"]
items: {$ref: "#/definitions/meteo_source_entry"}
drag_law: {$ref: "#/definitions/string_or_null"}
ice: {$ref: "#/definitions/boolean_or_null"}
ice_drag_law: {$ref: "#/definitions/string_or_null"}
wind_scale: {$ref: "#/definitions/number_or_null"}
pressure_scale: {$ref: "#/definitions/number_or_null"}
ice_scale: {$ref: "#/definitions/number_or_null"}
wind_reduction: {$ref: "#/definitions/boolean_or_null"}
vortex: {$ref: "#/definitions/vortex"}
ramp: {$ref: "#/definitions/ramp"}
ramp: {$ref: "#/definitions/ramp"}
flow_boundary:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
ramp: {$ref: "#/definitions/ramp"}
segments:
type: [array, "null"]
items:
type: object
additionalProperties: false
properties:
segment_index: {$ref: "#/definitions/number_or_null"}
time_series_file: {$ref: "#/definitions/string_or_null"}
# Baroclinic nodal forcing (BPG + free-surface correction, internal-tide
# drag, dispersion-as-friction). Keep in sync with parse_baroclinic in
# ForcingParsers.cpp; see docs/sphinx/user_guide/baroclinic_coupling.rst.
baroclinic:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
filename: {$ref: "#/definitions/string_or_null"}
ramp: {$ref: "#/definitions/ramp"}
internal_tide:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
dispersion:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
mode: {$ref: "#/definitions/string_or_null"}
deep_water_depth: {$ref: "#/definitions/positive_number"}
mld_coefficients:
type: [object, "null"]
additionalProperties: false
properties:
a: {$ref: "#/definitions/number_or_null"}
b: {$ref: "#/definitions/number_or_null"}
output:
type: [object, "null"]
additionalProperties: false
properties:
step_interval: {$ref: "#/definitions/positive_duration"}
filename: {$ref: "#/definitions/string_or_null"}
mode: {$ref: "#/definitions/string_or_null"}
compression:
type: [object, "null"]
additionalProperties: false
properties:
level: {type: [integer, "null"], minimum: 0, maximum: 9}
shuffle: {$ref: "#/definitions/boolean_or_null"}
variables:
# Closed key set: a typo in a variable toggle (e.g. "velocty") must
# be a schema error, not a silently ignored key. Keep in sync with
# KNOWN_VARS in ModelConfigurationFactory.cpp.
type: [object, "null"]
additionalProperties: false
properties:
zeta: {$ref: "#/definitions/boolean_or_null"}
velocity: {$ref: "#/definitions/boolean_or_null"}
pressure: {$ref: "#/definitions/boolean_or_null"}
wind: {$ref: "#/definitions/boolean_or_null"}
tide_potential: {$ref: "#/definitions/boolean_or_null"}
ice_concentration: {$ref: "#/definitions/boolean_or_null"}
diagnostics:
type: [object, "null"]
additionalProperties: false
properties:
screen_interval: {$ref: "#/definitions/positive_duration"}
log_file: {$ref: "#/definitions/string_or_null"}
checkpoint:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
write_interval: {$ref: "#/definitions/non_negative_duration"}
restart_file: {$ref: "#/definitions/string_or_null"}
file_prefix: {$ref: "#/definitions/string_or_null"}
definitions:
string_or_null: {type: [string, "null"]}
number_or_null: {type: [number, "null"]}
boolean_or_null: {type: [boolean, "null"]}
positive_number: {type: [number, "null"], exclusiveMinimum: 0}
non_negative_number: {type: [number, "null"], minimum: 0}
# A numeric value or the literal "mesh" (take the field from mesh nodal
# attributes). SchemaValidation.cpp recognizes this exact anyOf shape and
# reports its failures with a domain-specific message.
mesh_or_numeric:
anyOf:
- {type: number}
- {const: mesh}
- {type: "null"}
# A positive number of seconds or a duration string such as "4s", "1m",
# "2d". Under weak typing the string branch accepts any scalar, so numeric
# positivity here is structural documentation; the parser and the semantic
# validator enforce the real bounds.
positive_duration:
anyOf:
- {type: number, exclusiveMinimum: 0}
- {type: string}
- {type: "null"}
# As positive_duration, but zero is legal (e.g. "checkpointing disabled").
non_negative_duration:
anyOf:
- {type: number, minimum: 0}
- {type: string}
- {type: "null"}
coordinate_pair:
type: [array, "null"]
items: {type: number}
minItems: 2
maxItems: 2
ramp:
type: [object, "null"]
additionalProperties: false
properties:
enabled: {$ref: "#/definitions/boolean_or_null"}
duration: {$ref: "#/definitions/positive_duration"}
# Constituents may carry varying extra fields, so the key set stays open.
tidal_constituent:
type: object
additionalProperties: true
properties:
name: {$ref: "#/definitions/string_or_null"}
frequency: {$ref: "#/definitions/number_or_null"}
amplitude: {$ref: "#/definitions/number_or_null"}
etrf: {$ref: "#/definitions/number_or_null"}
equilibrium_arg: {$ref: "#/definitions/number_or_null"}
nodal_factor: {$ref: "#/definitions/number_or_null"}
sal_constituent:
type: object
additionalProperties: false
properties:
name: {$ref: "#/definitions/string_or_null"}
frequency: {$ref: "#/definitions/number_or_null"}
nodal_factor: {$ref: "#/definitions/number_or_null"}
equilibrium_arg: {$ref: "#/definitions/number_or_null"}
tide_boundary_constituent:
type: object
additionalProperties: false
properties:
name: {$ref: "#/definitions/string_or_null"}
frequency: {$ref: "#/definitions/number_or_null"}
nodal_factor: {$ref: "#/definitions/number_or_null"}
equilibrium_arg: {$ref: "#/definitions/number_or_null"}
boundary_values:
type: [array, "null"]
items:
type: object
additionalProperties: false
properties:
amplitude: {$ref: "#/definitions/number_or_null"}
phase: {$ref: "#/definitions/number_or_null"}
# The `filenames` key's shape, shared verbatim by the flat top-level form
# and each `domains:` entry so the two cannot drift apart: a list of file
# names, or a list of {pressure, wind} OWI pairs.
meteo_filenames:
anyOf:
- type: array
items: {type: string}
- type: array
items: {$ref: "#/definitions/owi_file_pair"}
- {type: "null"}
owi_file_pair:
type: object
additionalProperties: false
required: [pressure, wind]
properties:
pressure: {type: string}
wind: {type: string}
grib_selector:
type: [object, "null"]
additionalProperties: false
properties:
discipline: {$ref: "#/definitions/number_or_null"}
category: {$ref: "#/definitions/number_or_null"}
number: {$ref: "#/definitions/number_or_null"}
surface_type: {$ref: "#/definitions/number_or_null"}
level: {$ref: "#/definitions/number_or_null"}
# The `variables` key's shape (CF variable-name strings OR GRIB numeric
# identity selectors), shared verbatim by the flat top-level form and each
# `domains:` entry so the two cannot drift apart. `ice` is optional in both
# branches (CF: a variable-name string; GRIB: a numeric selector) -- a
# source with no ice simply omits it. Parser-level rules (rejecting a
# CF-shaped `ice` string on a GRIB entry, rejecting `ice_scale` on non-CF
# formats) are defense in depth on top of this shape; see ForcingParsers.cpp.
meteo_variables_selector:
anyOf:
- type: object
additionalProperties: false
properties:
pressure: {$ref: "#/definitions/string_or_null"}
wind_u: {$ref: "#/definitions/string_or_null"}
wind_v: {$ref: "#/definitions/string_or_null"}
time: {$ref: "#/definitions/string_or_null"}
lon: {$ref: "#/definitions/string_or_null"}
lat: {$ref: "#/definitions/string_or_null"}
ice: {$ref: "#/definitions/string_or_null"}
- type: object
additionalProperties: false
properties:
pressure: {$ref: "#/definitions/grib_selector"}
wind_u: {$ref: "#/definitions/grib_selector"}
wind_v: {$ref: "#/definitions/grib_selector"}
ice: {$ref: "#/definitions/grib_selector"}
- {type: "null"}
# One `domains:` list entry: a general, self-contained meteorological
# source. The structural key set mirrors the flat top-level form (format
# added, since each entry picks its own); cross-key rules (format required,
# self-contained vs. the flat form, per-format policies) are a parser
# concern, not a schema one.
meteo_source_entry:
type: object
additionalProperties: false
properties:
format: {$ref: "#/definitions/string_or_null"}
filename: {$ref: "#/definitions/string_or_null"}
filenames: {$ref: "#/definitions/meteo_filenames"}
variables: {$ref: "#/definitions/meteo_variables_selector"}
product: {$ref: "#/definitions/string_or_null"}
wind_scale: {$ref: "#/definitions/number_or_null"}
pressure_scale: {$ref: "#/definitions/number_or_null"}
ice_scale: {$ref: "#/definitions/number_or_null"}
wind_reduction: {$ref: "#/definitions/boolean_or_null"}
ramp: {$ref: "#/definitions/positive_duration"}
# model, pressure_estimate, and env_wind VALUES validate via the parser's
# EnumTables (the schema declares strings; enum membership is a parser
# concern). tracks is a non-empty list. blend_factor is lower-bounded at
# 1.0 (no meaningful upper bound, matching the parser and VortexOverlay
# guards); boundary_layer_factor carries the [0.75, 0.9] range the parser
# also enforces (defense in depth -- the two must never disagree). Keep the
# key set in sync with parse_vortex in ForcingParsers.cpp.
vortex:
type: [object, "null"]
additionalProperties: false
properties:
model: {$ref: "#/definitions/string_or_null"}
tracks:
type: [array, "null"]
items: {type: string}
minItems: 1
blend_factor: {type: [number, "null"], minimum: 1.0}
wind_reduction: {$ref: "#/definitions/boolean_or_null"}
pressure_estimate: {$ref: "#/definitions/string_or_null"}
pressure_anchor_hours: {type: [number, "null"], minimum: 0}
env_wind: {$ref: "#/definitions/string_or_null"}
boundary_layer_factor: {type: [number, "null"], minimum: 0.75, maximum: 0.9}
ramp: {$ref: "#/definitions/positive_duration"}