comparison src/Grids/EquidistantGrid.jl @ 911:a378ab959b6f

Merge feature/equidistant_grid/refine
author Jonatan Werpers <jonatan@werpers.com>
date Tue, 15 Feb 2022 15:14:28 +0100
parents b900fea1c057
children 9b40aeac4269 5b3d4a8ec3ab
comparison
equal deleted inserted replaced
864:9a2776352c2a 911:a378ab959b6f
1 export EquidistantGrid
2 export spacing
3 export inverse_spacing
4 export restrict
5 export boundary_identifiers
6 export boundary_grid
7 export refine
8 export coarsen
9
1 """ 10 """
2 EquidistantGrid(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T}) 11 EquidistantGrid{Dim,T<:Real} <: AbstractGrid
3 EquidistantGrid{T}()
4 12
5 `EquidistantGrid` is a grid with equidistant grid spacing per coordinat direction. 13 `Dim`-dimensional equidistant grid with coordinates of type `T`.
6
7 `EquidistantGrid(size, limit_lower, limit_upper)` construct the grid with the
8 domain defined by the two points P1, and P2 given by `limit_lower` and
9 `limit_upper`. The length of the domain sides are given by the components of
10 (P2-P1). E.g for a 2D grid with P1=(-1,0) and P2=(1,2) the domain is defined
11 as (-1,1)x(0,2). The side lengths of the grid are not allowed to be negative.
12 The number of equidistantly spaced points in each coordinate direction are given
13 by `size`.
14
15 `EquidistantGrid{T}()` constructs a 0-dimensional grid.
16
17 """ 14 """
18 struct EquidistantGrid{Dim,T<:Real} <: AbstractGrid 15 struct EquidistantGrid{Dim,T<:Real} <: AbstractGrid
19 size::NTuple{Dim, Int} 16 size::NTuple{Dim, Int}
20 limit_lower::NTuple{Dim, T} 17 limit_lower::NTuple{Dim, T}
21 limit_upper::NTuple{Dim, T} 18 limit_upper::NTuple{Dim, T}
22 19
23 # General constructor 20 function EquidistantGrid{Dim,T}(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T}) where {Dim,T}
24 function EquidistantGrid(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T}) where Dim where T
25 if any(size .<= 0) 21 if any(size .<= 0)
26 throw(DomainError("all components of size must be postive")) 22 throw(DomainError("all components of size must be postive"))
27 end 23 end
28 if any(limit_upper.-limit_lower .<= 0) 24 if any(limit_upper.-limit_lower .<= 0)
29 throw(DomainError("all side lengths must be postive")) 25 throw(DomainError("all side lengths must be postive"))
30 end 26 end
31 return new{Dim,T}(size, limit_lower, limit_upper) 27 return new{Dim,T}(size, limit_lower, limit_upper)
32 end 28 end
29 end
33 30
34 # Specialized constructor for 0-dimensional grid 31 """
35 EquidistantGrid{T}() where T = new{0,T}((),(),()) 32 EquidistantGrid(size, limit_lower, limit_upper)
33
34 Construct an equidistant grid with corners at the coordinates `limit_lower` and
35 `limit_upper`.
36
37 The length of the domain sides are given by the components of
38 `limit_upper-limit_lower`. E.g for a 2D grid with `limit_lower=(-1,0)` and `limit_upper=(1,2)` the domain is defined
39 as `(-1,1)x(0,2)`. The side lengths of the grid are not allowed to be negative.
40
41 The number of equidistantly spaced points in each coordinate direction are given
42 by the tuple `size`.
43 """
44 function EquidistantGrid(size, limit_lower, limit_upper)
45 return EquidistantGrid{length(size), eltype(limit_lower)}(size, limit_lower, limit_upper)
36 end 46 end
37 export EquidistantGrid
38 47
48 """
49 EquidistantGrid{T}()
50
51 Constructs a 0-dimensional grid.
52 """
53 EquidistantGrid{T}() where T = EquidistantGrid{0,T}((),(),()) # Convenience constructor for 0-dim grid
39 54
40 """ 55 """
41 EquidistantGrid(size::Int, limit_lower::T, limit_upper::T) 56 EquidistantGrid(size::Int, limit_lower::T, limit_upper::T)
42 57
43 Convenience constructor for 1D grids. 58 Convenience constructor for 1D grids.
60 dimension(grid::EquidistantGrid{Dim}) where Dim = Dim 75 dimension(grid::EquidistantGrid{Dim}) where Dim = Dim
61 76
62 """ 77 """
63 spacing(grid::EquidistantGrid) 78 spacing(grid::EquidistantGrid)
64 79
65 The spacing between the grid points of the grid. 80 The spacing between grid points.
66 """ 81 """
67 spacing(grid::EquidistantGrid) = (grid.limit_upper.-grid.limit_lower)./(grid.size.-1) 82 spacing(grid::EquidistantGrid) = (grid.limit_upper.-grid.limit_lower)./(grid.size.-1)
68 export spacing
69 83
70 """ 84 """
71 inverse_spacing(grid::EquidistantGrid) 85 inverse_spacing(grid::EquidistantGrid)
72 86
73 The reciprocal of the spacing between the grid points of the grid. 87 The reciprocal of the spacing between grid points.
74 """ 88 """
75 inverse_spacing(grid::EquidistantGrid) = 1 ./ spacing(grid) 89 inverse_spacing(grid::EquidistantGrid) = 1 ./ spacing(grid)
76 export inverse_spacing
77 90
78 """ 91 """
79 points(grid::EquidistantGrid) 92 points(grid::EquidistantGrid)
80 93
81 The point of the grid as an array of tuples with the same dimension as the grid. 94 The point of the grid as an array of tuples with the same dimension as the grid.
91 end 104 end
92 105
93 """ 106 """
94 restrict(::EquidistantGrid, dim) 107 restrict(::EquidistantGrid, dim)
95 108
96 Pick out given dimensions from the grid and return a grid for them 109 Pick out given dimensions from the grid and return a grid for them.
97 """ 110 """
98 function restrict(grid::EquidistantGrid, dim) 111 function restrict(grid::EquidistantGrid, dim)
99 size = grid.size[dim] 112 size = grid.size[dim]
100 limit_lower = grid.limit_lower[dim] 113 limit_lower = grid.limit_lower[dim]
101 limit_upper = grid.limit_upper[dim] 114 limit_upper = grid.limit_upper[dim]
102 115
103 return EquidistantGrid(size, limit_lower, limit_upper) 116 return EquidistantGrid(size, limit_lower, limit_upper)
104 end 117 end
105 export restrict
106 118
107 """ 119 """
108 boundary_identifiers(::EquidistantGrid) 120 boundary_identifiers(::EquidistantGrid)
109 121
110 Returns a tuple containing the boundary identifiers for the grid, stored as 122 Returns a tuple containing the boundary identifiers for the grid, stored as
112 CartesianBoundary(1,Upper), 124 CartesianBoundary(1,Upper),
113 CartesianBoundary(2,Lower), 125 CartesianBoundary(2,Lower),
114 ...) 126 ...)
115 """ 127 """
116 boundary_identifiers(g::EquidistantGrid) = (((ntuple(i->(CartesianBoundary{i,Lower}(),CartesianBoundary{i,Upper}()),dimension(g)))...)...,) 128 boundary_identifiers(g::EquidistantGrid) = (((ntuple(i->(CartesianBoundary{i,Lower}(),CartesianBoundary{i,Upper}()),dimension(g)))...)...,)
117 export boundary_identifiers
118 129
119 130
120 """ 131 """
121 boundary_grid(grid::EquidistantGrid,id::CartesianBoundary) 132 boundary_grid(grid::EquidistantGrid,id::CartesianBoundary)
122 boundary_grid(::EquidistantGrid{1},::CartesianBoundary{1}) 133 boundary_grid(::EquidistantGrid{1},::CartesianBoundary{1})
131 if orth_dims == dims 142 if orth_dims == dims
132 throw(DomainError("boundary identifier not matching grid")) 143 throw(DomainError("boundary identifier not matching grid"))
133 end 144 end
134 return restrict(grid,orth_dims) 145 return restrict(grid,orth_dims)
135 end 146 end
136 export boundary_grid
137 boundary_grid(::EquidistantGrid{1,T},::CartesianBoundary{1}) where T = EquidistantGrid{T}() 147 boundary_grid(::EquidistantGrid{1,T},::CartesianBoundary{1}) where T = EquidistantGrid{T}()
148
149
150 """
151 refine(grid::EquidistantGrid, r::Int)
152
153 Refines `grid` by a factor `r`. The factor is applied to the number of
154 intervals which is 1 less than the size of the grid.
155
156 See also: [`coarsen`](@ref)
157 """
158 function refine(grid::EquidistantGrid, r::Int)
159 sz = size(grid)
160 new_sz = (sz .- 1).*r .+ 1
161 return EquidistantGrid{dimension(grid), eltype(grid)}(new_sz, grid.limit_lower, grid.limit_upper)
162 end
163
164 """
165 coarsen(grid::EquidistantGrid, r::Int)
166
167 Coarsens `grid` by a factor `r`. The factor is applied to the number of
168 intervals which is 1 less than the size of the grid. If the number of
169 intervals are not divisible by `r` an error is raised.
170
171 See also: [`refine`](@ref)
172 """
173 function coarsen(grid::EquidistantGrid, r::Int)
174 sz = size(grid)
175
176 if !all(n -> (n % r == 0), sz.-1)
177 throw(DomainError(r, "Size minus 1 must be divisible by the ratio."))
178 end
179
180 new_sz = (sz .- 1).÷r .+ 1
181
182 return EquidistantGrid{dimension(grid), eltype(grid)}(new_sz, grid.limit_lower, grid.limit_upper)
183 end