Readme
Readme
Tutorial
Cheuk Lau
Febrary 5, 2014
Overview
The goal of this tutorial is not to provide a mathematically rigorous background
on the finite element method (FEM). For those interested in advanced FEM
topics and a deeper understanding of its mathematical background I would
direct you to a couple references:
1. Grossmann, Roos and Stynes, Numerical Treatment of Partial Differential
Equations, Springer.
2. Ern, Guermond, Theory and Practice of Finite Elements, Applied Mathematical Sciences, Vol. 159, Springer (2004).
The goals of this tutorial is to:
1. Explain the basic concepts of the finite element method (FEM).
2. Show how FEM is applied to solve a simple 1D partial differential equation (PDE).
3. Discuss the provided Matlab files.
The provided Matlab files may serve as a launching point for writing ones
own code to solve 1D FEM problems. Extending the code to multi-dimensions
follows the same priciples. A 2D FEM code will be published in the future.
Basic Idea
FEM is a numerical method for solving PDEs over a spatial domain. The
following steps make up the FEM:
1. Choose a test function to derive the weak form of your PDE.
2. Discretize your problem domain into elements.
3. Choose a shape function to interpolate your solution over each element.
4. Solve the resulting linear system using a chosen iterative method .
The best way to learn is by example so lets go through how to apply the FEM
to solve a simple 1D problem.
Simple 1D Problem
Problem Description
Consider the one-dimensional problem:
0
2
where:
a (x) = 1 + x
with boundary conditions:
u (0) = 1
u0 (2) = 3
Lets choosef such that the solution is:
2
u (x) = 1 + 3x + x (2 x) (2)
Inserting eqn 2 into eqn 1 gives:
f = 2 + 17x 13x2 + x3 (3)
Knowing the analytical solution for u (x) allows us to calculate error convergence
as a function of mesh size for code validation. As a side note, this is known as
the method of manufactured solutions (MMS).
v (0) = 0
selecting a test
a (x) u0 (x) v 0 (x) dxa (2) u0 (2) v (2)+a (0) u0 (0) v (0)+
0
u (x) v (x) dx =
f (x) v (x) dx
0
L (v) =
0
resulting in:
a (u, v) = L (v) (6)
The integrals in eqn 6 are performed using any standard numerical quadrature e.g., Gauss.
a
b
=
1
1
0
1
1
p (
x0 )
p (
x1 )
1, j = i
i, j = 0, 1
0, j =
6 i
1
1 0
1
=
1 1
0
a0
1
=
b0
1
a0
b0
4
p0 (
x) = 1 x
(9)
Then for p1 :
a1
b1
1
1 0
0
1 1
1
a1
0
=
b1
1
p1 (
x) = x
(10)
Eqns 9 and 10 are the left and right linear shape functions over the reference
element.
f d
x
M
X
wi f (
xi ) (11)
i=1
where {
xl } [0, 1] are the quadrature nodes and {wi } are the quadrature
weights. For simplicity, we will use a simple two-point Gaussian quadrature:
w1 = w2 = 0.5 (12)
1
1
1 = 0.5 , 2 = 0.5 + (13)
2 3
2 3
ref_quad.m
Input: none
Output:
ref_quad_pos: quadrature positions on the reference element.
5
quad_weights: quadrature weights.
Function:
Generates the two-point Gauss quadrature position and weights over
the reference element.
dof.m
Input:
num_edges: number of finite element edges over the physical domain.
Output:
dof_pos: the location of the degrees of freedom for each finite element.
Function:
Computes the location of the degrees of freedom for each finite element. For linear basis functions these are at the finite element edges.
eval_shape.m
Input:
ref_quad_pos: Gauss quadrature positions on the reference element.
Output:
ev: basis function (eqns 9 and 10) values at the Gauss quadrature
positions on the reference element.
Function:
Solves eqns 9 and 10 for the basis function values at the Gauss quadrature positions on the reference element:
1
= 0.789
f0 (1 ) = 1 0.5
2 3
1
f0 (2 ) = 1 0.5 +
= 0.211
2 3
1
f1 (1 ) = 0.5 = 0.211
2 3
1
f1 (2 ) = 0.5 + = 0.789
2 3
eval_dir_shape.m
Input: none
Output:
evder: the basis function derivative values at the Gauss quadrature
positions on the reference element.
Function:
Solves the derivatives of eqns 9 and 10 at the Gauss quadrature positions on the reference element. The derivative of f0 (eqn 9) is:
f00 (x) = 1
The derivative of f1 (eqn 10) is:
f10 (x) = 1
The derivative of fo and f1 at the two-point Gaussian quadrature
reference nodes are
f00 (1 ) = f00 (2 ) = 1
f10 (1 ) = f10 (2 ) = 1
act_quad.m
Input:
dof_pos: degrees of freedom positions over physical domain.
ref_quad_pos: Gauss quadrature positions on reference element.
num_edges: number of degrees of freedom over physical domain.
Output:
act_quad_pos: quadrature positions on each physical element.
Function:
Maps the quadrature positions from the reference element to each
physical element.
xi
-5
1
2
3
4
xi+1
1
2
3
4
6
glob_to_loc.m
Input:
num_edges: number of finite element edges.
Output:
loc_glob: this is a table of size number of elements 2. Each row
contains the left and right degrees of freedom index for the corresponding element. The first element in the table corresponds to the
leftmost degree of freedom. This element is negative to flag an essential boundary condition exists i.e., u (0) = 1. It is worth noting that
the last element corresponding to the rightmost degree of freedom
does not need to be flagged because it is a natural boundary condition. To better illustrate the loc_glob matrix consider the degrees
of freedom locations {x0 , x1 , x2 , ..., xN 1 , xN }. The global degrees of
freedom are numbered from left to right as {N, 1, 2, ..., N 1, (N + 1)}.
The table 1 shows loc_glob with six degrees of freedom. loc_glob
will be used later to assemble the right-hand vector of eqn 6 i.e.,
L (v).
compute_RHS_local.m
Input:
quad_weights: Gauss quadrature weights.
dof_pos: degrees of freedom positions.
act_quad_pos: quadrature positions mapped onto the physical domain.
ev: shape function values at quadrature positions on reference element.
num_edges: number of finite element edges.
Output:
8
RHS_local: this is a matrix of size number of elements 2. Each
row represents the numerical integration of each shape function over
the element using the Gauss quadrature. Recall the right-hand side
of the system i.e., eqn 6 is:
2
L (v) =
f (x) v (x) dx + 3a (2) v (2) (14)
0
f (x) (
x) d
x (xj+1 xj )
Fij = (xj+1 xj )
0
M
X
wl f (xj,l ) i (l ) (15)
l=1
compute_RHS_global.m
The input, output and function of RHS_global.m are:
Input:
RHS_local: local integrated contibution of the RHS integral in eqn
6 for each basis function over each element.
loc_glob: matrix of edge indices for each element.
num_edges: number of finite element edges.
Output:
RHS_global: this is a matrix of size number of elements 1. The
contributions from RHS_loc are added up for each degree of freedom
using loc_glob.
compute_stiff_local.m
Input:
dof_pos: location of degrees of freedom in physical domain.
quad_weights: two-point Gauss quadrature weights.
act_quad_pos: Gauss quadrature nodes on physical domain.
ev: shape function values at quadrature nodes on reference element.
evder: shape function derivative values at quadrature nodes on reference element.
num_edges: number of finite element edges.
Output:
9
stiff_local: this is a number of elements 9 matrix. Each row represents the 3 3 local stiffness matrix for each element. Recall the
left-hand side of the system we are solving for i.e., eqn 6:
2
a (x) u0 (x) v 0 (x) + u (x) v (x) dx (16)
a (u, v) =
0
a (x) l i d
x
Mj,il = (xj+1 xj )
Mj,il
M
X
0
0
1
wt a (xj,t ) l (t ) i (t ) (17)
(xj+1 xj )
t=1
compute_stiff_global
Input:
stiff_local: element-wise local stiffness matrices.
num_edges: number of finite element edges.
Output:
stiff_global: this is a number of elements number of elements matrix. It is the combination of the local stiffness matrices.
a_def.m
Defines a (x) given in eqn 1.
F_def.m
Defines f (x) given in eqn 3.
10
1
32