@@ -160,8 +160,141 @@ getindex(Z::Zernike, xy::StaticVector{2}, B::BlockIndex{1}) = Z[RadialCoordinate
160
160
getindex (Z:: Zernike , xy:: StaticVector{2} , B:: Block{1} ) = [Z[xy, B[j]] for j= 1 : Int (B)]
161
161
getindex (Z:: Zernike , xy:: StaticVector{2} , JR:: BlockOneTo ) = mortar ([Z[xy,Block (J)] for J = 1 : Int (JR[end ])])
162
162
163
+ # ##
164
+ # Jacobi matrices
165
+ # ##
166
+
167
+ # Due to excessively long lazy typing, we wrap the bands of the Zernike Jacobi matrix in its own type
168
+ # The bands for X and Y are distinct
169
+ struct ZernikeJacobimatrixBandsX{T} <: AbstractBlockMatrix{T}
170
+ Z:: Zernike{T}
171
+ data:: AbstractBlockMatrix{T}
172
+ ZernikeJacobimatrixBandsX {T} (Z:: Zernike{T} ) where T = new {T} (Z, zernikejacobibandsX (Z))
173
+ end
174
+ struct ZernikeJacobimatrixBandsY{T} <: AbstractBlockMatrix{T}
175
+ Z:: Zernike{T}
176
+ data:: AbstractBlockMatrix{T}
177
+ ZernikeJacobimatrixBandsY {T} (Z:: Zernike{T} ) where T = new {T} (Z, zernikejacobibandsY (Z))
178
+ end
179
+
180
+ size (b:: ZernikeJacobimatrixBandsX ) = size (b. data)
181
+ axes (b:: ZernikeJacobimatrixBandsX ) = axes (b. data)
182
+ size (b:: ZernikeJacobimatrixBandsY ) = size (b. data)
183
+ axes (b:: ZernikeJacobimatrixBandsY ) = axes (b. data)
184
+
185
+ function zernikejacobibandsX (Z:: Zernike )
186
+ α = Z. b # extract second basis parameter
187
+
188
+ k = mortar (Base. OneTo .(oneto (∞))) # k counts the the angular mode (+1)
189
+ n = mortar (Fill .(oneto (∞),oneto (∞))) # n counts the block number which corresponds to the order (+1)
190
+
191
+ # repeatedly used for sorting
192
+ keven = iseven .(k)
193
+ kodd = isodd .(k)
194
+ neven = iseven .(n)
195
+ nodd = isodd .(n)
196
+
197
+ # h1-h5 are helpers for our different sorting scheme
198
+
199
+ # # Compute super diagonal of super diagonal blocks.
200
+ dufirst = neven .* (k .== 2 ) .* n .* (n .+ 2 * α) ./ 2
201
+
202
+ # # Compute even-block entries in super diagonal of super diagonal blocks
203
+ h1 = n .- (n .+ 2 .- k .- keven .* (n .> 2 )) .÷ 2
204
+ dueven = ((nodd .* k) .>= 2 ) .* h1 .* (h1 .+ α)
205
+
206
+ # # Compute odd-block entries in super diagonal of super diagonal blocks
207
+ h2 = (n .- 2 .+ k .+ kodd .* (n .> 2 )) .÷ 2
208
+ duodd = (((neven .* k) .>= 2 ) .- (neven .* (k .== 2 ))) .* h2 .* (h2 .+ α)
209
+
210
+ # # Compute even-block sub diagonal elements of super diagonal blocks
211
+ h3 = n .- (k .+ 1 .+ kodd .+ n) .÷ 2
212
+ dleven = ((k .<= (n .- 2 )) .- ((k .< 2 ) .* nodd)) .* neven .* h3 .* (h3 .+ α)
213
+
214
+ # # Compute odd-block sub diagonal elements of super diagonal blocks
215
+ h4 = n .- (k .+ 1 .+ keven .+ n) .÷ 2
216
+ dlodd = (k .> 1 ) .* (n .> 3 ) .* nodd .* h4 .* (h4 .+ α)
163
217
218
+ # # Compute and add in special case odd-block sub diagonal elements of super diagonal blocks
219
+ h5 = n .- 2 .+ k .+ keven
220
+ dlspecial = nodd .* (k .== 1 ) .* h5 .* (h5 .+ 2 * α) ./ 2
164
221
222
+ # finalize bands with explicit formula
223
+ quotient = 4 .* (n .+ (α- 1 )) .* (n .+ α)
224
+ du = sqrt .( (dufirst .+ dueven .+ duodd ) ./ quotient)
225
+ dl = sqrt .( (dleven .+ dlodd .+ dlspecial) ./ quotient)
226
+
227
+ return BlockHcat (
228
+ BlockBroadcastArray (hcat, du, Zeros ((axes (n,1 ),)), dl),
229
+ Zeros ((axes (n,1 ),Base. OneTo (3 ))),
230
+ Zeros ((axes (n,1 ),Base. OneTo (3 )))
231
+ )
232
+ end
233
+
234
+ function zernikejacobibandsY (Z:: Zernike )
235
+ α = Z. b # extract second basis parameter
236
+
237
+ k = mortar (Base. OneTo .(oneto (∞))) # k counts the the angular mode (+1)
238
+ n = mortar (Fill .(oneto (∞),oneto (∞))) # n counts the block number which corresponds to the order (+1)
239
+
240
+ # repeatedly used for sorting
241
+ keven = iseven .(k)
242
+ kodd = isodd .(k)
243
+ neven = iseven .(n)
244
+ nodd = isodd .(n)
245
+
246
+ # h1-h4 are helpers for our different sorting scheme
247
+
248
+ # first entries for all blocks
249
+ h1 = (n .- nodd)
250
+ l1 = (k .== 1 ) .* (h1 .* (h1 .+ 2 * α) ./ 2 )
251
+
252
+ # Even blocks
253
+ h0 = (kodd .* ((k .÷ 2 ) .+ 1 ) .- (keven .* ((k .÷ 2 ) .- 1 )))
254
+ h2 = (k .>= 2 ) .* ((n .÷ 2 .- 1 ) .+ h0)
255
+ l2 = neven .* (h2 .* (h2 .+ α))
256
+
257
+ # Odd blocks
258
+ h3 = (n .> k .>= 2 ) .* (((n .+ 1 ) .÷ 2 ) .- h0)
259
+ l3 = nodd .* (h3 .* (h3 .+ α))
260
+ # Combine for diagonal of super diagonal block
261
+ d = sqrt .((l1 .+ l2 .+ l3) ./ (4 .* (n .+ (α- 1 )) .* (n .+ α)))
262
+
263
+ # The off-diagonals of the super diagonal block are negative, shifted versions of the diagonal with some entries skipped
264
+ dl = (- 1 ) .* (nodd .* kodd .+ neven .* keven) .* Vcat (0 , d)
265
+ du = (- 1 ) .* (nodd .* keven .+ neven .* kodd) .* d[2 : end ]
266
+
267
+ # zero blocks for banded blockarray structure
268
+ z = Zeros ((axes (n,1 ),))
269
+ z5 = Zeros ((axes (n,1 ),Base. OneTo (5 )))
270
+
271
+ # generate and return bands
272
+ return dat = BlockHcat (BlockBroadcastArray (hcat, dl, z, d, z, du), z5, z5)
273
+ end
274
+
275
+ function getindex (b:: ZernikeJacobimatrixBandsX{T} ,i,j) where T
276
+ return BlockArrays. getindex (b. data,i,j)
277
+ end
278
+ function getindex (b:: ZernikeJacobimatrixBandsY{T} ,i,j) where T
279
+ return BlockArrays. getindex (b. data,i,j)
280
+ end
281
+
282
+ function jacobimatrix (:: Val{1} , Z:: Zernike{T} ) where T
283
+ if iszero (Z. a)
284
+ dat = ZernikeJacobimatrixBandsX {T} (Z)
285
+ return Symmetric (BlockBandedMatrices. _BandedBlockBandedMatrix (dat' , axes (dat,1 ), (1 ,1 ), (1 ,1 )))
286
+ else
287
+ error (" Implement for non-zero first basis parameter." )
288
+ end
289
+ end
290
+ function jacobimatrix (:: Val{2} , Z:: Zernike{T} ) where T
291
+ if iszero (Z. a)
292
+ dat = ZernikeJacobimatrixBandsY {T} (Z)
293
+ return Symmetric (BlockBandedMatrices. _BandedBlockBandedMatrix (dat' , axes (dat,1 ), (1 ,1 ), (2 ,2 )))
294
+ else
295
+ error (" Implement for non-zero first basis parameter." )
296
+ end
297
+ end
165
298
166
299
# ##
167
300
# Transforms
@@ -314,4 +447,4 @@ function \(A::Zernike{T}, wB::Weighted{V,Zernike{V}}) where {T,V}
314
447
c = Int (B. a - A. a + B. b - A. b)
315
448
@assert iszero (B. a)
316
449
ModalInterlace {TV} ((Normalized .(Jacobi {TV} .(A. b, A. a: ∞)) .\ HalfWeighted {:a} .(Normalized .(Jacobi {TV} .(B. b, B. a: ∞)))) .* convert (TV, 2 )^ (- c/ 2 ), (ℵ₀,ℵ₀), (2 Int (B. b), 2 Int (A. a+ A. b)))
317
- end
450
+ end
0 commit comments