-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcubic_spline_incomplete.py
122 lines (89 loc) · 2.77 KB
/
cubic_spline_incomplete.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import matplotlib.pyplot as plt
import numpy as np
import math
from numpy.linalg import inv
from numpy.linalg import norm
def driver():
f = lambda x: np.exp(x)
a = 0
b = 1
''' number of intervals'''
Nint = 3
xint = np.linspace(a,b,Nint+1)
yint = f(xint)
''' create points you want to evaluate at'''
Neval = 100
xeval = np.linspace(xint[0],xint[Nint],Neval+1)
(M,C,D) = create_natural_spline(yint,xint,Nint)
print('M =', M)
# print('C =', C)
# print('D=', D)
yeval = eval_cubic_spline(xeval,Neval,xint,Nint,M,C,D)
# print('yeval = ', yeval)
''' evaluate f at the evaluation points'''
fex = f(xeval)
nerr = norm(fex-yeval)
print('nerr = ', nerr)
plt.figure()
plt.plot(xeval,fex,'ro-',label='exact function')
plt.plot(xeval,yeval,'bs--',label='natural spline')
plt.legend
plt.show()
err = abs(yeval-fex)
plt.figure()
plt.semilogy(xeval,err,'ro--',label='absolute error')
plt.legend()
plt.show()
def create_natural_spline(yint,xint,N):
# create the right hand side for the linear system
b = np.zeros(N+1)
# vector values
h = np.zeros(N+1)
for i in range(1,N):
hi = xint[i]-xint[i-1]
hip = xint[i+1] - xint[i]
b[i] = (yint[i+1]-yint[i])/hip - (yint[i]-yint[i-1])/hi
h[i-1] = hi
h[i] = hip
# create matrix so you can solve for the M values
# This is made by filling one row at a time
A = np.zeros((N+1,N+1))
for i in range(1,N):
A[i][i-1] = h[i-1]
A[i][i] = 2*(h[i-1]+h[i])
A[i][i+1] = h[i]
A[0][0] = 1
A[N][N] = 1
Ainv = inv(A)
M = Ainv * b
# Create the linear coefficients
C = np.zeros(N)
D = np.zeros(N)
for j in range(N):
C[j] = yint[j]/h[j]-h[j]*M[j]/6
D[j] = yint[j+1]/h[j]-h[j]*M[j+1]/6
return(M,C,D)
def eval_local_spline(xeval,xi,xip,Mi,Mip,C,D):
# Evaluates the local spline as defined in class
# xip = x_{i+1}; xi = x_i
# Mip = M_{i+1}; Mi = M_i
hi = xip-xi
yeval =
return yeval
def eval_cubic_spline(xeval,Neval,xint,Nint,M,C,D):
yeval = np.zeros(Neval+1)
for j in range(Nint):
'''find indices of xeval in interval (xint(jint),xint(jint+1))'''
'''let ind denote the indices in the intervals'''
atmp = xint[j]
btmp= xint[j+1]
# find indices of values of xeval in the interval
ind= np.where((xeval >= atmp) & (xeval <= btmp))
xloc = xeval[ind]
# evaluate the spline
yloc = eval_local_spline(xloc,atmp,btmp,M[j],M[j+1],C[j],D[j])
# print('yloc = ', yloc)
# copy into yeval
yeval[ind] = yloc
return(yeval)
driver()