Mercurial > repos > public > sbplib_julia
view src/Grids/EquidistantGrid.jl @ 907:e81b89ae17c4 feature/equidistant_grid/refine
Add coarsen()
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Tue, 15 Feb 2022 11:36:12 +0100 |
parents | dd2ab001a7b6 |
children | bc71dd5b8311 |
line wrap: on
line source
export EquidistantGrid export spacing export inverse_spacing export restrict export boundary_identifiers export boundary_grid export refine export coarsen """ EquidistantGrid(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T}) EquidistantGrid{T}() `EquidistantGrid` is a grid with equidistant grid spacing per coordinat direction. `EquidistantGrid(size, limit_lower, limit_upper)` construct the grid with the domain defined by the two points P1, and P2 given by `limit_lower` and `limit_upper`. The length of the domain sides are given by the components of (P2-P1). E.g for a 2D grid with P1=(-1,0) and P2=(1,2) the domain is defined as (-1,1)x(0,2). The side lengths of the grid are not allowed to be negative. The number of equidistantly spaced points in each coordinate direction are given by `size`. `EquidistantGrid{T}()` constructs a 0-dimensional grid. """ struct EquidistantGrid{Dim,T<:Real} <: AbstractGrid size::NTuple{Dim, Int} limit_lower::NTuple{Dim, T} limit_upper::NTuple{Dim, T} # General constructor function EquidistantGrid{Dim,T}(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T}) where {Dim,T} if any(size .<= 0) throw(DomainError("all components of size must be postive")) end if any(limit_upper.-limit_lower .<= 0) throw(DomainError("all side lengths must be postive")) end return new{Dim,T}(size, limit_lower, limit_upper) end end function EquidistantGrid(size, limit_lower, limit_upper) return EquidistantGrid{length(size), eltype(limit_lower)}(size, limit_lower, limit_upper) end EquidistantGrid{T}() where T = EquidistantGrid{0,T}((),(),()) # Convenience constructor for 0-dim grid """ EquidistantGrid(size::Int, limit_lower::T, limit_upper::T) Convenience constructor for 1D grids. """ function EquidistantGrid(size::Int, limit_lower::T, limit_upper::T) where T return EquidistantGrid((size,),(limit_lower,),(limit_upper,)) end Base.eltype(grid::EquidistantGrid{Dim,T}) where {Dim,T} = T Base.eachindex(grid::EquidistantGrid) = CartesianIndices(grid.size) Base.size(g::EquidistantGrid) = g.size """ dimension(grid::EquidistantGrid) The dimension of the grid. """ dimension(grid::EquidistantGrid{Dim}) where Dim = Dim """ spacing(grid::EquidistantGrid) The spacing between the grid points of the grid. """ spacing(grid::EquidistantGrid) = (grid.limit_upper.-grid.limit_lower)./(grid.size.-1) """ inverse_spacing(grid::EquidistantGrid) The reciprocal of the spacing between the grid points of the grid. """ inverse_spacing(grid::EquidistantGrid) = 1 ./ spacing(grid) """ points(grid::EquidistantGrid) The point of the grid as an array of tuples with the same dimension as the grid. The points are stored as [(x1,y1), (x1,y2), … (x1,yn); (x2,y1), (x2,y2), … (x2,yn); ⋮ ⋮ ⋮ (xm,y1), (xm,y2), … (xm,yn)] """ function points(grid::EquidistantGrid) indices = Tuple.(CartesianIndices(grid.size)) h = spacing(grid) return broadcast(I -> grid.limit_lower .+ (I.-1).*h, indices) end """ restrict(::EquidistantGrid, dim) Pick out given dimensions from the grid and return a grid for them """ function restrict(grid::EquidistantGrid, dim) size = grid.size[dim] limit_lower = grid.limit_lower[dim] limit_upper = grid.limit_upper[dim] return EquidistantGrid(size, limit_lower, limit_upper) end """ boundary_identifiers(::EquidistantGrid) Returns a tuple containing the boundary identifiers for the grid, stored as (CartesianBoundary(1,Lower), CartesianBoundary(1,Upper), CartesianBoundary(2,Lower), ...) """ boundary_identifiers(g::EquidistantGrid) = (((ntuple(i->(CartesianBoundary{i,Lower}(),CartesianBoundary{i,Upper}()),dimension(g)))...)...,) """ boundary_grid(grid::EquidistantGrid,id::CartesianBoundary) boundary_grid(::EquidistantGrid{1},::CartesianBoundary{1}) Creates the lower-dimensional restriciton of `grid` spanned by the dimensions orthogonal to the boundary specified by `id`. The boundary grid of a 1-dimensional grid is a zero-dimensional grid. """ function boundary_grid(grid::EquidistantGrid,id::CartesianBoundary) dims = collect(1:dimension(grid)) orth_dims = dims[dims .!= dim(id)] if orth_dims == dims throw(DomainError("boundary identifier not matching grid")) end return restrict(grid,orth_dims) end boundary_grid(::EquidistantGrid{1,T},::CartesianBoundary{1}) where T = EquidistantGrid{T}() """ refine(grid::EquidistantGrid, r::Int) Refines `grid` by a factor `r`. The factor is applied to the number of intervals which is 1 less than the size of the grid. """ function refine(grid::EquidistantGrid, r::Int) sz = size(grid) new_sz = (sz .- 1).*r .+ 1 return EquidistantGrid{dimension(grid), eltype(grid)}(new_sz, grid.limit_lower, grid.limit_upper) end function coarsen(grid::EquidistantGrid, r::Int) sz = size(grid) if !all(n -> (n % r == 0), sz.-1) throw(DomainError(r, "Size minus 1 must be divisible by the ratio.")) end new_sz = (sz .- 1).÷r .+ 1 return EquidistantGrid{dimension(grid), eltype(grid)}(new_sz, grid.limit_lower, grid.limit_upper) end