comparison src/Grids/grid.jl @ 2057:8a2a0d678d6f feature/lazy_tensors/pretty_printing

Merge default
author Jonatan Werpers <jonatan@werpers.com>
date Tue, 10 Feb 2026 22:41:19 +0100
parents 491887181b8c
children
comparison
equal deleted inserted replaced
1110:c0bff9f6e0fb 2057:8a2a0d678d6f
1 """
2 Grid{T,D}
3
4 A grid with coordinates of type `T`, e.g. `SVector{3,Float64}`, and dimension
5 `D`. The grid can be embedded in a higher dimension in which case the number
6 of indices and the number of components of the coordinate vectors will be
7 different.
8
9 All grids are expected to behave as a grid function for the coordinates.
10
11 `Grids` is top level abstract type for grids. A grid should implement Julia's interfaces for
12 indexing and iteration.
13
14 ## Note
15
16 Importantly a grid does not have to be an `AbstractArray`. The reason is to
17 allow flexible handling of special types of grids like multi-block grids, or
18 grids with special indexing.
19 """
20 abstract type Grid{T,D} end
21
22 Base.ndims(::Grid{T,D}) where {T,D} = D
23 Base.eltype(::Type{<:Grid{T}}) where T = T
24
25 Base.getindex(g::Grid, I::CartesianIndex) = g[Tuple(I)...]
26
27 """
28 coordinate_size(g)
29
30 The length of the coordinate vector of `Grid` `g`.
31 """
32 coordinate_size(::Type{<:Grid{T}}) where T = _ncomponents(T)
33 coordinate_size(g::Grid) = coordinate_size(typeof(g)) # TBD: Name of this function?!
34
35 """
36 component_type(gf)
37
38 The type of the components of the elements of `gf`. I.e if `gf` is a vector
39 valued grid function, `component_view(gf)` is the element type of the vectors
40 at each grid point.
41
42 # Examples
43 ```julia-repl
44 julia> component_type([[1,2], [2,3], [3,4]])
45 Int64
46 ```
47 """
48 component_type(T::Type) = eltype(eltype(T))
49 component_type(t) = component_type(typeof(t))
50
51 """
52 componentview(gf, component_index...)
53
54 A view of `gf` with only the components specified by `component_index...`.
55
56 # Examples
57 ```julia-repl
58 julia> componentview([[1,2], [2,3], [3,4]],2)
59 3-element ArrayComponentView{Int64, Vector{Int64}, 1, Vector{Vector{Int64}}, Tuple{Int64}}:
60 2
61 3
62 4
63 ```
64 """
65 componentview(gf, component_index...) = ArrayComponentView(gf, component_index)
66
67 struct ArrayComponentView{CT,T,D,AT <: AbstractArray{T,D}, IT} <: AbstractArray{CT,D}
68 v::AT
69 component_index::IT
70
71 function ArrayComponentView(v, component_index)
72 CT = typeof(first(v)[component_index...])
73 return new{CT, eltype(v), ndims(v), typeof(v), typeof(component_index)}(v,component_index)
74 end
75 end
76
77 _array_type(v::ArrayComponentView) = _array_type(typeof(v))
78 _array_type(::Type{ArrayComponentView{CT,T,D,AT,IT}}) where {CT,T,D,AT,IT} = AT
79
80 Base.size(cv::ArrayComponentView) = size(cv.v)
81 Base.getindex(cv::ArrayComponentView, i::Int) = cv.v[i][cv.component_index...]
82 Base.getindex(cv::ArrayComponentView, I::Vararg{Int}) = cv.v[I...][cv.component_index...]
83 Base.IndexStyle(ACT::Type{<:ArrayComponentView}) = IndexStyle(_array_type(ACT))
84
85 # TODO: Implement `setindex!`?
86 # TODO: Implement a more general ComponentView that can handle non-AbstractArrays.
87
88
89 """
90 min_spacing(g::Grid)
91
92 The smallest distance between any pair of grid points in `g`.
93 """
94 function min_spacing end
95
96 """
97 refine(g::Grid, r)
98
99 The grid where `g` is refined by the factor `r`.
100
101 See also: [`coarsen`](@ref).
102 """
103 function refine end
104
105 """
106 coarsen(g::Grid, r)
107
108 The grid where `g` is coarsened by the factor `r`.
109
110 See also: [`refine`](@ref).
111 """
112 function coarsen end
113
114 """
115 BoundaryIdentifier
116
117 An identifier for a boundary of a grid.
118 """
119 abstract type BoundaryIdentifier end
120
121 """
122 boundary_identifiers(g::Grid)
123
124 Identifiers for all the boundaries of `g`.
125 """
126 function boundary_identifiers end
127
128 """
129 boundary_grid(g::Grid, id::BoundaryIdentifier)
130
131 The grid for the boundary specified by `id`.
132 """
133 function boundary_grid end
134 # TBD: Can we implement a version here that accepts multiple ids and grouped boundaries? Maybe we need multiblock stuff?
135
136 """
137 boundary_indices(g::Grid, id::BoundaryIdentifier)
138
139 A collection of indices corresponding to the boundary with given id. For grids
140 with Cartesian indexing these collections will be tuples with elements of type
141 ``Union{Int,Colon}``.
142
143 When implementing this method it is expected that the returned collection can
144 be used to index grid functions to obtain grid functions on the boundary grid.
145 """
146 function boundary_indices end
147
148 """
149 eval_on(g::Grid, f)
150
151 Lazy evaluation of `f` on the grid. `f` can either be on the form `f(x,y,...)`
152 with each coordinate as an argument, or on the form `f(x̄)` taking a
153 coordinate vector.
154
155 For concrete array grid functions `map(f,g)` can be used instead.
156 """
157 eval_on(g::Grid, f) = eval_on(g, f, Base.IteratorSize(g))
158 function eval_on(g::Grid, f, ::Base.HasShape)
159 if hasmethod(f, (Any,))
160 return LazyTensors.LazyFunctionArray((I...)->f(g[I...]), size(g))
161 else
162 # TBD This branch can be removed if we accept the trade off that we define f with the syntax f((x,y)) instead if we don't want to handle the vector in the body of f. (Add an example in the docs)
163 # Also see Notes.md
164 return LazyTensors.LazyFunctionArray((I...)->f(g[I...]...), size(g))
165 end
166 end
167
168 """
169 eval_on(g::Grid, f::Number)
170
171 Lazy evaluation of a scalar `f` on the grid.
172 """
173 eval_on(g::Grid, f::Number) = return LazyTensors.LazyConstantArray(f, size(g))
174
175 _ncomponents(::Type{<:Number}) = 1
176 _ncomponents(T::Type{<:SVector}) = length(T)
177
178