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
Example block output

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).