Skip to content

Commit 47bd773

Browse files
Merge #1072
1072: Update backing arrays for SpectralElementSpace2D r=sriharshakandala a=sriharshakandala Co-authored-by: sriharshakandala <sriharsha.kvs@gmail.com>
2 parents b521958 + 51ce5e9 commit 47bd773

File tree

4 files changed

+230
-7
lines changed

4 files changed

+230
-7
lines changed

examples/sphere/shallow_water_cuda.jl

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CUDA
22
using ClimaComms
3+
using DocStringExtensions
34

45
import ClimaCore:
56
Device,
@@ -12,6 +13,199 @@ import ClimaCore:
1213
Topologies,
1314
DataLayouts
1415

16+
"""
17+
PhysicalParameters{FT}
18+
19+
Physical parameters needed for the simulation.
20+
21+
# Fields
22+
$(DocStringExtensions.FIELDS)
23+
"""
24+
Base.@kwdef struct PhysicalParameters{FT} # rename to PhysicalParameters
25+
"Radius of earth"
26+
R::FT = FT(6.37122e6)
27+
"Rotation rate of earth"
28+
Ω::FT = FT(7.292e-5)
29+
"Gravitational constant"
30+
g::FT = FT(9.80616)
31+
"Hyperdiffusion coefficient"
32+
D₄::FT = FT(1.0e16)
33+
end
34+
#This example solves the shallow-water equations on a cubed-sphere manifold.
35+
#This file contains five test cases:
36+
abstract type AbstractTest end
37+
"""
38+
SteadyStateTest{FT, P} <: AbstractTest
39+
40+
The first one, called "steady_state", reproduces Test Case 2 in Williamson et al,
41+
"A standard test set for numerical approximations to the shallow water
42+
equations in spherical geometry", 1992. This test case gives the steady-state
43+
solution to the non-linear shallow water equations. It consists of solid
44+
body rotation or zonal flow with the corresponding geostrophic height field.
45+
This can be run with an angle α that represents the angle between the north
46+
pole and the center of the top cube panel.
47+
48+
https://doi.org/10.1016/S0021-9991(05)80016-6
49+
50+
# Fields
51+
$(DocStringExtensions.FIELDS)
52+
"""
53+
Base.@kwdef struct SteadyStateTest{FT, P} <: AbstractTest
54+
"Physical parameters"
55+
params::P = PhysicalParameters{FT}()
56+
"advection velocity"
57+
u0::FT = 2 * pi * params.R / (12 * 86400)
58+
"peak of analytic height field"
59+
h0::FT = 2.94e4 / params.g
60+
"angle between the north pole and the center of the top cube panel"
61+
α::FT
62+
end
63+
SteadyStateTest::FT) where {FT} =
64+
SteadyStateTest{FT, PhysicalParameters{FT}}(; α = α)
65+
66+
"""
67+
SteadyStateCompactTest{FT, P} <: AbstractTest
68+
69+
A second one, called "steady_state_compact", reproduces Test Case 3 in the same
70+
reference paper. This test case gives the steady-state solution to the
71+
non-linear shallow water equations with nonlinear zonal geostrophic flow
72+
with compact support.
73+
74+
https://doi.org/10.1016/S0021-9991(05)80016-6
75+
76+
# Fields
77+
$(DocStringExtensions.FIELDS)
78+
"""
79+
Base.@kwdef struct SteadyStateCompactTest{FT, P} <: AbstractTest
80+
"Physical parameters"
81+
params::P = PhysicalParameters{FT}()
82+
"advection velocity"
83+
u0::FT = 2 * pi * params.R / (12 * 86400)
84+
"peak of analytic height field"
85+
h0::FT = 2.94e4 / params.g
86+
"latitude lower bound for coordinate transformation parameter"
87+
ϕᵦ::FT = -30.0
88+
"latitude upper bound for coordinate transformation parameter"
89+
ϕₑ::FT = 90.0
90+
"velocity perturbation parameter"
91+
xₑ::FT = 0.3
92+
"angle between the north pole and the center of the top cube panel"
93+
α::FT
94+
end
95+
SteadyStateCompactTest::FT) where {FT} =
96+
SteadyStateCompactTest{FT, PhysicalParameters{FT}}(; α = α)
97+
98+
"""
99+
MountainTest{FT, P} <: AbstractTest
100+
101+
A third one, called "mountain", reproduces Test Case 5 in the same
102+
reference paper. It represents a zonal flow over an isolated mountain,
103+
where the governing equations describe a global steady-state nonlinear
104+
zonal geostrophic flow, with a corresponding geostrophic height field over
105+
a non-uniform reference surface h_s.
106+
107+
https://doi.org/10.1016/S0021-9991(05)80016-6
108+
109+
# Fields
110+
$(DocStringExtensions.FIELDS)
111+
"""
112+
Base.@kwdef struct MountainTest{FT, P} <: AbstractTest
113+
"Physical parameters"
114+
params::P = PhysicalParameters{FT}()
115+
"advection velocity"
116+
u0::FT = 20.0
117+
"peak of analytic height field"
118+
h0::FT = 5960
119+
"radius of conical mountain"
120+
a::FT = 20.0
121+
"center of mountain long coord, shifted by 180 compared to the paper,
122+
because our λ ∈ [-180, 180] (in the paper it was 270, with λ ∈ [0, 360])"
123+
λc::FT = 90.0
124+
"latitude coordinate for center of mountain"
125+
ϕc::FT = 30.0
126+
"mountain peak height"
127+
h_s0::FT = 2e3
128+
"angle between the north pole and the center of the top cube panel"
129+
α::FT
130+
end
131+
MountainTest::FT) where {FT} =
132+
MountainTest{FT, PhysicalParameters{FT}}(; α = α)
133+
134+
"""
135+
RossbyHaurwitzTest{FT, P} <: AbstractTest
136+
137+
A fourth one, called "rossby_haurwitz", reproduces Test Case 6 in the same
138+
reference paper. It represents the solution of the nonlinear barotropic
139+
vorticity equation on the sphere
140+
141+
https://doi.org/10.1016/S0021-9991(05)80016-6
142+
143+
# Fields
144+
$(DocStringExtensions.FIELDS)
145+
"""
146+
Base.@kwdef struct RossbyHaurwitzTest{FT, P} <: AbstractTest
147+
"Physical parameters"
148+
params::P = PhysicalParameters{FT}()
149+
"velocity amplitude parameter"
150+
a::FT = 4.0
151+
"peak of analytic height field"
152+
h0::FT = 8.0e3
153+
"vorticity amplitude parameter (1/sec)"
154+
ω::FT = 7.848e-6
155+
"vorticity amplitude parameter (1/sec)"
156+
K::FT = 7.848e-6
157+
"angle between the north pole and the center of the top cube panel"
158+
α::FT
159+
end
160+
RossbyHaurwitzTest::FT) where {FT} =
161+
RossbyHaurwitzTest{FT, PhysicalParameters{FT}}(; α = α)
162+
163+
"""
164+
BarotropicInstabilityTest{FT, P} <: AbstractTest
165+
166+
A fifth one, called "barotropic_instability", reproduces the test case in
167+
Galewsky et al, "An initial-value problem for testing numerical models of
168+
the global shallow-water equations", 2004 (also in Sec. 7.6 of Ullirch et al,
169+
"High-order finite-volume methods for the shallow-water equations on
170+
the sphere", 2010). This test case consists of a zonal jet with compact
171+
support at a latitude of 45°. A small height disturbance is then added,
172+
which causes the jet to become unstable and collapse into a highly vortical
173+
structure.
174+
175+
https://doi.org/10.3402/tellusa.v56i5.14436
176+
https://doi.org/10.1016/j.jcp.2010.04.044
177+
178+
# Fields
179+
$(DocStringExtensions.FIELDS)
180+
"""
181+
Base.@kwdef struct BarotropicInstabilityTest{FT, P} <: AbstractTest
182+
"Physical parameters"
183+
params::P = PhysicalParameters{FT}()
184+
"maximum zonal velocity"
185+
u_max::FT = 80.0
186+
"mountain shape parameters"
187+
αₚ::FT = 19.09859
188+
"mountain shape parameters"
189+
βₚ::FT = 3.81971
190+
"peak of balanced height field from Tempest
191+
https://github.com/paullric/tempestmodel/blob/master/test/shallowwater_sphere/BarotropicInstabilityTest.cpp#L86"
192+
h0::FT = 10158.18617
193+
"local perturbation peak height"
194+
h_hat::FT = 120.0
195+
"southern jet boundary"
196+
ϕ₀::FT = 25.71428
197+
"northern jet boundary"
198+
ϕ₁::FT = 64.28571
199+
"height perturbation peak location"
200+
ϕ₂::FT = 45.0
201+
"zonal velocity decay parameter"
202+
eₙ::FT = exp(-4.0 / (deg2rad(ϕ₁) - deg2rad(ϕ₀))^2)
203+
"angle between the north pole and the center of the top cube panel"
204+
α::FT
205+
end
206+
BarotropicInstabilityTest::FT) where {FT} =
207+
BarotropicInstabilityTest{FT, PhysicalParameters{FT}}(; α = α)
208+
15209
function shallow_water_driver_cuda(ARGS, ::Type{FT}) where {FT}
16210
device = Device.device()
17211
context = ClimaComms.SingletonCommsContext(device)
@@ -22,7 +216,28 @@ function shallow_water_driver_cuda(ARGS, ::Type{FT}) where {FT}
22216
α = parse(FT, replace(test_angle_name, "alpha" => ""))
23217

24218
println("Test name: $test_name, α = $(α)")
219+
# Test-specific physical parameters
220+
test =
221+
test_name == "steady_state_compact" ? SteadyStateCompactTest(α) :
222+
(
223+
test_name == "mountain" ? MountainTest(α) :
224+
(
225+
test_name == "rossby_haurwitz" ? RossbyHaurwitzTest(α) :
226+
(
227+
test_name == "barotropic_instability" ?
228+
BarotropicInstabilityTest(α) : SteadyStateTest(α)
229+
)
230+
)
231+
)
232+
# Set up discretization
233+
ne = 9 # the rossby_haurwitz test case's initial state has a singularity at the pole. We avoid it by using odd number of elements
234+
Nq = 4
25235

236+
domain = Domains.SphereDomain(test.params.R)
237+
mesh = Meshes.EquiangularCubedSphere(domain, ne)
238+
quad = Spaces.Quadratures.GLL{Nq}()
239+
grid_topology = Topologies.Topology2D(context, mesh)
240+
space = Spaces.SpectralElementSpace2D(grid_topology, quad)
26241
return nothing
27242
end
28243

src/DataLayouts/DataLayouts.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ function IJFH{S, Nij}(array::AbstractArray{T, 4}) where {S, Nij, T}
258258
IJFH{S, Nij, typeof(array)}(array)
259259
end
260260

261-
rebuild(data::IJFH{S, Nij}, array) where {S, Nij} = IJFH{S, Nij}(array)
261+
rebuild(data::IJFH{S, Nij}, array::A) where {S, Nij, A <: AbstractArray} =
262+
IJFH{S, Nij}(array)
262263

263264
Base.copy(data::IJFH{S, Nij}) where {S, Nij} = IJFH{S, Nij}(copy(parent(data)))
264265

@@ -1254,6 +1255,9 @@ end
12541255
return dataview
12551256
end
12561257

1258+
rebuild(data::AbstractData, ::Type{DA}) where {DA} =
1259+
rebuild(data, DA(getfield(data, :array)))
1260+
12571261
# broadcast machinery
12581262
include("broadcast.jl")
12591263

src/Spaces/Spaces.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ using ClimaComms
1919
import ..slab, ..column, ..level
2020
import ..Utilities: PlusHalf
2121
import ..DataLayouts, ..Geometry, ..Domains, ..Meshes, ..Topologies
22+
import ..Device
2223
using StaticArrays, ForwardDiff, LinearAlgebra, UnPack
2324

2425
abstract type AbstractSpace end

src/Spaces/spectralelement.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ function SpectralElementSpace2D(
215215

216216
### How to DSS multiple fields?
217217
# 1. allocate buffers externally
218-
218+
context = topology.context
219+
DA = Device.device_array_type(context.device)
219220
domain = Topologies.domain(topology)
220221
if domain isa Domains.SphereDomain
221222
CoordType3D = Topologies.coordinate_type(topology)
@@ -457,6 +458,8 @@ function SpectralElementSpace2D(
457458
internal_surface_geometry_slab[q] = sgeom⁻
458459
end
459460
end
461+
internal_surface_geometry =
462+
DataLayouts.rebuild(internal_surface_geometry, DA)
460463

461464
boundary_surface_geometries =
462465
map(Topologies.boundary_tags(topology)) do boundarytag
@@ -479,7 +482,7 @@ function SpectralElementSpace2D(
479482
)
480483
end
481484
end
482-
boundary_surface_geometry
485+
DataLayouts.rebuild(boundary_surface_geometry, DA)
483486
end
484487
else
485488
internal_surface_geometry = nothing
@@ -489,10 +492,10 @@ function SpectralElementSpace2D(
489492
topology,
490493
quadrature_style,
491494
global_geometry,
492-
local_geometry,
493-
ghost_geometry,
494-
dss_local_weights,
495-
dss_ghost_weights,
495+
DataLayouts.rebuild(local_geometry, DA),
496+
DataLayouts.rebuild(ghost_geometry, DA),
497+
DataLayouts.rebuild(dss_local_weights, DA),
498+
DataLayouts.rebuild(dss_ghost_weights, DA),
496499
internal_surface_geometry,
497500
boundary_surface_geometries,
498501
)

0 commit comments

Comments
 (0)