|
39 | 39 |
|
40 | 40 | TriangleWeight(a::T, b::T, c::T) where T = TriangleWeight{float(T),T}(a, b, c)
|
41 | 41 |
|
42 |
| -const WeightedTriangle{T} = WeightedBasis{T,<:TriangleWeight,<:JacobiTriangle} |
| 42 | +const WeightedTriangle{T,V} = Weighted{T,JacobiTriangle{T,V}} |
43 | 43 |
|
44 |
| -WeightedTriangle(a, b, c) = TriangleWeight(a,b,c) .* JacobiTriangle(a,b,c) |
| 44 | +WeightedTriangle(a, b, c) = Weighted(JacobiTriangle(a,b,c)) |
45 | 45 |
|
46 | 46 | axes(P::TriangleWeight{T}) where T = (Inclusion(UnitTriangle{T}()),)
|
| 47 | +function getindex(P::TriangleWeight, xy::StaticVector{2}) |
| 48 | + x,y = xy |
| 49 | + x^P.a * y^P.b * (1-x-y)^P.c |
| 50 | +end |
| 51 | + |
| 52 | +all(::typeof(isone), w::TriangleWeight) = iszero(w.a) && iszero(w.b) && iszero(w.c) |
| 53 | +==(w::TriangleWeight, v::TriangleWeight) = w.a == v.a && w.b == v.b && w.c == v.c |
| 54 | + |
| 55 | +==(wA::WeightedTriangle, B::JacobiTriangle) = wA.P == B == JacobiTriangle(0,0,0) |
| 56 | +==(B::JacobiTriangle, wA::WeightedTriangle) = wA == B |
| 57 | + |
| 58 | +==(w_A::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}, w_B::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}) = arguments(w_A) == arguments(w_B) |
| 59 | + |
| 60 | +function ==(w_A::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}, B::JacobiTriangle) |
| 61 | + w,A = arguments(w_A) |
| 62 | + all(isone,w) && A == B |
| 63 | +end |
| 64 | + |
| 65 | +==(B::JacobiTriangle, w_A::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}) = w_A == B |
| 66 | + |
| 67 | +function ==(w_A::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}, wB::WeightedTriangle) |
| 68 | + w,A = arguments(w_A) |
| 69 | + w.a == A.a && w.b == A.b && w.c == A.c && A == wB.P |
| 70 | +end |
| 71 | + |
| 72 | +==(wB::WeightedTriangle, w_A::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}) = w_A == wB |
47 | 73 |
|
48 | 74 | Base.summary(io::IO, P::TriangleWeight) = print(io, "x^$(P.a)*y^$(P.b)*(1-x-y)^$(P.c) on the unit triangle")
|
49 | 75 |
|
| 76 | +orthogonalityweight(P::JacobiTriangle) = TriangleWeight(P.a, P.b, P.c) |
| 77 | + |
50 | 78 | @simplify function *(Dx::PartialDerivative{1}, P::JacobiTriangle)
|
51 | 79 | a,b,c = P.a,P.b,P.c
|
52 | 80 | n = mortar(Fill.(oneto(∞),oneto(∞)))
|
@@ -117,6 +145,18 @@ function Ry(a,b,c)
|
117 | 145 | _BandedBlockBandedMatrix(dat, axes(k,1), (0,1), (0,1))
|
118 | 146 | end
|
119 | 147 |
|
| 148 | +function Rz(a,b,c) |
| 149 | + n = mortar(Fill.(oneto(∞),oneto(∞))) |
| 150 | + k = mortar(Base.OneTo.(oneto(∞))) |
| 151 | + dat = PseudoBlockArray(Vcat( |
| 152 | + (-(k .+ (b-1) ) .* (n .+ k .+ (b+c-1)) ./ ((2n .+ (a+b+c)) .* (2k .+ (b+c-1) )))', |
| 153 | + ((k .- n .- a ) .* (k .+ (b+c)) ./ ((2n .+ (a+b+c)) .* (2k .+ (b+c-1) )))', |
| 154 | + (-(k .+ (b-1) ) .* (k .- n .- 1) ./ ((2n .+ (a+b+c)) .* (2k .+ (b+c-1) )))', |
| 155 | + ((n .+ k .+ (a+b+c) ) .* (k .+ (b+c)) ./ ((2n .+ (a+b+c)) .* (2k .+ (b+c-1) )))' |
| 156 | + ), (blockedrange(Fill(2,2)), axes(n,1))) |
| 157 | + _BandedBlockBandedMatrix(dat, axes(k,1), (0,1), (0,1)) |
| 158 | +end |
| 159 | + |
120 | 160 | function Lx(a,b,c)
|
121 | 161 | n = mortar(Fill.(oneto(∞),oneto(∞)))
|
122 | 162 | k = mortar(Base.OneTo.(oneto(∞)))
|
@@ -151,35 +191,94 @@ end
|
151 | 191 |
|
152 | 192 |
|
153 | 193 | function \(w_A::WeightedTriangle, w_B::WeightedTriangle)
|
154 |
| - wA,A = w_A.args |
155 |
| - wB,B = w_B.args |
156 |
| - |
157 |
| - @assert wA.a == A.a && wA.b == A.b && wA.c == A.c |
158 |
| - @assert wB.a == B.a && wB.b == B.b && wB.c == B.c |
| 194 | + A,B = w_A.P,w_B.P |
159 | 195 |
|
160 |
| - if A.a + 1 == B.a && A.b == B.b && A.c == B.c |
| 196 | + if A.a == B.a && A.b == B.b && A.c == B.c |
| 197 | + Eye{promote_type(eltype(A),eltype(B))}((axes(B,2),)) |
| 198 | + elseif A.a + 1 == B.a && A.b == B.b && A.c == B.c |
161 | 199 | Lx(B.a, B.b, B.c)
|
162 | 200 | elseif A.a == B.a && A.b + 1 == B.b && A.c == B.c
|
163 | 201 | Ly(B.a, B.b, B.c)
|
164 | 202 | elseif A.a == B.a && A.b == B.b && A.c + 1 == B.c
|
165 | 203 | Lz(B.a, B.b, B.c)
|
| 204 | + elseif A.a < B.a |
| 205 | + w_C = WeightedTriangle(A.a+1,A.b,A.c) |
| 206 | + (w_A \ w_C) * (w_C \ w_B) |
| 207 | + elseif A.b < B.b |
| 208 | + w_C = WeightedTriangle(A.a,A.b+1,A.c) |
| 209 | + (w_A \ w_C) * (w_C \ w_B) |
| 210 | + elseif A.c < B.c |
| 211 | + w_C = WeightedTriangle(A.a,A.b,A.c+1) |
| 212 | + (w_A \ w_C) * (w_C \ w_B) |
166 | 213 | else
|
167 |
| - error("not implemented for $A and $wB") |
| 214 | + error("not implemented for $w_A and $w_B") |
168 | 215 | end
|
169 | 216 | end
|
170 | 217 |
|
171 |
| -\(w_A::JacobiTriangle, w_B::WeightedTriangle) = |
172 |
| - (TriangleWeight(0,0,0) .* w_A) \ w_B |
| 218 | +function \(w_A::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}, w_B::WeightedTriangle) |
| 219 | + wA,A = w_A.args |
| 220 | + w_A == Weighted(A) && Weighted(A) \ w_B |
| 221 | + all(isone,wA) && return A \ w_B |
| 222 | + error("Not implemented") |
| 223 | +end |
| 224 | + |
| 225 | +function \(w_A::WeightedTriangle, w_B::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}) |
| 226 | + wB,B = w_B.args |
| 227 | + w_B == Weighted(B) && w_A \ Weighted(B) |
| 228 | + all(isone,wB) && return w_A \ B |
| 229 | + error("Not implemented") |
| 230 | +end |
| 231 | + |
| 232 | + |
| 233 | +function \(w_A::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}, w_B::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}) |
| 234 | + wA,A = w_A.args |
| 235 | + w_A == Weighted(A) && Weighted(A) \ w_B |
| 236 | + all(isone,wA) && return A \ w_B |
| 237 | + error("Not implemented") |
| 238 | +end |
| 239 | + |
| 240 | +function \(w_A::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}, B::JacobiTriangle) |
| 241 | + wA,A = w_A.args |
| 242 | + w_A == Weighted(A) && return Weighted(A) \ B |
| 243 | + all(isone,wA) && return A \ B |
| 244 | + error("Not implemented") |
| 245 | +end |
| 246 | + |
| 247 | +function \(A::JacobiTriangle, w_B::WeightedBasis{<:Any,<:TriangleWeight,<:JacobiTriangle}) |
| 248 | + wB,B = w_B.args |
| 249 | + w_B == Weighted(B) && return A \ Weighted(B) |
| 250 | + all(isone,wB) && return A \ B |
| 251 | + error("Not implemented") |
| 252 | +end |
| 253 | + |
| 254 | +function \(A::JacobiTriangle, w_B::WeightedTriangle) |
| 255 | + w_B.P == JacobiTriangle() && return A \ w_B.P |
| 256 | + A == JacobiTriangle() && return Weighted(A) \ w_B |
| 257 | + (TriangleWeight(0,0,0) .* A) \ w_B |
| 258 | +end |
| 259 | +function \(w_A::WeightedTriangle, B::JacobiTriangle) |
| 260 | + w_A.P == JacobiTriangle() && return w_A.P \ B |
| 261 | + w_A \ (TriangleWeight(0,0,0) .* B) |
| 262 | +end |
173 | 263 |
|
174 | 264 | function \(A::JacobiTriangle, B::JacobiTriangle)
|
175 |
| - if A.a == B.a && A.b == B.b && A.c == B.c |
176 |
| - Eye((axes(B,2),)) |
| 265 | + if A == B |
| 266 | + Eye{promote_type(eltype(A),eltype(B))}((axes(B,2),)) |
177 | 267 | elseif A.a == B.a + 1 && A.b == B.b && A.c == B.c
|
178 | 268 | Rx(B.a, B.b, B.c)
|
179 | 269 | elseif A.a == B.a && A.b == B.b + 1 && A.c == B.c
|
180 | 270 | Ry(B.a, B.b, B.c)
|
181 |
| - # elseif A.a == B.a && A.b == B.b && A.c == B.c + 1 |
182 |
| - # Rz(B.a, B.b, B.c) |
| 271 | + elseif A.a == B.a && A.b == B.b && A.c == B.c + 1 |
| 272 | + Rz(B.a, B.b, B.c) |
| 273 | + elseif A.a > B.a |
| 274 | + C = JacobiTriangle(B.a+1,B.b,B.c) |
| 275 | + (A \ C) * (C \ B) |
| 276 | + elseif A.b > B.b |
| 277 | + C = JacobiTriangle(B.a,B.b+1,B.c) |
| 278 | + (A \ C) * (C \ B) |
| 279 | + elseif A.c > B.c |
| 280 | + C = JacobiTriangle(B.a,B.b,B.c+1) |
| 281 | + (A \ C) * (C \ B) |
183 | 282 | else
|
184 | 283 | error("not implemented for $A and $B")
|
185 | 284 | end
|
@@ -431,14 +530,18 @@ function tri_forwardrecurrence(N::Int, X, Y, x, y)
|
431 | 530 | N < 1 && return ret
|
432 | 531 | ret[1] = 1
|
433 | 532 | N < 2 && return ret
|
434 |
| - ret[2] = x/X[1,1]-1 |
435 |
| - ret[3] = -Y[2,1]/(Y[3,1]*X[1,1]) * (x-X[1,1]) + (y-Y[1,1])/Y[3,1] |
436 | 533 |
|
437 | 534 | X_N = X[Block.(1:N), Block.(1:N-1)]
|
438 | 535 | Y_N = Y[Block.(1:N), Block.(1:N-1)]
|
439 | 536 |
|
| 537 | + let n = 1 |
| 538 | + A = TriangleRecurrenceA(n, X_N, Y_N) |
| 539 | + B = TriangleRecurrenceB(n, X_N, Y_N) |
| 540 | + ret[Block(2)] .= A*[x; y] + vec(B) |
| 541 | + end |
| 542 | + |
440 | 543 | for n = 2:N-1
|
441 |
| - # P[n+1,xy] == (A[n]*[x*Eye(n); y*Eye(n)] + B[n])*P[n,xy] - C[n]*P[n-1,xy] |
| 544 | + # P[n+1,xy] == (A*[x*Eye(n); y*Eye(n)] + B)*P[n,xy] - C*P[n-1,xy] |
442 | 545 | A = TriangleRecurrenceA(n, X_N, Y_N)
|
443 | 546 | B = TriangleRecurrenceB(n, X_N, Y_N)
|
444 | 547 | C = TriangleRecurrenceC(n, X_N, Y_N)
|
|
0 commit comments