comparison src/Grids/manifolds.jl @ 1954:b0915f43b122 feature/sbp_operators/laplace_curvilinear

Merge feature/grids/geometry_functions
author Jonatan Werpers <jonatan@werpers.com>
date Sat, 08 Feb 2025 09:38:58 +0100
parents dd77b45ee1ac
children 3fb5b03162ee
comparison
equal deleted inserted replaced
1953:835b1dcee38e 1954:b0915f43b122
1 """
2 ParameterSpace{D}
3
4 A space of parameters of dimension `D`. Used with `Chart` to indicate which
5 parameters are valid for that chart.
6
7 Common parameter spaces are created using the functions unit sized spaces
8 * `unitinterval`
9 * `unitrectangle`
10 * `unitbox`
11 * `unittriangle`
12 * `unittetrahedron`
13 * `unithyperbox`
14 * `unitsimplex`
15
16 See also: [`Interval`](@ref), [`Rectangle`](@ref), [`Box`](@ref),
17 [`Triangle`](@ref), [`Tetrahedron`](@ref), [`HyperBox`](@ref),
18 [`Simplex`](@ref),
19 """
20 abstract type ParameterSpace{D} end
21 Base.ndims(::ParameterSpace{D}) where D = D
22
23 struct Interval{T} <: ParameterSpace{1}
24 a::T
25 b::T
26
27 function Interval(a,b)
28 a, b = promote(a, b)
29 new{typeof(a)}(a,b)
30 end
31 end
32
33 limits(i::Interval) = (i.a, i.b)
34
35 unitinterval(T=Float64) = Interval(zero(T), one(T))
36
37
38 struct HyperBox{T,D} <: ParameterSpace{D}
39 a::SVector{D,T}
40 b::SVector{D,T}
41 end
42
43 function HyperBox(a,b)
44 ET = promote_type(eltype(a),eltype(b))
45 T = SVector{length(a),ET}
46 HyperBox(convert(T,a), convert(T,b))
47 end
48
49 Rectangle{T} = HyperBox{T,2}
50 Box{T} = HyperBox{T,3}
51
52 limits(box::HyperBox, d) = (box.a[d], box.b[d])
53 limits(box::HyperBox) = (box.a, box.b)
54
55 unitsquare(T=Float64) = unithyperbox(T,2)
56 unitcube(T=Float64) = unithyperbox(T,3)
57 unithyperbox(T, D) = HyperBox((@SVector zeros(T,D)), (@SVector ones(T,D)))
58 unithyperbox(D) = unithyperbox(Float64,D)
59
60
61 struct Simplex{T,D,NV} <: ParameterSpace{D}
62 verticies::NTuple{NV,SVector{D,T}}
63 end
64
65 function Simplex(verticies::Vararg{AbstractArray})
66 ET = mapreduce(eltype,promote_type,verticies)
67 T = SVector{length(verticies[1]),ET}
68
69 return Simplex(Tuple(convert(T,v) for v ∈ verticies))
70 end
71
72 verticies(s::Simplex) = s.verticies
73
74 Triangle{T} = Simplex{T,2}
75 Tetrahedron{T} = Simplex{T,3}
76
77 unittriangle(T=Float64) = unitsimplex(T,2)
78 unittetrahedron(T=Float64) = unitsimplex(T,3)
79 function unitsimplex(T,D)
80 z = @SVector zeros(T,D)
81 unitelement = one(eltype(z))
82 verticies = ntuple(i->setindex(z, unitelement, i), D)
83 return Simplex((z,verticies...))
84 end
85 unitsimplex(D) = unitsimplex(Float64, D)
86
87 """ 1 """
88 Chart{D} 2 Chart{D}
89 3
90 A parametrized description of a manifold or part of a manifold. 4 A parametrized description of a manifold or part of a manifold.
91 """ 5 """
117 which will both allow calling `jacobian(c,ξ)`. 31 which will both allow calling `jacobian(c,ξ)`.
118 """ 32 """
119 jacobian(c::Chart, ξ) = jacobian(c.mapping, ξ) 33 jacobian(c::Chart, ξ) = jacobian(c.mapping, ξ)
120 # TBD: Can we register a error hint for when jacobian is called with a function that doesn't have a registered jacobian? 34 # TBD: Can we register a error hint for when jacobian is called with a function that doesn't have a registered jacobian?
121 35
36 boundary_identifiers(c::Chart) = boundary_identifiers(parameterspace(c))
122 37
123 # TBD: Should Charts, parameterspaces have boundary names?
124 38
125 """ 39 """
126 Atlas 40 Atlas
127 41
128 A collection of charts and their connections. 42 A collection of charts and their connections.
129 Should implement methods for `charts` and 43 Should implement methods for `charts` and `connections`.
130 """ 44 """
131 abstract type Atlas end 45 abstract type Atlas end
132 46
133 """ 47 """
134 charts(::Atlas) 48 charts(::Atlas)
136 The colloction of charts in the atlas. 50 The colloction of charts in the atlas.
137 """ 51 """
138 function charts end 52 function charts end
139 53
140 """ 54 """
141 connections 55 connections(::Atlas)
142 56
143 TBD: What exactly should this return? 57 Collection of pairs of multiblock boundary identifiers.
58 """
59 function connections end
60
144 61
145 """ 62 """
63 CartesianAtlas{D,C<:Chart,AT<:AbstractArray{C,D}} <: Atlas
146 64
147 struct CartesianAtlas <: Atlas 65 An atlas where the charts are arranged and connected like an array.
148 charts::Matrix{Chart} 66 """
67 struct CartesianAtlas{D,C<:Chart,AT<:AbstractArray{C,D}} <: Atlas
68 charts::AT
149 end 69 end
150 70
151 charts(a::CartesianAtlas) = a.charts 71 charts(a::CartesianAtlas) = a.charts
152 connections(a::CartesianAtlas) = nothing
153 72
154 struct UnstructuredAtlas <: Atlas 73 function connections(a::CartesianAtlas)
155 charts::Vector{Chart} 74 c = Tuple{MultiBlockBoundary, MultiBlockBoundary}[]
156 connections 75
76 for d ∈ 1:ndims(charts(a))
77 Is = eachslice(CartesianIndices(charts(a)); dims=d)
78 for i ∈ 1:length(Is)-1 # For each interface between slices
79 for jk ∈ eachindex(Is[i]) # For each block in slice
80 Iᵢⱼₖ = Tuple(Is[i][jk])
81 Iᵢ₊₁ⱼₖ = Tuple(Is[i+1][jk])
82 push!(c,
83 (
84 MultiBlockBoundary{Iᵢⱼₖ, CartesianBoundary{d,UpperBoundary}}(),
85 MultiBlockBoundary{Iᵢ₊₁ⱼₖ, CartesianBoundary{d,LowerBoundary}}(),
86 )
87 )
88 end
89 end
90 end
91
92 return c
93 end
94
95 """
96 boundary_identifiers(a::CartesianAtlas)
97
98 All non-connected boundaries of the charts of `a`.
99 """
100 function boundary_identifiers(a::CartesianAtlas)
101 bs = MultiBlockBoundary[]
102
103 for d ∈ 1:ndims(charts(a))
104 Is = eachslice(CartesianIndices(charts(a)); dims=d)
105
106 for (i,b) ∈ ((1,LowerBoundary),(length(Is),UpperBoundary)) # For first and last slice
107 for jk ∈ eachindex(Is[i]) # For each block in slice
108 Iᵢⱼₖ = Tuple(Is[i][jk])
109 push!(bs,
110 MultiBlockBoundary{Iᵢⱼₖ, CartesianBoundary{d,b}}(),
111 )
112 end
113 end
114 end
115
116 return bs
117 end
118
119
120 """
121 UnstructuredAtlas{C<:Chart, CN<:Tuple{MultiBlockBoundary,MultiBlockBoundary}, ...} <: Atlas
122
123 An atlas with connections determined by a vector `MultiBlockBoundary` pairs.
124 """
125 struct UnstructuredAtlas{C<:Chart, CN<:Tuple{MultiBlockBoundary,MultiBlockBoundary}, CV<:AbstractVector{C}, CNV<:AbstractVector{CN}} <: Atlas
126 charts::CV
127 connections::CNV
157 end 128 end
158 129
159 charts(a::UnstructuredAtlas) = a.charts 130 charts(a::UnstructuredAtlas) = a.charts
160 connections(a::UnstructuredAtlas) = nothing 131 connections(a::UnstructuredAtlas) = a.connections
161 132
133 """
134 boundary_identifiers(a::UnstructuredAtlas)
162 135
163 ### 136 All non-connected boundaries of the charts of `a`.
164 # Geometry 137 """
165 ### 138 function boundary_identifiers(a::UnstructuredAtlas)
139 bs = MultiBlockBoundary[]
166 140
167 abstract type Curve end 141 for (i,c) ∈ enumerate(charts(a))
168 abstract type Surface end 142 for b ∈ boundary_identifiers(c)
143 mbb = MultiBlockBoundary{i,typeof(b)}()
169 144
145 if !any(cn->mbb∈cn, connections(a))
146 push!(bs, mbb)
147 end
148 end
149 end
170 150
171 struct Line{PT} <: Curve 151 return bs
172 p::PT
173 tangent::PT
174 end 152 end
175
176 (c::Line)(s) = c.p + s*c.tangent
177
178
179 struct LineSegment{PT} <: Curve
180 a::PT
181 b::PT
182 end
183
184 (c::LineSegment)(s) = (1-s)*c.a + s*c.b
185
186
187 function linesegments(ps...)
188 return [LineSegment(ps[i], ps[i+1]) for i ∈ 1:length(ps)-1]
189 end
190
191
192 function polygon_edges(ps...)
193 n = length(ps)
194 return [LineSegment(ps[i], ps[mod1(i+1,n)]) for i ∈ eachindex(Ps)]
195 end
196
197 struct Circle{T,PT} <: Curve
198 c::PT
199 r::T
200 end
201
202 (c::Circle)(θ) = c.c + r*@SVector[cos(Θ), sin(Θ)]
203
204 struct TransfiniteInterpolationSurface{T1,T2,T3,T4} <: Surface
205 c₁::T1
206 c₂::T2
207 c₃::T3
208 c₄::T4
209 end
210
211 function (s::TransfiniteInterpolationSurface)(u,v)
212 c₁, c₂, c₃, c₄ = s.c₁, s.c₂, s.c₃, s.c₄
213 P₀₀ = c₁(0)
214 P₁₀ = c₂(0)
215 P₁₁ = c₃(0)
216 P₀₁ = c₄(0)
217 return (1-v)*c₁(u) + u*c₂(v) + v*c₃(1-u) + (1-u)*c₄(1-v) - (
218 (1-u)*(1-v)*P₀₀ + u*(1-v)*P₁₀ + u*v*P₁₁ + (1-u)*v*P₀₁
219 )
220 end
221
222 function (s::TransfiniteInterpolationSurface)(ξ̄::AbstractArray)
223 s(ξ̄...)
224 end
225
226 # TODO: Implement jacobian() for the different mapping helpers
227