Mercurial > repos > public > sbplib_julia
changeset 1448:0322c181a1cd feature/grids/curvilinear
Merge default
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Wed, 22 Nov 2023 17:53:31 +0100 |
parents | 433245fd33c0 (diff) f217c6167952 (current diff) |
children | a0b1449dba4e |
files | src/Grids/tensor_grid.jl test/Grids/tensor_grid_test.jl |
diffstat | 4 files changed, 217 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/Grids/Grids.jl Wed Nov 22 17:52:03 2023 +0100 +++ b/src/Grids/Grids.jl Wed Nov 22 17:53:31 2023 +0100 @@ -1,3 +1,4 @@ +# TODO: Double check that the interfaces for indexing and iterating are fully implemented and tested for all grids. module Grids using Sbplib.RegionIndices @@ -35,11 +36,18 @@ export equidistant_grid export CartesianBoundary + +# CurvilinearGrid +export CurvilinearGrid +export jacobian +export logicalgrid + abstract type BoundaryIdentifier end include("grid.jl") include("tensor_grid.jl") include("equidistant_grid.jl") include("zero_dim_grid.jl") +include("curvilinear_grid.jl") end # module
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Grids/curvilinear_grid.jl Wed Nov 22 17:53:31 2023 +0100 @@ -0,0 +1,92 @@ +# TBD: Rename to MappedGrid? +struct CurvilinearGrid{T,D, GT<:Grid{<:Any,D}, CT<:AbstractArray{T,D}, JT<:AbstractArray{<:AbstractArray{<:Any, 2}, D}} <: Grid{T,D} + logicalgrid::GT + physicalcoordinates::CT + jacobian::JT +end + +jacobian(g::CurvilinearGrid) = g.jacobian +logicalgrid(g::CurvilinearGrid) = g.logicalgrid + + +# Indexing interface +Base.getindex(g::CurvilinearGrid, I::Vararg{Int}) = g.physicalcoordinates[I...] +Base.eachindex(g::CurvilinearGrid) = eachindex(g.logicalgrid) + +Base.firstindex(g::CurvilinearGrid, d) = firstindex(g.logicalgrid, d) +Base.lastindex(g::CurvilinearGrid, d) = lastindex(g.logicalgrid, d) + +# function Base.getindex(g::TensorGrid, I...) +# szs = ndims.(g.grids) + +# Is = LazyTensors.split_tuple(I, szs) +# ps = map((g,I)->SVector(g[I...]), g.grids, Is) + +# return vcat(ps...) +# end + +# function Base.eachindex(g::TensorGrid) +# szs = LazyTensors.concatenate_tuples(size.(g.grids)...) +# return CartesianIndices(szs) +# end + +# # Iteration interface +# Base.iterate(g::TensorGrid) = iterate(Iterators.product(g.grids...)) |> _iterate_combine_coords +# Base.iterate(g::TensorGrid, state) = iterate(Iterators.product(g.grids...), state) |> _iterate_combine_coords +# _iterate_combine_coords(::Nothing) = nothing +# _iterate_combine_coords((next,state)) = combine_coordinates(next...), state + +# Base.IteratorSize(::Type{<:TensorGrid{<:Any, D}}) where D = Base.HasShape{D}() +# Base.eltype(::Type{<:TensorGrid{T}}) where T = T +# Base.length(g::TensorGrid) = sum(length, g.grids) +# Base.size(g::TensorGrid) = LazyTensors.concatenate_tuples(size.(g.grids)...) + + +# refine(g::TensorGrid, r::Int) = mapreduce(g->refine(g,r), TensorGrid, g.grids) +# coarsen(g::TensorGrid, r::Int) = mapreduce(g->coarsen(g,r), TensorGrid, g.grids) + +# """ +# TensorGridBoundary{N, BID} <: BoundaryIdentifier + +# A boundary identifier for a tensor grid. `N` Specifies which grid in the +# tensor product and `BID` which boundary on that grid. +# """ +# struct TensorGridBoundary{N, BID} <: BoundaryIdentifier end +# grid_id(::TensorGridBoundary{N, BID}) where {N, BID} = N +# boundary_id(::TensorGridBoundary{N, BID}) where {N, BID} = BID() + +# """ +# boundary_identifiers(g::TensorGrid) + +# Returns a tuple containing the boundary identifiers of `g`. +# """ +# function boundary_identifiers(g::TensorGrid) +# per_grid = map(eachindex(g.grids)) do i +# return map(bid -> TensorGridBoundary{i, typeof(bid)}(), boundary_identifiers(g.grids[i])) +# end +# return LazyTensors.concatenate_tuples(per_grid...) +# end + + +# """ +# boundary_grid(g::TensorGrid, id::TensorGridBoundary) + +# The grid for the boundary of `g` specified by `id`. +# """ +# function boundary_grid(g::TensorGrid, id::TensorGridBoundary) +# local_boundary_grid = boundary_grid(g.grids[grid_id(id)], boundary_id(id)) +# new_grids = Base.setindex(g.grids, local_boundary_grid, grid_id(id)) +# return TensorGrid(new_grids...) +# end + + + + + + + + +# Do we add a convenience function `curvilinear_grid`? It could help with +# creating the logical grid, evaluating functions and possibly calculating the +# entries in the jacobian. +
--- a/src/Grids/tensor_grid.jl Wed Nov 22 17:52:03 2023 +0100 +++ b/src/Grids/tensor_grid.jl Wed Nov 22 17:53:31 2023 +0100 @@ -1,3 +1,5 @@ +# TODO: Check this file and other grids for duplicate implementation of general methods implemented for Grid + """ TensorGrid{T,D} <: Grid{T,D}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/Grids/curvilinear_grid_test.jl Wed Nov 22 17:53:31 2023 +0100 @@ -0,0 +1,115 @@ +using Sbplib.Grids +using Test +using StaticArrays + +@testset "CurvilinearGrid" begin + lg = equidistant_grid((11,11), (0,0), (1,1)) # TODO: Change dims of the grid to be different + x̄ = map(ξ̄ -> 2ξ̄, lg) + J = map(ξ̄ -> @SArray(fill(2., 2, 2)), lg) + cg = CurvilinearGrid(lg, x̄, J) + + # TODO: Test constructor for different dims of range and domain for the coordinates + # TODO: Test constructor with different type than TensorGrid. a dummy type? + + @test_broken false # @test_throws ArgumentError("Sizes must match") CurvilinearGrid(lg, map(ξ̄ -> @SArray[ξ̄[1], ξ̄[2], -ξ̄[1]], lg), rand(SMatrix{2,3,Float64},15,11)) + + + @test cg isa Grid{SVector{2, Float64},2} + + @test jacobian(cg) isa Array{<:AbstractMatrix} + @test logicalgrid(cg) isa Grid + + @testset "Indexing Interface" begin + cg = CurvilinearGrid(lg, x̄, J) + @test cg[1,1] == [0.0, 0.0] + @test cg[4,2] == [0.6, 0.2] + @test cg[6,10] == [1., 1.8] + + @test cg[begin, begin] == [0.0, 0.0] + @test cg[end,end] == [2.0, 2.0] + @test cg[begin,end] == [0., 2.] + + @test eachindex(cg) == CartesianIndices((11,11)) + + @testset "cartesian indexing" begin + cases = [ + (1,1) , + (3,5) , + (10,6), + (1,1) , + (3,2) , + ] + + @testset "i = $is" for (lg, is) ∈ cases + @test cg[CartesianIndex(is...)] == cg[is...] + end + end + + @testset "eachindex" begin + @test eachindex(cg) == CartesianIndices((11,11)) + end + + @testset "firstindex" begin + @test firstindex(cg, 1) == 1 + @test firstindex(cg, 2) == 1 + end + + @testset "lastindex" begin + @test lastindex(cg, 1) == 11 + @test lastindex(cg, 2) == 11 + end + end + # TODO: Test with different types of logical grids + + @testset "Iterator interface" begin + # @test eltype(EquidistantGrid(0:10)) == Int + # @test eltype(EquidistantGrid(0:2:10)) == Int + # @test eltype(EquidistantGrid(0:0.1:10)) == Float64 + + # @test size(EquidistantGrid(0:10)) == (11,) + # @test size(EquidistantGrid(0:0.1:10)) == (101,) + + # @test collect(EquidistantGrid(0:0.1:0.5)) == [0.0, 0.1, 0.2, 0.3, 0.4, 0.5] + + # @test Base.IteratorSize(EquidistantGrid{Float64, StepRange{Float64}}) == Base.HasShape{1}() + end + + @testset "Base" begin + # @test ndims(EquidistantGrid(0:10)) == 1 + end + + @testset "boundary_identifiers" begin + # g = EquidistantGrid(0:0.1:10) + # @test boundary_identifiers(g) == (Lower(), Upper()) + # @inferred boundary_identifiers(g) + end + + @testset "boundary_grid" begin + # g = EquidistantGrid(0:0.1:1) + # @test boundary_grid(g, Lower()) == ZeroDimGrid(0.0) + # @test boundary_grid(g, Upper()) == ZeroDimGrid(1.0) + end + + @testset "refine" begin + # g = EquidistantGrid(0:0.1:1) + # @test refine(g, 1) == g + # @test refine(g, 2) == EquidistantGrid(0:0.05:1) + # @test refine(g, 3) == EquidistantGrid(0:(0.1/3):1) + end + + @testset "coarsen" begin + # g = EquidistantGrid(0:1:10) + # @test coarsen(g, 1) == g + # @test coarsen(g, 2) == EquidistantGrid(0:2:10) + + # g = EquidistantGrid(0:0.1:1) + # @test coarsen(g, 1) == g + # @test coarsen(g, 2) == EquidistantGrid(0:0.2:1) + + # g = EquidistantGrid(0:10) + # @test coarsen(g, 1) == EquidistantGrid(0:1:10) + # @test coarsen(g, 2) == EquidistantGrid(0:2:10) + + # @test_throws DomainError(3, "Size minus 1 must be divisible by the ratio.") coarsen(g, 3) + end +end