@@ -12,6 +12,10 @@ isequaldict2(b1::Jacobi, b2::Ultraspherical) = isequaldict1(b2, b1)
1212
1313const RECURRENCEBASIS = Union{Monomials,OrthogonalPolynomials}
1414
15+ # ##########################
16+ # Polynomial conversions
17+ # ##########################
18+
1519function conversion1 (:: Type{T} , src:: RECURRENCEBASIS , dest:: RECURRENCEBASIS ; options... ) where T
1620 if length (dest) < length (src)
1721 throw (ArgumentError (" Cannot convert to a smaller basis." ))
@@ -31,11 +35,11 @@ function conversion1(::Type{T}, src::RECURRENCEBASIS, dest::RECURRENCEBASIS; opt
3135end
3236
3337conversion_using_recurrences (:: Type{T} , src:: RECURRENCEBASIS , dest:: RECURRENCEBASIS ; options... ) where T =
34- generic_conversion_using_recurrences (T, src, dest; options ... )
38+ generic_conversion_using_recurrences (T, src, dest)
3539
3640# For two bases satisfying a recurrence relation we use that relation to compute the connection
3741# coefficients to transform between them.
38- function generic_conversion_using_recurrences (:: Type{T} , src:: RECURRENCEBASIS , dest:: RECURRENCEBASIS ; options ... ) where T
42+ function generic_conversion_using_recurrences (:: Type{T} , src:: RECURRENCEBASIS , dest:: RECURRENCEBASIS ) where T
3943 @assert length (dest) == length (src)
4044 n = length (dest)
4145 A = zeros (T, n, n)
@@ -208,3 +212,123 @@ function conversion_using_recurrences(::Type{T}, src::Jacobi, dest::ChebyshevU;
208212 generic_conversion_using_recurrences (T, src, dest; options... )
209213 end
210214end
215+
216+ # ##########################
217+ # Differentiation matrices
218+ # ##########################
219+
220+ differentiation (:: Type{T} , src:: B , dest:: B , order:: Int ; options... ) where {T,B<: OrthogonalPolynomials } =
221+ differentiation_for_ops (T, src, dest, order; options... )
222+
223+ function differentiation_for_ops (:: Type{T} , src:: B , dest:: B , order:: Int ; options... ) where {T,B<: OrthogonalPolynomials }
224+ @assert order == 1
225+ if length (src) == length (dest)
226+ A = differentiation_using_recurrences (T, src; options... )
227+ ArrayOperator (A, src, dest)
228+ elseif length (src) == length (dest)+ 1
229+ A = differentiation_using_recurrences (T, src; options... )
230+ restriction (T, src, dest) ∘ ArrayOperator (A, src, src)
231+ else
232+ throw (ArgumentError (" Incompatible sizes of src and dest dictionaries for differentiation." ))
233+ end
234+ end
235+
236+
237+ differentiation_using_recurrences (:: Type{T} , src:: RECURRENCEBASIS ; options... ) where T =
238+ generic_differentiation_using_recurrences (T, src)
239+
240+ function generic_differentiation_using_recurrences (:: Type{T} , src:: RECURRENCEBASIS ) where T
241+ n = length (src)
242+ M = zeros (T, n, n)
243+ if n >= 2
244+ A0 = rec_An (src, 0 )
245+ M[1 ,2 ] = A0
246+ end
247+ if n >= 3
248+ B0 = rec_Bn (src, 0 )
249+ A1 = rec_An (src, 1 )
250+ B1 = rec_Bn (src, 1 )
251+ M[1 ,3 ] = B1* A0 - A1* B0
252+ M[2 ,3 ] = 2 A1
253+ end
254+ for k in 2 : n- 2
255+ C1 = rec_Cn (src, 1 )
256+ Ak = rec_An (src, k)
257+ Bk = rec_Bn (src, k)
258+ Ck = rec_Cn (src, k)
259+ Akm1 = rec_An (src, k- 1 )
260+ Bkm1 = rec_Bn (src, k- 1 )
261+ Akm2 = rec_An (src, k- 2 )
262+ M[1 ,k+ 2 ] = Bk * M[1 ,k+ 1 ] - Ck* M[1 ,k] - M[1 ,k+ 1 ]* Ak* B0/ A0 + M[2 ,k+ 1 ]* Ak* C1/ A1
263+ for j in 1 : k- 2
264+ Aj = rec_An (src, j)
265+ Bj = rec_Bn (src, j)
266+ Cj = rec_Bn (src, j)
267+ Ajm1 = rec_An (src, j- 1 )
268+ Ajp1 = rec_An (src, j+ 1 )
269+ Cjp1 = rec_Cn (src, j+ 1 )
270+ M[j+ 1 ,k+ 2 ] = Bk * M[j+ 1 ,k+ 1 ] - Ck* M[j+ 1 ,k] + M[j,k+ 1 ]* Ak/ Ajm1 - M[j+ 1 ,k+ 1 ]* Ak* Bj/ Aj + M[j+ 2 ,k+ 1 ]* Ak* Cjp1/ Ajp1
271+ end
272+ M[k,k+ 2 ] = Bk* M[k,k+ 1 ] + M[k- 1 ,k+ 1 ]* Ak/ Akm2 - M[k,k+ 1 ]* Ak* Bkm1/ Akm1
273+ M[k+ 1 ,k+ 2 ] = Ak+ M[k,k+ 1 ]* Ak/ Akm1
274+ end
275+ UpperTriangular (M)
276+ end
277+
278+ # Some special cases
279+
280+ function chebyshevt_to_chebyshevu_differentiation (:: Type{T} , n, m) where T
281+ @assert n- 1 <= m <= n
282+ A = BandedMatrix {T} (undef, (m,n), (0 ,1 ))
283+ for k in 1 : n- 1
284+ A[k,k] = 0
285+ A[k,k+ 1 ] = k
286+ end
287+ if m == n
288+ A[n,n] = 0
289+ end
290+ A
291+ end
292+
293+ function differentiation (:: Type{T} , src:: ChebyshevT , dest:: ChebyshevU , order:: Int ; options... ) where T
294+ @assert order == 1
295+ n = length (src)
296+ m = length (dest)
297+ if n- 1 <= m <= n
298+ A = chebyshevt_to_chebyshevu_differentiation (T, n, m)
299+ ArrayOperator (A, src, dest)
300+ else
301+ throw (ArgumentError (" Incompatible length of dictionaries for differentiation." ))
302+ end
303+ end
304+
305+ function ultraspherical_differentiation (λ:: T , n, m) where T
306+ @assert n- 1 <= m <= n
307+ A = BandedMatrix {T} (undef, (m,n), (0 ,1 ))
308+ for k in 1 : n- 1
309+ A[k,k] = 0
310+ A[k,k+ 1 ] = 2 λ
311+ end
312+ if m == n
313+ A[n,n] = 0
314+ end
315+ A
316+ end
317+
318+ function differentiation (:: Type{T} , src:: Ultraspherical , dest:: Ultraspherical , order:: Int ; options... ) where T
319+ @assert order == 1
320+ if ultraspherical_λ (dest) == ultraspherical_λ (src) + 1
321+ n = length (src)
322+ m = length (dest)
323+ if n- 1 <= m <= n
324+ A = ultraspherical_differentiation (ultraspherical_λ (src), n, m)
325+ ArrayOperator (A, src, dest)
326+ else
327+ throw (ArgumentError (" Incompatible length of dictionaries for differentiation." ))
328+ end
329+ elseif ultraspherical_λ (dest) == ultraspherical_λ (src)
330+ differentiation_for_ops (T, src, dest, order; options... )
331+ else
332+ throw (ArgumentError (" Incompatible dictionaries for differentiation." ))
333+ end
334+ end
0 commit comments