0% found this document useful (0 votes)
47 views99 pages

Feelpp Manual

Copyright
© © All Rights Reserved
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)
47 views99 pages

Feelpp Manual

Copyright
© © All Rights Reserved
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/ 99

FEEL MANUAL

A LIBRARY FOR
FINITE AND SPECTRAL ELEMENT METHODS IN
1D, 2D AND 3D
Version 0.92.0 git610b332

Editor
Christophe P RUD ’ HOMME
F EEL ++ Consortium
[email protected]

Date 130303
Buildid 610b332
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free
Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with
no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included
in the section entitled "GNU Free Documentation License".
Contents

I Tutorial 7
1 Crash course
By Vincent Huber 9
1.1 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2 Building F EEL ++ from source on *nix . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3 Compiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.4 F EEL ++ Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.4.1 About the math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.4.2 About the code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.5 First execution & vizualisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2 Building Feel++
By Christophe Prud’homme, Baptiste Morin 13
2.1 Getting the source via an archive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2 Getting the source via Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3 Unix : dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4 F EEL ++ on Debian and Ubuntu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4.1 Debian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4.2 Ubuntu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.5 F EEL ++ on Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.5.1 Compilers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.5.2 MacPorts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.5.3 MacPorts and F EEL ++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.5.4 PETSc and SLEPc on Snow Leopard and Lion . . . . . . . . . . . . . . . . . . . 17
2.5.5 Missing ports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.6 Compiling Feel++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.6.1 Compiling the Feel++ manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3 Getting Started with Feel++


By Christophe Prud’homme, Baptiste Morin, Guillaume Dollé 21
3.1 First F EEL ++ Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.1.1 Minimal example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.1.2 Compilation, execution, logs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.1.3 Config files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.1.4 Initializing PETSc and Trilinos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2 Mesh Manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

3
3.3 Computing Integrals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.4 Function Spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.5 Laplacian Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.6 Stokes Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.7 Diffusion advection reaction problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.8 Linear Algebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.8.1 Choosing a linear algebra backend . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.8.2 Solving . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

4 Feel++ Language Keywords


By Christophe Prud’homme 33
4.1 Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.2.1 Integrals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.2.2 Projections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.2.3 Meshes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

II Learning by Examples 39
5 Non-Linear examples
By Christophe Prud’homme 41
5.1 Solving nonlinear equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.1.1 A first nonlinear problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.1.2 Simplified combustion problem: Bratu . . . . . . . . . . . . . . . . . . . . . . . . 42

6 Heat sink
By Baptiste Morin, Christophe Prud’homme 43
6.1 Problem description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
6.1.1 Domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
6.1.2 Inputs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
6.2 Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
6.2.1 Figure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
6.2.2 Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6.2.3 Boundary conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6.2.4 Finite Element Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
6.3.1 Application parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
6.3.2 Surfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
6.3.3 Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.3.4 Outputs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.4 Use cases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.4.1 How to use it ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.4.2 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

7 Natural convection in a heated tank


By Christophe Prud’homme 57
7.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.2 Influence of parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.3 Quantities of interest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.3.1 Mean temperature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.3.2 Flow rate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.4 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.5 Numerical Schemes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

4
7.5.1 Stokes problem formulation and the pressure . . . . . . . . . . . . . . . . . . . . 61
7.5.2 The Stokes problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.5.3 Reformulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.5.4 Variational formulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.5.5 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.5.6 Fix point iteration for Navier-Stokes . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.5.7 A Fix point coupling algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
7.5.8 A Newton coupling algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

8 2D Maxwell simulation in a diode


By Thomas Strub, Philippe Helluy, Christophe Prud’homme 67
8.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
8.2 Variational formulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
8.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
8.4 Numerical Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

9 Domain decomposition methods


By Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme 69
9.1 A Really Short Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
9.2 A 1D model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
9.2.1 Schwartz algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
9.2.2 Variational formulations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
9.3 A 2 domain overlapping Schwartz method in 2D and 3D . . . . . . . . . . . . . . . . . . 70
9.3.1 Schwartz algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
9.3.2 Variational formulations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
9.3.3 Numerical results in 2D case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
9.3.4 Numerical solutions in 2D case . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
9.4 Computing the eigenmodes of the Dirichlet to Neumann operator . . . . . . . . . . . . . . 72
9.4.1 Problem description and variational formulation . . . . . . . . . . . . . . . . . . 72
9.4.2 Numerical solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

III Programming with F EEL ++ 75

IV Appendix 77

A How to ? 79
A.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
A.2 Meshes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
A.2.1 What are the main execution options of a F EEL ++ application ? . . . . . . . . . . 79
A.2.2 How to create a mesh? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
A.2.3 What are the different parameters of the function domain() ? . . . . . . . . . . . . 80
A.2.4 How to loop on the degrees of freedom coordinates of a function ? . . . . . . . . . 80
A.2.5 How to work with specific meshes ? . . . . . . . . . . . . . . . . . . . . . . . . . 80
A.3 Language for Partial Differential Equations . . . . . . . . . . . . . . . . . . . . . . . . . 81
A.3.1 What is the difference between using the "vf::project" function and solve a weak
projection problem ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
A.3.2 How to do a quick L2 projection of an expression ? . . . . . . . . . . . . . . . . . 81
A.3.3 How to compose F EEL ++ operators ? . . . . . . . . . . . . . . . . . . . . . . . . 82

5
B Random notes 83
B.1 Becoming a Feel++ developer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
B.1.1 Interest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
B.1.2 Creating RSA keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
B.1.3 Downloading the sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
B.2 Programming environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
B.2.1 Boost C++ Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
B.2.2 F EEL ++ Namepaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
B.3 Linear Algebra with PETSC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
B.3.1 Using the Petsc Backend: recommended . . . . . . . . . . . . . . . . . . . . . . . 85
B.3.2 List of solvers and preconditioners . . . . . . . . . . . . . . . . . . . . . . . . . . 85
B.3.3 What is going on in the solvers? . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
B.4 Weak Dirichlet boudary conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
B.4.1 Basic idea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
B.4.2 Laplacian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
B.4.3 Convection-Diffusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
B.4.4 Stokes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
B.5 Stabilisation techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
B.5.1 Convection dominated flows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
B.5.2 The CIP methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
B.6 Interpolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

C GNU Free Documentation License 91

Index 97

6
Part I

Tutorial

7
Vincent Huber

CHAPTER 1

Crash course
By Vincent Huber

Chapter ref: [cha:tutorial-crash-course]

This chapter is designed for impatient people who wants to test F EEL ++ as soon as possible.

1.1 Requirements
Before installing F EEL ++, you need to get this required packages:

• g++ (4.4, 4.5, 4.6 or 4.7) OR Clang (≥ 3.1)


• MPI : openmpi (preferred) or mpich
• Boost (≥1.39)
• Petsc (≥2.3.3)
• Cmake (≥2.6)
• Gmsh1
• Libxml2
It is assumed that all this packages are properly installed.

1.2 Building F EEL ++ from source on *nix


F EEL ++ is distributed as a tarball once in a while. The tarballs are available at
http://code.google.com/p/feelpp/downloads/list
Download the latest tarball. Then follow the steps and replace x,y,z with the corresponding numbers

tar xzf feel-x.y.z.tar.gz


cd feel-x.y.z
1 Gmsh is a pre/post processing software for scientific computing available at http://www.geuz.org/gmsh

9
Crash course

We define then the current directory as the source one, ie:


export FeelppSrcDir=`pwd`

1.3 Compiling
Please, notice that 4 Gbytes of RAM is a minimum to make F EEL ++ compiling (with GCC), with clang
(≥ 3.1), the memory footprint is much lower.
In order to compile F EEL ++ and a test application, we create a new directory:
mkdir build
cd build
export buildDir=`pwd`
and then, we are able to compile our first application:
cd $buildDir
cmake $FeelppSrcDir
make -j4
This procedure will build the entire librarie (with DebWithRelInfo option) and a dummy program to
presents the F EEL ++’s abilities.
There is a procedure to install as a system librarie F EEL ++.
make install
See chapter 2 for more details.

1.4 F EEL ++ Hello World


As an introduction to the aim and the way to do with F EEL ++, we provide a sort of Hello World program
to evaluate the library.

1.4.1 About the math


We want to solve the simplest problem:
−∆u = 1,
u|∂Ω = 0,
n
where Ω ∈ R , n ∈ 1, 2, 3.

That problem written in variational form is: looks for v ∈ H 1 (Ω)

a (u, v) = l (v)
∀v ∈ H 1 (Ω) .

with: Z
a (u, v) = ∇u · ∇v,

Z
l (v) = v.

The aim of F EEL ++ is to provide the simplest way to write the a and f forms.

From a discrete point of view, we introduce Vh ⊂ H 1 (Ω) such that:

Vh = v ∈ C 0 (Ω) , ∀K ∈ Th , v |K ∈ P1 (K)} ,


10
Vincent Huber

where Th is the set of element K forming the mesh of Ω.


We now look for uh ∈ Vh such that:
∀vh ∈ Vh , a (uh , vh ) = l (vh ) .

1.4.2 About the code


This section is here to declare that we want to use the namespace F EEL ++, to passe the command line
options to the created environnement and add some informations (basics F EEL ++ options, application
name).
using namespace Feel;
Environment env( _argc=argc, _argv=argv,
_desc=feel_options(),
_directory=".",
_about=about(_name="qs_laplacian",
_author="Feel++ Consortium",
_email="[email protected]"));
We have to define the mesh, the approximation space and our test and trial functions.
auto mesh = unitSquare();
auto Vh = Pch<1>( mesh );
auto u = Vh->element();
auto v = Vh->element();
We create now our bilinear and linear forms, we add the homogeneous Dirichlet conditions and solve the
discretized (linear) system.
auto l = form1( _test=Vh );
l = integrate(_range=elements(mesh),
_expr=id(v));
auto a = form2( _trial=Vh, _test=Vh );
a = integrate(_range=elements(mesh),
_expr=gradt(u)*trans(grad(v)) );
a+=on(_range=boundaryfaces(mesh), _rhs=l, _element=u,
_expr=constant(0.) );
a.solve(_rhs=l,_solution=u);
F EEL ++ provides the possibility to save the results:
auto e = exporter( _mesh=mesh );
e->add( "u", u );
e->save();
return 0;

1.5 First execution & vizualisation


To test that part of code, please go to:
cd $FeelppSrcDir/quickstart
and execute the code, by:
./feelpp_qs_laplacian
This will produce several files:
qs_laplacian-1_0.case
qs_laplacian-1.sos
qs_laplacian.timeset
qs_laplacian.u-1_0.001
qs_laplacian-1_0.geo001
qs_laplacian.pid-1_0.001
square.geo
square.msh

11
Crash course

You can vizualise the results using any Ensight file reader, such as Paraview, opening qs_laplacian-1.sos.
paraview qs_laplacian-1.sos
You may have a look to the differents option provided by
./feelpp_qs_laplacian --help

12
Christophe Prud’homme, Baptiste Morin

CHAPTER 2

Building Feel++
By Christophe Prud’homme, Baptiste Morin

Chapter ref: [tutorial-building]

2.1 Getting the source via an archive


F EEL ++ is distributed as a tarball once in a while. The tarballs are available at

http://code.google.com/p/feelpp/

Download the latest tarball.

tar -xzf feelpp-0.92.0.tar.gz


cd feel-0.92.0

2.2 Getting the source via Git


In order to download the sources of F EEL ++, you can download it directly from the source depository
thanks to Git. To make it possible, you can download them anonymously or with an account in Github that
you have created. As an open-source project, we strongly suggest you to create an account and take part
of the project with sharing your ideas, developments or suggests. If you’re interested to participate and
become a F EEL ++ developer, please don’t hesitate to see how it works in the appendix B.1. For now, if
you want to get the sources without an account, open a command-line and type

git clone https://github.com/feelpp/feelpp.git


then you can go to the F EEL ++ top directory with

cd feel
You should obtain furthers directories such as :
applications/ # functional applications
benchmarks/ # applications under test
cmake/ # do not touch, used for compilation
contrib/
doc/ # tutorial and examples
feel/ # Feel++ library

13
Building Feel++

ports/ # used for Mac OS X installation


research/ # research projects using Feel++
testsuite/ # Feel++ unit tests testsuite
CMakeListe.txt # the file for cmake to build, do not modify
...

2.3 Unix : dependencies


In order to install F EEL ++ on Unix systems (other than Mac OS X, in you have a Macintosh, please go
to 2.5), you have to install many dependencies before. Those libraries and programs are necessary for the
compilation and installation of the F EEL ++ librairies. This is the list of all the librairies you must have
installed on your computer, and the *-dev packages for some of them.
Required packages:
• g++ (4.5, 4.6 and 4.7) or clang++ (> 3.1)
• MPI : openmpi (preferred) or mpich
• Boost (≥1.39)
• Petsc (≥2.3.3)
• Cmake (≥2.6)
• Gmsh1
• Libxml2
Optional packages:
• Superlu
• Suitesparse(umfpack)
• Metis: scoth with the metis interface (preferred), metis (non-free)
• Trilinos (≥8.0.8)
• Google perftools
• Paraview2 , this is not stricly required to run F EEL ++ programs but it is somehow necessary for
visualisation
• Python (≥ 2.5) for the validation tools
Note that all these packages are available under Debian/GNU/Linux and Ubuntu. They should be available.
Once you have installed those dependencies, you can jump to 2.6.

2.4 F EEL ++ on Debian and Ubuntu


2.4.1 Debian
Debian is the platform of choice for F EEL ++, it was developed mainly on it. The commands to install
F EEL ++ on Debian are
sudo apt-get update
sudo apt-get install feel++-apps libfeel-dev feel++-doc
1 Gmsh is a pre/post processing software for scientific computing available at http://www.geuz.org/gmsh
2 Paraview is a few parallel scientific data visualisation plateform, http://www.paraview.org

14
Christophe Prud’homme, Baptiste Morin

The interested user is encourage to follow the F EEL ++ PTS page

• F EEL ++ Debian Packages Tracking System

At the moment F EEL ++ compiles and is available on the following Debian plateforms:

• F EEL ++ Buildd results

2.4.2 Ubuntu
F EEL ++ was uploaded in the distribution Ubuntu-Natty (11.04) for the first time. The commands to install
F EEL ++ on Ubuntu are

sudo apt-get update


sudo apt-get install feel++-apps libfeel-dev feel++-doc
The interested user might want to follow the Ubuntu Launchpad F EEL ++ page in order to know what is
going on with F EEL ++ on Ubuntu

• F EEL ++ Ubuntu Source Page for all Ubuntu versions

2.5 F EEL ++ on Mac OS X


F EEL ++ is also working on Mac operating systems. The way to make it work is quite different.

2.5.1 Compilers
In order to F EEL ++ and cmake work properly, you have to install differents compilers :

• Gcc
The first step is to install the latest version of Xcode. If your computer is recent, you can install it
with your DVD that came with your machine (not the OS DVD, but the applications one). You don’t
have to install the complete Xcode (you can uncheck iOS SDK for example, it’s not necessary here
and requiers a lot of memory). Xcode will provide your computer all basic tools to compile such as
gcc 4.2. It’s the first step, you’ll see later how to easily install gcc 4.5 or later using MacPorts.

• Fortran
To build the Makefiles, cmake will need a Fortran compiler. To make it works, please go to Source-
Forge.net and download gfortran-snwleo-intel-bin.tar.gz which is the fortran compiler
only (from now, don’t download the complete install with gcc 4.6 because Feel needs gcc 4.5 or
later). To install it, go to the directory where you have downloaded the file and type in a command-
line

sudo tar -xvf gfortran-snwleo-intel-bin.tar -C /

2.5.2 MacPorts
Introduction MacPorts is an open-source community projet which aims to design an easy-to-use system
for compiling, installing and upgrading open-source softwares on Mac OS X operating system. It is dis-
tributed under BSD License and facilitate the access to thousands of ports (softwares) without installing or
compiling open-source softwares. MacPorts provides a single software tree which includes the latest stable
releases of approximately 8050 ports targeting the current Mac OS X release (10.6 or 10.5). If you want
more information, please visite their website.

15
Building Feel++

Installation To install the latest version of MacPorts, please go to Installing MacPorts page and follow
the instructions. The simplest way is to download the dmg disk image corresponding to your version of
Mac OS X. It is recommended that you install X11 (X Window System) which is normally used to display
X11 applications.
If you have installed with the package installer (MacPorts-1.x.x.dmg) that means MacPorts will be
installed in /opt/local. From now on we will suppose that macports has been installed in /opt/local
which is the default MacPorts location. Note that from now on, all tools installed by MacPorts will be
installed in /opt/local/bin or /opt/local/sbin for example (that’s here you’ll find gcc4.5 or later
e.g /opt/local/bin/g++-mp-4.5 once being installed).

Key commands In your command-line, the software MacPorts is called by the command port. Here is a
list of key commands for using MacPorts, if you want more informations please go to MacPorts Commands.

• sudo port -v selfupdate This action should be used regularly to update the local tree with the
global MacPorts ports. The option -v enables verbose which generates verbose messages.

• port info flowd This action is used to get information about a port (description, license, main-
tainer, etc.)

• sudo port install mypackage This action install the port mypackage

• sudo port uninstall mypackage This action uninstall the port mypackage

• port installed This action displays all ports installed and their versions, variants and activation
status. You can also use the -v option to also display the platform and CPU architecture(s) for which
the ports were built, and any variants which were explicitly negated.

• sudo port upgrade mypackage This action updgrades installed ports and their dependencies
when a Portfile in the repository has been updated. To avoid the upgrade of a port’s dependencies,
use the option -n.

Portfile A Portfile is a TCL script which usually contains simple keyword values and TCL expressions.
Each package/port has a corresponding Portfile but it’s only a part of a port description. F EEL ++ provides
some mandatory Portfiles for its compilation which are either not available in MacPorts or are buggy but
F EEL ++ also provides some Portfiles which are already available in MacPorts such as gmsh or petsc. They
usually provide either some fixes to ensure F EEL ++ works properly or new version not yet available in
MacPorts. These Portfiles are installed in ports/macosx/macports.

2.5.3 MacPorts and F EEL ++


To be able to install F EEL ++, add the following line in /opt/local/etc/macports/source.conf at
the top of the file before any other sources :
file:///<path to feel top directory>/ports/macosx/macports

Once it’s done, type in a command-line :

cd <your path to feel top directory>/ports/macosx/macports


portindex -f

You should have an output like this :

16
Christophe Prud’homme, Baptiste Morin

Reading port index in <your path to feel top directory>/ports/macosx/macports


Adding port science/feel++
Adding port science/gmsh
Adding port science/petsc

Total number of ports parsed: 3


Ports successfully parsed: 3
Ports failed: 0
Up-to-date ports skipped: 0
Your are now able to type
sudo port install feel++
It might take some time (possibly an entire day) to compile all the requirements for F EEL ++ to com-
pile properly. If you have several cores on your MacBook Pro, iMac or MacBook we suggest that you
configure macports to use all or some of them. To do that uncomment the following line in the file
/opt/local/etc/macports/macports.conf

buildmakejobs 0 # all the cores

At the end of the sudo port install feel++, you have all dependencies installed. To build all the
Makefile, cmake is automatically launched but can have some libraries may not be found but they are not
mandatory for build Feel++, only the features related to the missing libraries will be missing.

2.5.4 PETSc and SLEPc on Snow Leopard and Lion


We have heard about issues with petsc and slepc with some new MacBook Pro with Snow Leopard while
they are being installed with the command
sudo port install feel++
If it’s the case, that probably means there is an issue with atlas. If atlas is already installed, you have to
unsinstall it (be careful with dependencies, they also have to be uninstalled). Once it’s done, you should do
cd <path to feel top directory>/ports/macosx/macports
portindex -f
then type in the exact same order :
sudo port uninstall slepc
sudo port uninstall petsc
sudo port install -d petsc
sudo port install slepc
Then add to you shell script environment (e.g. for Bash shells .bashrc or .profile or for CSh shells
.tcshrc)
# Sh based shell
export PETSC_DIR=/opt/local/lib/petsc
export SLEPC_DIR=/opt/local/lib/petsc

# CSh based shell


setenv PETSC_DIR /opt/local/lib/petsc
setenv SLEPC_DIR /opt/local/lib/petsc
and type once again
sudo port install feel++
In that order, slepc and petsc will be installed before atlas, and feel will be properly installed.

17
Building Feel++

2.5.5 Missing ports


cmake can build Makefiles even if some packages are missing (latex2html, VTK ...). It’s not necessary to
install them but you can complete the installation with MacPorts, cmake will find them by itself once they
have been installed.

2.6 Compiling Feel++


Feel build system uses cmake 3 as its build system. Check that cmake is using gcc4.5 (or a higher version)
or clang++ as C++ compiler (you can use the option CMAKE_CXX_COMPILER=<path>/g++-4.5 where
the path depends on your OS, it’s probably /usr/bin or /opt/local/bin but you can also change it
with the command ccmake and press t for advanced options). F EEL ++, using cmake, can be built either
in source and out of source and different build type:

• minsizerel : minimal size release

• release release

• debug : debug

• none(default)

CMake Out Source Build (preferred) The best way is to have a directory (FEEL for example) in which
you have :

feel/

where feel is the top directory where the source have been downloaded. Placed in FEEL, you can create
the build directory (feel.opt for example) and lauch cmake with :

mkdir feel.opt
cd feel.opt
cmake <directory where the feel source are>
# e.g cmake ../feel if feel.opt is at the same
# directory level as feel

you can customize the build type:

# Choose g++ release


cmake -CMAKE_CXX_COMPILER=/usr/bin/g++-4.5
# Debug build type (-g...)
cmake -D CMAKE_BUILD_TYPE=Debug
# Release build type (-O3...)
cmake -D CMAKE_BUILD_TYPE=Release
...

Once Cmake has made its work, you are now able to compile the library with

make

Important : from now, all commands should be type in feel.opt or its subdirectories.
3 http://www.cmake.org

18
Christophe Prud’homme, Baptiste Morin

2.6.1 Compiling the Feel++ manual


The manual (which includes the tutorial) is edited with LATEXso you need to have installed the LATEXdistribution
on your computer. LATEXis a high-quality typesetting system, it includes features designed for the produc-
tion of technical and scientific documentation. There are several ways to make it work, for example you can
go on MacTeX website and follow the instructions to install the distribution. If the command make check
in feel.opt/ has been run before, the tutorial should be already compiled and ready. The steps are as
follows to build the Feel tutorial
cd feel.opt/doc/manual
make pdf
The directory doc/manual contains all examples used in the tutorial. You will see how it works in the
following parts.

19
Building Feel++

20
Christophe Prud’homme, Baptiste Morin, Guillaume Dollé

CHAPTER 3

Getting Started with Feel++


By Christophe Prud’homme, Baptiste Morin, Guillaume Dollé

Chapter ref: [getting-started]

3.1 First F EEL ++ Application


See section 2 for more information about F EEL ++ installation.

3.1.1 Minimal example


Let’s begin with our first program using the F EEL ++ framework (source "doc/manual/tutorial/myapp.cpp").
Before all, you have to include the F EEL ++ headers.
#include <feel/feel.hpp>
using namespace Feel;

We use the C++ namespace to avoid Feel:: prefix before F EEL ++ objects.
int main( int argc, char* argv[] )
{
// create custom command option
po::options_description app_options( "MyApp options" );
app_options.add( feel_options() );
app_options.add_options()
( "value",
po::value<double>() -> default_value(4.2),
"a ’double’ with default value" )
;
// initialize feel++ environment
Environment env( _argc=argc, _argv=argv,
_desc=app_options,
_about=about( _name="myapp",
_author="Feel++ Consortium",
_email="[email protected]") );
// create a log and write inside
LOG(INFO) << "value = " << option(_name="value").as<double>()
<< std::endl;
LOG(INFO) << "proc " << Environment::worldComm().globalRank()

21
Getting Started with Feel++

<<" of "<< Environment::numberOfProcessors()


<< std::endl;
} // main

• We pass command line options using the Boost Program Options1 library using the prefix po::
which is a F EEL ++ alias for the Boost::program_options namespace. To add a new F EEL ++ option,
we must create a new F EEL ++ options_description. You must add the default F EEL ++ options
and the new one that we choose here as a double value. Note that the default value will be assigned
if not specified by the user.
• Then we initialize the environment variables through the F EEL ++ Environment class (Check the
Constructor prototype on the online documentation).
• We instantiate a new application. We specify the directory where to execute the program. That could
be usefull for archiving your results.
• Finally, we save the results in a log file using the google-glog library 2 . As you can see, we save in
this example our custom option value and the current processor number.

3.1.2 Compilation, execution, logs


To compile a tutorial, just use the GNU make command.
make feelpp_doc_<appname>
where appname is the name of the application you wish to compile (here, myapp). Go to the execution
directory as specified in the program, and execute it. You can change your option value.
./feelpp_doc_myapp [--value 6.6]
You can list the log files created.
ls /tmp/<your login>/feelpp_doc_myapp/
If you open one of these log, you should be able to see your value and the processor number used to
compute. You can run your application on several processors using MPI.
mpirun -np 2 feelpp_doc_myapp
Note that there will be one log for each processor in that case.

3.1.3 Config files


A config file can be parsed to the program to profile your options. The default config paths are,
1. current dir
2. $HOME/feel/config/
3. $INSTALL_PREFIX/share/feel/config/
then you have to write inside one of these folders a file called <app_name>.cfg or feelpp_<app_name>.cfg.
For example, our myapp.cfg would looks like,
value=0.53

Note that you can specify the config file through the option --config-file=<path>
1 http://www.boost.org/doc/libs/1_53_0/doc/html/program_options.html
0 http://code.google.com/p/google-glog/

22
Christophe Prud’homme, Baptiste Morin, Guillaume Dollé

3.1.4 Initializing PETSc and Trilinos


PETSc is a suite of data structures and routines for the scalable (parallel) solution of scientific applications
modeled by partial differential equations. It employs the MPI standard for parallelism.
F EEL ++ supports the PETSc framework, the Environment takes care of initializing the associated
PETSc environment.

3.2 Mesh Manipulation


Feel++ provides some tools to manipulate mesh. Here is a basic example that shows you how to generate
a mesh for a square geometry (source "doc/manual/tutorial/mymesh.cpp").
int main( int argc, char** argv )
{
// initialize Feel++ Environment
Environment env( _argc=argc, _argv=argv,
_desc=feel_options(),
_about=about( _name="mymesh" ,
_author="Feel++ Consortium",
_email="[email protected]" ) );
// create a mesh with GMSH using Feel++ geometry tool
auto mesh = unitSquare();
// export results for post processing
auto e = exporter( _mesh=mesh );
e->save();
} // main

As always, we initialise the F EEL ++ environment (see section 3.1). The unitSquare() will generate
a mesh for a square geometry. F EEL ++ provides several functions to automate the GMSH mesh generation
for different topologies. ( unitCircle(), unitCube(), . . . ). These functions will create a geometry file
.geo and a mesh file .msh. We can visualize them in GMSH.

gmsh <entity_name>.msh
Finally we use the exporter() function to export the mesh for post processing. It will create by default a
Paraview format file .sos and an Ensight format file .case.

paraview <app_name>.sos
For advanced usage, there is the more generic createGMSHMesh() function which is useful for creating
a mesh from a geometry. For loading a mesh, there is the loadGMSHMesh() function (see section A.2.5
for a load example). Note that unitSquare() is just a particular case of createGMSHMesh(). F EEL ++
provide useful tools to iterate on the mesh or some faces that we will see later. The process of the mesh
creation is fully parallelized. You can as explained in section 3.1 run this example on several processors
and visualise subregions with paraview (see figures 3.2 and 3.2).

3.3 Computing Integrals


You should be able to create a mesh now. If it is not the case, get back to the section 3.2. This part explains
how to integrate on a mesh with F EEL ++ (source "doc/manual/tutorial/myintegrals.cpp"). Let’s consider
the domain Ω = [0, 1]d and associated meshes. Here, we want to integrate the following function,

f (x, y, z) = x2 + y 2 + z 2 (3.1)

on the whole domain Ω and on part of the boundary Ω. Take a look at the code.

23
Getting Started with Feel++

Figure 3.1: Mesh computed for square and cube geometries using one processor

(a) Square and subregions (b) Cube and subregions

Figure 3.2: Mesh created for square and cube geometries using 4 processors

int
main( int argc, char** argv )
{
// Initialize Feel++ Environment
Environment env( _argc=argc, _argv=argv,
_desc=feel_options(),
_about=about( _name="myintegrals" ,
_author="Feel++ Consortium",
_email="[email protected]" ) );
// create the mesh (specify the dimension of geometric entity)
auto mesh = unitHypercube<3>();
// our function to integrate
auto f = Px()*Px() + Py()*Py() + Pz()*Pz();
// compute integral of f (global contribution)
double intf_1 = integrate( _range = elements( mesh ),
_expr = f ).evaluate()( 0,0 );
// compute integral of f (local contribution)
double intf_2 = integrate( _range = elements( mesh ),
_expr = f ).evaluate(false)( 0,0 );
// compute integral f on boundary
double intf_3 = integrate( _range = boundaryfaces( mesh ),
_expr = f ).evaluate()( 0,0 );
std::cout << "int global ; local ; boundary" << std::endl
<< intf_1 << ";" << intf_2 << ";" << intf_3 << std::endl;
}

24
Christophe Prud’homme, Baptiste Morin, Guillaume Dollé

To use the integrate() function, we have to precise the domain range. You can use,
• elements() to iterate on the whole mesh Ω,
• boundaryfaces() to iterate on the boundary ∂Ω,
• markedfaces() to iterate on a choose face.
You have to specify the expression we wish to compute. F EEL ++ provides a set of functions to write
these expressions 4.1. The evaluate() function computes the integral on the global mesh. The false
parameter limits the computation on the subregion owned by the processor. Note that F EEL ++ computes
automatically the quadrature and consider by default each non polynomial terms of the expression as a
polynomial of degree 2. You can change it by passing a _quad parameter to the integrate() function
which takes a _Q<int order> object as value. (refer to API documentation).

3.4 Function Spaces


Now we are able to construct basic F EEL ++ applications and compute some integrals (If it is not the case,
get back to section 3.2). We interest now to solve partial differential equations, so we must define function
spaces to work on. (source "doc/manual/tutorial/myfunctionspace.cpp").
int main( int argc, char** argv )
{
//Initialize Feel++ Environment
Environment env( _argc=argc, _argv=argv,
_desc=feel_options(),
_about=about( _name="myfunctionspace",
_author="Feel++ Consortium",
_email="[email protected]" ) );
auto g = sin( 2*pi*Px() )*cos( 2*pi*Py() )*cos( 2*pi*Pz() );
// create the mesh
auto mesh = unitSquare();
// function space Xh using order 2 Lagrange basis functions
auto Xh = Pch<2>( mesh );
// elements of u, w ∈ Xh
auto u = Xh->element( "u" );
auto w = Xh->element( "w" );
// build the interpolant
u = vf::project( _space=Xh, _range=elements( mesh ), _expr=g );
w = vf::project( _space=Xh, _range=elements( mesh ), _expr=idv( u )-g );
// compute L2 norms
double L2g = normL2( elements( mesh ), g );
double L2uerror = normL2( elements( mesh ), ( idv( u )-g ) );
std::cout << "||u-g||_0 = " << L2uerror/L2g << std::endl;
// export for post-processing
auto e = exporter( mesh );
e->add( "g", u );
e->add( "u-g", w );
e->save();
} // main

As you can see, we instantiate a new function space object Xh ⊂ P ckh = {v ∈ C 0 (Ω) | ∀K ∈ τh , v|K ∈
Pk (K)} using the Pch<int K>() template. These functions are continuous piecewise polynomials of an

25
Getting Started with Feel++

order K and the basis functions are Lagrange polynomials. Let g be a function such as for all (x, y, z) ∈ Ω
we have,
πx πy πz
g(x, y, z) = sin( ). cos( ). cos( )
2 2 2
We build the Lagrange interpolant u ∈ Xh of g and w ∈ Xh of u − g. We use for this the vf::project()
function which returns the projection on the mesh node for an expression given as parameter. Then we
compute the L2 norm, sZ 
kgk2 = g2 ,

and the error kg − gXh k2 using the normL2() function. Finally, we export our elements u, w ∈ Xh to
visualize them with paraview. To do so, we have to add them to the exporter.

3.5 Laplacian Problem


This part explains how to solve the Laplacian equation for homogeneous dirichlet conditions,

−∆u = f on Ω ,
(3.2)
u = 0 on ∂Ω ,

where u ∈ Ω is the unknown "trial" function and Ω the domain. We multiply each part of the first equation
by a "test" function v ∈ H01 (Ω) and we integrate the resulting equation on the domain Ω,
Z Z
− ∆uv = fv . (3.3)
Ω Ω

We can integrate by parts this equation (Green Theorem) to obtain the variationnal formulation,
Z Z Z
∂u
∇u∇v − v= fv , (3.4)
Ω ∂n
| ∂Ω{z } Ω
=0

where n denotes a unit outward normal vector to the boundary. We can rewrite the problem (3.2) as find
u ∈ H01 (Ω) such that for all v ∈ H01 (Ω),

a(u, v) = l(v) , (3.5)

where a is a bilinear form, continuous, coercive and l a linear form. Let’s take a look at the F EEL ++ code
(source "doc/manual/tutorial/mylaplacian.cpp"). We consider for this example f = 1 constant.
int main(int argc, char**argv )
{
// initialize feel++
using namespace Feel;
Environment env( _argc=argc, _argv=argv,
_desc=feel_options(),
_about=about(_name="mylaplacian",
_author="Feel++ Consortium",
_email="[email protected]"));
// create mesh
auto mesh = unitSquare();
// function space
auto Vh = Pch<1>( mesh );
auto u = Vh->element();
auto v = Vh->element();
// left hand side
auto a = form2( _trial=Vh, _test=Vh );
a = integrate(_range=elements(mesh),
_expr=gradt(u)*trans(grad(v)) );

26
Christophe Prud’homme, Baptiste Morin, Guillaume Dollé

// right hand side


auto l = form1( _test=Vh );
l = integrate(_range=elements(mesh),
_expr=id(v));
// apply the boundary condition
a+=on(_range=boundaryfaces(mesh), _rhs=l, _element=u,
_expr=constant(0.) );
// solve the equation a(u,v) = l(v)
a.solve(_rhs=l,_solution=u);
// export results
auto e = exporter( _mesh=mesh );
e->add( "u", u );
e->save();
}

As you can see, the program looks very close to the mathematical formulation. We use the form2() func-
tion to define the bilinear form and form1() for the linear one. The gradient for the trial functions is
declared with the gradt() expression where as grad() is used for the test functions (see all keywords
4.1). Note that we need to transpose the second vector to perform the scalar product. To introduce the
homogeneous dirichlet conditions on the boundary, we use the function on(). Once the variationnal for-
mulation and the boundary conditions are set, we call the solver with solve().

3.6 Stokes Problem


Let solve the stokes equation considering a Poiseuille flow profile on the inlet. We have the following
system of equations, 

 −µ∆u + ∇p = f on Ω ,
div(u) = 0 on Ω ,

(3.6)

 Ru = g on Γwall ∪ Γinlet ,
p = 0 on Γoutlet ,

where u ∈ [Hg1 (Ω)]d denotes the flow speed, p ∈ [L20 (Ω)] the fluid pressure, µ the fluid viscosity. The last
boundary condition expresses a null pressure fixed on the outlet. The Poiseuille profile on the boundary is,
 
y(1 − y)
u(x, y) = (3.7)
0
The method used to obtain the strong formulation is closed to the one used for the laplacian (see section
3.5). We multiply the first equation by a test function v ∈ H 1 (Ω) and we integrate on the domain Ω,
Z Z Z
− µ∆u · v + ∇p · v = f ·v . (3.8)
Ω Ω Ω

Then we use the Green Formula on the first term and we rewrite the second one to get the following
equation, Z Z  Z Z
∂u
µ∇u : ∇v − · v + (div(pv) − v div(p)) = f ·v . (3.9)
Ω ∂Ω ∂n Ω Ω
where n denotes a normal vector on the boundary. The divergence theorem (or Gauss’s theorem) gives,
Z Z
div(pv) = pv · n . (3.10)
Ω ∂Ω

We have to add a consistency terms to the equation (3.9) to guaranty the symmetry of the bilinear form.
This term is provided by the second equation (3.6). We multiply this equation by a test function q ∈ L2 (Ω)
and we integrate on the domain Ω, Z
div(u)q = 0 , (3.11)

27
Getting Started with Feel++

Finally, we deduce from the equations (3.10), (3.11) and after rearranging the integrals (3.9) the variationnal
formulation,
Z Z Z   Z
∂u
µ∇u : ∇v + (div(u)q − p div(v)) + pn − ·v = f ·v (3.12)
Ω Ω ∂n
| ∂Ω {z } Ω
=0

We have an equation which can be rewritten as find (u, p) ∈ [Hg1 (Ω)]d × L20 (Ω) such that for all (v, q) ∈
[H01 (Ω)]d × L20 (Ω)
a((u, p), (v, q)) = l((v, q)) (3.13)
where a is a bilinear form, continuous, coercive and where l is a linear form. Let’s see the F EEL ++ code
corresponding to this mathematical statement. (source "doc/manual/tutorial/mystokes.cpp"). We suppose
for this example the viscosity µ = 1 and f = 0.
int main(int argc, char**argv )
{
Environment env( _argc=argc, _argv=argv,
_desc=feel_options(),
_about=about(_name="mystokes",
_author="Feel++ Consortium",
_email="[email protected]"));
// create the mesh
auto mesh = unitSquare();
// function space
auto Vh = THch<2>( mesh );
// element U=(u,p) in Vh
auto U = Vh->element();
auto u = U.element<0>();
auto p = U.element<1>();
// left hand side
auto a = form2( _trial=Vh, _test=Vh );
a = integrate(_range=elements(mesh),
_expr=trace(gradt(u)*trans(grad(u))) );
a+= integrate(_range=elements(mesh),
_expr=-div(u)*idt(p)+divt(u)*id(p));
// right hand side
auto l = form1( _test=Vh );
// boundary condition
a+=on(_range=boundaryfaces(mesh), _rhs=l, _element=u,
_expr=Py()*(1-Py()) );
// solve a(u,v)=l(v)
a.solve(_rhs=l,_solution=U);
// save results
auto e = exporter( _mesh=mesh );
e->add( "u", u );
e->add( "p", p );
e->save();
}

As for the laplacian problem, the code is very closed to the mathematical formulation. We define the
product of function spaces for the flow speed and the flow pressure using THch<order>() functionwhich 
u
is Pch<N+1>× Pch<N> for respectively flow speed and pressure spaces. We take an element U =
p
in this space. Then we define the integrals of the variationnal formulation for the left and the right hand
side. Finally, we apply the Poiseuille profile on the boundary. We call the solver to resolve the problem
(3.13).

28
Christophe Prud’homme, Baptiste Morin, Guillaume Dollé

3.7 Diffusion advection reaction problem


The diffusion advection reaction equation is a classical partial differential equation which can be found in
many processes for example in chemistry or biology. This can be described by an equation containing a
diffusion, an advection and a reaction term as follows,

−∆u + β · ∇u + µu = f on Ω ,
(3.14)
u = 0 on ∂Ω ,

We use here homogeneous Dirichlet boundary conditions.

Variationnal formulation
To establish the variationnal formulation, as always we mutiply the first equation by a test function v ∈
H01 (Ω) such that,
H01 (Ω) = {v ∈ H 1 (Ω), v = 0 on ∂Ω} .
Then we integrate on the domain Ω,
Z Z Z Z
− ∆u v + β · ∇u v + µuv= fv. (3.15)
Ω Ω Ω Ω

We establish the variationnal formulation from the previous equation and using the Green formula, find
u ∈∈ H01 (Ω)
Z Z Z Z Z
∇u · ∇v − (∇u · n) v + (β · ∇u) v + µuv= f v ∀v ∈∈ H01 (Ω), (3.16)
Ω ∂Ω Ω Ω Ω
| {z }
=0

where n is a unit outward normal vector. We can rewrite the problem, find u ∈∈ H01 (Ω)

a(u, v) = l(v) ∀v ∈∈ H01 (Ω), (3.17)

where a is a bilinear form, continuous, coercive and l is a linear form.

Application
We choose for our example µ = 1,  = 1, f = 1, and β = (1, 1)T .

Listing 3.1: doc/manual/tutorial/myadvection.cpp


int
main( int argc, char** argv )
{
po::options_description opts ( "Advection diffusion reaction options ");
opts.add_options()
( "epsilon", po::value<double>()->default_value( 1 ), "diffusion term
coefficient" )
( "betax", po::value<double>()->default_value( 1 ), "convection term
coefficient in x-direction" )
( "betay", po::value<double>()->default_value( 1 ), "convection term
coefficient in y-direction" )
( "mu", po::value<double>()->default_value( 1 ), "reaction term
coefficient" );
// Initialize Feel++ Environment
Environment env( _argc=argc, _argv=argv,
_desc=opts.add( feel_options() ),
_about=about(_name="myadvection",
_author="Feel++ Consortium",
_email="[email protected]") );
// create mesh
auto mesh = unitSquare();

29
Getting Started with Feel++

// function space
auto Xh = Pch<1>( mesh );
auto u = Xh->element( "u" );
auto v = Xh->element( "v" );
// diffusion coeff.
double epsilon = option(_name="epsilon").as<double>();
// reaction coeff.
double mu = option(_name="mu").as<double>();
auto beta = vec( cst(option(_name="betax").as<double>()),
cst(option(_name="betay").as<double>()) );
auto f = cst(1.);
// left hand side
auto a = form2( _test=Xh, _trial=Xh );
a += integrate( _range=elements( mesh ),
_expr=( epsilon*gradt( u )*trans( grad( v ) )
+ ( gradt( u )*beta )*id(v)
+ mu*idt( u )*id( v ) ) );
// right hand side
auto l = form1( _test=Xh );
l+= integrate( _range=elements( mesh ), _expr=f*id( v ) );
// boundary condition
a += on( _range=boundaryfaces( mesh ), _rhs=l, _element=u,
_expr=cst(0.) );
// solve the system
a.solve( _rhs=l, _solution=u );
// export results
auto e = exporter( _mesh=mesh );
e->add("u",u);
e->save();
} // end main

Again the implementation is close to the mathematical formulation. Here again, we create the mesh for an
unit square geometry. Then we define the function space Xh we choose as order 1 Lagrange basis function
using Pch<Order>(). Note that here, the function space is the same for "trial" and "test" functions. We
declare the left and the right hand side integrals expressions for the equation (3.16). Finally we add the
Dirichlet boundary condition and we use the default solver to solve (3.17). We export the solution u for
post processing.

(a)  = 1 (b)  = 0.01 (c)  = 0.0001

Figure 3.3: Various solutions of problem (3.17) for  = 1, 0.01, 0.0001. Notice how the solution gets
unstable for  = 0.0001, this is classical and requires stabilisation methods to handle this issue.

30
Christophe Prud’homme, Baptiste Morin, Guillaume Dollé

3.8 Linear Algebra


F EEL ++ supports PETS C as it Linear algebra backend. PETS C is a suite of data structures and routines for
the scalable solution of scientific applications modeled by PDE available at http://www.mcs.anl.
gov/petsc/petsc-as/

3.8.1 Choosing a linear algebra backend


To select a backend in order to solve a linear system, we instantiate the Backend class associated :
#include <feel/feelalg/backend.hpp>
boost::shared_ptr<Backend<double> > backend =
Backend<double>::build( BACKEND_PETSC );
The backend provides an interface to solve
Ax = b (3.18)
where A is a n × n sparse matrix and x, b vectors of size n. The backend defines the C++ types for each of
these, e.g :
Backend<double>::sparse_matrix_type A;
Backend<double>::vector_type x,b;
In practice, we use the boost::shared_ptr<> shared pointer to ensure that we won’t get memory leaks.
The backends provide a corresponding typedef
Backend<double>::sparse_matrix_ptrtype A( backend->newMatrix( Xh, Yh ) );
Backend<double>::vector_ptrtype x( backend->newVector( Yh ) );
Backend<double>::vector_ptrtype b( backend->newVector( Xh ) );
where Xh and Yh are function spaces providing the number of degrees of freedom that will define the size of
the matrix and vectors thanks to the helpers functions Backend::newMatrix() and Backend::newVector.
In a parallel setting, the local/global processor mapping would be passed down by the function spaces.

3.8.2 Solving
To solve the linear problem Ax = b, the backend provides a function solve with three required parameters
solve(_matrix=A, _solution=x, _rhs=b)
where :

• the matrix A has a sparse_matrix_ptrtype type

• the solution x has a type vector_type or vector_ptrtype

• the second member vector b has a type vector_ptrtype

You can also add optional parameters like :

• a preconditioner : instead of solving Ax = b, we solve P −1 Ax = P −1 b. This method can be applied


in iterative methods and permits to decrease the number of iterations in the resolution system

• a maximum number of iterations : this option is used with an iterative solving method

|| r(k) ||
• a residual tolerance : the fraction is inferior to the residual tolerance with r(k) = b − Ax(k)
|| r(0) ||
and x(k) the solution at the k th iteration

• a absolute tolerance : || r(k) || is inferior to the absolute tolerance

• a different tolerance : sometimes, the residue doesn’t decrease continuously during the iterations.
The difference between two plots doesn’t have to exceed the parameter choosen for the difference
tolerance.

31
Getting Started with Feel++

• a boolean to use transpose matrix : instead of solving Ax = b, we solve At x = b. If A is defined


and positive, At = A.
To have a view of the values of the optional parameters, see the following code :
BOOST_PARAMETER_MEMBER_FUNCTION(
(solve_return_type),
solve,
tag,
(required
(matrix,(sparse_matrix_ptrtype))
(in_out(solution),*(mpl::or_<boost::is_convertible<mpl::_,vector_type&>,
boost::is_convertible<mpl::_,vector_ptrtype>
>))
(rhs,(vector_ptrtype)))
(optional
(prec,(sparse_matrix_ptrtype), matrix )
(maxit,(size_type), 1000 )
(rtolerance,(double), 1e-13)
(atolerance,(double), 1e-50)
(dtolerance,(double), 1e5)
(reuse_prec,(bool), false )
(transpose,(bool), false )
)
)
{
The library Boost::Parameters allows you to enter parameters in the order you want. It supports de-
duced parameters, that is to say parameters whose identity can be deduced from their types.

32
Christophe Prud’homme

CHAPTER 4

Feel++ Language Keywords


By Christophe Prud’homme

Chapter ref: [cha:appendix-feel]

4.1 Keywords
One of F EEL ++ assets is it finite element embedded language. The language follows the C++ grammar,
and provides keywords as well as operations between objects which are, mathematically, tensors of rank 0,
1 or 2.

Here are some notations :


• f : Rn 7→ Rm×p with n = 1, 2, 3, m = 1, 2, 3, p = 1, 2, 3.
• Ωe current mesh element

and here is the table which gathers all tools you may need:

Keyword Math object Description Rank M ×N



− T
P() P current point coordinates (Px , Py , Pz ) 1 d×1


Px() Px x coordinate of P 0 1×1


Py() Py y coordinate of P 0 1×1
(value is 0 in 1D)


Pz() Pz z coordinate of P 0 1×1
(value is 0 in 1D and 2D)


C() C element barycenter point coordinates 1 d×1
(Cx , Cy , Cz )T


Cx() Cx x coordinate of C 0 1×1


Cy() Cy y coordinate of C 0 1×1
(value is 0 in 1D)


Cz() Cz z coordinate of C 0 1×1
(value is 0 in 1D and 2D)

33
Feel++ Language Keywords

Keyword Math object Description Rank M ×N



N() N normal at current point (Nx , Ny , Nz )T 1 d×1


Nx() Nx x coordinate of N at current point 0 1×1


Ny() Ny y coordinate of N at current point 0 1×1
(value is 0 in 1D)


Nz() Nz z coordinate of N at current point 0 1×1
(value is 0 in 1D and 2D)

eid() e index of Ωe 0 1×1


emarker() m(e) marker of Ωe 0 1×1
h() he size of Ωe 0 1×1
hFace() heΓ size of face Γ of Ωe 0 1×1
 
m11 m12 ...
m21 m22 ...
mat<M,N>(m_11, M × N matrix 2 M ×N
..
 
.
m_12,...) entries being expressions
vec<M>(v_1, (v1 , v2 , ...)T column vector with M rows 1 M ×1
v_2,...) entries being expressions
trace(expr) tr(f (→

x )) trace of f (→

x) 0 1×1

abs(expr) |f (→

x )| element wise absolute value of f rank(f (→
−x )) m×p
cos(expr) cos(f (→−
x )) element wise cosinus value of f →

rank(f ( x )) m×p
sin(expr) →

sin(f ( x )) element wise sinus value of f rank(f (→
−x )) m×p
tan(expr) tan(f (→−x )) element wise tangent value of f →

rank(f ( x )) m×p
acos(expr) acos(f (→−x )) element wise acos value of f rank(f (→
−x )) m×p
asin(expr) →

asin(f ( x )) element wise asin value of f →

rank(f ( x )) m×p
atan(expr) atan(f (→ −x )) element wise atan value of f rank(f (→
−x )) m×p
cosh(expr) →

cosh(f ( x )) element wise cosh value of f →

rank(f ( x )) m×p
sinh(expr) sinh(f (→−x )) element wise sinh value of f rank(f (→
−x )) m×p
tanh(expr) tanh(f (→ −x )) element wise tanh value of f →

rank(f ( x )) m×p
exp(expr) →

exp(f ( x )) element wise exp value of f rank(f (→
−x )) m×p
log(expr) log(f (→
−x )) element wise log value of f →

rank(f ( x )) m×p
p →
− rank(f (→
− m×p
sqrt(expr) ( f( x ) element wise sqrt value of f x ))
1 if f (→
−x)≥0
sign(expr) →
− element wise sign of f rank(f (→

x )) m×p
−1 if f ( x ) < 0

− rank(f (→
− m×p
chi(expr) ( ( x )) =
χ(f element wise boolean test of f x ))
0 if f (→ −x)=0


1 if f ( x ) 6= 0

id(f) f test function rank(f (→


−x )) m×p
idt(f) f trial function →

rank(f ( x )) m×p
idv(f) f evaluation function rank(f (→
−x )) m×p
grad(f) ∇f gradient of test function →

rank(f ( x )) + 1 p = 1, m ×
gradt(f) ∇f gradient of trial function rank(f (→
−x )) + 1 p = 1, m ×
gradv(f) ∇f evaluation function gradient →

rank(f ( x )) + 1 p = 1, m ×


div(f) ∇· f divergence of test function rank(f (→
−x )) − 1 1 × 12

1 Gradient of matrix value functions is not implemented, hence p = 1


2 Divergence of matrix value functions is not implemented, hence p = 1

34
Christophe Prud’homme

Keyword Math object Description Rank M ×N




divt(f) ∇· f divergence of trial function rank(f (→
−x )) − 1 1×1

− →

divv(f) ∇· f evaluation of function divergence rank(f ( x )) − 1 1×1


curl(f) ∇× f curl of test function 1 n = m, n ×


curlt(f) ∇× f curl of trial function 1 m = n, n ×


curlv(f) ∇× f evaluation of function curl 1 m = n, n ×
hess(f) ∇2 f hessian of test function 2 m = p = 1,
−→ −→
jump(f) [f ] = f0 N0 + f1 N1 jump of test function 1 m = 1, n ×

− →
− − → → − − →
jump(f) [ f ] = f0 · N0 + f1 · N1 jump of test function 0 m = 2, 1 × 1
−→ −→
jumpt(f) [f ] = f0 N0 + f1 N1 jump of trial function 1 m = 1, n ×

− →
− − → → − − →
jumpt(f) [ f ] = f0 · N0 + f1 · N1 jump of trial function 0 m = 2, 1 × 1
−→ −→
jumpv(f) [f ] = f0 N0 + f1 N1 jump of function evaluation 1 m = 1, n ×

− →
− − → → − − →
jumpv(f) [ f ] = f 0 · N0 + f 1 · N1 jump of function evaluation 0 m = 2, 1 × 1
average(f) f = 12 (f0 + f1 ) average of test function rank(f (→
−x )) m = n, n ×
averaget(f) f = 12 (f0 + f1 ) average of trial function rank(f (−
→x )) m = n, n ×
averagev(f) f = 12 (f0 + f1 ) average of function evaluation rank(f (→
−x )) m = n, n ×
leftface(f) f0 left test function rank(f (→
−x )) m = n, n ×
leftfacet(f) f0 left trial function rank(f (→
−x )) m = n, n ×
leftfacev(f) f0 left function evaluation →

rank(f ( x )) m = n, n ×
rightface(f) f1 right test function rank(f (→
−x )) m = n, n ×
rightfacet(f) f1 right trial function →

rank(f ( x )) m = n, n ×
rightfacev(f) f1 right function evaluation rank(f (→
−x )) m = n, n ×
maxface(f) max(f0 , f1 ) maximum of right and left →

rank(f ( x )) m×p
test function
maxfacet(f) max(f0 , f1 ) maximum of right and left rank(f (→

x )) m×p
trial function
maxfacev(f) max(f0 , f1 ) maximum of right and left rank(f (→

x )) m×p
function evaluation
minface(f) min(f0 , f1 ) minimum of right and left rank(f (→

x )) m×p
test function
minfacet(f) min(f0 , f1 ) minimum of right and left rank(f (→

x )) m×p
trial function
minfacev(f) min(f0 , f1 ) minimum of right and left rank(f (→

x )) m×p
function evaluation

- −g element wise unary minus


- !g element wise logical not

+ f +g tensor sum
- f −g tensor substraction
* f ∗g tensor product
/ f /g tensor division (g scalar field)

< f <g element wise less


<= f ≤g element wise less or equal
> f >g element wise greater
>= f ≥g element wise greater or equal
== f =g element wise equal
!= f 6= g element wise not equal
&& f and g element wise logical and

35
Feel++ Language Keywords

Keyword Math object Description Rank M ×N


|| f or g element wise logical or

4.2 Operators
4.2.1 Integrals
Thank to its finite element embedded language, F EEL ++ has its owned integrate() function, which can
be written for example :
integrate( _range= elements(mesh), _expr= gradt(T)*trans(grad(v)) );

please notice that the order of the parameter is not important, these are boost parameters, so you can enter
them in the order you want. To make it clear, there are two required parameters and 2 optional and they
of course can be entered in any order provided you give the parameter name. If you don’t provide the
parameter name (that is to say _range= or the others) they must be entered in the order they are described
below.

The required parameters are

• _range = domain of integration

• _expr = integrand expression

The optional parameters are

• _quad = quadrature to use instead of the default one, wich means _Q<integer>() where the integer
is the polynomal order to integrate exactely

• _geomap = type of geometric mapping to use, that is to say :

– GEOMAP_HO = high order approximation (same of the mesh)


– GEOMAP_OPT = optimal approximation: high order on boundary elements, order 1 in the interior
– GEOMAP_O1 = order 1 approximation

4.2.2 Projections
It is also possible to make projections with the library, the interface is as follow :
project( _range, _space, _expr, _geomap );

where

• _space is the space in which lives the projected expression, it should be a nodal function space

• _expr the expression to project

• _range is the domain for the projection (optional, default: all elements from space->mesh())

• _geomap is the type of geometric mapping approximation (optional, default = GEOMAP_HO)

• _accumulate (optional, default = false)

36
Christophe Prud’homme

4.2.3 Meshes
F EEL ++ enables full different ways to interact with the mesh on which you want to work. Mainly with
the function integrate, the various keywords we have established will make your program’s code eas-
ier. The interoperability between F EEL ++ and G MSH is huge and provides various access to any point,
item, domain or almost anything you want in a mesh. The access to different items of a mesh is possible
thanks to the filters which enable the access of only a mesh’s part. Theses helpfull keywords are coded in
feel/feelmesh/filters.hpp, we are here going to describe most of them.

To access one particular part of a mesh, you can use :


• elements(mesh) corresponds to all the elements of a mesh

• markedelements(mesh, id) corresponds to the precise element defined by the id. It can be any
element (line, surface, domain, and so on).
• faces(mesh) corresponds to all the faces of the mesh.
• markedfaces(mesh) corresponds to all the faces of the mesh which are marked.

• boundaryfaces(mesh) corresponds to all elements that own a topological dimension one below
the mesh. For example, if you mesh is a 2D one, boundaryfaces(mesh) will return all the lines
(because of dimension 2−1 = 1). These elements which have one dimension less, are corresponding
to the boundary faces.

• internalelements(mesh) corresponds to all the elements of the mesh which are stricly within
the domain that is to say they do not share a face with the boundary.
• boundaryelements(mesh) corresponds to all the elements of the mesh which share a face with
the boundary of the mesh.
• edges(mesh) corresponds to all the edges of the mesh.

• boundaryedges(mesh) corresponds to all boundary edges of the mesh.


where id is the element’s identifier : thanks to G MSH, this identifier can be an integer or a string, it depends
on the identifier your have or you gave in the mesh .geo file.

37
Feel++ Language Keywords

38
Christophe Prud’homme

Part II

Learning by Examples

39
Christophe Prud’homme

CHAPTER 5

Non-Linear examples
By Christophe Prud’homme

Chapter ref: [cha:non-linear-ex]

5.1 Solving nonlinear equations


F EEL ++ allows to solve nonlinear equations thanks to its interface to the interface to the PETSc nonlinear
solver library. It requires the implementation of two extra functions in your application that will update the
jacobian matrix associated to the tangent problem and the residual.
Consider that you have an application class MyApp with a backend as data member
#include <feel/feelcore/feel.hpp>
#include <feel/feelcore/application.hpp>
#include <feel/feelalg/backend.hpp>
namespace Feel {
class MyApp : public Application
{
public:
typedef Backend<double> backend_type;
typedef boost::shared_ptr<backend_type> backend_ptrtype;
MyApp( int argc, char** argv,
AboutData const& ad, po::options_description const& od )
:
// init the parent class
Application( argc, argv, ad, od ),
// init the backend
M_backend( backend_type::build( this->vm() ) ),
{
// define the callback functions (works only for the PETSc backend)
M_backend->nlSolver()->residual =
boost::bind( &self_type::updateResidual, boost::ref( *this ), _1, _2 );
M_backend->nlSolver()->jacobian =
boost::bind( &self_type::updateJacobian, boost::ref( *this ), _1, _2 );
}
void updateResidual( const vector_ptrtype& X, vector_ptrtype& R )
{
// update the matrix J (Jacobian matrix) associated
// with the tangent problem
}

41
Non-Linear examples

void updateJacobian( const vector_ptrtype& X, sparse_matrix_ptrtype& J)


{
// update the vector R associated with the residual
}
void run()
{
//define space
Xh...
element_type u(Xh);
// initial guess is 0
u = project( M_Xh, elements(mesh), constant(0.) );
vector_ptrtype U( M_backend->newVector( u.functionSpace() ) );
*U = u;
// define R and J
vector_ptrtype R( M_backend->newVector( u.functionSpace() ) );
sparse_matrix_ptrtype J;
// update R
updateJacobian( U, R );
// update J
updateResidual( U, J );
// solve using non linear methods (newton)
// tolerance : 1e-10
// max number of iterations : 10
M_backend->nlSolve( J, U, R, 1e-10, 10 );
// the soluution was stored in U
u = *U;
}
private:
backend_ptrtype M_backend;
};
} // namespace Feel
The function updateJacobian and updateResidual implement the assmebly of the matrix J (ja-
cobian matrix) and the vector R (residual vector) respectively.

5.1.1 A first nonlinear problem


As a simple example, let Ω be a subset of Rd , d = 1, 2, 3, (i.e. Ω = [−1, 1]d ) with boundary ∂Ω. Consider
now the following equation and boundary condition
− ∆u + uλ = f, u = 0 on ∂Ω. (5.1)
where λ ∈ R+ is a given parameter and f = 1.
To be described in this section. For now see doc/manual/nonlinearpow.cpp for an imple-
mentation of this problem.

5.1.2 Simplified combustion problem: Bratu


As a simple example, let Ω be a subset of Rd , d = 1, 2, 3, (i.e. Ω = [−1, 1]d ) with boundary ∂Ω. Consider
now the following equation and boundary condition
− ∆u + λeu = f, u = 0 on ∂Ω (5.2)
where λ is a given parameter. Ceci est généralement appellé le problème de Bratu et apparaît lors de
la simplification de modèles de processus de diffusion non-linéaires par exemple dans le domaine de la
combustion.
To be described in this section. For now see doc/manual/bratu.cpp for an implementation
of this problem.

42
Baptiste Morin, Christophe Prud’homme

CHAPTER 6

Heat sink
By Baptiste Morin, Christophe Prud’homme

Chapter ref: [cha:heatsink]

This problem considers the performance of a heat sink designed for the thermal management of high-
density electronic components. The heat sink is comprised of a base/spreader which in turn supports a
number of plate fins exposed to flowing air. We model the flowing air through a simple convection heat
transfer coefficient. From the engineering point of view, this problem illustrates the application of conduc-
tion analysis to an important class of cooling problems: electronic components and systems.

Our interest is in the conduction temperature distribution at the base of the spreader. The target is to
study how the heat transfer occures with different parameters on our heat sink. The heat generated by
high-density electronic components is such that it’s very expensive to cool large structures (data center).
The cooling optimization is consequent in the run for decreasing operating costs.
A classical thermal CPU cooler looks like this

Figure 6.1: Mesh of a classical CPU cooler

We are here going to describe how it is theorically working and how it is impleted with F EEL ++.

43
Heat sink

6.1 Problem description


6.1.1 Domain
We consider here a classical "radiator" which is a CPU heat sink. Those types of coolers are composed with
a certain number of plate fins exposed to flowing air or exposed to a ventilator. Regarding the periodicity
and geometry of our concern, we can make our study on a characteristic element of the problem : a half
cell of the heat sink single thermal fin with its spreader at the basis. Let’s take a look at the geometry of
our problem :

Figure 6.2: Geometry of heat sink

Our study is avaible in 2 or 3 dimensions, depending on the application’s parameters. You’ll see later
how to work with it. Let’s see on which meshes we are working on :

Figure 6.3: 2D mesh Figure 6.4: 3D mesh

6.1.2 Inputs
The implementation of thoses parameters is described in the section 6.3.1.

Material
Here the material parameter can be described with furthers parameters. We have, with i = 1 for the fin and
i = 2 for the base :

44
Baptiste Morin, Christophe Prud’homme

• the thermal conductivity κi


• the material’s density ρi

• the heat capacity of the material Ci


The term ρi Ci corresponds to the heat volumetric capacity. In that way, we make possible the construction
of a heat sink with 2 different materials. Here is a list of the well-known ones, ρ and C are gave at 298K :

Material Thermal conductivity (κ in W.m−1 .K −1 ) Density (ρ in kg.m−3 ) Heat Capacity (C in J.kg −1 .K −1 )


Aluminium 180 (alloys) or 290 (pure) 2700 897
Copper 386 8940 385
Gold 314 19320 129
Silver 406 10500 233

Physical
• Depth
This parameter is only to take into account for the 3D simulation. It represents the depth of the
caracteristical heat sink and is called depth in the application.
• Length
You can also parameterize the length of the fin. This one is called L in the application’s parameters,
its dimension is the meter.
• Width
Typically, this parameter is linked with constructor’s standards. This parameter is called width in
the application’s implementation.

Thermal
• Heat flux
It represents the heat flux brought by the electronic component at the bottom of the base. Here it’s
typically the heat brought by the processor.
• Thermal coefficient
The thermal coefficient h named thermc oef f in the application is representative of the heat transfer
between the fin and the air flow.
• Ambien temperature
This parameter called Tamb represents the temperature around the heat sink at the beginning. That
means the ambient temperature before the computer is turned on.

Summary table
The following table displays the various fixed and variables parameters of this application.

45
Heat sink

Name Description Nominal Value Range Units


BDF parameters
time − initial begining 0
time − f inal end 50 ]0, 1500]
time − step time step 0.1 ]0, 1[
steady steady state 0 {0, 1}
order order 2 [0, 4]

Physical parameters
L fin’s length 2 · 10−2 [0.02, 0.05] m
width fin’s width 5 · 10−4 [10−5 , 10−4 ] m
deep heat sink depth 0 [0, 7 · 10−2 ] m

Mesh parameter
hsize mesh’s size 10−4 [10−5 , 10−3 ]

Fin Parameters
κf thermal conductivity 386 [100, 500] W · m−1 · K −1
ρf material density 8940 [10 , 12 · 103 ]
3
kg · m−3
Cf heat capacity 385 [102 , 103 ] J · kg · K −1
−1

Base/spreader Parameters
κs thermal conductivity 386 [100, 500] W · m−1 · K −1
ρs material density 8940 [10 , 12 · 103 ]
3
kg · m−3
Cs heat capacity 385 [102 , 103 ] J · kg · K −1
−1

Heat Parameters
Tamb ambient temperature 300 [300,310] K
heat_f lux heat flux Q 106 [0, 106 ] W · m−3
therm_coef f thermal coefficient h 103 [0, 103 ] W · m−2 · K −1

Table 6.1: Table of fixed and variable parameters

6.2 Theory
6.2.1 Figure
The global domain is Ω = Ω1 ∪ Ω2 where Ω1 is the fin’s domain and Ω2 the spreader’s domain. We note
∂Ω the border of the domain Ω. The physical lines we are using will be noted as Γi such as described
above. The following figure describes the parameters and the geometry we are using in the equations to
solve our 3D issue : The following figures describe the parameters and the geometry we are using in the
equations to solve our 2D or 3D issue :

46
Baptiste Morin, Christophe Prud’homme

Figure 6.5: 2D geometry details

Figure 6.6: 3D geometry details

47
Heat sink

6.2.2 Equations
Our concern satisfies the heat equation which reads
2
X ∂T
κi ∆T − ρi Ci =0 (6.1)
i=1
∂t

∂T
κ1 = 0 on Γ2 and Γ6
∂n (6.2)

∂T
κ2 = 0 on Γ5 , Γ7 and Γ8
∂n (6.3)

∂T
κ1 = −h(T − Tamb ) on Γ1
∂n (6.4)

∂T
κ2 = Q(1 − e−t ) on Γ4
∂n (6.5)

T|Ω1 = T|Ω2 on Γ3
(6.6)

κ1 ∇T · n = κ2 ∇T · n on Γ3
(6.7)

with i = 1 for the fin and i = 2 for the base and where κi is the thermal conductivity, ρi is the material’s
density (kg.m−3 in the SI unit), Ci the heat capacity and T the temperature at a precise point (in 2D or
3D). To see how it has been coded, you can read 6.3.3.

6.2.3 Boundary conditions


The problem requieres that the temperature and heat flux are continute on Γ3 . Considering the problem’s
geometry, we also impose zero heat flux on the vertical surfaces of the spreader. Let’s detail the conditions
we have imposed :

• Homogeneous Neumann condition (6.2) and (6.3) : it represents the fact that the heat flux is only
vertical (for Γ6 and Γ7 ) or the fact that the heat flux is only provided by Γ4 (for Γ2 and Γ5 ).

• Homogeneous Neumann condition (6.4) : it imposes that the heat flux is brought by this surface (it
mathematically represents that the heat sink is placed on the heat source).

• Non-homogeneous Neumann condition (6.5) : this boundary condition represents the transient state
for the heat transfer calculation.

• Temperature continuity (6.6) : it imposes that the temperature is continute at the interface between
the two materials (if there are two materials, we can also have the same one for the two pieces).

• Heat flux continuity (6.7) : it represents that the heat flux is continute at the interface between the
two materials. Literally, it means that the two flows offset each other.

Theses conditions have been coded as explained in the section 6.3.3.

48
Baptiste Morin, Christophe Prud’homme

6.2.4 Finite Element Method


Let’s apply the method to our concern, we introduce the test function v and we integrate the main equation,
which reads now as :
2 Z Z
X ∂T
ρi C i v − κi v∆T = 0 (6.8)
i=1 Ωi ∂t Ωi

We integrate by parts, which leads to :

2 Z Z Z
X ∂T
ρi Ci v + κi ∇v · ∇T − κi (∇T · n)v = 0 (6.9)
i=1 Ωi ∂t Ωi ∂Ωi

then, by decomposing the borders ∂Ωi , we obtain :


Z Z Z Z
−κ1 (∇T · n)v − κ2 (∇T · n)v − κ1 (∇T · n)v − κ2 (∇T · n)v +
Γ1 Γ4 Γ2,6 Γ5,7,8
2 Z Z Z
X ∂T
ρi Ci v + κi ∇v · ∇T − κi (∇T · n)v = 0 (6.10)
i=1 Ωi ∂t Ωi ∂Ωi ∩Γ3

Now, we apply the conditions (6.2), (6.3), (6.4) and (6.5) which brings us to :
Z Z 2 Z Z Z
X ∂T
hv(T − Tamb ) − vQ(1 − e−t ) + ρi C i v + κi ∇v · ∇T − κi (∇T · n)v = 0
Γ1 Γ4 i=1 Ωi ∂t Ωi ∂Ωi ∩Γ3
| {z }
=0 thanks to 6.7
(6.11)

Now we apply the boundary conditions (6.7) which results in :


Z Z 2 Z Z
−t
X ∂T
h v(T − Tamb ) − vQ(1 − e ) + ρi Ci v + κi ∇v · ∇T = 0 (6.12)
Γ1 Γ4 i=1 Ωi ∂t Ωi

We can now start to transform the equation by puting in the right hand the known terms :
Z 2 Z Z Z Z
X ∂T
h vT + ρi Ci v + κi ∇v · ∇T = vQ(1 − e−t ) + hTamb v (6.13)
Γ1 i=1 Ωi ∂t Ωi Γ4 Γ1

∂T
We discretize where δt is the time step, such as:
∂t
2
T n+1 − T n
Z X Z Z Z Z
h vT + ρi Ci v + κi ∇v · ∇T = vQ(1 − e−t ) + hTamb v (6.14)
Γ1 i=1 Ωi δt Ωi Γ4 Γ1

Finally we obtain :

2 2
T n+1 Tn
Z X Z Z Z Z X Z
−t
h vT + ρi Ci v + κi ∇v · ∇T = vQ(1 − e ) + hTamb v+ ρi C i v
Γ1 i=1 Ωi δt Ωi Γ4 Γ1 i=1 Ωi δt
(6.15)

This is that equation which is implemented in the application feel_heatsink.

49
Heat sink

6.3 Implementation
6.3.1 Application parameters
The parameters of the application are implemented such as
inline
Feel::po::options_description
makeOptions()
{
Feel::po::options_description heatsinkoptions("heatsink options");
heatsinkoptions.add_options()
// mesh parameters
("hsize", Feel::po::value<double>()->default_value( 0.1 ),
"first h value to start convergence")
("L", Feel::po::value<double>()->default_value( 0.03 ),
"dimensional length of the sink (in meters)")
("width", Feel::po::value<double>()->default_value( 0.0005 ),
"dimensional width of the fin (in meters)")
// 3D parameter
("deep", Feel::po::value<double>()->default_value( 0 ),
"depth of the mesh (in meters) only in 3D simulation")
// thermal conductivities parameters
("kappa_s", Feel::po::value<double>()->default_value( 386 ),
"thermal conductivity of the base spreader in SI unit W.m^{-1}.K^{-1}")
("kappa_f", Feel::po::value<double>()->default_value( 386 ),
"thermal conductivity of the fin in SI unit W.m^{-1}.K^{-1}")
// density parameter
("rho_s", Feel::po::value<int>()->default_value( 8940 ),
"density of the spreader’s material in SI unit kg.m^{-3}")
("rho_f", Feel::po::value<int>()->default_value( 8940 ),
"density of the fin’s material in SI unit kg.m^{-3}")
// heat capacities parameter
("c_s", Feel::po::value<double>()->default_value( 385 ),
"heat capacity of the spreader’s material in SI unit J.kg^{-1}.K^{-1}")
("c_f", Feel::po::value<double>()->default_value( 385 ),
"heat capacity of the fin’s material in SI unit J.kg^{-1}.K^{-1}")
// physical coeff
("therm_coeff", Feel::po::value<double>()->default_value(50),
"thermal coefficient")
("Tamb", Feel::po::value<double>()->default_value(300),
"ambiant temperature")
("heat_flux", Feel::po::value<double>()->default_value(1e6),
"heat flux generated by CPU")
("steady", Feel::po::value<bool>()->default_value(false),
"if true : steady else unsteady")
// export
("export-matlab", "export matrix and vectors in matlab" );
return heatsinkoptions.add( Feel::feel_options() );
}

6.3.2 Surfaces
To be able to calculate the surfaces in further dimension without changing the code, we have given the
same names for the faces we were interested in. In 2D Γi represents a line whereas in 3D it represents a
surface. The calculation of those surfaces which makes possible the calculation of averages temperature is
as follow :
surface_base =
integrate( _range= markedfaces(mesh,"gamma4"), _expr=
cst(1.)).evaluate()(0,0);

50
Baptiste Morin, Christophe Prud’homme

surface_fin =
integrate( _range= markedfaces(mesh,"gamma1"),
_expr=cst(1.)).evaluate()(0,0);

6.3.3 Equations
First we start by calculate the non-steady state which means that we integrate all the time-independant
terms, which is done with :
/*
* Right hand side construction (steady state)
*/
form1( _test=Xh, _vector=F, _init=true ) =
integrate( _range= markedfaces(mesh, "gamma1"), _expr=
therm_coeff*Tamb*id(v));
/*
* Left hand side construction (steady state)
*/
form2( Xh, Xh, D, _init=true ) =
integrate( _range= markedelements(mesh,"spreader_mesh"),
_expr= kappa_s*gradt(T)*trans(grad(v)) );
form2( Xh, Xh, D) +=
integrate( _range= markedelements(mesh,"fin_mesh"),
_expr= kappa_f*gradt(T)*trans(grad(v)) );
form2 (Xh, Xh, D) +=
integrate( _range= markedfaces(mesh, "gamma1"),
_expr= therm_coeff*idt(T)*id(v));
form2(Xh, Xh, D) +=
integrate( _range=markedelements(mesh, "spreader_mesh"),
_expr=rho_s*c_s*idt(T)*id(v)*M_bdf->polyDerivCoefficient(0) )
+ integrate( _range=markedelements(mesh, "fin_mesh"),
_expr=rho_f*c_f*idt(T)*id(v)*M_bdf->polyDerivCoefficient(0) );
Then, to compute the transient state, which means time dependant terms, you have to initialize the
temperature (which is initialized as Tamb on Xh space) and create a new vector Ft which corresponds to
the time dependent term. The code is as follow :
T = vf::project( _space=Xh, _expr=cst(Tamb) );
M_bdf->initialize(T);
auto Ft = M_backend->newVector( Xh );
for ( M_bdf->start(); M_bdf->isFinished()==false; M_bdf->next() )
{
// update right hand side with time dependent terms
auto bdf_poly = M_bdf->polyDeriv();
form1( _test=Xh, _vector=Ft ) =
integrate( _range=markedelements(mesh, "spreader_mesh"),
_expr=rho_s*c_s*idv(bdf_poly)*id(v)) +
integrate( _range=markedelements(mesh, "fin_mesh"),
_expr=rho_f*c_f*idv(bdf_poly)*id(v) );
form1( _test=Xh, _vector=Ft ) +=
integrate( _range= markedfaces(mesh,"gamma4"),
_expr= heat_flux*(1-exp(-M_bdf->time()))*id(v) );
// add contrib from time independent terms
Ft->add( 1., F );
// solve
M_backend->solve( _matrix=D, _solution=T, _rhs=Ft );
// both average temperatures
Tavg = integrate( _range=markedfaces(mesh,"gamma4"),
_expr=(1/surface_base)*idv(T) ).evaluate()(0,0);

51
Heat sink

Tgamma1 = integrate( _range=markedfaces(mesh,"gamma1"),


_expr=(1/surface_fin)*idv(T) ).evaluate()(0,0);
// export results
out << M_bdf->time() << " " << Tavg << " " << Tgamma1 << "\n";
this->exportResults( M_bdf->time(), T );
}

6.3.4 Outputs
As you can see in the equation’s implementation above, there are two ouputs :

• G MSH format : this file contains the entire mesh and the temperatures associated to each degrees
of freedom of the mesh. To open it, you juste have to do as you always do with G MSH : gmsh
heatsink-1_0.msh. You will obtain the figure with the different temperatures, you are now able
to click on "play" with its significative logo and admire the evolution

• averages file : this file is completed at each time step, each line contains the current time, the
average temperature on Γ4 (surface where is the contact between the heat sink and the heat source)
and the average temperature on Γ1 . To analyze this file, we recommend you to work with O CTAVE
which is an open-source software similar to M ATLAB. If it is installed, open a command line and go
to ~/feel/heatsink/Simplex_*.*.*/0.000*/ and try :
> octave
octave:1> M=load(’averages’);
octave:2> plot(M(:,1),M(:,2))
octave:3> plot(M(:,1),M(:,3))
octave:4> plot(M(1:70,1),M(1:70,2))
octave:5> plot(M(1:70,1),M(1:70,3))

The 4th and 5th lines are here to observe the transient state.

6.4 Use cases


6.4.1 How to use it ?
To make easier the use of this application, we recommand you to use the configurations files. This is the
fastest way : to do it, you juste have to create the file heatsink.cfg and place it in the same directory
that your application’s executable.
We have created 3 typical cfg files such as :
# file heatsink_1.cfg
# spreader and fin in copper
# 2D simulation
hsize=1e-4
kappa_s=386 # W/m/K
c_s=385
rho_s=8940
kappa_f=386 # W/m/K
c_f=385 #J/kg/K
rho_f=8940
L=15e-3
width=5e-4
therm_coeff=1000 #W/(m2K)
heat_flux=1e6
[bdf]
order=2

52
Baptiste Morin, Christophe Prud’homme

time-step=0.05
time-final=100
steady=0
[exporter]
format=gmsh

# file heatsink_3.cfg
# spreader in copper
# fin in aluminium
# 3D simulation
hsize=3e-4
kappa_s=386 # W/m/K
c_s=385
rho_s=8940
kappa_f=386 # W/m/K
c_f=385 #J/kg/K
rho_f=8940
L=15e-3
width=5e-4
deep=4e-2
therm_coeff=1000 #W/(m2K)
heat_flux=1e6
[bdf]
order=2
time-step=0.05
time-final=100
steady=0
[exporter]
format=gmsh
This file is the only modification you will have to bring to the application, in that way you won’t have
to compile each time the files (except for heatsink.cpp if you want to increase the order and/or the
dimension, in that case you’ill have to modify this parameter at then end of the file in the main method).

6.4.2 Results
2D cases
Here are some results of the 2D simulations considering different configurations files. The figures have
been extracted thanks to G MSH and O CTAVE :

53
Heat sink

Figure 6.7: heatsink_1.cfg : steady state, spreader and fin in copper, Q = 1e6 and h = 1e3

Figure 6.8: heatsink_1.cfg : transient state on Γ4 Figure 6.9: heatsink_1.cfg : transient state on Γ1

54
Baptiste Morin, Christophe Prud’homme

3D cases
Here is the result of 3D simulations considering the following configurations :

Figure 6.10: heatsink_3.cfg : spreader and fin in copper, Q = 1e6 and h = 1e3

Figure 6.11: heatsink_3.cfg : transient state on Figure 6.12: heatsink_3.cfg : transient state on
Γ4 Γ1

55
Heat sink

56
Christophe Prud’homme

CHAPTER 7

Natural convection in a heated tank


By Christophe Prud’homme

Chapter ref: [cha:natural-convection-2d]

7.1 Description
The goal of this project is to simulate the fluid flow under natural convection: the heated fluid circulates
towards the low temperature under the action of density and gravity differences. Thie phenomenon is
important in the sense it models evacuation of heat, generated by friction forces for example, with a cooling
fluid.
We shall put in place a simple convection problem in order to study the phenomenon without having
to handle the difficulties of more complex domaines. We describe then some necessary transformations
to the equations, then we define quantities of interest to be able to compare the simulations with different
parameter values.
To study the convection, we use a model problem: it consists in a rectangular tank of height 1 and width
W , in which the fluid is enclosed, see figure 7.1. We wish to know the fluid velocity u, the fluid pressure
p and fluid temperature θ.
We introduce the adimensionalized Navier-Stokes and heat equations parametrized by the Grashof and
Prandtl numbers. These parameters allow to describe the various regimes of the fluid flow and heat transfer
in the tank when varying them.
The adimensionalized steady incompressible Navier-Stokes equations reads:

1
u · ∇u + ∇p − √ ∆u = θe2
Gr
(7.1)
∇ · u = 0 sur Ω
u = 0 sur ∂Ω

where Gr is the Grashof number, u the adimensionalized velocity and p adimensionalized pressure and θ
the adimensionalized temperature. The temperature is in fact the difference between the temperature in the
tank and the temperature T0 on boundary Γ1 .

57
Natural convection in a heated tank

1
Γ4

Γf

T0 Γ1 Γ3 Heat flux

Ω(F LUID)

Γ2
0

x
0 W

Figure 7.1: Geometry of the model

The heat equation reads:

1
u · ∇θ − √ ∆θ =0
GrPr
θ = 0 sur Γ1
∂θ (7.2)
= 0 sur Γ2,4
∂n
∂θ
= 1 sur Γ3
∂n
where Pr is the Prandtl number.

7.2 Influence of parameters


what are the effects of the Grashof and Prandtl numbers ? We remark that both terms with these parameters
appear in front of the ∆ parameter, they thus act on the diffusive terms. If we increase the Grashof number
or the Prandtl number the coefficients multiplying the diffusive terms decrease, and this the convection, that
is to say the transport of the heat via the fluid, becomes dominant. This leads also to a more difficult and
complex flows to simulate, see figure 7.2. The influence of the Grashof and Prandtl numbers are different
but they generate similar difficulties and flow configurations. Thus we look only here at the influence of
the Grashof number which shall vary in [1, 1e7].

7.3 Quantities of interest


We would like to compare the results of many simulations with respect to the Grashof defined in the
previous section. We introduce two quantities which will allow us to observe the behavior of the flow and
heat transfer.

58
Christophe Prud’homme

Figure 7.2: Velocity norm with respect to Grashof, Gr = 100, 10000, 100000, 500000. h = 0.01 and
Pr = 1.

7.3.1 Mean temperature


We consider first the mean temperature on boundary Γ3
Z
T3 = θ (7.3)
Γ3

This quantity should decrease with increasing Grashof because the fluid flows faster and will transport
more heat which will cool down the heated boundary Γ3 . We observe this behavior on the figure 7.3.

7.3.2 Flow rate


Another quantity of interest is the flow rate through the middle of the tank. We define a segment Γf as
being the vertical top semi-segment located at W/2 with height 1/2, see figure 7.1. The flow rate, denoted
Df , reads
Z
Df = u · e1 (7.4)
Γf

where e1 = (1, 0). Note that the flow rate can be negative or positive depending on the direction in which
the fluid flows.
As a function of the Grashof, we shall see a increase in the flow rate. This is true for small Grashof,
but starting at 1e3 the flow rate decreases. The fluid is contained in a boundary layer which is becoming
smaller as the Grashof increases.

59
Natural convection in a heated tank

Figure 7.3: Mean temperature with respect to the Grashof number; h = 0.02 with P3 Lagrange element
for the velocity, P2 Lagrange for the pressure and P1 Lagrange for the temperature.

Figure 7.4: Behavior of the flow rate with respect to the Grashof number; h = 0.02, P3 for the velocity, P2
for the pressure and P1 for the temperature.

60
Christophe Prud’homme

7.4 Implementation
This application in implemented in feel/doc/manual/convection*.cpp. The implementation
solve the full nonlinear problem using the nonlinear solver framework.

7.5 Numerical Schemes


7.5.1 Stokes problem formulation and the pressure
7.5.2 The Stokes problem
Consider the following problem,

 −µ∆u + ∇p = f
Stokes: ∇·u=0 (7.5)
u|∂Ω = 0

where Ω ⊂ Rd . There are no boundary condition on the pressure. This problem is ill-posed, indeed we
only control the pressure through its gradient ∇p. Thus if (u, p) is a solution, then (u, p + c) is also a
solution with c any constant. This comes from the way the problem is posed: the box is closed and it is not
possible to determine the pressure inside. The remedy is to impose arbitrarily a constraint on the pressure,
e.g. its mean value is zero. In other words, we add this new equation to the problem (7.5)
Z
p=0 (7.6)

Remark 1 (The Navier-Stokes case) This is also true for the incompressible Navier-Stokes equations. We
chose Stokes to simplify the exposure.

7.5.3 Reformulation
In order to impose the condition (7.6), we introduce a new unknown, a Lagrange multiplier, λ ∈ R and
modify the incompressibility equation. Our problem reads now, find (u, p, λ) such that


 −µ∆u + ∇p = f
∇·u+λ = 0

Stokes 2: (7.7)

 u|
R ∂Ω = 0
p = 0

Remark 2 (The pressure as Lagrange multiplier) The pressure field p can actually be seen as a La-
grange multiplier for the velocity u in order to enforce the constraint ∇ · u = 0. λ will play the same role
but for theR pressure to enforce
R the condition (7.6). As h → 0, λ → 0 as well as the divergence of u. Note
also that Ω ∇ · u ≈ − Ω λ from the second equation.

7.5.4 Variational formulation


The variational formulation now reads: find (u, p, λ) ∈ H10 (Ω) × L20 (Ω) × R such that for all (v, q, η) ∈
H10 (Ω) × L20 (Ω) × R
 R   R

 Ω
 ∇u : ∇v + ∇ · vp = Ωf ·v
R  
Stokes 3: ∇ · uq + λq = 0 (7.8)

 Ω R
pη = 0

61
Natural convection in a heated tank

Summing up all three equations we get the following condensed formulation:


Z Z
∇u : ∇v + ∇ · vp + ∇ · uq + λq + ηp = f ·v (7.9)
Ω Ω
n o n o
where H10 (Ω) = v ∈ L2 (Ω), ∇v ∈ [L2 (Ω)]d×d , v = 0 on ∂Ω , L20 (Ω) = v ∈ L2 (Ω), Ω v = 0 ,
R
n o
and L2 (Ω) = v ∈ [L2 (Ω)]d that is to say each component of a vector field of L2 (Ω) are in L2 (Ω).

7.5.5 Implementation
/*basis*/
typedef Lagrange<Order, Vectorial> basis_u_type; // velocity
typedef Lagrange<Order-1, Scalar> basis_p_type; // pressure
typedef Lagrange<0, Scalar> basis_l_type; // multipliers
typedef bases<basis_u_type, basis_p_type, basis_l_type> basis_type;
/*space: product of the velocity, pressure and multiplier spaces*/
typedef FunctionSpace<mesh_type, basis_type, value_type> space_type;
// ...
space_ptrtype Xh = space_type::New( mesh );
element_type U( Xh, "u" );
element_type V( Xh, "v" );
element_0_type u = U.element<0>();
element_0_type v = V.element<0>();
element_1_type p = U.element<1>();
element_1_type q = V.element<1>();
element_2_type lambda = U.element<2>();
element_2_type nu = V.element<2>();
// ...
sparse_matrix_ptrtype D( M_backend->newMatrix( Xh, Xh ) );
form2( Xh, Xh, D, _init=true )=
integrate( elements(mesh), im,
// ∇u : ∇v
mu*trace(deft*trans(def))
// ∇ · vp + ∇ · uq
- div(v)*idt(p) + divt(u)*id(q)
// λq + ηp
+id(q)*idt(lambda) + idt(p)*id(nu) );
// ...

7.5.6 Fix point iteration for Navier-Stokes


Steady incompressible Navier-Stokes equations
Consider the following steady incompressible Navier-Stokes equations, find (u, p) such that
ρu · ∇u − ν∆u +∇p = f on Ω
| {z } | {z }
convection diffusion
(7.10)
∇·u=0
u = 0 on ∂Ω
where ρ is the density of the fluid, ν is the dynamic viscosity of the fluid(la viscosité cinématique η = ν/ρ)
and f is the external force density applied to the fluid, (e.g. f = −ρge2 with e2 = (0, 1)T ). This equation
system is nonlinear due to the u · ∇u convection term. A simple approach to solve (7.10) is to use a fix
point algorithm.
The fixpoint algorithm for NS reads as follows, find (u(k) , p(k) ) such that

ρu(k−1) · ∇u(k) − ν∆u(k) + ∇p(k) = f on Ω


∇ · u(k) = 0
(7.11)
u(k) = 0 on ∂Ω
(u(0) , p(0) ) = (0, 0)

62
Christophe Prud’homme

The system (7.11) is now linear at each iteration k and we can write the variational formulation accordingly.
A stopping criterium is for example that kuk − u(k−1) k + kpk − p(k−1) k <  where  is a given tolerance
(e.g. 1e − 4) and k · k is the L2 norm.
Here is the implementation using F EEL ++:
// define some tolerance 
epsilon = 1e-4;
// set (u(0) , p(0) ) to (0, 0)
velocity_element_type uk(Xh);
velocity_element_type uk1(Xh);
pressure_element_type pk(Ph);
pressure_element_type pk1(Ph);
// by default uk1, uk and pk,pk1 are initialized to 0
// assemble the linear form associated to f
// store in vector F , it does not change over the iterations

// iterations to find (u(k) , p(k) )


do
{
// save results of previous iterations
uk1 = uk;
pk1 = pk;
//assemble for bilinear form associated to
// ρu(k−1) · ∇u(k) − ν∆u(k) + ∇p(k)
// store in matrix A(k)

// solve the system A(k) X = F where X = (u(k) , p(k) )T


// use uk,uk1 and pk,pk1 to compute the error estimation at each
iteration
error = kuk − u(k−1) k + kpk − p(k−1) k
} while( error > epsilon );

7.5.7 A Fix point coupling algorithm


Coupling fluid flow and heat transfer: problem
Recall that we have to solve two coupled problems :


 −κ∆T + u · ∇T = 0
T |Γ1 = T0

Heat(u) ∂T

 ∂n |Γ3 = 1
∂T
∂n |Γ2 ,Γ4 = 0

and
1

 −ν∆u + ρ ∇p = F
Stokes(T) : ∇·u=0
u|∂Ω = 0

 
0
Where F can be taken as for some β > 0. β is called the dilatation coefficient.
β(T − T0 )

Coupling fluid flow and heat transfer: algorithm


Here is a simple algorithm fix point strategy in pseudo-code:
double tol = 1.e-6;
int maxIter = 50;
//Initial guess Un = 0
do
{

63
Natural convection in a heated tank

// Find Tn solution of Heat(Un)


// Find Unp1 solution of Stokes(Tn)
// compute stopTest = norme(Unp1 - Un)
// Un = Unp1
}while((stopTest < tol) && (niter <= maxIter));

Remark 3 (The unsteady case) To solve the unsteady problems, one can insert the previous loop in the
one dedicated to time discretization

7.5.8 A Newton coupling algorithm


A fully coupled scheme
Another possiblity is to use a Newton method which allows us to solve the full nonlinear problem coupling
velocity, pressure and temperature
Find X such that F (X) = 0 (7.12)
the method is iterative and reads, find X (n+1) such that
JF (X (n) )(X (n+1) − X (n) ) = −F (X (n) ) (7.13)
starting with X (0) = 0 or some other initial value and where JF is the jacobian matrix of F evaluated at
X = ((ui )i , (pi )i , (θi )i )T . For any φk , ψl and ρm the test functions associated respectively to velocity,
pressure and temperature, our full system reads, Find X = ((ui )i , (pi )i , (θi )i )T such that
P P P P
F1 ((ui )i , (pi )i , (θi )i ) = i,j ui uj a(φi , φk , φj ) − i pi b(φk , ψi ) + i θi c(ρi , φk ) + i ui d(φi , φk ) = 0
P
F2 ((ui )i , (pi )i , (θi )i ) = Pi ui b(φi , ψl ) P =0
F3 ((ui )i , (pi )i , (θi )i ) = i,j ui θj e(φi , ρj , ρm ) + i θi f (ρi , ρm ) − g(ρm ) =0
(7.14)
where F = (F1 , F2 , F3 )T and
a(u, v, β) = RΩ vT ((∇u)β)R
R

b(v, p) = RΩ p(∇ · v) − ∂Ω v · np
c(θ, v) = Ω θe2 · v 
d(u, v) = √1Gr Ω ∇u : (∇v)T − ∂Ω ((∇u)n) · v
R R
R (7.15)
e(u, θ, χ) = Ω (u · ∇θ)χ 
1
R R
f (θ, χ) = √GrPr ∇θ · ∇χ − (∇θ · n)χ
1
R Ω Γ1
g(χ) = √GrPr Γ3
χ

Remark 4 Note that the boundary integrals are kept in order to apply the weak Dirichlet boundary condi-
tion trick, see next section B.4.

Jacobian matrix
In order to apply the newton scheme, we need to compute the jacobian matrix JF by deriving each equation
with respect to each unknowns, ie ui , pi and θi . Consider the first equation
• Deriving the first equation with respect to ui we get
∂F1 X X
= uj a(φi , φk , φj ) + ui a(φi , φk , φj ) + d(φi , φk ) (7.16)
∂ui j i

• Deriving the first equation with respect to pi we get


∂F1
= −b(φk , ψl ) (7.17)
∂pi

64
Christophe Prud’homme

• Deriving the first equation with respect to θi we get

∂F1
= c(ρi , ρk ) (7.18)
∂θi

Consider the second equation, only the derivative with respect to ui is non zero.

∂F2
= b(φi , ψl ) (7.19)
∂ui

Finally the third component

• Deriving with respect to ui


∂F3 X
= θj e(φi , ρj , ρm ) (7.20)
∂ui j

• Deriving with respect to pi ,


∂F3
=0 (7.21)
∂pi

• Deriving with respect to thetai ,

∂F3 X
= uj e(φj , ρi , ρm ) + f (ρi , ρm ) (7.22)
∂θi j

 ∂F ∂F1 ∂F1

1
∂u ∂pi ∂θi
 ∂F2i ∂F2 ∂F2
JF = ∂pi (= 0) ∂θi (= 0) (7.23)

 ∂ui
∂F3 ∂F3 ∂F3
∂ui ∂pi (= 0) ∂θi

In order to implement JF and solve (7.13), JF can be expressed as the matrix associated with the discreti-
sation of
a(u, v, β1 ) + a(β1 , v, u) + d(u, v) − b(v, p) + c(θ, v) = 0
b(u, q) = 0 (7.24)
e(β1 , θ, χ) + f (θ, χ) + e(u, β2 , χ) = 0

where β1 = u(n) , β2 = θ(n) are known from the previous Newton iteration, indeed JF is actually evaluated
in X (n) .

F EEL ++ Implementation

Now we use the F EEL ++ non linear framework in order to implement our Newton scheme (7.13). We need
to define two new functions in our application

• updateJacobian(X,J) which takes as input X= X (n) and returns the matrix J=JF (X (n) )

• updateResidual(X,R) which takes as input X= X (n) and returns the vector R=F (X (n) )

Remark 5 Backend Only the PETSC backend supports the nonlinear solver framework. Use in the com-
mand line like in the first section
--backend=petsc

Here is a snippet of code that implements the nonlinear framework.

65
Natural convection in a heated tank

class MyApp
{
public:
void run();
void updateResidual( const vector_ptrtype& X, vector_ptrtype& R );
void updateJacobian( const vector_ptrtype& X, sparse_matrix_ptrtype& J);
void solve( sparse_matrix_ptrtype& D, element_type& u, vector_ptrtype&
F );
private:
backend_ptrtype M_backend;
sparse_matrix_ptrtype M_jac;
vector_ptrtype M_residual;
};
void
MyApp::run()
{
// ...
// plug the updateResidual and updateJacobian functions
// in the nonlinear framework
M_backend->nlSolver()->residual = boost::bind(
&self_type::updateResidual,
boost::ref( *this ), _1,
_2 );
M_backend->nlSolver()->jacobian = boost::bind(
&self_type::updateJacobian,
boost::ref( *this ), _1,
_2 );
vector_ptrtype U( M_backend->newVector( u.functionSpace() ) );
*U = u;
vector_ptrtype R( M_backend->newVector( u.functionSpace() ) );
this->updateResidual( U, R );
sparse_matrix_ptrtype J;
this->updateJacobian( U, J );
solve( J, u, R );

*U = u;
this->updateResidual( U, R );
// R(u) should be small
std::cout << "R( u ) = " << M_backend->dot( U, R ) << "\n";

}
void
MyApp::solve( sparse_matrix_ptrtype& D, element_type& u, vector_ptrtype&
F )
{
vector_ptrtype U( M_backend->newVector( u.functionSpace() ) );
*U = u;
M_backend->nlSolve( D, U, F, 1e-10, 10 );
u = *U;
}
void
MyApp::updateResidual( const vector_ptrtype& X, vector_ptrtype& R )
{
// compute R(X)
R=M_residual;
}
void
MyApp::updateJacobian( const vector_ptrtype& X, vector_ptrtype& R )
{
// compute J(X)
J=M_jac;
}
see bratu.cpp or nonlinearpow.cpp for example.

66
Thomas Strub, Philippe Helluy, Christophe Prud’homme

CHAPTER 8

2D Maxwell simulation in a diode


By Thomas Strub, Philippe Helluy, Christophe Prud’homme

Chapter ref: [cha:maxwell-2d]

8.1 Description
The Maxwell equations read:

−1 ∂E
+∇×B = µ0 J
c2 ∂t
Bt + ∇ × E = 0
∇·B = 0
ρ
∇·E =
o
where E is the electric field, B the magnetic field, J the current density, c the speed of light, rho
density of electric charge, mu0 the vacuum permeability and epsilon0 the vacuum permittivity.
In the midst industrial notament in aeronautics, systems Products must verify certain standards such as
the receipt an electromagnetic wave emitted by a radar does not cause the inefficassité of part or all of the
hardware in the system.
Thus, the simulation of such situations can develop when or during the certification of a new product
to test its reaction to such attacks.
Also note that the last two equations are actually initial conditions, since if we assume they are true at
the moment t = 0 then it can be deduced from the first two.
At t = 0s, we suppose that
∇·B = 0 (8.1)
ρ
∇·E = (8.2)
o
Suppose that B = (Bx , By , Bz )T and E = (Ex , Ey , Ez )T i.e.
∂Bx ∂By ∂Bz
(t = 0) + (t = 0) + (t = 0) = 0 (8.3)
∂x ∂y ∂z
∂Ex ∂Ey ∂Ez ρ
(t = 0) + (t = 0) + (t = 0) = (8.4)
∂x ∂y ∂z o

67
2D Maxwell simulation in a diode

Differentiating the first of these two equations with respect to time, we get:

∂ ∂ ∂ ∂ ∂ ∂
Bx + By + Bz =
∂t ∂x ∂t ∂y ∂t ∂z
     
∂ ∂ ∂ ∂ ∂ ∂ ∂ ∂ ∂
Ez − Ey + Ex − Ez + Ey − Ex
∂x ∂y ∂z ∂y ∂z ∂x ∂z ∂x ∂y
= 0 (8.5)

thanks to

Bt + ∇ × E = 0 (8.6)
So, for all t ≥ 0,
∇ · B(t) = ∇ · B(0) = 0 (8.7)
We deduce the same way the second equation, using the charge conservation equation :
∂ρ
+ ∇ · (ρJ ) = 0 (8.8)
∂t

8.2 Variational formulation


8.3 Implementation
8.4 Numerical Results

68
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

CHAPTER 9

Domain decomposition methods


By Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

Chapter ref: [cha:dd]

9.1 A Really Short Introduction


In mathematics, numerical analysis, and numerical partial differential equations, domain decomposition
methods solve a boundary value problem by splitting it into smaller boundary value problems on subdo-
mains and iterating to coordinate the solution between the adjacent subdomains. A corse problem with one
or fiew unknows per subdomain is used to further coordinate the solution between the subdomains globally.

9.2 A 1D model
We consider the following laplacian boundary value problem
(
− u”(x) = f (x) in ]0, 1[
(9.1)
u(0) = α, u(1) = β

where α, β ∈ R.

9.2.1 Schwartz algorithms


The schwartz overlapping multiplicative algorithm with dirichlet interface conditions for this problem at
nth iteration is given by
n n
 
 −u1 ” (x) = f (x) in ]0, b[
  −u2 ” (x) = f (x) in ]a, 1[

un1 (0) = α and un2 (1) = β (9.2)
n n
 n n−1

u1 (b) = u2 (b) u2 (a) = u1 (a)
 

where n ∈ N∗ , a, b ∈ R and a < b.


Let eni = uni − u (i = 1, 2), the error at nth iteration relative to the exact solution, the convergence rate is
given by
|en1 | a 1−b |en2 |
ρ = n−1 = = n−1 . (9.3)
|e1 | b 1−a |e2 |

69
Domain decomposition methods

9.2.2 Variational formulations


find u such that Z b Z b
u01 v 0 = fv ∀v in the first subdomain Ω1 =]0, b[
0 0
Z 1 Z 1
u02 v 0 = fv ∀v in the second subdomain Ω2 =]a, 1[
a a

9.3 A 2 domain overlapping Schwartz method in 2D and 3D


We consider the following laplacian boundary value problem
(
−∆u = f in Ω
(9.4)
u=g on ∂Ω

where Ω ⊂ Rd , d = 2, 3 and g is the dirichlet boundary value.

9.3.1 Schwartz algorithms


The schwartz overlapping multiplicative algorithm with dirichlet interface conditions for this problem on
two subdomains Ω1 and Ω2 at nth iteration is given by
n n
 −∆u1 = f
 
 in Ω1  −∆u2 = f
 in Ω2
n ext n
u1 = g on ∂Ω1 and u2 = g on ∂Ωext2 (9.5)
  n n
n n−1
u = u on Γ
 
u1 = u2 on Γ1 2 1 2

9.3.2 Variational formulations


Z Z
∇ui · ∇v = fv ∀ v, i = 1, 2.
Ωi Ωi

F EEL ++ implementation

/*
Implementation of the local problem
*/
template<Expr>
void
localProblem(element_type& u, Expr expr)
{ Z
// Assembly of the right hand side fv

auto F = M_backend->newVector(Xh);
form1( _test=Xh,_vector=F, _init=true ) =
integrate( elements(mesh), f*id(v) );
F->close();
Z
// Assembly of the left hand side ∇u · ∇v

auto A = M_backend->newMatrix( Xh, Xh );
form2( _test=Xh, _trial=Xh, _matrix=A, _init=true ) =
integrate( elements(mesh), gradt(u)*trans(grad(v)) );
A->close();
// Apply the dirichlet boundary conditions
form2( Xh, Xh, A ) +=
on( markedfaces(mesh, "Dirichlet") ,u,F,g);
// Apply the dirichlet interface conditions

70
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

form2( Xh, Xh, A ) +=


on( markedfaces(mesh, "Interface") ,u,F,expr);
// solve the linear system Au = F
M_backend->solve(_matrix=A, _solution=u, _rhs=F );
}
unsigned int cpt = 0;
double tolerance = 1e − 8;
double maxIterations = 20;
double l2erroru1 = 1.;
double l2erroru2 = 1;
/*
Iteration loop
*/
while( (l2erroru1 +l2erroru2 ) > tolerance && cpt <= maxIterations)
{
// call the localProblem on the first subdomain Ω1
localProblem(u1 , idv(u2 ));
// call the localProblem on the first subdomain Ω2
localProblem(u2 , idv(u1 ));
// compute L2 errors on each subdomain
L2erroru1 = l2Error(u1 );
L2erroru2 = l2Error(u2 );
// increment the cunter
++cpt;
}

9.3.3 Numerical results in 2D case


The numerical results presented in the following table correspond to the partition of the global domain Ω
in two subdomains Ω1 and Ω2 (see figure 9.2) and the following configuration:
1. g(x, y) = sin(πx) cos(πy) : the exact solution
2. f (x, y) = 2π 2 g : the right hand side of the equation
3. P2 approximation : the lagrange polynomial order
4. hsize = 0.02 : the mesh size
5. tol = 1e − 9 : the tolerance
Ω1
Ω1

Ω2

Ω2
Ω2

Ω2

Ω1
Ω1

(a) Two overlapping subdomains (b) Two overlapping meshes

Figure 9.1: geometry

71
Domain decomposition methods

Nomber of iterations ku1 − uex kL2 ku2 − uex kL2


11 2.52e-8 2.16e-8

9.3.4 Numerical solutions in 2D case

(a) first iteration (b) 10th iteration

Figure 9.2: isovalues of solution in 2D

9.4 Computing the eigenmodes of the Dirichlet to Neumann oper-


ator
9.4.1 Problem description and variational formulation
We consider at the continuous level the Dirichlet-to-Neumann(DtN) map on Ω, denoted by DtNΩ .
Let u : Γ 7−→ R,
∂v
DtNΩ (u) = κ
n Γ
where v satisfies (
L(v) := (η − div(κ∇))v = 0 dans Ω,
(9.6)
v=u sur Γ

where Ω is a bounded domain of Rd (d=2 or 3), and Γ it border, κ is a positive diffusion function which
can be discontinuous, and η ≥ 0. The eigenmodes of the Dirichlet-to-Neumann operator are solutions of
the following eigenvalues problem
DtNΩ (u) = λκu (9.7)
To obtain the discrete form of the DtN map, we consider the variational form of (9.6). let’s define the
bilinear form a : H 1 (Ω) × H 1 (Ω) −→ R,
Z
a(w, v) := ηwv + κ∇w · ∇v.

With a finite element basis {φk }, the coefficient matrix of a Neumann boundary value problem in Ω is
Z
Akl := ηφk φl + κ∇φk · ∇φl .

A variational formulation of the flux reads


Z Z
∂v
κ φk = ηvφk + κ∇v · ∇φk ∀ φk .
Γ ∂n Ω

72
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

So the variational formulation of the eigenvalue problem (9.7) reads


Z Z
ηvφk + κ∇v · ∇φk = λ κvφk ∀ φk . (9.8)
Ω Γ

Let B be the weighted mass matrix Z


(B)kl = κφk φl
Γ
The compact form of (9.8) is
Av = λBv (9.9)

F EEL ++ implementation

Z
// Assembly of the right hand side B = κvw
Γ
auto B = M_backend->newMatrix( Xh, Xh ) ;
form2( _test=Xh, _trial=Xh, _matrix=B, _init=true );
BOOST_FOREACH( int marker, flags )
{
form2( Xh, Xh, B ) +=
integrate( markedfaces(mesh,marker), kappa*idt(u)*id(v) );
}
B->close(); Z
// Assembly of the left hand side A = ηvw + κ∇v · ∇w

auto A = M_backend->newMatrix( Xh, Xh ) ;
form2( _test=Xh, _trial=Xh, _matrix=A, _init=true ) =
integrate( elements(mesh), kappa*gradt(u)*trans(grad(v)) + nu*idt(u)*id(v) );
A->close();
// eigenvalue solver options
int nev = this->vm()["solvereigen-nev"].template as<int>();
int ncv = this->vm()["solvereigen-ncv"].template as<int>();;
// definition of the eigenmodes
SolverEigen<double>::eigenmodes_type modes;
// solve the eigenvalue problem Av = λBv
modes=
eigs( _matrixA=A,
_matrixB=B,
_nev=nev,
_ncv=ncv,
_transform=SINVERT,
_spectrum=SMALLEST_MAGNITUDE,
_verbose = true );
}

9.4.2 Numerical solutions

(a) first mode (b) second mode (c) third mode

Figure 9.3: three eigenmodes

73
Domain decomposition methods

These numerical solutions correspond to the following configuration :


1. P2 approximation : the lagrange polynomial order

2. hsize = 0.02 : the mesh size


3. µ = κ = 1.

74
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

Part III

Programming with F EEL ++

75
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

Part IV

Appendix

77
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

APPENDIX A

How to ?

A.1 Introduction
This section includes the FAQ avaible on Feel web site, if you want to post a question, please visit it and
follow the instruction to edit the FAQ.

A.2 Meshes
A.2.1 What are the main execution options of a F EEL ++ application ?
Let’s consider that your application is named feelapp, in that case you can modify the main execution
options of your application with
./feelapp --shape="simplex" --nochdir --exporter-format=gmsh
These options are :
• shape=["simplex","hypercube"] which is the shape of the generated mesh
• nochdir means that you want the result in the current directory (by default in ~/feel)
• exporter-format enables you to choose the format of mesh results output

A.2.2 How to create a mesh?


Here is an example of how to create a mesh with GMSH generator :
mesh_ptrtype mesh =
createGMSHMesh( _mesh=new mesh_type,
_update=MESH_CHECK!MESH_UPDATE_FACES!MESH_UPDATE_EDGES!MESH_RENUMBER,
_desc=domain( _name= (boost::format( "%1%-%2%-%3%" ) %"hypercube"
%Dim %1).str(),
_shape="hypercube",
_dim=Dim,
_h=meshSize,
_xmin=-1.,
_xmax=1.,
_ymin=-1.,
_ymax=1. ) );
Here is an example of how to create a mesh with a .geo file :

79
Domain decomposition methods

mesh_ptrtype mesh =
createGMSHMesh( _mesh=new mesh_type,
_update=MESH_CHECK!MESH_UPDATE_FACES!MESH_UPDATE_EDGES!MESH_RENUMBER,
_desc="???" );

A.2.3 What are the different parameters of the function domain() ?


The function domain() is located in feel/feel/feefilters/gmsh.hpp and enables to generate a
simple geometrical domain from required and optional parameters. Its avaible options are :
• _name = "string" gives the prefix of the gmsh geo and mesh files,
• _shape = "simplex", "hypercube", "ellipsoid" gives the shape of the domain, it is one
of these three possibilities
• _dim = 1, 2 or 3 gives the topological dimension of the domain. For example if _dim=2 and
_shape="simplex" this will produce a triangle

• _h = real value gives the characteristic size of the mesh, e.g. _h=0.1
• _xmin = real gives the minimum x value of the domain for example _xmin=-1
• _xmax = real gives the maximum x value of the domain for example _xmax=-1
• _ymin = real gives the minimum x value of the domain for example _ymin=-1.
• _ymax = real gives the maximum y value of the domain for example _ymax=1.

A.2.4 How to loop on the degrees of freedom coordinates of a function ?


Take a look at the example which is in feel/examples/snippets/dofpoints.cpp

A.2.5 How to work with specific meshes ?


loadmesh.cpp
F EEL ++ supports several meshes file formats. It supports essentially Gmsh mesh file format but other are
acceptable, with some modifications :
• medit (.mesh)
There is a small difference between medit meshes and gmsh ones. The medit reader of Gmsh is
able to read medit meshes, the issue comes from markers for areas of the edges were we want to
apply different boundary conditions. Gmsh is currently using the Physical Entities (physical line,
area, volume). Unfortunetly, the medit reader of Gmsh considers the physical flag as null (to go
deeper, you can check this part on Gmsh web site). This option is took into account in F EEL ++,
the only modification is to put the optional parameter physical_are_elementary_regions as
true in both functions createGMSHMesh and/or loadGMSHMesh. We have prepared a simple ex-
ample which imports a medit mesh with a surface and volume calculation on it. You can find it in
feel/doc/manual/loadmesh.cpp.
Please not that furthers medit meshes are presented in example in the directory /feel/data/medit/.
The geo scripts are those which are produced by F EEL ++ when reading those meshes.
• Stl (.stl)
You can also use stl files, those files are native to the stereolithography CAD software created by
3D Systems. These files describe only the surface geometry of a three dimensional object without
any representation of color, texture or other common attributes. You have further examples of such
files in feel/data/stl.
To use F EEL ++ with stl files, you have to create a geo script to enable gmsh to remesh the file. The
stl file you want to use has to be a volume mesh. The script is very small, you have all informations
to make one at Gmsh/slt section on their web site. Once it’s done, you juste have to type

80
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

gmsh stl_le_name.geo -3
with stl_file_name.stl in the same directory. That command will produce you the correct .msh
mesh that you could now use as usual without any modification in your F EEL ++ application.
Take a look above how the remesh has produced a complete mesh with the file pelvis.stl and
pelvis.geo:

Figure A.1: Pelvis before remesh (stl) Figure A.2: Pelvis after remesh (msh)

A.3 Language for Partial Differential Equations


A.3.1 What is the difference between using the "vf::project" function and solve a weak
projection problem ?
To make it clear, let’s considerate that we want to project a P1 scalar function σ on a P0 space. We have
two alternatives to do it :

• Computing the L2 projection of σ onto the space


Here kappa and v are P0 functions :
Matrix_M=integrate(elements(mesh), idt(kappa) * id(v));
Vector_F=integrate(elements(mesh), idv(sigma) * id(v));

• Use the project function vf::project


This function does a nodal projection : at the dof point the projection will be exactly equal to the
projected function σ. It works as follow
kappa=vf::project(P0_space, elements(mesh), idv(sigma));

These two projections are in general different, if you compare the values in the vector, they will be
(slightly) different. However as h → 0 they should both converge to the σ function.

A.3.2 How to do a quick L2 projection of an expression ?


Let say that we have created two spaces, one scalar and one vectorial, we call them Xh and XhV ec and one
wants to project some expressions on those spaces.
p
For example, we want to project (x, y) → x2 − y 2 − 1 on the scalar space and (−2y, cos x) on the
vectorial space. First of all, one has to create projectors for the scalar and vectorial spaces, the code reads
as follow :
#include <feel/feeldiscr/projector.hpp>
auto l2p = projector(Xh, Xh);
auto l2pVec = projector(XhVec, XhVec);

81
Domain decomposition methods

You can note that projector(Space, Space) returns a boost::shared_ptr on a Projector object
which makes projecting functions on Space possible.

Then, one uses the function Projector::project(Expression) :


auto Circle = l2p->project( sqrt( pow((vf::Px()),2.0)+ pow((vf::Py()),2.0)) -
1 );
auto F = l2pVec->project( -2 * Py() * oneX() + cos(vf::Px()) * oneY() );
Here you can note that the types of Circle and F are respectively : Xh _type :: element_type and
XhV ec _type :: element_type
An equivalent way to write it is to use the Projector::operator()(Expression) :
auto Circle = (*l2p)( sqrt( pow((vf::Px()),2.0)+ pow((vf::Py()),2.0)) - 1 );
auto F = (*l2pVec)( -2 * Py() * oneX() + cos(vf::Px()) * oneY() );
Projector::operator() accepts many types of arguments, see feel/feeldiscr/projector.hpp
for details.

A.3.3 How to compose F EEL ++ operators ?


Let’s considerate that we have created two spaces, one scalar Xh and one vectorial XhV ec . We also have
two vectors a and b (of type Xh _type :: element_type).
One wants to do the following operation : div(grad(a ∗ b)). The following expression is not yet
implemented in F EEL ++:
divv( gradv( idv(a) * idv(b) ) )
One has to do intermediate projections to compose the operators. Using the Projector class, the code reads
:
#include <feel/feeldiscr/projector.hpp>
// create projectors on Xh and XhVec spaces
auto l2p = projector(Xh, Xh);
auto l2pVec = projector(XhVec, XhVec);
auto ab = l2p->project( idv(a)*idv(b) );
auto grad_ab = l2pVec->project( gradv(ab) );
auto div_grad_ab = l2p->project( divv(grad_ab) );
Here div_grad_ab has the type Xh _type :: elementt ype. There is an equivalent but verboseless way to
write this composition : use the Projector::operator() which accepts has argument an expression or
an element_type. So one could write :
#include <feel/feeldiscr/projector.hpp>
//create projectors on Xh and XhVec spaces
auto l2p = projector(Xh, Xh);
auto l2pVec = projector(XhVec, XhVec);
auto div_grad_ab = (*l2p)( divv( (*l2pVec)( gradv( (*l2p)(idv(a)*idv(b)) ) )
) );
the * is needed before l2p or l2pVec since there are boost::shared_ptr objects. One could also create
directly Projector objects :
Projector<Xh_type, Xh_type> l2p(Xh, Xh);
auto ab = l2p(idv(a)*idv(b));

82
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

APPENDIX B

Random notes

B.1 Becoming a Feel++ developer


B.1.1 Interest
Becoming a F EEL ++ developer makes library improvements possible, you may have several proposals
which may be usefull. Taking part of the project will enable you to commit some modifications or new
applications, we will be glad to count you among us. As an open-source project under GNU licence, you
will be able to commit and participate to the entire project and its various aspects. Our aim is that each
user should be involved in the library’s expansion. In the following part, you will see how you can become
a F EEL ++ collaborator.

B.1.2 Creating RSA keys


At the top of the manual, you have seen how to get the sources anonymously, if you want to checkout or
commit properly, you will need an account on . After the administrator approval, you have to demand the
rights to see the project tree.

Once it’s done, you will have to create RSA keys to be able to connect to the server using ssh. To do
that you have to type the commands : ssh-keygen and accept the 3 questions without typing anything.
The generated key is placed in ~/.ssh/id_rsa.pub, you just need to copy this file’s content in your
forge account. To make it, go on the Forge website and enter into your account’s personnal page. At
the bottom of the page, you’ll have the possibility to edit your SSH keys, go into it and copy/paste the
id_rsa.pub content. Once it’s done, the number of your SSH keys in that page should have increased. Now,
you will be able to connect to the server within an hour.

Important : If you don’t have the same login on your computer as on Forge, you must add the com-
mands in the ~/.ssh/config file :
host forge.imag.fr
user <your_login_forge>

B.1.3 Downloading the sources


To be able to download the F EEL ++ sources, you need subversion and SSH > 1.xxx installed on your
computer. In a command prompt, go where you want F EEL ++ to be downloaded and type the following

83
Domain decomposition methods

command :
svn co svn+ssh://[email protected]/var/lib/gforge/chroot/scmrepos
/svn/life/trunk/life/trunk feel
where login is your login name in the Forge plateform.
You are now able to checkout, commit or add the file your judge usefull using svn, please don’t forget
to comment on your various actions. The first commit is subject to the approbation of one of the main
developers.

B.2 Programming environment


We present here a quick list of all namespaces and librairies proposed by F EEL ++, refer to the tutorial
which starts at chapter 3 how you can use them.

B.2.1 Boost C++ Libraries


F EEL ++ depends on a number of libraries, some are required some are optional. Among the required
libraries, The Boost C++ libraries play a very important role as they drive or shape the design of F EEL ++.
F EEL ++ uses in particular the following Boost libraries:

• Boost.Parameter : use to provide powerful interfaces to F EEL ++ and third party library such as

– PETSc for the linear, nonlinear solvers


– SLEPc for the eigenvalue solvers
– GMSH for mesh generation

• Boost.MPL - meta programming library : use for type computations

• Boost.Fusion - linking meta-runtime programming: use for type computations used at runtime

• Boost.Program_Options - command-line options library : provides the command line options for the
F EEL ++ applications as well as configuration files

• Boost.Test - Unit testing framework ; used by the F EEL ++ testsuite

B.2.2 F EEL ++ Namepaces


• Feel

• Feel::po

• Feel::mpl

• Feel::ublas

• Feel::math

• Feel::fem

• Feel::vf

84
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

B.3 Linear Algebra with PETSC


B.3.1 Using the Petsc Backend: recommended
Using the Petsc backend is recommended. To do that type in the command line
myprog --backend=petsc

then you can change the type of solvers and preconditioners by adding Petsc options at the end of the
command lines, for example

-pc_type lu

will actually solve the problem in one iteration of an iterative solver (p.ex. gmres).

P Ax = P B (B.1)

where P ≈ A−1 . Here A is decomposed in LU form and (B.1) is solved in one iteration.

B.3.2 List of solvers and preconditioners


List of some iterative solvers (Krylov subspace)

• cg, bicg

• gmres, fgmres, lgmres

• bcgs, bcgsl

• see petsc/petscksp.h for more

List of some preconditioners

• lu, choleski

• jacobi, sor

• ilu, icc

• see petsc/petscpc.h for more

B.3.3 What is going on in the solvers?


In order to monitor what is going on (iterations, residual...) Petsc provides some monitoring options

-ksp_monitor

For example

myprog -backend=petsc -ksp_monitor -pc_type lu

it should show only one iteration.


See http://www.mcs.anl.gov/petsc/petsc-as/snapshots/petsc-current/docs/manualpages/KSP/KSPMonitorSet.html for more details

85
Domain decomposition methods

B.4 Weak Dirichlet boudary conditions


B.4.1 Basic idea
Weak treatment
In order to treat the boundary conditions uniformly (i.e. the same way as Neumann and Robin Conditions),
we wish to treat the Dirichlet BC (e.g. u = g) weakly.
R
Remark 6 Initial Idea add the penalisation term ∂Ω µ(u − g) where µ is a constant. But this is not
enough, this is not consistent with the initial formulation.

One can use the Nitsche “trick” to implement weak Dirichlet conditions.
• write the equations in conservative form (i.e. identify the flux);
• add the terms to ensure consistency (i.e the flux on the boundary);
• symmetrize to ensure adjoint consistency;
• add a penalisation term with factor γ(u − g)/h that ensures that the solution will be set to the proper
value at the boundary;

Penalisation parameter
Remark 7 Choosing γ γ must be chosen such that the coercivity(or inf-sup) property is satisfied. Difficult
to do in general. Increase γ until the BC are properly satisfied, e.g. start with γ = 1, typical values are
between 1 and 10.
The choice of γ is a problem specially when h is small.

Advantages, disadvantages
Remark 8 Weak treatment: Advantages
• uniform(weak) treatment of all boundary conditions type
• if boundary condition is independant of time, the terms are assembled once for all
• the boundary condition is not enforced exactely but the convergence order remain optimal

Remark 9 Weak treatment: Disadvantages


• Introduction of the penalisation parameter γ that needs to be tweaked

Advantages, disadvantages
Remark 10 Strong treatment: Advantages
• Enforce exactely the boundary conditions

Remark 11 Strong treatment : Disadvantages


• Need to modify the matrix once assembled to reflect that the Dirichlet degree of freedom are actually
known. Then even if the boundary condition is independant of time, at every time step if there are
terms depending on time that need reassembly (e.g. convection) the strong treatment needs to be
reapplied.
• it can be expensive to apply depending on the type of sparse matrix used, for example using CSR
format setting rows to 0 except on the diagonal to 1 is not expensive but one must do that also for the
columns associated with each Dirichlet degree of freedom and that is expensive.

86
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

B.4.2 Laplacian
Example: Laplacian
− ∆u = f (non conservative), −∇ · (∇u) = f (conservative), u = g|∂Ω (B.2)
the flux is vector ∇u

Z Z
∂u ∂v γ
∇u · ∇v + − v − u + uv (B.3)
Ω ∂Ω ∂n
| {z } ∂n
| {z } h
|{z}
integration by part adjoint consistency: symetrisation penalisation: enforce Dirichlet condition
Z Z
∂v γ
f ∇v + ( − g + v)g (B.4)
Ω ∂Ω ∂n
| {z } h
| {z }
adjoint consistency penalisation: enforce Dirichlet condition

Example: Laplacian

// bilinear form (left hand side)


form2( Xh, Xh, D ) +=
integrate( boundaryfaces(mesh), im_type(),
-(gradt(u)*N())*id(v) // integration by part
-(grad(v)*N())*idt(u) // adjoint consistency
+gamma*id(v)*idt(u)/hFace()); // penalisation
// linear form (right hand side)
form1( Xh, F ) +=
integrate( boundaryfaces(mesh), im_type(),
-(grad(v)*N())*g // adjoint consistency
+gamma*id(v)*g/hFace()); // penalisation

B.4.3 Convection-Diffusion
Example: Convection-Diffusion
Remark 12 Convection Diffusion Consider now the following problem, find u such that

− ∆u + c · ∇u = f, u = g|∂Ω , ∇·c=0 (B.5)

under conservative form the equation reads

∇ · (−∇u + cu) = f, u = g|∂Ω , ∇·c=0 (B.6)

the flux vector field is F = −∇u + cu. Note that here the condition, ∇ · c = 0 was crucial to expand
∇ · (cu) into c · ∇u since
∇ · (cu) = c · ∇u + u∇
| {z· c} (B.7)
=0

Weak formulation for convection diffusion


Multiplying by any test function v and integration by part of (B.6) gives
Z Z Z
∇u · ∇v + (c · ∇u)v + (F · n)v = fv (B.8)
Ω ∂Ω Ω

where n is the outward unit normal to ∂Ω. We now introduce the penalisation term that will ensure that
u → g as h → 0 on ∂Ω. (B.8) reads now
Z Z Z Z
γ γ
∇u · ∇v + (c · ∇u)v + (F · n)v + uv = fv + gv (B.9)
Ω ∂Ω h Ω ∂Ω h

87
Domain decomposition methods

Finally we incorporate the symetrisation of the bilinear form to ensure adjoint consistency and hence
proper convergence order
Z Z
γ
∇u · ∇v + (c · ∇u)v + ((−∇u + cu) · n)v + ((−∇v + cv) · n)u + uv =
Ω ∂Ω h
Z Z (B.10)
γ
fv + ((−∇v + cv) · n)g + gv
Ω ∂Ω h

Example: Convection-Diffusion

// bilinear form (left hand side)


form2( Xh, Xh, D ) +=
integrate( boundaryfaces(mesh), im_type(),
// integration by part
-(gradt(u)*N())*id(v) + (idt(u)*trans(idv(c))*N())*id(v)
// adjoint consistency
-(grad(v)*N())*idt(u) + (id(v)*trans(idv(c))*N())*idt(u)
// penalisation
+gamma*id(v)*idt(u)/hFace());
// linear form (right hand side)
form1( Xh, F ) +=
integrate( boundaryfaces(mesh), im_type(),
// adjoint consistency
-(grad(v)*N())*g + (id(v)*trans(idv(c))*N())*g
// penalisation
+gamma*id(v)*g/hFace());

B.4.4 Stokes
Example: Stokes
Remark 13 Stokes Consider now the following problem, find (u, p) such that

− ∆u + ∇p = f , u = g|∂Ω , ∇·u=0 (B.11)

under conservative form the equation reads

∇ · (−∇u + pI) = f, (B.12)


∇·u = 0, (B.13)
u = g|∂Ω (B.14)
 
1 0
where I(x) = (in 2D) ∀x ∈ Ω is the identity tensor(matrix) field ∈ Rd×d . The flux tensor field is
0 1
F = −∇u + pI. Indeed we have the following relation, if M is a tensor (rank 2) field and v is a vector
field
∇ · (Mv) = (∇ · M) · v + M : (∇v) (B.15)
where M : (∇v) = trace(M ∗ ∇vT ), ∗ is the matrix-matrix multiplication and∇ · Mis the vector field
p 0
with components the divergence of each row of M. For example ∇ · (p I) = ∇ · (in 2D) = ∇p.
0 p

Weak formulation for Stokes


Taking the scalar product of (B.12) by any test function v (associated to velocity) and multiplying (B.13)
by any test function q (associated to pressure), the variational formulation of (B.12) reads, thanks to (B.15),
Z Z Z
∇u : ∇v + p∇ · v + ((−∇u + pI)n) · v = f ·v (B.16)
Ω ∂Ω Ω

88
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

where n is the outward unit normal to ∂Ω. We now introduce the penalisation term that will ensure that
u → g as h → 0 on ∂Ω. (B.16) reads now
Z Z Z Z
γ γ
∇u : ∇v + p∇ · v + ((−∇u + pI)n) · v + u · v = f ·v+ g·v (B.17)
Ω ∂Ω h Ω ∂Ω h

Finally we incorporate the symetrisation of the bilinear form to ensure adjoint consistency and hence
proper convergence order
Z Z
γ
∇u : ∇v + p∇ · v + ((−∇u + pI)n) · v + ((−∇v + qI)n) · u + u · v =
Ω ∂Ω h
Z Z (B.18)
γ
f ·v+ ((−∇v + qI)n) · g + g · v
Ω ∂Ω h

Example: Stokes

// total stress tensor (trial)


AUTO( SigmaNt, (-idt(p)*N()+mu*gradt(u)*N()) );
// total stress tensor (test)
AUTO( SigmaN, (-id(p)*N()+mu*grad(v)*N()) );
// linear form (right hand side)
form1( Xh, F ) +=
integrate( boundaryfaces(mesh), im,
trans(g)*(-SigmaN+gamma*id(v)/hFace() ) );
// bilinear form (left hand side)
form2( Xh, Xh, D )+=
integrate( boundaryfaces(mesh), im,
-trans(SigmaNt)*id(v)
-trans(SigmaN)*idt(u)
+gamma*trans(idt(u))*id(v)/hFace() );

B.5 Stabilisation techniques


B.5.1 Convection dominated flows
Consider this type of problem

− ∆u + c · ∇u + γu = f, ∇·c=0 (B.19)

Introduce Pe = |c|h
 the Péclet number. The dominating convection occurs when, on at least some cells,
Pe >> 1. We talk about singularly (i.e.  << h) perturbed flows.
Without doing anything wiggles occur. There are remedies so called Stabilisation Methods, here some
some examples:

• Artificial diffusion (streamline diffusion) (SDFEM)

• Galerkin Least Squares method (GaLS)

• Streamline Upwind Petrov Galerkin (SUPG)

• Continuous Interior Penalty methods (CIP)

B.5.2 The CIP methods


Add the term
X Z
γ h2F |c · n| [∇u][∇v] (B.20)
F ∈Γint F

89
Domain decomposition methods

where Γint is the set of internal faces where the Pe >> 1 (typically it is applied to all internal faces) and

[∇u] = ∇u · n|1 + ∇u · n|2 (B.21)

is the jump of ∇u(scalar valued) across the face. In the case of scalar valued functions

[u] = un|1 + un|2 (B.22)

Remark 14 (Choice for γ) γ can be taken in the range [1e − 2; 1e − 1]. A typical value is 2.5e − 2.

// define the stabilisation coefficient expression


AUTO( stab_coeff , (γβ abs(trans(N())*idv(beta)))*
vf::pow(hFace(),2.0));
// assemble the stabilisation operator
form2( Xh, Xh, M ) +=
integrate(
// internal faces of the mesh
internalfaces(Xh->mesh()),
// integration method
_Q<OrderOfPolynomialToBeIntegratedExactely>,
// stabilisation term
stab_coeff*(trans(jumpt(gradt(u)))*jump(grad(v))));

B.6 Interpolation
In order to interpolate a function defined on one domain to another domain, one can use the interpolate
function. The basis function of the image space must be of Lagrange type.
typedef bases<Lagrange<Order, Vectorial> > basis_type; // velocity
typedef FunctionSpace<mesh_type, basis_type, value_type> space_type;
// ...
space_ptrtype Xh = space_type::New( mesh1 );
element_type u( Xh, "u" );
space_ptrtype Yh = space_type::New( mesh2 );
element_type v( Yh, "v" );
// interpolate u on mesh2 and store the result in v
interpolate( Yh, u, v );

90
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

APPENDIX C

GNU Free Documentation License

GNU Free Documentation License Version 1.2, November 2002


Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document,
but changing it is not allowed.

Preamble
The purpose of this License is to make a manual, textbook, or other functional and useful document "free"
in the sense of freedom: to assure everyone the effective 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 modifications
made by others.
This License is a kind of "copyleft", which means that derivative works of the document must them-
selves 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.

Applicability and definitions


This License applies to any manual or other work, in any medium, that contains a notice placed by the
copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-
wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The
"Document", below, refers to any such manual or work. Any member of the public is a licensee, and is
addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring
permission under copyright law.
A "Modified Version" of the Document means any work containing the Document or a portion of it,
either copied verbatim, or with modifications and/or translated into another language.
A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclu-
sively with the relationship of the publishers or authors of the Document to the Document’s overall subject

91
Domain decomposition methods

(or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, 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 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. If a section does
not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document
may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there
are none.
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 Front-Cover Text may be
at most 5 words, and a Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose
specification is available to the general public, that is suitable for revising the document 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
file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent
modification by readers is not Transparent. An image format is not Transparent if used for any substantial
amount of text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo in-
put format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming
simple HTML, PostScript or PDF designed for human modification. Examples of transparent image for-
mats include PNG, XCF and JPG. Opaque formats include 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, PostScript or PDF produced by some word proces-
sors 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
work’s title, preceding the beginning of the body of the text.
A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ
or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands
for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorse-
ments", or "History".) To "Preserve the Title" of such a section when you modify the Document means that
it remains a section "Entitled XYZ" according to this definition.
The Document may include Warranty Disclaimers next to the notice which states that this License
applies to the Document. These Warranty Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers
may have is void and has no effect on the meaning of this License.

Verbatim copying
You may copy and distribute the Document in any medium, either commercially or noncommercially,
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 whatsoever 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 compensation 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.

92
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

Copying in quantity
If you publish printed copies (or copies in media that commonly have printed covers) of the Document,
numbering more than 100, and the Document’s 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 fit legibly, you should put the first ones listed
(as many as fit 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 either
include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque
copy a computer-network location from which the general network-using public has access to download
using public-standard network protocols a complete Transparent copy of the Document, free of added
material. 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.

Modifications
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3
above, provided that you release the Modified Version under precisely this License, with the Modified Ver-
sion filling the role of the Document, thus licensing distribution and modification of the Modified Version
to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

1. 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.

2. List on the Title Page, as authors, one or more persons or entities responsible for authorship of
the modifications in the Modified Version, together with at least five of the principal authors of the
Document (all of its principal authors, if it has fewer than five), unless they release you from this
requirement.

3. State on the Title page the name of the publisher of the Modified Version, as the publisher.

4. Preserve all the copyright notices of the Document.

5. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.

6. Include, immediately after the copyright notices, a license notice giving the public permission to use
the Modified Version under the terms of this License, in the form shown in the Addendum below.

7. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in
the Document’s license notice.

8. Include an unaltered copy of this License.

93
Domain decomposition methods

9. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title,
year, new authors, and publisher of the Modified 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 Modified Version as
stated in the previous sentence.

10. Preserve the network location, if any, given in the Document for public access to a Transparent 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.

11. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section,
and preserve in the section all the substance and tone of each of the contributor acknowledgements
and/or dedications given therein.

12. 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.

13. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified
Version.

14. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any
Invariant Section.

15. Preserve any Warranty Disclaimers.

If the Modified 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 Modified
Version’s 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 Modified Version by various parties–for example, statements of peer review or that the text has been
approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five 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 Modified 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 Modified Version.

Combining documents
You may combine the Document with other documents released under this License, under the terms defined
in section 4 above for modified versions, provided that you include in the combination all of the Invari-
ant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your
combined work in its license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and multiple identical Invariant Sec-
tions may be replaced with a single copy. If there are multiple Invariant Sections with the same name but
different 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.

94
Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme

In the combination, you must combine any sections Entitled "History" in the various original docu-
ments, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledge-
ments", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements".

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 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.

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, is called an "aggregate" if the copyright resulting
from the compilation is not used to limit the legal rights of the compilation’s users beyond what the indi-
vidual works permit. When the Document is included in an aggregate, this License does not apply to the
other works in the aggregate which 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 half of the entire aggregate, the Document’s Cover Texts may be placed on covers
that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is
in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.

Translation
Translation is considered a kind of modification, so you may distribute translations of the Document 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 translation of this License, and all the
license notices in the Document, and any Warranty Disclaimers, provided that you also include the original
English version of this License and the original versions of those notices and disclaimers. In case of a
disagreement between the translation and the original version of this License or a notice or disclaimer, the
original version will prevail.
If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the require-
ment (section 4) to Preserve its Title (section 1) will typically require changing the actual title.

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.

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 differ in detail

95
Domain decomposition methods

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 specifies 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 specified 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.

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 docu-
ment under the terms of the GNU Free Documentation License, Version 1.2 or any later version published
by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts."
line with this:
with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and
with the Back-Cover Texts being LIST.
If you have Invariant Sections without Cover Texts, or some other combination of the three, merge
those two alternatives to suit the situation.
If your document contains nontrivial examples of program code, we recommend releasing these exam-
ples in parallel under your choice of free software license, such as the GNU General Public License, to
permit their use in free software.

96
INDEX Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme 97

Index

Boost
Parameter, 84
boost
shared_ptr, 31

Class
Backend, 31
cmake, 18

Environment, 23

Libraries
PETSc, 23
Trilinos, 23

PETSc, 23

Trilinos, 23
98 Domain decomposition methods INDEX
BIBLIOGRAPHY Abdoulaye Samake, Vincent Chabannes, Christophe Prud’homme 99

Bibliography

[1] Wikipedia. http://fr.wikipedia.org.


[2] Vincent Chabannes, Gonçalo Pena, and Christophe Prud’Homme. High order fluid structure interac-
tion in 2D and 3D. Application to blood flow in arteries. Submitted to Elsevier Journal of Computa-
tional and Applied Mathematics (JCAM), February 2012.
[3] Vincent Doyeux, Yann Guyot, Vincent Chabannes, Christophe Prud’Homme, and Mourad Ismail.
Simulation of two-fluid flows using a finite element/level set method. Application to bubbles and
vesicle dynamics. Submitted to Elsevier Journal of Computational and Applied Mathematics (JCAM),
February 2012.
[4] J.-L. GUERMOND. Fluid Mechanics: Numerical Methods., pages 365–374. Oxford: Elsevier,
Ecyclopedia of Mathematical Physics, eds. J.-P. Françoise, G.L. Naber, and Tsou S.T. , (ISBN 978-0-
1251-2666-3), volume 2 edition, 2006.
[5] Incropera, DeWitt, Bergman, and Lavine. Fundamentals of heat and mass transfer. Wiley, 6 edition,
2007.
[6] Gonçalo Pena. Spectral element approximation of the incompressible Navier-Stokes equations in a
moving domain and applications. PhD thesis, Lausanne, 2009.
[7] Gonçalo Pena and Christophe Prud’homme. Construction of a high order fluid-structure interaction
solver. Journal of Computational and Applied Mathematics, In Press, Accepted Manuscript, 2009.
[8] Christophe Prud’homme. A domain specific embedded language in c++ for automatic differentiation,
projection, integration and variational formulations. Scientific Programming, 14(2):81–110, 2006.
http://iospress.metapress.com/link.asp?id=8xwd8r59hg1hmlcl.
[9] Christophe Prud’homme. Life: Overview of a unified c++ implementation of the finite and spectral
element methods in 1d, 2d and 3d. In Workshop On State-Of-The-Art In Scientific And Parallel
Computing, Lecture Notes in Computer Science, page 10. Springer-Verlag, 2006. Accepted.
[10] Christophe Prud’Homme, Vincent Chabannes, Vincent Doyeux, Mourad Ismail, Abdoulaye Samake,
and Gonçalo Pena. Feel++: A Computational Framework for Galerkin Methods and Advanced Nu-
merical Methods. Submitted to ESAIM Proc., January 2012.
[11] Benjamin Stamm. Stabilization strategies for discontinuous Galerkin methods. PhD thesis, Lausanne,
2008.
[12] Christoph Winkelmann. Interior penalty finite element approximation of Navier-Stokes equations and
application to free surface flows. PhD thesis, Lausanne, 2007.

You might also like