Mercurial > repos > public > sbplib_julia
comparison src/Grids/equidistant_grid.jl @ 1116:c2d7e940639e feature/grids
Rename AbstractGrid to Grid and clean up Grids module
| author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
|---|---|
| date | Fri, 15 Jul 2022 09:54:15 +0200 |
| parents | src/Grids/EquidistantGrid.jl@6530fceef37c |
| children | 832ac87a54a3 |
comparison
equal
deleted
inserted
replaced
| 1115:6530fceef37c | 1116:c2d7e940639e |
|---|---|
| 1 | |
| 2 """ | |
| 3 EquidistantGrid{Dim,T<:Real} <: Grid | |
| 4 | |
| 5 `Dim`-dimensional equidistant grid with coordinates of type `T`. | |
| 6 """ | |
| 7 struct EquidistantGrid{Dim,T<:Real} <: Grid | |
| 8 size::NTuple{Dim, Int} | |
| 9 limit_lower::NTuple{Dim, T} | |
| 10 limit_upper::NTuple{Dim, T} | |
| 11 | |
| 12 function EquidistantGrid{Dim,T}(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T}) where {Dim,T} | |
| 13 if any(size .<= 0) | |
| 14 throw(DomainError("all components of size must be postive")) | |
| 15 end | |
| 16 if any(limit_upper.-limit_lower .<= 0) | |
| 17 throw(DomainError("all side lengths must be postive")) | |
| 18 end | |
| 19 return new{Dim,T}(size, limit_lower, limit_upper) | |
| 20 end | |
| 21 end | |
| 22 | |
| 23 | |
| 24 """ | |
| 25 EquidistantGrid(size, limit_lower, limit_upper) | |
| 26 | |
| 27 Construct an equidistant grid with corners at the coordinates `limit_lower` and | |
| 28 `limit_upper`. | |
| 29 | |
| 30 The length of the domain sides are given by the components of | |
| 31 `limit_upper-limit_lower`. E.g for a 2D grid with `limit_lower=(-1,0)` and `limit_upper=(1,2)` the domain is defined | |
| 32 as `(-1,1)x(0,2)`. The side lengths of the grid are not allowed to be negative. | |
| 33 | |
| 34 The number of equidistantly spaced points in each coordinate direction are given | |
| 35 by the tuple `size`. | |
| 36 """ | |
| 37 function EquidistantGrid(size, limit_lower, limit_upper) | |
| 38 return EquidistantGrid{length(size), eltype(limit_lower)}(size, limit_lower, limit_upper) | |
| 39 end | |
| 40 | |
| 41 | |
| 42 """ | |
| 43 EquidistantGrid{T}() | |
| 44 | |
| 45 Constructs a 0-dimensional grid. | |
| 46 """ | |
| 47 EquidistantGrid{T}() where T = EquidistantGrid{0,T}((),(),()) # Convenience constructor for 0-dim grid | |
| 48 | |
| 49 | |
| 50 """ | |
| 51 EquidistantGrid(size::Int, limit_lower::T, limit_upper::T) | |
| 52 | |
| 53 Convenience constructor for 1D grids. | |
| 54 """ | |
| 55 function EquidistantGrid(size::Int, limit_lower::T, limit_upper::T) where T | |
| 56 return EquidistantGrid((size,),(limit_lower,),(limit_upper,)) | |
| 57 end | |
| 58 | |
| 59 Base.eltype(grid::EquidistantGrid{Dim,T}) where {Dim,T} = T | |
| 60 | |
| 61 Base.eachindex(grid::EquidistantGrid) = CartesianIndices(grid.size) | |
| 62 | |
| 63 Base.size(g::EquidistantGrid) = g.size | |
| 64 | |
| 65 | |
| 66 """ | |
| 67 dim(grid::EquidistantGrid) | |
| 68 | |
| 69 The dimension of the grid. | |
| 70 """ | |
| 71 dim(::EquidistantGrid{Dim}) where Dim = Dim | |
| 72 | |
| 73 | |
| 74 """ | |
| 75 spacing(grid::EquidistantGrid) | |
| 76 | |
| 77 The spacing between grid points. | |
| 78 """ | |
| 79 spacing(grid::EquidistantGrid) = (grid.limit_upper.-grid.limit_lower)./(grid.size.-1) | |
| 80 | |
| 81 | |
| 82 """ | |
| 83 inverse_spacing(grid::EquidistantGrid) | |
| 84 | |
| 85 The reciprocal of the spacing between grid points. | |
| 86 """ | |
| 87 inverse_spacing(grid::EquidistantGrid) = 1 ./ spacing(grid) | |
| 88 | |
| 89 | |
| 90 """ | |
| 91 points(grid::EquidistantGrid) | |
| 92 | |
| 93 The point of the grid as an array of tuples with the same dimension as the grid. | |
| 94 The points are stored as [(x1,y1), (x1,y2), … (x1,yn); | |
| 95 (x2,y1), (x2,y2), … (x2,yn); | |
| 96 ⋮ ⋮ ⋮ | |
| 97 (xm,y1), (xm,y2), … (xm,yn)] | |
| 98 """ | |
| 99 function points(grid::EquidistantGrid) | |
| 100 indices = Tuple.(CartesianIndices(grid.size)) | |
| 101 h = spacing(grid) | |
| 102 return broadcast(I -> grid.limit_lower .+ (I.-1).*h, indices) | |
| 103 end | |
| 104 | |
| 105 | |
| 106 """ | |
| 107 restrict(::EquidistantGrid, dim) | |
| 108 | |
| 109 Pick out given dimensions from the grid and return a grid for them. | |
| 110 """ | |
| 111 function restrict(grid::EquidistantGrid, dim) | |
| 112 size = grid.size[dim] | |
| 113 limit_lower = grid.limit_lower[dim] | |
| 114 limit_upper = grid.limit_upper[dim] | |
| 115 | |
| 116 return EquidistantGrid(size, limit_lower, limit_upper) | |
| 117 end | |
| 118 | |
| 119 | |
| 120 """ | |
| 121 orthogonal_dims(grid::EquidistantGrid,dim) | |
| 122 | |
| 123 Returns the dimensions of grid orthogonal to that of dim. | |
| 124 """ | |
| 125 function orthogonal_dims(grid::EquidistantGrid, dim) | |
| 126 orth_dims = filter(i -> i != dim, dims(grid)) | |
| 127 if orth_dims == dims(grid) | |
| 128 throw(DomainError(string("dimension ",string(dim)," not matching grid"))) | |
| 129 end | |
| 130 return orth_dims | |
| 131 end | |
| 132 | |
| 133 | |
| 134 """ | |
| 135 boundary_identifiers(::EquidistantGrid) | |
| 136 | |
| 137 Returns a tuple containing the boundary identifiers for the grid, stored as | |
| 138 (CartesianBoundary(1,Lower), | |
| 139 CartesianBoundary(1,Upper), | |
| 140 CartesianBoundary(2,Lower), | |
| 141 ...) | |
| 142 """ | |
| 143 boundary_identifiers(g::EquidistantGrid) = (((ntuple(i->(CartesianBoundary{i,Lower}(),CartesianBoundary{i,Upper}()),dim(g)))...)...,) | |
| 144 | |
| 145 | |
| 146 """ | |
| 147 boundary_grid(grid::EquidistantGrid, id::CartesianBoundary) | |
| 148 | |
| 149 Creates the lower-dimensional restriciton of `grid` spanned by the dimensions | |
| 150 orthogonal to the boundary specified by `id`. The boundary grid of a 1-dimensional | |
| 151 grid is a zero-dimensional grid. | |
| 152 """ | |
| 153 function boundary_grid(grid::EquidistantGrid, id::CartesianBoundary) | |
| 154 orth_dims = orthogonal_dims(grid, dim(id)) | |
| 155 return restrict(grid, orth_dims) | |
| 156 end | |
| 157 boundary_grid(::EquidistantGrid{1,T},::CartesianBoundary{1}) where T = EquidistantGrid{T}() | |
| 158 | |
| 159 | |
| 160 """ | |
| 161 boundary_size(grid::EquidistantGrid, id::CartesianBoundary) | |
| 162 | |
| 163 Returns the size of the boundary of `grid` specified by `id`. | |
| 164 """ | |
| 165 function boundary_size(grid::EquidistantGrid, id::CartesianBoundary) | |
| 166 orth_dims = orthogonal_dims(grid, dim(id)) | |
| 167 return grid.size[orth_dims] | |
| 168 end | |
| 169 boundary_size(::EquidistantGrid{1,T},::CartesianBoundary{1}) where T = () | |
| 170 | |
| 171 | |
| 172 """ | |
| 173 refine(grid::EquidistantGrid, r::Int) | |
| 174 | |
| 175 Refines `grid` by a factor `r`. The factor is applied to the number of | |
| 176 intervals which is 1 less than the size of the grid. | |
| 177 | |
| 178 See also: [`coarsen`](@ref) | |
| 179 """ | |
| 180 function refine(grid::EquidistantGrid, r::Int) | |
| 181 sz = size(grid) | |
| 182 new_sz = (sz .- 1).*r .+ 1 | |
| 183 return EquidistantGrid{dim(grid), eltype(grid)}(new_sz, grid.limit_lower, grid.limit_upper) | |
| 184 end | |
| 185 | |
| 186 | |
| 187 """ | |
| 188 coarsen(grid::EquidistantGrid, r::Int) | |
| 189 | |
| 190 Coarsens `grid` by a factor `r`. The factor is applied to the number of | |
| 191 intervals which is 1 less than the size of the grid. If the number of | |
| 192 intervals are not divisible by `r` an error is raised. | |
| 193 | |
| 194 See also: [`refine`](@ref) | |
| 195 """ | |
| 196 function coarsen(grid::EquidistantGrid, r::Int) | |
| 197 sz = size(grid) | |
| 198 | |
| 199 if !all(n -> (n % r == 0), sz.-1) | |
| 200 throw(DomainError(r, "Size minus 1 must be divisible by the ratio.")) | |
| 201 end | |
| 202 | |
| 203 new_sz = (sz .- 1).÷r .+ 1 | |
| 204 | |
| 205 return EquidistantGrid{dim(grid), eltype(grid)}(new_sz, grid.limit_lower, grid.limit_upper) | |
| 206 end |
