0% found this document useful (0 votes)
79 views138 pages

Non Homo

Rheolef is a programming environment that serves as a convenient laboratory for computations involving finite element methods. It is both a C++ library and a set of commands for unix shell programming, providing algorithms and data structures. The book details, step-by-step, how some simple and more complex problems can be solved, most of them in less than 20 lines of code.

Uploaded by

winsky123
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
79 views138 pages

Non Homo

Rheolef is a programming environment that serves as a convenient laboratory for computations involving finite element methods. It is both a C++ library and a set of commands for unix shell programming, providing algorithms and data structures. The book details, step-by-step, how some simple and more complex problems can be solved, most of them in less than 20 lines of code.

Uploaded by

winsky123
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 138

Ecient C++ nite element

computing with Rheolef


P. Saramito
version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Introduction
Rheolef is a programming environment that serves as a convenient laboratory for com-
putations involving nite element methods. Rheolef is both a C++ library and a set
of commands for unix shell programming, providing algorithms and data structures.
Algorithms refer to the most up-to-date ones: preconditioned sparse solvers for
linear systems, incompressible elasticity, Stokes and Navier-Stokes ows, char-
acteristic method for convection dominated heat problems, etc. Also nonlinear
generic algorithms such as xed point and damped Newton methods.
Data structures t the standard variational formulation concept: spaces, dis-
crete elds, bilinear forms are C++ types for variables, that can be combined in
any expressions, as you write it on the paper.
Combined together, as a Lego game, these bricks allows the user to solve most complex
nonlinear problems. This Book details, step by step, how some simple and more
complex problems can be solved, most of them in less than 20 lines of code. The
concision and readability of codes written with Rheolef is certainly a major keypoint
of this environment.
Classical features
Poisson problems in 1D 2D and 3D with P1 or P2 elements
Stokes problems in 2D and 3D, with Taylor-Hood P2-P1 or stabilized P1 bubble-
P1 elements
linear elasticity in 2D and 3D, with P1 and P2 elements, including the incom-
pressible and nearly incompressible elasticity
characteristic method for convection-difusion, time-dependent problems and
Navier-Stokes equations.
input and output in various le format for meshes generators and numerical data
visualization systems
Advanced features
auto-adaptive mesh based for 2D problems
axisymetric problems
multi-regions and non-constant coecients
nonlinear problems with either xed-point algorithms or a provided generic
damped Newton solver
3d stereo visualization
All examples presented along the present book are available in the example/ directory
of the rheolef source distribution: the directory where examples are available is given
by the following unix command:
rheolef-config --exampledir
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
2 Rheolef version 5.94 update 27 May 2011
Contacts
email [email protected]
home page http://www-ljk.imag.fr/membres/Pierre.Saramito/rheolef
Please send all comments and bug reports by electronic mail to
[email protected]
The Rheolef contributors
2010 Lara Abouorm: banded level set method for equations on surfaces.
2008-* Ibrahim Cheddadi: dicontinuous Galerkin method for transport problems.
2002-* Jocelyn Etienne: characteristic method for time-dependent problems.
2000 Nicolas Roquet: Initial versions of Stokes and Bingham ow solvers.
2000-* Pierre Saramito: Project leader: main developments and code maintainer.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
4 Rheolef version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Contents
I Getting started with simple problems 7
1 Introduction to rheolef 9
1.1 The model problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2 Approximation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3 File dirichlet.cc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.4 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.5 How to compile the code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.6 How to run the program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.7 How to extend the program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.8 Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2 Getting Started 17
2.1 Non-homogeneous Dirichlet conditions . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2 Non-homogeneous Neumann boundary conditions for I operator . . . . . . . . 20
2.3 The Robin boundary conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.4 Non-homogeneous Neumann boundary conditions for the Laplace operator . . . . . 24
II Fluids and solids computations 29
3 The linear elasticity and the Stokes problems 31
3.1 The linear elasticity problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.2 Computing the stress tensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.3 Mesh adaptation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.4 The Stokes problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.5 Computing the vorticity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.6 Computing the stream function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4 Nearly incompressible elasticity and the stabilized Stokes problems 51
4.1 The incompressible elasticity problem . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.2 The P
1
bubble element for the Stokes problem . . . . . . . . . . . . . . . . . . . . 54
4.3 The stabilized Stokes problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.4 Axisymetric geometries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5 Time-dependent problems 59
5.1 The heat equation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
6 Rheolef version 5.94 update 27 May 2011
5.2 The convection-diusion problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.3 The Navier-Stokes problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
III Advanced and highly nonlinear problems 75
6 Equation dened on a surface 77
6.1 Formulation on an explicit surface mesh . . . . . . . . . . . . . . . . . . . . . . . . 77
6.2 Building a surface mesh from level set . . . . . . . . . . . . . . . . . . . . . . . . . 79
6.3 Formulation based on the banded level-set method . . . . . . . . . . . . . . . . . . 80
7 Multi-regions and non-constant coecients problems 83
8 The p-laplacian problem 89
8.1 Problem statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
8.2 The xed-point algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
8.3 The Newton algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
8.4 The damped Newton algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
9 Error analysis and singularities 103
9.1 Error analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
9.2 Computing the Gradient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
9.3 Error analysis for the gradient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
9.4 A problem with singularity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
IV Technical appendices 115
A How to prepare a mesh ? 117
A.1 Bidimensionnal mesh with bamg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
A.2 Bidimensionnal mesh with gmsh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
A.3 Tridimensionnal mesh with gmsh . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
B GNU Free Documentation License 123
B.1 Applicability and Denitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
B.2 Verbatim Copying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
B.3 Copying in Quantity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
B.4 Modications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
B.5 Combining Documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
B.6 Collections of Documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
B.7 Aggregation With Independent Works . . . . . . . . . . . . . . . . . . . . . . . . . 127
B.8 Translation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
B.9 Termination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
B.10 Future Revisions of This License . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Part I
Getting started with simple
problems
7
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Chapter 1
Introduction to rheolef
rheolef provides build-in classes for solving some linear and non-linear partial dierential equa-
tions, based on the nite element method (see e.g. [1]). All example les presented along
the present manual are available in the examples/ directory of the rheolef distribution, e.g.
/usr/local/share/doc/rheolef/examples/. Please, replace the prex /usr/local by the suit-
able prex used for your installation, as returned by the command rheolef-config --prefix.
Before to run examples, please check your Rheolef installation with:
rheolef-config --check
1.1 The model problem
Let us consider the classical Poisson problem with homogeneous Dirichlet boundary conditions in
a domain bounded R
N
, N = 1, 2, 3:
(P): nd u, dened in such that:
u = 1 in
u = 0 on
The variational formulation of this problem expresses:
(VF): nd u H
1
0
() such that:
a(u, v) = m(1, v), v H
1
0
()
where the bilinear forms a(., .) and m(., .) are dened by
a(u, v) =
_

u.v dx, u, v H
1
0
()
m(u, v) =
_

uv dx, u, v L
2
()
The bilinear form a(., .) denes a scalar product in H
1
0
() and is related to the energy form. This
form is associated to the operator. The m(., .) is here the classical scalar product on L
2
(),
and is related to the mass form.
9
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
10 Rheolef version 5.94 update 27 May 2011
1.2 Approximation
Let us introduce a mesh T
h
of and the nite dimensional space X
h
of continuous picewise
polynomial functions.
X
h
= v H
1
(); v
/K
P
k
, K T
h

where k = 1 or 2. Let V
h
= X
h
H
1
0
() be the functions of X
h
that vanishes on the boundary of
: The approximate problem expresses:
(V F)
h
: nd u
h
V
h
such that:
a(u
h
, v
h
) = m(1, v
h
) v
h
V
h
By developping u
h
on a basis of V
h
, this problem reduces to a linear system.
The following C++ code implement this problem in the rheolef environment.
1.3 File dirichlet.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
int main(int argc, char**argv) {
geo omega (argv[1]);
space Xh (omega, argv[2]);
Xh.block ("boundary");
form a (Xh, Xh, "grad_grad");
form m (Xh, Xh, "mass");
field fh (Xh, 1);
field uh (Xh);
uh ["boundary"] = 0;
if (omega.dimension() < 3) {
ssk<Float> fact = ldlt(a.uu);
uh.u = fact.solve (m.uu*fh.u + m.ub*fh.b - a.ub*uh.b);
} else {
size_t max_iter = 10000;
Float tol = 1e-15;
uh.u = 0;
int status = pcg (a.uu, uh.u, m.uu*fh.u + m.ub*fh.b - a.ub*uh.b,
ic0(a.uu), max_iter, tol, &cerr);
}
cout << uh;
return 0;
}
1.4 Comments
This code applies for both one, two or three dimensional meshes and for both picewise linear or
quadratic nite element approximations. Four major classes are involved, namely: geo, space,
form and field.
Let us now comment the code, line by line.
geo omega (argv[1]);
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 11
This command get the rst unix command-line argument argv[1] as a mesh le name and store
the corresponding mesh in the variable omega.
space Xh (omega, argv[2]);
Build the nite element space Xh contains all the piecewise polynomial continuous functions. The
polynomial type is the second command-line arguments argv[2], and could be either P1 or P2.
Xh.block ("boundary");
The homgeneous Dirichlet conditions are declared on the boundary.
form a (Xh, Xh, "grad_grad");
The form a(., .) is the energy form.
form m (Xh, Xh, "mass");
The form m(., .) is the mass form.
field fh (Xh, 1);
The eld fh is initialized with constant value 1.
field uh (Xh);
The eld uh contains the the degrees of freedom.
uh ["boundary"] = 0;
Some degrees of freedom are prescribed as zero on the boundary.
Let (
i
)
0i<dim(X
h
)
be the basis of X
h
associated to the Lagrange nodes, i.e. the vertices of
the mesh for the P
1
approximation and the vertices and the middle of the edges for the P
2
approximation. The approximate solution u
h
expresses as a linear combination of the continuous
picewise polynomial functions (
i
):
u
h
=

i
u
i

i
Thus, the eld u
h
is completely represented by its coecients (u
i
). The coecients (u
i
) of this
combination are grouped into to sets: some have zero values, from the boundary condition and
are related to bloked coecients, and some others are unknown. Blocked coecients are stored
into the uh.b array while unknown one are stored into uh.u. Thus, the restriction of the bilinear
form a(., .) to X
h
X
h
can be conveniently represented by a block-matrix structure:
a(u
h
, v
h
) =
_
vh.u vh.b
_
_
a.uu a.ub
a.bu a.bb
__
uh.u
uh.b
_
This representation also applies for the restriction to X
h
X
h
of the mass form:
m(f
h
, v
h
) =
_
vh.u vh.b
_
_
m.uu m.ub
m.bu m.bb
__
fh.u
fh.b
_
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
12 Rheolef version 5.94 update 27 May 2011
Thus, the problem (V F)
h
writes now:
_
vh.u vh.b
_
_
a.uu a.ub
a.bu a.bb
__
uh.u
uh.b
_
=
_
vh.u vh.b
_
_
m.uu m.ub
m.bu m.bb
__
fh.u
fh.b
_
for any vh.u and where vh.b = 0.
After expansion, the problem reduces to nd uh.u such that:
a.uu uh.u = m.uu fh.u + m.ub fh.b a.ub uh.b
The LDL
t
factorization of the a.uu matrix is then performed:
ssk<Float> fact = ldlt(a.uu);
Then, the unkown part is solved:
uh.u = fact.solve(m.uu*fh.u + m.ub*fh.b - a.ub*uh.b);
When d > 3, an iterative strategy is prefered for solving the linear system:
uh.u = 0;
int status = pcg (a.uu, uh.u, m.uu*fh.u + m.ub*fh.b - a.ub*uh.b,
ic0(a.uu), max_iter, tol, &cerr);
The iterative algorithm is the conjugate gradient pcg, preconditionned by the incomplete Cfholeski
factorisation ic0. Finaly, the eld is printed to standard output:
cout << uh;
1.5 How to compile the code
First, create a Makefile as follow:
include $(shell rheolef-config --libdir)/rheolef/rheolef.mk
CXXFLAGS = $(INCLUDES_RHEOLEF)
LDLIBS = $(LIBS_RHEOLEF)
default: dirichlet
Then, enter:
make dirichlet
Now, your program, linked with rheolef, is ready to run on a mesh.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 13
1.6 How to run the program
Figure 1.1: Solution of the model problem for N = 2: (left) P
1
element; (right) P
2
element.
Enter the comands:
mkgeo_grid -t 10 -boundary > square.geo
geo square.geo
The rst command generates a simple 10x10 bidimensionnal mesh of =]0, 1[
2
and stores it in
the le square.geo. The second command shows the mesh. It uses mayavi visualization program
by default.
The next command performs the computation:
./dirichlet square.geo P1 | field -
The result is piped to the post-treatment, performed by the field command. The field command
reads this result on its standard input and presents it in a graphical form. A temporary le could
also be used to store the result, using the .field le format:
./dirichlet square.geo P1 > square.field
field square.field
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
14 Rheolef version 5.94 update 27 May 2011
Figure 1.2: Alternative representations of the solution of the model problem (N = 2 and the P
1
element): (left) in black-and-white; (right) in elevation and stereoscopic anagyph mode.
Also explore some graphic rendering modes (see Fig. 1.2):
field square.field -black-and-white
field square.field -gray
field square.field -elevation -nofill -stereo
The last command shows the solution in elevation and in stereoscopic anaglyph mode (see Fig. 1.4,
left). The anaglyph mode requires red-cyan glasses: red for the left eye and cyan for the right one,
as shown on Fig. 1.3.
Figure 1.3: Red-cyan anaglyph glasses for the stereoscopic visualization.
See http://en.wikipedia.org/wiki/Anaglyph image for more and
http://www.alpes-stereo.com/lunettes.html for how to nd anaglyphe red-cyan glasses.
Please, consults the corresponding unix manual page for more on field, geo and mkgeo grid:
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 15
man mkgeo_grid
man geo
man field
Turning to the P2 approximation simply writes:
./dirichlet square.geo P2 | field -
Fig. 1.1.right shows the result. Now, let us condider a mono-dimensional problem =]0, 1[:
mkgeo_grid -e 10 -boundary > line.geo
geo line.geo
./dirichlet line.geo P1 | field -
The rst command generates a subdivision containing ten edge elements. The last two lines show
the mesh and the solution via gnuplot visualization, respectively. Conversely, the P2 case writes:
./dirichlet line.geo P2 | field -
Figure 1.4: Solution of the model problem for N = 3 and the P
1
element : (left) mesh; (right)
isovalue, cut planes and stereo anaglyph renderings.
Finally, let us condider a three-dimensional problem =]0, 1[
3
. First, let us generate a mesh:
mkgeo_grid -T 10 -boundary > box.geo
geo box.geo
geo box.geo -stereo -full
geo box.geo -stereo -cut
The previous commands draw the mesh with all internal edges, stereoscopic anaglyph and then
with a cut inside the internal structure: a simple click on the central arrow draws the cut plane
normal vector or its origin, while the red square allows a translation.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
16 Rheolef version 5.94 update 27 May 2011
Then, we perform the computation and the visualization:
./dirichlet box.geo P1 > box.field
field box.field
The visualization presents an isosurface. Also here, you can interact with the cutting plane. Click
on IsoSurface in the left menu and change the value of the isosurface. Finally exit from the
visualization and explore the stereoscopic anaglyph mode (see Fig. 1.4, right):
field box.field -stereo
It is also possible to add a second IsoSurface or ScalarCutPlane module to this scene by using
the Visualize menu. After this exploration of the 3D visualisation capacities of our environment,
let us go back to the Dirichlet problem and perform the P2 approximation:
./dirichlet box.geo P2 | field -
Notices also that the one-dimensional exact solution writes:
u(x) =
x(1 x)
2
while the two-and three dimensional ones support a Fourier expansion (see e.g. [2], annex).
1.7 How to extend the program
A good unix command may check the validity of its arguments, and may have some default values.
These points are left to the reader as an exercice.
1.8 Limitations
When using the P
2
interpolation and some non-polygonal domains (i.e. curved boundaries), the
method works not optimaly: it converges in H
1
norm as h
3/2
instead of the optimal h
2
in the case
of polygonal domains. The optimal convergence requires the use of isoparametric P2 elements (i.e.
curved triangles): this will be a development in the future.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Chapter 2
Getting Started
The rst part of this book starts with the Dirichlet problem with homogeneous boundary condition:
this example is declined with details in dimension 1, 2 and 3, as a starting point to Rheolef.
Next chapters present various boundary conditions: for completeness, we treat non-homogeneous
Dirichlet, Neumann, and Robin boundary conditions for model problems. The last example
presents a special problem where the solution is dened up to a constant: the Neumann problem
for the Laplace operator.
This rst part can be viewed as a pedagogic preparation for more advanced applications, such as
Stokes and elasticity, that are treated in the second part of this book.
2.1 Non-homogeneous Dirichlet conditions
Formulation
We turn now to the case of a non-homogeneous Dirichlet boundary conditions. Let f H
1
()
and g H
1
2
(). The problem writes:
(P
2
)
h
nd u, dened in such that:
u = f in
u = g on
The variationnal formulation of this problem expresses:
(V F
2
) nd u V such that:
a(u, v) = m(f, v), v V
0
where
a(u, v) =
_

u.v dx
m(u, v) =
_

uv dx
V = v H
1
(); v
|
= g
V
0
= H
1
0
()
The computation of the right-hand side may be considered with attention since f is not a priori
piecewise polynomial.
17
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
18 Rheolef version 5.94 update 27 May 2011
Approximation
As usual, we introduce a mesh T
h
of and the nite dimensional space X
h
:
X
h
= v H
1
(); v
/K
P
k
, K T
h

Then, we introduce:
V
h
= v X
h
; v
|
=
h
(g)
V
0,h
= v X
h
; v
|
= 0
The approximate problem writes:
(V F
2
)
h
: nd u
h
V
h
such that:
a(u
h
, v
h
) = m(
h
(f), v
h
) v
h
V
0,h
Notices that the evaluation of the right-hand side is performed by remplacing f by its Lagrange in-
terpolation
h
(h) on , while the boundary condition g is remplaced by its Lagrange interpolation

h
(h) on .
Let us choose R
N
, N = 1, 2, 3 and
f(x) = N sin(
N

i=1
x
i
)
g(x) = sin(
N

i=1
x
i
)
This choice is convenient, since the exact solution is known:
u(x) = sin(
N

i=1
x
i
)
. The following C++ code implement this problem in the rheolef environment.
File dirichlet-nh.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
size_t N;
Float f (const point& x) { return 1.0*N*sin(x[0]+x[1]+x[2]); }
Float g (const point& x) { return sin(x[0]+x[1]+x[2]); }
int main(int argc, char**argv) {
geo omega (argv[1]);
N = omega.dimension();
space Vh (omega, argv[2]);
Vh.block ("boundary");
form a(Vh, Vh, "grad_grad");
form m(Vh, Vh, "mass");
field uh (Vh);
field fh = interpolate(Vh, f);
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 19
const domain& boundary = omega["boundary"];
space Wh (omega, boundary, argv[2]);
uh["boundary"] = interpolate(Wh, g);
if (omega.dimension() < 3) {
ssk<Float> fact = ldlt(a.uu);
uh.u = fact.solve (m.uu*fh.u + m.ub*fh.b - a.ub*uh.b);
} else {
size_t max_iter = 10000;
Float tol = 1e-15;
uh.u = 0;
int status = pcg (a.uu, uh.u, m.uu*fh.u + m.ub*fh.b - a.ub*uh.b,
ic0(a.uu), max_iter, tol, &cerr);
}
cout << uh;
return 0;
}
Comments
The code looks like the previous one, related to homogeneous boundary conditions. Let us com-
ments the changes. The class point describes the coordinates of a point (x
1
, . . . , x
N
) R
N
as a
N-uplet of Float. The Float type is usually a double. This type depends upon the rheolef con-
guration (see also Installing,,Congure options), and could represent some high precision oating
point class such as doubledouble (quadruple) or bigfloat (arbitrary).
field fh = interpolate(Vh,f);
This implements the Lagrange interpolation operator
h
(f).
space Wh (omega, omega["boundary"], argv[2]);
The space of picewise P
k
functions is builded. This space is suitable for the interpolation of g on
the boundary:
uh[boundary] = interpolate(Wh, g);
The values of the degrees of freedom related to the boundary are stored into the eld u, where
non-homogeneous Dirichlet conditions applies. The rest of the code is similar to the homogeneous
Dirichlet case.
2.1.1 How to run the program
First, compile the program:
make dirichlet-nh
Running the program is obtained from the homogeneous Dirichlet case, by remplacing dirichlet
by dirichlet-nh:
mkgeo_grid -e 10 -boundary > line.geo
./dirichlet-nh line.geo P1 | field -
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
20 Rheolef version 5.94 update 27 May 2011
for the bidimensional case:
mkgeo_grid -t 10 -boundary > square.geo
./dirichlet-nh square.geo P1 | field -
and for the tridimensional case:
mkgeo_grid -T 10 -boundary > box.geo
./dirichlet-nh box.geo P1 | field -mayavi -
Here, the P1 approximation can be remplaced by the P2 one, by modifying the command-line
argument.
2.2 Non-homogeneous Neumann boundary conditions for
I operator
Formulation
Let us show how to insert Neumann boundary conditions. Let f H
1
() and g H

1
2
().
The problem writes:
(P
3
)
h
: nd u, dened in such that:
u u = f in
u
n
= g on
The variationnal formulation of this problem expresses:
(V F
3
) nd u H
1
() such that:
a(u, v) = l(v), v V
0
where
a(u, v) =
_

uv dx +
_

u.v dx
l(v) = m(f, v) +m
b
(g, v)
m(f, v) =
_

fv dx
m
b
(g, v) =
_

gv ds
Approximation
As usual, we introduce a mesh T
h
of and the nite dimensional space X
h
:
X
h
= v H
1
(); v
/K
P
k
, K T
h

The approximate problem writes:


(V F
3
)
h
: nd u
h
X
h
such that:
a(u
h
, v
h
) = l
h
(v
h
) v
h
X
h
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 21
where
l
h
(v) = m(
h
f, v
h
) +m
b
(
h
g, v
h
)
The treatment of the right-hand side is similar to the case of the non-homogeneous Dirichlet
condition: the evaluation of the right-hand side is performed by remplacing f by its Lagrange
interpolation
h
f on , while the boundary condition g is remplaced by its Lagrange interpolation

h
g on .
Let us choose R
N
, N = 1, 2, 3 and
f(x) = 1 +
1
2N
N

i=1
x
i
(1 x
i
)
g(x) =
1
2N
This example is convenient, since the exact solution is known:
u(x) =
1
2N
N

i=1
x
i
(1 x
i
)
File neumann.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
size_t N;
Float f (const point& x) { return 1+(0.5/N)*(x[0]*(1-x[0])+x[1]*(1-x[1])+x[2]*(1-x[2])); }
Float g (const point& x) { return -0.5/N; }
int main(int argc, char**argv) {
geo omega (argv[1]);
N = omega.dimension();
space Vh (omega, argv[2]);
form m (Vh, Vh, "mass");
form a (Vh, Vh, "grad_grad");
a = a+m;
field fh = interpolate(Vh, f);
space Wh (omega, omega["boundary"], argv[2]);
field gh = interpolate(Wh, g);
form mb (Wh, Vh, "mass");
field uh(Vh);
if (omega.dimension() < 3) {
ssk<Float> fact = ldlt(a.uu);
uh.u = fact.solve(m.uu*fh.u + m.ub*fh.b + mb.uu*gh.u + mb.ub*gh.b - a.ub*uh.b);
} else {
size_t max_iter = 10000;
Float tol = 1e-15;
uh.u = 0;
int status = pcg (a.uu, uh.u, m.uu*fh.u + m.ub*fh.b + mb.uu*gh.u + mb.ub*gh.b - a.ub*uh.b,
ic0(a.uu), max_iter, tol, &cerr);
}
cout << uh;
return 0;
}
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
22 Rheolef version 5.94 update 27 May 2011
Comments
The code looks like the previous one. Let us comments the changes.
space Wh (omega, omega["boundary"], argv[2]);
field gh = interpolate(Wh, g);
The space W
h
of piecewise P
k
continuous functions dened on the boundary of is dened here.
Then, the Lagrange interpolation is performed on g.
form mb (Wh, Vh, "mass");
The form mb implements the restriction of the L
2
scalar product on W
h
.
uh.u = fact.solve(m.uu*fh.u + m.ub*fh.b + mb.uu*gh.u + mb.ub*gh.b - a.ub*uh.b);
The direct solver related to uh.u is called on the system:
_
a.uu a.ub
a.bu a.bb
__
uh.u
uh.b
_
=
_
m.uu m.ub
m.bu m.bb
__
fh.u
fh.b
_
+
_
mb.uu mb.ub
mb.bu mb.bb
__
gh.u
gh.b
_
Reduced to the uh.u component, this problem writes also:
a.uu*uh.u = m.uu*fh.u + m.ub*fh.b + mb.uu*gh.u + mb.ub*gh.b - a.ub*uh.b
Notices that uh.b has here a null size.
2.2.1 How to run the program
First, compile the program:
make neumann
Running the program is obtained from the homogeneous Dirichlet case, by remplacing dirichlet
by neumann.
2.3 The Robin boundary conditions
Formulation
Let g H
1
2
(). The problem writes:
(P
4
)
h
nd u, dened in such that:
u = 1 in
u
n
+u = g on
The variationnal formulation of this problem expresses:
(V F
4
) nd u H
1
() such that:
a(u, v) = l(v), v H
1
()
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 23
where
a(u, v) =
_

u.v dx +
_

uv ds
l(v) = m(1, v) +m
b
(g, v)
m(u, v) =
_

uv dx
m
b
(g, v) =
_

gv ds
Approximation
As usual, let
X
h
= v H
1
(); v
/K
P
k
, K T
h

The approximate problem writes:


(V F
4
)
h
: nd u
h
X
h
such that:
a(u
h
, v
h
) = l
h
(v
h
), v
h
X
h
where
l
h
(v
h
) = m(1, v
h
) +m
b
(
h
g, v
h
)
Notices that the evaluation of the right-hand side is performed by remplacing the boundary con-
dition g by its Lagrange interpolation
h
(h) on .
Let us choose =]0, 1[
N
, N = 1, 2, 3 and
g(x) =
1
2N
_
1 +
N

i=1
x
i
(1 x
i
)
_
This choice is convenient, since the exact solution is known:
u(x) =
1
2N
N

i=1
x
i
(1 x
i
)
The following C++ code implement this problem in the rheolef environment.
File robin.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
size_t N;
Float u_ex (const point& x) { return 0.5*(x[0]*(1-x[0]) + x[1]*(1-x[1]))/Float(N); }
Float g (const point& x) { return u_ex(x) - 0.5/N; }
int main(int argc, char**argv) {
geo omega (argv[1]);
N = omega.dimension();
domain boundary = omega["boundary"];
space Xh (omega, argv[2]);
space Wh (omega, boundary, argv[2]);
form a (Xh, Xh, "grad_grad");
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
24 Rheolef version 5.94 update 27 May 2011
form ab (Xh, Xh, "mass", boundary);
a = a + ab;
form m (Xh, Xh, "mass");
form mb (Wh, Xh, "mass") ;
field fh (Xh, 1);
field gh = interpolate(Wh, g);
field uh (Xh);
if (omega.dimension() < 3) {
ssk<Float> fact = ldlt(a.uu);
uh.u = fact.solve(m.uu*fh.u + m.ub*fh.b + mb.uu*gh.u + mb.ub*gh.b - a.ub*uh.b);
} else {
size_t max_iter = 10000;
Float tol = 1e-15;
uh.u = 0;
int status = pcg (a.uu, uh.u, m.uu*fh.u + m.ub*fh.b + mb.uu*gh.u + mb.ub*gh.b - a.ub*uh.b,
ic0(a.uu), max_iter, tol, &cerr);
}
cout << uh;
return 0;
}
Comments
The code looks like the previous one. Let us comments the changes.
form ab (Xh, Xh, "mass", boundary);
a = a + ab;
The boundary contribution to the a(., .) form on X
h
X
h
is introduced.
Notices that the exact solution is a second-order polynomial. Thus, the P
2
approximation furnishes
the exact solution, up to the machine precision.
2.3.1 How to run the program
First, compile the program:
make robin
Running the program is obtained from the homogeneous Dirichlet case, by remplacing dirichlet
by robin.
2.4 Non-homogeneous Neumann boundary conditions for
the Laplace operator
Formulation
Let f L
2
() and g H
1
2
() satisfying the following compatibility condition:
_

f dx +
_

g ds = 0
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 25
The problem writes:
(P
5
)
h
: nd u, dened in such that:
u = f in
u
n
= g on
Since this problem only involves the derivatives of u, it is clear that its solution is never unique [3,
p. 11]. A discrete version of this problem could be solved iterative by the conjugate gradient or the
MINRES algorithm [4]. In order to solve it by a direct method, we turn the dicuty by seeking
u in the following space
V = v H
1
(); b(v, 1) = 0
where
b(v, ) =
_

v dx, v L
2
(), R
The variationnal formulation of this problem expresses:
(V F
5
): nd u V such that:
a(u, v) = l(v), v V
where
a(u, v) =
_

u.v dx
l(v) = m(f, v) +m
b
(g, v)
m(f, v) =
_

fv dx
m
b
(g, v) =
_

gv ds
Since the direct discretization of the space V is not an obvious task, the constraint b(u, 1) = 0
is enforced by a lagrange multiplier R. Let us introduce the Lagrangian, dened for all
v H
1
() and R by:
L(v, ) =
1
2
a(v, v) +b(v, ) l(v)
The saddle point (u, ) H
1
() R of this lagrangian is characterized as the unique solution of:
a(u, v) +b(v, ) = l(v), v H
1
()
b(u, ) = 0, R
It is clear that if (u, ) is solution of this problem, then u V and u is a solution of (V F
5
).
Conversely, let u V the solution of (V F
5
). Choosing v = v
0
where v
0
(x) = 1, x leads to
meas() = l(v
0
). From the denition of l(.) and the compatibility condition between the data f
and g, we get = 0. Notice that the saddle point problem extends to the case when f and g does
not saties the compatibility condition, and in that case = l(v
0
)/meas().
Approximation
As usual, we introduce a mesh T
h
of and the nite dimensional space X
h
:
X
h
= v H
1
(); v
/K
P
k
, K T
h

The approximate problem writes:


(V F
5
)
h
: nd (u
h
,
h
) X
h
R such that:
a(u
h
, v) +b(v,
h
) = l
h
(v), v X
h
b(u
h
, ) = 0, R
where
l
h
(v) = m(
h
f, v
h
) +m
b
(
h
g, v
h
)
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
26 Rheolef version 5.94 update 27 May 2011
File neumann-laplace.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
#include "neumann-laplace-assembly.h"
size_t N;
Float f (const point& x) { return 1; }
Float g (const point& x) { return -0.5/N; }
int main(int argc, char**argv) {
geo omega (argv[1]);
N = omega.dimension();
space Xh (omega, argv[2]);
form m (Xh, Xh, "mass");
form a (Xh, Xh, "grad_grad");
field b = m*field(Xh,1.0);
csr<Float> A = neumann_laplace_assembly (a.uu, b.u);
field fh = interpolate(Xh, f);
space Wh (omega, omega["boundary"], argv[2]);
field gh = interpolate(Wh, g);
form mb (Wh, Xh, "mass");
field lh = m*fh + mb*gh;
vec<Float> L(lh.u.size()+1, 0.0);
for (size_t i = 0; i < L.size()-1; i++) L.at(i) = lh.u.at(i);
L.at(L.size()-1) = 0;
vec<Float> U (L.size());
ssk<Float> fact_A = ldlt(A);
U = fact_A.solve(L);
field uh(Xh);
for (size_t i = 0; i < U.size()-1; i++) uh.u.at(i) = U.at(i);
Float lambda = U.at(U.size()-1);
cout << setprecision(numeric_limits<Float>::digits10)
<< catchmark("u") << uh
<< catchmark("lambda") << lambda << endl;
}
Comments
Let R
N
, N = 1, 2, 3. We choose f(x) = 1 and g(x) = 1/(2N). This example is convenient,
since the exact solution is known:
u(x) =
1
12
+
1
2N
N

i=1
x
i
(1 x
i
)
The code looks like the previous ones. Let us comment the changes. The discrete bilinear form b
is computed as b
h
X
h
that interprets as a linear application from X
h
to R: b
h
(v
h
) = m(v
h
, 1).
Thus b
h
is computed as
field b = m*field(Xh,1.0);
where the discrete bilinear form m is identied to its matrix and field(Xh,1.0) is the constant
vector equal to 1. Let
/ =
_
a.uu trans(b.u)
b.u 0
_
, | =
_
uh.u
lambda
_
, L =
_
lh.u
0
_
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 27
The problem admits the following matrix form:
/ | = L
The matrix / is symetric and non-singular, but indenite : it admits eigenvalues that are eitehr
strictly positive or strictly negative. It can be factored in LDL
T
form:
csr<Float> A = neumann_laplace_assembly (a.uu, b.u);
ssk<Float> fact_A = ldlt(A);
The rest of the code is mostly standard. The statement
cout << setprecision(numeric_limits<Float>::digits10)
<< catchmark("u") << uh
<< catchmark("lambda") << lambda << endl;
writes the solution (u
h
, ) with full digit precision and labeled format, suitable for post-traitement,
visualization and error analysis. It remain to look at the / matrix assembly function.
File neumann-laplace-assembly.h
template <class T>
csr<T> neumann_laplace_assembly (const csr<T>& a, const vec<T>& b) {
size_t n = a.nrow();
asr<T> A (n+1, n+1);
Array<size_t>::const_iterator ia = a.ia().begin();
Array<size_t>::const_iterator ja = a.ja().begin();
typename Array<T>::const_iterator va = a.a().begin();
typename Array<T>::const_iterator vb = b.begin();
for (size_t i = 0; i < n; i++) {
for (size_t p = ia[i]; p < ia[i+1]; p++) {
A.entry(i,ja[p]) = va[p];
}
A.entry(i,n) = A.entry(n,i) = vb[i];
}
return csr<T>(A);
}
Comments
The function takes as input the a matrix in compressed sparse row format csr (see e.g. [5]), and
the b vector. It uses a temporary associative sparse row data structure asr for / that is converted
to csr at the end of the function.
2.4.1 How to run the program
As usual, enter:
make neumann-laplace
mkgeo_grid -t 10 -boundary > square.geo
./neumann-laplace square P1 | field -
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
28 Rheolef version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Part II
Fluids and solids computations
29
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Chapter 3
The linear elasticity and the
Stokes problems
3.1 The linear elasticity problem
Formulation
The total Cauchy stress tensor expresses:
(u) = div(u).I + 2D(u)
where and are the Lame coecients. Let us consider the elasticity problem for the embankment,
in =]0, 1[
N
, N = 2, 3. The problem writes:
(E): nd u = (u
0
, . . . , u
N1
), dened in , such that:
div (u) = f in ,
u
n
= 0 on
top

right
u = 0 on
left

bottom
,
u = 0 on
front

back
, when N = 3
where f = (0, 1) when N = 2 and f = (0, 0, 1) when N = 3. The lame coecients are assumed
to satisfy > 0 and + > 0. Since the problem is linear, we can suppose that = 1 without
any loss of generality.
x
2
x
1
left
right
bottom
top
front
x
1
x
0
bottom
right left
top
x
0
back
Figure 3.1: The boundary domains for the square and the cube.
31
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
32 Rheolef version 5.94 update 27 May 2011
In order to avoid mistakes with the C++ style indexation, we denote by (x
0
, . . . , x
N1
) the cartesian
coordinate system in R
N
.
For N = 2 we dene the boundaries:

left
= 0]0, 1[,
right
= 1]0, 1[

bottom
= ]0, 1[0,
top
= ]0, 1[1
and for N = 3:

back
= 0]0, 1[
2
,
front
= 1]0, 1[
2

left
= ]0, 1[0]0, 1[,
right
= ]0, 1[1]0, 1[

bottom
= ]0, 1[
2
0,
top
= ]0, 1[
2
1
These boundaries are represented on Fig. 3.1.
The variational formulation of this problem expresses:
(V FE): nd u V such that:
a(u, v) = m(f , v), v V,
where
a(u, v) =
_

div udiv v dx +
_

2D(u) : D(v) dx,


m(u, v) =
_

u.v dx,
V = v (H
1
())
2
; v = 0 on
left

bottom
, when N = 2
V = v (H
1
())
2
; v = 0 on
left

bottom

right

back
, when N = 3
Approximation
We introduce a mesh T
h
of and for k = 1, 2, the following nite dimensional spaces:
X
h
= v (H
1
())
N
; v
/K
(P
k
)
N
, K T
h
,
V
h
= X
h
V
The approximate problem writes:
(V FE)
h
: nd u
h
V
h
such that:
a(u
h
, v) = m(f , v
h
), v V
h
File embankment.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
#include "embankment.h"
int main(int argc, char**argv) {
const Float lambda = 1;
geo omega (argv[1]);
space Vh = embankment_space (omega, argv[2]);
field uh (Vh, 0.0), fh (Vh, 0.0);
fh [omega.dimension()-1] = -1.0;
form m (Vh, Vh, "mass");
form a1 (Vh, Vh, "div_div");
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 33
form a2 (Vh, Vh, "2D_D");
form a = lambda*a1 + a2;
if (omega.dimension() < 3) {
ssk<Float> fact = ldlt(a.uu);
uh.u = fact.solve (m.uu*fh.u + m.ub*fh.b - a.ub*uh.b);
} else {
size_t max_iter = 10000;
Float tol = 1e-15;
uh.u = 0;
int status = pcg (a.uu, uh.u, m.uu*fh.u + m.ub*fh.b - a.ub*uh.b,
ic0(a.uu), max_iter, tol, &cerr);
}
cout << catchmark("lambda") << lambda << endl
<< catchmark("u") << uh;
return 0;
}
File embankment.h
space embankment_space (const geo& omega_h, std::string approx) {
space Vh (omega_h, approx, "vector");
Vh.block("bottom"); Vh.block("left");
if (omega_h.dimension() == 3) {
Vh.block("right"); Vh.block("back");
}
return Vh;
}
Comments
The space is dened in a separate le embankment.h, for subsequent reusage:
space Vh (omega_h, "P2", "vector");
Note here the multi-components features for the velocity eld u. The boundary condition contain
a special case for tridimensionnal case. The right-hand-side f
h
represents the dimensionless gravity
forces, oriented on the vertical axis: the last component of f
h
is set to 1 as:
fh [omega_h.dimension()-1] = -1.0;
Finally, the parameter and the multi-eld result are printed, using mark labels, thanks to the
catchmark stream manipulator. Labels are convenient for post-processing purpose, as we will see
in the next paragraph.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
34 Rheolef version 5.94 update 27 May 2011
How to run the program
Figure 3.2: The linear elasticity for = 1 and N = 2 and N = 3: both wireframe and lled
surfaces ; stereoscopic anaglyph mode for 3D solutions.
We assume that the previous code is contained in the le embankment.cc. Compile the program
as usual (see page 12):
make embankment
and enter the comands:
mkgeo_grid -t 10 > square.geo
geo square.geo
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 35
The triangular mesh has four boundary domains, named left, right, top and bottom. Then,
enter:
./embankment square.geo P1 > square-P1.mfield
The previous command solves the problem for the corresponding mesh and writes the solution in
the multi-eld le format .mfield. Run the deformation vector eld visualization:
mfield square-P1.mfield -u -deformation
mfield square-P1.mfield -u -deformation -fill
Note the graphic options usage ; the unix manual for the mfield command is available as:
man mfield
The view is shown on Fig. 3.2. A specic eld can be also selected for a scalar visualization:
mfield -u0 square-P1.mfield | field -
mfield -u1 square-P1.mfield | field -
Next, perform a P
2
approximation of the solution:
./embankment square.geo P2 > square-P2.mfield
mfield -u square-P2.mfield -deformation
Finally, let us consider the three dimensional case
mkgeo_grid -T 10 > cube.geo
./embankment cube.geo P1 > cube-P1.mfield
mfield -u -deformation cube-P1.mfield -stereo
mfield -u -deformation cube-P1.mfield -stereo -fill
The two last commands show the solution in 3D stereoscopic anaglyph mode. The graphic is
represented on Fig. 3.2. The P
2
approximation writes:
./embankment cube.geo P2 > cube-P2.mfield
mfield -u -deformation cube-P2.mfield
3.2 Computing the stress tensor
Formulation and approximation
The following code computes the total Cauchy stress tensor, reading the Lame coecient and
the deformation eld u
h
from a .mfield le. Let us introduce:
T
h
=
h
(L
2
())
NN
;
h
=
T
h
and
h;ij/K
P
k1
, K T
h
, 1 i, j N
This computation expresses:
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
36 Rheolef version 5.94 update 27 May 2011
nd
h
such that:
m(
h
, ) = b(, u
h
), T
h
where
m(, ) =
_

: dx,
b(, u) =
_

div(u) tr dx +
_

2D(u) : dx,
tr =
N

i=1

ii
.
File stress.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
int main(int argc, char** argv) {
Float lambda;
field uh;
cin >> catchmark("lambda") >> lambda
>> catchmark("u") >> uh;
string approx = (uh.get_approx() == "P2") ? "P1d" : "P0";
space Th (uh.get_geo(), approx, "tensor");
space Xh (uh.get_geo(), approx);
form two_D (uh.get_space(), Th, "2D");
form div (uh.get_space(), Xh, "div");
form inv_mt (Th, Th, "inv_mass");
form inv_m (Xh, Xh, "inv_mass");
field q = inv_m*(div*uh);
field sh = inv_mt*(two_D*uh);
for (size_t i = 0; i < uh.dimension(); i++)
sh(i,i) += lambda*q;
cout << catchmark("s") << sh;
return 0;
}
Comments
First notice that this code applies for any deformation eld, and is not rectricted to our embank-
ment problem.
The P0 and P1d stands for the piecewise constant and picewise linear discontinuous approximations,
respectively. Since elements of T
h
are discontinuous accross interelement boundaries, the mass
operator is block-diagonal and can be inverted one time for all: this operation results in the
inv mass operator.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 37
How to run the program
Figure 3.3: The stress tensor visualization (linear elasticity = 1).
First, compile the program:
make stress
The visualization for the stress tensor as ellipes writes:
./stress < square-P1.mfield | mfield -s -tensor -proj -
Conversely, the 3D visualization bases on ellipsoides:
./stress < cube-P1.mfield | mfield -s -tensor -proj -
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
38 Rheolef version 5.94 update 27 May 2011
Figure 3.4: The
01
stress component (linear elasticity = 1): d = 2 (top) and d = 3 (bottom) ;
P
0
(left) and P
1
discontinuous approximation (right).
You can observe a discontinuous constant or piecewise linear representation of the approximate
stress component
00
(see Fig. 3.4):
./stress < square-P1.mfield | mfield -s01 - | field -
./stress < square-P2.mfield | mfield -s01 - | field -elevation -stereo -
Recall that the stress, as a derivative of the deformation, is P0 (resp. P1d) and discontinuous
when the deformation is P1 (resp. P2) and continuous. The approximate stress eld can be also
projected on a continuous piecewise linear space, using the -proj option:
./stress < square-P1.mfield | mfield -s01 - | field -proj -elevation -stereo -
./stress < square-P2.mfield | mfield -s01 - | field -proj -elevation -stereo -
The tridimensionnal case writes simply (see Fig. 3.4):
./stress < cube-P1.mfield | mfield -s01 - | field -stereo -
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 39
./stress < cube-P2.mfield | mfield -s01 - | field -stereo -fill -
and also the P1-projected versions write:
./stress < cube-P1.mfield | mfield -s01 - | field -proj -stereo -
./stress < cube-P2.mfield | mfield -s01 - | field -proj -stereo -
These operations can be repeated for each
ij
components and for both P1 and P2 approximation
of the deformation eld.
3.3 Mesh adaptation
The main principle of the auto-adaptive mesh writes [611]:
cin >> omega_h;
uh = solve(omega_h);
for (unsigned int i = 0; i < n; i++) {
ch = criteria(uh);
omega_h = adapt(ch);
uh = solve(omega_h);
}
The initial mesh is used to compute a rst solution. The adaptive loop compute an adaptive
criteria, denoted by ch, that depends upon the problem under consideration and the polynomial
approximation used. Then, a new mesh is generated, based on this critera. A second solution on
an adapted mesh can be constructed. The adaptation loop converges generaly in roughly 10 to 20
iterations.
Let us apply this principle to the elasticity problem.
File embankment-adapt-2d.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
#include "embankment.h"
field criteria(Float lambda, const field& uh) {
string approx = (uh.get_approx() == "P2") ? "P1d" : "P0";
if (approx == "P0") return sqrt(sqr(uh[0])+sqr(uh[1]));
space Th (uh.get_geo(), approx, "tensor");
space Xh (uh.get_geo(), approx);
form two_D (uh.get_space(), Th, "2D");
form div (uh.get_space(), Xh, "div");
form mt (Th, Th, "mass");
form m (Xh, Xh, "mass");
form inv_mt (Th, Th, "inv_mass");
form inv_m (Xh, Xh, "inv_mass");
field qh = inv_m*(div*uh);
field two_Duh = inv_mt*(two_D*uh);
return sqrt(lambda*sqr(qh) + sqr(field(two_Duh(0,0)))
+ sqr(field(two_Duh(1,1))) + 2*sqr(field(two_Duh(0,1))));
}
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
40 Rheolef version 5.94 update 27 May 2011
field solve(const geo& omega, const string& approx, Float lambda) {
space Vh = embankment_space(omega, approx);
field uh (Vh, 0.0), fh (Vh, 0.0);
fh[1] = -1.0;
form m (Vh, Vh, "mass");
form a1 (Vh, Vh, "div_div");
form a2 (Vh, Vh, "2D_D");
form a = lambda*a1 + a2;
ssk<Float> fact = ldlt(a.uu);
uh.u = fact.solve (m.uu*fh.u + m.ub*fh.b - a.ub*uh.b);
return uh;
}
int main(int argc, char**argv) {
const Float lambda = 1;
geo omega_h (argv[1]);
string approx = (argc > 2) ? argv[2] : "P1";
size_t n_adapt = (argc > 3) ? atoi(argv[3]) : 5;
adapt_option_type options;
options.hcoef = 1.1;
options.hmin = 0.004;
for (size_t i = 0; true; i++) {
field uh = solve(omega_h, approx, lambda);
orheostream o (omega_h.name(), "mfield");
o << catchmark("lambda") << lambda << endl
<< catchmark("u") << uh;
if (i == n_adapt) break;
field ch = criteria(lambda,uh);
omega_h = geo_adapt(ch, options);
omega_h.save();
}
}
Comments
The code works for both linear or quadratic approximations. Since there is not yet any available
anisotropic adaptive mesh generator in three dimension, we have specialized here the code for the
dimension two.
The criteria is here:
c
h
=
_
[u
h
[ when using P
1
((u
h
) : D(u
h
))
1/2
when using P
2
The adapt option type declaration is used by rheolef to send options to the mesh generator.
The hcoef parameter controls the edge length of the mesh: the smaller it is, the smaller the edges
of the mesh are. In our example, is set by default to one. Conversely, the hmin parameter controls
minimal edge length.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 41
How to run the program
Figure 3.5: Adapted meshes: the deformation visualization for P
1
and P
2
approximations.
The compilation command writes:
make embankment-adapt-2d
For a piecewise linear approximation:
mkgeo_grid -t 10 > square-P1.geo
./embankment-adapt-2d square-P1 P1 5
The code performs a loop of ve mesh adaptations: the corresponding meshes are stored in les,
from square-P1-1.geo.gz to square-P1-5.geo.gz, and the associated solutions in les, from
square-P1-1.mfield.gz to square-P1-5.mfield.gz. The additional .gz sux expresses that
the les are compressed using gzip.
geo square-P1-5.geo
mfield -u -deformation square-P1-5.mfield
Note that the .gz sux is assumed by the geo and the mfield commands. Enter the w key in
the graphic window: you will obtain the graphic shown on Fig.3.5.
For a piecewise quadratic approximation:
mkgeo_grid -t 10 > square-P2.geo
./embankment-adapt-2d square-P2 P2
Then, the visualization writes:
geo square-P2-5.geo
mfield -u -deformation square-P2-5.mfield
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
42 Rheolef version 5.94 update 27 May 2011
3.4 The Stokes problem
Formulation
Let us consider the Stokes problem for the driven cavity in =]0, 1[
N
, N = 2, 3. The problem
writes:
(S) nd u = (u
0
, . . . , u
N1
) and p dened in such that:
div(2D(u)) + p = 0 in ,
div u = 0 in ,
u = (1, 0) on
top
,
u = 0 on
left

right

bottom
,
u
0
n
=
u
1
n
= u
2
= 0 on
back

front
when N = 3,
where D(u) = (u +u
T
)/2. The boundaries are represented on Fig. 3.1, page 31.
The variational formulation of this problem expresses:
(V FS) nd u V(1) and p L
2
0
() such that:
a(u, v) + b(v, p) = 0, v V(0),
b(u, q) = 0, q L
2
0
(),
where
a(u, v) =
_

2D(u) : D(v) dx,


b(v, q) =
_

div(v) q dx.
V() = v (H
1
())
2
; v = 0 on
left

right

bottom
and v = (, 0) on
top
, when N = 2,
V() = v (H
1
())
3
; v = 0 on
left

right

bottom
,
v = (, 0, 0) on
top
and v
2
= 0 on
back

front
, when N = 3,
L
2
0
() = q L
2
();
_

q dx = 0.
Approximation
The Talor-Hood [12] nite element approximation of the Stokes problem is considered. We intro-
duce a mesh T
h
of and the following nite dimensional spaces:
X
h
= v (H
1
())
N
; v
/K
(P
2
)
N
, K T
h
,
V
h
() = X
h
V(),
Q
h
= q L
2
()) C
0
(

); q
/K
P
1
, K T
h
,
The approximate problem writes:
(V FS)
h
nd u
h
V
h
(1) and p Q
h
such that:
a(u
h
, v) + b(v, p
h
) = 0, v V
h
(0),
b(u
h
, q) = 0, q Q
h
.
(3.1)
File cavity.h
space cavity_space (const geo& omega_h, std::string approx) {
space Vh (omega_h, approx, "vector");
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 43
Vh.block("top"); Vh.block("bottom");
if (omega_h.dimension() == 3) {
Vh.block("back"); Vh.block("front");
Vh[1].block("left"); Vh[1].block("right");
} else {
Vh.block("left"); Vh.block("right");
}
return Vh;
}
field cavity_field (const space& Vh, Float alpha) {
field uh (Vh, 0.);
uh[0]["top"] = alpha;
if (Vh.dimension() == 3) { // set velocity=0 at corners
uh[0]["back"] = uh[0]["front"] = 0;
} else {
uh[0]["left"] = uh[0]["right"] = 0;
}
return uh;
}
File stokes-cavity.cc
#include "rheolef.h"
#include "rheolef/mixed_solver.h"
using namespace rheolef;
using namespace std;
#include "cavity.h"
#include "pcg_solver.h"
int main(int argc, char**argv) {
geo omega (argv[1]);
space Vh = cavity_space (omega, "P2");
space Qh (omega, "P1");
field uh = cavity_field (Vh, 1);
field ph (Qh, 0.);
form mp (Qh, Qh, "mass");
form a (Vh, Vh, "2D_D");
form b (Vh, Qh, "div"); b = -b;
int max_iter = 5000;
Float tol = 1e-15;
if (omega.dimension() < 3) {
int status = pcg_abtb (a.uu, b.uu, uh.u, ph.u, -(a.ub*uh.b), -(b.ub*uh.b),
ldlt(mp.uu), ldlt(a.uu), max_iter, tol, &cerr);
} else {
int status = pcg_abtb (a.uu, b.uu, uh.u, ph.u, -(a.ub*uh.b), -(b.ub*uh.b),
pcg_solver(mp.uu), pcg_solver(a.uu), max_iter, tol, &cerr);
}
cout << catchmark("u") << uh
<< catchmark("p") << ph;
return 0;
}
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
44 Rheolef version 5.94 update 27 May 2011
Comments
The spaces and boundary conditions and grouped in specic functions, dened in le cavity.h.
This le is suitable for a future reusage. Next, forms are dened as usual, in le
stokes-cavity.cc.
The problem admits the following matrix form:
_
a.uu trans(b.uu)
b.uu 0
__
uh.u
ph.u
_
=
_
a.ub uh.b
b.ub uh.b
_
An initial value for the pressure eld is provided:
field ph (Qh, 0);
This system is solved by the preconditioned conjugate gradient algorithm :
int status = pcg_abtb (a.uu, b.uu, uh.u, ph.u, -(a.ub*uh.b), -(b.ub*uh.b),
ldlt(mp.uu), ldlt(a.uu), max_iter, tol, &cerr);
The preconditioner is here the mass matrix mp.uu for the pressure: as showed in [13], the number of
iterations need by the conjugate gradient algorithm to reach a given precision is then independent
of the mesh size. For more details, see the Rheolef reference manual related to mixed solvers,
available e.g. via the unix command:
man mixed_solver
When d = 2, it is interessant to factorize both a.uu and the preconditionner mp.uu one time
for all the iterations: the arguments ldlt(mp.uu) and ldlt(a.uu) are passed to the pcg abtb
algorithm. When d = 3, it is preferable, for both computing time and memory occupation point
of view, to switch to an interative solver for subproblems related to a.uu and mp.uu:
int status = pcg_abtb (a.uu, b.uu, uh.u, ph.u, -(a.ub*uh.b), -(b.ub*uh.b),
pcg_solver(mp.uu), pcg_solver(a.uu), max_iter, tol, &cerr);
Finaly, the pcg solver class is a convenient wrapper class for the call to the pcg algorithm, used
for 3D problems. It uses the incomplete Choeski factorization preconditionner ic0.
File pcg solver.h
struct pcg_solver {
pcg_solver (const csr<Float>& a1) : a(a1), m(ic0(a1)) {}
vec<Float> solve (const vec<Float>& b) const {
size_t max_iter = 10000;
Float tol = 1e-15;
vec<Float> x (b.size(), 0.0);
int status = pcg (a, x, b, m, max_iter, tol);
return x;
}
csr<Float> a;
basic_ic0<Float> m;
};
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 45
How to run the program
Figure 3.6: The velocity visualization for N = 2 and N = 3 with stereo anaglyph.
We assume that the previous code is contained in the le stokes-cavity.cc. Then, compile the
program as usual (see page 12):
make stokes-cavity
and enter the comands:
mkgeo_grid -t 10 > square.geo
./stokes-cavity square > cavity2d.mfield
The previous command solves the problem for the corresponding mesh and writes the solution in
the multi-eld le format .mfield. Run the velocity vector visualization :
mfield cavity2d.mfield -u -velocity
Run also some scalar visualizations:
mfield cavity2d.mfield -u0 | field -
mfield cavity2d.mfield -u1 | field -
mfield cavity2d.mfield -p | field -
Next, perform another computation on a ner mesh:
mkgeo_grid -t 20 > square-fine.geo
./stokes-cavity square-fine.geo > cavity2d-fine.mfield
and observe the convergence.
Finally, let us consider the three dimensional case:
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
46 Rheolef version 5.94 update 27 May 2011
mkgeo_grid -T 5 > cube.geo
./stokes-cavity cube.geo > cavity3d.mfield
and the corresponding visualization:
mfield cavity3d.mfield -u -velocity -stereo
mfield cavity3d.mfield -u0 | field -
mfield cavity3d.mfield -u1 | field -
mfield cavity3d.mfield -u2 | field -
mfield cavity3d.mfield -p | field -
3.5 Computing the vorticity
Formulation and approximation
When N = 2, we dene [3, page 30] for any distributions and v:
curl =
_

x
1
,

x
0
_
,
curl v =
v
1
x
0

v
0
x
1
,
and when N = 3:
curl v =
_
v
2
x
1

v
1
x
2
,
v
0
x
2

v
2
x
0
,
v
1
x
0

v
0
x
1
_
Let u be the solution of the Stokes problem (S). The vorticity is dened by:
= curl u when N = 2,
= curl u when N = 3.
Since the approximation of the velocity is piecewise quadratic, we are looking for a discontinuous
piecewise linear vorticity eld that belongs to:
Y
h
= L
2
();
/K
P
1
, K T
h
, when N = 2
Y
h
= (L
2
())
3
;
i/K
P
1
, K T
h
, when N = 3
The approximate variational formulation writes:

h
Y
h
,
_

h
dx =
_

curl u
h
dx, Y
h
when N = 2,
Y
h
,
_

h
. dx =
_

curl u
h
. dx, Y
h
when N = 3.
File vorticity.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
int main(int argc, char** argv) {
field uh;
cin >> uh;
string option = (uh.n_component() == 3) ? "vector" : "scalar";
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 47
space Lh (uh.get_geo(), "P1d", option);
form curl (uh.get_space(), Lh, "curl");
form inv_m (Lh, Lh, "inv_mass");
cout << catchmark("w") << inv_m*(curl*uh);
return 0;
}
How to run the program
Figure 3.7: The vorticity: elevation view for N = 2 and vector representation for N = 3 (with
anaglyph).
For N = 2, just enter:
make vorticity
./vorticity < cavity2d.mfield | field -evelavtion -stereo -
and you observe a discontinuous piecewise linear representation of the approximate vorticity. The
approximate vorticity eld can also be projected on a continuous piecewise linear space, using the
-proj option (See Fig. 3.7 left):
./vorticity < cavity2d.mfield | field -proj -
./vorticity < cavity2d.mfield | \
field -proj -elevation -scale 2 -stereo -nofill -
For N = 3, the whole vorticity vector can also be visualized (See Fig. 3.7 right):
./vorticity < cavity3d.mfield | \
mfield -proj -w -velocity -vscale 2 -stereo -
In the previous command, the -proj option has been used: since the 3D render has no support for
discontinuous picewise linear elds, the P1-discontinuous eld is transformed into a P1-continuous
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
48 Rheolef version 5.94 update 27 May 2011
one, thanks to a L
2
projection. P1 The following command shows the second component of the
vorticity vector, roughtly similar to the bidimensionnal case.
./vorticity < cavity3d.mfield | mfield -w1 - | field -
./vorticity < cavity3d.mfield | mfield -w1 - | field -proj -
3.6 Computing the stream function
Formulation and approximation
The stream function satises curl = u. When N = 2, the stream function is the solution of
the following problem [3, page 88]:
= curl u in ,
= 0 on .
and when N = 3, the stream function is a vector-valued eld that satises [3, page 90]:
= curl u in ,
= 0 on
back

front

top

bottom
,

n
= 0 on
left

right
.
File streamf-cavity.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
int main (int argc, char** argv) {
field wh;
cin >> wh;
string option = (wh.n_component() == 3) ? "vector" : "scalar";
space Ph (wh.get_geo(), "P2", option);
Ph.block("top"); Ph.block("bottom");
if (wh.dimension() == 3) {
Ph.block("back"); Ph.block("front");
} else {
Ph.block("left"); Ph.block("right");
}
form m (wh.get_space(), Ph, "mass");
form c (Ph, Ph, "grad_grad");
field psih (Ph, 0.);
ssk<Float> fact_c = ldlt(c.uu);
psih.u = fact_c.solve (m.uu*wh.u + m.ub*wh.b - c.ub*psih.b);
cout << catchmark("psi") << psih;
return 0;
}
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 49
How to run the program
Figure 3.8: The stream function visualization: isolines for N = 2, and combined vectors and
isonorm surface for N = 3.
For N = 2, just enter (see Fig. 3.8 left):
make streamf-cavity
./vorticity < cavity2d.mfield | ./streamf-cavity | field -black-and-white -
For N = 3, the second component of the stream function is showed by:
./vorticity < cavity3d.mfield | ./streamf-cavity | mfield -psi1 - | \
field -normal 0 1 0 -
The whole stream function vector can be visualized:
./vorticity < cavity3d.mfield | ./streamf-cavity | \
mfield -psi -velocity
The combined representation of Fig. 3.8.right has been obtained in three steps. First, enter:
./vorticity < cavity3d.mfield | ./streamf-cavity | mfield -psi1 - | \
field -normal 0 1 0 -noclean -noexecute -name psi1 -
This command creates a le psi1.vtk. Next, in the previous mayavi window associated to the
whole stream function, select the File/Load data/VTK file menu and load psi1.vtk. Finaly,
select the Vizualize/Module/IsoSurface menu. Observe that the 3D stream function is mainly
represented by its second component.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
50 Rheolef version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Chapter 4
Nearly incompressible elasticity
and the stabilized Stokes problems
4.1 The incompressible elasticity problem
Formulation
Let us go back to the linear elasticity problem.
When becomes large, this problem is related to the incompressible elasticity and cannot be
solved as it was previously done. To overcome this diculty, the pressure is introduced :
p = div u
and the problem becomes:
(E) nd u and p dened in such that:
div(2D(u)) + p = f in ,
div u
1

p = 0 in ,
+B.C.
The variational formulation of this problem expresses:
(V FE) nd u V (1) and p L
2
() such that:
a(u, v) + b(v, p) = m(f , v), v V (0),
b(u, q) c(p, q) = 0, q L
2
0
(),
where
m(u, v) =
_

u.v dx,
a(u, v) =
_

D(u) : D(v) dx,


b(v, q) =
_

div(v) q dx.
c(p, q) =
1

p q dx.
V = v (H
1
())
2
; v = 0 on
left

bottom

When becomes large, we obtain the incompressible elasticity problem, that coincides with the
Stokes problem.
51
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
52 Rheolef version 5.94 update 27 May 2011
Approximation
As for the Stokes problem, the Talor-Hood [12] nite element approximation is considered. We
introduce a mesh T
h
of and the following nite dimensional spaces:
X
h
= v (H
1
()); v
/K
(P
2
)
2
, K T
h
,
V
h
() = X
h
V,
Q
h
= q L
2
()) C
0
(

); q
/K
P
1
, K T
h
,
The approximate problem writes:
(V FE)
h
nd u
h
V
h
(1) and p Q
h
such that:
a(u
h
, v) + b(v, p
h
) = 0, v V
h
(0),
b(u
h
, q) c(p, q) = 0, q Q
h
.
File incompresible-elasticity.cc
#include "rheolef.h"
#include "rheolef/mixed_solver.h"
using namespace rheolef;
using namespace std;
#include "embankment.h"
#include "pcg_solver.h"
int main(int argc, char**argv) {
geo omega (argv[1]);
Float inv_lambda = (argc > 2 ? atof(argv[2]) : 0);
space Vh = embankment_space(omega, "P2");
space Qh (omega, "P1");
field uh (Vh,0.0), fh (Vh, 0.0);
fh [omega.dimension()-1] = -1.0;
field ph (Qh, 0.);
form mu (Vh, Vh, "mass");
form mp (Qh, Qh, "mass");
form a (Vh, Vh, "2D_D");
form b (Vh, Qh, "div"); b = -b;
form c = inv_lambda*mp;
int max_iter = 5000;
Float tol = 1e-15;
if (omega.dimension() < 3) {
int status = pcg_abtbc (a.uu, b.uu, c.uu, uh.u, ph.u, -(a.ub*uh.b) + (mu*fh).u,
-(b.ub*uh.b), ldlt(mp.uu), ldlt(a.uu), max_iter, tol, &cerr);
} else {
int status = pcg_abtbc (a.uu, b.uu, c.uu, uh.u, ph.u, -(a.ub*uh.b) + (mu*fh).u,
-(b.ub*uh.b), pcg_solver(mp.uu), pcg_solver(a.uu), max_iter, tol, &cerr);
}
cout << setprecision(numeric_limits<Float>::digits10)
<< catchmark("inv_lambda") << inv_lambda << endl
<< catchmark("u") << uh
<< catchmark("p") << ph;
return 0;
}
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 53
Comments
The problem admits the following matrix form:
_
a.uu trans(b.uu)
b.uu c.uu
__
uh.u
ph.u
_
=
_
mfh.u a.ub uh.b
b.ub uh.b
_
The problem is similar to the Stokes one (see page 44): this system is solved by the preconditioned
conjugate gradient algorithm :
int status = pcg_abtbc (a.uu, b.uu, c.uu, uh.u, ph.u, -(a.ub*uh.b) + (mu*fh).u,
-(b.ub*uh.b), ldlt(mp.uu), ldlt(a.uu), max_iter, tol, &cerr);
The preconditioner is here the mass matrix mp.uu for the pressure. As showed in [13], the number of
iterations need by the conjugate gradient algorithm to reach a given precision is then independent
of the mesh size and is uniformly bounded when becomes small, i.e. in the incompressible case.
How to run the program
Figure 4.1: The incompressible linear elasticity ( = +) for N = 2 and N = 3.
We assume that the previous code is contained in the le incompressible-elasticity.cc.
Compile the program as usual (see page 12):
make incompressible-elasticity
and enter the comands:
mkgeo_grid -t 10 > square.geo
./incompressible-elasticity square.geo 0 > square.mfield
mfield -u -deformation square.mfield
mkgeo_grid -T 10 > cube.geo
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
54 Rheolef version 5.94 update 27 May 2011
./incompressible-elasticity cube.geo 0 > cube.mfield
mfield -u -deformation cube.mfield -fill
The visualization is performed as usual: see section 3.1, page 34. Compare the results on Fig. 4.1,
obtained for = + with those of Fig. 3.2, page 34, obtained for = 1.
Finally, the stress computation and the mesh adaptation loop is left as an execice to the reader.
4.2 The P
1
bubble element for the Stokes problem
Formulation and approximation
Let us go back to the Stokes problem. In section 3.4, page 42, the Taylor-Hood nite element was
considered. Here, we turn to the mini-element [14] proposed by Arnold, Brezzi and Fortin, also
well-known as the P1-bubble element. This element is generaly less precise than the Taylor-Hood
one, but becomes popular, mostly because it is easy to implement in two and three dimensions
and furnishes a P
1
approximation of the velocity eld. Moreover, this problem develops some links
with stabilization technics and will presents some new rheolef features.
We consider a mesh T
h
of R
N
, N = 2, 3 composed only of simplicial elements: triangles when
N = 2 and tetraedra when N = 3. The following nite dimensional spaces are introduced:
X
(1)
h
= v (H
1
())
N
; v
/K
(P
1
)
N
, K T
h
,
B
h
= (C
0
(

))
N
;
/K
B(K)
N
, K T
h

X
h
= X
(1)
h
B
h
V
h
() = X
h
V(),
Q
h
= q L
2
()) C
0
(

); q
/K
P
1
, K T
h
,
where B(K) = vect(
1
. . .
N+1
) and
i
are the barycentric coordinates of the simplex K.
The B(K) space is related to the bubble local space. The approximate problem is similar to (3.1),
page 42, up to the choice of nite dimensional spaces.
Remark that the velocity eld splits in two terms: u
h
= u
(1)
h
+u
(b)
h
, where u
(1)
h
X
(1)
h
is continuous
and piecewise linear, and u
(b)
h
B
h
is the bubble term.
File contraction-bubble.cc
#include "rheolef.h"
#include "rheolef/mixed_solver.h"
using namespace rheolef;
using namespace std;
Float u_upstream (const point& x) { return sqr(8.-x[0])/512.; }
int main(int argc, char**argv) {
geo omega (argv[1]);
domain upstream = omega["upstream"];
space X1h (omega, "P1", "vector");
space Bh (omega, "bubble", "vector");
space Qh (omega, "P1");
space Wh (omega, upstream, "P1");
X1h.block ("wall");
X1h.block ("upstream");
X1h[0].block ("axis");
X1h[0].block ("downstream");
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 55
X1h[0].block ("axis");
space Xh = X1h * Bh;
field uh (Xh);
field ph (Qh, 0.);
uh[0]["wall"] = 0;
uh[1]["wall"] = 0;
uh[0]["upstream"] = 0;
uh[1]["upstream"] = interpolate(Wh,u_upstream);
uh[0]["downstream"] = 0;
uh[0]["axis"] = 0;
form a1 (X1h, X1h, "2D_D");
form ab (Bh, Bh, "2D_D");
form a0 = form_nul (Bh, X1h);
form_manip a_manip;
a_manip << size(2,2)
<< a1 << a0
<< trans(a0) << ab;
form a (Xh, Xh);
a_manip >> a;
ssk<Float> fact_a = ldlt(a.uu);
form b1 = - form(X1h, Qh, "div");
form bb = - form(Bh, Qh, "div");
form_manip b_manip;
b_manip << size(1,2)
<< b1 << bb;
form b (Xh, Qh);
b_manip >> b;
form mp (Qh, Qh, "mass");
ssk<Float> fact_mp = ldlt(mp.uu);
int max_iter = 500;
Float tol = 1e-14;
int status = pcg_abtb (a.uu, b.uu, uh.u, ph.u, -(a.ub*uh.b), -(b.ub*uh.b),
fact_mp, fact_a, max_iter, tol, &cerr);
cout << catchmark("u") << uh
<< catchmark("p") << ph;
return status;
}
Comments
The boundary conditions are suitable for a ow in an abrupt contraction geometry. The matrix
structure is similar to those of the Taylor-Hood element, and thus the same ecient augmented
Lagrangian algorithms applies.
The global form a(., .) over X
h
is obtained by concatenation of the forms a
1
(., .) and a
b
(., .) over
X
(1)
h
and B
h
repectively, thanks to the form manip class:
a =
_
a1 0
0 ab
_
How to run the program
The boundary conditions in this example are related to an abrupt contraction geometry with a
free surface. The corresponding mesh contraction.geo can be easily builded from the geometry
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
56 Rheolef version 5.94 update 27 May 2011
description les contraction.bamgcad and contraction.dmn provided with the the rheolef
distribution. The directory where examples are available is given by the following unix command:
rheolef-config --exampledir
The building mesh procedure is presented in appendix A, page A. Running this example is left as
an exercice to the reader.
4.3 The stabilized Stokes problem
An alternative and popular implementation of this element eliminates the unknowns related to
the bubble components (see e.g. [15], page 24). This elimination can be easily performed since
the form a
b
(., .) over B
h
is diagonal, due to the fact that the bubble functions vanishes on the
boundary of elements. The system reduces to:
_
A1 B1
T
B1 C
__
U1
P
_
=
_
F
G
_
Remarks that the matrix structure is similar to those of the nealy incompressible elasticity (see 4.1,
page 4.1). A direct nite element formulation for this problem is known as the P
1
P
1
stabilized
element, proposed by Brezzi and Pitkaranta [16].
4.4 Axisymetric geometries
The coordinate system is associated to the geometry description, stored together with the mesh
in the .geo:
mkgeo_grid -t 10 -rz > square-rz.geo
more square-rz.geo
Note the additional line in the header:
...
coordinate_system rz
...
Here "rz" means that the coordinate system (x
0
, x
1
) = (r, z). Notes that the coordinate system
(z, r) is also supported but not fully tested yet: it may also be implemented by a suitable coordinate
swap. The "cartesian" argument string is also supported and means that the usual coordinate
system may be used. In the "rz" case, the L
2
functional space is equipped with the following
weighted scalar product
(f, g) =
_

f(r, z) g(r, z) r drdz


and all usual bilinear forms are now implemented by using this weight.
By this way, a program source code can handle both cartesian and axisymetric systems: only the
input geometry makes the dierence.
myprog square.geo
myprog square-rz.geo
Thus, the coordinate system can be chosen at run time and we can expect an ecient source code
reduction.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 57
Two complete examples stokes-poiseuille.cc and stokes-poiseuille-bubble.cc are pro-
vided in the example directory. These examples are related to the Poiseuille ow of a uid either
between parallel planes (cartesian) or in a pipe (axisymetric). The rst example implements the
Taylor-Hood approximation while the second one uses the bubble-stabilized P1-P1 approximation.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
58 Rheolef version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Chapter 5
Time-dependent problems
5.1 The heat equation
Formulation
Let T > 0, R
N
, N = 1, 2, 3 and fdened in . The heat problem writes:
(P): nd u, dened in ]0, T[, such that
u
t
u = f in ]0, T[,
u(0) = 0 in ,
u(t) = 0 on ]0, T[.
Approximation
Let t > 0 and t
n
= nt, n 0. The problem is approximated with respect to time by the
following rst-order implicit Euler scheme:
u
n+1
u
n
t
u
n+1
= f(t
n+1
) in
where u
n
u(nt) and u
(0)
= 0. We reuse the bilinear forms a and m dened in section 1.1,
page 9 for the Dirichlet problem and introduce the bilinear form c = m + t a. The variationnal
formulation of the time-discretized problem writes:
(V F)
n
: Let u
n
being known, nd u
n+1
H
1
0
() such that
c (u
n+1
, v) = m(u
n
+ t f(t
n+1
), v), v H
1
0
().
This is a Poisson-like problem. The discretization with respect to space of this problem is similar
to those presened in section 1.1, page 9.
File heat.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
int main (int argc, char **argv) {
geo omega (argv[1]);
59
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
60 Rheolef version 5.94 update 27 May 2011
size_t n_max = (argc > 2) ? atoi(argv[2]) : 10;
Float delta_t = 0.5/n_max;
space Vh (omega, "P1");
Vh.block ("boundary");
form m (Vh, Vh, "mass");
form a (Vh, Vh, "grad_grad");
form c = m + delta_t*a;
ssk<Float> c_fact = ldlt (c.uu);
field fh (Vh, 1.);
field uh (Vh, 0.);
branch event ("t","u");
cout << event (0, uh);
for (size_t n = 1; n <= n_max; n++) {
field mb = m*(uh + delta_t*fh);
uh.u = c_fact.solve (mb.u - c.ub*uh.b);
cout << event (Float(n)*delta_t, uh);
}
}
Comments
Notice the use of the branch class:
branch event ("t","u");
this is a wrapper class that is used here to print the branch of solution (t
n
, u
n
)
n0
, on the standard
output in the .branch le format. An instruction as:
cout << event (t,uh);
is equivalent to the formated output
cout << catchmark("t") << t << endl
<< catchmark("u") << uh;
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 61
How to run the program
Figure 5.1: Animation of the solution of the heat problem.
We assume that the previous code is contained in the le heat.cc. Then, compile the program
as usual (see page 12):
make heat
For a one dimensional problem, enter the comands:
mkgeo_grid -e 10 -boundary > line-10.geo
./heat line-10.geo > line-10.branch
The previous commands solve the problem for the corresponding mesh and write the solution in
the eld-family le format .branch. For a bidimensional one:
mkgeo_grid -t 10 -boundary > square-10.geo
./heat square-10.geo > square-10.branch
For a tridimensional one:
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
62 Rheolef version 5.94 update 27 May 2011
mkgeo_grid -T 10 -boundary > box-10.geo
./heat box-10.geo > box-10.branch
How to run the animation
branch line-10.branch -gnuplot
A gnuplot window appears. Enter q to exit the window. For a bidimensional case, a more
sophisticated procedure is required. Enter the following unix commands:
branch square-10.branch -paraview
paraview &
A window appears, that looks like a video player. Then, open the File->open menu and load
square-10.vtk. Then, press the apply green button and, in the object inspector window,
select display and clic on the rescale to data range button. Then clic on the video play button.
An elevation view can be also obtained: Select the Filter->alphabetical->wrap(scalar) menu,
choose 10 as scale factor and press the apply green button. Then, clic on the graphic window,
rotate the view and nally play the animation
To generate an animation le
1
, go to the File->save animation menu and enter as le name
square-10 and as le type jpeg. A collection of jpeg les are generated by paraview. Then, run
the unix command:
ffmpeg -r 2 -i square-10.%04d.jpg square-10.mov
The animation le square-10.mov can now be started from any video player, such as vlc:
vlc --loop square-10.mov
For the tridimensional case, the animation feature is similar.
5.2 The convection-diusion problem
Formulation
Let T > 0 and > 0. The convection-diusion problem writes:
(P): nd , dened in ]0, T[, such that

t
+u. = 0 in ]0, T[
(0) =
0
in
(t) =

(t) on ]0, T[
where u,
0
and

being known.
1
At this time, the avi output feature is broken in paraview, and an alternate mpeg output is here suggested.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 63
Time approximation
This problem is approximated by the following rst-order implicit Euler scheme:

n+1

n
X
n
t

n+1
= 0 in
where t > 0,
n
(nt) and
(0)
=
0
.
Let t
n
= nt, n 0. The term X
n
(x) is the position at t
n
of the particule that is in x at t
n+1
and is transported by u
n
. Thus, X
n
(x) = X(x, t
n
) where X(x, t) is the solution of the dierential
equation
_
dX
dt
= u(X(x, t), t) p.p. t ]t
n
, T
n+1
[,
X(x, t
n+1
) = x.
Then X
n
(x) is approximated by the rst-order Euler approximation
X
n
(x) x t n
n
(x).
This algorithm has been introduced by O. Pironneau (see e.g. [17]), and is known as the method
of characteristic. The ecient localization of X
n
(x) in an unstructured mesh involves a quadtree
data structure
2
.
The following code implements the classical rotating Gaussian hill (see e.g. [18]).
File convect.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
Float nu = 1e-3;
point u (const point & x) { return point(-x[1], x[0]); }
struct phi : unary_function<point,Float> {
Float operator() (const point& x) {
point xc (0.25, 0, 0);
Float sigma = 0.01;
return sigma/(sigma + 4*nu*t)
* exp(-(sqr( x[0]*cos(t) + x[1]*sin(t) - xc[0])
+ sqr(-x[0]*sin(t) + x[1]*cos(t) - xc[1]))/(sigma + 4*nu*t));
}
phi (Float tau) : t(tau) {}
protected: Float t;
};
int main (int argc, char **argv) {
geo omega (argv[1]);
size_t n_max = (argc > 2) ? atoi(argv[2]) : 24;
Float delta_t = 2*acos(-1.)/n_max;
space Vh (omega, "P1");
Vh.block ("boundary");
form m (Vh, Vh, "mass");
form a (Vh, Vh, "grad_grad");
form c = m + delta_t*nu*a;
ssk<Float> c_fact = ldlt (c.uu);
field uh = interpolate (Vh*Vh, u);
2
The quadtree is only implemented for two-dimensional problems in rheolef. It is planed to be extended to
tridimensional problems.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
64 Rheolef version 5.94 update 27 May 2011
field phih = interpolate (Vh, phi(0));
cerr << "# # t\terror" << endl;
geomap X (Vh, -delta_t*uh);
branch event ("t","phi");
cout << event (0, phih);
for (size_t n = 1; n <= n_max; n++) {
Float t = Float(n)*delta_t;
field prec_phih = compose (phih, X);
phih.u = c_fact.solve (m.uu*prec_phih.u + m.ub*prec_phih.b - c.ub*phih.b);
field e = phih - interpolate (Vh, phi(t));
cerr << "# " << t << "\t" << sqrt(m(e,e)) << endl;
cout << event (t, phih);
}
}
Comments
We take =]
1
2
,
1
2
[
2
and T = . This problem provides an example for a convection-diusion
equation with a variable velocity eld u(x
0
, x
1
) = (x
1
, x
0
) and a known analytical solution:
(x, t) =

+ 4t
exp
_

(x
0
cos(t) +x
1
sin(t) x
c,0
)
2
+ (x
0
sin(t) +x
1
cos(t) x
c,1
)
2
+ 4t
_
where > 0 is the slope and x
c
is the center of the hill.
Notice the use of a class-function implementation phi for the implementation of (t) as a function
of x. Such programation style has been introduced in the Standard Template Library [19], which
is a part of the standard C++ library. By this way, for a given t, (t) can be interpolated as an
usual function on a mesh.
The geomap variable X implements the localizer X
n
(x) and the compose function is used to perform
the composition
h
X
n
.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 65
How to run the program
Figure 5.2: Animation of the solution of the rotating hill problem.
We assume that the previous code is contained in the le convect.cc. Then, compile the program
as usual (see page 12):
make convect
and enter the comands:
mkgeo_grid -t 50 -boundary -a -0.5 -b 0.5 -c -0.5 -d 0.5 > omega-50.geo
./convect omega-50.geo > omega-50.branch
The visualization and animation are similar to those of the head problem previously presented in
paragraph 5.1:
branch -paraview omega-50
paraview&
The result is shown on Fig. 5.2.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
66 Rheolef version 5.94 update 27 May 2011
5.3 The Navier-Stokes problem
Formulation
This longer example combines most fonctionalities presented in the previous examples.
Let us consider the Navier-Stokes problem for the driven cavity in =]0, 1[
N
, N = 2, 3. Let
Re > 0 be the Reynolds number, and T > 0 a nal time. The problem writes:
(NS): nd u = (u
0
, . . . , u
N1
) and p dened in ]0, T[ such that:
Re
_
u
t
+u.u
_
div(2D(u)) + p = 0 in ]0, T[,
div u = 0 in ]0, T[,
u(t =0) = 0 in 0, T,
u = (1, 0) on
top
]0, T[,
u = 0 on (
left

right

bottom
)]0, T[,
u
0
n
=
u
1
n
= u
2
= 0 on (
back

front
)]0, T[ when N = 3,
where D(u) = (u + u
T
)/2. This nonlinear problem is the natural extension of the linear
Stokes problem, as presented in paragraph 5.3, page 66. The boundaries are represented on
Fig. 3.1, page 31.
Time approximation
Let t > 0. Let us consider the following backward second order scheme, for all C
2
([0, T]) :
d
dt
(t) =
3(t) 4(t t) +(t 2t)
2t
+O(t
2
)
The problem is approximated by the following second-order implicit Euler scheme:
Re
3u
n+1
4u
n
X
n
+u
n1
X
n1
2t
div(2D(u
n+1
)) + p
n+1
= 0 in ,
div u
n+1
= 0 in ,
u
n+1
= (1, 0) on
top
,
u
n+1
= 0 on
left

right

bottom
,
u
n+1
0
n
=
u
n+1
1
n
= u
n+1
2
= 0 on
back

front
when N = 3,
where, following [20, 21]:
X
n
(x) = x t u

(x)
X
n1
(x) = x 2t u

(x)
u

= 2u
n
u
n1
It is a second order extension of the method previously introduced in paragraph 5.2 page 63. The
scheme denes a second order recurence for the sequence (u
n
)
n1
, that starts with u
1
= u
0
= 0.
Variationnal formulation
The variationnal formulation of this problem expresses:
(NS)
t
: nd u
n+1
V(1) and p
n+1
L
2
0
() such that:
a(u
n+1
, v) + b(v, p
n+1
) = m(f
n
, v), v V(0),
b(u
n+1
, q) = 0, q L
2
0
(),
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 67
where
f
n
=
Re
2t
_
4 u
n
X
n
u
n1
X
n
_
where
a(u, v) =
3Re
2t
_

u.v dx +
_

2D(u) : D(v) dx
and b(., .) and V() was already introduced in paragraph 3.4, page 42, while studying the Stokes
problem.
Space approximation
The Taylor-Hood [12] nite element approximation of this generalised Stokes problem was also
considered in paragraph 3.4, page 42. We introduce a mesh T
h
of and the nite dimensional
spaces X
h
, V
h
() and Q
h
. The approximate problem writes:
(NS)
t,h
: nd u
n+1
h
V
h
(1) and p
n+1
Q
h
such that:
a(u
n+1
h
, v) + b(v, p
n+1
h
) = m(f
n
h
, v), v V
h
(0),
b(u
n+1
h
, q) = 0, q Q
h
.
(5.1)
where
f
n
h
=
Re
2t
_
4 u
n
h
X
n
u
n1
h
X
n
_
The problem reduces to a sequence resolution of a generalized Stokes problems.
File navier-stokes-solve.h
// second order scheme (experimental)
#include "rheolef/mixed_solver.h"
#include "cahouet-chabart.h"
using namespace std;
int navier_stokes_solve (Float Re, Float delta_t, field f0h, field& uh, field& ph,
size_t& max_iter, Float& tol, std::ostream *p_cerr=0, std::string label = "navier-stokes") {
const space& Vh = uh.get_space();
const space& Qh = ph.get_space();
form m (Vh, Vh, "mass");
form a (Vh, Vh, "2D_D");
a = a + 1.5*(Re/delta_t)*m;
ssk<Float> fact_a = ldlt(a.uu);
form b (Vh, Qh, "div"); b = -b;
cahouet_chabart preconditioner (Qh, 1.5*(Re/delta_t));
if (p_cerr != 0) *p_cerr << "[" << label << "] #n |du/dt|" << endl;
field uh1 = uh;
geomap_option_type opts;
opts.n_track_step = 10;
for (size_t n = 0; true; n++) {
field uh2 = uh1;
uh1 = uh;
field uh_star = 2.0*uh1 - uh2;
geomap X1 (Vh, -delta_t*uh_star, opts);
geomap X2 (Vh, -2.0*delta_t*uh_star, opts);
field fh = f0h + 0.5*(Re/delta_t)*(4.0*compose(uh1,X1) - compose(uh2,X2));
size_t gs_max_iter = 500;
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
68 Rheolef version 5.94 update 27 May 2011
Float gs_tol = 1e-15;
int status = pcg_abtb (a.uu, b.uu, uh.u, ph.u, (m*fh).u - a.ub*uh.b, -(b.ub*uh.b),
preconditioner, fact_a, gs_max_iter, gs_tol);
if (status != 0) warning_macro ("solve generalized stokes: precision not reached: tol = " << tol)
field duh_dt = (3*uh - 4*uh1 + uh2)/(2*delta_t);
Float residual = sqrt(m(duh_dt,duh_dt));
if (p_cerr != 0) *p_cerr << "[" << label << "] "<< n << " " << residual << endl;
if (residual < tol) {
tol = residual;
max_iter = n;
return 0;
}
if (n == max_iter-1) {
tol = residual;
return 1;
}
}
}
Comments
The navier stokes solve function is similar to the stokes-cavity.cc. It solves here a gener-
alised Stokes problem and manages a right-hand side f
h
:
field uh_star = 2.0*uh1 - uh2;
geomap X1 (Vh, -delta_t*uh_star);
geomap X2 (Vh, -2.0*delta_t*uh_star);
field fh = f0h + 0.5*(Re/delta_t)*(4.0*compose(uh1,X1) - compose(uh2,X2));
This last computation is similar to those done in the convect.cc example. The generalized
Stokes problem is solved by the conjugate gradient algorithm :
int status = pcg_abtb (a.uu, b.uu, uh.u, ph.u, (m*fh).u - a.ub*uh.b, -(b.ub*uh.b),
preconditioner, fact_a, gs_max_iter, gs_tol, &cerr);
The preconditioner is here the Cahouet and Chabart one [22]. As showed in [23], the number of
iterations need by the conjugate gradient algorithm to reach a given precision is then independent
of the mesh size. This preconditioner leads to the resolution of the follwoing subproblem:
(M
1
h
+A
1
h
)q
h
= r
h
where = Re/t, r
h
Q
h
is given and M and A are respectively the the mass matrix and the
discrete Poisson operator with Neumann boundary condition. The resolution of this subproblem
hqs been previously developed in section 2.4, page 24.
File cahouet-chabart.h
#include "neumann-laplace-assembly.h"
struct cahouet_chabart {
cahouet_chabart (const space& Qh, Float lambda_1)
: fact_m(), fact_c(), lambda(lambda_1) {
form m (Qh, Qh, "mass");
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 69
fact_m = ldlt(m.uu);
form a (Qh, Qh, "grad_grad");
form_diag dm (Qh, "mass");
field mh (dm);
csr<Float> c = neumann_laplace_assembly (a.uu, mh.u);
fact_c = ldlt(c);
}
vec<Float> solve (const vec<Float>& Mp) const {
vec<Float> q1 = fact_m.solve(Mp);
vec<Float> Mp_e (Mp.size()+1);
for (size_t i = 0; i < Mp.size(); i++) Mp_e.at(i) = Mp.at(i);
Mp_e.at(Mp.size()) = 0;
vec<Float> q2_e = fact_c.solve(Mp_e);
vec<Float> q2 (Mp.size());
for (size_t i = 0; i < q2.size(); i++) q2.at(i) = q2_e.at(i);
vec<Float> q = q1 + lambda*q2;
return q;
}
ssk<Float> fact_m;
ssk<Float> fact_c;
Float lambda;
};
File navier-stokes-cavity.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
#include "navier-stokes-solve.h"
#include "cavity.h"
field criteria (Float Re, const field& uh) {
space Xh (uh.get_geo(), "P1d");
form inv_m (Xh, Xh, "inv_mass");
form mpt (Xh, uh.get_space()[0], "mass");
form p = inv_m * trans(mpt);
field c1 = sqr(p*uh[0]) + sqr(p*uh[1]);
space Th (uh.get_geo(), "P1d", "tensor");
form two_D (uh.get_space(), Th, "2D");
form inv_mt (Th, Th, "inv_mass");
field two_Duh = inv_mt*(two_D*uh);
field c2 = sqr(field(two_Duh(0,0))) + sqr(field(two_Duh(1,1))) + 2*sqr(field(two_Duh(0,1)));
return sqrt(Re*c1 + c2);
}
int main (int argc, char**argv) {
if (argc < 2) {
cerr << "usage: " << argv[0] << " <geo> <Re> <Delta t> <n_adapt> <hcoef> <hmin>" << endl;
exit (1);
}
geo omega_h (argv[1]);
Float Re = (argc > 2) ? atof(argv[2]) : 100;
Float delta_t = (argc > 3) ? atof(argv[3]) : 0.05;
size_t n_adapt = (argc > 4) ? atoi(argv[4]) : 3;
adapt_option_type options;
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
70 Rheolef version 5.94 update 27 May 2011
options.hcoef = (argc > 5) ? atof(argv[5]) : 2;
options.hmin = (argc > 6) ? atof(argv[6]) : 0.004; // 0.004
options.hmax = 0.1;
space Vh = cavity_space (omega_h, "P2");
space Qh (omega_h, "P1");
field uh = cavity_field (Vh, 1.0);
field ph (Qh, 0.0);
field fh (Vh, 0.0);
for (size_t i = 0; true; i++) {
size_t max_iter = 500;
Float tol = 1e-10;
navier_stokes_solve (Re, delta_t, fh, uh, ph, max_iter, tol, &cerr);
orheostream o (omega_h.name(), "mfield");
o << setprecision(numeric_limits<Float>::digits10)
<< catchmark("Re") << Re << endl
<< catchmark("delta_t") << delta_t << endl
<< catchmark("u") << uh
<< catchmark("p") << ph;
if (i >= n_adapt) break;
field ch = criteria(Re,uh);
omega_h = geo_adapt(ch, options);
omega_h.save();
Vh = cavity_space (omega_h, "P2");
Qh = space (omega_h, "P1");
uh = cavity_field (Vh, 1.0);
ph = field (Qh, 0.0);
fh = field (Vh, 0);
}
}
Comments
The code performs a computation by using adaptive mesh renement, in order to capture recircu-
lation zones. The adapt option type declaration is used by rheolef to send options to the mesh
generator. The code reuse the le cavity.h introduced page 42. This le contains two functions
that denes boundary conditions associated to the cavity driven problem.
The criteria function computes the adaptive mesh renement criteria:
c
h
= (Re[u
h
[
2
+ 2[D(u
h
)[
2
)
1/2
The criteria function is similar to those presented in the embankment-adapt-2d.cc example.
The main function enters in a loop, that solves at each iteration a generalised Stokes problem,
then recompute the mesh and nally re-interpolates the solution u on the new mesh:
uh = interpolate (Vh, uh);
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 71
How to run the program
Re = 100: 2481 vertices
max
= 1.27 10
4
,
min
= 0.10
Re = 400: 3001 vertices
max
= 6.4 10
4
,
min
= 0.11
Figure 5.3: Meshes and stream functions associated to the solution of the Navier-Stokes equations
for Re = 100 (top) and Re = 400 (bottom).
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
72 Rheolef version 5.94 update 27 May 2011
Re = 1000: 3544 vertices
max
= 1.72 10
3
,
min
= 0.12
Figure 5.4: Meshes and stream functions associated to the solution of the Navier-Stokes equations
for Re = 1000.
First, creates an initial mesh:
mkgeo_grid -t 10 > square.geo
Then, compile and run the Navier-Stokes solver for the driven cavity for Re = 100:
make navier-stokes-cavity
./navier-stokes-cavity square.geo 100
The program performs a computation with Re = 100. By default the time step is t = 0.05
and the computation loops for three mesh adaptations. At each time step, the program prints
an approximation of the time derivative, and stops when a stationary solution is reached. Then,
extract and visualise the adapted mesh and the solution:
geo square-100-3.geo
mfield square-3.mfield.gz -u -velocity -vscale 10
The representation of the stream function writes:
zcat square-3.mfield.gz | ./vorticity | ./streamf-cavity | \
field -n-iso 15 n-iso-negative 10 -nofill -
The programs vorticity and streamf-cavity has been introduced pages 46 and 48, respectively.
The last options of the field program draws isocontours of the stream function using lines, as
shown on Fig. 5.3. The zero isovalue separates the main ow from recirculations located in corners
at the bottom of the cavity. For Re = 400 and 1000 the computation writes:
./navier-stokes-cavity square.geo 400
./navier-stokes-cavity square.geo 1000
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 73
Comparison: Re = 1000
Re = 1000
Comparison: Re = 400
Re = 400
Comparison: Re = 100
Re = 100
x
1
u
0
(0.5, x
1
)
1 0.5 0 -0.5
1
0.5
0
Re = 1000, comparsion
Re = 1000
Re = 400, comparison
Re = 400
Re = 100, comparison
Re = 100
u
1
(x
0
, 0.5)
x
0
1 0.5 0
0.5
0
-0.5
Figure 5.5: Navier-Stokes: velocity proles along lines passing throught the center of the cavity,
compared with data from [24]: (a) u
0
along the vertical line; (b) u
1
along the horizontal line line.
The visualization of the cut of the horizontal velocity along the vertical median line writes:
mfield square-3.mfield.gz -u0 | field -cut -normal -1 0 -origin 0.5 0 -gnuplot -
mfield square-3.mfield.gz -u1 | field -cut -normal 0 1 -origin 0 0.5 -gnuplot -
Fig. 5.5 compare the cuts with data from [24], table 1 and 2 (see also [25]). Observe that the
solution is in good agreement with these previous computations.
Re x
c
y
c

min
100 present 0.617 0.736 0.104
Labeur and Wells [26] 0.608 0.737 0.104
Donea and Huerta [27] 0.62 0.74 0.103
400 present 0.552 0.602 0.117
Labeur and Wells [26] 0.557 0.611 0.115
Donea and Huerta [27] 0.568 0.606 0.110
1000 present 0.532 0.569 0.121
Labeur and Wells [26] 0.524 0.560 0.121
Donea and Huerta [27] 0.540 0.573 0.110
Figure 5.6: Cavity ow: primary vortex position and stream function value.
Finaly, table 5.6 compares the primary vortex position and its associated stream function value.
Notice also the good agreement with previous simulations. The small program that computes
the primary vortex is showed below. Notice that degrees of freedom for the P
2
approximation of
the stream function are listed with rst the degrees of freedom associated to vertices and then
thoses located at the middle of edges. When the extremum of the stream function is located on
an edge, the program build rst the edges, and then compute the middle-point associated to the
edge degree of freedom.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
74 Rheolef version 5.94 update 27 May 2011
File vortex-position.cc
#include "rheolef.h"
#include "rheolef/geo-connectivity.h"
using namespace rheolef;
using namespace std;
int main (int argc, char** argv) {
field psi_h; cin >> psi_h; psi_h *= -1;
Float psi_max = 0;
size_t i_dof_max = 0;
for (size_t i_dof = 0; i_dof < psi_h.size(); i_dof++) {
if (psi_h.at(i_dof) <= psi_max) continue;
psi_max = psi_h.at(i_dof);
i_dof_max = i_dof;
}
point x_max;
const geo& omega = psi_h.get_geo();
if (i_dof_max < omega.n_vertex()) {
x_max = omega.vertex(i_dof_max);
} else {
vector<pair<size_t,size_t> > edge;
build_edge (omega, edge);
size_t i_edge = i_dof_max - omega.n_vertex();
point a = omega.vertex (edge[i_edge].first);
point b = omega.vertex (edge[i_edge].second);
x_max = (a+b)/2;
}
cout << "xc\t\tyc\t\tpsi" << endl
<< x_max[0] << "\t" << x_max[1] << "\t" << psi_max << endl;
}
For higher Reynolds number, Shen [28] showed in 1991 that the ow converges to a stationary
state for Reynolds numbers up to 10000; for Reynolds numbers larger than a critical value 10 000 <
Re
1
< 10 500 and less than another critical value 15 000 < Re
2
< 16 000, these authors founded
that the ow becomes periodic in time which indicates a Hopf bifurcation; the ow loses time
periodicity for Re Re
2
. In 2002, Auteri et al. [29] estimated the critical value for the apparition
of the rst instability to Re
1
8018. In 2005, Erturk et al. [30] computed steady driven cavity
solutions up to Re 21 000. Also in 2005, this result was inrmed by [31]: these authors estimated
Re
1
close to 8000, in agreement with [29]. The 3D driven cavity has been investigated in [32] by
the method of characteristic. In conclusion, the exploration of the driven cavity at large Reynolds
number is a fundamental challenge in computational uid dynamics.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Part III
Advanced and highly nonlinear
problems
75
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Chapter 6
Equation dened on a surface
This chapter deals with equations dened on a surface.
Let be a closed map in R
d
, i.e. a closed surface when d = 3 or a closed curve when d = 2. We
consider the following problem:
nd u, dened on , such that
u
s
u = f
where
s
is the Laplace-Beltrami operator and f is a given function, dened on . Remark that
this is a Helmholtz problem on and, since is closed, we have = and there is no boundary
conditions.
In this chapter, we describe three approaches for the resolution of this problem. The rst one
bases on an explict discretization of and is suitable when is not too complex. The second
one suppose that is expressed implicitly by an equation (x) = 0, where , called the level
set function, is dened on a bounded domain R
d
containing . The second approach build
explicitly an intersection mesh of , but there is not theoretical proof that it is convergent. Finally,
the third approach is a variant of the second one, with rigorous convergence proof.
6.1 Formulation on an explicit surface mesh
TODO
File helmholtz s sphere.cc
#include "rheolef.h"
#include "sphere.h"
using namespace std;
using namespace rheolef;
int main (int argc, char**argv) {
geo omega (argv[1]);
size_t d = omega.dimension();
space Xh (omega, "P1");
form m(Xh, Xh, "mass");
form a(Xh, Xh, "grad_grad");
a = a + m;
ssk<Float> fact_a = ldlt(a.uu);
field fh = interpolate(Xh, f(d));
field uh(Xh);
77
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
78 Rheolef version 5.94 update 27 May 2011
uh.u = fact_a.solve((m*fh).u);
cout << setprecision(numeric_limits<Float>::digits10)
<< uh;
}
Comments
TODO
How to run the program ?
Figure 6.1: Explicit surface surface method: (left) for a circle: (right) for a sphere; (top) mesh;
(bottom) solution.
2D
gmsh -1 circle-gmsh.mshcad
msh2geo circle-gmsh.msh > circle-gmsh.geo
geo circle-gmsh.geo -gnuplot
make helmholtz_s_sphere
./helmholtz_s_sphere circle-gmsh.geo | field -
3D
gmsh -2 sphere-gmsh.mshcad
msh2geo sphere-gmsh.msh > sphere-gmsh.geo
geo sphere-gmsh.geo
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 79
./helmholtz_s_sphere sphere-gmsh.geo | field -
6.2 Building a surface mesh from level set
Figure 6.2: Building a surface mesh from level set: (left) for a circle: (right) for a sphere.
2D
mkgeo_grid -t 20 -a -2 -b 2 -c -2 -d 2 > square2.geo
make isovalue_sphere geo_min_aera
./isovalue_sphere square2.geo > square2-iso.geo
geo square2-iso-iso.geo -gnuplot
./helmholtz_s_sphere square2-iso.geo | field -
./geo_min_aera square2-iso.geo
3D
mkgeo_grid -T 20 -a -2 -b 2 -c -2 -d 2 -f -2 -g 2 > cube2.geo
./isovalue_sphere cube2.geo > cube2-iso.geo
geo cube2-iso.geo
./helmholtz_s_sphere cube2-iso.geo
./geo_min_aera cube2-iso.geo
File isovalue sphere.cc
#include "rheolef.h"
#include "sphere.h"
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
80 Rheolef version 5.94 update 27 May 2011
using namespace rheolef;
using namespace std;
int main (int argc, char**argv) {
geo Lambda (argv[1]);
space Vh (Lambda, "P1");
field phi_h = interpolate(Vh, phi);
geo Gamma = zero_level_set (phi_h);
cout << setprecision(16) << Gamma;
}
File geo min aera.cc
#include "rheolef.h"
#include "sphere.h"
using namespace rheolef;
using namespace std;
int main (int argc, char**argv) {
geo gamma (argv[1]);
space Vh (gamma, "P0");
form_diag m (Vh, "mass");
Float min_aera = field(m).min();
Float min_abs_aera = abs(field(m)).min();
cout << setprecision(16)
<< "min aera = " << min_aera << endl
<< "min abs aera = " << min_abs_aera << endl;
return (min_aera > 1e-8) ? 0 : 1;
}
6.3 Formulation based on the banded level-set method
TODO
File helmholtz band sphere.cc
#include "rheolef.h"
#include "helmholtz_band_assembly.h"
#include "sphere.h"
using namespace std;
using namespace rheolef;
int main (int argc, char**argv) {
geo Lambda (argv[1]);
size_t d = Lambda.dimension();
space Vh (Lambda, "P1");
field phi_h_lambda = interpolate(Vh, phi);
geo band = banded_level_set (phi_h_lambda);
space Bh (band, "P1");
Bh.block("isolated");
field phi_h = interpolate(Bh, phi);
form m (Bh, Bh, "mass_s", phi_h);
form a (Bh, Bh, "grad_grad_s", phi_h);
a = m+a;
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 81
field fh = interpolate(Bh, f(d));
field lh = m*fh;
csr<Float> A = band_assembly<Float> (a, phi_h);
vec<Float> L(A.nrow(), 0.0);
for (size_t i = 0; i < lh.u.size(); i++) L.at(i) = lh.u.at(i);
for (size_t i = lh.u.size(); i < L.size(); i++) L.at(i) = 0;
vec<Float> U (L.size());
ssk<Float> fact_A = ldlt(A);
U = fact_A.solve(L);
field uh(Bh);
uh.b = 0;
for (size_t i = 0; i < uh.u.size(); i++) uh.u.at(i) = U.at(i);
Bh.get_geo().save();
cout << setprecision(numeric_limits<Float>::digits10)
<< catchmark("u") << uh
<< catchmark("phi") << phi_h;
}
File helmholtz band assembly.h
namespace rheolef {
template <class T>
csr<T>
band_assembly (const form& a, const field& phi_h) {
const space& Bh = a.get_first_space();
check_macro (Bh == phi_h.get_space(), "incompatible spaces");
const geo& band = Bh.get_geo();
size_t n = a.uu.nrow();
size_t m = band.n_domain() - 2; // n_connected components: skip zero & isolated
asr<T> A (n+m, n+m);
Array<size_t>::const_iterator ia = a.uu.ia().begin();
Array<size_t>::const_iterator ja = a.uu.ja().begin();
typename Array<T>::const_iterator va = a.uu.a().begin();
for (size_t i = 0; i < n; i++) {
for (size_t p = ia[i]; p < ia[i+1]; p++) {
A.entry(i,ja[p]) = va[p];
}
}
typename Array<T>::const_iterator vb = phi_h.u.begin();
for (size_t i = 0; i < m; i++) {
const domain& ci = band["connected_component_"+itos(i)];
for (size_t p = 0; p < ci.size(); p++) {
const geo_element& P = ci.at(p);
size_t jdx = P[0];
size_t j = Bh.index(jdx);
A.entry(n+i, j) = vb[j];
A.entry(j, n+i) = vb[j];
}
}
return csr<T>(A);
}
} // namespace rheolef
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
82 Rheolef version 5.94 update 27 May 2011
How to run the program ?
Figure 6.3: Banded level set method: (left) for a circle: (right) for a sphere (n = 10).
2D
mkgeo_grid -t 41 -a -2 -b 2 -c -2 -d 2 > square2.geo
make helmholtz_band_sphere
./helmholtz_band_sphere square2 | field -
3D
mkgeo_grid -T 20 -a -2 -b 2 -c -2 -d 2 -f -2 -g 2 > cube2.geo
./helmholtz_band_sphere cube2 | field -
TODO: add a gure with a cut the solution on the intersection surface mesh, for a clean visual-
ization
TODO: also comment the dirichlet s torus.cc example
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Chapter 7
Multi-regions and non-constant
coecients problems
This chapter is related to the so-called transmission problem.
Formulation
Let us consider the diusion problem with a non-constant diusion coecient in a domain
bounded R
N
, N = 1, 2, 3:
(P): nd u dened in such that:
div(u) = 1 in
u = 0 on
left

right
u
n
= 0 on
top

bottom
when N 2
u
n
= 0 on
front

back
when N = 3
We consider here very important special case when is picewise constant. Let:
(x) =
_
when x
west
1 when x
east
where (
west
,
east
) is a partition of . This problem is known as the transmission problem,
since the solution and the ux are continuous on the interface:
u
west
= u
east
on
0

u
/west
n
=
u
east
n
on
0
where

0
=
west

east
It expresses the transmission of the quantity u and its ux accross the interface
0
between two
regions that have dierent diusion properties: We go back to the standard problem when = 1.
The variational formulation of this problem expresses:
(V F): nd u V such that:
a(u, v) = m(1, v), v V
83
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
84 Rheolef version 5.94 update 27 May 2011
where the bilinear forms a(., .) and m(., .) are dened by
a(u, v) =
_

u.v dx, u, v H
1
()
m(u, v) =
_

uv dx, u, v L
2
()
V = v H
1
(); v = 0 on
left

right

The bilinear form a(., .) denes a scalar product in V and is related to the energy form. This form
is associated to the div operator. The m(., .) is here the classical scalar product on L
2
(),
and is related to the mass form as usual.
The approximation of this problem could performed by a standard Lagrange P
k
continuous ap-
proximation. We switch here to a mixed formulation that implements easily.
Mixed Formulation
Let us introduce the following vector-valued eld:
p = u
The problem can be rewritten as:
(M): nd p and u dened in such that:
1

p u = 0 in
div p = 1 in
u = 0 on
left

right
u
n
= 0 on
top

bottom
when N 2
u
n
= 0 on
front

back
when N = 3
The variationnal formulation writes:
(MV F): nd p (L
2
())
N
and u V such that:
a(p, q) +

b(q, u) = 0, q (L
2
())
N

b(p, v) = m(1, v), v V


where
a(p, q) =
_

p.qdx,

b(q, v) =
_

v.qdx, u, v L
2
()
This problem appears as more complex than the previous one, since there is two unknown instead
of one. Nevertheless, the p unknown could be eliminated by inverting the operator associated to
the a form. This can be done easily since p is approximated by discontinuous piecewise polynomial
functions.
Mixed approximation
Let k 1 and
Q
h
= q (L
2
())
N
; q
/K
(P
k1
)
N

V
h
= v V ; v
/K
P
k

c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 85
The mixed nite element approximation writes:
(MV F)
h
: nd p
h
Q
h
and u
h
V
h
such that:
a(p
h
, q) +

b(q, u
h
) = 0, q Q
h

b(p
h
, v) = m(1, v), v V
h
Here the operator associated to a is block-diagonal and can be inverted at the element level. The
problem reduced to a standard linear system, and solved by a direct method.
File transmission.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
const Float epsilon = 0.01;
int main(int argc, char**argv) {
geo omega (argv[1]);
space Vh (omega, "P1");
if (omega.dimension() <= 2) {
Vh.block ("left"); Vh.block ("right");
} else {
Vh.block ("back"); Vh.block ("front");
}
field uh (Vh);
if (omega.dimension() <= 2)
uh["left"] = uh["right"] = 0;
else
uh["back"] = uh["front"] = 0;
field fh (Vh, 1);
space Qh (omega, "P0", "vector");
field eta (Qh);
eta ["east"] = 1;
eta ["west"] = epsilon;
form_diag d (eta);
form grad (Vh, Qh, "grad");
form m (Vh, Vh, "mass");
form inv_m (Qh, Qh, "inv_mass");
form a = trans(grad)*(inv_m*d)*grad;
ssk<Float> fact = ldlt(a.uu);
uh.u = fact.solve (m.uu*fh.u + m.ub*fh.b - a.ub*uh.b);
cout << setprecision(numeric_limits<Float>::digits10)
<< catchmark("epsilon") << epsilon << endl
<< catchmark("u") << uh;
return 0;
}
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
86 Rheolef version 5.94 update 27 May 2011
Comments
The code begins as usual. In the second part, the space Q
h
is dened. For convenience, the
diusion coecient is introduced diagonal diusion tensor operator d, i.e. for N = 2:
d =
_
0
0
_
It is rst dened as an element of Q
h
i.e. a vector-valued eld:
field eta (Qh);
and then converted to a diagonal form representing the diusion tensor operator:
form_diag d (eta);
Notice that, by this way, an anisotropic diusion operator could be considered. The statement
cout << setprecision(numeric_limits<Float>::digits10)
<< catchmark("epsilon") << epsilon << endl
<< catchmark("u") << uh;
writes and u
h
in a labeled format, suitable for post-traitement, visualization and error analysis.
The number of digits printed depends upon the Float type. When Float is a double, this is
roughly 15 disgits; this number depends upon the machine precision. Here, we choose to print all
the relevant digits: this choice is suitable for the following error analysis.
How to run the program ?
Build the program as usual: make transmission. Then, creates a one-dimensional geometry with
two regions:
mkgeo_grid -e 100 -region > line-region.geo
geo -gnuplot line-region.geo
The trivial mesh generator mkgeo grid, denes two regions east and west when used with the
-region option. This correspond to the situation:
= [0, 1]
N
,
west
= x
0
< 1/2 and
east
= x
0
> 1/2.
In order to avoid mistakes with the C++ style indexation, we denote by (x
0
, . . . , x
N1
) the cartesian
coordinate system in R
N
.
Finaly, run the program and look at the solution:
./transmission line-region.geo > transmission1d.mfield
mfield transmission1d.mfield -u | field -
The two dimensionnal case corresponds to the commands:
mkgeo_grid -t 10 -region > square-region.geo
geo square-region.geo
./transmission square-region.geo > transmission2d.mfield
mfield transmission2d.mfield -u | field -
while the tridimensional to
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 87
mkgeo_grid -T 10 -region > cube-region.geo
./transmission cube-region.geo > transmission3d.mfield
mfield transmission3d.mfield -u | field -mayavi -
This problem is convenient, since the exact solution is known and is piecewise second order poly-
nomial:
u(x) =
_

_
x
0
2
_
1 + 3
2(1 +)
x
0
_
when x
0
< 1/2
1 x
0
2
_
x
0
+
1
2(1 +)
_
otherwise
Since the change in the diusion coecient value ts the element boundaries, obtain the exact
solution at the vertices of the mesh for the P
1
approximation, as shown on Fig. 7.1.
h=1/14
h=1/10
h=1/6
exact
1 0.75 0.5 0.25 0
3
2
1
0
Figure 7.1: Transmission problem: u
h
=
h
(u) ( = 10
2
, N = 1, P
1
approximation).
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
88 Rheolef version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Chapter 8
The p-laplacian problem
rheolef provides build-in classes for solving some linear and non-linear partial dierential equa-
tions, based on the nite element method (see e.g. [1]). All example les presented along
the present manual are available in the examples/ directory of the rheolef distribution, e.g.
/usr/local/share/doc/rheolef/examples/.
8.1 Problem statement
Let us consider the classical p-laplacian problem with homogeneous Dirichlet boundary conditions
in a domain bounded R
N
, N = 1, 2, 3:
(P): nd u, dened in such that:
div
_
[u[
p2
u
_
= f in
u = 0 on
where f is known and f = 1 in the computational examples. When p = 2, this problem reduces
to the linear Poisson problem with homogeneous Dichlet boundary conditions. Otherwise, for any
p > 1, the nonlinear problem is equivalent to the following minimisation problem:
(MP): nd u W
1,p
0
() such that:
u = arg min
vW
1,p
0
()
1
p
_

[v[
p
dx
_

f v dx,
where W
1,p
0
() denotes the usual Sobolev spaces of functions in W
1,p
() that vanishes on the
boundary [33, p. 118]. The variational formulation of this problem expresses:
(VF): nd u W
1,p
0
() such that:
a(u; u, v) = m(f, v), v W
1,p
0
()
where a(., .) and m(., .) are dened for any u
0
, u, v W
1,p
() by
a(u
0
; u, v) =
_

[u
0
[
p2
u.v dx, u, v W
1,p
0
()
m(u, v) =
_

uv dx, u, v L
2
()
The m(., .) is here the classical scalar product on L
2
(), and is related to the mass form. The
quantity a(u; u, u) = |u|
p,
induces a norm in W
1,p
0
, equivalent to the standard norm. The
form a(.; ., .) is bilinear with respect to the two last variable and is related to the energy form.
89
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
90 Rheolef version 5.94 update 27 May 2011
8.2 The xed-point algorithm
8.2.1 Principe of the algorithm
This nonlinear problem is then reduced to a sequence of linear subproblems by using the xed-point
algorithm. The sequence
_
u
(n)
_
n0
is dened by recurrence as:
n = 0: let u
(0)
W
1,p
0
() be known.
n 0: suppose that u
(n)
W
1,p
0
() is known and nd u
(n+1)
W
1,p
0
() such that:
a
_
u
(n)
; u
(n+1)
, v
_
= m(f, v), v W
1,p
0
()
Let u
(n+1)
= G
_
u
(n)
_
denotes the operator that solve the previous linear subproblem for a given
u
(n)
. Since the solution u satises u = G(u), it is a xed-point of G.
Let us introduce a mesh T
h
of and the nite dimensional space X
h
of continuous picewise poly-
nomial functions and V
h
, the subspace of X
h
containing elements that vanishes on the boundary
of :
X
h
= v
h
C
0
0
_

_
; v
h/K
P
k
, K T
h

V
h
= v
h
X
h
; v
h
= 0 on
where k = 1 or 2. The approximate problem expresses: suppose that u
(n)
h
V
h
is known and nd
u
(n+1)
h
V
h
such that:
a
_
u
(n)
h
; u
(n+1)
h
, v
h
_
= m(f, v
h
), v
h
V
h
By developping u
h
on a basis of V
h
, this problem reduces to a linear system. The implementation
with rheolef, involving weighted forms, is quite standard: the weight eld wh is inserted as the
last argument to the form constructor. The following code implement this problem in the rheolef
environment.
8.2.2 File p-laplacian-fixed-point.h
int p_laplacian_fixed_point (Float p, field fh, field& uh, Float& r, size_t& n) {
Float tol = r;
Float r0 = 0;
size_t max_iter = n;
const geo& omega_h = uh.get_geo();
const space& Vh = uh.get_space();
string grad_approx = (Vh.get_approx() == "P2") ? "P1d" : "P0";
space Th (omega_h, grad_approx, "vector");
form m (Vh, Vh, "mass");
form inv_mt (Th, Th, "inv_mass");
form grad (Vh, Th, "grad");
cerr << "# Fixed-point algorithm on p-laplancian: p = " << p << endl
<< "# n r v" << endl;
n = 0;
do {
field grad_uh = inv_mt*(grad*uh);
field wh = pow(sqr(grad_uh[0]) + sqr(grad_uh[1]), p/2.-1);
form a (Vh, Vh, "grad_grad", wh);
field rh = a*uh - m*fh;
r = rh.u.max_abs();
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 91
if (n == 0) r0 = r;
Float v = (n == 0) ? 0 : log10(r0/r)/n;
cerr << n << " " << r << " " << v << endl;
if (r <= tol || n++ >= max_iter) break;
ssk<Float> fact_a = ldlt(a.uu);
uh.u = fact_a.solve (m.uu*fh.u + m.ub*fh.b - a.ub*uh.b);
} while (true);
return r <= tol;
}
8.2.3 File p-laplacian-fixed-point.cc
#include "rheolef.h"
using namespace rheolef;
using namespace std;
#include "p-laplacian-fixed-point.h"
#include "poisson-dirichlet.icc"
int main(int argc, char**argv) {
geo omega_h (argv[1]);
string approx = (argc > 2) ? argv[2] : "P1";
Float p = (argc > 3) ? atof(argv[3]) : 2.5;
cerr << "# P-Laplacian problem by fixed-point:" << endl
<< "# geo = " << omega_h.name() << endl
<< "# approx = " << approx << endl
<< "# p = " << p << endl;
space Vh (omega_h, approx);
Vh.block (omega_h["boundary"]);
field uh (Vh);
uh ["boundary"] = 0;
field fh (Vh, 1);
poisson_dirichlet (fh, uh);
Float tol = 10*numeric_limits<Float>::epsilon();
size_t max_iter = 500;
int status = p_laplacian_fixed_point (p, fh, uh, tol, max_iter);
cout << setprecision(numeric_limits<Float>::digits10)
<< catchmark("p") << p << endl
<< catchmark("u") << uh;
return status;
}
8.2.4 File poisson-dirichlet.icc
void poisson_dirichlet (field fh, field& uh) {
const space& Vh = uh.get_space();
form a (Vh, Vh, "grad_grad");
form m (Vh, Vh, "mass");
ssk<Float> fact = ldlt(a.uu);
uh.u = fact.solve (m.uu*fh.u + m.ub*fh.b - a.ub*uh.b);
}
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
92 Rheolef version 5.94 update 27 May 2011
8.2.5 Comments
The xed-point algorithm is amorced with u
(0)
as the solution of the linear problem associated to
p = 2, i.e. the standard Poisson problem with Dirichlet boundary conditions. The construction of
the weighted form a(.; ., .) writes:
field eta_h = pow(sqr(grad_uh[0]) + sqr(grad_uh[1]), p/2.-1);
form a (Vh, Vh, "grad_grad", eta_h);
8.2.6 Running the program
We assume that the previous code is contained in the le p-laplacian-fixed-point.cc. Com-
pile the program, as usual:
make p-laplacian-fixed-point
and enter the comands:
mkgeo_grid -t 10 -boundary > square.geo
geo square.geo
The triangular mesh has a boundary domain named boundary.
./p-laplacian-fixed-point square.geo P1 1.1 > square-P1.field
The previous command solves the problem for the corresponding mesh and writes the solution in
the le format .field.
0.010
0
1.010
8
2.010
8
3.010
8
4.010
8
5.010
8
6.010
8
6.910
8
Y

A
x
is
0
1
X
A
xis
0
1
u
h
(x
0
, x
1
)
s =

x
2
0
+ x
2
1

2
0

2
0.015
0.010
0.005
0
Figure 8.1: The p-laplacian for N = 2: (a) elevation view for p = 1.1; (b) cut along the rst
bissectice x
0
x
1
= 0.
Run the eld visualization:
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 93
field square-P1.field -elevation
field square-P1.field -cut -origin 0.5 0.5 -normal 1 1 -gnuplot
The rst command shows an elevation view of the solution (see 8.1.a) while the second one shows
a cut along the rst bissectrice x
0
= x
1
. (see 8.1.b).
8.2.7 Convergence properties of the xed-point algorithm
p = 1.50
p = 1.20
p = 1.10
r
h

1,h
n
500 0
10
0
10
5
10
10
10
15
p = 2.95
p = 2.90
p = 2.50
r
h

1,h
n
500 0
10
0
10
5
10
10
10
15
v
p
3 2 1
2
1
0
p > 2
p < 2
v
| p 2|
10
0
10
1
10
2
2
1
0
Figure 8.2: The xed-point algorithm on the p-laplacian for N = 2: (a) convergence when p < 2;
(b) when p > 2; (c) convergence rate versus p; (d) convergence rate versus p in semi-log scale.
The xed-point algorithm prints also at each iteration n, the residual term r
n
in discrete H
1
()
and the convergence rate v
n
= log10(r
n
/r
0
)/n. The residual term is dened by
r
(n)
h
= A
h
_
u
(n)
_
M
h
f
h
where A
h
and M
h
are the discrete operators induced by the forms a(.; ., .) and m(., .) on V
h
, and
dened for all u
h
, v
h
V h by:
A
h
(u
h
) v
T
h
= a(u
h
; u
h
, v
h
)
(M
h
u
h
) v
T
h
= m(u
h
, v
h
)
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
94 Rheolef version 5.94 update 27 May 2011
where the elements of V
h
are identied to elements of R
dim(V
h
)
. The W
1,p
() norm, dened for
all r W
1,p
() by duality:
|r|
1,p,
= sup
vW
1,p
()
v1,p,=1
m(r, v)
By analogy, the discrete W
1,p
() norm, denoted as |.|
1,h
, is dened by duality for all r
h
V
h
by:
|r
h
|
1,h
= sup
v
h
V
h
v
h
1,p,=1
m(r
h
, v
h
) = sup
xxdof(V
h
)
[r
h
(x)[
where xdof(V
h
) denotes the set of nodes associated to the V
h
degrees of freedom. Since elements
of V
h
vanishes on the boundary, the xdof(V
h
) contains all nodes associated to the degrees of
freedoms of X
h
except nodes located on the boudnary. Fig 8.2.a and 8.2.b show that the residual
term decreases exponentially versus n, since the slope of the plot in semi-log scale tends to be strait.
Thus, the convergence rate v
n
= log10(r
n
/r
0
)/n tends to a constant, denoted by v. Fig 8.2.c shows
the dependence of v: r
n
r
0
10
v n
. Observe that v tends to + when p = 2, since the system
becomes linear and the algorithm converge in one iteration. Observe also that v tends to zero in
p = 1 and p = 3. The singularity in p = 1 is not surprising, since the problem is dened only
when p > 1. Conversely, the singularity in p = 3 is not clear and requires more analysis. Fig 8.2.d
shows the same plot in semi-log scale and shows that v behaves as: v 2 log
10
([p 2[). Finally,
this study shows that the residual term behaves as:
r
n
2 [p 2[ r
0
10
n
8.3 The Newton algorithm
8.3.1 Principe of the algorithm
An alternative to the xed-point algorithm is to solve the nonlinear problem (P) by using the
Newton algorithm. Let us consider the following operator:
F : W
1,p
0
() W
1,p
()
u F(u) = div
_
[u[
p2
u
_
f
The F operator computes simply the residual term and the problem expresses now as: nd u
W
1,p
0
() such that F(u) = 0.
The Newton algorithm reduces the nonlinear problem into a sequence of linear subproblems: the
sequence
_
u
(n)
_
n0
is classically dened by recurrence as:
n = 0: let u
(0)
W
1,p
0
() be known.
n 0: suppose that u
(n)
is known, nd u
(n)
, dened in , such that:
F

_
u
(n)
_
u
(n)
= F
_
u
(n)
_
and then compute explicitely:
u
(n+1)
:= u
(n)
+u
(n)
The notation F

(u) stands for the Frechet derivative of F, as an operator from W


1,p
() into
W
1,p
0
(). For any r W
1,p
(), the linear tangent problem writes:
nd u W
1,p
0
() such that:
F

(u) u = r
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 95
After the computation of the Frechet derivative, we obtain the strong form of this problem:
(LT): nd u, dened in , such that
div
_
[u[
p2
(u) + (p 2)[u[
p4
u.(u) u
_
= r in
u = 0 on
This is a Poisson-like problem with homogeneous Dirichlet boundary conditions and a non-constant
tensorial coecient. The variational form of the linear tangent problem writes:
(V LT): nd u W
1,p
0
() such that
a
1
(u; u, v) = m(r, v), v W
1,p
0
()
where the a
1
(.; ., .) is dened for any u, u, v W
1,p
0
() by:
a
1
(u; u, v) =
_

_
[u[
p2
(u).(v) + (p 2)[u[
p4
u.(u) u.(v)
_
dx
For any R
N
let us denote by () the following N N matrix:
() = [[
p2
I + (p 2)[[
p4

where I stands for the N-order identity matrix. Then the a
1
expresses in a more compact form:
a
1
(u; u, v) =
_

((u)(u)) .(v) dx
Clearly a
1
is linear and symmetric with respect to the two last variables.
8.3.2 File p-laplacian-newton.cc
#include "rheolef.h"
#include "rheolef/newton.h"
using namespace rheolef;
using namespace std;
#include "p-laplacian.h"
int main(int argc, char**argv) {
geo omega_h (argv[1]);
string approx = (argc > 2) ? argv[2] : "P1";
Float p = (argc > 3) ? atof(argv[3]) : 2.5;
cerr << "# P-Laplacian problem by Newton:" << endl
<< "# geo = " << omega_h.name() << endl
<< "# approx = " << approx << endl
<< "# p = " << p << endl;
p_laplacian F (p, omega_h, approx);
field uh = F.initial();
Float tol = 1e6*numeric_limits<Float>::epsilon();
size_t max_iter = 500;
int status = newton (F, uh, tol, max_iter, &cerr);
cout << setprecision(numeric_limits<Float>::digits10)
<< catchmark("p") << p << endl
<< catchmark("u") << uh;
return status;
}
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
96 Rheolef version 5.94 update 27 May 2011
8.3.3 File p-laplacian.h
class p_laplacian {
public:
typedef field value_type;
typedef Float float_type;
p_laplacian(Float p, const geo& omega_h, string approx = "P1");
void reset(const geo& omega_h, string approx = "previous");
field initial () const;
field residue (const field& uh) const;
void update_derivative (const field& uh) const;
field derivative_solve (const field& mrh) const;
field derivative_trans_mult (const field& mrh) const;
Float norm (const field& uh) const;
Float dual_norm (const field& Muh) const;
Float dot (const field& uh, const field& vh) const;
Float dual_dot (const field& Muh, const field& Mvh) const;
field criteria(const field& uh) const;
Float p;
space Vh, Kh;
field fh;
form m, inv_mt, grad;
ssk<Float> fact_m;
mutable form a1;
mutable ssk<Float> fact_a1;
};
#include "p-laplacian.icc"
8.3.4 File p-laplacian.icc
#include "poisson-dirichlet.icc"
p_laplacian::p_laplacian(Float p1, const geo& omega_h, string approx1)
: p(p1), Vh(), Kh(), fh(),
m(), inv_mt(), grad(), fact_m(), a1(), fact_a1() {
reset(omega_h, approx1);
}
void p_laplacian::reset(const geo& omega_h1, string approx1) {
if (approx1 == "previous") approx1 = Vh.get_approx();
Vh = space(omega_h1, approx1);
Vh.block (omega_h1["boundary"]);
fh = field(Vh, 1);
m = form (Vh, Vh, "mass");
fact_m = ldlt(m.uu);
string grad_approx = (Vh.get_approx() == "P2") ? "P1d" : "P0";
space Th (fh.get_geo(), grad_approx, "vector");
inv_mt = form (Th, Th, "inv_mass");
grad = form (Vh, Th, "grad");
Kh = space(fh.get_geo(), grad_approx, "tensor");
}
field p_laplacian::initial () const {
field uh(Vh);
uh [Vh.get_geo()["boundary"]] = 0;
poisson_dirichlet (fh, uh);
return uh;
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 97
}
void p_laplacian::update_derivative (const field& uh) const {
field grad_uh = inv_mt*(grad*uh);
field norm2_grad_uh = euclidian_norm2(grad_uh);
field w0h = pow(norm2_grad_uh, p/2)/norm2_grad_uh;
field w1h = pow(norm2_grad_uh, p/2)/sqr(norm2_grad_uh);
field eta_h (Kh);
eta_h(0,0) = w0h + (p-2)*w1h*sqr(grad_uh[0]);
if (uh.dimension() >= 2) {
eta_h(1,1) = w0h + (p-2)*w1h*sqr(grad_uh[1]);
eta_h(0,1) = (p-2)*w1h*grad_uh[0]*grad_uh[1];
}
if (uh.dimension() == 3) {
eta_h(2,2) = w0h + (p-2)*w1h*sqr(grad_uh[2]);
eta_h(1,2) = (p-2)*w1h*grad_uh[1]*grad_uh[2];
eta_h(0,2) = (p-2)*w1h*grad_uh[0]*grad_uh[2];
}
a1 = form (Vh, Vh, "grad_grad", eta_h);
fact_a1 = ldlt(a1.uu);
}
field p_laplacian::residue (const field& uh) const {
field grad_uh = inv_mt*(grad*uh);
field norm2_grad_uh = euclidian_norm2(grad_uh);
field w0h = pow(norm2_grad_uh, p/2-1);
form a (Vh, Vh, "grad_grad", w0h);
field mrh = a*uh - m*fh;
mrh.b = 0;
return mrh;
}
field p_laplacian::derivative_solve (const field& mrh) const {
field delta_uh (Vh,0);
delta_uh.u = fact_a1.solve(mrh.u);
delta_uh.b = 0;
return delta_uh;
}
field p_laplacian::derivative_trans_mult (const field& mrh) const {
field rh (Vh);
rh.u = fact_m.solve(mrh.u);
rh.b = 0;
field mgh;
mgh = a1*rh;
mgh.b = 0;
return mgh;
}
Float p_laplacian::dot (const field& uh, const field& vh) const {
return m(uh,vh);
}
Float p_laplacian::norm (const field& uh) const {
return sqrt(m(uh,uh));
}
Float p_laplacian::dual_dot (const field& mrh, const field& msh) const {
field sh (Vh);
sh.u = fact_m.solve(msh.u);
sh.b = 0;
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
98 Rheolef version 5.94 update 27 May 2011
return ::dot(mrh,sh);
}
Float p_laplacian::dual_norm (const field& mrh) const {
return sqrt(dual_dot(mrh,mrh));
}
field p_laplacian::criteria(const field& uh) const {
if (uh.get_approx() == "P1") return abs(uh);
field grad_uh = inv_mt*(grad*uh);
field norm2_grad_uh = euclidian_norm2(grad_uh);
return pow(norm2_grad_uh, p/4);
}
8.3.5 Comments
The code implements a generic Newton algorithm in the le newton.h. The main program
is p-laplacian-newton.cc, that uses a class p-laplacian. This class interface is denied in the
le p-laplacian.h and its implementation in p-laplacian.icc The residual term F(u
h
) is
computed by the member function residual while the resolution of F

(u
h
)u
h
= Mr
h
is performed
by the function derivative solve. The derivative F

(u
h
) is computed separately by the function
update derivative. Notice that the a
1
(u; ., .) bilinear form is a tensorial weighted form, where
(u) is the weight tensor. In rheolef, the tensorial weight eld eta h is inserted as an usual
scalar weight, by passing the weight parameter as the last argument to the form constructor. The
introduction of the class p-laplacian allows an easiest implementation of several variants of the
Newton algorithm.
8.3.6 Running the program
p = 1.7
p = 1.6
p = 1.5
r
h

1,h
n
25 0
10
0
10
5
10
10
10
15
p = 4.0
p = 3.5
p = 3.0
p = 2.5
r
h

1,h
n
25 0
10
0
10
5
10
10
10
15
Figure 8.3: The Newton algorithm on the p-laplacian for N = 2: (a) convergence when p < 2; (b)
when p > 2.
We assume that the previous code is contained in the le p-laplacian-newton.cc. As usual,
enter:
make p-laplacian-newton
mkgeo_grid -t 10 -boundary > square.geo
./p-laplacian-newton square.geo P1 1.5 | field -
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 99
The program prints at each iteration n, the residual term r
n
in discrete L
2
() norm. Fig. 8.3.a
and. 8.3.b shows that the residual terms tends very fast to zero. Observe that the slope is no more
constant in semi-log scale: the convergence rate accelerates and the slope tends to be vertical, the
so-called super-linear convergence. This is the major advantage of the Newton method. Also the
algorithm converge when p 3, until p = 4. It was not the case with the xed point algorithm
that diverges in that case. Finally, the Newton algorithm diverges for small values of p, e.g. p < 1.5
and the plot is not showed here. Conversely, when p > 4, the rst iterations increases dramatically
the residual terms, before to decrease. In that case, another strategy should be considered: the
damped Newton algorithm. This is the subject of the next section.
8.4 The damped Newton algorithm
8.4.1 Principe of the algorithm
The Newton algorithm diverges when the initial u
(0)
is too far from a solution. Our aim is to
modify the Newton algorithm and to obtain a globaly convergent algorith, i.e to converge to a
solution for any initial u
(0)
. The basic idea is to decrease the step length while maintaining the
direction of the original Newton algorithm:
u
(n+1)
:= u
(n)
+
n
u
(n)
where
(n)
]0, 1] and u
(n)
is the direction from the Newton algorithm, given by:
F

_
u
(n)
_
u
(n)
= F
_
u
(n)
_
Let V a Banach space and let T : V R dened for any v V by:
T(v) =
1
2
|C
1
F(v)|
2
V
,
where C is some non-singular operator, easy to invert, used as a non-linear preconditioner. The
simplest case, without preconditioner, is C = I. The T function furnishes a measure of the residual
term in L
2
norm. The convergence is global when for any initial u
(0)
, we have for any n 0:
T
_
u
(n+1)
_
T
_
u
(n)
_
+
_
T

_
u
(n)
_
, u
(n+1)
u
(n)
_
V

,V
(8.1)
where ., .
V

,V
is the duality product between V and its dual V

, and ]0, 1[ is a small parameter.


Notice that
T

(u) = C
1
F

(u)

C
1
F(u)
where the superscript

denotes the adjoint operator, i.e. the transpose matrix the in nite
dimensional case. In practice we consider = 10
4
and we also use a minimal step length

min
= 1/10 in order to avoid too small steps. Let us consider a xed step n 0: for convenience
the n superscript is dropped in u
(n)
and u
(n)
. Let g : R R dened for any R by:
g() = T (u +u)
Then :
g

() = T

(u +u), u
V

,V
= C
1
F(u +u), F

(u +u)C
1
u
V,V

where the superscript

denotes the adjoint operator, i.e. the transpose matrix the in nite
dimensional case. The practical algorithm for obtaining was introduced rst in [34] and is also
presented in [35, p. 385]. The step length that satify (8.1) is computed by using a nite sequence

k
, k = 0, 1 . . . with a second order recurrence:
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
100 Rheolef version 5.94 update 27 May 2011
k = 0 : initialisation
0
= 1. If (8.1) is satied whith u +
0
d then let :=
0
and the
sequence stop here.
k = 1 : rst order recursion. The quantities g(0) = f(u) et g

(0) = f

(u), d are already


computed at initialisation. Also, we already have computed g(1) = f(u +d) when veriying
whether (8.1) was satied. Thus, we consider the following approximation of g() by a
second order polynom:
g
1
() = g(1) g(0) g

(0)
2
+g

(0) +g(0)
After a short computation, we nd that the minimum of this polynom is:

1
=
g

(0)
2g(1) g(0) g

(0)
Since the initialisation at k = 0 does not satisfy (8.1), it is possible to show that, when is
small enougth, we have

1
1/2 and

1
1/2. Let
1
:= max(
min
,

1
). If (8.1) is satised
with u +
1
d then let :=
1
and the sequence stop here.
k 2 : second order recurrence. The quantities g(0) = f(u) et g

(0) =f

(u), d are
available, ytogether with
k1
, g(
k1
),
k2
and g(
k2
). Then, g() is approximed by
the following third order polynom:
g
k
() = a
3
+b
2
+g

(0) +g(0)
where a et b are expressed by:
_
a
b
_
=
1

k1

k2
_
_
_
_
1

2
k1

2
k2

k2

2
k1

k1

2
k2
_
_
_
_
_
g(
k1
) g

(0)
k1
g(0)
g(
k2
) g

(0)
k2
g(0)
_
The minimum of g
k
() is

k
=
b +
_
b
2
3ag

(0)
3a
Let
k
= min(1/2
k
, max(

k
/10,

k+1
) in order for
k
to be at the same order of magnitude
as
k1
. If (8.1) is satised with u +
k
d then let :=
k
and the sequence stop here.
The sequence (
k
)
k0
is strictly decreasing: when the stopping criteria is not satied until
k
reaches the machine precision
mach
then the algorithm stops with an error.
8.4.2 File p-laplacian-damped-newton.cc
#include "rheolef.h"
#include "rheolef/damped-newton.h"
using namespace rheolef;
using namespace std;
#include "p-laplacian.h"
int main(int argc, char**argv) {
geo omega_h (argv[1]);
string approx = (argc > 2) ? argv[2] : "P1";
Float p = (argc > 3) ? atof(argv[3]) : 2.5;
cerr << "# P-Laplacian problem by Newton:" << endl
<< "# geo = " << omega_h.name() << endl
<< "# approx = " << approx << endl
<< "# p = " << p << endl;
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 101
p_laplacian F (p, omega_h, approx);
field uh = F.initial();
Float tol = numeric_limits<Float>::epsilon();
size_t max_iter = 500;
int status = damped_newton (F, uh, tol, max_iter, &cerr);
cout << setprecision(numeric_limits<Float>::digits10)
<< catchmark("p") << p << endl
<< catchmark("u") << uh;
return status;
}
8.4.3 Comments
The le damped-newton-generic.h implements the damped Newton algorithm for a generic T(u)
function, i.e. a generic nonlinear preconditioner. This algorithms use a backtrack strategy imple-
mented in le newton-backtrack.h. The simplest choice of the identity preconditioner C = I
i.e. T(u) = |F(u)|
2
V
/2 is showed in le damped-newton.h. The gradient at = 0 is
T

(u) = F

(u)

F(u)
and the slope at = 0 is:
g

(0) = T

(u), u
V

,V
= F(u), F

(u)u
V

,V

= |F(u)|
2
V

The p-laplacian-damped-newton.cc is the application program to the p-Laplacian problem
together with the |.|
L
2
()
discrete norm for the function T.
8.4.4 Running the program
p = 1.5
p = 1.4
p = 1.3
p = 1.2
r
h

L
2
()
n
50 0
10
0
10
5
10
10
10
15
p = 10
p = 5
p = 4
p = 3
r
h

L
2
()
n
50 0
10
0
10
5
10
10
10
15
Figure 8.4: The damped Newton algorithm on the p-laplacian for N = 2: (a) convergence when
p < 2; (b) when p > 2.
We assume that the previous code is contained in the le p-laplacian-damped-newton.cc. As
usual, enter:
make p-laplacian-damped-newton
mkgeo_grid -t 10 -boundary > square.geo
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
102 Rheolef version 5.94 update 27 May 2011
./p-laplacian-damped-newton square.geo P1 1.5 | field -
./p-laplacian-damped-newton square.geo P1 5.0 | field -
The algorithm is now quite robust: the convergence occurs for a large range of p > 1 values. and
has been pushed until p = 100. The only limitation is due to machine roundo when p = 1.1: the
residual term reaches only 10
10
instead of 10
15
.
8.4.5 Robustness and mesh invariance
50 50
40 40
30 30
20 20
10 10
r
h

L
2
n
15 10 5 0
10
0
10
5
10
10
10
15
50 50
40 40
30 30
20 20
10 10
r
h

L
2
n
15 10 5 0
10
0
10
5
10
10
10
15
50 50
40 40
30 30
20 20
10 10
r
h

L
2
n
150 100 50 0
10
0
10
5
10
10
10
15
50 50
40 40
30 30
20 20
10 10
r
h

L
2
n
15 10 5 0
10
0
10
5
10
10
10
15
Figure 8.5: Convergence versus n for various meshes: (a) Newton algorithm when p = 1.7 and (b)
p = 1.6; (c) Newton algorithm when p = 1.5; (d) damped-Newton algorithm when p = 1.5.
Fig. 8.5.a, 8.5.b and. 8.5.c show the convergence of the Newton method when p = 1.7, 1.6 and
1.5, respectively. Observe that the convergence is asymptotically invariant of the mesh when the
element size decreases. The convergence is more dicult when p decreases to 1.5 and the Newton
algorithm is no more mesh invariant. Fig. 8.5.d shows the convergence of the damped Newton
method when p = 1.5 : the convergence is now very fast and also mesh-invariant.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Chapter 9
Error analysis and singularities
This chapter is in progess...
9.1 Error analysis
(Source le: doc/usrman/dirichlet-nh-error.cc)
9.1.1 Principe
Since the solution u is regular, the following error estimates holds:
|u u
h
|
0,2,
O(h
k+1
)
|u u
h
|
0,,
O(h
k+1
)
providing the approximate solution u
h
uses P
k
continuous nite element method, k 1. Here,
|.|
0,2,
and |.|
0,,
denotes as usual the L
2
() and L

() norms.
By denoting
h
the Lagrange interpolation operator, the triangular inequality leads to:
|u u
h
|
0,2,
|u
h
u|
0,2,
+|u
h

h
u|
0,2,
Since |u
h
u|
0,2,
O(h
k+1
), we have just to check the |u
h

h
u|
0,2,
error term.
9.1.2 Implementation
#include "rheolef/rheolef.h"
using namespace rheolef;
using namespace std;
Float u (const point& x) { return sin(x[0]+x[1]+x[2]); }
int main(int argc, char**argv)
{
field u_h;
cin >> u_h;
space Vh = u_h.get_space();
field pi_h_u = interpolate(Vh, u);
field eh = pi_h_u - u_h;
form m(Vh, Vh, "mass");
103
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
104 Rheolef version 5.94 update 27 May 2011
cout << "error_inf " << eh.max_abs() << endl;
cout << "error_l2 " << sqrt(m(eh,eh)) << endl;
return 0;
}
9.1.3 Running the program
Remarks on step (b) the use of the get space member function. Thus, the previous implementa-
tion does not depend upon the degree of the polynomial approximation.
After compilation, run the code by using the command:
dirichlet-nh square-h=0.1.geo P1 | dirichlet-nh-error
The two errors in L

and L
2
are printed for a h = 0.1 quasi-uniform mesh.
Let nelt denotes the number of elements in the mesh. Since the mesh is quasi-uniform, we have
h nelt
1
N
. Here N = 2 for our bidimensionnal mesh. The gure 9.1 plots in logarithmic scale
the error versus nelt
1
2
for both P
1
(on the left) and P
2
(on the right) approximations.
2=k+1
u
h

h
u
0,,
u
h

h
u
0,2,
nelt

1
2
P
1
element
10
1
10
2
10
3
10
2
10
3
10
4
10
5
10
6
3=k+1
u
h

h
u
0,,
u
h

h
u
0,2,
nelt

1
2
P
2
element
10
1
10
2
10
3
10
4
10
5
10
6
10
7
10
8
Figure 9.1: Error analysis in L
2
and L

norms.
9.2 Computing the Gradient
(Source le: doc/usrman/d-dx.cc)
Remark that the gradient q
h
= u
h
of a continuous picewise linear function u
h
is a discontinuous
piecewise constant function. Conversely, the gradient of a continuous picewise quadratic function
is a discontinuous piecewise linear function.
9.2.1 Formulation
For all i = 1 . . . N, the i-th component q
h,i
of the gradient belongs to the space:
T
h

h
L
2
();
h/K
P
k1
, K T
h

c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 105
By introducing the two following bilinear forms:
m
T
(
h
,
h
) =
_

h
dx
b
i
(u
h
,
h
) =
_

u
h
x
i

h
dx
the gradient satises the following variational formulation:
m
T
(q
h,i
,
h
) = b
i
(u
h
,
h
),
h
Th
Remark that the matrix associated to the m
T
(., , ) bilinear form is block-diagonal. Each block is
associated to an element, and can be inverted at the element level. The following code uses this
property on step (e), as the "inv mass" form.
9.2.2 Implementation
#include "rheolef/rheolef.h"
using namespace rheolef;
using namespace std;
string get_approx_grad (const space &Vh)
{
string Pk = Vh.get_approx();
if (Pk == "P1") return "P0";
if (Pk == "P2") return "P1d";
cerr << "unexpected approximation " << Pk << endl;
exit (1);
}
int main(int argc, char**argv)
{
field uh;
cin >> uh;
space Vh = uh.get_space();
geo omega_h = Vh.get_geo();
string approx_grad = get_approx_grad(Vh);
space Th (omega_h, approx_grad);
form b(Vh, Th, "d_dx0");
form inv_mass (Th, Th, "inv_mass");
field du_dx0 = inv_mass*(b*uh);
int digits10 = numeric_limits<Float>::digits10;
cout << setprecision(digits10) << du_dx0;
}
9.3 Error analysis for the gradient
(Source le: doc/usrman/demo2-error-grad.cc)
The following estimation holds for the gradient:
|u u
h
|
0,2,
O(h
k
)
|u u
h
|
0,,
O(h
k
)
The gure 9.2 plots in logarithmic scale the error for the gradient versus nelt
1
2
for both P
1
(on
the left) and P
2
(on the right) approximations.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
106 Rheolef version 5.94 update 27 May 2011
1=k
(u
h

h
u)
0,,
(u
h

h
u)
0,2,
nelt

1
2
P
1
element
10
1
10
2
10
3
10
1
10
2
10
3
2=k
(u
h

h
u)
0,,
(u
h

h
u)
0,2,
nelt

1
2
P
2
element
10
1
10
2
10
3
10
1
10
2
10
3
10
4
10
5
Figure 9.2: Error analysis for the gradiend: H
1
and W
1,
norms.
9.3.1 Implementation
#include "rheolef/rheolef.h"
using namespace rheolef;
using namespace std;
Float du_dxi (const point& x) { return cos(x[0]+x[1]+x[2]); }
int main(int argc, char**argv)
{
field qh;
cin >> qh;
space Th = qh.get_space();
field pi_h_q = interpolate(Th, du_dxi);
field eh = pi_h_q - qh;
form m(Th, Th, "mass");
cerr << "error_inf " << eh.max_abs() << endl;
cerr << "error_l2 " << sqrt(m(eh,eh)) << endl;
if (argc > 1) cout << eh;
return 0;
}
9.4 A problem with singularity
(Source le: doc/usrman/crack.cc)
9.4.1 Formulation
Let us now consider the Laplace operator in a non-convex domain. The domain is a disk with a
missing part, thus there exists a re-entrant corner (see Figure, on the left). The angle associated
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 107
to the re-entrant corner is denoted by and whe suppose < 2. We assume homogeneous
Dirichlet conditions on the boundaries corresponding to the radius, and denoted by
0
. The rest
of the boundary is related to the envelop boundary and denoted by
e
.

(a) (b)
x
1
x
2
Figure 9.3: The domain of computation: (a) with a crack; (b) by using the Ox
1
symetry.
The problem expresses:
nd u dened in such that
u = 0 in
u = 0 on
0
u = g on
e
where g is expressed by the use of polar coordinates:
g(r, ) = r

sin()
and
=

The parameter is the intensity of the singularity at x = 0 (see e.g. [36]). This problem is
convenient since the exact solution is known: u = r

sin(). The problem for = 2 is related


to a crack (see Figure, on the right) and the intensity is = 1/2. Notes that there is a symmetry
axis, and the domain can be reduced to y > 0. The symmetry axis is associated to a homogeneous
Neumann condition for x < 0, and the corresponding boundary is denoted by
s
. For the problem
reduced to the half domain, the boundary conditions changes from homogeneous Neumann to
homogeneous Dirichlet, while the half domain is convex.
The problem can be implemented as the example of the previous sections. In order to put Dirichlet
condition on the boundary domains "crack" and "envelop", we block the related degrees of
freedom:
Vh.block ("envelop");
Vh.block ("crack");
while degrees of freedom on the "symmetry" domain, associated to homogeneous Neumann con-
dition, are unknown.
9.4.2 Implementation
// usage: crach <geo> [-diff|-exact]
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
108 Rheolef version 5.94 update 27 May 2011
#include "rheolef/rheolef.h"
using namespace rheolef;
using namespace std;
Float alpha = 0.5; // the singularity at r=0
Float u_crack(const point& x)
{
Float r = sqrt(x[0]*x[0] + x[1]*x[1]);
if (1 + r == Float(1)) return 0;
Float theta = atan2(x[1], x[0]); // in ]-pi,pi]
return pow(r,alpha)*sin(alpha*theta);
}
int main(int argc, char**argv)
{
geo omega(argv[1]);
space Vh (omega, argv[2]);
Vh.block ("envelop");
Vh.block ("crack");
form a(Vh, Vh,"grad_grad");
ssk<Float> fact = ldlt(a.uu);
field u = interpolate(Vh, u_crack);
field uh (Vh);
uh.b = u.b;
uh.u = fact.solve(- (a.ub*uh.b));
field eh = u - uh;
form m(Vh, Vh, "mass");
cerr << "error_l2 " << sqrt(m(eh, eh)) << endl;
cerr << "error_infinity " << eh.max_abs() << endl;
// H1 error
string approx_grad = (strcmp(argv[2],"P1") == 0) ? "P0" : "P1d";
space Th (omega, approx_grad);
form d_dx0(Vh, Th, "d_dx0");
form d_dx1(Vh, Th, "d_dx1");
form inv_mt (Th, Th, "inv_mass");
field deh_dx0 = inv_mt*(d_dx0*eh);
field deh_dx1 = inv_mt*(d_dx1*eh);
form mt (Th, Th, "mass");
cerr << "error_h1 " << sqrt(mt(deh_dx0, deh_dx0)
+mt(deh_dx1, deh_dx1))
<< endl;
int digits10 = numeric_limits<Float>::digits10;
cout << setprecision(digits10);
if (argc == 2) {
cout << uh;
} else {
if (strcmp(argv[2],"-exact") == 0) { cout << u; }
else if (strcmp(argv[2],"-diff") == 0) { cout << u-uh; }
else { cout << uh; }
}
return 0;
}
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 109
9.4.3 Analysis
1=+
1
2
1
2
=
u u
h

0,2,
u u
h

0,,
P
1
element
nelt

1
2
10
0
10
1
10
2
10
3
10
1
10
2
10
3
1=+
1
2
1
2
=
u u
h

0,2,
u u
h

0,,
P
2
element
nelt

1
2
10
0
10
1
10
2
10
3
10
1
10
2
10
3
Figure 9.4: Error analysis for a domain with a crack.
The gure plots the error in L
2
and L

norms for both P


1
(on the left) and P
2
(on the right) by
using a familly of unifom meshes. First, remarks that the order of convergence is not improved by
using P
2
elements. This case is dierent from the situation when the solution was regular. More
precisely, the following error estimates holds:
|u u
h
|
0,2,
O(h
min(+
1
2
,k+1)
)
|u u
h
|
0,,
O(h
min(,k+1)
)
The nite element mesh adaptation is an ecient way to restaure the optimal convergence rate
versus the mesh size, as we will see in the next paragraph.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
110 Rheolef version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Bibliography
[1] S. Brenner and R. Scott. The mathematical theory of nite element methods. Springer-Verlag,
1991. 9, 89
[2] P. Saramito and N. Roquet. An adaptive nite element method for viscoplastic uid ows in
pipes. Comput. Meth. Appl. Mech. Engrg., (to appear), 2000. 16
[3] V. Girault and P. A. Raviart. Finite Element Methods for Navier-Stokes EquationsTheory
and Algorithms. Springer Verlag, 1986. 25, 46, 48
[4] C. C. Paige and M. A. Saunders. Solution of sparse indenite sys-
tems of linear equations. SIAM J. Numer. Anal., 12(4):617629, 1975.
http://www.stanford.edu/group/SOL/software.html. 25
[5] Y. Saad. Iterative methods for sparse linear systems. SIAM, Philadelphia, USA, second
edition, 2000. 27
[6] N. Roquet, R. Michel, and P. Saramito. Estimations derreur pour un uide viscoplastique
par elements nis P
k
et maillages adaptes. C. R. Acad. Sci. Paris, serie I, to appear. 39
[7] N. Roquet. Simulation numerique decoulements de uides viscoplastiques par un algorithme
de Lagrangien augmente et une methode delements nis incompressibles. Universite dOrsay
Paris-Sud, Prebublication 97-21, 1997. 39
[8] F. Hecht. Bidimensional anisotropic mesh generator, version 0.67. INRIA, october 1998.
ftp://ftp.inria.fr/INRIA/Projects/Gamma/bamg/. 39, 117
[9] H. Borouchaki, P. L. George, F. Hecht, P. Laug, and E. Saltel. Delaunay mesh generation
governed by metric specications. Part I: Algorithms. Finite Elem. Anal. Des., 25:6183,
1997. 39
[10] M. J. Castro-Diaz, F. Hecht, B. Mohammadi, and O. Pironneau. Anisotropic unstructured
mesh adaption for ow simulations. Int. J. Numer. Methods Fluids, 25:475491, 1997. 39
[11] M. G. Vallet. Generation de maillages anisotropes adaptes. Application `a la capture de couches
limites. Rapport de Recherche n
0
1360, INRIA, 1990. 39
[12] P. Hood and C. Taylor. A numerical solution of the Navier-Stokes equations using the nite
element technique. Comp. and Fluids, 1:73100, 1973. 42, 52, 67
[13] A. Klawonn. An optimal preconditioner for a class of saddle point problems with a penalty
term. SIAM J. Sci. Comput, 19(2):540552, 1998. 44, 53
[14] D. N. Arnold, F. Brezzi, and M. Fortin. A stable nite element for the Stokes equations.
1983. 54
[15] E. M. Abdalass. Resolution performante du probl`eme de Stokes par mini-elements, maillages
auto-adaptatifs et methodes multigrilles - applications. Th`se de l

Ecole Centrale de Lyon,


1987. 56
111
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
112 Rheolef version 5.94 update 27 May 2011
[16] F. Brezzi and J. Pitkaranta. On the stabilization of nite element approximation of the Stokes
equations. In Ecient solutions of elliptic systems, Kiel, Notes on numerical uid mechanics,
volume 10, pages 1119, 1984. 56
[17] O. Pironneau. Methode des elements nis pour les uides. Masson, 1988. 63
[18] H. Rui and M. Tabata. A second order characteristic nite element scheme for convection
diusion problems. Numer. Math. (to appear), 2001. 63
[19] D. R. Musser and A. Saini. STL tutorial and reference guide. Addison-Wesley, 1996. 64
[20] K. Boukir, Y. Maday, B. Metivet, and E. Razandrakoto. A high-order characteristic/nite
element method for the incompressible Navier-Stokes equations. Int. J. Numer. Meth. Fluids,
25:14211454, 1997. 66
[21] G. Fourestey and S. Piperno. A second-order time-accurate ALE Lagrange-Galerkin method
applied to wind engineering and control of bridge proles. Comput. Methods Appl. Mech.
Engrg., 193:41174137, 2004. 66
[22] Cahouet and J.-P. Chabard. Some fast 3d nite element solvers for the generalized Stokes
problem. Int. J. Numer. Meth. Fluids, 8(8):869895, 1988. 68
[23] G. M. Kobelkov and M. A. Olshanskii. Eective preconditioning of Uzawa type
schemes for a generalized Stokes problem. Numer. Math., 86:443470, 2000.
http://www.mathcs.emory.edu/ molshan/ftp/pub/gstokes.pdf. 68
[24] U. Ghia, K. N. Ghia, and C. T. Shin. High Re solutions for incompressible ow using the
Navier-Stokes equations and a multigrid method. J. Comput. Phys., 48:387411, 1982. 73,
135
[25] M. M. Gupta and J. C. Kalita. A new paradigm for solving Navier-Stokes equa-
tions: streamfunction-velocity formulation. J. Comput. Phys., 207:5268, 2005.
http://www.cours.polymtl.ca/mec6616/cavite 2.pdf. 73
[26] R. J. Labeur and G. N. Wells. A Galerkin interface stabilisation method for the advection-
diusion and incompressible Navier-Stokes equations. Comput. Meth. Appl. Mech. Engrg.,
196(4952):49855000, 2007. 73
[27] J. Donea and A. Huerta. Finite element methods for ow problems. Wiley, New-York, 2003.
73
[28] J. Shen. Hopf bifurcation of the unsteady regularized driven cavity ow. J. Comp. Phys.,
95:228245, 1991. http://www.math.purdue.edu/ shen/pub/Cavity.pdf. 74
[29] F. Auteri, N. Parolini, and L. Quartapelle. Numerical investigation on the stability of singular
driven cavity ow. J. Comput. Phys., 183(1):125, 2002. 74
[30] E. Erturk, T. C. Corke, and C. Gokcol. Numerical solutions of 2-D steady incompressible
driven cavity ow at high Reynolds numbers. Int. J. Numer. Meth. Fluids, 48:747774, 2005.
74
[31] T. Gelhard, G. Lube, M. A. Olshanskii, and J. H. Starcke. Stabilized nite element schemes
with LBB-stable elements for incompressible ows. J. Comput. Appl. Math., 177:243267,
2005. 74
[32] P. D. Minev and C. R. Ethier. A characteristic/nite element algorithm for the 3-D Navier-
Stokes equations using unstructured grids. Comput. Meth. in Appl. Mech. and Engrg., 178(1-
2):3950, 1998. 74
[33] H. Brezis. Analyse fonctionnelle. Theorie et application. Masson, Paris, 1983. 89
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 113
[34] Jr. J. E. Dennis and R. B. Schnablel. Numerical methods for unconstraint optimization and
nonlinear equations. Prentice Hall, Englewood Cli, N. J., 1983. 99
[35] W. H. Press, S. A. Teulkolsky, W. T. Vetterling, and B. P. Flannery. Numerical recepies in
C. The art of scientic computing. Cambridge University Press, UK, second edition, 1997.
Version 2.08. 99
[36] P. Grisvard. Probl`emes aux limites dans les polygones. mode demploi. Buletin de la direction
des etudes et recherches, serie C, EDF, 1986. 107
[37] C. Geuzaine and J.-F. Remacle. Gmsh: a three-dimensional nite element mesh generator
with built-in pre- and post-processing facilities. Int. J. Numer. Meths Engrg., 79(11):1309
1331, 2009. 117, 120
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
114 Rheolef version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Part IV
Technical appendices
115
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Appendix A
How to prepare a mesh ?
Since there is many good mesh generators, rheolef does not provide a built-in mesh generator.
There are several ways to prepare a mesh for rheolef.
We present here several procedures: by using the bamg bidimensional anisotropic mesh generator,
written by Frederic Hecht [8], and the gmsh bi- and tridimensional mesh generator, written by
Christophe Geuzaine and Jean-Franois Remacle [37].
A.1 Bidimensionnal mesh with bamg
We rst create a my-square.bamgcad le:
MeshVersionFormatted
0
Dimension
2
Vertices
4
0 0 1
1 0 2
1 1 3
0 1 4
Edges
4
1 2 101
2 3 102
3 4 103
4 1 104
hVertices
0.1 0.1 0.1 0.1
This is an uniform mesh with element size h = 0.1. We refer to the bamg documentation [8] for
the complete le format description. Next, enter the mesh generator commands:
bamg -g my-square.bamgcad -o my-square.bamg
Then, create the le my-square.dmn that associate names to the four boundary domains of the
mesh. Here, there is four boundary domains:
117
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
118 Rheolef version 5.94 update 27 May 2011
EdgeDomainNames
4
bottom
right
top
left
and enter the translation command:
bamg2geo my-square.bamg my-square.dmn > my-square.geo
This command creates a my-square.geo le. Look at the mesh via the command:
geo my-square
This presents the mesh it in a graphical form, usually with mayavi. You can switch to the gnuplot
renders:
geo my-square -gnuplot
A ner mesh could be generated by:
bamg -coef 0.5 -g my-square.bamgcad -o my-square-0.5.bamg
One inconvenience of bamg is that it does not provide multi-region support. However, if the two
regions desired in a mesh are separated with a boundary named, e.g., interface, and that there
exists another boundary domain in the mesh which is away from one of the regions, say top,
rheolef can label the two regions and create two domains for them:
omega.build_subregion(omega["top"],omega["interface"],"north","south");
where region north will have domain top in its boundary, while region south is away from it,
and separated from north by interface. To do this, the le my-square.dmn can be modied to
have 5 domain names, appending the name interface, and the le my-square.bamgcad can be
modied in this way:
The domains omega["north"] and omega["south"] can be used in the same way as is done in
section 7.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 119
A.2 Bidimensionnal mesh with gmsh
Figure A.1: Visualization of the gmsh meshes my-square.geo and my-cube.geo.
We rst create a my-square.mshcad le:
Mesh.Algorithm = 5;
Mesh.Optimize = 1;
// Mesh.OptimizeNetgen = 1; // uncomment if gmsh is compiled with netgen
h_local = 0.1;
Point(1) = {0, 0, 0, h_local};
Point(2) = {1, 0, 0, h_local};
Point(3) = {1, 1, 0, h_local};
Point(4) = {0, 1, 0, h_local};
Line(1) = {1,2};
Line(2) = {2,3};
Line(3) = {3,4};
Line(4) = {4,1};
Line Loop(5) = {1,2,3,4};
Plane Surface(6) = {5} ;
Physical Point("left_bottom") = {1};
Physical Point("right_bottom") = {2};
Physical Point("right_top") = {3};
Physical Point("left_top") = {4};
Physical Line("bottom") = {1};
Physical Line("right") = {2};
Physical Line("top") = {3};
Physical Line("left") = {4};
Physical Line("boundary") = {1,2,3,4};
Physical Surface("interior") = {6};
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
120 Rheolef version 5.94 update 27 May 2011
This is an uniform mesh with element size h = 0.1. We refer to the gmsh documentation [37] for
the complete le format description. Next, enter the mesh generator commands:
gmsh -2 my-square.mshcad -o my-square.msh
Then, enter the translation command:
msh2geo my-square.msh > my-square.geo
This command creates a my-square.geo le. Look at the mesh via the command:
geo my-square
Remark that the domain names, dened in the .mshcad le, are included in the gmsh .msh input
le and are propagated in the .geo by the format conversion.
A.3 Tridimensionnal mesh with gmsh
First, create a my-cube.mshcad le:
h_local = 0.1;
Point(1) = {0, 0, 0, h_local};
Point(2) = {1, 0, 0, h_local};
Point(3) = {1, 1, 0, h_local};
Point(4) = {0, 1, 0, h_local};
Point(5) = {0, 0, 1, h_local};
Point(6) = {1, 0, 1, h_local};
Point(7) = {1, 1, 1, h_local};
Point(8) = {0, 1, 1, h_local};
Line(1) = {1,2};
Line(2) = {2,3};
Line(3) = {3,4};
Line(4) = {4,1};
Line(5) = {5,6};
Line(6) = {6,7};
Line(7) = {7,8};
Line(8) = {8,5};
Line(9) = {1,5};
Line(10) = {2,6};
Line(11) = {3,7};
Line(12) = {4,8};
Line Loop(21) = {-1,-4,-3,-2};
Plane Surface(31) = {21} ;
Physical Surface("bottom") = {31};
Line Loop(22) = {5,6,7,8};
Plane Surface(32) = {22} ;
Physical Surface("top") = {32};
Line Loop(23) = {1,10,-5,-9};
Plane Surface(33) = {23} ;
Physical Surface("left") = {33};
Line Loop(24) = {2,11,-6,-10};
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 121
Plane Surface(34) = {24} ;
Physical Surface("front") = {34};
Line Loop(25) = {12,-7,-11,3};
Plane Surface(35) = {25} ;
Physical Surface("right") = {35};
Line Loop(26) = {9,-8,-12,4};
Plane Surface(36) = {26} ;
Physical Surface("back") = {36};
Surface Loop(41) = {31,32,33,34,35,36};
Volume(51) = {41};
Physical Volume("interior") = {51};
Next, enter the mesh generator commands:
gmsh -3 my-cube.mshcad -o my-cube.msh
Then, enter the translation command:
msh2geo my-cube.msh > my-cube.geo
This command creates a my-cube.geo le. Look at the mesh via the command:
geo my-cube
geo my-cube.geo -cut -normal 0 0 1 -origin 0.5 0.5 0.5
The second command allows to see inside the mesh.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
122 Rheolef version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Appendix B
GNU Free Documentation License
Version 1.1, March 2000
Copyright c _ 2000 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but chang-
ing it is not allowed.
Preamble
The purpose of this License is to make a manual, textbook, or other written document free
in the sense of freedom: to assure everyone the eective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially. Secondarily, this License
preserves for the author and publisher a way to get credit for their work, while not being considered
responsible for modications made by others.
This License is a kind of copyleft, which means that derivative works of the document must
themselves be free in the same sense. It complements the GNU General Public License, which is
a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software
needs free documentation: a free program should come with manuals providing the same freedoms
that the software does. But this License is not limited to software manuals; it can be used for
any textual work, regardless of subject matter or whether it is published as a printed book. We
recommend this License principally for works whose purpose is instruction or reference.
B.1 Applicability and Denitions
This License applies to any manual or other work that contains a notice placed by the copyright
holder saying it can be distributed under the terms of this License. The Document, below, refers
to any such manual or work. Any member of the public is a licensee, and is addressed as you.
A Modied Version of the Document means any work containing the Document or a portion of
it, either copied verbatim, or with modications and/or translated into another language.
A Secondary Section is a named appendix or a front-matter section of the Document that deals
exclusively with the relationship of the publishers or authors of the Document to the Documents
overall subject (or to related matters) and contains nothing that could fall directly within that
overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary
Section may not explain any mathematics.) The relationship could be a matter of historical
123
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
124 Rheolef version 5.94 update 27 May 2011
connection with the subject or with related matters, or of legal, commercial, philosophical, ethical
or political position regarding them.
The Invariant Sections are certain Secondary Sections whose titles are designated, as being those
of Invariant Sections, in the notice that says that the Document is released under this License.
The Cover Texts are certain short passages of text that are listed, as Front-Cover Texts or
Back-Cover Texts, in the notice that says that the Document is released under this License.
A Transparent copy of the Document means a machine-readable copy, represented in a format
whose specication is available to the general public, whose contents can be viewed and edited
directly and straightforwardly with generic text editors or (for images composed of pixels) generic
paint programs or (for drawings) some widely available drawing editor, and that is suitable for
input to text formatters or for automatic translation to a variety of formats suitable for input to
text formatters. A copy made in an otherwise Transparent le format whose markup has been
designed to thwart or discourage subsequent modication by readers is not Transparent. A copy
that is not Transparent is called Opaque.
Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo
input format, L
A
T
E
X input format, SGML or XML using a publicly available DTD, and standard-
conforming simple HTML designed for human modication. Opaque formats include PostScript,
PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML
or XML for which the DTD and/or processing tools are not generally available, and the machine-
generated HTML produced by some word processors for output purposes only.
The Title Page means, for a printed book, the title page itself, plus such following pages as are
needed to hold, legibly, the material this License requires to appear in the title page. For works
in formats which do not have any title page as such, Title Page means the text near the most
prominent appearance of the works title, preceding the beginning of the body of the text.
B.2 Verbatim Copying
You may copy and distribute the Document in any medium, either commercially or noncommer-
cially, provided that this License, the copyright notices, and the license notice saying this License
applies to the Document are reproduced in all copies, and that you add no other conditions what-
soever to those of this License. You may not use technical measures to obstruct or control the
reading or further copying of the copies you make or distribute. However, you may accept com-
pensation in exchange for copies. If you distribute a large enough number of copies you must also
follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may publicly display
copies.
B.3 Copying in Quantity
If you publish printed copies of the Document numbering more than 100, and the Documents
license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and
legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify you as the publisher of these
copies. The front cover must present the full title with all words of the title equally prominent
and visible. You may add other material on the covers in addition. Copying with changes limited
to the covers, as long as they preserve the title of the Document and satisfy these conditions, can
be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to t legibly, you should put the rst ones
listed (as many as t reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 125
either include a machine-readable Transparent copy along with each Opaque copy, or state in
or with each Opaque copy a publicly-accessible computer-network location containing a complete
Transparent copy of the Document, free of added material, which the general network-using public
has access to download anonymously at no charge using public-standard network protocols. If you
use the latter option, you must take reasonably prudent steps, when you begin distribution of
Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the
stated location until at least one year after the last time you distribute an Opaque copy (directly
or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before
redistributing any large number of copies, to give them a chance to provide you with an updated
version of the Document.
B.4 Modications
You may copy and distribute a Modied Version of the Document under the conditions of sections
2 and 3 above, provided that you release the Modied Version under precisely this License, with
the Modied Version lling the role of the Document, thus licensing distribution and modication
of the Modied Version to whoever possesses a copy of it. In addition, you must do these things
in the Modied Version:
Use in the Title Page (and on the covers, if any) a title distinct from that of the Document,
and from those of previous versions (which should, if there were any, be listed in the History
section of the Document). You may use the same title as a previous version if the original
publisher of that version gives permission.
List on the Title Page, as authors, one or more persons or entities responsible for authorship
of the modications in the Modied Version, together with at least ve of the principal
authors of the Document (all of its principal authors, if it has less than ve).
State on the Title page the name of the publisher of the Modied Version, as the publisher.
Preserve all the copyright notices of the Document.
Add an appropriate copyright notice for your modications adjacent to the other copyright
notices.
Include, immediately after the copyright notices, a license notice giving the public permission
to use the Modied Version under the terms of this License, in the form shown in the
Addendum below.
Preserve in that license notice the full lists of Invariant Sections and required Cover Texts
given in the Documents license notice.
Include an unaltered copy of this License.
Preserve the section entitled History, and its title, and add to it an item stating at least
the title, year, new authors, and publisher of the Modied Version as given on the Title
Page. If there is no section entitled History in the Document, create one stating the title,
year, authors, and publisher of the Document as given on its Title Page, then add an item
describing the Modied Version as stated in the previous sentence.
Preserve the network location, if any, given in the Document for public access to a Trans-
parent copy of the Document, and likewise the network locations given in the Document
for previous versions it was based on. These may be placed in the History section. You
may omit a network location for a work that was published at least four years before the
Document itself, or if the original publisher of the version it refers to gives permission.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
126 Rheolef version 5.94 update 27 May 2011
In any section entitled Acknowledgements or Dedications, preserve the sections title,
and preserve in the section all the substance and tone of each of the contributor acknowl-
edgements and/or dedications given therein.
Preserve all the Invariant Sections of the Document, unaltered in their text and in their
titles. Section numbers or the equivalent are not considered part of the section titles.
Delete any section entitled Endorsements. Such a section may not be included in the
Modied Version.
Do not retitle any existing section as Endorsements or to conict in title with any Invariant
Section.
If the Modied Version includes new front-matter sections or appendices that qualify as Secondary
Sections and contain no material copied from the Document, you may at your option designate
some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections
in the Modied Versions license notice. These titles must be distinct from any other section titles.
You may add a section entitled Endorsements, provided it contains nothing but endorsements
of your Modied Version by various parties for example, statements of peer review or that the
text has been approved by an organization as the authoritative denition of a standard.
You may add a passage of up to ve words as a Front-Cover Text, and a passage of up to 25 words as
a Back-Cover Text, to the end of the list of Cover Texts in the Modied Version. Only one passage
of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made
by) any one entity. If the Document already includes a cover text for the same cover, previously
added by you or by arrangement made by the same entity you are acting on behalf of, you may not
add another; but you may replace the old one, on explicit permission from the previous publisher
that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use
their names for publicity for or to assert or imply endorsement of any Modied Version.
B.5 Combining Documents
You may combine the Document with other documents released under this License, under the terms
dened in section 4 above for modied versions, provided that you include in the combination all
of the Invariant Sections of all of the original documents, unmodied, and list them all as Invariant
Sections of your combined work in its license notice.
The combined work need only contain one copy of this License, and multiple identical Invariant
Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same
name but dierent contents, make the title of each such section unique by adding at the end of
it, in parentheses, the name of the original author or publisher of that section if known, or else a
unique number. Make the same adjustment to the section titles in the list of Invariant Sections
in the license notice of the combined work.
In the combination, you must combine any sections entitled History in the various original
documents, forming one section entitled History; likewise combine any sections entitled Ac-
knowledgements, and any sections entitled Dedications. You must delete all sections entitled
Endorsements.
B.6 Collections of Documents
You may make a collection consisting of the Document and other documents released under this
License, and replace the individual copies of this License in the various documents with a single
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Rheolef version 5.94 update 27 May 2011 127
copy that is included in the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under
this License, provided you insert a copy of this License into the extracted document, and follow
this License in all other respects regarding verbatim copying of that document.
B.7 Aggregation With Independent Works
A compilation of the Document or its derivatives with other separate and independent documents
or works, in or on a volume of a storage or distribution medium, does not as a whole count
as a Modied Version of the Document, provided no compilation copyright is claimed for the
compilation. Such a compilation is called an aggregate, and this License does not apply to
the other self-contained works thus compiled with the Document, on account of their being thus
compiled, if they are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if
the Document is less than one quarter of the entire aggregate, the Documents Cover Texts may
be placed on covers that surround only the Document within the aggregate. Otherwise they must
appear on covers around the whole aggregate.
B.8 Translation
Translation is considered a kind of modication, so you may distribute translations of the Docu-
ment under the terms of section 4. Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include translations of some or all Invariant
Sections in addition to the original versions of these Invariant Sections. You may include a trans-
lation of this License provided that you also include the original English version of this License.
In case of a disagreement between the translation and the original English version of this License,
the original English version will prevail.
B.9 Termination
You may not copy, modify, sublicense, or distribute the Document except as expressly provided
for under this License. Any other attempt to copy, modify, sublicense or distribute the Document
is void, and will automatically terminate your rights under this License. However, parties who
have received copies, or rights, from you under this License will not have their licenses terminated
so long as such parties remain in full compliance.
B.10 Future Revisions of This License
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation
License from time to time. Such new versions will be similar in spirit to the present version, but
may dier in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document species
that a particular numbered version of this License or any later version applies to it, you have the
option of following the terms and conditions either of that specied version or of any later version
that has been published (not as a draft) by the Free Software Foundation. If the Document does
not specify a version number of this License, you may choose any version ever published (not as
a draft) by the Free Software Foundation.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
128 Rheolef version 5.94 update 27 May 2011
ADDENDUM: How to use this License for your documents
To use this License in a document you have written, include a copy of the License in the document
and put the following copyright and license notices just after the title page:
Copyright c _ YEAR YOUR NAME. Permission is granted to copy, distribute and/or
modify this document under the terms of the GNU Free Documentation License, Ver-
sion 1.1 or any later version published by the Free Software Foundation; with the
Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being
LIST, and with the Back-Cover Texts being LIST. A copy of the license is included in
the section entitled GNU Free Documentation License.
If you have no Invariant Sections, write with no Invariant Sections instead of saying which
ones are invariant. If you have no Front-Cover Texts, write no Front-Cover Texts instead of
Front-Cover Texts being LIST; likewise for Back-Cover Texts.
If your document contains nontrivial examples of program code, we recommend releasing these
examples in parallel under your choice of free software license, such as the GNU General Public
License, to permit their use in free software.
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Index of concepts
catchmark stream manipulator, 33
adaptive mesh, 39, 70
ajoint operator, 99
algorithm
damped Newton, 99
xed-point, 90, 99
Newton, 94
animation, 62
approximation, 10, 18, 20, 25, 32, 42, 52, 54,
59
P0, 36, 38
P1d, 36, 38
P1, 10, 31, 38, 42, 52, 54, 66
P2, 10, 31, 38, 42, 52, 66
bubble, 54
axisymetric geometry, 56
block-diagonal matrix, 104
boundary condition
Dirichlet, 9, 17, 31, 42, 51, 66, 83, 89, 95
Neumann, 20, 24, 31, 51, 83
Neuman, 68
Robin, 22
Characteristic method, 63
characteristic method, 63, 66
Choleski factorization, 12
class
Float, 17, 86
asr<T>, 27
branch, 60
csr<T>, 27
doubledouble, 17
field, 10
form diag, 85
form manip, 55
form, 10
geomap, 64, 70
geo, 10, 56
pcg solver, 44
point, 17
space, 10
ssk<T>, 10
class-function, 64
compilation, 12
conjugate gradient, 12
conjugate gradient algorithm, 44, 53, 68
convection-diusion problem, 62
convergence
super-linear, 99
convergence rate, 93, 94
crack, 106
degree of freedom, 94
diusion tensor, 86
Dirichlet boundary condition, 9, 17, 31, 42,
51, 66, 83
discontinuous approximation, 104
discontinuous eld, 36, 38
discrete operator, 93
driven cavity, 42, 66
elasticity problem, 31
elevation view, 93
ellipsoid, for tensor visualization, 37
embankment, 31
energy, 9, 84, 89
error analysis, 103, 105
Euler implicit scheme, 59, 62
oating point precision, 86
form
2D D, 31, 42, 51, 55, 66
2D, 35
curl, 46
div div, 31, 51, 55
div, 35, 42, 51, 55, 66
grad grad s, 80
grad grad, 10, 77
grad, 85
inv mass, 35, 85
mass s, 80
mass, 10, 77, 85, 103, 104
weighted, 90
tensorial weight, 98
Frechet derivative, 94
function
129
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
130 Rheolef version 5.94 update 27 May 2011
catchmark, 27, 60, 86
compose, 64, 70
ic0, 12, 44
interpolate, 64
pcg abtbc, 53
pcg abtb, 44
pcg, 12, 44
gradient, 104
heat equation, 59
incompressible elasticity problem, 51
interpolation on a new mesh, 70
Lagrange interpolation, 17, 20, 25, 70
Lagrange node, 11
Lame coecients, 31
Laplace-Beltrami operator, 77
linear tangent problem, 94
matrix
compressed sparse row format, 27
mesh, 10, 113
mesh generation, 113
mixed formulation, 84
Navier-Stokes problem, 66
Neumann boundary condition, 20, 24, 31, 51,
83, 106
node, 94
nonlinear problem, 66
norm
in W
1,p
, 94
discrete version, 94
in W
1,p
, 89
in W
1,p
0
, 89
Poiseuille ow, 56
Poisson problem, 9, 17, 20, 22, 24, 59, 68
polar coordinate system, 56
preconditioner, 44, 53, 68
preconditionner
Choleski icomplete factorization, 12
problem
Navier-Stokes, 66
Poisson
non-constant tensorial coecients, 95
Poisson, 9, 17, 20, 22, 24, 68, 89, 92
Stokes, 42, 54, 66
convection-diusion, 62
elasticity, 31
heat, 59
incompressible elasticity, 51
p-laplacian, 89
transmission, 83
projection, 37, 47
quadtree, 63
region, 83, 86, 114
residual term, 93, 94
Robin boundary condition, 22
shell script, 62
singularity, 106
space
W
1,p
, dual of W
1,p
0
, 94
W
1,p
, 89
W
1,p
0
, 89
dual, 94
stabilization, 51
stabilized Stokes problem, 54, 56
Standard Template Library, 64
stereoscopic anaglyph, 14, 35
Stokes problem, 42, 66
stress tensor, 35
tensor visualization as ellipsoid, 37
transmission problem, 83
vorticity, 46
weighted functional space, 56
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Index of le formats
.bamgcad bamg geometry, 113
.bamg bamg mesh, 113
.branch family of elds, 60, 62
.dmn domain names, 113
.field eld, 13
.geo mesh, 13, 56, 113, 115
.gz gzip compressed le, 41
.jpg joint photographic experts group (im-
ages), 62
.mfield multi-eld, 35, 41, 45
.mov QuickTime le (video), 62
.mshcad gmsh geometry, 115
.msh gmsh mesh, 115
131
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Index of example les
Makefile.demo, 12
build-poisson-neumann.h, 68
cahouet-chabart.h, 68
cavity.h, 42, 70
contraction-bubble.cc, 54
contraction.bamgcad, 55
contraction.dmn, 55
convect.cc, 63, 68
dirichlet-nh.cc, 18
dirichlet.cc, 10
embankment-adapt-2d.cc, 39
embankment.cc, 32
embankment.h, 33
geo min aera.cc, 80
heat.cc, 59
helmholtz band assembly.h, 81
helmholtz band sphere.cc, 80
helmholtz s sphere.cc, 77
incompressible-elasticity.cc, 52
isovalue sphere.cc, 79
my-cube.mshcad, 116
my-square-cut.bamgcad, 114
my-square.bamgcad, 113
my-square.dmn, 113
my-square.mshcad, 115
navier-stokes-solve.h, 67
neumann-laplace-assembly.h, 27
neumann-laplace.cc, 26
neumann.cc, 21
p-laplacian-damped-newton.cc, 100
p-laplacian-fixed-point.cc, 91
p-laplacian-fixed-point.h, 90
p-laplacian-newton.cc, 95
p-laplacian.h, 96
p-laplacian.icc, 96
pcg solver.h, 44
poisson-dirichlet.icc, 91
robin.cc, 23
stokes-cavity.cc, 43, 69
stokes-poiseuille-bubble.cc, 57
stokes-poiseuille.cc, 57
streamf-cavity.cc, 48, 72
stress.cc, 36
transmission.cc, 85
vortex-position.cc, 74
vorticity.cc, 46, 72
132
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
Index of programs
bamg2geo, 113
bamg, 40, 113
branch, 62, 65
convect, 65
dirichlet, 10
ffmpeg, 62
field, 13, 35, 37, 41, 45, 53, 92, 98
geo, 13, 34
gmsh, 115
gnuplot, 15, 62, 86, 114
gzip, 41
make, 12
mayavi, 13, 16, 35, 49, 114
mfield, 35, 37, 41, 45, 53
mkgeo grid, 13, 34, 45, 53, 65, 86, 92, 98
msh2geo, 115
p-laplacian-damped-newton, 100
p-laplacian-fixed-point, 91
p-laplacian-newton, 95
paraview, 62
rheolef-config, 9
vlc, 62
vtk, 62
133
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
134 Rheolef version 5.94 update 27 May 2011
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
List of Figures
1.1 Solution of the model problem for N = 2: (left) P
1
element; (right) P
2
element. . . 13
1.2 Alternative representations of the solution of the model problem (N = 2 and the P
1
element): (left) in black-and-white; (right) in elevation and stereoscopic anagyph
mode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.3 Red-cyan anaglyph glasses for the stereoscopic visualization. . . . . . . . . . . . . . 14
1.4 Solution of the model problem for N = 3 and the P
1
element : (left) mesh; (right)
isovalue, cut planes and stereo anaglyph renderings. . . . . . . . . . . . . . . . . . 15
3.1 The boundary domains for the square and the cube. . . . . . . . . . . . . . . . . . 31
3.2 The linear elasticity for = 1 and N = 2 and N = 3: both wireframe and lled
surfaces ; stereoscopic anaglyph mode for 3D solutions. . . . . . . . . . . . . . . . 34
3.3 The stress tensor visualization (linear elasticity = 1). . . . . . . . . . . . . . . . . 37
3.4 The
01
stress component (linear elasticity = 1): d = 2 (top) and d = 3 (bottom)
; P
0
(left) and P
1
discontinuous approximation (right). . . . . . . . . . . . . . . . 38
3.5 Adapted meshes: the deformation visualization for P
1
and P
2
approximations. . . 41
3.6 The velocity visualization for N = 2 and N = 3 with stereo anaglyph. . . . . . . . 45
3.7 The vorticity: elevation view for N = 2 and vector representation for N = 3 (with
anaglyph). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.8 The stream function visualization: isolines for N = 2, and combined vectors and
isonorm surface for N = 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.1 The incompressible linear elasticity ( = +) for N = 2 and N = 3. . . . . . . . . 53
5.1 Animation of the solution of the heat problem. . . . . . . . . . . . . . . . . . . . . 61
5.2 Animation of the solution of the rotating hill problem. . . . . . . . . . . . . . . . . 65
5.3 Meshes and stream functions associated to the solution of the Navier-Stokes equa-
tions for Re = 100 (top) and Re = 400 (bottom). . . . . . . . . . . . . . . . . . . . 71
5.4 Meshes and stream functions associated to the solution of the Navier-Stokes equa-
tions for Re = 1000. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
5.5 Navier-Stokes: velocity proles along lines passing throught the center of the cavity,
compared with data from [24]: (a) u
0
along the vertical line; (b) u
1
along the
horizontal line line. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
5.6 Cavity ow: primary vortex position and stream function value. . . . . . . . . . . . 73
6.1 Explicit surface surface method: (left) for a circle: (right) for a sphere; (top) mesh;
(bottom) solution. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.2 Building a surface mesh from level set: (left) for a circle: (right) for a sphere. . . . 79
135
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2
136 Rheolef version 5.94 update 27 May 2011
6.3 Banded level set method: (left) for a circle: (right) for a sphere (n = 10). . . . . . 82
7.1 Transmission problem: u
h
=
h
(u) ( = 10
2
, N = 1, P
1
approximation). . . . . . 87
8.1 The p-laplacian for N = 2: (a) elevation view for p = 1.1; (b) cut along the rst
bissectice x
0
x
1
= 0. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
8.2 The xed-point algorithm on the p-laplacian for N = 2: (a) convergence when
p < 2; (b) when p > 2; (c) convergence rate versus p; (d) convergence rate versus p
in semi-log scale. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
8.3 The Newton algorithm on the p-laplacian for N = 2: (a) convergence when p < 2;
(b) when p > 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
8.4 The damped Newton algorithm on the p-laplacian for N = 2: (a) convergence when
p < 2; (b) when p > 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
8.5 Convergence versus n for various meshes: (a) Newton algorithm when p = 1.7 and
(b) p = 1.6; (c) Newton algorithm when p = 1.5; (d) damped-Newton algorithm
when p = 1.5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
9.1 Error analysis in L
2
and L

norms. . . . . . . . . . . . . . . . . . . . . . . . . . . 104
9.2 Error analysis for the gradiend: H
1
and W
1,
norms. . . . . . . . . . . . . . . . . 106
9.3 The domain of computation: (a) with a crack; (b) by using the Ox
1
symetry. . . . 107
9.4 Error analysis for a domain with a crack. . . . . . . . . . . . . . . . . . . . . . . . 109
A.1 Visualization of the gmsh meshes my-square.geo and my-cube.geo. . . . . . . . 119
c
e
l
-
0
0
5
7
3
9
7
0
,

v
e
r
s
i
o
n

2

-

2
7

F
e
b

2
0
1
2

You might also like