(Updating my Waves and Tides laboratory lecture on Snell-Descartes Law. This post was written in Portuguese.)
Altura e direção de onda usando a lei de snell e batimetria realística
Região do estudo
Utilizaremos a lei de snell-descartes para estudar o ângulo de refração e a altura de ondas na praia de Santos. Podemos observar tais transformações na imagem retirar do Google-Earth abaixo. Mas notem que teremos também os efeitos da difração e interferência de ondas oriundas da ilha ao lado. Adicionalmente, nosso modelo não resolve os efeitos não-lineares!!!
In [2]:
from IPython.display import Image
Image('./data/perfis.png', retina=True)
Out[2]:
Esse bloco apenas lê os dados da planilha do Excel dos alunos, converte a batimetria para metros, e inverte o sinal (o modelo usa com "h" positivo).
In [3]:
from pandas import read_excel
xls = -1e-2 * read_excel('./data/batimetria.xlsx', sheetname='Plan1', skiprows=1, index_col=0, parse_cols=(0, 1, 4, 7))
xls.index.name = 'Distance [m]'
xls.columns = ['T1', 'T2', 'T3']
xls
Out[3]:
Observe como o perfil T1
tem um gradiente mais suave que os T2
e T3
.
In [4]:
ax = xls.plot()
ax.invert_yaxis()
_ = ax.set_ylabel('Depth [m]')
O modelo
In [5]:
import numpy as np
import numpy.ma as ma
# Constantes.
g = 9.81
twopi = 2 * np.pi
# Relação de dispersão (Resolvida pelo método de Newton-Raphson).
def dispersion_relationship(T, h, Ho, thetao):
T, h, Ho, thetao = np.broadcast_arrays(T, h, Ho, thetao)
omega = twopi / T
Lo = (g * T ** 2) / twopi
# Começa pela relação de dispersão de águas profundas.
k = omega / np.sqrt(g)
# Vamos aproximando por incrementos de "f".
f = g * k * np.tanh(k * h) - omega ** 2
while np.abs(f.max()) > 1e-7:
dfdk = (g * k * h * (1 / (np.cosh(k * h))) ** 2 + g * np.tanh(k * h))
k = k - f / dfdk
f = g * k * np.tanh(k * h) - omega ** 2
# Com o número de onda resolvido podemos calcular:
L = twopi / k
C = omega / k
Co = Lo / T
G = 2 * k * h / np.sinh(2 * k * h)
# Aqui é basicamente a lei de Snell e o shoaling.
theta = np.rad2deg(np.arcsin(C / Co * np.sin(np.deg2rad(thetao))))
Kr = np.sqrt(np.cos(np.deg2rad(thetao)) / np.cos(np.deg2rad(theta)))
Ks = np.sqrt(1 / (1 + G) / np.tanh(k * h))
H = Ho * Ks * Kr
# Retorna Altura de onda e ângulo.
return map(ma.asanyarray, (theta, H))
Rodando o modelo
No modelo temos que entrar com,
- T: Período de onda típico;
- h: Batimetria que vocês mediram;
- Ho: Altura de onda inicial;
- thetao: Angulo de incidência das ondas.
In [6]:
T = 5. # Segundos.
h = np.fliplr(np.flipud(xls.values)[3:,:]) # Começa no mais fundo até a costa.
Ho = 0.1 # Metros.
thetao = 45 # Graus.
rows, cols = h.shape
theta, H = [], []
for row in range(rows):
thetao, Ho = dispersion_relationship(T=T, h=h[row, :], Ho=Ho, thetao=thetao)
H.append(Ho)
theta.append(thetao)
H = np.array(H)
theta = np.array(theta)
Plotando os resultados
In [7]:
import matplotlib.pyplot as plt
cmap = plt.cm.BrBG
x = np.arange(3)
y = xls.index.values[:-3]
fig, (ax0, ax1, ax2) = plt.subplots(ncols=3, sharex=True, sharey=True, figsize=(12, 4))
cs0 = ax0.pcolorfast(x, y, h, cmap=cmap)
fig.colorbar(cs0, ax=ax0, extend='both')
ax0.set_title('Batimetria [m]')
ax0.set_xlabel('Perfil [sem unidade]')
cs1 = ax1.pcolorfast(x, y, H, vmax=1., vmin=0.1, cmap=cmap)
fig.colorbar(cs1, ax=ax1, extend='both')
ax1.set_ylabel(u'Distância [m]')
ax1.set_title('Altura de onda [m]')
cs2 = ax2.pcolorfast(x, y, theta, vmax=20, vmin=0, cmap=cmap)
fig.colorbar(cs2, ax=ax2, extend='both')
_ = ax2.set_title(u'Ângulo [graus]')
In [8]:
HTML(html)
Out[8]: