---
# System prepended metadata

title: 9-3. Chebyshev approximations - interpolation
tags: [Spectral method]

---

---
title: 9-3. Chebyshev approximations - interpolation
tags: Spectral method
GA: G-RYTKXJR91W
---

**Reference**
1. [Approximation theory and approximation practice](https://people.maths.ox.ac.uk/trefethen/ATAP/ATAPfirst6chapters.pdf) by *Lloyd N. Trefethen*

---

## Exercise 1

Consider 
$$
f(x) = e^x \sin(300 x), \quad -1\le x\le 1.
$$

1. Use "enough" grid points to approximation the function and its derivative. 

2. Write a program to interpolate f'(x) at given array of points. That is, the input of your program is a vector $\vec{x}$ and the output is the vector $f'(\vec{x})$.

    * Randomly choose $10^3$, $10^4$ and $10^5$ points on $[-1, 1]$, how long does it takes for the interpolation?

---

###CODE(PYTHON):

```python=
import math
import numpy as np
import random as random
import matplotlib.pyplot as plt

#grid number
n=330

X=np.cos(np.linspace(0,n,n)*np.pi/n)
F=np.exp(X)*np.sin(300*X)

#Barycentric interpolation in Chebyshev points
def Baryc(x,n,X,F):
    a=((-1)**0*F[0]/(x-X[0])+(-1)**n*F[0]/(x-X[n-1]))*0.5
    for j in range(1,n-1):
        a=a+(-1)**j*F[j]/(x-X[j])
    b=((-1)**0/(x-X[0])+(-1)**n/(x-X[n-1]))*0.5
    for j in range(1,n-1):
        b=b+(-1)**j/(x-X[j])
    return a/b

#First order differential  Barycentric interpolation in Chebyshev points   
def D_Baryc(x,n,X,F):
    a=(-(-1)**0*F[0]/(x-X[0])**2-(-1)**n*F[0]/(x-X[n-1])**2)*0.5
    for j in range(1,n-1):
        a=a-(-1)**j*F[j]/(x-X[j])**2
    b=((-1)**0/(x-X[0])+(-1)**n/(x-X[n-1]))*0.5
    for j in range(1,n-1):
        b=b+(-1)**j/(x-X[j])
    A=a/b

#solve f(x)
Test_10000=2*np.random.rand(1,10000)-1
Test_10000=np.sort(Test_10000[0])
FTest_10000=Baryc(Test_10000,n,X,F)
plt.plot(Test_10000,FTest_10000)

#solve f'(x)
Test_10000=2*np.random.rand(1,10000)-1
Test_10000=np.sort(Test_10000[0])
FTest_10000=D_Baryc(Test_10000,n,X,F)
plt.plot(Test_10000,FTest_10000)

###############################################################
#Chebyshev coefficients

# generate grid points
N = 380;
X = np.cos(np.arange(0,N)*np.pi/N)

# evaluate at grid points
f = np.exp(X)*np.sin(300*X)

# extend the function and take scaled FFT

res=f[1:N-1]
res=res[::-1]
f_extend=np.hstack((f,res))

f_hat = fft(f_extend)/(2*N)

# obtain the Chebyshev coefficients
a = np.zeros((1,N+1))
a[0][0] = np.real(f_hat[0])
a[0][1:N-1] = 2*np.real(f_hat[1:N-1])
a[0][N] = np.real(f_hat[N])
plt.plot(np.log10(abs(a[0])))

```


### ANS of Q1:

For this function,more than 340 grid points is enough.

f(x):
![](https://i.imgur.com/wSE8WRO.png)
f'(x):
![](https://i.imgur.com/2lywmSR.png)

Error estimation:
$log (a)$:
![](https://i.imgur.com/gobQ8P1.png)
$log_{10} (a)$:
![](https://i.imgur.com/HhDk8FG.png)



### ANS of Q2:

#### Randomly choose 100 points
f(x):
![](https://i.imgur.com/snXweF3.png)
f'(x):cost 0.00800sec
![](https://i.imgur.com/WvjQ8Ux.png)
#### Randomly choose 1000 points
f(x):
![](https://i.imgur.com/u2nSEI7.png)
f'(x):cost 0.01400sec
![](https://i.imgur.com/dyv7ALb.png)
#### Randomly choose 10000 points
f(x):
![](https://i.imgur.com/biKuuwY.png)
f'(x): cost 0.05803sec
![](https://i.imgur.com/twjV11A.png)
f'(x) on the range[-0.99,1]
![](https://i.imgur.com/2owQS56.png)

=========================================================
(閔中)
![](https://i.imgur.com/MNqI1JU.png)
![](https://i.imgur.com/YEs2LGT.png)
![](https://i.imgur.com/gZDTERR.png)
![](https://i.imgur.com/Xdsgsve.png)
![](https://i.imgur.com/s8KgnK3.png)
![](https://i.imgur.com/WOqhkgg.png)
![](https://i.imgur.com/7DvQyAI.png)


```
(Matlab code)
function Barycentric

N = 1000;
x = cos((2*(N:-1:1)-1)*pi/(2*N))';
x_plot = linspace(min(x-sqrt(5)/10000),max(x+sqrt(5)/10000),2*N)';

f = @(x) exp(x).*sin(300*x);
df = @(x) exp(x).*(sin(300*x)+300*cos(300*x));

p = chebf(x,x_plot,f);
dp = chebdf(x,x_plot,df);
errorf = abs(p-f(x_plot));
errordf = abs(dp-df(x_plot));

figure(1)
subplot(3,1,1)
plot(x_plot,p,'r') ; hold on;
axis([-1 1 -3 3])
title('f(x)')
ylabel('p(x)')
subplot(3,1,2)
plot(x_plot,f(x_plot),'k'); hold on;
axis([-1 1 -3 3])
ylabel('f(x)')
subplot(3,1,3)
semilogy(x_plot,errorf,'b'); hold off;
axis([-1 1 10^-5 1])
ylabel('|f(x)-p(x)|')
xlabel('x') 

figure(2)
subplot(3,1,1)
plot(x_plot,dp,'r') ; hold on;
axis([-1 1 -1000 1000])
title('df/dx')
ylabel('dp/dx')
subplot(3,1,2)
plot(x_plot,df(x_plot),'k'); hold on;
axis([-1 1 -1000 1000])
ylabel('df/dx')
subplot(3,1,3)
semilogy(x_plot,errordf,'b'); hold off;
axis([-1 1 10^-5 1])
ylabel('|df/dx-dp/dx|')
xlabel('x') 

tic
x2 = -1+2*rand(100,1);
x2 = sort(x2);
p2 = chebf(x,x2,f);
dp2 = chebdf(x,x2,df);
toc
tic
x3 = -1+2*rand(1000,1);
x3 = sort(x3);
p3 = chebf(x,x3,f);
dp3 = chebdf(x,x3,df);
toc
tic
x4 = -1+2*rand(10000,1);
x4 = sort(x4);
p4 = chebf(x,x4,f);
dp4 = chebdf(x,x4,df);
toc
tic
x5 = -1+2*rand(100000,1);
x5 = sort(x5);
p5 = chebf(x,x5,f);
dp5 = chebdf(x,x5,df);
toc

figure(3)
subplot(4,1,1)
plot(x2,p2,'r') ; hold on;
axis([-1 1 -3 3])
title('p(x)')
ylabel('p(x) at n = 10^2')
subplot(4,1,2)
plot(x3,p3,'b') ; hold on;
axis([-1 1 -3 3])
ylabel('p(x) at n = 10^3')
subplot(4,1,3)
plot(x4,p4,'g'); hold on;
axis([-1 1 -3 3])
ylabel('p(x) at n = 10^4')
subplot(4,1,4)
plot(x5,p5,'k'); hold off;
axis([-1 1 -3 3])
ylabel('p(x) at n = 10^5')
xlabel('x') 

figure(4)
subplot(4,1,1)
plot(x2,dp2,'r') ; hold on;
axis([-1 1 -1000 1000])
title('dp/dx')
ylabel('dp/dx at n = 10^2')
subplot(4,1,2)
plot(x3,dp3,'b') ; hold on;
axis([-1 1 -1000 1000])
ylabel('dp/dx at n = 10^3')
subplot(4,1,3)
plot(x4,dp4,'g'); hold on;
axis([-1 1 -1000 1000])
ylabel('dp/dx at n = 10^4')
subplot(4,1,4)
plot(x5,dp5,'k'); hold off;
axis([-1 1 -1000 1000])
ylabel('dp/dx at n = 10^5')
xlabel('x') 

function p = chebf(x,x_plot,f)
N = length(x);
p = zeros(length(x_plot),1);
for m = 1:length(x_plot)
p(m)  = sum((-1).^(1:N)'.*f(x)./(x_plot(m)-x))/sum((-1).^(1:N)'./(x_plot(m)-x));
end

function dp = chebdf(x,x_plot,df)
N = length(x);
dp = zeros(length(x_plot),1);
for m = 1:length(x_plot)
dp(m)  = sum((-1).^(1:N)'.*df(x)./(x_plot(m)-x))/sum((-1).^(1:N)'./(x_plot(m)-x));
end

```

## Exercise 2

Consider 
$$
g(x) = \sin(e^{10 x}), \quad -1\le x\le 1.
$$

1. Use "enough" grid points to approximation the function, denoted by $p(x)$. (It should be more than $10^4$)

2. Write a program to interpolate p(x) at $1000$ random points. That is, the input of your program is a vector $\vec{x}$ and the output is the vector $p(\vec{x})$.

    * How long does it takes to evluate $p(\vec{x})$? 
    * How long does it takes to evluate $g(\vec{x})$? 
    * Draw a plot for $|p(\vec{x}) - g(\vec{x})|$

---
### Answer:
A1. p(x) cost 113.978306 sec

A2. g(x) cost 0.005985 sec

A3.
![](https://i.imgur.com/OasWSoJ.png)

![](https://i.imgur.com/kbXFIyM.png)

error estimation
![](https://i.imgur.com/dcpKsug.png)


Python code
```python=
import numpy as np
import matplotlib.pyplot as plt

#在-1到1之間取 N 個 Chebyshev points 和對應的值
N=42800
x=np.cos((np.linspace(0,N,N+1)*np.pi)/N)
f=np.sin(np.exp(10*x))

#Barycentric_interpolation
def Barycentric_interpolation(x0,x,f,N):
    frac=0
    deno=0
    for j in range(1,N):
        frac=frac+((-1)**j*f[j])/(x0-x[j])
        deno=deno+((-1)**j)/(x0-x[j])
    
    frac=frac+0.5*(((-1)**0*f[0])/(x0-x[0]))+0.5*(((-1)**(N)*f[N])/(x0-x[N]))
    deno=deno+0.5*(((-1)**0)/(x0-x[0]))+0.5*(((-1)**(N))/(x0-x[N]))
    return frac/deno                                        

a=f.tolist()[1:N+1]
a.reverse()
A=f.tolist()+a
f_extend=np.array(A)

f_hat=np.real(np.fft.fft(f_extend))

a =np.zeros(N+1);
a[0]= f_hat[0];
a[1:N] = 2*f_hat[1:N];
a[N] = f_hat[N];

plt.plot(np.log10(abs(a)))
plt.savefig('the number of coefficient.png')
```
```python=
import random
import time

P=[]
for i in range(1000):
    P.append(random.uniform(-1, 1))
P=np.array(P)
P.sort()

tStart = time.time()

Res_num=[]
for i in range(len(P)):
    Res_num.append(Barycentric_interpolation(P[i],x,f,N))
Res_num=np.array(Res_num)

tEnd = time.time()
print ("p(x) cost %f sec" % (tEnd - tStart))
print (tEnd - tStart)

tStart = time.time()

Res_true=[]
for i in range(len(P)):
    Res_true.append(np.sin(np.exp(10*P[i])))
Res_true=np.array(Res_true)

tEnd = time.time()
print ("g(x) cost %f sec" % (tEnd - tStart))
print (tEnd - tStart)
```
```python=
import matplotlib.pyplot as plt
plt.plot(P,abs(Res_true-Res_num))
plt.ylabel('|p(x)-g(x)|')
plt.savefig('P-g.png')
```