Solve Synthetic Tides

This (notebook) solving for the harmonic constants for a tidal time series at a given location

Python Dependencies

Program Dependencies

  • arguments.py: load the nodal corrections for tidal constituents

  • astro.py: computes the basic astronomical mean longitudes

  • crs.py: Coordinate Reference System (CRS) routines

  • io.model.py: retrieves tide model parameters for named tide models

  • io.OTIS.py: extract tidal harmonic constants from OTIS tide models

  • io.ATLAS.py: extract tidal harmonic constants from ATLAS netCDF4 tide models

  • io.GOT.py: extract tidal harmonic constants from GOT tide models

  • io.FES.py: extract tidal harmonic constants from FES tide models

  • io.constituents.py: basic tide model constituent class

  • predict.py: predict tidal values using harmonic constants

  • solve.py: estimates the harmonic constants for ocean tides

  • time.py: utilities for calculating time operations

  • utilities.py: download and management utilities for files

This notebook uses Jupyter widgets to set parameters for calculating the tidal maps.

Load modules

from __future__ import print_function

import os
import numpy as np
import matplotlib.pyplot as plt
import IPython.display
import ipywidgets

# import tide programs
import pyTMD.io
import pyTMD.predict
import pyTMD.solve
import pyTMD.tools
import pyTMD.utilities
import timescale.time

# autoreload
%load_ext autoreload
%autoreload 2

Set parameters for program

  • Model directory

  • Tide model for synthetic

# available model list
model_list = sorted(pyTMD.io.model.ocean_elevation())
# display widgets for setting directory and model
TMDwidgets = pyTMD.tools.widgets()
TMDwidgets.model.options = model_list
TMDwidgets.model.value = 'GOT4.10'
TMDwidgets.VBox([
    TMDwidgets.directory,
    TMDwidgets.model,
    TMDwidgets.compress,
])

Select location for tide synthetic

# default coordinates to use
LAT,LON = (-76.0, -40.0)
m = pyTMD.tools.leaflet(center=(LAT,LON), zoom=3,
    zoom_control=True, marker_control=True)
# show map
m.map

HTML table with outputs

table = ipywidgets.HTML()
display(table)

Calculate and plot solution

# get model parameters
model = pyTMD.io.model(TMDwidgets.directory.value,
    compressed=TMDwidgets.compress.value
   ).elevation(TMDwidgets.model.value)

# convert time to days relative to Jan 1, 1992 (48622 MJD)
minutes = np.arange(366*1440)
ts = timescale.time.Timescale().from_calendar(2000, 1, 1, minute=minutes)

# read tidal constants and interpolate to leaflet points
if model.format in ('OTIS','ATLAS-compact','TMD3'):
    constituents = pyTMD.io.OTIS.read_constants(
        model.grid_file, model.model_file,
        model.projection, type=model.type,
        grid=model.file_format)
    c = constituents.fields
    DELTAT = np.zeros_like(ts.tide)
elif (model.format == 'ATLAS-netcdf'):
    constituents = pyTMD.io.ATLAS.read_constants(
        model.grid_file, model.model_file,
        type=model.type, compressed=model.compressed)
    c = constituents.fields
    DELTAT = np.zeros_like(ts.tide)
elif model.format in ('GOT-ascii', 'GOT-netcdf'):
    constituents = pyTMD.io.GOT.read_constants(
        model.model_file, grid=model.file_format,
        compressed=model.compressed)
    c = constituents.fields
    # delta time (TT - UT1)
    DELTAT = ts.tt_ut1
elif (model.format == 'FES-netcdf'):
    constituents = pyTMD.io.FES.read_constants(model.model_file,
        type=model.type, version=model.version,
        compressed=model.compressed)
    c = model.constituents
    # delta time (TT - UT1)
    DELTAT = ts.tt_ut1

# update the tide solution
def update_tide_solution(*args):
    # leaflet location
    LAT,LON = np.copy(m.marker.location)
    # verify longitudes
    LON = m.wrap_longitudes(LON)
    if model.format in ('OTIS','ATLAS-compact','TMD3'):
        amp,ph,D = pyTMD.io.OTIS.interpolate_constants(
            np.atleast_1d(LON), np.atleast_1d(LAT),
            constituents, model.projection, type=model.type,
            method='spline', extrapolate=True)
    elif (model.format == 'ATLAS-netcdf'):
        amp,ph,D = pyTMD.io.ATLAS.interpolate_constants(
            np.atleast_1d(LON), np.atleast_1d(LAT),
            constituents, type=model.type, scale=model.scale,
            method='spline', extrapolate=True)
    elif model.format in ('GOT-ascii', 'GOT-netcdf'):
        amp,ph = pyTMD.io.GOT.interpolate_constants(
            np.atleast_1d(LON), np.atleast_1d(LAT),
            constituents, scale=model.scale,
            method='spline', extrapolate=True)
    elif (model.format == 'FES-netcdf'):
        amp,ph = pyTMD.io.FES.interpolate_constants(
            np.atleast_1d(LON), np.atleast_1d(LAT),
            constituents, scale=model.scale,
            method='spline', extrapolate=True)
    # calculate complex phase in radians for Euler's
    cph = -1j*ph*np.pi/180.0
    # calculate constituent oscillation
    hc = amp*np.exp(cph)
    # predict tidal elevations at time 1 and infer minor corrections
    TIDE = pyTMD.predict.time_series(ts.tide, hc, c,
        deltat=DELTAT, corrections=model.corrections)
    MINOR = pyTMD.predict.infer_minor(ts.tide, hc, c,
        deltat=DELTAT, corrections=model.corrections)
    TIDE.data[:] += MINOR.data[:]

    # solve for harmonic constants
    famp, fph = pyTMD.solve.constants(ts.tide, TIDE.data, c,
        deltat=DELTAT, corrections=model.corrections)

    # create a HTML table with values
    # HTML table header
    table.value = """<table>
		<thead>
		<tr>
			<th style="text-align:center; padding: 10px">Constituent</th>
			<th style="text-align:center; padding: 10px">Original Amplitude</th>
			<th style="text-align:center; padding: 10px">Original Phase</th>
			<th style="text-align:center; padding: 10px">Solution Amplitude</th>
			<th style="text-align:center; padding: 10px">Solution Phase</th>
		</tr>
		</thead>
		<tbody>
    """
    # print the original and solution amplitudes and phases to table
    for i,con in enumerate(c):
        table.value += f"""
            <tr>
			    <td style="text-align:center">{con}</td>
			    <td style="text-align:center">{100*amp.data[0,i]:0.1f}cm</td>
                <td style="text-align:center">{ph.data[0,i]:0.1f}\u00b0</td>
			    <td style="text-align:center">{100*famp[i]:0.1f}cm</td>
                <td style="text-align:center">{fph[i]:0.1f}\u00b0</td>
            </tr>
        """
    # close HTML table
    table.value += """
        </tbody>
    </table>
    """

# run tide prediction and solution at initial location
update_tide_solution()
# watch marker location for changes
m.marker_text.observe(update_tide_solution)