Skip to content

Commit 4b819b9

Browse files
Add convenience constructors for grids
1 parent bf41449 commit 4b819b9

File tree

4 files changed

+444
-0
lines changed

4 files changed

+444
-0
lines changed

src/Grids/Grids.jl

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ include("spectralelement.jl")
7676
include("extruded.jl")
7777
include("column.jl")
7878
include("level.jl")
79+
include("convenience_constructors.jl")
7980

8081

8182

src/Grids/convenience_constructors.jl

+366
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
#=
2+
While we recommend users to use our compose-able
3+
methods, this file contains some convenience
4+
constructors, which are meant to improve
5+
developer experience.
6+
=#
7+
check_device_context(context, device) =
8+
@assert ClimaComms.device(context) == device "The given device and context device do not match."
9+
"""
10+
ExtrudedCubedSphereGrid(
11+
::Type{<:AbstractFloat}; # defaults to Float64
12+
z_elem::Integer,
13+
z_min::Real,
14+
z_max::Real,
15+
radius::Real,
16+
h_elem::Integer,
17+
Nq::Integer,
18+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
19+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
20+
stretch::Meshes.StretchingRule = Meshes.Uniform(),
21+
hypsography::HypsographyAdaption = Flat(),
22+
global_geometry::Geometry.AbstractGlobalGeometry = Geometry.ShallowSphericalGlobalGeometry(radius),
23+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
24+
h_mesh = Meshes.EquiangularCubedSphere(Domains.SphereDomain(radius), h_elem),
25+
)
26+
27+
A convenience constructor, which builds a
28+
`ExtrudedFiniteDifferenceGrid`.
29+
"""
30+
ExtrudedCubedSphereGrid(; kwargs...) =
31+
ExtrudedCubedSphereGrid(Float64; kwargs...)
32+
33+
function ExtrudedCubedSphereGrid(
34+
::Type{FT};
35+
z_elem::Integer,
36+
z_min::Real,
37+
z_max::Real,
38+
radius::Real,
39+
h_elem::Integer,
40+
Nq::Integer,
41+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
42+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
43+
stretch::Meshes.StretchingRule = Meshes.Uniform(),
44+
hypsography::HypsographyAdaption = Flat(),
45+
global_geometry::Geometry.AbstractGlobalGeometry = Geometry.ShallowSphericalGlobalGeometry(
46+
radius,
47+
),
48+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
49+
h_mesh = Meshes.EquiangularCubedSphere(
50+
Domains.SphereDomain{FT}(radius),
51+
h_elem,
52+
),
53+
) where {FT}
54+
check_device_context(context, device)
55+
56+
z_boundary_names = (:bottom, :top)
57+
h_topology = Topologies.Topology2D(context, h_mesh)
58+
h_grid = Grids.SpectralElementGrid2D(h_topology, quad)
59+
z_domain = Domains.IntervalDomain(
60+
Geometry.ZPoint{FT}(z_min),
61+
Geometry.ZPoint{FT}(z_max);
62+
boundary_names = z_boundary_names,
63+
)
64+
z_mesh = Meshes.IntervalMesh(z_domain, stretch; nelems = z_elem)
65+
z_topology = Topologies.IntervalTopology(context, z_mesh)
66+
vertical_grid = FiniteDifferenceGrid(z_topology)
67+
return ExtrudedFiniteDifferenceGrid(
68+
h_grid,
69+
vertical_grid,
70+
hypsography,
71+
global_geometry,
72+
)
73+
end
74+
75+
"""
76+
CubedSphereGrid(
77+
::Type{<:AbstractFloat}; # defaults to Float64
78+
radius::Real,
79+
Nq::Integer,
80+
h_elem::Integer,
81+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
82+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
83+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
84+
h_mesh = Meshes.EquiangularCubedSphere(Domains.SphereDomain(radius), h_elem),
85+
)
86+
87+
A convenience constructor, which builds a
88+
`SpectralElementGrid2D`.
89+
"""
90+
CubedSphereGrid(; kwargs...) = CubedSphereGrid(Float64; kwargs...)
91+
function CubedSphereGrid(
92+
::Type{FT};
93+
radius::Real,
94+
Nq::Integer,
95+
h_elem::Integer,
96+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
97+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
98+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
99+
h_mesh = Meshes.EquiangularCubedSphere(
100+
Domains.SphereDomain{FT}(radius),
101+
h_elem,
102+
),
103+
) where {FT}
104+
check_device_context(context, device)
105+
h_topology = Topologies.Topology2D(context, h_mesh)
106+
return Grids.SpectralElementGrid2D(h_topology, quad)
107+
end
108+
109+
"""
110+
ColumnGrid(
111+
::Type{<:AbstractFloat}; # defaults to Float64
112+
z_elem::Integer,
113+
z_min::Real,
114+
z_max::Real,
115+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
116+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
117+
stretch::Meshes.StretchingRule = Meshes.Uniform(),
118+
)
119+
120+
A convenience constructor, which builds a
121+
`FiniteDifferenceGrid` given.
122+
"""
123+
ColumnGrid(; kwargs...) = ColumnGrid(Float64; kwargs...)
124+
function ColumnGrid(
125+
::Type{FT};
126+
z_elem::Integer,
127+
z_min::Real,
128+
z_max::Real,
129+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
130+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
131+
stretch::Meshes.StretchingRule = Meshes.Uniform(),
132+
) where {FT}
133+
check_device_context(context, device)
134+
z_boundary_names = (:bottom, :top)
135+
z_domain = Domains.IntervalDomain(
136+
Geometry.ZPoint{FT}(z_min),
137+
Geometry.ZPoint{FT}(z_max);
138+
boundary_names = z_boundary_names,
139+
)
140+
z_mesh = Meshes.IntervalMesh(z_domain, stretch; nelems = z_elem)
141+
z_topology = Topologies.IntervalTopology(context, z_mesh)
142+
return FiniteDifferenceGrid(z_topology)
143+
end
144+
145+
"""
146+
Box3DGrid(
147+
::Type{<:AbstractFloat}; # defaults to Float64
148+
z_elem::Integer,
149+
x_min::Real,
150+
x_max::Real,
151+
y_min::Real,
152+
y_max::Real,
153+
z_min::Real,
154+
z_max::Real,
155+
periodic_x::Bool,
156+
periodic_y::Bool,
157+
Nq::Integer,
158+
x_elem::Integer,
159+
y_elem::Integer,
160+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
161+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
162+
stretch::Meshes.StretchingRule = Meshes.Uniform(),
163+
hypsography::HypsographyAdaption = Flat(),
164+
global_geometry::Geometry.AbstractGlobalGeometry = Geometry.CartesianGlobalGeometry(),
165+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
166+
)
167+
168+
A convenience constructor, which builds a
169+
`ExtrudedFiniteDifferenceGrid` with a
170+
`FiniteDifferenceGrid` vertical grid and a
171+
`SpectralElementGrid2D` horizontal grid.
172+
"""
173+
Box3DGrid(; kwargs...) = Box3DGrid(Float64; kwargs...)
174+
function Box3DGrid(
175+
::Type{FT};
176+
z_elem::Integer,
177+
x_min::Real,
178+
x_max::Real,
179+
y_min::Real,
180+
y_max::Real,
181+
z_min::Real,
182+
z_max::Real,
183+
periodic_x::Bool,
184+
periodic_y::Bool,
185+
Nq::Integer,
186+
x_elem::Integer,
187+
y_elem::Integer,
188+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
189+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
190+
stretch::Meshes.StretchingRule = Meshes.Uniform(),
191+
hypsography::HypsographyAdaption = Flat(),
192+
global_geometry::Geometry.AbstractGlobalGeometry = Geometry.CartesianGlobalGeometry(),
193+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
194+
) where {FT}
195+
check_device_context(context, device)
196+
x1boundary = (:east, :west)
197+
x2boundary = (:south, :north)
198+
z_boundary_names = (:bottom, :top)
199+
domain = Domains.RectangleDomain(
200+
Domains.IntervalDomain(
201+
Geometry.XPoint{FT}(x_min),
202+
Geometry.XPoint{FT}(x_max);
203+
periodic = periodic_x,
204+
boundary_names = x1boundary,
205+
),
206+
Domains.IntervalDomain(
207+
Geometry.YPoint{FT}(y_min),
208+
Geometry.YPoint{FT}(y_max);
209+
periodic = periodic_y,
210+
boundary_names = x2boundary,
211+
),
212+
)
213+
h_mesh = Meshes.RectilinearMesh(domain, x_elem, y_elem)
214+
h_topology = Topologies.Topology2D(context, h_mesh)
215+
h_grid = Grids.SpectralElementGrid2D(h_topology, quad)
216+
z_domain = Domains.IntervalDomain(
217+
Geometry.ZPoint{FT}(z_min),
218+
Geometry.ZPoint{FT}(z_max);
219+
boundary_names = z_boundary_names,
220+
)
221+
z_mesh = Meshes.IntervalMesh(z_domain, stretch; nelems = z_elem)
222+
z_topology = Topologies.IntervalTopology(context, z_mesh)
223+
vertical_grid = FiniteDifferenceGrid(z_topology)
224+
return ExtrudedFiniteDifferenceGrid(
225+
h_grid,
226+
vertical_grid,
227+
hypsography,
228+
global_geometry,
229+
)
230+
end
231+
232+
"""
233+
SliceXZGrid(
234+
::Type{<:AbstractFloat}; # defaults to Float64
235+
z_elem::Integer,
236+
x_min::Real,
237+
x_max::Real,
238+
z_min::Real,
239+
z_max::Real,
240+
periodic_x::Bool,
241+
Nq::Integer,
242+
x_elem::Integer,
243+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
244+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
245+
stretch::Meshes.StretchingRule = Meshes.Uniform(),
246+
hypsography::HypsographyAdaption = Flat(),
247+
global_geometry::Geometry.AbstractGlobalGeometry = Geometry.CartesianGlobalGeometry(),
248+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
249+
)
250+
251+
A convenience constructor, which builds a
252+
`ExtrudedFiniteDifferenceGrid` with a
253+
`FiniteDifferenceGrid` vertical grid and a
254+
`SpectralElementGrid1D` horizontal grid.
255+
- ``
256+
"""
257+
SliceXZGrid(; kwargs...) = SliceXZGrid(Float64; kwargs...)
258+
function SliceXZGrid(
259+
::Type{FT};
260+
z_elem::Integer,
261+
x_min::Real,
262+
x_max::Real,
263+
z_min::Real,
264+
z_max::Real,
265+
periodic_x::Bool,
266+
Nq::Integer,
267+
x_elem::Integer,
268+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
269+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
270+
stretch::Meshes.StretchingRule = Meshes.Uniform(),
271+
hypsography::HypsographyAdaption = Flat(),
272+
global_geometry::Geometry.AbstractGlobalGeometry = Geometry.CartesianGlobalGeometry(),
273+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
274+
) where {FT}
275+
check_device_context(context, device)
276+
277+
x1boundary = (:east, :west)
278+
z_boundary_names = (:bottom, :top)
279+
h_domain = Domains.IntervalDomain(
280+
Geometry.XPoint{FT}(x_min),
281+
Geometry.XPoint{FT}(x_max);
282+
periodic = periodic_x,
283+
boundary_names = x1boundary,
284+
)
285+
h_mesh = Meshes.IntervalMesh(h_domain; nelems = x_elem)
286+
h_topology = Topologies.IntervalTopology(context, h_mesh)
287+
h_grid = Grids.SpectralElementGrid1D(h_topology, quad)
288+
z_domain = Domains.IntervalDomain(
289+
Geometry.ZPoint{FT}(z_min),
290+
Geometry.ZPoint{FT}(z_max);
291+
boundary_names = z_boundary_names,
292+
)
293+
z_mesh = Meshes.IntervalMesh(z_domain, stretch; nelems = z_elem)
294+
z_topology = Topologies.IntervalTopology(context, z_mesh)
295+
vertical_grid = FiniteDifferenceGrid(z_topology)
296+
return ExtrudedFiniteDifferenceGrid(
297+
h_grid,
298+
vertical_grid,
299+
hypsography,
300+
global_geometry,
301+
)
302+
end
303+
304+
"""
305+
RectangleXYGrid(
306+
::Type{<:AbstractFloat}; # defaults to Float64
307+
x_min::Real,
308+
x_max::Real,
309+
y_min::Real,
310+
y_max::Real,
311+
periodic_x::Bool,
312+
periodic_y::Bool,
313+
Nq::Integer,
314+
x_elem::Integer, # number of horizontal elements
315+
y_elem::Integer, # number of horizontal elements
316+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
317+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
318+
hypsography::HypsographyAdaption = Flat(),
319+
global_geometry::Geometry.AbstractGlobalGeometry = Geometry.CartesianGlobalGeometry(),
320+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
321+
)
322+
323+
A convenience constructor, which builds a
324+
`SpectralElementGrid2D` with a horizontal
325+
`RectilinearMesh` mesh.
326+
"""
327+
RectangleXYGrid(; kwargs...) = RectangleXYGrid(Float64; kwargs...)
328+
function RectangleXYGrid(
329+
::Type{FT};
330+
x_min::Real,
331+
x_max::Real,
332+
y_min::Real,
333+
y_max::Real,
334+
periodic_x::Bool,
335+
periodic_y::Bool,
336+
Nq::Integer,
337+
x_elem::Integer, # number of horizontal elements
338+
y_elem::Integer, # number of horizontal elements
339+
device::ClimaComms.AbstractDevice = ClimaComms.device(),
340+
context::ClimaComms.AbstractCommsContext = ClimaComms.context(device),
341+
hypsography::HypsographyAdaption = Flat(),
342+
global_geometry::Geometry.AbstractGlobalGeometry = Geometry.CartesianGlobalGeometry(),
343+
quad::Quadratures.QuadratureStyle = Quadratures.GLL{Nq}(),
344+
) where {FT}
345+
check_device_context(context, device)
346+
347+
x1boundary = (:east, :west)
348+
x2boundary = (:south, :north)
349+
domain = Domains.RectangleDomain(
350+
Domains.IntervalDomain(
351+
Geometry.XPoint{FT}(x_min),
352+
Geometry.XPoint{FT}(x_max);
353+
periodic = periodic_x,
354+
boundary_names = x1boundary,
355+
),
356+
Domains.IntervalDomain(
357+
Geometry.YPoint{FT}(y_min),
358+
Geometry.YPoint{FT}(y_max);
359+
periodic = periodic_y,
360+
boundary_names = x2boundary,
361+
),
362+
)
363+
h_mesh = Meshes.RectilinearMesh(domain, x_elem, y_elem)
364+
h_topology = Topologies.Topology2D(context, h_mesh)
365+
return Grids.SpectralElementGrid2D(h_topology, quad)
366+
end

0 commit comments

Comments
 (0)