A FEM Alghorithm in Octave
A FEM Alghorithm in Octave
A FEM Alghorithm in Octave
net/publication/252865736
CITATIONS READS
0 305
1 author:
Andreas Stahel
Bern University of Applied Sciences
28 PUBLICATIONS 222 CITATIONS
SEE PROFILE
All content following this page was uploaded by Andreas Stahel on 01 October 2014.
Contents
1 Basic description of the problem 2
2 FEM commands 4
2.1 Reading the mesh information and generating meshes . . . . . . . . . . . . . . . . . 4
2.1.1 ReadMesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.2 ReadMeshTriangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.3 CreateRectMesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.4 CreateEasyMesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.5 CreateMeshTriangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.6 ShowMesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2 Setting up and solving the system of linear equations . . . . . . . . . . . . . . . . . . 6
2.2.1 Writing the function files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.2 FEMEquation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.3 FEMSolveSym . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.4 FEMEig . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.5 FEMValue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.6 FEMGradient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.7 FEMIntegrate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2.8 FindDOF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Visualization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.1 ShowSolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.2 ShowLevelCurves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.3 ShowVectorField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3.4 ShowSolutionMTV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4 Some function files for educational purposes . . . . . . . . . . . . . . . . . . . . . . . 12
4 Auxiliary programs 17
1
5 Examples 18
5.1 Demo 1: a first example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.2 Demo 2: parameter dependence and animation . . . . . . . . . . . . . . . . . . . . . 19
5.3 Demo 3: using function files only . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5.4 Demo 4: a bigger problem, evaluation of the solution, its gradient, eigenvalues and
eigenfunctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.5 Demo 5: using triangle and CuthillMcKee . . . . . . . . . . . . . . . . . . . . . . . . 26
5.6 Demo 6: using CreateMeshTriangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.7 Demo 7: eigenfunctions of circular membrane . . . . . . . . . . . . . . . . . . . . . . 27
5.8 Demo 8: computing a capacitance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.9 Demo 9: exact solution and convergence . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.10 Demo 10: potential flow problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.11 Demo 11: minimal surface problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
List of Figures 37
Bibliography 37
Index 38
div(a grad u) − b u = f in Ω
u = gD on Γ1 (1)
∂u
a ∂n = gN on Γ2
1
http://www.hta-bi.bfh.ch/~sha
2
http://www.mathsource.com
2
Creating, reading and visualizing a mesh
ReadMesh() reading mesh information from EasyMesh files
ReadMeshTriangle() reading mesh information from triangle files
CreateRectMesh() create a rectangular mesh
CreateEasyMesh() create a mesh by calling EasyMesh
CreateMeshTriangle() create a mesh by calling triangle
ShowMesh() visualize the mesh.
Creating and solving the system of linear equations, evaluate functions
FEMEquation() set up the system of linear equations
FEMSolveSym() solve the system of linear equations, banded symmetric solver
FEMEig() find eigenvalues and eigenfunctions
FEMValue() evaluate the solution and its gradient at given points
FEMGradient() evaluate the gradient at the nodes of the mesh
FEMIntegrate() integrate a function over the domain
Visualization of the solution
ShowSolution() visualize the solution with the help of Gnuplot
ShowLevelCurves() show the level curves of a function
ShowVectorField() visualize the gradient of the solution as vector field
ShowSolutionMTV() create an input file for plotmtv
Functions for education purposes
ReadMeshM() reading mesh information from EasyMesh files
ReadMeshTriangleM() reading mesh information from triangle files
ElementContribution() find element stiffness matrix and the element vector
ElementContributionEdge() find contribution of one edge
FEMEquationM() set up the system of linear equations
FEMSolve() solve the system of linear equations, full matrix
FEMValueM() evaluate the solution and its gradient at given points
ShowSolutionM() visualize the solution
Operations for symmetric, banded matrices
SBSolve() solve a system of linear equations
SBFactor() find the RT DR factorization
SBBacksub() use back-substitution to solve system of equations
SBEig() find a few of the smallest eigenvalues and eigenvectors
SBProd() multiply symmetric banded matrix with full matrix
FullToBand() convert a symmetric matrix to a banded matrix
BandToFull() convert a banded matrix to a symmetric matrix
BandToSparse() convert a banded matrix to a sparse matrix
3
2 FEM commands
A list of all commands is given in table 1. The following sections give short descriptions of each
command.
2.1.1 ReadMesh
If the mesh is generated by EasyMesh, then the files are read by the command ReadMesh() to make
the information available to Octave, i.e. read the variables nodes, elem und edges by calling
[nodes,elem,edges]=ReadMesh("test")
The directory of the files can be be given as part of the filename. The type of boundary conditions
have to be given in these mesh descriptions. Dirichlet conditions are of type 1 and Neumann
conditions of type 2. The on-line help on ReadMesh() gives some more information.
[nodes,elem,edges]=ReadMesh(filename);
the files filename.n filename.e filename.s are read
these files have to be generated first by ‘EasyMesh filename’
EasyMesh reads filename.d for the description of the domain
The boundary markers in filename.d lead to the following boundary conditions
1 leads to a Dirichlet condition
2 leads to a Neumann condition
nodes contains the x and y coordinates of the nodes and the material
type at each node, i.e. nodes =[x1,y1,m1;x2,y2,m2;...;xn,yn,mn]
elem contains the information about the elements
One row shows the numbers of the three nodes forming the element and
then the material type of the element
edges contains the information about the boundary segments
One row shows the numbers of the two nodes forming the segment and
then the boundary markers is shown (1=Dirichlet, 2=Neumann)
4
2.1.2 ReadMeshTriangle
If the mesh is generated by triangle, then the files are read by the command ReadMeshTriangle()
to make the information available to Octave, i.e. read the corresponding variables with the help of
[nodes,elem,edges]=ReadMeshTriangle("test.1")
One should definitely use CuthillMcKee to renumber the nodes, see ./demos/demo5.
2.1.3 CreateRectMesh
With the command CreateRectMesh() a rectangular mesh can be generated, without the help of
EasyMesh or triangle.
[...] = CreateRectMesh(...)
generate a rectangular mesh
[nodes,elem,edges] = CreateRectMesh(x,y,blow,bup,bleft,bright)
nodes elem edges contain the information on the mesh
2.1.4 CreateEasyMesh
If the domain to be meshed is enclosed by a simple curve, then the command CreateEasyMesh
can be used. The nodes forming the curve and the type of boundary conditions, together with the
typical length of the sides of the triangles and the filename, are given as input parameters. The
command generates an input file for EasyMesh and then calls EasyMesh, thus EasyMesh needs to
be installed for this to work. An example is shown in demos 8 and 10 .
[...] = CreateEasyMesh(...)
generate a mesh using EasyMesh
CreateEasyMesh(name,xy,len)
name the base filename: the file name.d will be generated
then EasyMesh will generate files name.* with the mesh
5
len vector with the typical length of triangle side at a point
if len is a scalar the same length will be used for all points
2.1.5 CreateMeshTriangle
If the domain to be meshed is enclosed by a simple curve, then the command CreateMeshTriangle
can be used. The nodes forming the curve and the type of boundary conditions, together with
the maximal area of the triangles and the filename, are given as input parameters. The command
generates an input file for triangle and then calls triangle, thus triangle needs to be installed for
this to work. In addition CuthillMcKee is called to assure a band structure of the resulting matrix.
Examples are shown in demos 6, 7, 8, 9 and 10 .
[...] = CreateMeshTriangle(...)
generate a mesh using triangle
[...] = CreateMeshTriangle(...)
generate a mesh using triangle
CreateMeshTriangle(name,xy,area)
name the base filename: the file name.poly will be generated
then triangle will generate files name.1.* with the mesh
2.1.6 ShowMesh
For a visual control of the mesh use ShowMesh(). With ShowMesh(nodes,elem) a temporary file
will be written to the disk and then Gnuplot is called to show the mesh.
6
2.2.1 Writing the function files
The examples in ./demos/* show different techniques to implement the functions.
To solve the boundary value problem (1) the functions a, b, f , gD and gN have to be given.
They can be given by one constant or by a vector of values at the nodes of the mesh. One can also
implement the functions in script files, as function files (‘*.m’) or as dynamically linked functions
(‘*.oct’). The function accept a matrix with x and y coordinates of points as arguments and return
a vector with the values of the function as result. As an example consider an implementation of
the function a(x, y) = 1 + x. Calling a([1,2;3,4;5,-6]) should return the answer [2;4;6] . The
code below has to be in a file a.m .
function res = a(xy)
[n,m]=size(xy);
res=zeros(n,1);
for k=1:n
res(k)=1+xy(k,1);
endfor
endfunction
A vectorized (faster) implementation of the same function is given by
function res = aVector(xy)
res=1 + xy(:,1);
endfunction
If the applications has to run as fast as possible, then an implementation as a dynamically linked
function should be considered. On good operating systems the command mkoctfile -s a.cc will
create a file a.oct using the input below. The speed improvement can be considerable. Below find
the file a.cc
#include <iostream.h>
#include <math.h>
#include <octave/oct.h>
#include <octave/parse.h>
7
2.2.2 FEMEquation
Once all functions and the mesh information are set up, then the system of linear equations can
be setup up by [A,b,n2d]=FEMEquation(nodes,elem,edges,’a’,’b’,’f’,’gD’,’gN’); to solve
the boundary value problem in equation (1).
• The functions a, b and f can be given as string with the function–name, as array of values
at the nodes or as one scalar value to be used on all nodes, i.e. constant coefficients.
• The boundary functions gD and gN can be given as string with the function–name or as a
constant scalar value.
The command will create a representation of the symmetric matrix in A and the RHS in the vector
b. The vector n2d shows the essential boundary conditions and numbers the actual degrees of
freedom of the system. Almost FEM problems solved with this package will require a call of
FEMEquation().
The on-line help on FEMEquation() gives more information, as shown below.
[A,b,n2d]=FEMEquation(nodes,elem,edges,’a’,’b’,’f’,’gD’,’gN’)
[A,b,n2d]=FEMEquation(nodes,elem,edges,aVec,bVec,fVec,’gD’,’gN’)
nodes elem edges describe the mesh
see ReadMesh() for the description of the format
’a’,’b’,’f’,’gD’,’gN’ are the names of the functions and coefficients
in the boundary value problem given below
the functions a, b and f may be given as constant scalar value
or as vector with the values of the function at the nodes
the functions gD and gN may be given as constant scalar value
The contributions of each element and edge are computed internally by this function. The function
files ElementContribution and ElementContributionEdge are not used.
2.2.3 FEMSolveSym
Once the equations are known they can be solve by u=FEMSolveSym(nodes,A,b,n2d,’gD’). The
vector u will contain the values of the function at the nodes. The on-line help shows more infor-
mation.
8
u=FEMSolveSym(nodes,A,b,n2d,gDFunc)
The source of FEMSolveSym is very simple. First the system of equations is solved by calling
SBSolve(), then the solution is supplemented with the values on the Dirichlet boundary for the
final solution vector u.
function u=FEMSolveSym(nodes,gMat,gVec,n2d,gDFunc)
if (nargin!=5)
help("FEMSolveSym"); usage("FEMSolveSym(nodes,A,b,n2d,gDFunc)");
endif
ug=-SBSolve(gMat,gVec);
n=length(n2d);
u=zeros(n,1);
for k=1:n
if n2d(k)>0
u(k) = ug(n2d(k));
else
if is_scalar(gDFunc) u(k) = gDFunc;
else u(k) = feval(gDFunc,nodes(k,1:2));
endif % scalar
endif
endfor
endfunction
If the matrix A is not given in banded symmetric form, then the command FEMSolve() can be
used instead. If possible FEMSolveSym() should be used, as it is considerably faster.
2.2.4 FEMEig
To determine eigenvalues λ and eigenfunctions u of the boundary value problem
div(a grad u) − b u = λ f u in Ω
u = 0 on Γ1 (2)
a ∂∂nu = 0 on Γ2
9
[...] = FEMEig (...)
determine eigenvalues and eigenfunctions for the given BVP
la = FEMEig(nodes,elem,edges,aFunc,bFunc,fFunc,eigVec,tol)
[la,ev] = FEMEig(nodes,elem,edges,aFunc,bFunc,fFunc,eigVec,tol)
The command will create the global stiffness matrix A and a mass matrix B and then call SBEig()
to solve the generalized eigenvalue problem A~v = λ B~v .
An example is given in demos 4 and 7.
2.2.5 FEMValue
To compute the value of the solution at a specific point or at multiple use FEMValue(). Calling the
function values=FEMValue(xy,nodes,elem,u,defaultvalue) returns the values of the linearly
interpolated solution at the points given in xy. It is considerably more efficient to call the function
once with multiple points in xy than to call it for each point separately. If a point is not in the
domain, then 0 is returned, unless defaultvalue is specified. There are certainly faster algorithms
than the one used here, but its it not extremely slow either.
If one also wishes to calculate the values of the gradient at the given points then one can call the
function with 2 output arguments, e.g. [values,grad]=FEMValue(xy,nodes,elem,u). Examples
are shown in demos 1, 2, 4, 7, 8 and 10.
2.2.6 FEMGradient
To compute the value of the gradient of a function at all nodes of the mesh use FEMGradient().
Calling grad=FEMGradient(nodes,elem,u) will determine the gradient of the function u at the
nodes. The function is constructed by linear interpolation, using the given values u at the nodes.
Then the gradient is computed on each element. For each node a weighted average of the gradient
on the neighboring elements is used. The weight is given by the angle of the element (triangle)
at the node. For evaluation at the nodes FEMGradient returns better results than FEMValue. An
example is shown in demo 7 .
10
2.2.7 FEMIntegrate
With the command integral=FEMIntegrate(nodes,elem,u) the linear interpolation of the func-
tion determined by u will be integrated over the domain, i.e. compute
ZZ
u dA
Ω
integral = FEMIntegrate(nodes,elem,’f’)
integral = FEMIntegrate(nodes,elem,fValues)
nodes elem describe the mesh
see ReadMesh() for the description of the format
’f’ is the name of the function to be integrated
fValues a vector with the values of the function at the nodes
2.2.8 FindDOF
The function file FindDOF determines the DOF (degrees of freedom) for the system at hand. It also
determines the correct numbering of the DOF. It is an internal function, called in FEMEquation and
FEMEquationM. The result is stored in a variable n2d, to be used in FEMSolveSym and FEMSolve.
There should be no need to call this function explicitly.
2.3 Visualization
2.3.1 ShowSolution
The computed solution can be graphed using Gnuplot using the command ShowSolution(). Its
syntax is self-explanatory.
ShowSolution(...)
shows a graph of a numerical solution of the PDE
ShowSolution(nodes,elem,u);
nodes, elem contain information about the mesh
see ReadMesh() for the description of the format
u contains the values of the solution at the nodes
To speed up the writing to the temporary file a dynamically linked function WriteSolution is
used. The source of ShowSolution is a function file. Examples are given in most demos.
2.3.2 ShowLevelCurves
The level curves of a computed function can be visualized by ShowLevelCurves(). Its syntax is
self-explanatory.
ShowLevelCurves(...)
shows level curves of a function on the mesh
11
ShowLevelCurves(nodes,elem,u,levels);
nodes, elem contain information about the mesh
see ReadMesh() for the description of the format
u contains the values of the solution at the nodes
level is a list of values for which the level curves are drawn
2.3.3 ShowVectorField
A vector field (e.g. a gradient field) can be visualized by the command ShowVectorField(). Its
syntax is self-explanatory.
ShowVectorField(...)
shows a vector field plot of a numerical solution of the PDE
ShowVectorField(nodes,vectors,factor)
nodes the coordinates of the points at which the vector field was computed
vectors components of the vectorfield at nodes
factor vector field is rescaled by this factor, if given
2.3.4 ShowSolutionMTV
If a visualization with the help of plotmtv is desired, then use ShowSolutionMTV(). This command
generates an input file to be displayed from a command line by plotmtv filename. The full power
of plotmtv is at your disposition.
[...] = ShowSolutionMTV (...)
generate the data to be plotted with plotmtv
ShowSolutionMTV(nodes,elem,u,’filename’)
nodes elem u describe the mesh and the solution
’filename’ is the name of the file to be used
The header of the file filename allows for some modifications of the output. For more information
consult the documentation of plotmtv.
12
• ElementContributionEdge
To compute the contribution of the RHS vector due to one line segment of the Neumann part
of the boundary call edgeVec=ElementContributionEdge(corners,gNFunc)
See also the on-line help on ElementContributionEdge
• FEMEquationM
This function file implements the same procedures as FEMEquation. It calls the above two
functions repeatedly. It returns a full matrix A and thus FEMSolve has to be used to solve
the system of equations.
• FEMSolve
This function serves the same purpose as FEMSolveSym, but for a full matrix. It is usually
not as fast.
• FEMValueM
This function serves the same purpose as FEMValue, but is considerably slower.
• ShowSolutionM, ShowVectorField
Display the solution or its gradient using Gnuplot.
A banded version of the LDLT factorization in [GoluVanLoan96] can be implemented. If the matrix
A is strictly positive definite, then the algorithm is known to be stable. If A is not positive definite,
then problems might occur, since no pivoting is done. The matrix A is positive definite if and only
if the diagonal matrix D is positive.
For a given matrix some of its smallest eigenvalues can be computed with an algorithm based
on inverse power iteration. Precise information on the numerical errors is provided. The code is
capable of finding eigenvalues of medium size matrices, where the standard command eig() of
Octave is either very slow or will fail.
13
3.2 Description of the commands
3.2.1 SBSolve
The basic factorization algorithm is implemented in SBSolve. The function can return the solution
of the system of linear equations, or the solution and the factorization of the original matrix.
Multiple sets of equations can be solved.
X=SBSolve(A,B)
[X,R]=SBSolve(A,B)
solves A X = B
B is a full matrix
To determine the inverse matrix A−1 one can use the command invA = SBSolve(A,eye(n));. Be
aware that calculating the inverse matrix is rarely a wise thing to do. Most often the inverse of a
banded matrix will loose the band structure. If many system of linear equations have to be solved
simultaneously, then use SBSolve(A,B) with a matrix B. If multiple systems need to be solved
sequentially, use SBFactor() and then SBBacksub for each system to be solved.
If the matrix A is strictly positive definite, then the algorithm is stable and one can expect the
solution to be as accurate as the condition number of A permits. If A is semidefinite, then large
errors might occur, since no pivoting is implemented in the code. The matrix is positive definite
if all eigenvalues are positive, this can be verified by inspection of the signs of the numbers in the
first column of R. The matrix is positive definite if the first column of the factorization matrix
R (use SBFactor()) contains positive numbers only. A description of the algorithm can be found
in [GoluVanLoan96] or [VarFem].
14
computational effort is in the factorization, this can be useful if many system of linear equations
have to be solved sequentially. If multiple system are to be solved simultaneously it is preferable
to use SBSolve(A,B) with a matrix B .
[...] = SBFactor(...)
find the R’DR factorization of a symmetric banded matrix
R=SBFactor(A)
[...] = SBBacksub(...)
using backsubstitution to return the solution of a system of linear equations
X=SBBacksub(R,B)
B is mxn
X is mxn
R is mxt
If there is interest in the classical Cholesky decomposition of the matrix A (i.e. A = R 0 · R) then
R can be computed by
rBand=SBFactor(A);
d=sqrt(rBand(:,1));
rBand(:,1)=ones(n,1);
r=triu(diag(d)*rBand)
The number of positive/negative numbers in the first column of R equals the number of posi-
tive/negative eigenvalues of A.
15
3.2.3 SBEig
For given symmetric matrices A and B the standard (resp. generalized) eigenvalue problem will
be solved, i.e.
A ~v = λ ~v resp. A ~v = λ B ~v
Using inverse power iteration a given number of the smallest (absolute value) eigenvalues if
a symmetric matrix A are computed. If needed the eigenvectors are also generated. A set of
initial vectors V have to be given. If those are already close to the eigenvectors, then the algo-
rithm will converge rather quickly. For a precise description and analysis consult [GoluVanLoan96]
or [VarFem].
[...] = SBEig(...)
find a few eigenvalues of the symmetric, banded matrix
inverse power iteration is used for the standard and generalized
eigenvalue problem
The algorithm is based on inverse power iteration with n independent vectors. The iteration will
proceed until the relative change of all eigenvalues is smaller than the given value of tol. This does
not guarantee that the relative error is smaller than tol. The initial guesses V for the eigenvectors
have to be linearly independent. The closer the initial guess is to the actual eigenvector, the faster
the algorithm will converge. The algorithm returns the n eigenvalues closest to 0 .
For the standard eigenvalue problem A ~v i = λi ~vi the eigenvectors ~vi will be orthonormal with
respect to the standard scalar product, i.e, h~v i , ~vj i = δi,j . For the generalized eigenvalue problem
A ~vi = λi B ~vi this translates to h~vi , B ~vj i = δi,j . The symmetric matrix B should be positive
definite. The columns of Ev can be used to restart the algorithm if higher accuracy is required.
The algorithm will return reliable estimates for the errors in the eigenvalues. The a posteriori
error estimate err is based on the residual ~r = A ~v − λ ~v and
where we use the normalization h~v , ~v i = 1. If one of the eigenvalues has to be computed with high
accuracy, the approximate value λ may be subtracted from the diagonal of the matrix. Then the
eigenvalue closest to zero of the modified matrix A − λ I can be computed, using the already com-
puted eigenvector. If the eigenvalue is isolated the algorithm will converge very quickly. This algo-
rithm is similar to the Rayleigh quotient iteration. A good description is given in [GoluVanLoan96].
16
If the eigenvalue closest to λ is denoted by λ i we have the improved estimate
k~rk2
|λ − λi | ≤ where gap = min{|λ − λj | : λj ∈ σ(A), j 6= i}
gap
It is very easy to implement this test in Octave. If the estimate is based on approximate values of
the eigenvalues, then the result is not as reliable as the previous one. Since the value of gap will
carry an approximation error. The situation is particularly bad if some eigenvalues are clustered.
For the generalized eigenvalue problem we use the residual ~r = A ~v − λ B ~v and the estimates
p h~r , B−1~ri
min |λ − λi | ≤ h~r , B−1~ri and |λ − λi | ≤
λi ∈σ(A) gap
with the normalization h~v , B ~v i = 1. The variable err will return the first of the above estimates.
The precise algorithm and proof of the above estimate is given in [VarFem].
3.2.4 SBProd
With this command a symmetric banded matrix can be multiplied with a full matrix.
[...] = SBProd(...)
multiplies a symmetric banded matrix with a matrix
X=SBProd(A,B)
4 Auxiliary programs
An essential part of a FEM solution to a boundary value problem is the generation of a mesh. The
package FEMoctave is building on external codes to generate the meshes.
• EasyMesh This code is available from a web site 5 or also from this author’s home page. The
original source is slightly modified.
– On the first few lines replace #define MAX_NODES 3000 by #define MAX_NODES 100000
to allow for meshes with more than 3000 nodes.
5
http://www-dinma.univ.trieste.it/~nirftc/research/easymesh/
17
– On the very last lines replace return 1 by return 0, otherwise the make command will
not do all of its job.
• triangle This is an excellent mesh generator by Jonathan Richard Shewchuk 6 . The source
is included with this package.
• CuthillKcKee The numbering of the nodes in a mesh generated by triangle will not lead to
a matrix with small bandwidth. The algorithm of Cuthill–McKee will improve this situation.
The code is included with this package or also available on the web site [www:sha].
5 Examples
There are a few examples distributed with this package. Find them in the subdirectories of
./demos . To run a demo change into the appropriate directory, run make, start Octave and
then use the script file demorun.m. Some of the demos require EasyMesh to generate the meshes,
which might have to be installed first. Most sample applications either use triangle or the mesh is
provided.
5 # number of points #
# Nodes which define the boundary #
0: 0 0 0.2 1
1: 5 0 0.2 1
2: 5 4 0.2 1
3: 0 4 0.2 1
# material marker #
4: 2 2 0 1 # material 1 #
4 # Number Boundary of segments #
0: 0 1 1 #Dirichlet
1: 1 2 2 #Neumann
2: 2 3 1 #Dirichlet
3: 3 0 2 #Neumann
The command EasyMesh test4 will then create the mesh. The coefficient functions are all given
as constants. The Octave script below will generate a graph of the solution.
clear
tic
[nodes,elem,edges]=ReadMesh("./test4");
readingtime=toc
6
http://www.cs.cmu.edu/~quake/triangle.html
18
tic
[A,b,n2d]=FEMEquation(nodes,elem,edges,1,0,-1,0,-1);
setuptime=toc
tic
u=FEMSolveSym(nodes,A,b,n2d,0);
solvetime=toc
tic
ShowSolution(nodes,elem,u)
graphtime=toc
octave:1> demorun
readingtime = 0.11547
setuptime = 0.12725
solvetime = 0.13990
graphtime = 0.067842
1.6
1.4
1.2
1
0.8
0.6
0.4
0.2
0
-0.2
4
3.5
3
2.5
0 2
1 1.5
2 1
3
4 0.5
50
The additional lines in demorun.m evaluate the function along a diagonal in the domain.
np=25;
xy=[linspace(0,5,np);linspace(0,4,np)]’;
[values,grad]=FEMValue(xy,nodes,elem,u)
and implemented in the script file demorun.m. The parameter par varies from −1 to 2 and the
script file creates a poor man’s animation with the help of Gnuplot.
19
page_screen_output=0;
global par;
clear f
function res = f(xy)
global par;
[n,m]=size(xy);
res=-1*ones(n,1)*par;
for k=1:max(size(xy))
if(xy(k,1)>2) res(k)=-1;endif
endfor
endfunction
[nodes,elem,edges]=ReadMesh("../demo1/test4");
gset zrange [-3:4]
for par=-1:0.1:2
[A,b,n2d]=FEMEquation(nodes,elem,edges,1,0,’f’,0,-1);
u=FEMSolveSym(nodes,A,b,n2d,0);
ShowSolution(nodes,elem,u)
res=[par,FEMValue([2,2],nodes,elem,u)];
printf("For lambda=%2.3f we find u(2,2)=%2.4f\n",res);
endfor
20
Since no dynamically linked libraries are used this is a rather slow method to solve the problem. But
for small meshes this is feasible nonetheless. The above computation leads to the global stiffness
matrix A and the vector b below.
A =
5.000 -2.000 0.000 -0.500 0.000 0.000 0.000 0.000 0.000
-2.000 5.000 -2.000 0.000 -0.500 0.000 0.000 0.000 0.000
0.000 -2.000 5.000 0.000 0.000 -0.500 0.000 0.000 0.000
-0.500 0.000 0.000 5.000 -2.000 0.000 -0.500 0.000 0.000
0.000 -0.500 0.000 -2.000 5.000 -2.000 0.000 -0.500 0.000
0.000 0.000 -0.500 0.000 -2.000 5.000 0.000 0.000 -0.500
0.000 0.000 0.000 -0.500 0.000 0.000 5.000 -2.000 0.000
0.000 0.000 0.000 0.000 -0.500 0.000 -2.000 5.000 -2.000
0.000 0.000 0.000 0.000 0.000 -0.500 0.000 -2.000 5.000
b’=
-0.125 -0.125 -0.125 -0.125 -0.125 -0.125 -0.125 -0.125 -0.125
The script demorun.m also computes the values of the solution along a diagonal of the rectangular
domain.
We may examine a single element stiffness matrices. To find the contributions from a triangular
element with corners at (0, 0, (1, 0) and (0, 1) use
[mat,vec]=ElementContribution([0,0;1,0;0,1],1,0,-1)
to obtain
mat = 1.00000 -0.50000 -0.50000
-0.50000 0.50000 0.00000
-0.50000 0.00000 0.50000
vec = -0.16667
-0.16667
-0.16667
A second problem
∆u = 0 in Ω
u = x +3y on ∂Ω
is solved in demorun2.m.
5.4 Demo 4: a bigger problem, evaluation of the solution, its gradient, eigen-
values and eigenfunctions
On an L–shaped domain Ω we consider the boundary value problem
∆u = 10 (x − y) in Ω
u = 0 on ∂Ω
The mesh is generated, such that it is finer at the inside corner. It consists of 2496 nodes, forming
4802 elements.
The codes in this demo use compiled functions for the coefficient function. Thus before launching
the FEM code one has to compile the function with the help of the make programm. Then the
script demorun.m shown below will compute the solution and create a few plots.
21
tic
[nodes,elem,edges]=ReadMesh("./Lshape");
NumberNodes=max(size(nodes))
readingtime=toc
tic
[A,b,n2d]=FEMEquation(nodes,elem,edges,’a’,0,’f’,0,0);
setuptime=toc
[dof,semiband]=size(A)
tic
u=FEMSolveSym(nodes,A,b,n2d,0);
solvetime=toc
figure(1);
tic
ShowSolution(nodes,elem,u)
graphtime=toc
ShowSolutionMTV(nodes,elem,u,’u.mtv’)
npoints=41;
x=linspace(-1,1,npoints);
y=linspace(1,-1,npoints);
xy=[x;y]’;
pause(3)
tic
values=FEMValue(xy,nodes,elem,u,0);
evaluatetime=toc
figure(2);
gset nokey
gset title "A section"
plot (x,values)
tic
[la,vec]=FEMEig(nodes,elem,edges,’a’ ,0,1,4,1e-4);
eigenvaluetime=toc
eigenvalues=la’
figure(3);
gset title "3rd eigenfunction"
ShowSolution(nodes,elem,vec(:,3))
gset title
# evaluate on a mesh
npoints=21;
xv=linspace(-1,1,npoints); yv=linspace(-1,1,npoints);
22
[xx,yy]=meshgrid(xv,yv);
xy=[xx(:),yy(:)];
figure(4);
ShowVectorField(xy,-grad)
octave:1> demorun
NumberNodes = 2496
readingtime = 0.26706
setuptime = 0.27529
dof = 2308
semiband = 133
solvetime = 0.63635
graphtime = 0.21737
evaluatetime = 0.018111
eigenvaluetime = 5.1880
eigenvalues = 9.6359 15.1744 19.6921 29.4253
This shows that we have a system with 2308 unknowns with a semi-bandwidth of 133. On a given
computer7 it takes 0.27 sec to read the mesh information, 0.28 sec to set up the equations and
0.6 sec to solve. The time to evaluate the solution along the diagonal from (−1, 1) to (1, −1) at
41 points is 0.02 sec. To find the first four eigenvalues 5 sec are used. The shape of the third
eigenfunction is plotted. The resulting graphs are shown in Figure 2.
Using the command plotmtv u.mtv & we can generate 3–d plots and level curves, as shown in
Figure 3.
7
A dual Pentium III 800MHz PC with 256KB cash per CPU and 256M RAM, running Linux
23
1
1
0.8
0.6
0.4
0.2 0.5
0
-0.2
-0.4
-0.6
-0.8
-1 0
1
0.5
1 0
0.5 -0.5
0 -0.5
-0.5
-1 -1
-1
-1 -0.5 0 0.5 1
3rd eigenfunction
1.5
A section
1
0.8
0.5
0.6
0
-0.5
0.4
-1
0.2
-1.5
-0.2
0.5
-1
-0.4
-0.5
-0.6
-0.5
0.5
-0.8
1 -1
-1
-1 -0.5 0 0.5 1
Figure 2: Solution of a PDE, the gradient vector field, a cross section and the third eigenfunction
24
1 0.171
0.0574 0.0574
0.285 0.171
0.398
0.2
0.626 0.5 85
12
0.51 98
0.0574
0.3
2
0.7
−0.0
562
39
0.171
0.62
0.285
74
0.7
05
39
6
0.
98
1
−0.1
17
0.3
0.
7
0.512 2
85 56
0.2 .0
0.398 −0 −0
0.285 .28
3
7
.1
0.171
−0
−0
3
−0
.28
.51
−0.624
−0
−0.0562
1
−0.397
8
.73
−0
−0.283
−0.0562
4
−0.62
−0.397
−0.511
−0.17
−0.17
−0.283
−0.738
24
.6
−0
1
.51
−0
−0.397
−0.0562
−0.283
−0.17
−1 −0.0562
−1 0 1
x
25
5.5 Demo 5: using triangle and CuthillMcKee
The mesh can be generated by triangle. The input file for the mesh in Figure 4 was generated
using the input file testA.poly shown below. Further documentation can be found on the home
page of triangle.
8
7
6
5
4
3 2
2
1
0
1.5
0
0.5 1
1
1.5
2 0.5
2.5
3
3.5
∆u = 0 for (x, y) ∈ Ω
u = x·y for (x, y) ∈ Γ
The exact solution is u(x, y) = x · y, thus we can compare the approximate solution and compute
the error.
# nodes
10 2 0 0
1 0 0
2 4 0
3 4 2
4 1 2
5 1 1
6 0 1
7 2 0.5
8 3 0.5
9 3 1.5
10 2 1.5
# segments
10 1
1 1 2 1
2 2 3 1
3 3 4 1
4 4 5 1
5 5 6 1
6 6 1 1
# hole
7 7 8 1
8 8 9 1
9 9 10 1
26
10 10 7 1
1
1 2.5 1
Then the command triangle -pqa0.03 testA.poly will generate the mesh. To reduce the com-
putation time it is important to use the utility CuthillMcKee to renumber the mesh. The structure
of nonzero elements is shown in Figure 5. This figure was generated by sparseplot("testA.1",1)
and sparseplot("testA.1") . For a larger sample problem 8 with a matrix of size 1422 the com-
putation time jumped from 0.38 sec to 84 sec as the bandwidth changed from 44 to 1398 .
20 20
40 40
60 60
80 80
100 100
120 120
140 140
160 160
180 180
20 40 60 80 100 120 140 160 180 20 40 60 80 100 120 140 160 180
CreateMeshTriangle("test",[0,0,1;1,0,2;1,1,1;0,1,1],0.01)
[nodes,elem,edges]=ReadMeshTriangle("./test.1");
ShowMesh(nodes,elem)
[A,b,n2d]=FEMEquation(nodes,elem,edges,1,0,1,0,1);
u=FEMSolveSym(nodes,A,b,n2d,0);
ShowSolution(nodes,elem,u)
where Ω ⊂ R2 is the disk with radius 1. The code below will compute four eigenvalues and
eigenfunctions, leading to Figure 6.
8
create the mesh by triangle -pqa0.003 testA.poly
27
R=1; % radius of circle
nR = 40 ; % number of divisions to create circle
area=0.004;
w=linspace(0,2*pi*(1-1/nR),nR); % angles of points on circle
xy=[R*cos(w);R*sin(w);ones(1,nR)]’;
CreateMeshTriangleQ("circle",xy,area)
[nodes,elem,edges]=ReadMeshTriangle("./circle.1");
[la,vec]=FEMEig(nodes,elem,edges,1,0,1,4,1e-6);
la=la’
figure(1);
ShowSolution(nodes,elem,vec(:,1))
figure(2);
vmin=min(vec(:,1)); vmax=max(vec(:,1));
ShowLevelCurves(nodes,elem,vec(:,1),linspace(vmin,vmax,11))
disp("Hit RETURN"); pause();
figure(1); ShowSolution(nodes,elem,vec(:,2))
figure(2); vmin=min(vec(:,2)); vmax=max(vec(:,2));
ShowLevelCurves(nodes,elem,vec(:,2),linspace(vmin,vmax,11))
disp("Hit RETURN"); pause();
figure(1); ShowSolution(nodes,elem,vec(:,4))
figure(2); vmin=min(vec(:,4)); vmax=max(vec(:,4));
ShowLevelCurves(nodes,elem,vec(:,4),linspace(vmin,vmax,11))
A separation of variable argument shows that the exact eigenvalues are given by
√
λ = zn,m = mth zero of Jn (r)
where Jn (r) are the Bessel functions of the first kind. The eigenfunctions are
n n
u(r, φ) = Jn (r/zn,m ) · cos( φ) and u(r, φ) = Jn (r/zn,m ) · sin( φ)
2π 2π
Thus we can compare the results of this code with the exact solution. Observe that for n ≥ 1√we
have eigenvalues of multiplicity 2. The table below identifies the first 20 eigenvalues (resp. λ)
computed by FEMoctave with the exact values z n,m .
√ 1 2 3 4 5 6 7 8 9 10
λ 2.4089 3.8365 3.8365 5.1393 5.1390 5.5226 6.3799 6.3802 7.0120 7.0122
zn,m 2.4048 3.8317 5.1356 5.5201 6.3802 7.0156
n 0 1 1 2 2 0 3 3 1 1
m 1 1 1 1 1 2 1 1 2 2
√ 11 12 13 14 15 16 17 18 19 20
λ 7.5826 7.5810 8.4047 8.4028 8.6384 8.7552 8.7555 9.7363 9.7307 9.9043
zn,m 7.5883 8.4172 8.6537 8.7715 9.7610 9.9361
n 4 4 2 2 0 5 5 3 3 6
m 1 1 2 2 3 1 1 2 2 1
For the second eigenfunction in Figure 6 we can compute and display the gradient field, shown
in Figure 7. First compute the first two eigenfunctions and define a regular grid on the circle.
28
1
0.5
1.2
1
0.8
0.6
0
0.4
0.2
0
1
0.5 -0.5
-1 0
-0.5
0 -0.5
0.5
1 -1
-1
-1 -0.5 0 0.5 1
0.8
0.6
1.5 0.4
1
0.5 0.2
0
0
-0.5
-1
-0.2
-1.5
1 -0.4
0.5
-1 0 -0.6
-0.5
0 -0.5
0.5 -0.8
1 -1
-1
-1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1
0.8
0.6
1.5 0.4
1
0.5 0.2
0
0
-0.5
-1
-0.2
-1.5
1 -0.4
0.5
-1 0 -0.6
-0.5
0 -0.5
0.5 -0.8
1 -1
-1
-1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1
29
[nodes,elem,edges]=ReadMeshTriangle("./circle.1");
[la,vec]=FEMEig(nodes,elem,edges,1,0,1,2,1e-6);
R=1;
nn=21; v=linspace(-R,R,nn);
[xx,yy]=meshgrid(v,v); xy=[xx(:),yy(:)];
• Compute values of the function and gradient on the grid, then show the solution.
• Compute the gradient at the nodes of the mesh, then evaluate the components with the help
of FEMValue and display the graph.
grad=FEMGradient(nodes,elem,vec(:,2));
g1=FEMValue(xy,nodes,elem,grad(:,1),0);
g2=FEMValue(xy,nodes,elem,grad(:,2),0);
ShowVectorField(xy,[g1’;g2’]’)
0.5
-0.5
-1
-1 -0.5 0 0.5 1
The command FEMIntegrate() allows to integrate functions over the meshed domain.
FEMIntegrate(nodes,elem,1)
FEMIntegrate(nodes,elem,vec(:,1))
FEMIntegrate(nodes,elem,vec(:,2))
FEMIntegrate(nodes,elem,vec(:,2).^2)
Leading to answers 3.1287 ≈ π (area of the circle), 1.4681 and 0.00043, the integrals of the first
and second eigenfunction. The last answer of 1.000 shows that the eigenfunction is normalized in
the L2 (Ω)–norm.
30
5.8 Demo 8: computing a capacitance
Consider a radially symmetric capacitor consisting of two symmetric, conducting plates of radius r.
The two conductors are 2 h apart. The setup is enclosed in a cylinder of radius R and height 2 H
(−H < y < H). By modeling only the upper half of the capacitor we find the following differential
equation for the voltage u (radius x, height y)
Between the two plates the field is expected to be homogeneous and this is confirmed by figures 8.
By computing the flux through the middle plain by
Z R Z r
∂u ∂u 1 π r2
ZZ
flux = dA = 2 π x dx ≈ 2 π x dx =
∂y 0 ∂y 0 h h
disk
we find the capacitance of this setup. If the setup would correspond to a perfect plane capacitor,
then the normalized flux should be 1. The configuration in the script demorunTriangle (shown
below) leads to the significantly different result of 1.5 . This illustrates that a capacitance with the
dimensions above can not be treated as an idealized plate capacitor.
clear *
r=1;
R=2.5;
global h=0.2;
H=0.5;
N=201;
area=0.0001;
CreateMeshTriangle("cap",xy,area)
[nodes,elem,edges]=ReadMeshTriangle("./cap.1");
31
endfunction
[A,b,n2d]=FEMEquation(nodes,elem,edges,’aF’,’zero’,’zero’,’volt’,’zero’);
u=FEMSolveSym(nodes,A,b,n2d,’volt’);
x=linspace(0,R,N);
y=0.0*ones(1,N);
[uVal,grad]=FEMValue([x;y]’,nodes,elem,u);
plot(x,grad(:,2))
# trapezoidal integration
flux=2*(x*grad(:,2)-x(1)*grad(1,2)/2-x(N)*grad(N,2)/2)*R/(N-1)*(h/r**2)
0.5
6
5
0.4
4
0.3
0.2
2
0.1 1
0
0
0 0.5 1 1.5 2 2.5 0 0.5 1 1.5 2 2.5
With the above code the triangles are of uniform size throughout the domain, but since the
solution varies only very little in the right part of the domain we are using too many triangles
there. By generating the mesh directly with triangle we can divide the domain in two sections
and generate larger triangles in the right part. This is done in the file capManual.poly, which is
the used as input for triangle. Consider the Makefile and demorunManual.m for details. The file
capManual2.poly describes the situation of a very thin conducting plate, the result will be closer
to an ideal capacitor.
The same problem is also solved by the script demorunEasyMesh.m, using a mesh generated by
EasyMesh.
32
-4
-5
-6
-7
log error
-8
-9
-10
-11
-12
-5 -4.5 -4 -3.5 -3 -2.5 -2 -1.5 -1
log h
6
- @ -
- -
- @ -
Φ=1 - @ - Φ=0
- -
- -
- -
-
We may introduce a velocity potential Φ(x, y). The velocity vector ~v is then given by
∂Φ
vx ∂x
~v = =− ∂Φ
vy ∂y
The flow is assumed to be uniform far away from the obstacle. Thus we set the potential to Φ = 1
(resp. Φ = 0) at the left (resp. right) end of the plates. Since the fluid can not flow through the
plates we know that the normal component of the velocity has to vanish at the upper and lower
boundary. The differential equation to be satisfied by Φ is
∆Φ = div (grad Φ) = 0
In Figure 11 the vector field for the velocity ~v is shown. The vector filed was computed with the
help of FEMValue(). Find the code in demorun2.m . With demorun.m and demorun3.m different
meshes are used.
33
2 0.6
0.55
1.5
0.5
0.45
1
0.4
0.35
0.5
0.3
0 0.25
0 1 2 3 4 5 1.7 1.8 1.9 2 2.1 2.2 2.3
Figure 11: Velocity field of a ideal fluid, full view and details
0.5
0.4
0.3
0.2
0.1
0
0 1 2 3 4 5
34
5.11 Demo 11: minimal surface problem
Let u(x, y) be the hight of a surface above the border of a 2-dimensional domain Ω is given by
a function g(x, y). Then the function u representing the surface of minimal with has to solve a
nonlinear PDE.
div( √ 1 2
grad u) = 0 in domain Ω
1+| grad u|
u = g along edge Γ = ∂Ω
This software is not directly capable of solvin linear problems, but a simple iteration will lead to
an approximation of the solution.
• start with an initial solution u0 (x, y) = 0
The code below implements the above algorithm for a square Ω and will lead to the result in
Figure 13.
if(!exist("square.1.node","file"))
xy=[1,0,1;0,1,1;-1,0,1;0,-1,1];
CreateMeshTriangle("square",xy,0.001)
endif
[nodes,elem,edges]=ReadMeshTriangle("square.1");
[A,b,n2d]=FEMEquation(nodes,elem,edges,1,0,0,’BC’,0);
u=FEMSolveSym(nodes,A,b,n2d,’BC’);
area0=FEMIntegrate(nodes,elem,1)
numit=5;
errors=zeros(numit,1);
areas=errors;
for it=1:numit
norm=FEMIntegrate(nodes,elem,u.^2);
ugrad=FEMGradient(nodes,elem,u);
coeff=sqrt(1+ugrad(:,1).^2+ugrad(:,2).^2);
areas(it)=FEMIntegrate(nodes,elem,coeff);
coeff=1./coeff;
uold=u;
[A,b,n2d]=FEMEquation(nodes,elem,edges,coeff,0,0,’BC’,0);
35
u=FEMSolveSym(nodes,A,b,n2d,’BC’);
errors(it)=FEMIntegrate(nodes,elem,(u-uold).^2);
endfor
[areas,errors]
figure(1);
ShowSolution(nodes,elem,u);
figure(2);
ShowSolution(nodes,elem,u-uold);
0.8
0.6
0.4
0.2
1
0.5
0 1
0.5
-0.5 0
-0.5
-1 -1
36
List of Figures
1 Solution of an elementary PDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2 Solution of a PDE, the gradient vector field, a cross section and the third eigenfunction 24
3 A plot of level curves, generated by plotmtv . . . . . . . . . . . . . . . . . . . . . . . 25
4 Solution on a structure with a hole . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5 The structure of the matrix before and after renumbering . . . . . . . . . . . . . . . 27
6 The first, second and fourth eigenfunction of a vibrating membrane . . . . . . . . . . 29
7 The gradient field of the second eigenfunction of a vibrating membrane . . . . . . . . 30
8 Voltage and vertical field in a capacitor . . . . . . . . . . . . . . . . . . . . . . . . . 32
9 Logarithmic plot of error versus typical length of triangle . . . . . . . . . . . . . . . 33
10 Fluid flow between two plates, the setup . . . . . . . . . . . . . . . . . . . . . . . . . 33
11 Velocity field of a ideal fluid, full view and details . . . . . . . . . . . . . . . . . . . . 34
12 Horizontal velocity along a horizontal straight line . . . . . . . . . . . . . . . . . . . 34
13 A minimal surface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
References
[GoluVanLoan96] G. Golub and C. Van Loan. Matrix Computations. Johns Hopkins University
Press, third edition, 1996.
[John87] C. Johnson. Numerical Solution of Partial Differential Equations by the Finite Element
Method. Cambridge University Press, 1987.
[Loga92] D. L. Logan. A First Course in the Finite Element Method. PWS–Kent, second edition,
1992.
[VarFem] A. Stahel. Calculus of Variations and Finite Elements. Lecture Notes used at HTA Biel,
2000.
37
Index
a posteriori estimate, 16 power iteration, inverse, 13, 16
factorization, 13
FEMEig, 9, 21, 27, 28
FEMEquation, 8, 19–21, 27, 31
FEMEquationM, 13, 21
FEMGradient, 10, 30
FEMIntegrate, 11, 30
FEMSolve, 9, 13, 21
FEMSolveSym, 8, 19–21, 27
FEMValue, 10, 19, 21, 30, 31
FEMValueM, 13
FindDOF, 11
function file, 7
function in script file, 7
function, dynamically linked, 7
matrix, inverse, 14
membrane, 27
minimal surface, 35
Neumann condition, 4
pivoting, 13, 14
plotmtv, 12, 23
positive definite, 13, 14
potential flow, 33
38
View publication stats