============= Configuration ============= Cocoa uses YAML configuration files for simulation setup. Configuration File Structure ---------------------------- A complete configuration file contains the following sections: .. code-block:: yaml 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 :ref:`config-schema-reference` at the end of this page. Mesh Section ------------ Specifies the mesh file, coordinate projection, and optional coordinate rotation for global meshes. .. code-block:: yaml 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:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``filename`` - string - (required) - Path to mesh file (NetCDF UGRID format) * - ``projection.type`` - string - ``EquidistantCylindrical`` - Coordinate projection type * - ``projection.center`` - [lon, lat] - [0.0, 0.0] - Projection center coordinates .. _rotation-configuration: Coordinate Rotation (Global Meshes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ For global ocean models, coordinate rotation moves the computational poles away from the geographic poles to avoid singularities. .. code-block:: yaml mesh: rotation: enabled: true pole_location: [0.0, 0.0] # [longitude, latitude] of new North Pole **Rotation Parameters:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``rotation.enabled`` - bool - false - Enable coordinate rotation * - ``rotation.pole_location`` - [lon, lat] - (required) - Geographic coordinates where the new North Pole is located [degrees] When ``enabled: true``, the ``pole_location`` parameter must be specified. Common choices for ``pole_location``: - ``[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 **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 in - Coriolis 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 :ref:`coordinate-rotation` in the Theory documentation for details and :doc:`../user_guide/global_simulations` for a complete guide. Simulation Section ------------------ Controls simulation timing. .. code-block:: yaml 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:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``start_time`` - datetime - (required) - Simulation start time * - ``end_time`` - datetime - (required) - Simulation end time * - ``time_step`` - duration - ``1s`` - Computational time step. Accepts a :ref:`duration string ` (e.g. ``4s``, ``1m``) or a bare number of seconds (e.g. ``10.0``). 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. .. code-block:: yaml initial_conditions: water_level: 0.0 # Initial water surface elevation [m] **Parameters:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``water_level`` - float - 0.0 - Initial water surface elevation [m] Physics Section --------------- Physical model parameters. .. code-block:: yaml 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 wetting_velocity: linear # Wetting test form (linear, quadratic, inertial) **Parameters:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``manning_n`` - float or "mesh" - 0.025 - Manning's roughness coefficient for bottom friction * - ``tau0`` - float or "mesh" - 0.05 - GWCE weighting parameter * - ``cf_lower_limit`` - float - 0.001 - Lower limit for the computed quadratic friction coefficient * - ``min_depth_friction`` - float - 0.1 - Minimum total water depth (HBREAK) used in the bottom friction computation [m] * - ``min_velocity_friction`` - float - 0.0 - Minimum velocity used in the bottom friction computation [m/s] * - ``internal_tide_friction`` - float, "mesh", or 0 - 0 - Internal tide friction coefficient [1/s]. Set to ``0`` to disable, a constant value to apply uniformly, or ``mesh`` to read from the mesh file (see :ref:`spatially-varying-parameters`). * - ``h0`` - float - 0.1 - Minimum depth threshold for wet elements [m] * - ``velmin`` - float - 0.01 - Minimum velocity for node wetting [m/s] * - ``smagorinsky_coefficient`` - float - 0.2 - Smagorinsky subgrid turbulence coefficient * - ``min_viscosity`` - float - 1.0e-6 - Minimum eddy viscosity [m^2/s] * - ``wind_drag_limit`` - float - 0.0025 - Maximum drag coefficient for the circulation's wind stress; the wave model's is ``forcing.wave.model.sources.wind.drag_limit`` * - ``surface_directional_roughness`` - 0 or "mesh" - 0 - Directional effective roughness lengths for wind reduction. Set to ``mesh`` to read the 12-directional roughness field from the mesh file, or ``0`` to disable (see :ref:`wind-reduction-config`). * - ``surface_canopy_coefficient`` - float or "mesh" - 1.0 - Binary canopy mask for wind reduction (0 or 1). Set to ``mesh`` to read per-node values from the mesh file, or ``1`` to disable (identity). A fractional value fails loud. See :ref:`wind-reduction-config`. * - ``wet_dry_slope_limiter`` - float - 1.0e9 - Wet/dry shallow-water slope limiter coefficient (ADCIRC ``SLIM``). Distinct from ``elemental_slope_limiter`` below. * - ``wetting_velocity`` - "linear", "quadratic" or "inertial" - ``linear`` - How the nodal wetting test estimates the flow onto a dry node, and with it the friction boost after wetting. ``linear`` is ADCIRC's default; ``quadratic`` and ``inertial`` are its ``directvelWD`` and ``directvelWD`` + ``useHF`` settings, the latter the one Global STOFS uses. See :ref:`Wetting Velocity `. * - ``elemental_slope_limiter`` - float or "mesh" - (disabled) - Optional selective post-continuity elevation-gradient limiter [m/m]. Absent/``null`` disables it; a constant applies one threshold everywhere; ``mesh`` reads per-node thresholds from the mesh file. See :doc:`../user_guide/elemental_slope_limiter`. * - ``advection`` - bool, "off_at_open_boundaries" or "mesh" - ``off_at_open_boundaries`` - Where the advective terms are evaluated. ``off_at_open_boundaries`` (the default) disables advection along the open, flow and radiation boundary strings, ``true`` applies it everywhere, ``false`` disables it everywhere, and ``mesh`` reads a per-node binary mask (1 = on, 0 = off) from the mesh file's ``advection_state`` nodal attribute. A fractional mesh value fails loud; ``yes``/``on``/``1`` are not accepted spellings. See :ref:`advection-state-config`. .. _advection-state-config: Advection ^^^^^^^^^ Every mode resolves to the same per-node binary mask; they differ only in where it comes from. The mask is reduced to one flag per element once at startup, and **an element evaluates advection only when every one of its corner nodes does** (ADCIRC's ``ADVECTLOCAL``). A node with advection off therefore switches it off in every element touching that node. .. code-block:: yaml physics: advection: off_at_open_boundaries # default: off where the domain ends # advection: true # everywhere # advection: false # nowhere # advection: mesh # per-node mask from the mesh file ``off_at_open_boundaries`` clears the mask at every node of the boundary strings where the domain is truncated -- elevation-specified (open), specified-flow and radiation -- so the disabled region is a band **one element thick** just inside those strings. That is where the advective terms are least well behaved: they reach for an upstream state the mesh does not hold. Land walls and weirs keep advection, because the flow they bound is inside the mesh; clearing them as well cost a channel bend its cross-bend balance one element in from each bank. For anything finer, write the mask you want into the mesh file and use ``mesh``: for example, to disable advection only on the open boundary and not on the inflow, set ``advection_state`` to 0 at those nodes and 1 everywhere else. See :doc:`../user_guide/mesh_preparation`. .. note:: ``off_at_open_boundaries`` became the default in place of "advection everywhere". A run that needs the previous behavior must set ``advection: true`` explicitly. .. _spatially-varying-parameters: 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``: .. code-block:: yaml 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: .. list-table:: :header-rows: 1 :widths: 20 40 40 * - Parameter - Mesh Variable Name - Description * - ``manning_n`` - ``mannings_n_at_sea_floor`` - Manning's n at each node [s/m^(1/3)] * - ``tau0`` - ``primitive_weighting_in_continuity_equation`` - GWCE tau0 at each node [1/s] * - ``internal_tide_friction`` - ``internal_tide_friction`` - 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. * - ``surface_directional_roughness`` - ``surface_directional_effective_roughness_length`` - Directional land roughness lengths at each node [m]. Stored as a 12-component vector (one per 30-degree directional bin). * - ``surface_canopy_coefficient`` - ``surface_canopy_coefficient`` - 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 :doc:`../user_guide/mesh_preparation` for details on creating mesh files with nodal attributes. .. _wind-reduction-config: Wind Reduction """""""""""""" When meteorological forcing is enabled, Cocoa can apply two types of overland wind reduction before computing wind stress: 1. **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. 2. **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. The processing order within the meteorological forcing kernel is: 1. Apply directional roughness reduction (if enabled) 2. Apply canopy coefficient (if enabled) 3. Apply meteorological ramp 4. Compute kinematic wind stress from the reduced, ramped wind **Bottom Friction:** The friction coefficient is computed from Manning's n: .. math:: C_f = \max\left(\frac{g n^2}{H^{1/3}}, C_{f,min}\right) where :math:`C_{f,min}` is ``cf_lower_limit``. Wetting and Drying Algorithm ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **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. .. _wetting-velocity-config: **Wetting Velocity:** ``wetting_velocity`` selects the force balance behind the velocity that ``velmin`` is compared against (equations in :doc:`../theory/wetdry`): - ``linear`` (default): the surface slope against friction held at its ``velmin`` value. ADCIRC's default. - ``quadratic``: the surface slope against quadratic friction. ADCIRC ``directvelWD = T``. - ``inertial``: the frictionless shallow-water speed, with a 100-fold friction boost at the wet neighbors after wetting. ADCIRC ``directvelWD = T`` with ``useHF = T``, the setting Global STOFS uses. To reproduce an ADCIRC run, match its ``&wetDryControl`` namelist; a fort.15 without one uses ``linear``. **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 :math:`\alpha` for the elevation gradient: .. math:: \alpha = \frac{\text{SLIM} \cdot |\nabla h|}{|\nabla \zeta|} where :math:`h` is bathymetric depth and :math:`\zeta` is water surface elevation. The gradient is scaled by :math:`\min(\alpha, 1)`. - **Default (1.0e9):** Effectively disables limiting - **Typical active value (0.0004):** Applies gradient limiting in shallow areas Example enabling slope limiting: .. code-block:: yaml physics: h0: 0.1 velmin: 0.01 wet_dry_slope_limiter: 0.0004 Numeric Section --------------- Numerical solver parameters. .. code-block:: yaml 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:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``solver`` - string - ``explicit`` - GWCE solver type (see below) * - ``gwce_coefficients`` - [a00, b00, c00] - [0.0, 1.0, 0.0] - GWCE temporal integration weights **Solver Types:** The ``solver`` parameter accepts the following values: .. list-table:: :header-rows: 1 :widths: 30 70 * - Value - Description * - ``explicit`` or ``lumped`` - Diagonal mass matrix with direct solve (faster, coefficients set to [0, 1, 0]) * - ``implicit``, ``iterative``, or ``consistent`` - 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+1 - ``b00``: Weight for time level n - ``c00``: 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. .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``type`` - string - ``belos_cg`` - CG solver implementation (see below) * - ``tolerance`` - float - 1.0e-5 - Convergence tolerance for the iterative solver. The solver terminates when the (scaled) residual norm drops below this value. * - ``max_iterations`` - int - 50 - Maximum number of CG iterations per solve. If the solver does not converge within this limit, it reports unconverged. * - ``verbosity`` - int - 0 - Solver output verbosity: ``0`` = silent, ``1`` = summary, ``2`` = per-iteration. * - ``convergence_scaling`` - string - ``norm_of_initial_residual`` - 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. .. list-table:: :header-rows: 1 :widths: 30 70 * - Value - Description * - ``belos_cg`` - Standard Belos CG. The most portable and well-tested implementation. Uses classical Belos convergence testing with configurable verbosity output. * - ``tpetra_cg_pipeline`` - Tpetra-native pipelined CG. Overlaps communication with computation by pipelining inner products, which can reduce latency on distributed systems with many MPI ranks. * - ``tpetra_single_reduce`` - Tpetra-native single-reduce CG. Combines two inner products per iteration into a single MPI allreduce, reducing synchronization points. Useful on high-latency interconnects. Use the default ``belos_cg``. The Tpetra-native variants may scale better on large distributed runs; all three produce identical mathematical results. **Convergence Scaling:** The ``convergence_scaling`` parameter determines how the residual norm is normalized when checking the convergence criterion. .. list-table:: :header-rows: 1 :widths: 30 70 * - Value - Description * - ``norm_of_initial_residual`` - Relative convergence: the solver converges when :math:`\|r_k\| / \|r_0\| < \text{tolerance}`. This is the most common choice and makes the tolerance independent of problem scaling. * - ``norm_of_prec_init_res`` - Like ``norm_of_initial_residual`` but scales by the preconditioned initial residual :math:`\|M^{-1} r_0\|` instead. This can be useful when the preconditioner significantly changes the residual norm. * - ``none`` - Absolute convergence: the solver converges when :math:`\|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:** .. code-block:: yaml 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 the spinup ramp and the tidal, meteorological, wave and flow-boundary forcing. Ramp Configuration ^^^^^^^^^^^^^^^^^^ .. code-block:: yaml forcing: ramp: enabled: true # Enable spinup ramp duration: 1d # Ramp duration (e.g. 1d, 12h, 2d) **Parameters:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``ramp.enabled`` - bool - true - Enable hyperbolic tangent spinup ramp * - ``ramp.duration`` - duration - ``1d`` - Duration of spinup ramp. Accepts a :ref:`duration string ` (e.g. ``1d``, ``12h``) or a bare number of seconds. To use a different ramp for meteorological forcing, add an optional ``ramp`` subsection under ``forcing.meteorological``: .. code-block:: yaml 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 **Meteorological Ramp Parameters:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``meteorological.ramp.enabled`` - bool - (from ``ramp.enabled``) - Enable met-specific spinup ramp * - ``meteorological.ramp.duration`` - duration - (from ``ramp.duration``) - Met ramp duration. Accepts a :ref:`duration string ` or a bare number of seconds. See :ref:`meteorological-ramp` for details on the ramp function. .. _meteo-forcing-config: Meteorological Forcing ^^^^^^^^^^^^^^^^^^^^^^ Configures atmospheric wind and pressure forcing. See :doc:`../user_guide/meteorological_forcing` for full details on file formats and usage. .. code-block:: yaml 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 :doc:`../user_guide/meteorological_forcing` for the composition rules. **Parameters:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``meteorological.enabled`` - bool - false - Enable meteorological forcing * - ``meteorological.format`` - string - ``cf_netcdf`` - File format: ``cf_netcdf`` (aliases: ``cf``, ``netcdf``), ``owi_ascii`` (alias: ``owi``), ``owi_netcdf``, or ``grib`` (alias: ``grib2``, requires ``cocoa_ENABLE_GRIB``) * - ``meteorological.filename`` - string - (one of ``filename``/``filenames``) - Path to meteorological data file (CF NetCDF, OWI NetCDF, or a single GRIB file) * - ``meteorological.filenames`` - list - (one of ``filename``/``filenames``) - List of pressure/wind file pairs (OWI ASCII), or a list of GRIB files (GRIB) * - ``meteorological.product`` - string - (required for GRIB) - Preset weather product name (e.g. ``gfs``, ``hrrr``) selecting the numeric GRIB2 field identities, or omit and supply a ``variables`` override * - ``meteorological.drag_law`` - string - ``garratt`` - Wind drag law of the circulation: ``garratt``, ``wu``, ``zijlema``, ``hwang`` or ``swell`` (:doc:`../theory/meteorological_forcing`), capped by ``physics.wind_drag_limit``. ``swell`` reads the wave model's spectrum and needs ``wave.source: model``. * - ``meteorological.pressure_scale`` - float - 100.0 - Scale factor for pressure, OWI formats only (default converts hPa to Pa). Rejected for ``cf_netcdf`` (units come from the file's ``units`` attribute) and ``grib`` (GRIB2 fields are SI by definition). * - ``meteorological.wind_scale`` - float - 1.0 - Scale factor for wind velocity * - ``meteorological.wind_reduction`` - bool - true - Opt out of overland wind reduction for this source by setting ``false``; the reduction applies only when the mesh carries the roughness/canopy attributes (see :ref:`wind-reduction-config`) **CF NetCDF Variable Names:** When using the ``cf_netcdf`` format, you can override the default variable names used to read the meteorological data: .. code-block:: yaml 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: .. code-block:: yaml 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 :doc:`../user_guide/meteorological_forcing` for the available products, numeric ``variables`` overrides, and multi-source composition: .. code-block:: yaml 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: .. code-block:: yaml 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: * ``include`` is accepted only at ``forcing.meteorological.filenames``, a ``domains`` entry's ``filenames``, ``forcing.tide.boundary``, and ``forcing.tide.boundary.constituents``. Anywhere else it is a configuration error naming the allowed locations. * The ``include`` mapping must contain only the ``include`` key. * 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 ``include`` nodes (one level only). .. _wave-forcing-config: Wave Forcing ^^^^^^^^^^^^ The radiation-stress force of the wave field sets up the water level where waves break. It joins the wind stress as one surface stress; see :doc:`../user_guide/wave_forcing` for how it is applied and when to use which source. ``forcing.wave.source`` chooses where the force comes from: - ``model`` (the default): Cocoa's own spectral wave model, run on the same mesh and coupled to the circulation (`Internal Wave Model`_; theory in :doc:`../theory/spectral_waves`). - ``file``: a NetCDF of force or radiation stress written by another wave model, such as a converted ADCIRC+SWAN ``rads.64`` (`External Wave Forcing`_). The two are exclusive: each source's keys are refused with the other. The ramp and the cap apply to the force from either source. .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``wave.enabled`` - bool - false - Apply the wave force. * - ``wave.source`` - string - ``model`` - ``model`` or ``file``. * - ``wave.ramp.enabled`` - bool - true - The wave force's own spinup ramp (ADCIRC's ``RampWRad``), the same hyperbolic tangent as ``forcing.ramp``. It does not inherit ``forcing.ramp``. * - ``wave.ramp.duration`` - duration - ``1d`` - Ramp length (:ref:`duration-syntax`). * - ``wave.cap`` - float - (none) - Largest force magnitude the equations see, keeping its direction (ADCIRC's ``WaveStressGrad_Cap``) [m\ :sup:`2` s\ :sup:`-2`]; must be positive. Output keeps the uncapped force. External Wave Forcing """"""""""""""""""""" A force or a radiation stress on the mesh's nodes, interpolated linearly in time. The file format and the ADCIRC converter are in :doc:`../user_guide/wave_forcing`. .. code-block:: yaml forcing: wave: enabled: true source: file filename: "wave_force.nc" quantity: force # force (default) or stress ramp: enabled: false # a converted rads.64 is already ramped cap: 0.05 # optional [m2 s-2] .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``wave.filename`` - string - (required) - The wave forcing NetCDF; it must cover the whole run. * - ``wave.quantity`` - string - ``force`` - ``force``: the file carries ``force_x``/``force_y``, geographic. ``stress``: it carries ``sxx``/``sxy``/``syy`` in the mesh frame, and Cocoa takes the divergence (refused on a rotated-pole mesh). Internal Wave Model """"""""""""""""""" Cocoa's spectral wave model advances the action spectrum on the circulation mesh every coupling interval, from the circulation's depth, current and wet mask, and hands back the force. Every key has a default, and the defaults are the SWAN+ADCIRC hurricane configuration of Dietrich et al. (2011), so this is a complete configuration: .. code-block:: yaml forcing: wave: enabled: true source: model # the default The waves take their wind from ``forcing.meteorological``; without it they have no wind to grow from. The example below shows every key at its default: .. code-block:: yaml forcing: wave: enabled: true source: model model: coupling_interval: 10m directions: 36 frequencies: 41 lowest_frequency: 0.031384 # Hz highest_frequency: 1.420416 # Hz stop: relative_tolerance: 0.01 absolute_tolerance: 0.005 # m pass_fraction: 0.999 max_iterations: 30 max_height: 30.0 # m sink_relaxation: 0.45 generation: limiter: 0.1 sweep: block_size: 4096 team_size: 256 host_spectra: auto # auto, never or always sources: physics: default # default or st6 generation: true wind: linear_growth: 0.0015 current_coupling: 1.0 multiplier: 1.0 drag_law: garratt # garratt, wu, zijlema, hwang, swell drag_limit: 0.0025 low_wind_drag: true whitecapping: # default package only coefficient: 2.36e-5 steepness: 3.02e-3 steepness_power: 2.0 wavenumber_weight: 1.0 wavenumber_power: 1.0 breaking: enabled: true alpha: 1.0 gamma: 0.73 friction: enabled: true roughness: 0.05 # m, or manning ``filename`` and ``quantity`` are refused with ``source: model``. Wind input needs meteorological forcing; the waves take its wind with ``wind_scale`` divided back out, which constrains the meteorological sources as :doc:`../user_guide/wave_forcing` describes. **Coupling and spectral grid** (:ref:`spectral-waves-grid`): .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``model.coupling_interval`` - duration - ``10m`` - The wave time step and the interval at which the force is renewed; between couplings the circulation sees ADCIRC+SWAN's linear ramp toward the extrapolated force. Must be positive. * - ``model.directions`` - int - 36 - Direction bins, :math:`360^\circ/n` wide; at least 3. Keep it even, so the sweep's snapshot stays small (:ref:`spectral-waves-memory`). * - ``model.frequencies`` - int - 41 - Frequencies spaced geometrically from ``lowest_frequency`` to ``highest_frequency``, both included; at least 2. SWAN's ``msc`` is one fewer. * - ``model.lowest_frequency`` - float - 0.031384 - Lowest frequency [Hz], positive. * - ``model.highest_frequency`` - float - 1.420416 - Highest frequency [Hz], above ``lowest_frequency``. Keep the ratio between neighbors, :math:`(f_{max}/f_{min})^{1/(n-1)}`, near 1.1. **Iteration** (:ref:`spectral-waves-iteration`): .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``model.stop.relative_tolerance`` - float - 0.01 - A node has converged when its Hs changed in the last iteration by at most the larger of this fraction of Hs and ``absolute_tolerance``. * - ``model.stop.absolute_tolerance`` - float - 0.005 - The absolute part of that test [m]. * - ``model.stop.pass_fraction`` - float - 0.999 - The step ends when this fraction of the active nodes has converged; in (0, 1]. SWAN's usual 0.95 takes about half the iterations for a less converged step. * - ``model.stop.max_iterations`` - int - 30 - Iterations allowed per step. Reaching it is logged with the count of nodes still moving, and the run continues. * - ``model.stop.max_height`` - float - 30.0 - Stops the run, as a diverged circulation does, when Hs at any node reaches this height [m] or is not finite after a coupling. The log names the node, the output is written at that step, and no final checkpoint is written. * - ``model.sink_relaxation`` - float - 0.45 - :math:`w` in the relaxed breaking and friction rates, :math:`D_k = wD(N_k) + (1-w)D_{k-1}`; in (0, 1]. * - ``model.generation.limiter`` - float - 0.1 - SWAN's ``GRWMX``: the largest change of a bin per iteration, as a fraction of :math:`0.0081/(2\sigma k^3 c_g)`; 0 lifts the limit. **Sweep** (:ref:`spectral-waves-sweeps`), performance only; the converged step does not depend on them: .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``model.sweep.block_size`` - int - 4096 - The most nodes in a sweep block. * - ``model.sweep.team_size`` - int - 256 - Threads per (block, direction) sweep team. * - ``model.sweep.host_spectra`` - string - ``auto`` - Whether the starting spectrum and the snapshot may live in pinned host memory, read over the bus: ``never``, ``always``, or ``auto``, which keeps each on the device when 1 GB stays free beside it (:ref:`spectral-waves-memory`). **Source terms** (:ref:`spectral-waves-sources`): .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``model.sources.physics`` - string - ``default`` - ``default``: SWAN's ``GEN3 KOMEN AGROW`` with ``WCAP KOMEN``. ``st6``: SWAN's ST6 as Day and Dietrich configure it for ADCIRC+SWAN (:ref:`spectral-waves-st6`), whose coefficients are fixed. * - ``model.sources.generation`` - bool - true - Wind input, whitecapping and quadruplets; ``false`` propagates the waves with breaking and friction alone. * - ``model.sources.wind.linear_growth`` - float - 0.0015 - :math:`A` of the linear wind input (SWAN's ``AGROW``), both packages; non-negative. * - ``model.sources.wind.current_coupling`` - float - 1.0 - :math:`s` in the wind the waves feel, :math:`\mathbf U_{10} - s\,\mathbf U_c` (:ref:`spectral-waves-wind`); in [0, 1]. 1 is SWAN's relative wind, 0 the absolute wind. * - ``model.sources.wind.multiplier`` - float - 1.0 - Scales the wind the waves feel, after the meteorological ``wind_scale`` is divided out (ADCIRC's ``waveWindMultiplier``); positive. * - ``model.sources.wind.drag_law`` - string - ``garratt`` - The law :math:`u_*` is taken from: ``garratt``, ``wu``, ``zijlema``, ``hwang`` or ``swell`` (:doc:`../theory/meteorological_forcing`). Independent of the circulation's ``meteorological.drag_law``. * - ``model.sources.wind.drag_limit`` - float - 0.0025 - The largest drag coefficient the waves take, independent of ``physics.wind_drag_limit``; positive. * - ``model.sources.wind.low_wind_drag`` - bool - true - :math:`C_D = 1.2875\times10^{-3}` at and below 7.5 m/s whatever the law, as ADCIRC+SWAN takes it. Standalone SWAN applies it only under ``DRAG WU``. * - ``model.sources.whitecapping.coefficient`` - float - 2.36e-5 - :math:`C_{ds}` (SWAN's ``cds2``). The whitecapping keys belong to the default package and are refused with ``physics: st6``. * - ``model.sources.whitecapping.steepness`` - float - 3.02e-3 - :math:`\tilde s_{PM}^2` (``stpm``), positive. * - ``model.sources.whitecapping.steepness_power`` - float - 2.0 - :math:`p` (``powst``). * - ``model.sources.whitecapping.wavenumber_weight`` - float - 1.0 - :math:`\delta`. * - ``model.sources.whitecapping.wavenumber_power`` - float - 1.0 - :math:`n` (``powk``). * - ``model.sources.breaking.enabled`` - bool - true - Battjes-Janssen depth-induced breaking and the depth limit on a node's energy (:ref:`spectral-waves-shared`). * - ``model.sources.breaking.alpha`` - float - 1.0 - :math:`\alpha`, the dissipation coefficient; non-negative. * - ``model.sources.breaking.gamma`` - float - 0.73 - :math:`\gamma` in :math:`H_{max} = \gamma d`, which also caps a node's energy at :math:`(\gamma d)^2/4`; positive. * - ``model.sources.friction.enabled`` - bool - true - Madsen bottom friction (:ref:`spectral-waves-shared`). * - ``model.sources.friction.roughness`` - float or ``manning`` - 0.05 - :math:`k_N` [m], positive; or ``manning``, which derives it from the mesh's Manning's :math:`n` at every coupling as ADCIRC hands it to SWAN. Flow Boundary Forcing ^^^^^^^^^^^^^^^^^^^^^^ Configures normal-flow (discharge) boundary conditions driven by per-segment time series. .. code-block:: yaml 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:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``flow_boundary.enabled`` - bool - false - Enable flow boundary forcing * - ``flow_boundary.ramp`` - ramp - (from ``forcing.ramp``) - Optional spinup ramp applied to flow boundaries. Accepts ``enabled`` and ``duration`` (see :ref:`duration-syntax`). * - ``flow_boundary.segments`` - 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 mesh - ``time_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`` (or ``harmonic``): Uses pre-defined tidal constituents - ``astronomical`` (or ``ephemeris``, ``direct``): Computes directly from Moon and Sun positions - ``auto`` (default): Selects automatically based on what is configured **Harmonic Constituent Method:** .. code-block:: yaml 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:** .. list-table:: :header-rows: 1 :widths: 20 15 65 * - Parameter - Units - Description * - ``name`` - string - Constituent name (Q1, O1, P1, K1, N2, M2, S2, K2, etc.) * - ``frequency`` - rad/s - Angular frequency * - ``amplitude`` - m - Tidal potential constant K * - ``etrf`` - - - Earth tide reduction factor * - ``nodal_factor`` - - - Nodal modulation factor f * - ``equilibrium_arg`` - degrees - Equilibrium argument V+u **Astronomical Method:** .. code-block:: yaml forcing: tide: potential: enabled: true type: astronomical astronomical: order: 3 # Expansion order: 2=P2, 3=P2+P3, 4+=untruncated include_nutation: true # Include nutation corrections k2: 0.302 # Love number (optional) h2: 0.609 # Love number (optional) **Astronomical Parameters:** .. list-table:: :header-rows: 1 :widths: 25 15 60 * - Parameter - Default - Description * - ``order`` - 3 - Legendre polynomial expansion order (ADCIRC's ``TIPOrder`` semantics). 2 is the degree-2 equilibrium tide; 3, the default, adds degree-3 corrections; 4 or higher carries every degree that matters rather than truncating. See :doc:`../user_guide/tidal_forcing` for how cocoa evaluates the untruncated form and why it deviates from ADCIRC there. * - ``include_nutation`` - true - Include nutation corrections in celestial position calculations. * - ``k2`` - 0.302 - Second-degree Love number for body tide. * - ``h2`` - 0.609 - Second-degree Love number for vertical displacement. The astronomical method needs no constituent list. See :doc:`../user_guide/tidal_forcing` for details. Tidal Boundary Forcing ^^^^^^^^^^^^^^^^^^^^^^ Elevation-specified tidal boundary conditions. .. code-block:: yaml 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:** .. list-table:: :header-rows: 1 :widths: 20 15 65 * - Parameter - Units - Description * - ``name`` - string - Constituent name * - ``frequency`` - rad/s - Angular frequency * - ``nodal_factor`` - - - Nodal modulation factor * - ``equilibrium_arg`` - degrees - Equilibrium argument * - ``boundary_values`` - list - Per-node amplitude [m] and phase [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 :doc:`../user_guide/tidal_forcing`). .. code-block:: yaml forcing: tide: sal: enabled: true parameter_source: "auto" # or "manual" **Parameters:** .. list-table:: :header-rows: 1 :widths: 25 15 60 * - Parameter - Default - Description * - ``enabled`` - false - Enable SAL forcing * - ``parameter_source`` - "auto" - How to determine constituent parameters. ``"auto"`` looks up frequencies and nodal factors from the built-in tidal database. ``"manual"`` uses values provided in the ``constituents`` list. In manual mode, provide constituent parameters explicitly: .. code-block:: yaml 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. .. code-block:: yaml 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:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``filename`` - string - ``cocoa_output.nc`` - Output file name (NetCDF format) * - ``step_interval`` - int or duration - 100 - Interval between output writes. Accepts a plain integer (number of time steps) or a duration string with suffix: ``s`` (seconds), ``m`` (minutes), ``h`` (hours), ``d`` (days). Fractional values are allowed (e.g., ``0.5h``). The duration must be evenly divisible by the simulation time step. * - ``mode`` - string - ``split`` - Controls where peak variables are written. In ``split`` mode (default), peak variables are written to a separate file named ``_peak.nc`` (e.g., ``cocoa_output_peak.nc``). In ``combined`` mode, peak variables are included in the main output file. See :doc:`../user_guide/output_files` for details. * - ``variables`` - map - *(all enabled except* ``tide_potential`` *and* ``bpg_effective`` *)* - Selectively disable time-series output variables. List variable names with ``false`` to disable them. Omitted variables remain enabled, except the forcing diagnostics ``tide_potential`` and ``bpg_effective``, which are off unless set to ``true``. Peak variables are always written and cannot be disabled. Available names: ``zeta``, ``velocity``, ``pressure``, ``wind``, ``tide_potential``, ``ice_concentration``, ``bpg_effective``. See :doc:`../user_guide/output_files` for the full variable reference. * - ``compression`` - map - ``level: 1``, ``shuffle: false`` - NetCDF deflate settings: ``level`` 0-9 (0 disables compression) and the ``shuffle`` byte-shuffle filter. Lower the level (or use 0) when frequent output stalls the run on the background writer. See :doc:`../user_guide/output_files`. Diagnostics Section ------------------- Controls logging and screen output. .. code-block:: yaml diagnostics: screen_interval: 2h # Screen output every 2 hours (duration or integer step count) log_file: "simulation.log" # Structured log file path (optional) **Parameters:** .. list-table:: :header-rows: 1 :widths: 25 15 15 45 * - Parameter - Type - Default - Description * - ``screen_interval`` - int or duration - 100 - Interval between screen output. Accepts a plain integer (number of time steps) or a duration string (e.g., ``30m``, ``1h``). See :ref:`duration-intervals` for the full syntax. * - ``log_file`` - string - (none) - Path to log file (JSON structured log format) .. _checkpoint-configuration: Checkpoint Section ------------------ Configures checkpoint/restart for long-running simulations. See :doc:`../user_guide/checkpoint` for a complete guide. .. code-block:: yaml 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:** .. list-table:: :header-rows: 1 :widths: 25 15 20 40 * - Parameter - Type - Default - Description * - ``enabled`` - bool - false - Enable the checkpoint/restart system * - ``write_interval`` - int or duration - 0 - How often to write checkpoints. ``0`` (the default) writes a single checkpoint at the end of the run; a positive value writes every ``N`` time steps plus one at the final step. Accepts a plain integer (number of time steps) or a duration string (e.g., ``6h``, ``1d``). See :ref:`duration-intervals` for the full syntax. * - ``file_prefix`` - string - ``cocoa_checkpoint`` - Filename prefix. Each write produces a timestamped file ``{prefix}.{simulation_time}.nc`` (e.g. ``cocoa_checkpoint.20250101T120000.nc``). * - ``restart_file`` - string - (none) - Path to a checkpoint file to restart from. When set, the simulation resumes from the saved state. **Restarting from a checkpoint:** .. code-block:: yaml checkpoint: enabled: true restart_file: "cocoa_checkpoint.20250101T120000.nc" Complete Example ---------------- A complete configuration file for a tidal simulation: .. code-block:: yaml 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: .. _duration-intervals: Duration Syntax --------------- Time-based fields share a common duration grammar. A duration string consists of a numeric value followed by a unit suffix: .. list-table:: :header-rows: 1 :widths: 15 25 30 * - Suffix - Unit - Example * - ``s`` - seconds - ``30s`` = 30 seconds * - ``m`` - minutes - ``20m`` = 20 minutes * - ``h`` - hours - ``1h`` = 1 hour * - ``d`` - days - ``1d`` = 1 day 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_step`` and the ramp ``duration`` fields (``forcing.ramp.duration``, ``forcing.meteorological.ramp.duration``, ``forcing.flow_boundary.ramp.duration``). A bare number is interpreted as **seconds** (``time_step: 2.0`` is identical to ``time_step: 2s``). - **Step intervals** -- ``output.step_interval``, ``diagnostics.screen_interval`` and ``checkpoint.write_interval``. A bare integer is interpreted as a **count of time steps** (``step_interval: 3600`` means every 3600 steps). A suffixed duration must be evenly divisible by ``time_step``; for example ``20m`` with ``time_step: 7s`` errors because 1200 s is not a multiple of 7 s. **Rules:** - Fractional values are allowed: ``0.5h`` = 30 minutes, ``0.25d`` = 6 hours. - ``0`` is legal only for ``checkpoint.write_interval``, where it means "write a single checkpoint at the end of the run" (see :ref:`checkpoint-configuration`); the other intervals must be positive. **Examples:** .. code-block:: yaml 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 ---------------- Input units follow these conventions: .. list-table:: :header-rows: 1 :widths: 30 35 35 * - 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: .. list-table:: :header-rows: 1 :widths: 30 45 25 * - Variable - Description - Default * - ``OMP_NUM_THREADS`` - Number of OpenMP threads (CPU backend) - All available * - ``CUDA_VISIBLE_DEVICES`` - GPU device selection (CUDA backend) - (unset; all devices visible) .. _config-schema-reference: 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. .. literalinclude:: ../../../src/cocoa_kernel/core/config/cocoa_config.schema.yaml :language: yaml