============= Tidal Forcing ============= Cocoa supports two methods for tidal forcing: 1. **Harmonic constituents** - Traditional method using pre-defined tidal amplitudes, frequencies, and phases 2. **Astronomical tide potential** - Direct calculation of Moon and Sun positions using Jean Meeus algorithms for automatic inclusion of all tidal constituents The harmonic constituent method requires pre-computed tidal databases, while the astronomical method computes tide-generating forces directly from Moon and Sun positions. 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: 2 # Expansion order: 2=P2, 3=P3, 4=exact 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`` - 4 - Legendre polynomial expansion order. 2 (P2) is standard equilibrium tide; 3 (P3) adds degree-3 term for improved coastal accuracy; 4+ uses full expansion matching ADCIRC. * - ``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. .. note:: When using the astronomical method, you do not need to specify individual tidal constituents for the potential. The method automatically computes the complete tide-generating potential from calculated celestial positions. 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 --------------------- The harmonic constituent method specifies tides using pre-computed amplitudes, frequencies, and phases. This approach is suitable when tidal databases are available and for shorter simulations where nodal factors 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/phase pairs, one per open boundary node 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 Spatially Varying Amplitudes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ``boundary_values`` list provides per-node tidal amplitudes and phases for open boundaries. Each entry corresponds to a boundary node in mesh order: .. code-block:: yaml boundary_values: - { amplitude: 0.50, phase: 340.0 } # Node 1 - { amplitude: 0.52, phase: 342.0 } # Node 2 - { amplitude: 0.48, phase: 338.0 } # Node 3 # ... one entry per open boundary node where: - ``amplitude``: Tidal amplitude in meters - ``phase``: Tidal phase in degrees 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}`.