import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import pandas as pd
from IPython.display import display, HTML
display(HTML("""<style>.output {display: flex;align-items: center;text-align: center;}</style>"""))
def example1_1d():
a = 0.0
b = 1.0
c = 0
u = lambda x: np.sin(2.0*np.pi*(x-c))
alpha = np.sin(2.0*np.pi*(a-c)); beta = np.sin(2.0*np.pi*(b-c))
f = lambda x: 4.0*(np.pi)**2*np.sin(2.0*np.pi*(x-c))
return u, (a,b), (alpha, beta), f
def solve_fd1d(domain, bdata, f, N=10):
x = np.linspace(domain[0],domain[1],N+1)
h = (domain[1]-domain[0])/(N)
A = np.diag(2.0*np.ones(N-1)) + np.diag(-1.0*np.ones(N-2),1)+ np.diag(-1.0*np.ones(N-2),-1)
F = f(x[1:N]); F[0]+=bdata[0]/h**2; F[-1]+=bdata[1]/h**2
uh = np.zeros(N+1)
uh[0] = bdata[0]
uh[N] = bdata[1]
uh[1:N] = np.linalg.solve(A,h**2*F)
return x, uh, A
uexact, domain, bdata, f = example1_1d()
x, uh, A1d = solve_fd1d(domain, bdata, f, N=10)
fig, ax = plt.subplots(1,2, figsize=(14,6))
ax[1].spy(A1d, marker='o')
ax[0].plot(x, uh,color='C01', marker='o', linestyle='None', label=r'$u_h$')
xplot = np.linspace(domain[0], domain[1], 100)
ax[0].plot(xplot, uexact(xplot), label=r'$u$')
ax[0].legend()
plt.show()
def example2_1d():
a = 0.0
b = 1.0
alpha = 0.0; beta = 1.0
def f(x):
if x<=0.5 and x>=0.2:
return 100.0
elif x<=0.8 and x>=0.6:
return -50.0
else:
return 0
def fvec(x):
return np.array([f(xj) for xj in x])
xplot = np.linspace(-1, 2, 100)
return None, (a,b), (alpha, beta), fvec
_, domain, bdata, f = example2_1d()
x, uh, A1d = solve_fd1d(domain, bdata, f, N=600)
fig, ax = plt.subplots(1,2, figsize=(14,6))
xplot = np.linspace(domain[0], domain[1], 100)
ax[1].plot(xplot, f(xplot),color='C00', marker='None', linestyle='-', label=r'$f$')
ax[0].plot(x, uh,color='C01', marker='None', linestyle='--', label=r'$u_h$')
ax[0].legend()
ax[1].legend()
plt.show()
uexact, domain, bdata, f = example1_1d()
NN = [2**l for l in range(3,12)]; hh = [(domain[1]-domain[0])/(N) for N in NN]
Eh = np.zeros(len(NN), dtype=np.float64); Emax = np.zeros(len(NN), dtype=np.float64)
for n, N in enumerate(NN):
x, uh, _ = solve_fd1d(domain, bdata, f, N=N)
Eh[n] = np.sqrt( hh[n]*(uexact(x)-uh).dot(uexact(x)-uh))
Emax[n] = np.max( np.abs(uexact(x)-uh) )
r = [ np.log(Eh[l+1]/Eh[l])/np.log(hh[l+1]/hh[l]) for l in range(len(Eh)-1)]; r.insert(0,'-')
rmax = [ np.log(Emax[l+1]/Emax[l])/np.log(hh[l+1]/hh[l]) for l in range(len(Emax)-1)]; rmax.insert(0,'-')
df = pd.DataFrame({'h':hh, 'L2 error': Eh, 'rate':r, 'Max error': Emax, 'rate max':rmax})
df
h | L2 error | rate | Max error | rate max | |
---|---|---|---|---|---|
0 | 0.125000 | 3.749737e-02 | - | 5.302929e-02 | - |
1 | 0.062500 | 9.157561e-03 | 2.03375 | 1.295075e-02 | 2.03375 |
2 | 0.031250 | 2.276152e-03 | 2.00837 | 3.218964e-03 | 2.00837 |
3 | 0.015625 | 5.682152e-04 | 2.00209 | 8.035777e-04 | 2.00209 |
4 | 0.007812 | 1.420025e-04 | 2.00052 | 2.008218e-04 | 2.00052 |
5 | 0.003906 | 3.549741e-05 | 2.00013 | 5.020092e-05 | 2.00013 |
6 | 0.001953 | 8.874152e-06 | 2.00003 | 1.254995e-05 | 2.00003 |
7 | 0.000977 | 2.218525e-06 | 2.00001 | 3.137469e-06 | 2.00001 |
8 | 0.000488 | 5.546305e-07 | 2 | 7.843664e-07 | 2 |
y \begin{equation} u_{i,j} = g(x_{i,j}), \quad \{i,j=0 \wedge i,j=n \} \end{equation}
def example1_2d():
a = 0.0; b = 1.0
c = 0.1
u = lambda x,y : np.sin(2.0*np.pi*(x+y-c))
f = lambda x,y : 8.0*(np.pi)**2*np.sin(2.0*np.pi*(x+y-c))
def gboundary():
gb = lambda x,y: np.sin(2.0*np.pi*(x+0.0-c))
gr = lambda x,y: np.sin(2.0*np.pi*(1.0+y-c))
gt = lambda x,y: np.sin(2.0*np.pi*(x-0.0-c))
gl = lambda x,y: np.sin(2.0*np.pi*(0+y-c))
g = {'bottom':gb, 'right':gr, 'top': gt, 'left':gl}
return g
return u, (a,b,a,b), gboundary(), f
def rectangulargrid2d(domain,N):
x = np.linspace(domain[0],domain[1],N+1)
y = np.linspace(domain[2],domain[3],N+1)
X, Y = np.meshgrid(x,y)
Nodes = np.zeros( ((N+1)**2,2))
Nodes[:,0] = X.reshape((N+1)**2)
Nodes[:,1] = Y.reshape((N+1)**2)
# boundary nodes
bottom= [*range(0, N+1)]
left = [*range(N+1, (N+1)*N, N+1)]
right = [*range(2*N+1, (N+1)*N, N+1)]
top = [*range((N+1)*N, (N+1)**2)]
allnodes = bottom+left+top+right
boundary = {'bottom':bottom, 'right':right, 'top':top, 'left':left, 'all':allnodes}
return Nodes, boundary, X, Y
uexact, domain, g, f = example1_2d()
X, Y, uh, A2d, Nodes = solve_fd2d(domain, g, f, N=40)
fig = plt.figure(figsize =(14, 9))
ax = fig.add_subplot(111, projection='3d', )
Z = uh.reshape(X.shape)
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, linewidth=0, rstride=1, cstride=1)
# Customize the z axis.
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
fig.colorbar(surf, shrink=0.75, aspect=15)
plt.show()
uexact, domain, g, f = example1_2d()
NN = [2**l for l in range(3,8)]
hh = [(domain[1]-domain[0])/(N) for N in NN]
Eh = np.zeros(len(NN), dtype=np.float64)
Emax = np.zeros(len(NN), dtype=np.float64)
for n, N in enumerate(NN):
X, Y, uh, _, Nodes = solve_fd2d(domain, g, f, N=N)
Eh[n] = np.sqrt( hh[n]**2*(uexact(Nodes[:,0], Nodes[:,1])-uh).dot(uexact(Nodes[:,0], Nodes[:,1])-uh))
Emax[n] = np.max( np.abs(uexact(Nodes[:,0], Nodes[:,1])-uh) )
r = [ np.log(Eh[l+1]/Eh[l])/np.log(hh[l+1]/hh[l]) for l in range(len(Eh)-1)]; r.insert(0,'-')
rmax = [ np.log(Emax[l+1]/Emax[l])/np.log(hh[l+1]/hh[l]) for l in range(len(Emax)-1)]; rmax.insert(0,'-')
df = pd.DataFrame({'N nodes': (N+1)**2, 'h':hh, 'L2 error': Eh, 'rate':r, 'Max error': Emax, 'rate max':rmax})
df
N nodes | h | L2 error | rate | Max error | rate max | |
---|---|---|---|---|---|---|
0 | 16641 | 0.125000 | 0.032856 | - | 0.067802 | - |
1 | 16641 | 0.062500 | 0.007960 | 2.04528 | 0.016609 | 2.02932 |
2 | 16641 | 0.031250 | 0.001974 | 2.01162 | 0.004147 | 2.0018 |
3 | 16641 | 0.015625 | 0.000493 | 2.00293 | 0.001035 | 2.00311 |
4 | 16641 | 0.007812 | 0.000123 | 2.00073 | 0.000259 | 1.99986 |