============= Tidal Forcing ============= Tidal forcing enters Cocoa in two places, and a run may use either or both: 1. **Tide potential** (``forcing.tide.potential``) - the tide-generating body force applied over the whole domain. With no ``constituents`` list it is computed astronomically: Moon and Sun positions from Jean Meeus's algorithms give the complete potential with no harmonic decomposition. A constituent-based potential (``type: constituent`` with an explicit ``constituents`` list) is also accepted but is not documented here. 2. **Harmonic boundary constituents** (``forcing.tide.boundary``) - prescribed elevation at open boundary nodes from pre-defined tidal amplitudes, frequencies, and phases. A regional mesh with an open ocean boundary typically uses both (the :ref:`wnat-test` case does); a global mesh has no open boundaries and is driven by the potential alone (see :ref:`global-test`). Astronomical Tide Potential --------------------------- The astronomical tide potential method computes the equilibrium tide directly from celestial body positions, automatically capturing: - All tidal constituents (no explicit harmonic decomposition needed) - Nodal modulation (18.6-year lunar cycle) - Long-period tides (fortnightly, monthly, semi-annual, annual) This method is recommended for: - Long simulations where nodal factors may become outdated - Global or regional applications without constituent databases - Studies requiring accurate representation of the complete tidal spectrum Configuration ^^^^^^^^^^^^^ Enable astronomical tide potential in your configuration file: .. code-block:: yaml forcing: ramp: enabled: true duration: 1d tide: potential: enabled: true type: "astronomical" astronomical: order: 3 # Expansion order: 2=P2, 3=P2+P3, 4+=untruncated include_nutation: true k2: 0.302 # Optional Love number override h2: 0.609 # Optional Love number override Parameters: .. list-table:: :header-rows: 1 :widths: 25 15 60 * - Parameter - Default - Description * - ``order`` - 3 - Legendre polynomial expansion order, matching ADCIRC's ``TIPOrder`` semantics: 2 is the degree-2 equilibrium tide, 3 (the default) adds the degree-3 term for improved coastal accuracy, and 4 or higher carries every degree that matters. The untruncated form differs from 3 by under 0.1 mm, dominated by the lunar degree-4 term. Cocoa deviates from ADCIRC in how it evaluates that form: it sums the Legendre series to degree 11 rather than evaluating the equivalent closed form, whose subtraction of two order-one quantities buries the Sun's contribution under roughly 80 times its own magnitude in cancellation noise. * - ``include_nutation`` - true - Include nutation corrections in position calculations for higher accuracy at the cost of slightly more computation. * - ``k2`` - 0.302 - Second-degree Love number for body tide. Represents elastic deformation of Earth due to tidal forces. * - ``h2`` - 0.609 - Second-degree Love number for vertical displacement. Represents radial displacement of Earth's surface. The Earth elasticity factor :math:`(1 + k_2 - h_2) \approx 0.69` reduces the equilibrium tide amplitude to account for the solid Earth's elastic response. Self-Attraction and Loading (SAL) --------------------------------- Self-attraction and loading (SAL) accounts for two effects that modify the ocean tide: 1. The gravitational attraction of the ocean on itself (self-attraction) 2. The deformation of the Earth's crust under the weight of the ocean tide (loading) SAL corrections are applied as spatially-varying amplitude and phase adjustments per tidal constituent at each mesh node. The SAL data must be pre-computed externally (e.g., from a global tide model) and embedded in the mesh file during conversion. Preparing SAL Data ^^^^^^^^^^^^^^^^^^ SAL data is included during mesh conversion using the ``--sal`` flag: .. code-block:: bash python utils/cocoa_mesh_tools.py from_adcirc \ --mesh fort.14 \ --attributes fort.13 \ --sal fort.24 \ --output mesh.nc The SAL file can be in ADCIRC ASCII format (fort.24) or NetCDF format (fort.24.nc). It contains per-node amplitude (meters) and phase (degrees) for each SAL constituent. Configuration ^^^^^^^^^^^^^ Enable SAL in the configuration file: .. 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 frequencies and nodal factors. ``"auto"`` looks up each constituent in the built-in tidal database. ``"manual"`` uses values provided in the config file. Auto Mode """"""""" In auto mode (the default), Cocoa matches SAL constituent names from the mesh file against its built-in tidal constituent database to determine frequencies, nodal factors, and equilibrium arguments at the simulation coldstart time. No additional configuration is needed: .. code-block:: yaml forcing: tide: sal: enabled: true Manual Mode """"""""""" Manual mode is used for exact validation against ADCIRC, where you need to specify the precise frequency, nodal factor, and equilibrium argument for each constituent: .. code-block:: yaml forcing: tide: sal: enabled: true parameter_source: "manual" constituents: - name: M2 frequency: 1.405189028e-04 # rad/s (converted to rad/hr internally) nodal_factor: 1.026777 equilibrium_arg: 26.668130 # degrees (converted to radians internally) - name: K1 frequency: 7.292117e-05 # rad/s nodal_factor: 1.0064 equilibrium_arg: 12.45 # degrees Each constituent in the list must have a ``name`` matching one of the constituent names stored in the mesh SAL data. .. note:: If SAL is enabled but no SAL data is found in the mesh file, Cocoa will log a warning and continue without SAL corrections. Re-run the mesh converter with the ``--sal`` flag to include the data. Harmonic Constituents --------------------- Harmonic constituents prescribe the tidal elevation at open boundary nodes from pre-computed amplitudes, frequencies, and phases. They need a tidal database for the boundary, and because each constituent's nodal factor is fixed for the run, they suit simulations short enough for it to remain valid. Common Tidal Constituents ^^^^^^^^^^^^^^^^^^^^^^^^^ Common tidal constituents used in Cocoa: .. list-table:: :header-rows: 1 * - Name - Description - Period (hours) - Frequency (rad/s) * - M2 - Principal lunar semidiurnal - 12.42 - 1.405189e-4 * - S2 - Principal solar semidiurnal - 12.00 - 1.454441e-4 * - N2 - Larger lunar elliptic - 12.66 - 1.378797e-4 * - K1 - Lunar diurnal - 23.93 - 7.292117e-5 * - O1 - Lunar diurnal - 25.82 - 6.759774e-5 * - K2 - Lunisolar semidiurnal - 11.97 - 1.458423e-4 * - Q1 - Larger lunar elliptic - 26.87 - 6.495854e-5 Boundary Configuration ^^^^^^^^^^^^^^^^^^^^^^ Tidal boundary constituents are specified in the forcing section of the configuration file: .. 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 } - name: K1 frequency: 0.000072921158358 nodal_factor: 1.0064 equilibrium_arg: 12.45 boundary_values: - { amplitude: 0.15, phase: 45.0 } - { amplitude: 0.14, phase: 46.2 } Each constituent requires: - ``name``: Constituent identifier (M2, S2, K1, O1, etc.) - ``frequency``: Angular frequency in rad/s - ``nodal_factor``: Nodal modulation factor - ``equilibrium_arg``: Equilibrium argument in degrees - ``boundary_values``: List of amplitude (meters) / phase (degrees) pairs, one per open boundary node, in mesh order With per-node values for every constituent, this block grows with the mesh's open boundary and is the same for every run on that mesh. It can therefore live in its own reusable file and be pulled in with an ``include`` node -- either the whole ``boundary`` block or just the ``constituents`` list (see :doc:`../getting_started/configuration` for the inclusion rules): .. code-block:: yaml forcing: tide: boundary: include: wnat_tide_boundary.yaml Ramp-up Period -------------- To avoid initial transients, use a ramp-up period: .. code-block:: yaml forcing: ramp: enabled: true duration: 1d # 1 day ramp-up The tidal forcing is gradually increased during the ramp-up period using a normalized hyperbolic tangent function: .. math:: R(t) = \frac{1}{\tanh(2)}\tanh\left(\frac{2t}{T_{ramp}}\right) The normalization by :math:`\tanh(2)` ensures the ramp reaches exactly 1.0 at :math:`t = T_{ramp}`. The value is clamped to 1.0 for :math:`t \ge T_{ramp}`.