From d05f90ae0da205083658f4d2f2c2d6b9c5846e60 Mon Sep 17 00:00:00 2001 From: Charles Kawczynski Date: Mon, 11 Nov 2024 12:58:55 -0500 Subject: [PATCH] Define CommonSpaces module --- NEWS.md | 21 +- docs/src/api.md | 14 + src/ClimaCore.jl | 1 + src/CommonGrids/CommonGrids.jl | 11 +- src/CommonSpaces/CommonSpaces.jl | 417 ++++++++++++++++++++++++ src/Spaces/extruded.jl | 14 + test/CommonSpaces/unit_common_spaces.jl | 137 ++++++++ 7 files changed, 607 insertions(+), 8 deletions(-) create mode 100644 src/CommonSpaces/CommonSpaces.jl create mode 100644 test/CommonSpaces/unit_common_spaces.jl diff --git a/NEWS.md b/NEWS.md index b4eb35a610..629987be79 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,16 +4,23 @@ ClimaCore.jl Release Notes main ------- + - We've added new convenience constructors for spaces PR [2082](https://github.com/CliMA/ClimaCore.jl/pull/2082). Here are links to the new constructors: + - [ExtrudedCubedSphereSpace]() + - [CubedSphereSpace]() + - [ColumnSpace]() + - [Box3DSpace]() + - [SliceXZSpace]() + - [RectangleXYSpace]() + v0.14.20 -------- - We've added new convenience constructors for grids PR [1848](https://github.com/CliMA/ClimaCore.jl/pull/1848). Here are links to the new constructors: - - [ExtrudedCubedSphereGrid]() - - [CubedSphereGrid]() - - [ColumnGrid]() - - [Box3DGrid]() - - [SliceXZGrid]() - - [RectangleXYGrid]() + - [ExtrudedCubedSphereGrid](https://github.com/CliMA/ClimaCore.jl/blob/cbb193042fac3b4bef33251fbc0f232427bfe506/src/CommonGrids/CommonGrids.jl#L85-L144) + - [CubedSphereGrid](https://github.com/CliMA/ClimaCore.jl/blob/cbb193042fac3b4bef33251fbc0f232427bfe506/src/CommonGrids/CommonGrids.jl#L200-L235) + - [ColumnGrid](https://github.com/CliMA/ClimaCore.jl/blob/cbb193042fac3b4bef33251fbc0f232427bfe506/src/CommonGrids/CommonGrids.jl#L259-L281) + - [Box3DGrid](https://github.com/CliMA/ClimaCore.jl/blob/cbb193042fac3b4bef33251fbc0f232427bfe506/src/CommonGrids/CommonGrids.jl#L303-L378) + - [SliceXZGrid](https://github.com/CliMA/ClimaCore.jl/blob/cbb193042fac3b4bef33251fbc0f232427bfe506/src/CommonGrids/CommonGrids.jl#L441-L498) + - [RectangleXYGrid](https://github.com/CliMA/ClimaCore.jl/blob/cbb193042fac3b4bef33251fbc0f232427bfe506/src/CommonGrids/CommonGrids.jl#L547-L602) - A `strict = true` keyword was added to `rcompare`, which checks that the types match. If `strict = false`, then `rcompare` will return `true` for `FieldVector`s and `NamedTuple`s with the same properties but permuted order. For example: - `rcompare((;a=1,b=2), (;b=2,a=1); strict = true)` will return `false` and diff --git a/docs/src/api.md b/docs/src/api.md index cfb9fd029b..66bf86511c 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -180,6 +180,8 @@ Topologies.ghost_neighboring_elements ## Grids ```@docs +Grids.CellFace +Grids.CellCenter Grids.ColumnGrid Grids.FiniteDifferenceGrid Grids.ExtrudedFiniteDifferenceGrid @@ -247,6 +249,18 @@ Spaces.SpectralElementSpaceSlab Spaces.node_horizontal_length_scale ``` +## CommonSpaces + +```@docs +CommonSpaces +CommonSpaces.ExtrudedCubedSphereSpace +CommonSpaces.CubedSphereSpace +CommonSpaces.ColumnSpace +CommonSpaces.Box3DSpace +CommonSpaces.SliceXZSpace +CommonSpaces.RectangleXYSpace +``` + ### Quadratures diff --git a/src/ClimaCore.jl b/src/ClimaCore.jl index cb908bf7f1..2ee050abb2 100644 --- a/src/ClimaCore.jl +++ b/src/ClimaCore.jl @@ -24,6 +24,7 @@ include("Limiters/Limiters.jl") include("InputOutput/InputOutput.jl") include("Remapping/Remapping.jl") include("CommonGrids/CommonGrids.jl") +include("CommonSpaces/CommonSpaces.jl") include("deprecated.jl") diff --git a/src/CommonGrids/CommonGrids.jl b/src/CommonGrids/CommonGrids.jl index 7322fb9779..4a0b183c38 100644 --- a/src/CommonGrids/CommonGrids.jl +++ b/src/CommonGrids/CommonGrids.jl @@ -269,7 +269,16 @@ end ) A convenience constructor, which builds a -[`Grids.FiniteDifferenceGrid`](@ref). +[`Grids.FiniteDifferenceGrid`](@ref) given: + + - `FT` the floating-point type (defaults to `Float64`) [`Float32`, `Float64`] + - `z_elem` the number of z-points + - `z_min` the domain minimum along the z-direction. + - `z_max` the domain maximum along the z-direction. + - `device` the `ClimaComms.device` + - `context` the `ClimaComms.context` + - `stretch` the mesh `Meshes.StretchingRule` (defaults to [`Meshes.Uniform`](@ref)) + - `z_mesh` the vertical mesh, defaults to an `Meshes.IntervalMesh` along `z` with given `stretch` # Example usage diff --git a/src/CommonSpaces/CommonSpaces.jl b/src/CommonSpaces/CommonSpaces.jl new file mode 100644 index 0000000000..f668ba5ea6 --- /dev/null +++ b/src/CommonSpaces/CommonSpaces.jl @@ -0,0 +1,417 @@ +""" + CommonSpaces + +CommonSpaces contains convenience constructors for common +spaces, which builds off of [`CommonGrids`](@ref) and +(when appropriate) requires an additional argument, +`staggering::Staggering` to construct the desired +space. +""" +module CommonSpaces + +export ExtrudedCubedSphereSpace, + CubedSphereSpace, ColumnSpace, Box3DSpace, SliceXZSpace, RectangleXYSpace + +export Grids +import ClimaComms + +import ..DataLayouts, + ..Meshes, ..Topologies, ..Geometry, ..Domains, ..Quadratures, ..Grids + +import ..Grids: Staggering +import ..Spaces +import ..CommonGrids +import ..CommonGrids: + ExtrudedCubedSphereGrid, + CubedSphereGrid, + ColumnGrid, + Box3DGrid, + SliceXZGrid, + RectangleXYGrid + +""" + ExtrudedCubedSphereSpace( + ::Type{<:AbstractFloat}; # defaults to Float64 + z_elem::Integer, + z_min::Real, + z_max::Real, + radius::Real, + h_elem::Integer, + n_quad_points::Integer, + device::ClimaComms.AbstractDevice = ClimaComms.device(), + context::ClimaComms.AbstractCommsContext = ClimaComms.context(device), + stretch::Meshes.StretchingRule = Meshes.Uniform(), + hypsography_fun = (h_grid, z_grid) -> Grids.Flat(), + global_geometry::Geometry.AbstractGlobalGeometry = Geometry.ShallowSphericalGlobalGeometry(radius), + quad::Quadratures.QuadratureStyle = Quadratures.GLL{n_quad_points}(), + h_mesh = Meshes.EquiangularCubedSphere(Domains.SphereDomain{FT}(radius), h_elem), + h_topology::Topologies.AbstractDistributedTopology = Topologies.Topology2D(context, h_mesh), + horizontal_layout_type = DataLayouts.IJFH, + z_mesh::Meshes.IntervalMesh = DefaultZMesh(FT; z_min, z_max, z_elem, stretch), + enable_bubble::Bool = false + staggering::Staggering, + ) + +Construct an [`Spaces.ExtrudedFiniteDifferenceSpace`](@ref) for a +cubed sphere configuration, given: + + - `FT` the floating-point type (defaults to `Float64`) [`Float32`, `Float64`] + - `z_elem` the number of z-points + - `z_min` the domain minimum along the z-direction. + - `z_max` the domain maximum along the z-direction. + - `radius` the radius of the cubed sphere + - `h_elem` the number of horizontal elements per side of every panel (6 panels in total) + - `n_quad_points` the number of quadrature points per horizontal element + - `device` the `ClimaComms.device` + - `context` the `ClimaComms.context` + - `stretch` the mesh `Meshes.StretchingRule` (defaults to [`Meshes.Uniform`](@ref)) + - `hypsography_fun` a function or callable object (`hypsography_fun(h_grid, z_grid) -> hypsography`) for constructing the hypsography model. + - `global_geometry` the global geometry (defaults to [`Geometry.CartesianGlobalGeometry`](@ref)) + - `quad` the quadrature style (defaults to `Quadratures.GLL{n_quad_points}`) + - `h_mesh` the horizontal mesh (defaults to `Meshes.EquiangularCubedSphere`) + - `h_topology` the horizontal topology (defaults to `Topologies.Topology2D`) + - `horizontal_layout_type` the horizontal DataLayout type (defaults to `DataLayouts.IJFH`). This parameter describes how data is arranged in memory. See [`Grids.SpectralElementGrid2D`](@ref) for its use. + - `z_mesh` the vertical mesh, defaults to an `Meshes.IntervalMesh` along `z` with given `stretch` + - `enable_bubble` enables the "bubble correction" for more accurate element areas when computing the spectral element space. See [`Grids.SpectralElementGrid2D`](@ref) for more information. + - `staggering` vertical staggering, can be one of [[`Grids.FaceCenter`](@ref), [`Grids.CellCenter`](@ref)] + +Note that these arguments are all the same +as [`CommonGrids.ExtrudedCubedSphereGrid`](@ref), +except for `staggering`. + +# Example usage + +```julia +using ClimaCore.CommonSpaces +space = ExtrudedCubedSphereSpace(; + z_elem = 10, + z_min = 0, + z_max = 1, + radius = 10, + h_elem = 10, + n_quad_points = 4, + staggering = Grids.CellCenter() +) +``` +""" +function ExtrudedCubedSphereSpace end + +ExtrudedCubedSphereSpace(; kwargs...) = + ExtrudedCubedSphereSpace(Float64; kwargs...) +ExtrudedCubedSphereSpace( + ::Type{FT}; + staggering::Staggering, + kwargs..., +) where {FT} = Spaces.ExtrudedFiniteDifferenceSpace( + ExtrudedCubedSphereGrid(FT; kwargs...), + staggering, +) + +""" + CubedSphereSpace( + ::Type{<:AbstractFloat}; # defaults to Float64 + radius::Real, + h_elem::Integer, + n_quad_points::Integer, + device::ClimaComms.AbstractDevice = ClimaComms.device(), + context::ClimaComms.AbstractCommsContext = ClimaComms.context(device), + quad::Quadratures.QuadratureStyle = Quadratures.GLL{n_quad_points}(), + h_mesh = Meshes.EquiangularCubedSphere(Domains.SphereDomain{FT}(radius), h_elem), + h_topology::Topologies.AbstractDistributedTopology = Topologies.Topology2D(context, h_mesh), + horizontal_layout_type = DataLayouts.IJFH, + ) + +Construct a [`Spaces.SpectralElementSpace2D`](@ref) for a +cubed sphere configuration, given: + + - `FT` the floating-point type (defaults to `Float64`) [`Float32`, `Float64`] + - `radius` the radius of the cubed sphere + - `h_elem` the number of horizontal elements per side of every panel (6 panels in total) + - `n_quad_points` the number of quadrature points per horizontal element + - `device` the `ClimaComms.device` + - `context` the `ClimaComms.context` + - `quad` the quadrature style (defaults to `Quadratures.GLL{n_quad_points}`) + - `h_mesh` the horizontal mesh (defaults to `Meshes.EquiangularCubedSphere`) + - `h_topology` the horizontal topology (defaults to `Topologies.Topology2D`) + - `horizontal_layout_type` the horizontal DataLayout type (defaults to `DataLayouts.IJFH`). This parameter describes how data is arranged in memory. See [`Grids.SpectralElementGrid2D`](@ref) for its use. + +Note that these arguments are all the same +as [`CommonGrids.CubedSphereGrid`](@ref). + +# Example usage + +```julia +using ClimaCore.CommonSpaces +space = CubedSphereSpace(; + radius = 10, + n_quad_points = 4, + h_elem = 10, +) +``` +""" +function CubedSphereSpace end +CubedSphereSpace(; kwargs...) = CubedSphereSpace(Float64; kwargs...) +CubedSphereSpace(::Type{FT}; kwargs...) where {FT} = + Spaces.SpectralElementSpace2D(CubedSphereGrid(FT; kwargs...)) + +""" + ColumnSpace( + ::Type{<:AbstractFloat}; # defaults to Float64 + z_elem::Integer, + z_min::Real, + z_max::Real, + device::ClimaComms.AbstractDevice = ClimaComms.device(), + context::ClimaComms.AbstractCommsContext = ClimaComms.context(device), + stretch::Meshes.StretchingRule = Meshes.Uniform(), + z_mesh::Meshes.IntervalMesh = DefaultZMesh(FT; z_min, z_max, z_elem, stretch), + ) + +Construct a 1D [`Spaces.FiniteDifferenceSpace`](@ref) for a +column configuration, given: + + - `FT` the floating-point type (defaults to `Float64`) [`Float32`, `Float64`] + - `z_elem` the number of z-points + - `z_min` the domain minimum along the z-direction. + - `z_max` the domain maximum along the z-direction. + - `device` the `ClimaComms.device` + - `context` the `ClimaComms.context` + - `stretch` the mesh `Meshes.StretchingRule` (defaults to [`Meshes.Uniform`](@ref)) + - `z_mesh` the vertical mesh, defaults to an `Meshes.IntervalMesh` along `z` with given `stretch` + - `staggering` vertical staggering, can be one of [[`Grids.FaceCenter`](@ref), [`Grids.CellCenter`](@ref)] + +Note that these arguments are all the same +as [`CommonGrids.ColumnGrid`](@ref), +except for `staggering`. + +# Example usage + +```julia +using ClimaCore.CommonSpaces +space = ColumnSpace(; + z_elem = 10, + z_min = 0, + z_max = 10, + staggering = Grids.CellCenter() +) +``` +""" +function ColumnSpace end +ColumnSpace(; kwargs...) = ColumnSpace(Float64; kwargs...) +ColumnSpace(::Type{FT}; staggering::Staggering, kwargs...) where {FT} = + Spaces.FiniteDifferenceSpace(ColumnGrid(FT; kwargs...), staggering) + +""" + Box3DSpace( + ::Type{<:AbstractFloat}; # defaults to Float64 + z_elem::Integer, + x_min::Real, + x_max::Real, + y_min::Real, + y_max::Real, + z_min::Real, + z_max::Real, + periodic_x::Bool, + periodic_y::Bool, + n_quad_points::Integer, + x_elem::Integer, + y_elem::Integer, + device::ClimaComms.AbstractDevice = ClimaComms.device(), + context::ClimaComms.AbstractCommsContext = ClimaComms.context(device), + stretch::Meshes.StretchingRule = Meshes.Uniform(), + hypsography_fun = (h_grid, z_grid) -> Grids.Flat(), + global_geometry::Geometry.AbstractGlobalGeometry = Geometry.CartesianGlobalGeometry(), + quad::Quadratures.QuadratureStyle = Quadratures.GLL{n_quad_points}(), + horizontal_layout_type = DataLayouts.IJFH, + [h_topology::Topologies.AbstractDistributedTopology], # optional + [z_mesh::Meshes.IntervalMesh], # optional + enable_bubble::Bool = false, + staggering::Staggering + ) + +Construct a [`Spaces.ExtrudedFiniteDifferenceSpace`](@ref) +for a 3D box configuration, given: + + - `z_elem` the number of z-points + - `x_min` the domain minimum along the x-direction. + - `x_max` the domain maximum along the x-direction. + - `y_min` the domain minimum along the y-direction. + - `y_max` the domain maximum along the y-direction. + - `z_min` the domain minimum along the z-direction. + - `z_max` the domain maximum along the z-direction. + - `periodic_x` Bool indicating to use periodic domain along x-direction + - `periodic_y` Bool indicating to use periodic domain along y-direction + - `n_quad_points` the number of quadrature points per horizontal element + - `x_elem` the number of x-points + - `y_elem` the number of y-points + - `device` the `ClimaComms.device` + - `context` the `ClimaComms.context` + - `stretch` the mesh `Meshes.StretchingRule` (defaults to [`Meshes.Uniform`](@ref)) + - `hypsography_fun` a function or callable object (`hypsography_fun(h_grid, z_grid) -> hypsography`) for constructing the hypsography model. + - `global_geometry` the global geometry (defaults to [`Geometry.CartesianGlobalGeometry`](@ref)) + - `quad` the quadrature style (defaults to `Quadratures.GLL{n_quad_points}`) + - `h_topology` the horizontal topology (defaults to `Topologies.Topology2D`) + - `z_mesh` the vertical mesh, defaults to an `Meshes.IntervalMesh` along `z` with given `stretch` + - `enable_bubble` enables the "bubble correction" for more accurate element areas when computing the spectral element space. See [`Grids.SpectralElementGrid2D`](@ref) for more information. + - `horizontal_layout_type` the horizontal DataLayout type (defaults to `DataLayouts.IJFH`). This parameter describes how data is arranged in memory. See [`Grids.SpectralElementGrid2D`](@ref) for its use. + - `staggering` vertical staggering, can be one of [[`Grids.FaceCenter`](@ref), [`Grids.CellCenter`](@ref)] + +Note that these arguments are all the same +as [`CommonGrids.Box3DGrid`](@ref), +except for `staggering`. + +# Example usage + +```julia +using ClimaCore.CommonSpaces +space = Box3DSpace(; + z_elem = 10, + x_min = 0, + x_max = 1, + y_min = 0, + y_max = 1, + z_min = 0, + z_max = 10, + periodic_x = false, + periodic_y = false, + n_quad_points = 4, + x_elem = 3, + y_elem = 4, + staggering = Grids.CellCenter() +) +``` +""" +function Box3DSpace end +Box3DSpace(; kwargs...) = Box3DSpace(Float64; kwargs...) +Box3DSpace(::Type{FT}; staggering::Staggering, kwargs...) where {FT} = + Spaces.ExtrudedFiniteDifferenceSpace(Box3DGrid(FT; kwargs...), staggering) + +""" + SliceXZSpace( + ::Type{<:AbstractFloat}; # defaults to Float64 + z_elem::Integer, + x_min::Real, + x_max::Real, + z_min::Real, + z_max::Real, + periodic_x::Bool, + n_quad_points::Integer, + x_elem::Integer, + device::ClimaComms.AbstractDevice = ClimaComms.device(), + context::ClimaComms.AbstractCommsContext = ClimaComms.context(device), + stretch::Meshes.StretchingRule = Meshes.Uniform(), + hypsography_fun = (h_grid, z_grid) -> Grids.Flat(), + global_geometry::Geometry.AbstractGlobalGeometry = Geometry.CartesianGlobalGeometry(), + quad::Quadratures.QuadratureStyle = Quadratures.GLL{n_quad_points}(), + staggering::Staggering + ) + +Construct a [`Spaces.ExtrudedFiniteDifferenceSpace`](@ref) +for a 2D slice configuration, given: + + - `FT` the floating-point type (defaults to `Float64`) [`Float32`, `Float64`] + - `z_elem` the number of z-points + - `x_min` the domain minimum along the x-direction. + - `x_max` the domain maximum along the x-direction. + - `z_min` the domain minimum along the z-direction. + - `z_max` the domain maximum along the z-direction. + - `periodic_x` Bool indicating to use periodic domain along x-direction + - `n_quad_points` the number of quadrature points per horizontal element + - `x_elem` the number of x-points + - `device` the `ClimaComms.device` + - `context` the `ClimaComms.context` + - `stretch` the mesh `Meshes.StretchingRule` (defaults to [`Meshes.Uniform`](@ref)) + - `hypsography_fun` a function or callable object (`hypsography_fun(h_grid, z_grid) -> hypsography`) for constructing the hypsography model. + - `global_geometry` the global geometry (defaults to [`Geometry.CartesianGlobalGeometry`](@ref)) + - `quad` the quadrature style (defaults to `Quadratures.GLL{n_quad_points}`) + - `staggering` vertical staggering, can be one of [[`Grids.FaceCenter`](@ref), [`Grids.CellCenter`](@ref)] + +Note that these arguments are all the same +as [`CommonGrids.SliceXZGrid`](@ref), +except for `staggering`. + +# Example usage + +```julia +using ClimaCore.CommonSpaces +space = SliceXZSpace(; + z_elem = 10, + x_min = 0, + x_max = 1, + z_min = 0, + z_max = 1, + periodic_x = false, + n_quad_points = 4, + x_elem = 4, + staggering = Grids.CellCenter() +) +``` +""" +function SliceXZSpace end +SliceXZSpace(; kwargs...) = SliceXZSpace(Float64; kwargs...) +SliceXZSpace(::Type{FT}; staggering::Staggering, kwargs...) where {FT} = + Spaces.ExtrudedFiniteDifferenceSpace(SliceXZGrid(FT; kwargs...), staggering) + +""" + RectangleXYSpace( + ::Type{<:AbstractFloat}; # defaults to Float64 + x_min::Real, + x_max::Real, + y_min::Real, + y_max::Real, + periodic_x::Bool, + periodic_y::Bool, + n_quad_points::Integer, + x_elem::Integer, # number of horizontal elements + y_elem::Integer, # number of horizontal elements + device::ClimaComms.AbstractDevice = ClimaComms.device(), + context::ClimaComms.AbstractCommsContext = ClimaComms.context(device), + hypsography::Grids.HypsographyAdaption = Grids.Flat(), + global_geometry::Geometry.AbstractGlobalGeometry = Geometry.CartesianGlobalGeometry(), + quad::Quadratures.QuadratureStyle = Quadratures.GLL{n_quad_points}(), + ) + +Construct a [`Spaces.SpectralElementSpace2D`](@ref) space +for a 2D rectangular configuration, given: + + - `x_min` the domain minimum along the x-direction. + - `x_max` the domain maximum along the x-direction. + - `y_min` the domain minimum along the y-direction. + - `y_max` the domain maximum along the y-direction. + - `periodic_x` Bool indicating to use periodic domain along x-direction + - `periodic_y` Bool indicating to use periodic domain along y-direction + - `n_quad_points` the number of quadrature points per horizontal element + - `x_elem` the number of x-points + - `y_elem` the number of y-points + - `device` the `ClimaComms.device` + - `context` the `ClimaComms.context` + - `hypsography_fun` a function or callable object (`hypsography_fun(h_grid, z_grid) -> hypsography`) for constructing the hypsography model. + - `global_geometry` the global geometry (defaults to [`Geometry.CartesianGlobalGeometry`](@ref)) + - `quad` the quadrature style (defaults to `Quadratures.GLL{n_quad_points}`) + +Note that these arguments are all the same +as [`CommonGrids.RectangleXYGrid`](@ref), +except for `staggering`. + +# Example usage + +```julia +using ClimaCore.CommonSpaces +space = RectangleXYSpace(; + x_min = 0, + x_max = 1, + y_min = 0, + y_max = 1, + periodic_x = false, + periodic_y = false, + n_quad_points = 4, + x_elem = 3, + y_elem = 4, +) +``` +""" +function RectangleXYSpace end +RectangleXYSpace(; kwargs...) = RectangleXYSpace(Float64; kwargs...) +RectangleXYSpace(::Type{FT}; kwargs...) where {FT} = + Spaces.SpectralElementSpace2D(RectangleXYGrid(FT; kwargs...)) + +end # module diff --git a/src/Spaces/extruded.jl b/src/Spaces/extruded.jl index afa35a69c7..5bf7be2c69 100644 --- a/src/Spaces/extruded.jl +++ b/src/Spaces/extruded.jl @@ -1,5 +1,19 @@ +""" + ExtrudedFiniteDifferenceSpace(grid, staggering) + + ExtrudedFiniteDifferenceSpace( + horizontal_space::AbstractSpace, + vertical_space::FiniteDifferenceSpace, + hypsography::Grids.HypsographyAdaption = Grids.Flat(), + ) +An extruded finite-difference space, +where the extruded direction is _staggered_, +containing grid information at either + - cell centers (where `staggering` is [`Grids.CellCenter`](@ref)) or + - cell faces (where `staggering` is [`Grids.CellFace`](@ref)) +""" struct ExtrudedFiniteDifferenceSpace{ G <: Grids.AbstractExtrudedFiniteDifferenceGrid, S <: Staggering, diff --git a/test/CommonSpaces/unit_common_spaces.jl b/test/CommonSpaces/unit_common_spaces.jl new file mode 100644 index 0000000000..468ea9e69f --- /dev/null +++ b/test/CommonSpaces/unit_common_spaces.jl @@ -0,0 +1,137 @@ +#= +julia --project +using Revise; include(joinpath("test", "CommonSpaces", "unit_common_spaces.jl")) +=# +import ClimaComms +ClimaComms.@import_required_backends +using ClimaCore.CommonSpaces +using ClimaCore: + Geometry, + Hypsography, + Fields, + Spaces, + Grids, + Topologies, + Meshes, + DataLayouts +using Test + +@testset "Convenience constructors" begin + function warp_surface(coord) + # sin²(x) form ground elevation + x = Geometry.component(coord, 1) + FT = eltype(x) + hc = FT(500.0) + h = hc * FT(sin(π * x / 25000)^2) + return h + end + + space = ExtrudedCubedSphereSpace(; + z_elem = 10, + z_min = 0, + z_max = 1, + radius = 10, + h_elem = 10, + n_quad_points = 4, + horizontal_layout_type = DataLayouts.IJHF, + staggering = Grids.CellCenter(), + ) + grid = Spaces.grid(space) + @test grid isa Grids.ExtrudedFiniteDifferenceGrid + @test grid.horizontal_grid isa Grids.SpectralElementGrid2D + @test Grids.topology(grid.horizontal_grid).mesh isa + Meshes.EquiangularCubedSphere + + function hypsography_fun(h_grid, z_grid) + h_space = Spaces.SpectralElementSpace2D(h_grid) + cf = Fields.coordinate_field(h_space) + warp_fn = warp_surface # closure + z_surface = map(cf) do coord + Geometry.ZPoint(warp_fn(coord)) + end + Hypsography.LinearAdaption(z_surface) + end + + space = ExtrudedCubedSphereSpace(; + z_elem = 10, + z_min = 0, + z_max = 1, + radius = 10, + h_elem = 10, + n_quad_points = 4, + hypsography_fun, + staggering = Grids.CellCenter(), + ) + grid = Spaces.grid(space) + @test grid isa Grids.ExtrudedFiniteDifferenceGrid + @test grid.horizontal_grid isa Grids.SpectralElementGrid2D + @test Grids.topology(grid.horizontal_grid).mesh isa + Meshes.EquiangularCubedSphere + @test Grids.topology(grid.horizontal_grid).mesh isa + Meshes.EquiangularCubedSphere + + space = CubedSphereSpace(; radius = 10, n_quad_points = 4, h_elem = 10) + grid = Spaces.grid(space) + @test grid isa Grids.SpectralElementGrid2D + @test Grids.topology(grid).mesh isa Meshes.EquiangularCubedSphere + + space = ColumnSpace(; + z_elem = 10, + z_min = 0, + z_max = 1, + staggering = Grids.CellCenter(), + ) + grid = Spaces.grid(space) + @test grid isa Grids.FiniteDifferenceGrid + + space = Box3DSpace(; + z_elem = 10, + x_min = 0, + x_max = 1, + y_min = 0, + y_max = 1, + z_min = 0, + z_max = 10, + periodic_x = false, + periodic_y = false, + n_quad_points = 4, + x_elem = 3, + y_elem = 4, + staggering = Grids.CellCenter(), + ) + grid = Spaces.grid(space) + @test grid isa Grids.ExtrudedFiniteDifferenceGrid + @test grid.horizontal_grid isa Grids.SpectralElementGrid2D + @test Grids.topology(grid.horizontal_grid).mesh isa Meshes.RectilinearMesh + + space = SliceXZSpace(; + z_elem = 10, + x_min = 0, + x_max = 1, + z_min = 0, + z_max = 1, + periodic_x = false, + n_quad_points = 4, + x_elem = 4, + staggering = Grids.CellCenter(), + ) + grid = Spaces.grid(space) + @test grid isa Grids.ExtrudedFiniteDifferenceGrid + @test grid.horizontal_grid isa Grids.SpectralElementGrid1D + @test Grids.topology(grid.horizontal_grid).mesh isa Meshes.IntervalMesh + + space = RectangleXYSpace(; + x_min = 0, + x_max = 1, + y_min = 0, + y_max = 1, + periodic_x = false, + periodic_y = false, + n_quad_points = 4, + x_elem = 3, + y_elem = 4, + ) + grid = Spaces.grid(space) + @test grid isa Grids.SpectralElementGrid2D + @test Grids.topology(grid).mesh isa Meshes.RectilinearMesh +end