Examples
Regular linear waves
We are modelling linear and regular waves of length L
and height H
propagating in water of constant depth d
. We consider one wave along the length of the domain ℓ
.
using SpectralWaves
using CairoMakie # plotting package
L = 2.0 # wavelength (m)
H = 0.1 # wave height (m)
d = 1.0 # water depth (m)
ℓ = L # fluid domain length (m) - one wave
We need a wave period T
.
k = 2π / L # wave number (rad/m)
ω = sqrt(g * k * tanh(k * d)) # angular wave frequency (rad/s)
T = 2π / ω # wave period (s)
We define a number of numerical model parameters.
ℐ = 1 # number of harmonics
nΔt = 200 # number of time increments per wave period
Δt = T / nΔt # time step (s)
nT = 1 # number of periods
t₀ = 0.0 # initial time (s)
τ = nT * T # total simulation time (s)
t = range(start = t₀, stop = τ, step = Δt) # time range
We initialize wave problem using a struct Problem
.
p = Problem(ℓ, d, ℐ, t)
Initial condition values of $\hat{\eta}$, $\dot{\eta}$, $\hat{\phi}$, and $\dot{\phi}$ are computed and inserted into vectors η̂
, η̇
, ϕ̂
, ϕ̇
using linear_regular_wave!
in-place function.
linear_regular_wave!(p, H, ω)
Now, we are ready to solve a problem.
solve_problem!(p; msg_flag=false)
We define a function that calculates free-surface elevation at specified location x
and time instant n
and velocity components u
and w
at specified location (x
, z
) and time instant n
using water_surface
, water_velocity
functions. Please note that the last argument to water_velocity
specifies the axis of projection of the velocity vector using symbolic variables :x
or :z
.
η(x, n) = water_surface(p, x, n)
u(x, z, n) = (z < η(x, n)) * water_velocity(p, x, z, n, :x)
w(x, z, n) = (z < η(x, n)) * water_velocity(p, x, z, n, :z)
v(x, z, n) = sqrt.(u(x, z, n)^2 + w(x, z, n)^2)
We need a grid to present results.
x = range(start = 0, stop = ℓ, length = 21)
z = range(start = -d, stop = H, length = 11)
Finally we are ready to plot results.
n = 101
set_theme!(theme_latexfonts()) # set latex fonts
fig = Figure(size = (700, 300))
ax = Axis(fig[1, 1], xlabel = L"$x$ (m)", ylabel = L"$\eta$ (m)")
band!(ax, x, η.(x, n), -d,
color=:azure) # plot water bulk
lines!(ax, x, η.(x, n),
color=:black,
linewidth = 1) # plot free surface
band!(ax, x, -1.1d, - d,
color=:wheat) # plot bottom bulk
hlines!(ax, -d,
color=:black,
linewidth = 0.7) # plot bottom line
arrows!(ax, x, z, u.(x, z', n), w.(x, z', n);
lengthscale = 0.3,
arrowsize = 10 * vec(v.(x, z', n)/maximum(v.(x, z', n)))) # plot velocity vectors
limits!(ax, 0, L, -1.1d, H)
fig

Linear shoaling
We are modelling linear and regular waves of length L
and height H
climbing up a slope. We apply a linear wavemaker at both sides of the domain, while we consider only a half of the domain of length ℓ
.
using SpectralWaves
using CairoMakie # plotting package
L = 5.0 # wavelength (m)
H = 0.05 # wave height (m)
d = 1.0 # water depth (m)
ℓ = 200.0 # fluid domain length (m)
Again, we need a wave period T
.
k = 2π / L # wave number (rad/m)
ω = sqrt(g * k * tanh(k * d)) # angular wave frequency (rad/s)
T = 2π / ω # wave period (s)
We define a number of numerical model parameters. In order to secure a smooth start of the wavemaker paddle, we define a number of ramped wave periods nT₀
in addition to a total number of simulated wave periods nT
.
ℐ = 600 # number of harmonics
nT = 30 # number of simulated wave periods
nT₀ = 3 # number of ramped wave periods
nΔt = 200 # number of time steps per wave period
Δt = T / nΔt # time step (s)
t₀ = 0.0 # initial time (s)
τ = nT * T # total simulation time (s)
t = range(start = t₀, stop = τ, step = Δt) # time range
We initialize wave problem p
with M_b=40
.
p = Problem(ℓ, d, ℐ, t; M_b=40)
We use linear_wavemaker!
function to define wavemaker paddle motion.
linear_wavemaker!(p, H, T, L, nT₀)
The slope of height h
is introduced using bottom_slope!
function.
h = 0.9d
bottom_slope!(p, h)
And we solve the problem.
solve_problem!(p; msg_flag=false)
We calculate free surface elevation and bottom surface position using water_surface
and bottom_surface
functions
η(x, n) = water_surface(p, x, n)
β(x) = bottom_surface(p, x)
and we are ready to animate results and see how the waves shoal.
x = range(start = 0, stop = ℓ / 3, length = 501) # spatial range
η₀ = Observable(η.(x, firstindex(t))) # set free-surface observable for p
set_theme!(theme_latexfonts()) # set latex fonts
fig = Figure(size = (700, 300)) # initialize a figure
ax = Axis(fig[1, 1],
xlabel = L"$x$ (m)",
ylabel = L"$z$ (m)") # define axis with labels and title
band!(ax, x, η₀, β.(x) .-d,
color=:azure) # plot water bulk
lines!(ax, x, η₀,
color=:black,
linewidth = 1) # plot free surface line
band!(ax, x, β.(x) .- d, - 1.1d,
color=:wheat) # plot bottom bulk
lines!(ax, x, β.(x) .- d,
color=:black,
linewidth = 1) # plot bottom line
limits!(ax, x[1], x[end], -1.1d, 2H) # set limits
# animate free surface
record(fig, "shoaling.mp4", lastindex(t)-nΔt+1:lastindex(t);
framerate = nΔt) do n
η₀[] = η.(x, n)
end
Replacing p = Problem(ℓ, d, ℐ, t; M_b=40)
with p = Problem(ℓ, d, ℐ, t; M_b=40, M_s=2)
gives a corresponding nonlinear shoaling, which looks like this:
Linear wave transformation at a step
We are modelling linear and regular waves of length L
and height H
undergoing a transformation at an underwater step. We apply a linear wavemaker at both sides of the domain, while we consider only a half of the domain of length ℓ
.
using SpectralWaves
using CairoMakie # plotting package
L = 10.0 # wavelength (m)
H = 0.05 # wave height (m)
d = 1.0 # water depth (m)
ℓ = 200.0 # fluid domain length (m)
We need a wave period T
.
k = 2π / L # wave number (rad/m)
ω = sqrt(g * k * tanh(k * d)) # angular wave frequency (rad/s)
T = 2π / ω # wave period (s)
We define a number of numerical model parameters (cf. linear shoaling example).
ℐ = 400 # number of harmonics
nT = 16 # number of simulated wave periods
nT₀ = 3 # number of ramped wave periods
nΔt = 200 # number of time steps per wave period
Δt = T / nΔt # time step (s)
t₀ = 0.0 # initial time (s)
τ = nT * T # total simulation time (s)
t = range(start = t₀, stop = τ, step = Δt) # time range
We initialize wave problem p
with M_b=40
.
p = Problem(ℓ, d, ℐ, t; M_b=40)
We use linear_wavemaker!
function to define wavemaker paddle motion.
linear_wavemaker!(p, H, T, L, nT₀)
The step of height h
is introduced using bottom_step!
function.
h = 0.6d
bottom_step!(p, h)
We solve the problem.
solve_problem!(p; msg_flag=false)
We calculate free surface elevation and bottom surface position using water_surface
and bottom_surface
functions
η(x, n) = water_surface(p, x, n)
β(x) = bottom_surface(p, x)
and we animate the results to see how the waves undergo transformation at a step.
x = range(start = ℓ / 8, stop = 3ℓ / 8, length = 501) # spatial range
η₀ = Observable(η.(x, firstindex(t))) # set free-surface observable for p
set_theme!(theme_latexfonts()) # set latex fonts
fig = Figure(size = (700, 300)) # initialize a figure
ax = Axis(fig[1, 1],
xlabel = L"$x$ (m)",
ylabel = L"$z$ (m)") # define axis with labels and title
band!(ax, x, η₀, β.(x) .-d,
color=:azure) # plot water bulk
lines!(ax, x, η₀,
color=:black,
linewidth = 1) # plot free surface line
band!(ax, x, β.(x) .- d, - 1.1d,
color=:wheat) # plot bottom bulk
lines!(ax, x, β.(x) .- d,
color=:black,
linewidth = 1) # plot bottom line
limits!(ax, x[1], x[end], -1.1d, 2H) # set limits
# animate free surface
record(fig, "step_transformation.mp4", lastindex(t)-nΔt+1:lastindex(t);
framerate = nΔt) do n
η₀[] = η.(x, n)
end
Again, we may compute nonlinear scenario using p = Problem(ℓ, d, ℐ, t; M_b=40, M_s=2)
.