Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

2d: Tidal constituents

image

2d: Tidal constituents

This notebook is the fourth of four notebooks accompanying Chapter 3 of the Coastal Dynamics Open Textbook. It specifically addresses tidal constituents, tidal propagation and tidal prediction (see Sections 3.7.6 through 3.9 of the book and the corresponding slides). The notebooks explore these concepts in a more interactive way, with some exercises, visualizations, and code. There are also ten quiz questions included in this notebook. We will not repeat the whole theory, however, so make sure you have followed the lectures for this week and read the relevant pages in chapter 3 of the book.

Earth has continents, oceans with varying water depths, and a complex gravitational field, hence the tidal signals we observe around the planet are complex. Fortunately, we can break them down into multiple harmonic components, called tidal constituents. The principal harmonic components can either be diurnal, semi-diurnal, short-, or long-period constituents. Each constituent is characterized by an amplitude, frequency and phase, and individually looks like a smooth sin/cosine curve. When we sum up all the individual components we observe signal beating resulting in complex tidal signals with spring-neap cycles, daily inequalities, and longer-term variations.

We will focus on the following concepts:

  1. Tidal analysis and prediction (Part 1, 1 question)

  2. Beating of tidal constituents (Part 2, 5 questions)

  3. Tidal amplitude spectrum (Part 3, open questions to help you reflect)

  4. Tidal propagation (Part 4, open questions to help you reflect)

Import packages

Run the cell below to load the libraries and questions used in this notebook.

from pathlib import Path

import pandas as pd
import hvplot.pandas
import pickle
import uptide
from IPython.display import display
import panel as pn
import holoviews as hv

import coastal_dynamics as cd

pn.extension()
hv.extension("bokeh")
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
import sys

sys.path.append('../')

from modules import mod_2d
Loading...
Loading...
Loading...
Loading...
Loading...
questions = cd.read_questions(Path("../hashed_questions/2d_tidal_constituents_hashed.json"))

question_industry = cd.QuestionIndustry(questions)

cd.UseAnswersApp("2d").serve()
Loading...

Part 1: Tidal analysis and prediction

Astronomical constituents

A table of principal tidal constituents is provided below (compare Table 3.5 in the book). These components are direclty related to the astronomical forcing and the listed amplitudes are according to equilibrium theory (if needed, look up the assumptions behind this theory in Section 3.7.1). The period is given with more significant figures than in Table 3.5 to make more accurate calculations of the beating periods possible.

Tidal constituentsNameEquil.
Amplitude [m]
Period [h]
Semi-diurnal
Principal lunarM20.2412.4206012
Principal solarS20.1112
Lunar ellipticalN20.04612.65834751
Lunar-solar declinationalK20.03111.96723606
Diurnal
Lunar-solar declinationalK10.1423.93447213
Principal lunarO10.1025.81933871
Principal solarP10.04724.06588766
Lunar ellipticalQ10.01926.868350
Long period
FortnightlyMf0.042327.8599387
MonthlyMm0.022661.3111655
Semi-annualSsa0.0194383.076325

Water level record and tide prediction for Scheveningen

Since the tide is caused by regular astronomical phenomena, it can be predicted accurately a long time ahead (but note that this does not include meteorological effects such as storm surges!). The method used for tide prediction is harmonic analysis (see Section 3.9). By a combination of harmonic analysis and hydrodynamic modelling, tidal signals can be predicted for an arbitrary location.

In this part of the exercise, we compare the full observational sea level with a predicted tidal signal at Scheveningen. To achieve this, we will use two datasets:

The GESLA (Global Extreme Sea Level Analysis) data set contains high-frequency (at least hourly) sea-level information from tide gauge stations distributed worldwide. It can be used to analyse tides, storm surges, extreme sea levels and other related processes. The FES2014 is a global finite element hydrodynamic model, which assimilates in-situ data and altimeter data. It provided tidal elevations and tidal currents in terms of amplitudes and phases of 34 tidal components. These 34 tidal components include both astronomical components (like in the Table above) and the higher harmonics that are generated due to non-linear effects in shallowing coastal waters. We will explain more about these non-linear shallow water tides or overtides later, when treating Section 5.7.5 of the book.

The first cell below creates a figure of the observed sea level from GESLA and the tidal signal from FES2014 for Scheveningen, the Netherlands. The figure helps you to see how the observed sea level from GESLA matches up with the tidal signal derived from the available 34 constituents. If you run the second cell below you get a question about this.

About the figure:

  • We computed the tidal signal from the all 34 FES2014 constituents for a timeframe spanning from 1977 to 2017, using the uptide python package

  • In the code, we have chosen to visualize 2015 only, but you can change the code to present an arbitrary timeframe in the period from 1977 to 2017.

  • Note that you can easily adjust the view of the figure; you can not only pan (move the view) and zoom, but the two axes are individually zoomable as well by hovering over them and using the wheelzoom tool.

# Plot
dir_path = Path("../database/2_wind_waves_tides/")

# Choose a time window to plot (has to be between 1977 - 2017)
start_date = pd.to_datetime("2000-01-01 00:00")
end_date = pd.to_datetime("2001-01-01 00:00")

signal, tide_gauge, eta_df = mod_2d.tidal_scheveningen(dir_path, start_date, end_date)

display(signal)
Loading...

Question block for part 1

## Run this cell to get a reflective question

q = [
    "Q2d_measured_predicted_Scheveningen"
]

question_industry.serve(q)
Loading...

Part 2: Beating of tidal constituents

What if we don’t use all 34 tidal constituents? Below is an interactive plot with a year of data. You can again using the wheelzoom while hovering over the time-axis to shorten the plotted time range to less than a year. You can select which tidal constituents should be plotted with the tick boxes. This way you can play around with different constituents and see what kind of signal you get and how close it is to the total tidal signal.

The plot displays the individual tidal components (upper plot), their combined tidal signal (second plot), the combined tidal signal against the total tidal signal (third plot), and the observed sea level with the total tidal signal and the combined signal (fourth plot).

Play around with the figure. You could for instance check the period of the various components and their relative amplitudes (compare with the above Table). You can also consider to what extent these astronomical components contribute to the total predicted tidal signal.

Once you are familiar with the figure, you can run the questions cell below to get some questions about the beating of certain tidal constituents.

# We choose one year to plot, 2000-2001

## Download and load previously calculated tidal signal per constituent
scheveningen_fp = Path("../database/2_wind_waves_tides/tide_scheveningen.p")

with open(scheveningen_fp, "rb") as pickle_file:
    scheveningen = pickle.load(pickle_file)
## Plot
mod_2d.plot_timeseries_with_interactive_controls_hv(tide_gauge, eta_df, scheveningen)
Loading...

Question block for part 2

Below you will find questions about the interplay between some of the main semi-diurnal and diurnal components. Verify your answers from the above interactive plot and make the appropriate computations. The code field can be used to make these computations.

## Write your code here to get the answer to Q-4 and Q-6 of part 2. 

## Use the Table at the top of this notebook for the periods of principal constituents; they are more accurate than the values in the book
## Use the equation for the group period from the textbook. 
## Refer to Notebook 2b (Part Wave grouping) to understand the beating of harmonics constituents better

## Run this cell to get questions

q = [
    "Q2d_M2_S2_phenomenon",
    "Q2d_beating_formula",
    "Q2d_M2_S2_period",
    "Q2d_M2_K1_phenomenon",
    "Q2d_M2_K1_period"
]

question_industry.serve(q)
Loading...

Part 3: Tidal Amplitude spectrum

Figure 3.27 in the textbook shows a spectrum of equilibrium tides. Let’s now look at the amplitudes of the tidal constituents at Scheveningen, obtained from FES2014, in a similar way. Here are some general questions to help you reflect on this figure:

  • What are the main constituents?

  • What are their frequencies (compared to the periods in Table 1)?

  • Can you recognize the tides near twice a day and near once a day?

  • How do the diurnal and semi-diurnal constituents that we used above relate to this larger set?

  • How do the longer-period constituents that we used above relate to this larger set?

  • Can you recognize the non-linear shallow water tides and longer-period tides?

plot = mod_2d.tidal_constituents(dir_path)

plot
Loading...

Part 4: Tidal Propagation

In chapter 3.8 of the textbook, you learned that the propagation of the tide is influenced by the Coriolis acceleration and by friction and resonances determined by the shapes and depths of the ocean basins and marginal seas.

This propagation can be visualised by mapping the lines of simultaneous high water (co-tidal or co-phase lines) and the lines of equal tidal range (co-range lines), as in the figure below. Examine the M2 amplitude and phase pattern along the Atlantic, computed from the FES2014 data. What insights does this pattern provide? Why are the co-tidal (co-phase) lines not equally spaced? Can you link the amplitudes and phases to the Figure 3.30 from the textbook?

What is the direction of the Kelvin wave in the Northern Atlantic? You will find that this corresponds to the theory about amphidromic systems. Now have a look at the direction of the Kelvin wave in the Southern Atlantic. Here, the direction may not be what you expect for an ideal Kelvin wave in a semi-enclosed basin on the Southern Hemisphere (Section 3.8.3 in the book)! Can you think of reasons for this?

image

The end

You have reached the end of this Notebook 2d. This was the last notebook of this week.

Appendix

Below is a script that you can use to load FES2014 data yourself, just in case you would need this at some point in your studies.

### Script for loading FES2014 data (phase and amplitudes)

# import xarray as xr
# from os.path import join
# import pandas as pd

# path = '.../ocean_tide_extrapolated/' # Your path to data

# # Rename la2 to lambda2 if you plan on using uptide
# comps = ['eps2', 'j1', 'k1', 'k2', 'l2', 'la2', 'm2', 'm3', 'm4', 'm6', 'm8', 'mf', 'mks2',
#          'mm', 'mn4', 'ms4', 'msf', 'msqm', 'mtm', 'mu2', 'n2', 'n4', 'nu2', 'o1', 'p1', 'q1',
#          'r2', 's1', 's2', 's4', 'sa', 'ssa', 't2']

# # Resolution of fes2014 is 0.0625x0.0625 (lat,lon), we choose a few
# # locations and the closest model points

# locs = {
#     'scheveningen'  :   [52.125, 4.25], #lat, lon
#     'galveston'     :   [29.25, -94.6875],
#     'valparaiso'    :   [-33, -71.625],
#     'jakarta'       :   [-6.0625, 106.8125]
# }

# tide = {}

## Extract constituents from FES2014 and store pickle files
# for comp in comps:
#     data = xr.open_dataset(join(path, comp + '.nc'))
#     data.coords['lon'] = (data.coords['lon'] + 180) % 360 - 180 #lon=[0,360]
#     temp = {}

#     for loc in locs.keys():
#         temp[loc] = (data.sel(lat=locs[loc][0],lon=locs[loc][1])
#         .to_dataframe()
#         .drop(['lat_bnds', 'lon_bnds', 'crs'], axis=1)
#         .drop(1)
#         .assign(place=loc)
#         .set_index('place', drop=True)
#     )

#     tide[comp] = pd.concat(temp.values())
#     tide[comp].to_pickle('path/02_%s.p' % comp) # Choose your path