Skip to content

Commit 74e6c75

Browse files
committed
Initial commit. Quadratic base not working. No longer being developed.
0 parents  commit 74e6c75

File tree

4 files changed

+371
-0
lines changed

4 files changed

+371
-0
lines changed

.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

FEM.py

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# coding: utf-8
2+
__author__ = "Arwa Ashi and Tom Gresavage"
3+
4+
import numpy as np
5+
import matplotlib.pyplot as plt
6+
from math import *
7+
from numpy import linalg as LA
8+
from random import *
9+
import math
10+
11+
def utrue(x):
12+
# Define the true solution
13+
return np.exp(x**(2./3.))
14+
15+
def g(x, k, v):
16+
# Define the forcing function of utrue
17+
return (2.*np.exp(x**(2./3.))*(k - 2.*k*x**(2./3.) + 3.*v*x))/(9.*x**(4./3.))
18+
19+
def linbasis(xj):
20+
'''
21+
Creates a linear basis from the 3-element list xj centered at the middle element
22+
'''
23+
def f(x):
24+
if xj[0] <= x <= xj[1]:
25+
return (x-xj[0])/(xj[1]-xj[0])
26+
elif xj[1] <= x <= xj[2]:
27+
return (xj[2]-x)/(xj[2]-xj[1])
28+
else:
29+
return 0.
30+
return f
31+
32+
def quadrature5(f, a, b):
33+
'''
34+
Calculate int_a^b f(x)dx using 5-point Gaussian Quadrature
35+
Print the result
36+
'''
37+
quad_x = [0., np.sqrt(5.-2.*np.sqrt(10./7.))/3., -np.sqrt(5.-2.*np.sqrt(10./7.))/3., np.sqrt(5.+2.*np.sqrt(10./7.))/3., -np.sqrt(5.+2.*np.sqrt(10./7.))/3.]
38+
quad_w = [128./225., (322.+13.*np.sqrt(70))/900., (322.+13.*np.sqrt(70))/900., (322.-13.*np.sqrt(70))/900., (322.-13.*np.sqrt(70))/900.]
39+
s_int = ((b-a)/2.)*np.sum([quad_w[j]*f(((b-a)/2.)*quad_x[j]+(a+b)/2.) for j in range(5)])
40+
return s_int
41+
42+
# Define a function to generate a set of basis functions for each x
43+
def genbasis(xpts):
44+
'''
45+
Creates a set of linear basis functions centered at each item in xpts
46+
'''
47+
dx = np.diff(xpts)
48+
phi = list()
49+
for i in range(len(xpts)):
50+
if i == 0:
51+
phi.append(linbasis([xpts[i]-dx[i],xpts[i], xpts[i]+dx[i]]))
52+
elif i == len(xpts)-1:
53+
phi.append(linbasis([xpts[i]-dx[i-1],xpts[i], xpts[i]+dx[i-1]]))
54+
else:
55+
phi.append(linbasis(xpts[i-1:i+2]))
56+
return phi
57+
58+
# Define the discretization of the problem.
59+
x0 = 1.0 # start of the grid
60+
xn = 10.0 # End of grid
61+
n = 100 # number of nodes on the grid
62+
dx = (xn-x0)/float(n) # Set a uniform grid spacing
63+
xpts = np.linspace(x0, xn, n)
64+
dxs = np.diff(xpts) # Calculate \Delta x if mesh is not uniform
65+
phi = genbasis(xpts) # Create basis function
66+
67+
# Define the temporal domain
68+
t0 = 0.
69+
tn = 3.
70+
timeSteps = 100
71+
dt = (tn-t0)/timeSteps
72+
73+
# Set the equation coefficients
74+
k = 3.0
75+
v = 1
76+
77+
#set the true solution at time t=0 to be our initial profile.
78+
un = utrue(xpts)
79+
unpo = np.zeros((n,1))
80+
B = np.zeros((n,n))
81+
82+
83+
# Create the tridiagonal coefficient matrix for the basis functions assuming non-equal spacing
84+
for i in range(1,n-1):
85+
B[i,i-1] = - v/2. - k/dxs[i-1]
86+
B[i,i ] = k*(1./dxs[i]+1./dxs[i-1])
87+
B[i,i+1] = + v/2. - k/dxs[i]
88+
B[0,0] = 1.0
89+
B[-1, -1] = 1.0
90+
91+
# Set the RHS
92+
# Use gaussian quadrature to integrate the right hand side w.r.t x
93+
RHS = [quadrature5(lambda p: phi[i](p)*g(p, k, v), xpts[i-1], xpts[i+1]) for i in range(1, len(xpts)-1)]
94+
#Set the boundary condiations
95+
RHS.insert(0, utrue(xpts[0]))
96+
RHS.append(utrue(xpts[-1]))
97+
98+
# Solve for the coefficients of each basis function
99+
coeff = LA.solve(B, RHS)
100+
101+
# Update the solution unpo
102+
unpo = np.sum([coeff[i]*np.array(map(phi[i],xpts)) for i in range(len(coeff))], 0)
103+
104+
# Calculate the error
105+
error = np.sum([(quadrature5(lambda p: utrue(p)*phi[i](p), xpts[i-1], xpts[i+1])-quadrature5(lambda p: coeff[i]*phi[i](p), xpts[i-1], xpts[i+1]))**2.*dxs[i-1] for i in range(1,len(xpts)-1)])
106+
107+
plt.plot(xpts, utrue(xpts), 'r')
108+
plt.plot(xpts, unpo)
109+
plt.show()
110+
print sqrt(error)

FEMTime.py

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# coding: utf-8
2+
__author__ = "Arwa Ashi and Tom Gresavage"
3+
import numpy as np
4+
import matplotlib.pyplot as plt
5+
from math import *
6+
from numpy import linalg as LA
7+
from random import *
8+
import math
9+
10+
def utrue(t, x):
11+
# Define the true solution
12+
return np.exp(-t)*np.cos(x)*np.sin(x)
13+
14+
def g(t, x, k, v):
15+
# Define the forcing function of utrue
16+
return np.exp(-t)*(2.*v*np.cos(2.*x) + (-1. + 4.*k)*np.sin(2.*x))/2.
17+
# return (2.*np.exp(x**(2./3.))*(k - 2.*k*x**(2./3.) + 3.*v*x))/(9.*x**(4./3.))
18+
19+
def linbasis(xj):
20+
'''
21+
Creates a linear basis from the 3-element list xj centered at the middle element
22+
'''
23+
def f(x):
24+
if xj[0] <= x <= xj[1]:
25+
return (x-xj[0])/(xj[1]-xj[0])
26+
elif xj[1] <= x <= xj[2]:
27+
return (xj[2]-x)/(xj[2]-xj[1])
28+
else:
29+
return 0.
30+
return f
31+
32+
def quadrature5(f, a, b):
33+
'''
34+
Calculate int_a^b f(x)dx using 5-point Gaussian Quadrature
35+
Print the result
36+
'''
37+
quad_x = [0., np.sqrt(5.-2.*np.sqrt(10./7.))/3., -np.sqrt(5.-2.*np.sqrt(10./7.))/3., np.sqrt(5.+2.*np.sqrt(10./7.))/3., -np.sqrt(5.+2.*np.sqrt(10./7.))/3.]
38+
quad_w = [128./225., (322.+13.*np.sqrt(70.))/900., (322.+13.*np.sqrt(70.))/900., (322.-13.*np.sqrt(70.))/900., (322.-13.*np.sqrt(70.))/900.]
39+
s_int = ((b-a)/2.)*np.sum([quad_w[j]*f(((b-a)/2.)*quad_x[j]+(a+b)/2.) for j in range(5)])
40+
return s_int
41+
42+
# Define a function to generate a set of basis functions for each x
43+
def genbasis(xpts):
44+
'''
45+
Creates a set of linear basis functions centered at each item in xpts
46+
'''
47+
48+
dx = np.diff(xpts)
49+
phi = list()
50+
for i in range(len(xpts)):
51+
if i == 0:
52+
phi.append(linbasis([xpts[i]-dx[i], xpts[i], xpts[i]+dx[i]]))
53+
elif i == len(xpts)-1:
54+
phi.append(linbasis([xpts[i]-dx[i-1], xpts[i], xpts[i]+dx[i-1]]))
55+
else:
56+
phi.append(linbasis(xpts[i-1:i+2]))
57+
return phi
58+
# Define the discretization of the problem.
59+
x0 = 1.0 # start of the grid
60+
xn = 10.0 # End of grid
61+
n = 100 # number of nodes on the grid
62+
dx = (xn-x0)/float(n) # Set a uniform grid spacing
63+
xpts = np.linspace(x0, xn, n)
64+
dxs = np.diff(xpts) # Calculate \Delta x if mesh is not uniform
65+
phi = genbasis(xpts) # Create basis function
66+
67+
# Define the temporal domain
68+
t0 = 0.
69+
tn = 3.
70+
timeSteps = 10
71+
dt = (tn-t0)/timeSteps
72+
saveEvery = 2
73+
74+
# Set the equation coefficients
75+
k = 3.0
76+
v = 1.
77+
78+
# Create variables to save the error at each iteration
79+
Error = []
80+
error = 0.0
81+
82+
# Set the true solution at time t=0 to be our initial profile.
83+
coeff = utrue(t0, xpts)
84+
unpo = np.zeros((n,1))
85+
B = np.zeros((n,n))
86+
87+
88+
# Create the tridiagonal coefficient matrix for the basis functions assuming non-equal spacing
89+
for i in range(1,n-1):
90+
B[i,i-1] = (- v/2. - k/dxs[i-1])*dt+dxs[i-1]/6.
91+
B[i,i ] = k*dt*(1./dxs[i]+1./dxs[i-1])+(dxs[i]+dxs[i-1])/3.
92+
B[i,i+1] = (+ v/2. - k/dxs[i])*dt+dxs[i]/6.
93+
B[0,0] = 1.0
94+
B[-1, -1] = 1.0
95+
96+
for b in range(timeSteps):
97+
# Set the iteration time
98+
tIter = t0+dt*b
99+
100+
# Set the RHS
101+
# Use gaussian quadrature to integrate the right hand side w.r.t. x
102+
RHS = [dxs[i-1]*coeff[i-1]/6.+(dxs[i]+dxs[i-1])*coeff[i]/3.+dxs[i]*coeff[i+1]/6.+dt*quadrature5(lambda p: phi[i](p)*g(tIter, p, k, v), xpts[i-1], xpts[i+1]) for i in range(1, len(xpts)-1)]
103+
104+
#Set the boundary condiations
105+
RHS.insert(0, utrue(tIter, xpts[0]))
106+
RHS.append(utrue(tIter, xpts[-1]))
107+
108+
# Solve for the coefficients of each basis function
109+
coeff = LA.solve(B, RHS)
110+
111+
# Update the solution unpo
112+
unpo = np.sum([coeff[i]*np.array(map(phi[i], xpts)) for i in range(len(coeff))], 1)
113+
114+
# Calculate the iteration error
115+
stepError = np.sum([(quadrature5(lambda p: utrue(tIter, p)*phi[i](p), xpts[i-1], xpts[i+1])-quadrature5(lambda p: coeff[i]*phi[i](p), xpts[i-1], xpts[i+1]))**2.*dxs[i-1] for i in range(1,len(xpts)-1)])
116+
error = error + stepError*dt
117+
118+
if (b%saveEvery==0):
119+
Error.append(error**0.5)
120+
plt.plot(xpts, utrue(tIter, xpts), 'r')
121+
plt.plot(xpts, unpo, 'b')
122+
print Error
123+
plt.show()

FEMTimeQuadBase.py

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# coding: utf-8
2+
__author__ = "Arwa Ashi and Tom Gresavage"
3+
import numpy as np
4+
import matplotlib.pyplot as plt
5+
from math import *
6+
from numpy import linalg as LA
7+
from random import *
8+
import math
9+
10+
def utrue(t, x):
11+
# Define the true solution
12+
return np.exp(-t)*np.cos(x)*np.sin(x)
13+
14+
def g(t, x, k, v):
15+
# Define the forcing function of utrue
16+
return np.exp(-t)*(2.*v*np.cos(2.*x) + (-1. + 4.*k)*np.sin(2.*x))/2.
17+
# return (2.*np.exp(x**(2./3.))*(k - 2.*k*x**(2./3.) + 3.*v*x))/(9.*x**(4./3.))
18+
19+
def quadbasis(xj):
20+
'''
21+
Creates a linear basis from the 3-element list xj centered at the middle element
22+
'''
23+
def f(x):
24+
if xj[0] <= x <= xj[2]:
25+
return (x*-xj[0])*(xj[2]-x)/((xj[1]-xj[0])*(xj[2]-xj[1]))
26+
else:
27+
return 0.
28+
return f
29+
30+
def quadrature5(f, a, b):
31+
'''
32+
Calculate int_a^b f(x)dx using 5-point Gaussian Quadrature
33+
Print the result
34+
'''
35+
quad_x = [0., np.sqrt(5.-2.*np.sqrt(10./7.))/3., -np.sqrt(5.-2.*np.sqrt(10./7.))/3., np.sqrt(5.+2.*np.sqrt(10./7.))/3., -np.sqrt(5.+2.*np.sqrt(10./7.))/3.]
36+
quad_w = [128./225., (322.+13.*np.sqrt(70))/900., (322.+13.*np.sqrt(70))/900., (322.-13.*np.sqrt(70))/900., (322.-13.*np.sqrt(70))/900.]
37+
s_int = ((b-a)/2.)*np.sum([quad_w[j]*f(((b-a)/2.)*quad_x[j]+(a+b)/2.) for j in range(5)])
38+
return s_int
39+
40+
# Define a function to generate a set of basis functions for each x
41+
def genbasis(xpts):
42+
'''
43+
Creates a set of basis functions centered at each item in xpts
44+
'''
45+
46+
'''
47+
The basis function (phi) must further discretize the space between each x (dxpts)
48+
This is because the solution will describe the space between each x
49+
'''
50+
dx = np.diff(xpts)
51+
dxpts = np.linspace(xpts[0], xpts[-1], 100)
52+
phi = list()
53+
y = list()
54+
for i in range(len(xpts)):
55+
if i == 0:
56+
phi.append(quadbasis([xpts[i]-dx[i],xpts[i], xpts[i]+dx[i]]))
57+
elif i == len(xpts)-1:
58+
phi.append(quadbasis([xpts[i]-dx[i-1],xpts[i], xpts[i]+dx[i-1]]))
59+
else:
60+
phi.append(quadbasis(xpts[i-1:i+2]))
61+
y.append(map(phi[i], dxpts))
62+
return dxpts, y, phi
63+
64+
# Define the discretization of the problem.
65+
x0 = 1.0 # start of the grid
66+
xn = 10.0 # End of grid
67+
n = 20 # number of nodes on the grid
68+
dx = (xn-x0)/float(n) # Set a uniform grid spacing
69+
xpts = np.linspace(x0, xn, n)
70+
dxs = np.diff(xpts) # Calculate \Delta x if mesh is not uniform
71+
t, y, phi = genbasis(xpts) # Create basis function
72+
73+
# Define the temporal domain
74+
t0 = 0.
75+
tn = 3.
76+
timeSteps = 10
77+
dt = (tn-t0)/timeSteps
78+
saveEvery = 2
79+
80+
# Set the equation coefficients
81+
k = 3.0
82+
v = 1.
83+
84+
# Convenience Coefficients
85+
alfa = v/2.0
86+
gamma = k/dx
87+
88+
# Create variables to save the error at each iteration
89+
Error = []
90+
error = 0.0
91+
92+
# Set the true solution at time t=0 to be our initial profile.
93+
coeff = utrue(t0, xpts)
94+
unpo = np.zeros((n,1))
95+
B = np.zeros((n,n))
96+
97+
98+
# Create the tridiagonal coefficient matrix for the basis functions assuming non-equal spacing
99+
for i in range(1,n-1):
100+
B[i,i-1] = (- v/6. - 2.*k/(3.*dxs[i-1]))*dt + dxs[i-1]/30.
101+
B[i,i ] = 4.*k*dt*(1./dxs[i] + 1./dxs[i-1])/3. + (dxs[i-1] - dxs[i])/5.
102+
B[i,i+1] = (+ v/6. + 2.*k/(3.*dxs[i]))*dt + dxs[i]/30.
103+
B[0,0] = 1.0
104+
B[-1, -1] = 1.0
105+
106+
for b in range(timeSteps):
107+
# Set the iteration time
108+
tIter = t0+dt*b
109+
110+
# Set the RHS
111+
# Use gaussian quadrature to integrate the right hand side w.r.t. x
112+
RHS = [dxs[i-1]*coeff[i-1]/30.+(dxs[i-1] - dxs[i])*coeff[i]/5.+dxs[i]*coeff[i+1]/30.+dt*quadrature5(lambda p: phi[i](p)*g(tIter, p, k, v), xpts[i-1], xpts[i+1]) for i in range(1, len(xpts)-1)]
113+
#Set the boundary condiations
114+
RHS.insert(0, utrue(tIter, xpts[0]))
115+
RHS.append(utrue(tIter, xpts[-1]))
116+
117+
# Solve for the coefficients of each basis function
118+
coeff = LA.solve(B, RHS)
119+
120+
# Update the solution unpo
121+
unpo = np.sum([coeff[i]*np.array(y[i]) for i in range(len(coeff))], 0)
122+
123+
# Calculate the iteration error
124+
stepError = np.sum([(quadrature5(lambda p: utrue(t,p), xpts[i-1], xpts[i+1])-quadrature5()*dx
125+
error = error + stepError*dt
126+
127+
if (b%saveEvery==0):
128+
Error.append(error**0.5)
129+
plt.plot(xpts, utrue(tIter, xpts), 'r')
130+
plt.plot(t, unpo, 'b')
131+
print Error
132+
plt.show()

0 commit comments

Comments
 (0)