"""
The code below was written by https://github.com/DianaNtz and
is an implementation of a spectral ODE solver with dirichlet boundary condition.
"""
#import libraries
import numpy as np
import matplotlib.pyplot as plt
#setting up the grid
zmin=0
zmax=3*np.pi
N=64
z=np.linspace(zmin,zmax,N)
zz=np.zeros(N)
c=(zmax-zmin)/2
d=(zmax+zmin)/2
for j in range(0,N):
zz[j]=-np.cos(j*np.pi/(N-1))*c+d
#first spectral derivative
Dz=np.zeros((N,N))
Dz[0][0]=-(2*(N-1)**2+1)/6
Dz[N-1][N-1]=(2*(N-1)**2+1)/6
for i in range(0,N):
if(i==0 or i==N-1):
ci=2
else:
ci=1
for j in range(0,N):
if(j==0 or j==N-1):
cj=2
else:
cj=1
if(i==j and i!=0 and i!=N-1):
Dz[i][i]=-((zz[i]-d)/c)/(1-((zz[i]-d)/c)**2)*0.5
if(i!=j):
Dz[i][j]=ci/cj*(-1)**(i+j)/(zz[i]/c-zz[j]/c)
Dz=Dz/c
D2z=np.matmul(Dz,Dz)
#dirichlet boundary condition
b=np.sin(zz)
b[0]=-2
b[N-1]=2
for j in range(0,N):
if(j==0):
D2z[0][j]=1
else:
D2z[0][j]=0
if(j==N-1):
D2z[N-1][j]=1
else:
D2z[N-1][j]=0
#solving linear system
un=np.linalg.solve(D2z,b)
ua=-np.sin(zz)+4/(3*np.pi)*zz-2
ax1 = plt.subplots(1, sharex=True, figsize=(10,6))
plt.plot(zz,ua,color='black',linestyle='-',linewidth=3,label="$u_a(t)$")
plt.plot(zz,un,color='green',linestyle='-.',linewidth=3,label="$u_n(t)$")
plt.xlabel("t",fontsize=18)
plt.ylabel(r' ',fontsize=18,labelpad=20).set_rotation(0)
plt.xlim([zmin,zmax])
plt.xticks(fontsize= 17)
plt.yticks(fontsize= 17)
plt.legend(loc=2,fontsize=19,handlelength=3)
plt.savefig("spectral1d.png",dpi=200)
plt.show()