Stationary waves

Ecuación del Potencial

Una de las posibles soluciones del potencial \(\Phi\) es el de una onda propagándose en el sentido postivo del eje \(x\), que se expresa como:

\[ \Phi(x,z,t)=-\frac{Ag}{\omega}\frac{\cosh k(h+z)}{\cosh kh}\sin(kx-\omega t) \]

Pero las soluciones correspondientes a ondas suelen expresarse también haciendo uso de la variable compleja (facilitando esta el álgebra considerablemente), por lo que la expresión se reduce a:

\[ \Phi(x,z,t) = \textrm{Re} \left\{ -\frac{ig}{\omega}A\frac{\cosh k(h+z)}{\cosh kh}\exp{-i(kx-\omega t)}\right\} \]

dónde Re implica la parte real de la expresión entre corchetes.

Importamos las librerías necesarias

# import maths
import numpy as np
from sympy import *

# import matplotlib / plotting
import matplotlib
matplotlib.rcParams['animation.embed_limit'] = 2**32
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
plt.style.use('dark_background')
from IPython.display import HTML # diplay anim
import warnings
warnings.filterwarnings("ignore")

cargamos las variables para SymPy

# save variables for SymPy
A1, A2, g, w, k, h, x, z, t = symbols('A1 A2 g w k h x z t')

y definimos las ecuaciones

en este caso, vamos a generar una onda estacionaria / cuasi-estacionaria

# potential equation
pot1 = -(A1*g/w) * (cosh(k*(h+z))/cosh(k*h)) * sin(k*x-w*t)
pot2 = -(A2*g/w) * (cosh(k*(h+z))/cosh(k*h)) * sin(-k*x-w*t)
pot = pot1 + pot2
pot
\[\displaystyle - \frac{A_{1} g \sin{\left(k x - t w \right)} \cosh{\left(k \left(h + z\right) \right)}}{w \cosh{\left(h k \right)}} + \frac{A_{2} g \sin{\left(k x + t w \right)} \cosh{\left(k \left(h + z\right) \right)}}{w \cosh{\left(h k \right)}}\]
# calculate eta, u, w, ax y az
eta = 1/g * diff(pot,t).evalf(subs={'z':0})
u = - diff(pot, x)
w = - diff(pot, z)
ax = - diff(u, t)
az = - diff(w, t)
eta
\[\displaystyle \frac{A_{1} g \cos{\left(k x - t w \right)} + A_{2} g \cos{\left(k x + t w \right)}}{g}\]
# evaluate u, w and eta
def evaluate_potential(xs,zs,tt,wave_parameters):
    us = []
    ws = []
    etas = []
    u_lamb = lambdify((x,z,t),u.subs(wave_parameters),'math')
    w_lamb = lambdify((x,z,t),w.subs(wave_parameters),'math')
    eta_lamb = lambdify((x,z,t),eta.subs(wave_parameters),'math')
    for xss in xs:
        for zss in zs:
            us.append(u_lamb(xss,zss,tt))
            # us.append(float(u.evalf(subs={
            #     **{'x':xss,'z':zss,'t':tt},**wave_parameters
            # })))
            ws.append(w_lamb(xss,zss,tt))
            # ws.append(float(w.evalf(subs={
            #     **{'x':xss,'z':zss,'t':tt},**wave_parameters
            # })))
        etas.append(eta_lamb(xss,zss,tt))
        # etas.append(float(eta.evalf(subs={
        #     **{'x':xss,'z':zss,'t':tt},**wave_parameters
        # })))
        
    return np.array(us), np.array(ws), np.array(etas)

Evaluate and plot results

# fixed parameters for the wave
A1_value = 1.6 # meters
A2_value = 1.6
g_value = 9.8 # m / s^2
T_value = 6 # seconds
h_value = 10 # mean depth (meters)
# derived parameters for the wave
w_value = 2*np.pi/T_value
k_value = w_value**2/g_value # wave number

wave_parameters = {
    'A1': A1_value,
    'A2': A2_value,
    'g': g_value, 
    'w': w_value, 
    'k': k_value,
    'h': h_value
}
# plot parameters
fig = plt.figure(figsize=(12,6))
x_range = (0,100,24)
x_values = np.linspace(*x_range)
y_range = (-10,4,10)
y_values = np.linspace(*y_range)
ax = plt.axes(xlim=(x_range[0]-5,x_range[1]+5), 
              ylim=(y_range[0]-0.5,y_range[1]+0.5))
line, = ax.plot([], [], lw=4)
u0, w0, eta0 = evaluate_potential(x_values,y_values,0,wave_parameters)
line.set_data(x_values, eta0)
idxs = []
for i in range(len(eta0)-1):
    idxs += list(
        np.where(y_values<eta0[i])[0]+(i*len(y_values))
    ) # get idxs below wave
quiv = ax.quiver(
    np.meshgrid(y_values,x_values)[1].reshape(-1)[idxs],
    np.meshgrid(y_values,x_values)[0].reshape(-1)[idxs],
    u0[idxs], w0[idxs], u0[idxs], width=0.002, cmap='bwr_r'
)

def init():
    line.set_data([],[])
    
    return line, quiv

def animate(tt):
    global quiv
    quiv.remove()
    us, ws, etas = evaluate_potential(x_values,y_values,tt/3,wave_parameters)
    line.set_data(x_values, etas)
    idxs = []
    for i in range(len(etas)-1):
        idxs += list(
            np.where(y_values<etas[i])[0]+(i*len(y_values))
        ) # get idxs below wave
    quiv = ax.quiver(
        np.meshgrid(y_values,x_values)[1].reshape(-1)[idxs],
        np.meshgrid(y_values,x_values)[0].reshape(-1)[idxs],
        us[idxs], ws[idxs], us[idxs], width=0.002, cmap='bwr_r'
    )

    return line, quiv

plt.close()
# we create the animation, based in the previous cell
anim = FuncAnimation(fig, animate, init_func=init, frames=20, interval=200, blit=True)
# visualize animation
HTML(anim.to_jshtml())
# anim.save('onda_estacionaria.gif')