You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# because it really only makes sense to compute this symmetric operator in square blocks, we have to slightly rework some of LazyArrays caching and resizing
# modify recurrence coefficients to work for normalized Legendre
266
+
normconst_Pnadd1(m::Int, settype::T) where T<:Real=sqrt(2*m+3*one(T))/sqrt(2*m+one(T))
267
+
normconst_Pnsub1(m::Int, settype::T) where T<:Real=sqrt(2*m+3*one(T))/sqrt(2*m-one(T))
268
+
normconst_Pmnmix(n::Int, m::Int, settype::T) where T<:Real=sqrt(2*m+3*one(T))*sqrt(2*n+one(T))/(sqrt(2*m+one(T))*sqrt(2*n-one(T)))
269
+
# useful explicit initial case
270
+
functionPLnorminitial00(t::Real, a::Real)
271
+
return ((t+1)^(a+1)-(t-1)^(a+1))/(2*(a+1))
272
+
end
273
+
274
+
# compute r-th coefficient of product expansion of order p and order q normalized Legendre polynomials
275
+
productseriescfs(p::T, q::T, r::T) where T =sqrt((2*p+1)*(2*q+1)/((2*(p+q-2*r)+1)))*(2*(p+q-2*r)+1)/(2*(p+q-r)+1)*exp(loggamma(r+one(T)/2)+loggamma(p-r+one(T)/2)+loggamma(q-r+one(T)/2)-loggamma(q-r+one(T))-loggamma(p-r+one(T))-loggamma(r+one(T))-loggamma(q+p-r+one(T)/2)+loggamma(q+p-r+one(T)))/π
276
+
277
+
# # this generates the entire operator via normalized product Legendre decomposition
278
+
# # this is very stable but scales rather poorly with high orders, so we only use it for testing
279
+
# function productoperator(a::T, t::T, ℓ::Int) where T
280
+
# op::Matrix{T} = zeros(T,ℓ,ℓ)
281
+
# # first row where n arbitrary and m==0
282
+
# first = powerleg_backwardsfirstrow(a,t,2*ℓ+1)
283
+
# op[1,:] = first[1:ℓ]
284
+
# # generate remaining rows
285
+
# for p = 1:ℓ-1
286
+
# for q = p:ℓ-1
287
+
# productcfs = zeros(T,2*ℓ+1)
288
+
# for i = 0:min(p,q)
289
+
# productcfs[1+q+p-2*i] = productseriescfs(p,q,i)
290
+
# end
291
+
# op[p+1,q+1] = dot(first,productcfs)
292
+
# end
293
+
# end
294
+
# # matrix is symmetric
295
+
# for m = 1:ℓ
296
+
# for n = m+1:ℓ
297
+
# op[n,m] = op[m,n]
298
+
# end
299
+
# end
300
+
# return op
301
+
# end
302
+
303
+
# This function returns the full ℓ×ℓ dot product operator, relying on several different methods for first row, second row, diagonal and remaining elements. We don't use this outside of the initial block.
304
+
functiongennormalizedpower(a::T, t::T, ℓ::Int) where T <:Real
305
+
# initialization
306
+
ℓ = ℓ+3
307
+
coeff =zeros(T,ℓ,ℓ)
308
+
# construct first row via stable backwards recurrence
309
+
first =powerleg_backwardsfirstrow(a,t,2*ℓ+1)
310
+
coeff[1,:] = first[1:ℓ]
311
+
# contruct second row via normalized product Legendre decomposition
312
+
@inboundsfor q =1:ℓ-1
313
+
productcfs =zeros(T,2*ℓ+1)
314
+
productcfs[q+2] =productseriescfs(1,q,0)
315
+
productcfs[q] =productseriescfs(1,q,1)
316
+
coeff[2,q+1] =dot(first,productcfs)
317
+
end
318
+
# contruct the diagonal via normalized product Legendre decomposition
319
+
@inboundsfor q =2:ℓ-1
320
+
productcfs =zeros(T,2*ℓ+1)
321
+
@inboundsfor i =0:q
322
+
productcfs[1+2*q-2*i] =productseriescfs(q,q,i)
323
+
end
324
+
coeff[q+1,q+1] =dot(first,productcfs)
325
+
end
326
+
#the remaining cases can be constructed iteratively by means of a T-shaped recurrence
0 commit comments