--- title: 11-2. Rectangular spectral collocation tags: Final reports --- **Reference** 1. Rectangular spectral collocation, T. A. Driscoll and N. Hale, IMA Journal of Numerical Analysis **36** (2016) 108–132, . [10.1093/imanum/dru062](https://doi.org/10.1093/imanum/dru062) --- ## Questions to be answered 1. Sec3.2: Re-sampling and aliasing 2. Sec4: Rectangular collocation for boundary-value problems --- ### Resampling and aliasing #### (i) Resampling Recall the Barycentric interpolation formula : The polynomial interpolation through $(x_j,f_j)_{j=0}^N$ is given by $p(x) = \frac{\sum\limits_{j=0}^N \frac{\lambda_j f_j}{x-x_j}}{\sum\limits_{j=0}^N \frac{\lambda_j}{x-x_j}}$ with $p(x_j)=f_j,$ where $\lambda_j = (\prod\limits_{k \neq j} x_j-x_k )^{-1}$ In particular, when $\{ x_j \}_{j=0}^N$ are Chebyshev points of second kind, $\lambda_j = \begin{cases} (-1)^j &,j=1,\cdots ,N-1 \\ \frac{(-1)^j}{2} &,j=0,N \end{cases}$ From the formula, we can see that the interpolant depends linearly on the values $\{ f_j \}$. That is, the evaluation of $p(y)$ at a set of points $\mathbf{y} = \{ y_i \}_{i=0}^{N-m}$ can be expressed as the matrix-vector multiplication $$ p(\mathbf{y}) =\begin{bmatrix} & & \\ & & \\ &P_{N,-m}&\\ & & \\ & & \\ \end{bmatrix} \begin{bmatrix} f_0\\ f_1\\ \vdots\\ f_{N-1}\\ f_N \end{bmatrix} $$ where $P_{N,-m} \in \mathbb{R}^{(N-m+1) \times (N+1)}$ is the **barycentric resampling matrix** $$[ P_{N,-m} ]_{j,k}= \begin{cases} \frac{\lambda_k}{y_j-x_k} (\sum\limits_{l=1}^{N} \frac{\lambda_l}{y_j-x_l})^{-1} &, y_j \neq x_k\\ 1 &, y_j = x_k \end{cases} $$ **Example :** $u(x) = e^x \sin 5x$ ```julia= using LinearAlgebra using Plots using FFTW # resampling f from original second kind chebyshev points to n_new+1 new first/second kind chebyshev points function Chebresample(n_new, f, kind) # generate old grid and new grid n_old = length(f)-1; x_old = -sin.((-n_old:2:n_old)*pi/(2*n_old)); if kind == 1 x_new = cos.((1:2:2*n_new+1)*pi/(2*n_new+2)); else x_new = -sin.((-n_new:2:n_new)*pi/(2*n_new)); end # construct Barycentric resampling matrix P = zeros(n_new+1,n_old+1); w = (-1.0).^(0:n_old); # weight w[1] = w[1]/2; w[end] = w[end]/2; for i = 1:n_new+1 if x_new[i] in x_old P[i,findfirst(x->x==x_new[i],x_old)] = 1; else temp = sum(w ./(x_new[i]*ones(n_old+1)-x_old)); for j = 1:n_old+1 P[i,j] = w[j]/(x_new[i]-x_old[j])/temp; end end end return x_new, P*f end ``` ```julia= N = 26; x = -sin.((-N:2:N)*pi/(2*N)); u = exp.(x).*sin.(5*x); xx=-1:1/100:1; uu=(exp.(xx).*sin.(5*xx)); NN=13; (x_new, u_new) = Chebresample(NN,u,1); plot(xx,uu,label="u(x)") plot!(x,u,marker=:circle,seriestype = :scatter,label="original sample points",legend=:bottomleft) plot!(x_new,u_new,marker=:utriangle,seriestype = :scatter,label="resampling points") ``` ![](https://i.imgur.com/GFYUvZ1.png) ```julia= u_new_exact = exp.(x_new).*sin.(5*x_new); print(string("max error = ",norm(u_new_exact-u_new,Inf))); ``` ![](https://i.imgur.com/5phBRUJ.png) coefficients : ```julia= u_extend = [u; u[N:-1:2]]; u_hat = fft(u_extend)/(2*N); a = zeros(N+1,1); a[1] = real(u_hat[1]); a[2:N] = 2*real(u_hat[2:N]); a[N+1] = real(u_hat[N+1]); plot(1:N+1,log10.(abs.(a)),seriestype=:scatter,label="a_k") ``` ![](https://i.imgur.com/VNwMmu4.png) #### (ii) Resamlping with differentiation matrix Recall that $[f_j^{(k)}]=D^k[f_j]$ where $D$ is the differentiation matrix. We can have $$ p^{(k)}(\mathbf{y})=[P_{N,-m}][f_j^{(k)}]=[P_{N,-m}]D^k[f_j] $$ **Example :** $u'(x) = e^x(\sin 5x + 5\cos 5x)$ ```julia= function cheb(N) if N == 0 D = 0; x = 1; return end x = -sin.((-N:2:N)*pi/(2*N)); # generate grid x_i = cos(i*pi/N) c = [2; ones(N-1,1); 2].*(-1).^(0:N); # c_i*(-1)^i X = repeat(x,1,N+1); dX = X-X'; # compute x_i - x_j D = (c*(1 ./c)')./(dX+(I(N+1))); # off-diagonal entries D = D - diagm(vec(sum(D,dims=2))); # diagonal entries return D end ``` ```julia= DD = cheb(N); (x_prime, u_prime) = Chebresample(N-1,D*u,2); uu_prime = exp.(xx).*(sin.(5*xx)+5*cos.(5*xx)); exact_u_prime = exp.(x_prime).*(sin.(5*x_prime)+5*cos.(5*x_prime)); plot(xx,uu_prime,label="u'(x)") plot!(x,D*u,marker=:circle,markersize=6,seriestype=:scatter,label="D*u") plot!(x_prime,u_prime,marker=:utriangle,seriestype=:scatter,color=:yellow,label="resampling points (P*D*u)",legend=:bottomleft) ``` ![](https://i.imgur.com/UnwK9Xs.png) ```julia= print(string("max error = ",norm(exact_u_prime-u_prime,Inf))); ``` ![](https://i.imgur.com/pGmmQAC.png) #### (iii) Aliasing Theorem 1 : For any $N \geq 1$ and $0 \leq k \leq N$, the following Chebyshev polynomials take the same value on the $(N+1)-$point second-kind Chebyshev grid : $$ T_k,\; T_{2N \pm k},\; T_{4N \pm k},\; T_{6N \pm k},\; \cdots $$ Theorem 2 : For any $N \geq 1$ and $0 \leq k \leq N$, the following Chebyshev polynomials take the same value on the $N-$point first-kind Chebyshev grid : $$ T_k,\; -T_{2N \pm k},\; T_{4N \pm k},\; -T_{6N \pm k},\; \cdots $$ Now consider downsampling a degree $N$ polynomial $p_{N-1} = \sum\limits_{k=0}^{N-1} a_k T_k(x)$, quoting a result for second-kind discretizations, to the degree $N-m-1$ polynomial $p_{N-m-1} = \sum\limits_{k=0}^{N-m-1} c_k T_k(x)$ by interpolating at $N−m$ points (where, for simplicity, we restrict $m<\frac{N}{2}$). It follows from Theorem 1 that $$ c_k = \begin{cases} a_k &,\; k=0,1,\cdots,N-2m-2 \text{, and } N-m-1\\ a_k + a_{2(N-m)-(k+1)} &,\; k=N-2m-1,\cdots,N-m-2 \end{cases} $$ if the $N-m$ points are second-kind Chebyshev points. And it also follows from Theorem 2 that $$ c_k = \begin{cases} a_k &,\; k=0,1,\cdots,N-2m\\ a_k - a_{2(N-m)-(k-1)} &,\; k=N-2m+1,\cdots,N-m-1 \end{cases} $$ if the $N-m$ points are first-kind Chebyshev points. ![](https://i.imgur.com/KIOIRcu.png) Illustration of aliased coefficients : (a) is second to second and (b) is second to first. **Example :** $u(x)=e^x\sin5x$ (1) Second-kind to Second-kind ```julia= u_extend = [u; u[N:-1:2]]; u_hat = fft(u_extend)/(2*N); a = zeros(N+1,1); a[1] = real(u_hat[1]); a[2:N] = 2*real(u_hat[2:N]); a[N+1] = real(u_hat[N+1]); NN=N-1; (x_new, u_new) = Chebresample(NN,u,2); u_new_extend = [u_new; u_new[NN:-1:2]]; u_new_hat = fft(u_new_extend)/(2*NN); c = zeros(NN+1,1); c[1] = real(u_new_hat[1]); c[2:NN] = 2*real(u_new_hat[2:NN]); c[NN+1] = real(u_new_hat[NN+1]); plot(1:N+1,log10.(abs.(a)),seriestype=:scatter,label="a_k") plot!(1:NN+1,log10.(abs.(c)),seriestype=:scatter,marker=:utriangle,label="c_k") plot!(1:NN+1,log10.(abs.(c-a[1:NN+1])),seriestype=:scatter,marker=:+,label="error") ``` ![](https://i.imgur.com/XGHgqwL.png) (2) Second-kind to First-kind ```julia= u_extend = [u; u[N:-1:2]]; u_hat = fft(u_extend)/(2*N); a = zeros(N+1,1); a[1] = real(u_hat[1]); a[2:N] = 2*real(u_hat[2:N]); a[N+1] = real(u_hat[N+1]); NN=N-1; (x_new, u_new) = Chebresample(NN,u,1); c = dct(u_new); c[1] = c[1]/sqrt(NN+1); c[2:end] = c[2:end]/sqrt((NN+1)/2); plot(1:N+1,log10.(abs.(a)),seriestype=:scatter,label="a_k") plot!(1:NN+1,log10.(abs.(c)),seriestype=:scatter,marker=:utriangle,label="c_k") plot!(1:NN+1,log10.(abs.(c-a[1:NN+1])),seriestype=:scatter,marker=:+,label="error") ``` ![](https://i.imgur.com/sLRBgZp.png) ![](https://i.imgur.com/7CDwr3m.png) From the above illustration, the downsampling of $p_{N−1} =\sum\limits^{N−1}_{ k=0} a_kT_k(x)$ to a grid of $N − 1$ Chebyshev points of the first kind is equivalent to truncating the highest-order Chebyshev coefficient $a_{N−1}$.