Skip to content
This repository was archived by the owner on Mar 1, 2023. It is now read-only.

Commit 2f3ed54

Browse files
bors[bot]blallen
andauthored
Merge #1515
1515: Add rotating spindown test to handling of Coriolis force r=blallen a=blallen # Description Another spinoff from #1482. Depends on #1509. Adds a `rotation` field to the `SimpleBox` problem to turn on and off the Coriolis force in the hydrostatic spindown tests. Need to add state check values after the pretty-tables output is fixed. Co-authored-by: blallen <[email protected]>
2 parents d6c6161 + 7a1adaa commit 2f3ed54

File tree

6 files changed

+196
-56
lines changed

6 files changed

+196
-56
lines changed

.buildkite/pipeline.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,15 @@ steps:
381381
queue: central
382382
slurm_ntasks: 1
383383

384+
- label: "cpu_test_coriolis"
385+
key: "cpu_test_coriolis"
386+
command:
387+
- "mpiexec julia --color=yes --project test/Ocean/SplitExplicit/test_coriolis.jl "
388+
agents:
389+
config: cpu
390+
queue: central
391+
slurm_ntasks: 1
392+
384393
- label: "cpu_KM_saturation_adjustment"
385394
key: "cpu_KM_saturation_adjustment"
386395
command:
@@ -754,6 +763,16 @@ steps:
754763
slurm_ntasks: 1
755764
slurm_gres: "gpu:1"
756765

766+
- label: "gpu_test_coriolis"
767+
key: "gpu_test_coriolis"
768+
command:
769+
- "mpiexec julia --color=yes --project test/Ocean/SplitExplicit/test_coriolis.jl "
770+
agents:
771+
config: gpu
772+
queue: central
773+
slurm_ntasks: 1
774+
slurm_gres: "gpu:1"
775+
757776
- label: "gpu_KM_saturation_adjustment"
758777
key: "gpu_KM_saturation_adjustment"
759778
command:

src/Ocean/HydrostaticBoussinesq/HydrostaticBoussinesqModel.jl

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -607,24 +607,13 @@ end
607607

608608
@inline function coriolis_force!(m::HBModel, ::Uncoupled, S, Q, A, t)
609609
# f × u
610-
f = coriolis_parameter(m, A.y)
610+
f = coriolis_parameter(m, m.problem, A.y)
611611
u, v = Q.u # Horizontal components of velocity
612612
S.u -= @SVector [-f * v, f * u]
613613

614614
return nothing
615615
end
616616

617-
"""
618-
coriolis_parameter(::HBModel)
619-
620-
northern hemisphere coriolis
621-
622-
# Arguments
623-
- `m`: model object to dispatch on and get coriolis parameters
624-
- `y`: y-coordinate in the box
625-
"""
626-
@inline coriolis_parameter(m::HBModel, y) = m.fₒ + m.β * y
627-
628617
"""
629618
wavespeed(::HBModel)
630619

src/Ocean/OceanProblems/SimpleBoxProblem.jl

Lines changed: 126 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module OceanProblems
22

3-
export SimpleBox, HomogeneousBox, OceanGyre
3+
export SimpleBox, Fixed, Rotating, HomogeneousBox, OceanGyre
44

55
using StaticArrays
66
using CLIMAParameters.Planet: grav
@@ -23,10 +23,6 @@ SWModel = ShallowWaterModel
2323

2424
abstract type AbstractOceanProblem <: AbstractProblem end
2525

26-
############################
27-
# Basic box problem #
28-
# Set up dimensions of box #
29-
############################
3026
abstract type AbstractSimpleBoxProblem <: AbstractOceanProblem end
3127

3228
"""
@@ -53,8 +49,6 @@ function ocean_init_aux!(m::HBModel, p::AbstractSimpleBoxProblem, A, geom)
5349
A.ΔGᵘ = @SVector [-0, -0]
5450

5551
return nothing
56-
57-
return nothing
5852
end
5953

6054
function ocean_init_aux!(m::SWModel, p::AbstractSimpleBoxProblem, A, geom)
@@ -66,9 +60,29 @@ function ocean_init_aux!(m::SWModel, p::AbstractSimpleBoxProblem, A, geom)
6660
return nothing
6761
end
6862

63+
"""
64+
coriolis_parameter
65+
66+
northern hemisphere coriolis
67+
68+
# Arguments
69+
- `m`: model object to dispatch on and get coriolis parameters
70+
- `y`: y-coordinate in the box
71+
"""
72+
@inline coriolis_parameter(m::HBModel, p::AbstractSimpleBoxProblem, y) =
73+
m.fₒ + m.β * y
6974
@inline coriolis_parameter(m::SWModel, p::AbstractSimpleBoxProblem, y) =
7075
m.fₒ + m.β * y
7176

77+
############################
78+
# Basic box problem #
79+
# Set up dimensions of box #
80+
############################
81+
82+
abstract type AbstractRotation end
83+
struct Rotating <: AbstractRotation end
84+
struct Fixed <: AbstractRotation end
85+
7286
"""
7387
SimpleBoxProblem <: AbstractSimpleBoxProblem
7488
@@ -77,7 +91,8 @@ Lˣ = zonal (east-west) length
7791
Lʸ = meridional (north-south) length
7892
H = height of the ocean
7993
"""
80-
struct SimpleBox{T, BC} <: AbstractSimpleBoxProblem
94+
struct SimpleBox{R, T, BC} <: AbstractSimpleBoxProblem
95+
rotation::R
8196
::T
8297
::T
8398
H::T
@@ -86,60 +101,136 @@ struct SimpleBox{T, BC} <: AbstractSimpleBoxProblem
86101
Lˣ, # m
87102
Lʸ, # m
88103
H; # m
104+
rotation = Fixed(),
89105
BC = (
90106
OceanBC(Impenetrable(FreeSlip()), Insulating()),
91107
OceanBC(Penetrable(FreeSlip()), Insulating()),
92108
),
93109
) where {FT <: AbstractFloat}
94-
return new{FT, typeof(BC)}(Lˣ, Lʸ, H, BC)
110+
return new{typeof(rotation), FT, typeof(BC)}(rotation, Lˣ, Lʸ, H, BC)
95111
end
96112
end
97113

98-
function barotropic_state!(x, t, νʰ, kˣ, gH)
99-
M = @SMatrix [-νʰ *^2 gH * kˣ; -0]
100-
A = exp(M * t) * @SVector [1, 1]
114+
@inline coriolis_parameter(m::HBModel, ::SimpleBox{R}, y) where {R <: Fixed} =
115+
-0
116+
@inline coriolis_parameter(m::SWModel, ::SimpleBox{R}, y) where {R <: Fixed} =
117+
-0
101118

102-
U = A[1] * sin(kˣ * x)
103-
η = A[2] * cos(kˣ * x)
119+
@inline coriolis_parameter(
120+
m::HBModel,
121+
::SimpleBox{R},
122+
y,
123+
) where {R <: Rotating} = m.fₒ
124+
@inline coriolis_parameter(
125+
m::SWModel,
126+
::SimpleBox{R},
127+
y,
128+
) where {R <: Rotating} = m.fₒ
129+
130+
function ocean_init_state!(m::SWModel, p::SimpleBox, Q, A, coords, t)
131+
k = (2π / p.Lˣ, 2π / p.Lʸ, 2π / p.H)
132+
ν = (m.turbulence.ν, m.turbulence.ν, -0)
104133

105-
return (U = U, η = η)
134+
gH = grav(m.param_set) * p.H
135+
@inbounds f = coriolis_parameter(m, p, coords[2])
136+
137+
U, V, η = barotropic_state!(p.rotation, (coords..., t), ν, k, (gH, f))
138+
139+
Q.U = @SVector [U, V]
140+
Q.η = η
141+
142+
return nothing
106143
end
107144

108145
function ocean_init_state!(m::HBModel, p::SimpleBox, Q, A, coords, t)
109-
@inbounds x = coords[1]
110-
@inbounds y = coords[2]
111-
@inbounds z = coords[3]
112-
113-
= 2π / p.
114-
= 2π / p.
115-
kᶻ = 2π / p.H
146+
k = (2π / p.Lˣ, 2π / p.Lʸ, 2π / p.H)
147+
ν = (m.νʰ, m.νʰ, m.νᶻ)
116148

117149
gH = grav(m.param_set) * p.H
118-
U, η = barotropic_state!(x, t, m.νʰ, kˣ, gH)
150+
@inbounds f = coriolis_parameter(m, p, coords[2])
151+
152+
U, V, η = barotropic_state!(p.rotation, (coords..., t), ν, k, (gH, f))
153+
u°, v° = baroclinic_deviation(p.rotation, (coords..., t), ν, k, f)
119154

120-
λ = m.νʰ *^2 + m.νᶻ * kᶻ^2
121-
= exp(-λ * t) * cos(kᶻ * z) * sin(kˣ * x)
122155
u =+ U / p.H
156+
v =+ V / p.H
123157

124-
Q.u = @SVector [u, -0]
158+
Q.u = @SVector [u, v]
125159
Q.η = η
126160
Q.θ = -0
127161

128162
return nothing
129163
end
130164

131-
function ocean_init_state!(m::SWModel, p::SimpleBox, Q, A, coords, t)
132-
@inbounds x = coords[1]
133-
= 2π / p.
134-
νʰ = m.turbulence.ν
135-
gH = grav(m.param_set) * p.H
165+
function barotropic_state!(
166+
::Fixed,
167+
(x, y, z, t),
168+
(νˣ, νʸ, νᶻ),
169+
(kˣ, kʸ, kᶻ),
170+
params,
171+
)
172+
gH, _ = params
136173

137-
U, η = barotropic_state!(x, t, νʰ, kˣ, gH)
174+
M = @SMatrix [-νˣ *^2 gH * kˣ; -0]
175+
A = exp(M * t) * @SVector [1, 1]
138176

139-
Q.U = @SVector [U, -0]
140-
Q.η = η
177+
U = A[1] * sin(kˣ * x)
178+
V = -0
179+
η = A[2] * cos(kˣ * x)
141180

142-
return nothing
181+
return (U = U, V = V, η = η)
182+
end
183+
184+
function baroclinic_deviation(
185+
::Fixed,
186+
(x, y, z, t),
187+
(νˣ, νʸ, νᶻ),
188+
(kˣ, kʸ, kᶻ),
189+
f,
190+
)
191+
λ = νˣ *^2 + νᶻ * kᶻ^2
192+
193+
= exp(-λ * t) * cos(kᶻ * z) * sin(kˣ * x)
194+
= -0
195+
196+
return (u° = u°, v° = v°)
197+
end
198+
199+
function barotropic_state!(
200+
::Rotating,
201+
(x, y, z, t),
202+
(νˣ, νʸ, νᶻ),
203+
(kˣ, kʸ, kᶻ),
204+
params,
205+
)
206+
gH, f = params
207+
208+
M = @SMatrix [-νˣ *^2 f gH * kˣ; -f -νˣ *^2 0; -0 0]
209+
A = exp(M * t) * @SVector [1, 1, 1]
210+
211+
U = A[1] * sin(kˣ * x)
212+
V = A[2] * sin(kˣ * x)
213+
η = A[3] * cos(kˣ * x)
214+
215+
return (U = U, V = V, η = η)
216+
end
217+
218+
function baroclinic_deviation(
219+
::Rotating,
220+
(x, y, z, t),
221+
(νˣ, νʸ, νᶻ),
222+
(kˣ, kʸ, kᶻ),
223+
f,
224+
)
225+
λ = νˣ *^2 + νᶻ * kᶻ^2
226+
227+
M = @SMatrix[-λ f; -f -λ]
228+
A = exp(M * t) * @SVector[1, 1]
229+
230+
= A[1] * cos(kᶻ * z) * sin(kˣ * x)
231+
= A[2] * cos(kᶻ * z) * sin(kˣ * x)
232+
233+
return (u° = u°, v° = v°)
143234
end
144235

145236
@inline kinematic_stress(p::SimpleBox, y) = @SVector [-0, -0]
@@ -157,8 +248,6 @@ Lˣ = zonal (east-west) length
157248
Lʸ = meridional (north-south) length
158249
H = height of the ocean
159250
τₒ = maximum value of wind-stress (amplitude)
160-
fₒ = first coriolis parameter (constant term)
161-
β = second coriolis parameter (linear term)
162251
"""
163252
struct HomogeneousBox{T, BC} <: AbstractSimpleBoxProblem
164253
::T

src/Ocean/SplitExplicit/HydrostaticBoussinesqCoupling.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ end
3434

3535
@inline function coriolis_force!(m::HBModel, ::Coupled, S, Q, A, t)
3636
# f × u
37-
f = coriolis_parameter(m, A.y)
37+
f = coriolis_parameter(m, m.problem, A.y)
3838
uᵈ, vᵈ = A.uᵈ # Horizontal components of velocity
3939
S.u -= @SVector [-f * vᵈ, f * uᵈ]
4040

test/Ocean/SplitExplicit/hydrostatic_spindown.jl

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
include("split_explicit.jl")
22

3-
function SplitConfig(name, resolution, dimensions, coupling)
3+
function SplitConfig(name, resolution, dimensions, coupling, rotation = Fixed())
44
mpicomm = MPI.COMM_WORLD
55
ArrayType = ClimateMachine.array_type()
66

@@ -39,7 +39,7 @@ function SplitConfig(name, resolution, dimensions, coupling)
3939
polynomialorder = N,
4040
)
4141

42-
problem = SimpleBox{FT}(Lˣ, Lʸ, H)
42+
problem = SimpleBox{FT}(Lˣ, Lʸ, H; rotation = rotation)
4343

4444
model_3D = HydrostaticBoussinesqModel{FT}(
4545
param_set,
@@ -49,8 +49,6 @@ function SplitConfig(name, resolution, dimensions, coupling)
4949
αᵀ = FT(0),
5050
κʰ = FT(0),
5151
κᶻ = FT(0),
52-
fₒ = FT(0),
53-
β = FT(0),
5452
)
5553

5654
model_2D = ShallowWaterModel{FT}(
@@ -60,8 +58,6 @@ function SplitConfig(name, resolution, dimensions, coupling)
6058
nothing;
6159
coupling = coupling,
6260
c = FT(1),
63-
fₒ = FT(0),
64-
β = FT(0),
6561
)
6662

6763
return SplitConfig(
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env julia --project
2+
using Test
3+
4+
include("hydrostatic_spindown.jl")
5+
ClimateMachine.init()
6+
7+
const FT = Float64
8+
9+
#################
10+
# RUN THE TESTS #
11+
#################
12+
@testset "$(@__FILE__)" begin
13+
14+
include("../refvals/hydrostatic_spindown_refvals.jl")
15+
16+
# simulation time
17+
timeend = FT(15 * 24 * 3600) # s
18+
tout = FT(24 * 3600) # s
19+
timespan = (tout, timeend)
20+
21+
# DG polynomial order
22+
N = Int(4)
23+
24+
# Domain resolution
25+
= Int(5)
26+
= Int(5)
27+
Nᶻ = Int(8)
28+
resolution = (N, Nˣ, Nʸ, Nᶻ)
29+
30+
# Domain size
31+
= 1e6 # m
32+
= 1e6 # m
33+
H = 400 # m
34+
dimensions = (Lˣ, Lʸ, H)
35+
36+
config =
37+
SplitConfig("rotating", resolution, dimensions, Coupled(), Rotating())
38+
39+
run_split_explicit(
40+
config,
41+
timespan,
42+
dt_fast = 300,
43+
dt_slow = 300,
44+
# refDat = refVals.ninety_minutes,
45+
analytic_solution = true,
46+
)
47+
end

0 commit comments

Comments
 (0)