-
Notifications
You must be signed in to change notification settings - Fork 188
/
test_internal_wave_dynamics.jl
88 lines (69 loc) · 2.58 KB
/
test_internal_wave_dynamics.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# Note: internal_wave_solution and internal_wave_dynamics_test are formulated to work
# on grids that are _either_ Flat in y or Periodic in y.
function internal_wave_solution(; L, background_stratification=false)
# Internal wave parameters
ν = κ = 1e-9
z₀ = -L/3
δ = L/20
a₀ = 1e-3
m = 16
k = 1
f = 0.2
ℕ = 1.0
σ = sqrt( (ℕ^2 * k^2 + f^2 * m^2) / (k^2 + m^2) )
# Numerical parameters
Δt = 0.01 * 1/σ
cᵍ = m * σ / (k^2 + m^2) * (f^2/σ^2 - 1)
U = a₀ * k * σ / (σ^2 - f^2)
V = a₀ * k * f / (σ^2 - f^2)
W = a₀ * m * σ / (σ^2 - ℕ^2)
B = a₀ * m * ℕ^2 / (σ^2 - ℕ^2)
a(x, z, t) = exp( -(z - cᵍ*t - z₀)^2 / (2*δ)^2 )
u(x, z, t) = a(x, z, t) * U * cos(k*x + m*z - σ*t)
v(x, z, t) = a(x, z, t) * V * sin(k*x + m*z - σ*t)
w(x, z, t) = a(x, z, t) * W * cos(k*x + m*z - σ*t)
# Add a method for non-Flat y
u(x, y, z, t) = u(x, z, t)
v(x, y, z, t) = v(x, z, t)
w(x, y, z, t) = w(x, z, t)
# Buoyancy field depends on whether we use background fields or not
wavy_b(x, z, t) = a(x, z, t) * B * sin(k*x + m*z - σ*t)
wavy_b(x, y, z, t) = wavy_b(x, z, t)
background_b(x, z, t) = ℕ^2 * z
background_b(x, y, z, t) = background_b(x, z, t)
if background_stratification # Move stratification to a background field
background_fields = (; b=background_b)
b = wavy_b
else
background_fields = NamedTuple()
b(x, z, t) = wavy_b(x, z, t) + background_b(x, z, t)
end
solution = (; u, v, w, b)
# Form model keyword arguments
closure = ScalarDiffusivity(ν=ν, κ=κ)
buoyancy = BuoyancyTracer()
tracers = :b
coriolis = FPlane(f=f)
model_kwargs = (; closure, buoyancy, tracers, coriolis)
return solution, model_kwargs, background_fields, Δt, σ
end
function internal_wave_dynamics_test(model, solution, Δt)
# Make initial conditions
u₀(x, z) = solution.u(x, z, 0)
v₀(x, z) = solution.v(x, z, 0)
w₀(x, z) = solution.w(x, z, 0)
b₀(x, z) = solution.b(x, z, 0)
# Add a method for non-Flat y
u₀(x, y, z) = u₀(x, z)
v₀(x, y, z) = v₀(x, z)
w₀(x, y, z) = w₀(x, z)
b₀(x, y, z) = b₀(x, z)
set!(model, u=u₀, v=v₀, w=w₀, b=b₀)
simulation = Simulation(model, stop_iteration=10, Δt=Δt)
# Pesky NaNChecker
pop!(simulation.callbacks, :nan_checker)
run!(simulation)
# Tolerance was found by trial and error...
@test relative_error(model.velocities.u, solution.u, model.clock.time) < 1e-4
return nothing
end