Rheolef-Refmanrheolef Reference Manual

Download as pdf or txt
Download as pdf or txt
You are on page 1of 216

Rheolef, the finite element system.

Reference manual
Version 6.5
22 April 2013

by Pierre Saramito

c 1996, 1998, 2001, 2002 by Pierre Saramito. All rights reserved.


Copyright
Permission is granted to make and distribute verbatim copies of this manual provided the
copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed
under the terms of a permission notice identical to this one.

Chapter 1: Abstract

1 Abstract
rheolef is a computer environment that serves as a convenient laboratory for computations involving finite element-like methods. It provides a set of unix commands and C++
algorithms and containers. This environment is currently under development.
Algorithms are related, from one hand to sparse matrix basic linear algebra, e.g. x+y,
A*x, A+B, A*B, ... From other hand, we focus development on preconditionned linear and
non-linear solver e.g. direct and iterative methods for A*x=b, iterative solvers for Stokes
and Bingham flows problems. Future developments will consider also viscoelastic flows
problems.
Containers covers first the classic graph data structure for sparse matrix formats and finite element meshes. An higher level of abstraction is provided by containers related to
approximate finite element spaces, discrete fields and bilinear forms. Current developments
concerns distributed sparse matrix. Future developments will consider also 3D anisotropic
adaptative mesh generation.
Please send all comments and bug reports by electronic mail to Pierre.Saramito@imag.fr.

Rheolef, the finite element system.

Chapter 2: Installing rheolef

2 Installing rheolef
(Source file: configure.ac)


./configure
make
make install

Successfull compilation and installation require the GNU make command.

2.1 Reading the documentation


Rheolef comes with three documentations:
an users guide with a set of complete examples
a reference manual for unix commands an C++ classes
the full browsable source code in html format
All these documentations are downloadable in various formats from the Rheolef home page.
These files are also locally installed during the make install stage. The users guide is
generated in pdf format:


evince http://ljk.imag.fr/membres/Pierre.Saramito/rheolef/rheolef.pdf

The reference manual is generated in html format:


firefox http://ljk.imag.fr/membres/Pierre.Saramito/rheolef/rheolef-refman.html
and you could add it to your bookmarks. Moreover, after performing make install, unix
manuals are available for commands and classes:
man field
man 2rheolef field
The browsable source code is generated in html format:
firefox http://ljk.imag.fr/membres/Pierre.Saramito/rheolef/source_html/

2.2 Using and alternative installation directory


The default install prefix is /usr/local. If you prefer an alternative directory, e.g.
HOME/sys, you should enter:
./configure --prefix=$HOME/sys
In that case, you have to add the folowing lines at the end of your .profile or
.bash_profile file:
export PATH="$HOME/sys/bin:$PATH"
export LD_LIBRARY_PATH="$HOME/sys/lib:$LD_LIBRARY_PATH"
export MANPATH="$HOME/sys/man:$MANPATH"
assuming you are using the sh or the bash unix interpreter. Conversely, if you are using
csh or tcsh, add at the bottom of your .cshrc file:

Rheolef, the finite element system.

set path = ($HOME/sys/bin $path)


setenv LD_LIBRARY_PATH "$HOME/sys/lib:$LD_LIBRARY_PATH"
setenv MANPATH "$HOME/sys/man:$MANPATH"
If you are unure about unix interpreter, get the SHELL value:
echo $SHELL
Then, you have to source the modified file, e.g.:
source ~/.cshrc
hpux users should replace LD_LIBRARY_PATH by SHLIB_PATH. If you are unure, get the
shared library path variable:
rheolef-config --shlibpath-var
Check also your installation by compiling a sample program with the installed library:
make installcheck
Since it is a common mistake, you can later, at each time, test your run-time environment
sanity with:
rheolef-config --check

2.3 Requiered libraries


All the required libraries have precompiled packages under Debian GNU/Linux and Ubuntu
systems. If you are running a system where these libraries are not available, please consult
the corresponding home pages and install instructions.
a) Rheolef widely uses the boost library, that provides usefull extensions of the c++ standard
template library. boost at http://www.boost.org .
b) The use of implicit numerical schemes leads to the resolution of large sparse linear
systems. Rheolef installation optionally requieres mumps as direct solver library. mumps is
available at http://graal.ens-lyon.fr/MUMPS .
c) Rheolef implements the characteristic method and interpolation from one mesh to another: these features leads to sophisticated algorithms and octree-type data structures. The
cgal library provide easy access to efficient and reliable geometric algorithms in the form
of a C++ library. cgal is available at http://www.cgal.org .

2.4 Highly recommended libraries


All the highly recommended libraries have precompiled packages under Debian GNU/Linux
and Ubuntu systems. With all these libraries, Rheolef with run optimally. Otherwise, it
will build and run also, but with some loss of performances.
a) Rheolef bases on mpi, the message passing interface standard. When no mpi libraries are
available, the distributed features are turned off.
b) Rheolef bases on scotch for distributed mesh partitioning. scotch is available at
http://www.labri.fr/perso/pelegrin/scotch . When the scotch library is not available, the distributed features are turned off.
c) Rheolef installation optionally uses trilinos/ifpack as a library of preconditioner used
for iterative solvers. trilinos is available at http://trilinos.sandia.gov . When
trilinos is not available, a less efficient builtin IC0 preconditioner is used.

Chapter 2: Installing rheolef

2.5 Run-time optional tools


Using Rheolef suggests the use of the following optional tools for pre- and post-processing
purpose:
gmsh
gnuplot
mayavi
paraview
None of these tools are required when building and installing Rheolef.

2.6 Build-time extra tools for rheolef developpers


These tools are required if you build from the development version (under CVS). Regenerating some source files, as initiated with the "bootstrap" command, requiers autotools autoconf, automake and libtool and also flex and bison. It requiers also ginac
for polynomial basis management. ginac is available at http://www.ginac.de . It requiers
finaly latex figure management tools to. Here is the apt-get commands to install these
tools under Debian GNU/Linux and Ubuntu:
apt-get install cvs autoconf automake libtool
apt-get install flex bison
apt-get install pkg-config libginac-dev
apt-get install ghostscript gnuplot xfig transfig imagemagick graphviz

2.7 Portability issues


Rheolef is based on STL and its extensions, the BOOST library. Therefore you need a
compiler that supports the ANSI C++ standards. STL and Rheolef especially depend heavily
on the template support of the compiler. Most recent c++ 2012 standard features are
recommanded but still optional: when available, it allows an elegant matrix concatenation
syntax via the std::initializer_list class.
Current distributed version of Rheolef has been heavily tested with GNU C++ and INTEL
C++ on debian, ubuntu and suse GNU/Linux systems for various 32 and 64 bits architectures, up to 100 distributed memories and processes.
The GNU C++ compiler is a free software available at http://www.gnu.org. The Intel C++
compiler is a privative software.
Older 5.x versions was tested also on the KAI C++ compiler (KCC-3.2b) and the CRAY
C++ compiler (CC-3.0.2.0) on the following operating systems:
mac os x (i386-apple-darwin9.8.0), using GNU C++
sun solaris 2.8, ultrasparc, using GNU C++
compacq OSF1 alpha (V5.1, V4.0), using Compacq C++
aix 4.1 ibm sp2, multiprocessor based on rs6000
cray unicos t3e, multiprocessor based on 64 bits dec alpha
cray unicos c94
hpux 9.05 and 10.20, hppa
sgi irix 6.3, mips
sun solaris 2.5.1, sparc

Rheolef, the finite element system.

The KAI C++ is available at http://www.kai.com. The CRAY C++ is available on CRAY
platforms. Nevertheless, the current version has no more been tested on these compilers
and systems.
If the required libraries are located in a non-standard directory, please use the configure
options:
./configure --help
and also consider the CXX, CXXFLAGS and LIBS variables, as in the following more
complex configure command:
CXX=icpc CXXFLAGS=-I/usr/local/include LIBS="-L/usr/local/lib -lz" ./configure
Finaly, if troubles still persist after the configure step, you can also edit directly the config/config.mk and config/config.h files. In these cases please also post to the mailling list
rheolef@grenet.fr any portability problem.
If you are running a another compiler and operating system combination, please run the
non-regression test suite:


make check

and reports us the result. If all is ok, please, send us a mail, and we will add your configuration to the list, and else we will try to circumvent the problem.
--enable-optim
Turns compile-time optimization to maximum available. Include architecturedependent compilation (e.g. on intel, executable are less portable accross intel
variants). Default is on.
--with-bigfloat=digits10
Turn on Bruno Haibles cln arbitrary precision float library with digits10 precision,
See http://clisp.cons.org/~haible/packages-cln.html. Default is off.
The digits10 value is optional and default digits10 value is 60. This feature
is still under development.
--with-cln=dir cln
Set the home directory for the cln library. Default dir cln is /usr/local/math.
--with-doubledouble
Uses doubledouble class as the default Rheolef Float type. This option is
usefull for a quadruple-like precision on machines where this feature is not or
incorrectly available. Default is off.
--enable-debian-packaging=debian packaging
Generate files the debian way by respecting the Debian Policy Manual.
--with-boost-incdir=incdir boost
--with-boost-libdir=libdir boost
Specifies the boost library. This library is required by rheolef.
--enable-debug
Produce a c++ -g like code.

Chapter 2: Installing rheolef

--enable-dmalloc
With debugging, also uses dynamic allocation runtime checking with dmalloc
when available.
--enable-old-code
Turns on/off the old code branch (before distributed computation features).
Default is off.
--enable-mpi
Turns on/off the distributed computation features. Default is on when distributed is on. This feature is currently in development. When on, configure
try to detect either the scotch or the parmetis libraries.
--with-scotch-incdir=incdir scotch
--with-scotch-libdir=libdir scotch
--with-scotch-libs=libs scotch
Turns on/off the scotch distributed mesh partitioner. Check in libdir scotch
for libptscotchparmetis.so, libptscotch.so and libptscotcherrexit.so
or corresponding .a libraries. Default is to auto-detect when mpi is available.
--with-parmetis-incdir=incdir parmetis
--with-parmetis-libdir=libdir parmetis
Turns on/off the parmetis distributed mesh partitioner. Check in libdir parmetis for libparmetis.so, libparmetis.a and also libmetis.a libmetis.so.
Default is to autodetect when mpi is available and scotch unavailable.
--with-blas-libdidr=rheo libdir blas
--with-blas-libs=rheo libs blas
Turns on/off the blas libraries. Check in rheo libs blas for libblas.so, or the
corresponding .a libraries. Default is to auto-detect. This librariy is required
for the pastix library.
--with-scalapack-libdidr=rheo libdir scalapack
--with-scalapack-libs=rheo libs scalapack
Turns on/off the scalapack libraries. Check in rheo libs scalapack for libscalapack.so,
or the corresponding .a libraries. Default is to auto-detect. This librariy is
required for the pastix library.
--with-mumps-incdir=incdir mumps
--with-mumps-libdir=libdir mumps
--with-mumps-libs=libs mumps
Turns on/off the mumps distributed solver. Check in libdir mumps for libmumps.so,
or the corresponding .a libraries. Default is to auto-detect when mpi is available.
--with-trilinos
--with-trilinos=libdir trilinos
Turns on/off the trilinos distributed preconditioner library. Check in libdir trilinos for libtrilinos_ifpack.so, or the corresponding .a libraries. Default is to auto-detect when mpi is available.

Rheolef, the finite element system.

--with-pastix
--with-pastix=libdir pastix
Turns on/off the pastix distributed solver. Check in libdir pastix for libpastix.so,
or the corresponding .a libraries. Default is to auto-detect when mpi is available.

--with-umfpack-incdir=incdir umfpack
--with-umfpack-libdir=libdir umfpack
--with-umfpack-libs=libs umfpack
Turns on/off the umfpack version 4.3 multifrontal direct solver. Default incdir umfpack is libdir umfpack. Check in libdir umfpack for libumfpack.so or
libumfpack.a and for header incdir umfpack/umfpack.h or incdir umfpack/umfpack/umfpack.
When this library is not available, the direct solver bases upon a traditionnal skyline Choleski factorisation combined with a reverse Cuthill-Mc Kee
reordering.
--with-taucs-ldadd=taucs ldadd
--with-taucs-incdir=taucs incdir
Turns on/off the taucs version 2.0 out-of-core sparse direct solver. When this
library is not available, the configure script check for the spooles multifrontal
(see below).
--with-spooles-libdir=libdir spooles
--with-spooles-incdir=incdir spooles
Turns on/off the spooles version 2.2 multifrontal direct solver. Default incdir spooles is libdir spooles. Check in libdir spooles for libspooles.so,
libspooles.a or spooles.a and for header incdir spooles/FrontMtx.h. When
this library is not available, the direct solver bases upon a traditionnal skyline
Choleski factorisation combined with a reverse Cuthill-Mc Kee reordering.
--with-cgal-incdir=incdir cgal
--with-cgal-libdir=libdir cgal
Turns on/off the cgal distributed solver. Check in libdir cgal for libcgal.so,
or the corresponding .a libraries. Default is to auto-detect when mpi is available. Generic or hardware-dependant optimization

2.8 Future configure options


These options will be implemented in the future:
--with-long-double
Defines long double as the default Rheolef Float type. Default is off and
defines double as Float type. Warning: most of architectures does not provides
mathematical library in long double, e.g. sqrt((long double)2) returns only
double precision result on Sun architectures, despites it uses a double memory
space. Thus use --with-doubledouble instead.
rpath issue for debian package: seems to be buggy with DESTDIR!=""

Chapter 2: Installing rheolef

2.9 The directory structure


config

portability related files and documentation extractors

util

a collection of useful C++ classes and functions for smart pointers, handling files
and directories, using strings, timing.

skit

sparse matrix library, linear solvers.

nfem

finite element library, mesh, spaces and forms.

doc

reference manual, users guide and examples.

10

Rheolef, the finite element system.

Chapter 3: Reporting Bugs

11

3 Reporting Bugs
This software is still under development. Please, run the make check non-regression tests.
Send comments and bug repports to Pierre.Saramito@imag.fr. Include the version number, which you can find at the top of this document. Also include in your message the
input and the output that the program produced and some comments on the output you
expected.

12

Rheolef, the finite element system.

Chapter 4: Commands

13

4 Commands
4.1 branch handle a family of fields
(Source file: nfem/pbin/branch.cc)

Synopsis
branch [options] filename

Example
Generates vtk file colection for visualization with paraview:
branch output.branch -paraview

Description
Read and output a branch of finite element fields from file, in field text file format.

Input file specification


-Idir

add dir to the RHEOPATH search path. See also Section 5.9 [geo class], page 55
for RHEOPATH mechanism.

filename

specifies the name of the file containing the input field.

read field on standard input instead on a file.

-ndigit int
Number of digits used to print floating point values when using the -geo
option. Default depends upon the machine precision associated to the Float
type.

Inquire
-toc

print the table of contents (toc) to standard output and exit.

Output and render specification


-extract int
Extract the i-th record in the file. The output is a field or multi-field file format.
-branch

Output on stdout in .branch format. This is the default.

-paraview
Generate a collection of vtk files for using paraview.
-vtk

Generate a single vtk file with numbered fields.

-gnuplot

Run 1d animation using gnuplot.

-plotmtv

This driver is unsupported for animations.

14

Rheolef, the finite element system.

Other options
-umin float
-umax float
set the solution range for the gnuplot driver. By default this range is computed
from the first field of the branch, and this could be problematic when this field
is initialy zero.
-topography filename[.field[.gz]]
performs a tridimensionnal elevation view based on the topographic data.
-proj

performs a P1 projection on the fly. This option is useful when rendering P0


data while vtk render requieres P1 description.

-elevation
For two dimensional field, represent values as elevation in the third dimension.
This is the default.
-noelevation
Prevent from the elevation representation.
-scale float
applies a multiplicative factor to the field. This is useful e.g. in conjonction
with the elevation option. The default value is 1.
-verbose

print messages related to graphic files created and command system calls (this
is the default).

-noverbose
does not print previous messages.
-clean

clear temporary graphic files (this is the default).

-noclean

does not clear temporary graphic files.

-execute

execute graphic command (this is the default).

-noexecute
does not execute graphic command. Generates only graphic files. This is usefull
in conjuction with the -noclean command.

Branch file format


The .branch file format bases on the .field one:
EXAMPLE
GENERAL FORM
#!branch
branch
1 1 11
time u
#time 3.14
#u
field

#!branch
branch
<version> <nfield=1> <nvalue=N>
<key> <field name>
#<key> <key value 1>
#<field name>
<field 1>

Chapter 4: Commands

15

.....

....

.....
#time 6.28
#u
field
.....

....
#<key> <key value N>
#<field name>
<field N>
....

The key name is here time, but could be any string (without spaces). The previous example
contains one field at each time step. Labels appears all along the file to facilitate direct
jumps and field and step skips.
The format supports several fields, such as (t,u(t),p(t)), where u could be a multi-component
(e.g. a vector) field:
#!branch
branch
1 2 11
time u p
#time 3.14
#u
mfield
1 2
#u0
field
...
#u1
field
...
#p
#time 6.28
...

4.2 field plot a field


(Source file: nfem/pbin/field.cc)

Synopsis
field options filename[.field[.gz]]

Description
Read and output a finite element field from file.

16

Rheolef, the finite element system.

Example
field square.field
field square.field -bw
field box.field

Input file specification


filename

specifies the name of the file containing the input field.

read field on standard input instead on a file.

-Idir
-I dir

Add dir to the rheolef file search path. This option is usefull e.g. when the mesh
.geo and the .field fikes are in different directories. This mechanism initializes a
search path given by the environment variable RHEOPATH. If the environment
variable RHEOPATH is not set, the default value is the current directory.

-catchmark label
Jump accross the file to the specifield label. Label start at the begining of a line,
preceded by a # mark (see see Section 6.15 [catchmark algorithm], page 127).

Output file format options


-field

output field on standard output stream in field text file format.

-gmsh

output field on standard output stream in gmsh text file format.

-gmsh-pos
output field on standard output stream in gmsh-pos text file format, suitable
for mesh adaptation purpose.
-bamg-bb

output field on standard output stream in bamg-bb text file format, suitable
for mesh adaptation purpose.

-image-format string
The argument is any valid image format, such as bitmap png, jpg, gif or
vectorial ps or pdf image file formats, and that could be handled by the corresponding render. The output file is e.g. basename.png when basename is the
name of the mesh, or can be set with the -name option.

Getting information
-min
-max

print the min (resp. max) value of the scalar field and then exit.

Render options
-gnuplot

use gnuplot tool. This is the default in one and two dimension.

-mayavi

use mayavi tool. This is the default for tridimensional geometries.

Chapter 4: Commands

17

Rendering options
-color
-gray
-black-and-white
-bw
Use (color/gray scale/black and white) rendering. Color rendering is the default.
-elevation
-noelevation
For two dimensional field, represent values as elevation in the third dimension.
The default is no evelation.
-scale float
applies a multiplicative factor to the field. This is useful e.g. in conjonction
with the elevation option. The default value is 1.
-stereo
-nostereo
Rendering mode suitable for red-blue anaglyph 3D stereoscopic glasses. This
option is only available with mayavi.
-fill

isoline intervals are filled with color. This is the default.

-nofill

draw isolines by using lines.

-cut
-nocut

Cut by a specified plane. The cutting plane is specified by its origin point and
normal vector. This option requires the mayavi code.

-origin float [float [float]]


set the origin of the cutting plane. Default is (0.5, 0.5, 0.5).
-normal float [float [float]]
set the normal of the cutting plane. Default is (1, 0, 0).
-iso [float]
do draw 3d isosurface. When the optional float is not provided, a median value
is used. This option requires the mayavi code.
-noiso

do not draw isosurface.

-n-iso int
For 2D visualizations, the isovalue table contains regularly spaced values from
fmin to fmax, the bounds of the field.
-proj

Convert all selected fields to Pk-continuous approximation by using a L2 projection.

-round [float]
Round the input up to the specifiexd precision. This option, combined with
-field, leads to a round filter. Usefull for non-regression test purpose, in order
to compare numerical results between files with a limited precision, since the
full double precision is machine-dependent.

18

Rheolef, the finite element system.

-n-iso-negative int
The isovalue table is splitted into negatives and positives values. Assume there
is n iso=15 isolines: if 4 is requested by this option, then, there will be 4
negatives isolines, regularly spaced from fmin to 0 and 11=15-4 positive isolines,
regularly spaced from 0 to fmax. This option is usefull when plotting e.g.
vorticity or stream functions, where the sign of the field is representative.
-subdivide int
When using a high order geometry, the number of points per edge used to draw
a curved element. Default value is the mesh order.
-deformation
Render vector-valued fields as deformed mesh using mayavi or gnuplot. This
is the default vector field representation.
-velocity
Render vector-valued fields as arrows using mayavi.

Component extraction and domain reduction


-comp int
-comp string
Extract the i-th component of a vector-valued field. For a tensor-valued field,
indexing components as "00", "01", "11"... is supported.
-domain name
Reduce the visualization to the specified domain.

Others options
-verbose

print messages related to graphic files created and command system calls (this
is the default).

-noverbose
does not print previous messages.
-clean

clear temporary graphic files (this is the default).

-noclean

does not clear temporary graphic files.

-execute

execute graphic command (this is the default).

-noexecute
does not execute graphic command. Generates only graphic files. This is usefull
in conjuction with the -noclean command.

Field file format


It contains a header and a list values at degrees of freedom. The header contains the field
keyword followed by a line containing a format version number (presently 1), the number of
degrees of freedom (i.e. the number of values listed), the mesh file name without the .geo
extension the approximation (e.g. P1, P2, etc), and finaly the list of values: A sample

Chapter 4: Commands

19

field file (compatible with the sample mesh example presented in command manual; see
Section 4.3 [geo command], page 19) writes:
field
1 4
square
P1
0.0
1.0
2.0
3.0

Examples
field cube.field -cut -normal 0 1 0 -origin 0.5 0.5 0.5 -vtk
This command send to vtk the cutted 2d plane of the 3d field.
field cube.field -cut -normal 0 1 0 -origin 0.5 0.5 0.5 -text > cube-cut.field
This command generates the cutted 2d field and its associated mesh.
field cube.field -iso 0.5 -plotmtv
This command draws the isosurface.
field cube.field -iso 0.5 -text > isosurf.geo
This command generates the isosurface as a 3d surface mesh in .geo format. This is
suitable for others treatments.

Input file format options


TODO

File format conversions


TODO

Getting information
TODO

4.3 geo - plot a finite element mesh


(Source file: nfem/pbin/geo.cc)

Synopsis
geo options mesh[.geo[.gz]]

20

Rheolef, the finite element system.

Description
Plot or upgrade a finite element mesh.

Examples
Plot a mesh:
geo square.geo
geo box.geo
geo box.geo -full
Plot a mesh into a file:
geo square.geo -image-format png
Convert from a old geo file format to the new one:
geo -upgrade - < square-old.geo > square.geo
See below for the geo file format scpecification. The old file format does not contains
edges and faces connectivity in 3d geometries, or edges connectivity in 2d geometries. The
converter add it automatically into the upgraded file format. Conversely, the old file format
is usefull when combined with a translator from another file format that do not provides
edges and faces connectivity.

Input file specification


filename

specifies the name of the file containing the input mesh. The ".geo" suffix
extension is assumed.

read mesh on standard input instead on a file.

-name

when mesh comes from standard input, the mesh name is not known and is set
to "output" by default. This option allows to change this default. Useful when
dealing with output formats (graphic, format conversion) that creates auxilliary
files, based on this name.

-Idir
-I dir

-check

Add dir to the rheolef file search path. This mechanism initializes a search
path given by the environment variable RHEOPATH. If the environment variable
RHEOPATH is not set, the default value is the current directory.
Check that element orientation is positive.

Input format options


-if format
-input-format format
load mesh in format file format, instead of plotting it. Supported output formats are: geo, bamg, vtk. When loading from a file, the corresponding suffix
extension is assumed.

Chapter 4: Commands

21

Render specification
-gnuplot

use gnuplot tool. This is the default.

-mayavi

use mayavi tool.

Render options
-[no]lattice
When using a high order geometry, the lattice inside any element appears.
Default is on;
-subdivide int
When using a high order geometry, the number of points per edge used to draw
a curved element. Default value is the mesh order.
-[no]full
All internal edges appears, for 3d meshes. Default is off;
-[no]fill
Fill mesh faces using light effects, when available.
-[no]stereo
Rendering mode suitable for red-blue anaglyph 3D stereoscopic glasses. Option
only available with mayavi.
-[no]cut

cut by plane and clip (with mayavi only).

Output file format options


-geo

output mesh on standard output stream in geo text file format, instead of
plotting it.

-upgrade

Convert from a old geo file format to the new one.

-gmsh

output mesh on standard output stream in gmsh text file format, instead of
plotting it.

-image-format string
The argument is any valid image format, such as bitmap png, jpg, gif or
vectorial ps or pdf image file formats, and that could be handled by the corresponding render. The output file is e.g. basename.png when basename is the
name of the mesh, or can be set with the -name option.

Others options
-add-boundary
check for a domain named "boundary"; If this domain does not exists, extract
the boundary of the geometry and append it to the domain list. This command
is usefull for mesh converted from generators, as bamg, that cannot have more
than one domain specification per boundary edge.

22

Rheolef, the finite element system.

-rz
-zr

Specifies the coordinate system. Usefull when converting from bamg or gmsh
format,.

-verbose

print messages related to graphic files created and command system calls (this
is the default).

-noverbose
does not print previous messages.
-clean

clear temporary graphic files (this is the default).

-noclean

does not clear temporary graphic files.

-execute

execute graphic command (this is the default).

-noexecute
does not execute graphic command. Generates only graphic files. This is usefull
in conjuction with the "-noclean" command.
-check
-dump

used for debug purpose.

Inquire options
-min-element-measure
-max-element-measure
print the smallest (resp. largest) element measure and then exit.

Geo file format


TODO

4.4 msh2geo - convert gmsh mesh in geo format


(Source file: nfem/pbin/msh2geo)

Synopsis
msh2geo [-zr|-rz] input[.msh] > output.geo

Description
Convert a gmsh .msh into .geo one. The output goes to standart output. See the gmsh
documentation for a detailed description of the .mshcad input file for gmsh.

Examples
gmsh -2 toto.mshcad -o toto.msh
msh2geo toto.msh > toto.geo
gmsh -2 -order 2 toto.mshcad -o toto2.msh
msh2geo toto2.msh > toto2.geo

Chapter 4: Commands

23

Coordinate system option


Most of rheolef codes are coordinate-system independant. The coordinate system is specified
in the geometry file .geo.
-zr
-rz

the 2d mesh is axisymmetric: zr (resp. rz) stands when the symmetry is related
to the first (resp. second) coordinate.

Notes
Pk triangle, when k>=5, may have internal nodes renumbered: from the

Gmsh documentation
The nodes of a curved element are numbered in the following order:
the
the
the
the

element principal vertices;


internal nodes for each edge;
internal nodes for each face;
volume internal nodes.

The numbering for face and volume internal nodes is recursive,


i.e., the numbering follows that of the nodes of an embedded face/volume.
The higher order nodes are assumed to be equispaced on the element.
In rheolef, internal triangle nodes are numbered from left to right and then from bottom to
top. The numbering differ for triangle when k >= 5. Thus, msh2geo fix the corresponding
internal nodes numbering during the conversion.
Pk tetrahedrons and hexaedrons in gmsh and rheolef has not the same edge-node order nd
orientation. E.g. for tetrahedrons, edges 13 and 23 should be swaped and reoriented as 32
and 31. Thus, msh2geo fix the corresponding internal nodes numbering.

Todo
Fix for P3-tetra: swap edges orientations for 3,4,5 and swap faces 1 and 2. Check P4(T)
for face orientation. Perform face visualisation with gnuplot face fill.
See also hexa edges orient and faces numbers and orient.
Check that node are numbered by vertex-node, then edge-node, then face(tri,qua)-node and
then volume(T,P,H)-node. Otherwise, renumber all nodes.
Support for high order >= 6 element ? not documented in gmsh, but gmsh supports it at
run

4.5 bamg2geo - convert bamg mesh in geo format


(Source file: nfem/sbin/bamg2geo)

24

Rheolef, the finite element system.

Synopsis
bamg2geo options input[.bamg] input[.dmn]
bamg2geo options input[.bamg] -Cl domlabel
bamg2geo options input[.bamg] {-dom domname}*

Description
Convert a bamg .bamg into .geo one. The output goes to standart output. The .dmn
file specifies the domain names, since bamg mesh generator uses numbers as domain labels.

Example
bamg -g toto.bamgcad -o toto.bamg
bamg2geo toto.bamg toto.dmn > toto.geo

Bamg cad file


This file describe the boundary of the mesh geometry. A basic example writes (See bamg
documentation for more);
MeshVersionFormatted
0
Dimension
2
Vertices
4
0 0
1
1 0
2
1 1
3
0 1
4
Edges
4
1 2
101
2 3
102
3 4
103
4 1
104
hVertices
0.1 0.1 0.1 0.1

Domain name file


This auxilliary .dmn file defines the boundary domain names as used by Rheolef, since
bamg uses numeric labels for domains.
EdgeDomainNames
4
bottom
right
top
left

Chapter 4: Commands

25

The domain name file can also specify additional vertices domain
EdgeDomainNames
4
bottom
right
top
left
VerticeDomainNames
4
left_bottom
right_bottom
right_top
left_top
Vertice domain names are usefull for some special boundary conditions.

Options
-upgrade
-noupgrade
Default is to output a version 2 .geo file format. See Section 4.3 [geo command], page 19. With the -noupgrade, a version 1 file format is assumed.
-cartesian
-rz
-zr
Specifies the coordinate system.
-dom dom1 ... -dom domN

4.6 mkgeo_ball build an unstructured mesh of an ellipsoid,


in 2d or 3d
(Source file: nfem/sbin/mkgeo_ball)

Synopsis
mkgeo_ball options [n]

Example
The following command build a triangle based 2d unstructured mesh of the unit ball
mkgeo_ball -t 10 > ball-10.geo
geo -mayavi ball-10.geo
or in one comand line:
mkgeo_ball -t 10 | geo -mayavi -

26

Rheolef, the finite element system.

Description
This command is usefull when testing programs on simple geometries. Invocation is similar
to mkgeo_grid (see Section 4.7 [mkgeo grid command], page 27, Section 4.8 [mkgeo ugrid
command], page 29). It calls gmsh as unstructured mesh generator. It avoid the preparation
of an input file for a mesh generator. The optional n argument is an integer that specifies
the subdivision in each direction. By default n=10. The mesh files goes on standard output.

Element type options


-t

2d mesh using triangles.

-q

2d mesh using quadrangles.

-tq

2d mesh using both triangles and quadrangles.

The mesh order


-order int
The polynomial pproximation mesh order, for the curved boundary, as defined
by gmsh. Defualt is order=1.

The geometry
The geometry can be ellipse/ellipsoid inscribted in the [a,b]x[c,d] rectangle or the [a,b]x[c,d]x[f,g]
parallelotope. By default a=c=f=-1 and b=d=g=1, thus, the unit balls are considered.
Only a surface mesh is generated: a curved line in 2d or a curved surface mesh
in 3d. In 3d, supports both -t and -q options.

-s
-a
-b
-c
-d
-f
-g

float
float
float
float
float
float

Boundary domains
The meshes defines a domain named boundary that groups all boundary sides.

Others options
-fix
-nofix

-clean

By default, internal face and volume node from gmsh are recomputed, since they
have incorrect coordinate that destroy the convergence properties of isoparametric high order elements (order >= 3). The -nofix option skip this correction:
this option is available for test purpose.
clear temporary files (this is the default).

Chapter 4: Commands

-noclean

27

does not clear temporary files.

-verbose
-noverbose
print intermediate commands and information messages.

4.7 mkgeo_grid build a strutured mesh of a parallelotope,


in 1d, 2d or 3d
(Source file: nfem/sbin/mkgeo_grid)

Synopsis
mkgeo_grid options [nx [ny [nz]]]

Example
The following command build a triangular based 2d 10x10 grid of the unit square:
mkgeo_grid -t 10 > square-10.geo
geo square-10.geo
or in one comand line:
mkgeo_grid -t 10 | geo -

Description
This command is usefull when testing programs on simple geometries. It avoid the preparation of an input file for a mesh generator. The optional nx, ny and nz arguments are integer
that specifies the subdivision in each direction. By default nx=10, ny=nx and nz=ny. The
mesh files goes on standard output.
The command supports all the possible element types: edges, triangles, rectangles, tetraedra, prisms and hexahedra.

Element type options


-e

1d mesh using edges.

-t

2d mesh using triangles.

-q

2d mesh using quadrangles (rectangles).

-T

3d mesh using tetraedra.

-P

3d mesh using prisms.

-H

3d mesh using hexahedra.

28

Rheolef, the finite element system.

The geometry
The geometry can be any [a,b] segment, [a,b]x[c,d] rectangle or [a,b]x[c,d]x[f,g] parallelotope.
By default a=c=f=0 and b=d=g=1, thus, the unit boxes are considered. For instance, the
following command meshes the [-2,2]x[-1.5, 1.5] rectangle:
mkgeo_grid -t 10 -a -2 -b 2 -c -1.5 -d 1.5 | geo -a
-b
-c
-d
-f
-g

float
float
float
float
float
float

Boundary domains
-sides
-nosides

The boundary sides are representd by domains: left, right, top, bottom,front
and back.

-boundary
-noboundary
This option defines a domain named boundary that groups all sides.
By default, both sides and the whole boundary are defined as domains:
mkgeo_grid -t 10 > square.geo
geo square.geo
mkgeo_grid -t 10 -nosides > square.geo
geo square.geo
mkgeo_grid -t 10 -noboundary > square.geo
geo square.geo
mkgeo_grid -t 10 -noboundary -nosides > square.geo
geo square.geo

Regions
-region
-noregion
The whole domain is splitted into two subdomains: east and west, This option
is used for testing computations with subdomains (e.g. transmission problem;
see the user manual).
mkgeo_grid -t 10 -region | geo -

Corners
-corner
-nocorner
The corners (four in 2D and eight in 3D) are defined as OD-domains. This
could be usefull for some special boundary conditions.

Chapter 4: Commands

29

mkgeo_grid -t 10 -corner | geo mkgeo_grid -T 5 -corner | geo -

Coordinate system option


Most of rheolef codes are coordinate-system independant. The coordinate system is specified
in the geometry file .geo.
-zr
-rz

the 2d mesh is axisymmetric: zr (resp. rz) stands when the symmetry is related
to the first (resp. second) coordinate.

File format option

4.8 mkgeo_ugrid build an unstructured mesh of a


parallelotope, in 1d, 2d or 3d
(Source file: nfem/sbin/mkgeo_ugrid)

Synopsis
mkgeo_ugrid options [n]

Example
The following command build a triangle based 2d unstructured mesh of the unit square:
mkgeo_ugrid -t 10 > square-10.geo
geo -mayavi square-10.geo
or in one comand line:
mkgeo_ugrid -t 10 | geo -mayavi -

Description
This command is usefull when testing programs on simple geometries. Invocation is similar
to mkgeo_grid (see Section 4.7 [mkgeo grid command], page 27). It calls gmsh as unstructured mesh generator. It avoid the preparation of an input file for a mesh generator. The
optional n argument is an integer that specifies the subdivision in each direction. By default
n=10. The mesh files goes on standard output.
The command supports all the possible element types: edges, triangles, rectangles, tetraedra, prisms and hexahedra. It supports also mixed 2D with triangles and quadrangles:
mkgeo_ugrid -tq 10 | geo -mayavi and mixed 3D with tetraedra, prisms and/or hjexaedra:
mkgeo_ugrid -TP 10 | geo -mayavi mkgeo_ugrid -PH 10 | geo -mayavi mkgeo_ugrid -TPH 10 | geo -mayavi -

30

Rheolef, the finite element system.

Element type options


-e

1d mesh using edges.

-t

2d mesh using triangles.

-q

2d mesh using quadrangles.

-tq

2d mesh using both triangles and quadrangles.

-T

3d mesh using tetraedra.

-P

3d mesh using prisms.

-H

3d mesh using hexahedra.

-TP
-PH
-TPH

3d mesh using a mixt between tetraedra, prisms and/or hexahedra.

The geometry
The geometry can be any [a,b] segment, [a,b]x[c,d] rectangle or [a,b]x[c,d]x[f,g] parallelotope.
By default a=c=f=0 and b=d=g=1, thus, the unit boxes are considered. For instance, the
following command meshes the [-2,2]x[-1.5, 1.5] rectangle:
mkgeo_ugrid -t 10 -a -2 -b 2 -c -1.5 -d 1.5 | geo -a
-b
-c
-d
-f
-g

float
float
float
float
float
float

Boundary domains
-sides
-nosides

The boundary sides are representd by domains: left, right, top, bottom,front
and back.

-boundary
-noboundary
This option defines a domain named boundary that groups all sides.
By default, both sides and the whole boundary are defined as domains:
mkgeo_ugrid -t 10 > square.geo
geo square.geo
mkgeo_ugrid -t 10 -nosides > square.geo
geo square.geo
mkgeo_ugrid -t 10 -noboundary > square.geo
geo square.geo
mkgeo_ugrid -t 10 -noboundary -nosides > square.geo
geo square.geo

Chapter 4: Commands

31

Regions
-region
-noregion
The whole domain is splitted into two subdomains: east and west, This option
is used for testing computations with subdomains (e.g. transmission problem;
see the user manual).
mkgeo_ugrid -t 10 -region | geo -

Corners
-corner
-nocorner
The corners (four in 2D and eight in 3D) are defined as OD-domains. This
could be usefull for some special boundary conditions.
mkgeo_ugrid -t 10 -corner | geo mkgeo_ugrid -T 5 -corner | geo -

The mesh order


-order int
The polynomial approximation mesh order, as defined by gmsh. This option
enable a possible curved boundary, when applying a suitable nonlinear transformation to the mesh. Defualt is order=1.

Others options
-clean

clear temporary files (this is the default).

-noclean

does not clear temporary files.

4.9 bamg - bidimensional anisotropic mesh generator


(Source file: util/bamg/bamg-man.txt)

Synopsis
bamg options -g input[.bamgcad] -o ouput[.bamg]

Example
bamg -g toto.bamgcad -o toto.bamg

32

Rheolef, the finite element system.

Outline of the commands


This software can
create

a mesh from a geometry

adapt

a mesh from a background mesh using a metric or solution file

do smoothing
to make quadrilaterals and to split internal edge with 2 boundary vertices in
an existing mesh (in this case the metric is use to change the definition of the
elements quality).
construct
just a metric file, if you have an other mesher
do the P1 interpolation
of the solution on another mesh:

Create a mesh from a geometry


input

file with -g filename (file type DB mesh).

output

file arguments -oxxxx filename where xxxx is the type of output file (see below
for more details).

smoothing, quad, utility and other parameters.


In addition, metric specication may be prescribed with the help of -M filename argument
(file type Metric). All the options are described below.

Adapt a mesh from a background mesh using a metric or solution


file
input

files -b filename where the suffixe of the file define the type of the file .amdba,
.am_fmt, .am, .ftq, .nopo and otherwise the file is a BD mesh file.

input

-M filename (file type Metric) or -MBB filename or -Mbb filename (solution


file type BB or bb).

metric

control parameters, -err val, -errg val,....

output

file arguments reqired

interpolation, smoothing, quad,


utility parameter, and other parameter
do smoothing, to make quadrilaterals: and to split internal edge with 2 boundary vertices
in an existing mesh (in this case the metric is use to change the definition of the elements
quality).
input

files -r filename(file type DB mesh).

-M filename
(file type Metric).
output

file -o filename (file type DB mesh).

Chapter 4: Commands

33

Some other parameter related to quadrilaterals


-thetaquad val:
to create quad with 2 triangles
-2:

to create the submesh with mesh size h = h/2

-2q:

to split all triangles in 3 quad. and to split all quad. in 4 quad.

-NbSmooth ival:
to change the number of smoothing iteration (3 by default if the metric eld is
set with arguments : -M or -Mbb, 0 otherwise.
...

Construct just a metric file


e.g. if you have an other mesher:
input

files -r filename (file type DB mesh).

--Mbb filename
or -MBB filename
+ all the arguments
of the metric construction
output

file -oM filename (file type Metric).

do the P1 interpolation of the solution on another mesh:


input

files -r filename (file type DB mesh).

--rBB filename
or -rbb filename
output

file -wBB filename or -wbb filename

Metric computatiob options


These options are relevant when computing a metric from a scalar field provided in a .bb
file. Notice that, when providing a tensor metric in the .bb file, the metric computation is
not performed and these options are not relevent.
-RelError
compute the metric with a relative error. This is the default.
-CutOff float
the cut-off value used for the relative error criteria. Default value is 1e-5.
-AbsError
compute the metric with a relative error

34

Rheolef, the finite element system.

4.10 rheolef-config get installation directories


(Source file: rheolef-config.in)

Example
The following command returns the rheolef libraries directory:
rheolef-config --libdir
An environment sanity check writes:
rheolef-config --check

Description
This command is usefull when linking executables with rheolef: libraries locations are required by the link editor. Such directories are defined while configuring rheolef, before
to compile and install see Chapter 2 [Installing], page 3. The rheolef-config command
returns these settings.
Note that rheolef-config could be used in Makefiles for the determination of linker flags.
Another usefull feature is the --check option. When rheolef is installed in a user directory, i.e. not as root, the sane run-time environment depends upon two environment
variables. The first one is the PATH: bkindir directory may be present in PATH. The second environment variable is related to shared libraries, and its name is system-dependent,
e.g. LD LIBRARY PATH on most platforms and SHLIB PATH on HP-UX. Its content
may contains bindir.
rheolef-config --shlibpath-var
Since it is a common mistake to have incorrect values for these variable, for novice users or
for adanced ones, especialy when dealing with several installed versions, the environment
sanity check writes:
rheolef-config --check
If there is mistakes, a hint is suggested to fix it and the return status is 1. Instead, the
return status is 0.

File options
--version
rheolef version.
--help

print option summary and exit.

--prefix

install architecture-independent files location.

--exec-prefix
architecture-dependent files location.
--includedir
include header directory.
--bindir

executables directory.

Chapter 4: Commands

--mandir

man documentation directory.

--libdir

object code libraries directory.

--datadir
--datarootdir
read-only architecture-independent data location.
--pkgdatadir
read-only architecture-independent data location; specific for package.
--includes
include compiler flags.
--libs

library compiler flags.

--shlibpath-var
the shared library path variable.
--library-interface-version
the library interface version.
--hardcode-libdir-flag-spec
flag to hardcode a libdir into a binary during linking.
--is-distributed
true or false: whether it is the distributed version.
--have-old-code
--have-new-code
true or false: whether it is the new/old code branch that is installed.

35

36

Rheolef, the finite element system.

Chapter 5: Classes

37

5 Classes
5.1 band - compute the band arround a level set
(Source file: nfem/plib/band.h)

Description
Given a function fh defined in a domain Lambda, compute the band of elements intersecting
the level set defined by {x in Lambda, fh(x) = 0}. This class is used for solving problems
defined on a surface described by a level set function (See Section 6.6 [level set algorithm],
page 112).

Accessors
Each side in the surface mesh, as returned by the level_set member function, is included
into an element of the band mesh, as returned by the band member function. Moreover, in
the distributed memory environment, this correspondance is on the same process, so local
indexes can be used for this correspondance: this is the sid_ie2bnd_ie member functions.

Band topology and domains


For the direct resolution of systems posed on the band, the mesh returned by the band()
provides some domains of vertices. The "zero" vertex domain lists all vertices xi such
that fh(xi)=0. The "isolated" vertex domain lists all vertices xi such that fh(xi)!=0
and xi is contained by only one element K and all vertices xj!=xi of K satifies fh(xj)=0.
Others vertices of the band, separated by the zero and isolated ones, are organizd by
connected components: the n_connex_component member function returns its number.
Corresponding vertex domains of the band are named "cc<i>" where <i> should be replaced
by any number between 0 and n_connex_component-1.

Implementation
template <class T, class M = rheo_default_memory_model>
class band_basic {
public:
typedef typename geo_basic<T,M>::size_type size_type;
// allocators:
band_basic();
band_basic(const field_basic<T,M>& fh,
const level_set_option_type& opt = level_set_option_type());
/// accessors:
const geo_basic<T,M>& band() const { return _band; }

38

Rheolef, the finite element system.

const geo_basic<T,M>& level_set() const { return _gamma; }


size_type sid_ie2bnd_ie (size_type sid_ie) const { return _sid_ie2bnd_ie [sid_ie];
size_type n_connected_component() const { return _ncc; }
// data:
protected:
geo_basic<T,M>
_gamma;
geo_basic<T,M>
_band;
array<size_type,M> _sid_ie2bnd_ie;
size_type
_ncc;
};
typedef band_basic<Float> band;

5.2 branch - a parameter-dependent sequence of field


(Source file: nfem/plib/branch.h)

Description
Stores a field sequence together with its associated parameter value: a branch variable
represents a pair (t,uh(t)) for a specific value of the parameter t. Applications concern
time-dependent problems and continuation methods.
This class is convenient for file inputs/outputs and building graphical animations.

Examples
Coming soon...

Limitations
This class is under development.
The branch class store pointers on field class without reference counting. Thus, branch
automatic variables cannot be returned by functions. branch variable are limited to local
variables.

Implementation

template <class T, class M = rheo_default_memory_model>


class branch_basic : public std::vector<std::pair<std::string,field_basic<T,M> > > {
public :
// typedefs:
typedef std::vector<std::pair<std::string,field_basic<T,M> > >
typedef typename base::size_type
// allocators:
branch_basic ();

base;
size_type;

Chapter 5: Classes

39

branch_basic (const std::string& parameter_name, const std::string& u0);


branch_basic (const std::string& parameter_name, const std::string& u0, const std:
~branch_basic();
// accessors:
const T& parameter () const;
const std::string& parameter_name () const;
size_type
n_value () const;
size_type
n_field () const;
// modifiers:
void set_parameter_name (const std::string& name);
void set_parameter (const T& value);
void set_range (const std::pair<T,T>& u_range);
// input/output:
// get/set current value
__obranch<T,M> operator()
__obranch<T,M> operator()

(const T& t, const field_basic<T,M>& u0);


(const T& t, const field_basic<T,M>& u0, const field_ba

__iobranch<T,M> operator() (T& t, field_basic<T,M>& u0);


__iobranch<T,M> operator() (T& t, field_basic<T,M>& u0, field_basic<T,M>& u1);
__branch_header<T,M>
header ();
__const_branch_header<T,M>
header () const;
__const_branch_finalize<T,M> finalize () const;

5.3 characteristic - the Lagrange-Galerkin method


implemented
(Source file: nfem/plib/characteristic.h)

Synopsys
The class characteristic implements the Lagrange-Galerkin method: It is the extension of
the method of characteristic from the finite difference to the finite element context.

Example
Consider the bilinear form lh defined by
/
|
lh(x) = | uh(x+dh(x)) v(x) dx
|
/ Omega

40

Rheolef, the finite element system.

where dh is a deformation vector field. The characteristic is defined by X(x)=x+dh(x) and


the previous integral writes equivalently:
/
|
lh(x) = | uh(X(x)) v(x) dx
|
/ Omega
For instance, in Lagrange-Galerkin methods, the deformation field dh(x)=-dt*uh(x) where
uh is the advection field and dt a time step. The following code implements the computation
of lh:
field dh = ...;
field uh = ...;
characteristic X (dh);
test v (Xh);
field lh = integrate (compose(uh, X)*v, qopt);
The Gauss-Lobatto quadrature formule is recommended for Lagrange-Galerkin methods.
The order equal to the polynomial order of Xh (order 1: trapeze, order 2: simpson, etc).
Recall that this choice of quadrature formulae guaranties inconditional stability at any
polynomial order. Alternative quadrature formulae or order can be used by using the
additional quadrature option argument to the integrate function see Section 6.4 [integrate
algorithm], page 110.

Implementation
template<class T, class M = rheo_default_memory_model>
class characteristic_basic : public smart_pointer<characteristic_rep<T,M> > {
public:
typedef characteristic_rep<T,M> rep;
typedef smart_pointer<rep>
base;
// allocator:
characteristic_basic(const field_basic<T,M>& dh);
// accesors:
const field_basic<T,M>& get_displacement() const;
const characteristic_on_quadrature<T,M>&
get_pre_computed (
const space_basic<T,M>&
Xh,
const field_basic<T,M>&
dh,
const quadrature_option_type& qopt) const;
};

Chapter 5: Classes

41

typedef characteristic_basic<Float> characteristic;

5.4 field - piecewise polynomial finite element field


(Source file: nfem/plib/field.h)

Description
Store degrees of freedom associated to a mesh and a piecewise polynomial approximation,
with respect to the numbering defined by the underlying Section 5.10 [space class], page 63.
This class contains two vectors, namely unknown and blocked degrees of freedoms, and the
associated finite element space. Blocked and unknown degrees of freedom can be set by
using domain name indexation:
geo omega ("circle");
space Xh (omega, "P1");
Xh.block ("boundary");
field uh (Xh);
uh ["boundary"] = 0;

Interpolation
Interpolation of a function u in a field uh with respect to the interpolation writes:
Float u (const point& x) { return x[0]*x[1]; }
...
field uh = interpolate (Xh, u);

Linear algebra
Linear algebra, such as uh+vh, uh-vh and lambda*uh + mu*vh, where lambda and mu are of
type Float, are supported. The duality product between two fields lh and vh writes simply
dual(lh,vh): for discrete fields, it corresponds to a simple Euclidian dot product in IR^n.
The application of a bilinear form (see Section 5.6 [form class], page 48) writes m(uh,vh)
and is equivalent to dual(m*uh,vh).

Non-linear algebra
Non-linear operations, such as sqrt(uh) or 1/uh are also available. Notice that non-linear
operations do not returns in general picewise polynomials: the value returned by sqrt(uh)
may be filtered by interpolate,
field vh = interpolate (Xh, sqrt(uh));
the Lagrange interpolant, to becomes a piecewise polynomial: All standard unary and
binary math functions abs, cos, sin... are available on fields. Also sqr(uh), the square
of a field, and min(uh,vh), max(uh,vh) are provided. Binary functions can be used also
with a scalar, as in

42

Rheolef, the finite element system.

field vh = interpolate (Xh, max (abs(uh), 0));


field wh = interpolate (Xh, pow (abs(uh), 1./3));
For applying a user-provided function to a field, use the compose function:
field vh = interpolate(Xh, compose(f, uh));
field wh = interpolate(Xh, compose(f, uh, vh));
The composition supports also general unary and binary class-functions. Also, the multiplication uh*vh and the division uh/vh returns a result that is not in the same discrete finite
element space: its result may be filtered by the interpolate operator:
field wh = interpolate(Xh, uh*vh);
Any function or class function can be used in nonlinear expressions: the function is interpolated in the specified finite element space.
There is a special predefined class-function named normal that represents the outer unnit
normal vector on a boundary domain or surfacic mesh:
size_t k = omega.order();
string n_approx = "P" + itos(k-1) + "d";
space Nh (omega["boundary"], n_approx, "vector");
field nh = interpolate(Nh, normal());
The normal() function could appear in any nonlinear field expression: it is evaluated on the
fly, based on the current mesh. Notice that when using isoparametric elements, the normal
vector is no more constant along any face of the mesh. Also, on general curved domains,
the unit normal vector is discontinuous accross boundary element interfaces.

Access by domain
The restriction of a field to a geometric domain, says "boundary" writes uh["boundary"]:
it represents the trace of the field on the boundary:
space Xh (omega, "P1");
uh["boundary"] = 0;
Extraction of the trace as a field is also possible:
field wh = uh["boundary"];
The space associated to the trace writes wh.get_space() and is equivalent to space(omega["boundary"],
"P1"). See see Section 5.10 [space class], page 63.

Vector valued field


A vector-valued field contains several components, as:
space Xh (omega, "P2", "vector");
field uh (Xh);
field vh = uh[0] - uh[1];
field nh = norm (uh);
The norm function returns the euclidian norm of the vector-valuated field at each degree of
freedom: its result is a scalar field.

Chapter 5: Classes

43

Tensor valued field


A tensor-valued field can be constructed and used as:
space Th (omega, "P1d", "tensor");
field sigma_h (Xh);
field trace_h = sigma(0,0) + sigma_h(1,1);
field nh = norm (sigma_h);
The norm function returns the euclidian norm of the tensor-valuated field at each degree
of freedom: its result is a scalar field. Notice that, as tensor-valued fields are symmetric,
extra-diagonals are counted twice.

General multi-component interface


A general multi-component field writes:
space Th (omega, "P1d", "tensor");
space Vh (omega, "P2", "vector");
space Qh (omega, "P1");
space Xh = Th*Vh*Qh;
field xh (Xh);
field tau_h = xh[0]; // tensor-valued
field uh
= xh[1]; // vector-valued
field qh
= xh[2]; // scalar
Remark the hierarchical multi-component field structure: the first-component is tensorvalued and the second-one is vector-valued. There is no limitation upon the hierarchical
number of levels in use.
For any field xh, the string xh.valued() returns "scalar" for a scalar field and "vector"
for a vector-valued one. Other possible valued are "tensor" and "other". The xh.size()
returns the number of field components. When the field is scalar, it returns zero by
convention, and xh[0] is undefined. A vector-valued field has d components, where
d=omega.dimension(). A tensor-valued field has d*(d+1)/2 components, where d=omega.dimension().

Blocked and unblocked arrays


The field class contains two arrays of degrees-of-freedom (dof) associated respectively to
blocked and unknown dofs. Blocked dofs corresponds to Dirichlet boundary conditions, as
specified by space (See see Section 5.10 [space class], page 63). For simpliity, direct public
access to these array is allowed, as uh.b and uh.u: see see Section 5.25 [vec class], page 101.

Low-level degree-of-freedom access


The field class provides a STL-like container interface for accessing the degrees-of-freedom
(dof) of a finite element field uh. The number of dofs is uh.ndof() and any dof can be
accessed via uh.dof(idof). A non-local dof at the partition interface can be obtain via
uh.dis_dof(dis_idof) where dis_idof is the (global) distribued index assoiated to the
distribution uh.ownership().

44

Rheolef, the finite element system.

For performances, a STL-like iterator interface is available, with uh.begin_dof() and


uh.end_dof() returns iterators to the arrays of dofs on the current processor. See see
Section 5.17 [array class], page 79 for more about distributed arrays.
For convenience, uh.max(), uh.min() and uh.max_abs() retuns respectively the maximum,
minimum and maximum of the absolute value of the degrees of freedom.

File format
TODO

Implementation note
The field expression use the expression template technics in order to avoid temporaries when
evaluating complex expressions.

Implementation

template <class T, class M = rheo_default_memory_model>


class field_basic : public std::unary_function<point_basic<typename scalar_traits<T>
public :
// typedefs:

//

typedef typename std::size_t


typedef M
typedef T
typedef typename float_traits<T>::type
typedef undeterminated_basic<T>
typedef T
typedef space_constant::valued_type
typedef geo_basic <float_type,M>
typedef space_basic<float_type,M>
class iterator;
class const_iterator;

size_type;
memory_type;
scalar_type;
float_type;
value_type; // TODO
value_type; // TO_CLEAN
valued_type;
geo_type;
space_type;

// allocator/deallocator:
field_basic();
explicit field_basic (
const space_type& V,
const T& init_value = std::numeric_limits<T>::max());
void resize (
const space_type& V,
const T& init_value = std::numeric_limits<T>::max());
field_basic
field_basic<T, M>& operator=
field_basic

(const field_indirect<T,M>&);
(const field_indirect<T,M>&);
(const field_indirect_const<T,M>&);

Chapter 5: Classes

45

field_basic<T, M>& operator= (const


field_basic
(const
field_basic<T, M>& operator= (const
field_basic
(const
field_basic<T, M>& operator= (const
template <class Expr> field_basic
template <class Expr> field_basic<T,
field_basic<T, M>& operator= (const

field_indirect_const<T,M>&);
field_component<T,M>&);
field_component<T,M>&);
field_component_const<T,M>&);
field_component_const<T,M>&);
(const field_expr<Expr>&);
M>& operator= (const field_expr<Expr>&);
T&);

// initializer list (c++ 2011):

#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
field_basic (const std::initializer_list<field_concat_value<T,M> >& init_list);
field_basic<T,M>& operator= (const std::initializer_list<field_concat_value<T,M>
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
// accessors:
const space_type&
const geo_type&
std::string
std::string
valued_type
const std::string&

get_space()
get_geo()
stamp()
get_approx()
valued_tag()
valued()

const
const
const
const
const
const

{
{
{
{
{
{

return
return
return
return
return
return

_V; }
_V.get_geo(); }
_V.stamp(); }
_V.get_approx(); }
_V.valued_tag(); }
_V.valued(); }

// accessors & modifiers to unknown & blocked parts:


const vec<T,M>&
u() const { dis_dof_update_needed(); return _u; }
const vec<T,M>&
b() const { dis_dof_update_needed(); return _b; }
vec<T,M>& set_u()
{ return _u; }
vec<T,M>& set_b()
{ return _b; }
// accessors to extremas:
T
T
T
T

min() const;
max() const;
max_abs() const;
min_abs() const;

// accessors by domains:
field_indirect<T,M>
field_indirect_const<T,M>
field_indirect<T,M>
field_indirect_const<T,M>

operator[]
operator[]
operator[]
operator[]

(const geo_basic<T,M>& dom);


(const geo_basic<T,M>& dom) const;
(std::string dom_name);
(std::string dom_name) const;

// accessors by components:
size_type size() const { return _V.size(); }

46

Rheolef, the finite element system.

field_component<T,M>
field_component_const<T,M>
field_component<T,M>
field_component_const<T,M>

operator[]
operator[]
operator()
operator()

(size_type
(size_type
(size_type
(size_type

i_comp);
i_comp) const;
i_comp, size_type j_comp);
i_comp, size_type j_comp) const

// accessors by degrees-of-freedom (dof):


const distributor& ownership() const { return get_space().ownership(); }
const communicator& comm() const { return ownership().comm(); }
size_type
ndof() const { return ownership().size(); }
size_type dis_ndof() const { return ownership().dis_size(); }
T& dof (size_type idof);
const T& dof (size_type idof) const;
const T& dis_dof (size_type dis_idof) const;
iterator begin_dof();
iterator end_dof();
const_iterator begin_dof() const;
const_iterator end_dof() const;
// input/output:
idiststream& get (idiststream& ips);
odiststream& put (odiststream& ops) const;
odiststream& put_field (odiststream& ops) const;
// evaluate uh(x) where x is given locally as hat_x in K:
T dis_evaluate (const point_basic<T>& x, size_type i_comp = 0) const;
T operator()
(const point_basic<T>& x) const { return dis_evaluate (x,0); }
point_basic<T> dis_vector_evaluate (const point_basic<T>& x) const;
// internals:
public:

// evaluate uh(x) where x is given locally as hat_x in K:


// requiers to call field::dis_dof_upgrade() before.
T evaluate (const geo_element& K, const point_basic<T>& hat_xq, size_type i_comp
// propagate changed values shared at partition boundaries to others procs
void dis_dof_update() const;
template <class Expr>
void assembly_internal (
const geo_basic<T,M>&
const geo_basic<T,M>&
const band_basic<T,M>&
const Expr&
const quadrature_option_type&
bool

dom,
band,
gh,
expr,
qopt,
is_on_band);

Chapter 5: Classes

template <class Expr>


void assembly (
const geo_basic<T,M>&
const Expr&
const quadrature_option_type&
template <class Expr>
void assembly (
const band_basic<T,M>&
const Expr&
const quadrature_option_type&

47

domain,
expr,
qopt);

gh,
expr,
qopt);

protected:
void dis_dof_update_internal() const;
void dis_dof_update_needed() const;
// data:
space_type
_V;
vec<T,M>
_u;
vec<T,M>
_b;
mutable bool _dis_dof_update_needed;
};
template <class T, class M>
idiststream& operator >> (odiststream& ips, field_basic<T,M>& u);
template <class T, class M>
odiststream& operator << (odiststream& ops, const field_basic<T,M>& uh);
typedef field_basic<Float> field;
typedef field_basic<Float,sequential> field_sequential;

5.5 field_functor - a functor wrapper suitable for field


expressions
(Source file: nfem/plib/field_functor.h)

Description
A functor is a class-function, i.e. a class that defines the operator(). A variable f of a classfunction can be used as f(arg) and when its argument is of type point see Section 5.12
[point class], page 68, the function f interprets as a continuous field field. Thus, it can
be interpolated see Section 6.5 [interpolate algorithm], page 112 and it can be combined
within field expressions see Section 5.4 [field class], page 41 that appears in arguments of
see Section 6.4 [integrate algorithm], page 110.

Example
struct f : field_functor<f,Float> {
Float operator() (const point& x) const { return 1-norm(x); }
};

48

Rheolef, the finite element system.

// ...
geo omega ("square");
space Xh (omega, "P1");
field fh = interpolate (Xh, f);
test (Xh);
field lh = integrate (f*v);

Implementation note
The current implementation of a field_functor class bases on the curiously recurring
template pattern (CRTP) C++ idiom: the definition of the class f derives from field_
functor<f,Float> that depend itself upon f. So, be carrefull when using copy-paste, as
there is no checks if you write e.g. field_functor<g,Float> with another function g instead
of f.

Implementation

template <class Function, class Result>


struct field_functor
: std::unary_function<point_basic<float_traits<Result> >,Result> {
const Function& get_ref() const { return static_cast<const Function&>(*this); }
operator Function() const { return get_ref(); }
Result operator() (const point& x) const { return get_ref().operator()(x); }
};
#ifdef TODO
// transforme a function or a functor into a field_functor, suitable for expressions
template <class F, class R>
struct field_function_s : field_functor<field_function_s<F,R>, R> {
typedef typename float_traits<R>::type float_type;
R operator() (const point_basic<float_type>& x) const { return _f.operator()(x); }
field_function_s(F f) : _f(f) {}
F _f;
};
template <class F>
field_function_s<function<F>, typename F::result_type>
field_function (F f) {
typedef typename F::result_type R;
return field_function_s<function<F>,R>(function<F>(f));
}
#endif // TODO

5.6 form - representation of a finite element bilinear form


(Source file: nfem/plib/form.h)

Chapter 5: Classes

49

Description
The form class groups four sparse matrix, associated to a bilinear form on two finite element
spaces:
a: U*V
(u,v)

----> IR
|---> a(u,v)

The operator A associated to the bilinear form is defined by:


A: U
u

----> V
|---> A(u)

where u and v are fields (see Section 5.4 [field class], page 41), and A(u) is such that
a(u,v)=<A(u),v> for all u in U and v in V and where <.,.> denotes the duality product
between V and V. Since V is a finite dimensional spaces, the duality product is the euclidian
product in IR^dim(V).
Since both U and V are finite dimensional spaces, the linear operator can be represented by
a matrix. The form class is represented by four sparse matrix in csr format (see Section 5.19
[csr class], page 87), associated to unknown and blocked degrees of freedom of origin and
destination spaces (see Section 5.10 [space class], page 63).

Example
The operator A associated to a bilinear form a(.,.) by the relation (Au,v) = a(u,v) could
be applied by using a sample matrix notation A*u, as shown by the following code:
geo omega("square");
space V (omega,"P1");
form a (V,V,"grad_grad");
field uh = interpolate (fct, V);
field vh = a*uh;
cout << v;
The form-field vh=a*uh operation is equivalent to the following matrix-vector operations:
vh.set_u() = a.uu()*uh.u() + a.ub()*uh.b();
vh.set_b() = a.bu()*uh.u() + a.bb()*uh.b();

Algebra
Forms, as matrices (see Section 5.19 [csr class], page 87), support linear algebra: Adding or
substracting two forms writes a+b and a-b, respectively, and multiplying a form by a field
uh writes a*uh. Thus, any linear combination of forms is available.

Weighted form
A weighted form is a form with an extra weight function w(x), e.g.:

50

Rheolef, the finite element system.

/
|
a(uh,vh) = |
|
/ Omega

grad(uh).grad(vh) w(x) dx

In the present implementation, w can be any field, function or class-function or any nonlinear field expression (see Section 5.4 [field class], page 41). As the integration cannot
be performed exactly in general, a quadrature formula can be supplied. This feature is
extensively used when solving nonlinear problems.

Implementation
template<class T, class M>
class form_basic {
public :
// typedefs:
typedef
typedef
typedef
typedef
typedef

typename csr<T,M>::size_type
T
typename scalar_traits<T>::type
geo_basic<float_type,M>
space_basic<float_type,M>

size_type;
value_type;
float_type;
geo_type;
space_type;

// allocator/deallocator:
form_basic ();
form_basic (const form_basic<T,M>&);

// allocators from initializer list (c++ 2011):


#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
form_basic (const std::initializer_list<form_concat_value<T,M> >& init_list);
form_basic (const std::initializer_list<form_concat_line <T,M> >& init_list);
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
// accessors:
const space_type& get_first_space() const;
const space_type& get_second_space() const;
const geo_type&
get_geo() const;
const communicator& comm() const;
// linear algebra:
form_basic<T,M>
form_basic<T,M>

operator+
operator-

(const form_basic<T,M>& b) const;


(const form_basic<T,M>& b) const;

Chapter 5: Classes

51

form_basic<T,M> operator* (const form_basic<T,M>& b) const;


form_basic<T,M>& operator*= (const T& lambda);
field_basic<T,M> operator* (const field_basic<T,M>& xh) const;
field_basic<T,M> trans_mult (const field_basic<T,M>& yh) const;
float_type operator () (const field_basic<T,M>& uh, const field_basic<T,M>& vh)
// io:
odiststream& put (odiststream& ops, bool show_partition = true) const;
void dump (std::string name) const;
// accessors & modifiers to unknown & blocked parts:
const
const
const
const

csr<T,M>&
csr<T,M>&
csr<T,M>&
csr<T,M>&
csr<T,M>&
csr<T,M>&
csr<T,M>&
csr<T,M>&

// data
protected:
space_type
space_type
csr<T,M>
csr<T,M>
csr<T,M>
csr<T,M>

uu()
ub()
bu()
bb()
set_uu()
set_ub()
set_bu()
set_bb()

const
const
const
const

{
{
{
{
{
{
{
{

return
return
return
return
return
return
return
return

_uu;
_ub;
_bu;
_bb;
_uu;
_ub;
_bu;
_bb;

}
}
}
}
}
}
}
}

_X;
_Y;
_uu;
_ub;
_bu;
_bb;

// internals:
public:
// with vf expression arg
template <class Expr>
void assembly_internal (
const geo_basic<T,M>&
const geo_basic<T,M>&
const band_basic<T,M>&
const Expr&
const form_option_type&
bool
template <class Expr>
void assembly (
const geo_basic<T,M>&
const Expr&
const form_option_type&
template <class Expr>
void assembly (

dom,
band,
gh,
expr,
fopt,
is_on_band);

domain,
expr,
fopt);

52

Rheolef, the finite element system.

const band_basic<T,M>&
const Expr&
const form_option_type&

gh,
expr,
fopt);

// backward compat: named forms


form_basic (const space_type& X, const space_type& Y,
const std::string& name = "",
const quadrature_option_type& qopt = quadrature_option_type(quadrature_optio

form_basic (const space_type& X, const space_type& Y,


const std::string& name,
const field_basic<T,M>& weight,
const quadrature_option_type& qopt = quadrature_option_type(quadrature_optio

template<class Function>
form_basic (const space_type& X, const space_type& Y,
const std::string& name,
Function weight,
const quadrature_option_type& qopt = quadrature_option_type(quadrature_optio

form_basic (const space_type& X, const space_type& Y,


const std::string& name,
const geo_basic<T,M>& gamma,
const quadrature_option_type& qopt = quadrature_option_type(quadrature_optio

form_basic (const space_type& X, const space_type& Y,


const std::string& name,
const geo_basic<T,M>& gamma,
const field_basic<T,M>& weight,
const quadrature_option_type& qopt = quadrature_option_type(quadrature_optio

template<class Function>
form_basic (
const space_type& X,
const space_type& Y,
const std::string& name,
const geo_basic<T,M>& gamma,
Function weight,
const quadrature_option_type& qopt = quadrature_option_type(quadrature_optio
protected:
// backward compat: named forms (cont.)
template<class WeightFunction>
void form_init (
const std::string&
name,
bool
has_weight,
WeightFunction
weight,
const quadrature_option_type& qopt);
template<class WeightFunction>
void form_init_on_domain (

Chapter 5: Classes

53

const std::string&
name,
const geo_basic<T,M>&
gamma,
bool
has_weight,
WeightFunction
weight,
const geo_basic<T,M>&
w_omega, // the domain where the fct weig
const quadrature_option_type& qopt);
};
template<class T, class M> form_basic<T,M> trans (const form_basic<T,M>& a);
template<class T, class M> field_basic<T,M> diag (const form_basic<T,M>& a);
template<class T, class M> form_basic<T,M> diag (const field_basic<T,M>& dh);
typedef form_basic<Float,rheo_default_memory_model> form;

5.7 form_option_type - send options to the integrate function


(Source file: nfem/plib/form_option_type.h)

Description
This class is used to send options to the integrate function when building a form. It
allows to set the quadrature formulae that is used for numerical integration see Section 5.13
[quadrature option type class], page 72 and two boolean flags.

Flags
ignore_sys_coord
This flag has effects only for axisymmetric coordinate systems. When set, it
omits the r weight in the r dr dz measure during the numerical integration
performed the integrate function. This feature is usefull for computing the
stream function in the axisymmetric case.
lump

This flag, when set, perfoms a mass lumping procedure on the matrix at the
element level:
a(i,i) := sum(j) a(i,j)
The resulting matrix is diagonal. This feature is usefull for computing a diagonal approximation of the mass matrix for the continuous P1 element.

invert

This flag, when set, perfoms a local inversion on the matrix at the element
level:
a := inv(a)
This procedure is allowed only when the global matrix is block diagonal, e.g.
for discontinuous or bubble approximations. This property is true when basis
functions have a compact support inside exactly one element.

Default flag values


All flags are set to false by default.

54

Rheolef, the finite element system.

Implementation
struct form_option_type : quadrature_option_type {
// allocators:
form_option_type();
form_option_type (const form_option_type& fopt);
form_option_type (const quadrature_option_type& qopt);
form_option_type& operator= (const form_option_type& fopt);
operator quadrature_option_type() const { return *this; }
// data:
bool ignore_sys_coord, lump, invert;
};

5.8 trial, test, generic - symbolic forms arguments


(Source file: nfem/plib/generic.h)

Description
These classes are used for test and trial functions involved in variational formulations.
Variational formulations could be specified by expressions, in the spirit of c++ embeded
languages. A variable of the test type represents the formal argument (the test-function)
in the definition of a linear form, as in:
geo omega ("circle");
space Xh (omega, "P1");
test v(Xh);
field lh = integrate (omega, 2*v);
For a bilinear form, the test-function represents its second formal argument, while the first
one is designed by the trial type:
trial u(Xh);
test v(Xh);
form m = integrate (omega, u*v),
a = integrate (omega, dot(grad(u),grad(v)));
The generic class is abble to represents either test or trial types: it could be used to
formaly define a differential operator, as:
D(u) = (grad(u)+trans(grad(u)))

Implementation
template <class T, class M = rheo_default_memory_model>
class generic_basic {
public :
// typedefs:
typedef typename std::size_t

size_type;

Chapter 5: Classes

typedef
typedef
typedef
typedef
typedef
typedef
typedef

55

M
T
typename float_traits<T>::type
T
space_constant::valued_type
geo_basic <float_type,M>
space_basic<float_type,M>

memory_type;
scalar_type;
float_type;
value_type;
valued_type;
geo_type;
space_type;

// allocator/deallocator:
generic_basic() : _V() {}
explicit generic_basic (const space_type& V) : _V(V) {}
void resize (const space_type& V) { _V = V; }
// accessors:
const space_type&
const geo_type&
std::string
std::string
valued_type
const std::string&

get_space()
get_geo()
stamp()
get_approx()
valued_tag()
valued()

const
const
const
const
const
const

{
{
{
{
{
{

return
return
return
return
return
return

_V; }
_V.get_geo(); }
_V.stamp(); }
_V.get_approx(); }
_V.valued_tag(); }
_V.valued(); }

// accessors by components:
size_type size() const { return _V.size(); }
// accessors by degrees-of-freedom (dof):
const distributor& ownership() const { return get_space().ownership(); }
const communicator& comm() const { return ownership().comm(); }
size_type
ndof() const { return ownership().size(); }
size_type dis_ndof() const { return ownership().dis_size(); }
// data:
protected:
space_type _V;
};
typedef generic_basic<Float> generic;

5.9 geo - finite element mesh


(Source file: nfem/plib/geo.h)

Synopsys
Distributed finite element mesh.

Implementation

56

Rheolef, the finite element system.

template <class T>


class geo_basic<T,sequential> : public smart_pointer_clone<geo_abstract_rep<T,sequen
public:
// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

sequential
geo_abstract_rep<T,sequential>
geo_rep<T,sequential>
smart_pointer_clone<rep>
typename rep::size_type
typename rep::node_type
typename rep::variant_type
typename rep::reference
typename rep::const_reference
typename rep::iterator
typename rep::const_iterator
typename rep::iterator_by_variant
typename rep::const_iterator_by_variant
typename rep::coordinate_type

memory_type;
rep;
rep_geo_rep;
base;
size_type;
node_type;
variant_type;
reference;
const_reference;
iterator;
const_iterator;
iterator_by_variant;
const_iterator_by_variant;
coordinate_type;

// allocators:
geo_basic
geo_basic
void load
geo_basic

();
(std::string name, const communicator& comm = communicator());
(std::string name, const communicator& comm = communicator());
(const domain_indirect_basic<sequential>& dom, const geo_basic<T,seque

// build from_list (for level set)


geo_basic (
const geo_basic<T,sequential>&
lambda,
const array<point_basic<T>,sequential>&
node_list,
const boost::array<array<geo_element_auto<heap_allocator<size_type> >,sequenti
reference_element::max_variant>& elt_list)
: base (new_macro(rep_geo_rep(lambda,node_list,elt_list))) {}
// accessors:
std::string
name() const {
std::string
familyname() const {
size_type
dimension() const {
size_type
map_dimension() const {
size_type
serial_number() const {
size_type
variant() const {
coordinate_type
coordinate_system() const {
std::string coordinate_system_name() const {
const basis_basic<T>& get_piola_basis() const
size_type
order() const {
const node_type&
xmin() const {

return base::data().name(); }
return base::data().familyname();
return base::data().dimension(); }
return base::data().map_dimension(
return base::data().serial_number(
return base::data().variant(); }
return base::data().coordinate_sys
return space_constant::coordinate_
{ return base::data().get_piola_ba
return base::data().get_piola_basi
return base::data().xmin(); }

Chapter 5: Classes

57

const node_type&
xmax() const { return base::data().xmax(); }
const distributor& geo_element_ownership(size_type dim) const { return base::dat
const geo_size&
sizes()
const { return base::data().sizes(); }
const geo_size& ios_sizes()
const { return base::data().ios_sizes()
const_reference get_geo_element (size_type dim, size_type ige) const { return ba
reference get_geo_element (size_type dim, size_type ige)
{ return ba
const_reference dis_get_geo_element (size_type dim, size_type dis_ige) const
{ return get_geo_element (dim, dis_ige); }
const geo_element& bgd2dom_geo_element (const geo_element& bgd_K) const { return
const geo_element& dom2bgd_geo_element (const geo_element& dom_K) const { return
size_type neighbour (size_type ie, size_type loc_isid) const {
return base::data().neighbour (ie, loc_isid); }
void neighbour_guard() const { base::data().neighbour_guard(); }
size_type
n_node()
const { return base::data().n_node(); }
const node_type&
node(size_type
inod) const { return base::data().node(i
const node_type& dis_node(size_type dis_inod) const { return base::data().dis_no
void dis_inod (const geo_element& K, std::vector<size_type>& dis_inod) const {
return base::data().dis_inod(K,dis_inod); }
node_type piola (const geo_element& K, const node_type& hat_x) const { return ba
const array<node_type,sequential>& get_nodes() const { return base::data().get_n
size_type dis_inod2dis_iv (size_type dis_inod) const { return base::data().dis_i

size_type n_domain_indirect () const { return base::data().n_domain_indirect ();


bool have_domain_indirect (const std::string& name) const { return base::data().
const domain_indirect_basic<sequential>& get_domain_indirect (size_type i) const
return base::data().get_domain_indirect (i); }
const domain_indirect_basic<sequential>& get_domain_indirect (const std::string&
return base::data().get_domain_indirect (name); }
void insert_domain_indirect (const domain_indirect_basic<sequential>& dom) cons
base::data().insert_domain_indirect (dom); }
size_type n_domain () const { return base::data().n_domain_indirect (); }
geo_basic<T,sequential> get_domain (size_type i) const;
geo_basic<T,sequential> operator[] (const std::string& name) const;
geo_basic<T,sequential> boundary() const;
geo_basic<T,sequential> internal_sides() const;
geo_basic<T,sequential> sides() const;

size_type seq_locate (
const point_basic<T>& x,
size_type dis_ie_guest = std::numeric_limits<size_type>::max()) cons
{ return base::data().seq_locate (x, dis_ie_guest); }
size_type dis_locate (
const point_basic<T>& x,
size_type dis_ie_guest = std::numeric_limits<size_type>::max()) cons
{ return base::data().dis_locate (x, dis_ie_guest); }
void locate (
const array<point_basic<T>, sequential>& x,
array<size_type, sequential>& dis_ie) const

58

Rheolef, the finite element system.

{ return base::data().locate (x, dis_ie); }


size_type seq_trace_move (
const point_basic<T>&
x,
const point_basic<T>&
v,
point_basic<T>&
y) const
{ return base::data().seq_trace_move (x,v,y)
size_type dis_trace_move (
const point_basic<T>&
x,
const point_basic<T>&
v,
point_basic<T>&
y) const
{ return base::data().dis_trace_move (x,v,y)
void trace_ray_boundary (
const array<point_basic<T>,sequential>&
x,
const array<point_basic<T>,sequential>&
v,
array<size_type, sequential>&
dis_ie,
array<point_basic<T>,sequential>&
y) const
{ return base::data().trace_ray_boundary (x,
void trace_move (
const array<point_basic<T>,sequential>&
x,
const array<point_basic<T>,sequential>&
v,
array<size_type, sequential>&
dis_ie,
array<point_basic<T>,sequential>&
y) const
{ return base::data().trace_move (x,v,dis_ie
// modifiers:

void set_name (std::string name);


void set_dimension (size_type dim);
void set_serial_number (size_type i);
void reset_order (size_type order);
void set_coordinate_system (coordinate_type sys_coord);
void set_coordinate_system (std::string sys_coord_name) { set_coordinate_system
void set_nodes (const array<node_type,sequential>& x);
void build_from_data (
const geo_header&
hdr,
const array<node_type, sequential>&
node,
boost::array<array<geo_element_auto<heap_allocator<size_type> >,sequen
tmp_geo_elem
bool do_upgrade);
// extended accessors:

const communicator& comm()


const { return geo_element_ownership (0).comm(
size_type
size(size_type dim) const { return base::data().geo_element_owners
size_type dis_size(size_type dim) const { return base::data().geo_element_owners
size_type
size()
const { return size
(map_dimension()); }
size_type dis_size()
const { return dis_size (map_dimension()); }
size_type
n_vertex()
const { return size
(0); }
size_type dis_n_vertex()
const { return dis_size (0); }

Chapter 5: Classes

59

const_reference operator[] (size_type ie) const { return get_geo_element (map_di


reference operator[] (size_type ie)
{ return get_geo_element (map_di
const_iterator begin (size_type dim) const { return base::data().begin(dim); }
const_iterator end
(size_type dim) const { return base::data().end (dim); }
const_iterator begin ()
const { return begin(map_dimension()); }
const_iterator end
()
const { return end (map_dimension()); }
const_iterator_by_variant begin_by_variant
{ return base::data().begin_by_variant
const_iterator_by_variant
end_by_variant
{ return base::data(). end_by_variant

(variant_type variant) const


(variant); }
(variant_type variant) const
(variant); }

const geo_basic<T,sequential>& get_background_geo() const; // code in geo_domain


geo_basic<T,sequential> get_background_domain() const;
// for compatibility with distributed interface:

size_type ige2ios_dis_ige (size_type dim, size_type ige) const { return ige; }


size_type dis_ige2ios_dis_ige (size_type dim, size_type dis_ige) const { return
size_type ios_ige2dis_ige (size_type dim, size_type ios_ige) const { return ios_
// comparator:

bool operator== (const geo_basic<T,sequential>& omega2) const { return base::dat


// i/o:
idiststream& get (idiststream& ips);
odiststream& put (odiststream& ops) const;
void save (std::string filename = "") const;
void dump (std::string name) const {
base::data().dump (name); }
bool check (bool verbose = true) const { return base::data().check(verbose); }
};

Implementation

template <class T>


class geo_basic<T,distributed> : public smart_pointer_clone<geo_abstract_rep<T,distr
public:
// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef
typedef

distributed
geo_abstract_rep<T,distributed>
geo_rep<T,distributed>
smart_pointer_clone<rep>
typename rep::size_type
typename rep::node_type
typename rep::variant_type

memory_type;
rep;
rep_geo_rep;
base;
size_type;
node_type;
variant_type;

60

Rheolef, the finite element system.

typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

typename
typename
typename
typename
typename
typename
typename
typename

rep::node_map_type
rep::reference
rep::const_reference
rep::iterator
rep::const_iterator
rep::iterator_by_variant
rep::const_iterator_by_variant
rep::coordinate_type

node_map_type;
reference;
const_reference;
iterator;
const_iterator;
iterator_by_variant;
const_iterator_by_variant;
coordinate_type;

// allocators:
geo_basic
geo_basic
void load
geo_basic

();
(std::string name, const communicator& comm = communicator());
(std::string name, const communicator& comm = communicator());
(const domain_indirect_basic<distributed>& dom, const geo_basic<T,dist

// build from_list (for level set)


geo_basic (
const geo_basic<T,distributed>&
lambda,
const array<point_basic<T>,distributed>&
node_list,
const boost::array<array<geo_element_auto<heap_allocator<size_type> >,distribu
reference_element::max_variant>& elt_list)
: base (new_macro(rep_geo_rep(lambda,node_list,elt_list))) {}
// accessors:

std::string
name() const { return base::data().name(); }
std::string
familyname() const { return base::data().familyname();
size_type
dimension() const { return base::data().dimension(); }
size_type
map_dimension() const { return base::data().map_dimension(
size_type
serial_number() const { return base::data().serial_number(
size_type
variant() const { return base::data().variant(); }
coordinate_type
coordinate_system() const { return base::data().coordinate_sys
std::string coordinate_system_name() const { return space_constant::coordinate_
const basis_basic<T>& get_piola_basis() const { return base::data().get_piola_ba
size_type
order() const { return base::data().get_piola_basi
const node_type&
xmin() const { return base::data().xmin(); }
const node_type&
xmax() const { return base::data().xmax(); }
const distributor& geo_element_ownership(size_type dim) const
{ return base::data().geo_element_ownership (dim); }
const geo_size&
sizes()
const { return base::data().sizes(); }
const geo_size& ios_sizes()
const { return base::data().ios_sizes()
const_reference get_geo_element (size_type dim, size_type ige) const
{ return base::data().get_geo_element (dim, ige); }
const_reference dis_get_geo_element (size_type dim, size_type dis_ige) const
{ return base::data().dis_get_geo_element (dim, dis_ige); }
const geo_element& bgd2dom_geo_element (const geo_element& bgd_K) const
{ return base::data().bgd2dom_geo_element (bgd_K); }
const geo_element& dom2bgd_geo_element (const geo_element& dom_K) const

Chapter 5: Classes

61

{ return base::data().dom2bgd_geo_element (dom_K); }


size_type neighbour (size_type ie, size_type loc_isid) const {
return base::data().neighbour (ie, loc_isid); }
void neighbour_guard() const { base::data().neighbour_guard(); }
distributor geo_element_ios_ownership (size_type dim) const {
return base::data().geo_element_ios_ownership (dim); }
size_type ige2ios_dis_ige (size_type dim, size_type ige) const {
return base::data().ige2ios_dis_ige (dim,ige); }
size_type dis_ige2ios_dis_ige (size_type dim, size_type dis_ige) const {
return base::data().dis_ige2ios_dis_ige (dim,dis_ige); }
size_type ios_ige2dis_ige (size_type dim, size_type ios_ige) const {
return base::data().ios_ige2dis_ige (dim, ios_ige); }
size_type
n_node() const { return base::data().n_node(); }
const node_type&
node(size_type
inod) const { return base::data().node(i
const node_type& dis_node(size_type dis_inod) const { return base::data().dis_no
void dis_inod (const geo_element& K, std::vector<size_type>& dis_inod) const {
return base::data().dis_inod(K,dis_inod); }
node_type piola (const geo_element& K, const node_type& hat_x) const { return ba
const array<node_type,distributed>& get_nodes() const { return base::data().get_
void set_nodes (const array<node_type,distributed>& x);
void reset_order (size_type order);
size_type dis_inod2dis_iv (size_type dis_inod) const { return base::data().dis_i
void set_coordinate_system (coordinate_type sys_coord);
void set_coordinate_system (std::string sys_coord_name) { set_coordinate_system
void set_dimension (size_type dim);
void set_serial_number (size_type i);
void set_name (std::string name);

size_type n_domain_indirect () const { return base::data().n_domain_indirect ();


bool have_domain_indirect (const std::string& name) const { return base::data().
const domain_indirect_basic<distributed>& get_domain_indirect (size_type i) cons
return base::data().get_domain_indirect (i); }
const domain_indirect_basic<distributed>& get_domain_indirect (const std::string
return base::data().get_domain_indirect (name); }
void insert_domain_indirect (const domain_indirect_basic<distributed>& dom) con
base::data().insert_domain_indirect (dom); }
size_type n_domain () const { return base::data().n_domain_indirect (); }
geo_basic<T,distributed> get_domain (size_type i) const;
geo_basic<T,distributed> operator[] (const std::string& name) const;
geo_basic<T,distributed> boundary() const;
geo_basic<T,distributed> internal_sides() const;
geo_basic<T,distributed> sides() const;

size_type seq_locate (
const point_basic<T>& x,
size_type dis_ie_guest = std::numeric_limits<size_type>::max()) cons
{ return base::data().seq_locate (x, dis_ie_guest); }
size_type dis_locate (

62

Rheolef, the finite element system.

const point_basic<T>& x,
size_type dis_ie_guest = std::numeric_limits<size_type>::max()) cons
{ return base::data().dis_locate (x, dis_ie_guest); }
void locate (const array<point_basic<T>, distributed>& x, array<size_type, distr
{ return base::data().locate (x, dis_ie); }
size_type seq_trace_move (
const point_basic<T>&
x,
const point_basic<T>&
v,
point_basic<T>&
y) const
{ return base::data().seq_trace_move (x,v,y)
size_type dis_trace_move (
const point_basic<T>&
x,
const point_basic<T>&
v,
point_basic<T>&
y) const
{ return base::data().dis_trace_move (x,v,y)
void trace_ray_boundary (
const array<point_basic<T>,distributed>&
x,
const array<point_basic<T>,distributed>&
v,
array<size_type, distributed>&
dis_ie,
array<point_basic<T>,distributed>&
y) const
{ return base::data().trace_ray_boundary (x,
void trace_move (
const array<point_basic<T>,distributed>&
x,
const array<point_basic<T>,distributed>&
v,
array<size_type, distributed>&
dis_ie,
array<point_basic<T>,distributed>&
y) const
{ return base::data().trace_move (x,v,dis_ie
// extended accessors:

size_type
size(size_type dim) const { return base::data().geo_element_owners
size_type dis_size(size_type dim) const { return base::data().geo_element_owners
const communicator& comm()
const { return geo_element_ownership (0).comm(
size_type
size()
const { return size
(map_dimension()); }
size_type dis_size()
const { return dis_size (map_dimension()); }
size_type
n_vertex()
const { return size
(0); }
const_reference operator[] (size_type ie) const
{ return get_geo_element (map_dimension(), ie); }
const_iterator
const_iterator
const_iterator
const_iterator

begin
end
begin
end

(size_type dim) const { return


(size_type dim) const { return
()
const { return
()
const { return

const_iterator_by_variant begin_by_variant
{ return base::data().begin_by_variant
const_iterator_by_variant
end_by_variant
{ return base::data(). end_by_variant

base::data().begin(dim); }
base::data().end (dim); }
begin(map_dimension()); }
end (map_dimension()); }

(variant_type variant) const


(variant); }
(variant_type variant) const
(variant); }

Chapter 5: Classes

63

const geo_basic<T,distributed>& get_background_geo() const; // code in geo_domai


geo_basic<T,distributed> get_background_domain() const;
// comparator:

bool operator== (const geo_basic<T,distributed>& omega2) const { return base::da


// i/o:
odiststream& put (odiststream& ops) const { return base::data().put (ops); }
idiststream& get (idiststream& ips);
void save (std::string filename = "") const;
bool check (bool verbose = true) const { return base::data().check(verbose); }
// utilities:

void set_ios_permutation (
boost::array<size_type,reference_element::max_variant>& loc_ndof_by_variant,
array<size_type,distributed>&
idof2ios_dis_idof) c
{ base::data().set_ios_permutation (loc_ndof_by_variant, idof2ios_dis_idof); }
};

5.10 space piecewise polynomial finite element space


(Source file: nfem/plib/space.h)

Description
The space class contains some numbering for unknowns and blocked degrees of freedoms
related to a given mesh and polynomial approximation.

Synopsis
space Q (omega, "P1");
space V (omega, "P2", "vector");
space T (omega, "P1d", "tensor");

Product
space X = T*V*Q;
space Q2 = pow(Q,2);

Implementation
template <class T>
class space_basic<T,sequential> : public smart_pointer<space_rep<T,sequential> > {
public:
// typedefs:

64

Rheolef, the finite element system.

typedef
typedef
typedef
typedef

space_rep<T,sequential>
smart_pointer<rep>
typename rep::size_type
typename rep::valued_type

rep;
base;
size_type;
valued_type;

// allocators:

space_basic (const geo_basic<T,sequential>& omega = (geo_basic<T,sequential>()),


std::string approx = "", std::string valued = "scalar");
space_basic (const space_mult_list<T,sequential>& expr);
space_basic (const space_constitution<T,sequential>& constit);
// accessors:
void
void
void
void

block (std::string dom_name);


unblock(std::string dom_name);
block (const domain_indirect_basic<sequential>& dom);
unblock(const domain_indirect_basic<sequential>& dom);

const distributor&
const communicator&
size_type
size_type

ownership() const;
comm() const;
ndof() const;
dis_ndof() const;

const geo_basic<T,sequential>& get_geo() const;


const numbering<T,sequential>& get_numbering() const;
size_type size() const;
valued_type
valued_tag()
const;
const std::string&
valued()
const;
space_component<T,sequential>
operator[] (size_type i_comp);
space_component_const<T,sequential> operator[] (size_type i_comp) const;
const space_constitution<T,sequential>& get_constitution() const;
size_type degree() const;
std::string get_approx() const;
std::string stamp() const;
void dis_idof (const geo_element& K, std::vector<size_type>& dis_idof) const;
const distributor& iu_ownership() const;
const distributor& ib_ownership() const;
bool
is_blocked
size_type
iub
bool dis_is_blocked
size_type
dis_iub

(size_type
idof) const;
(size_type
idof) const;
(size_type dis_idof) const;
(size_type dis_idof) const;

const distributor& ios_ownership() const;


size_type idof2ios_dis_idof (size_type idof) const;

Chapter 5: Classes

65

size_type ios_idof2dis_idof (size_type ios_idof) const;


const point_basic<T>& xdof (size_type idof) const;
const array<point_basic<T>,sequential>& get_xdofs() const;
template <class Function>
T momentum (const Function& f, size_type idof) const;
template <class Function>
point_basic<T> vector_momentum (const Function& f, size_type idof) const;
template <class Function>
tensor_basic<T> tensor_momentum (const Function& f, size_type idof) const;
array<size_type, sequential> build_indirect_array (
const space_basic<T,sequential>& Wh, const std::string& dom_name) const;

array<size_type, sequential> build_indirect_array (


const space_basic<T,sequential>& Wh, const geo_basic<T,sequential>& bgd_gamm

const std::set<size_type>& ext_iu_set() const { return base::data().ext_iu_set()


const std::set<size_type>& ext_ib_set() const { return base::data().ext_ib_set()
// comparator:

bool operator== (const space_basic<T,sequential>& V2) const { return base::data(


bool operator!= (const space_basic<T,sequential>& V2) const { return ! operator=
friend bool are_compatible (const space_basic<T,sequential>& V1, const space_bas
return are_compatible (V1.data(), V2.data()); }
};

Implementation

template <class T>


class space_basic<T,distributed> : public smart_pointer<space_rep<T,distributed> > {
public:
// typedefs:
typedef
typedef
typedef
typedef

space_rep<T,distributed>
smart_pointer<rep>
typename rep::size_type
typename rep::valued_type

rep;
base;
size_type;
valued_type;

// allocators:

space_basic (const geo_basic<T,distributed>& omega = (geo_basic<T,distributed>()


std::string approx = "", std::string valued = "scalar");
space_basic (const space_mult_list<T,distributed>&);

66

Rheolef, the finite element system.

space_basic (const space_constitution<T,distributed>& constit);


// accessors:
void
void
void
void

block (std::string dom_name);


unblock(std::string dom_name);
block (const domain_indirect_basic<distributed>& dom);
unblock(const domain_indirect_basic<distributed>& dom);

const distributor&
const communicator&
size_type
size_type

ownership() const;
comm() const;
ndof() const;
dis_ndof() const;

const geo_basic<T,distributed>& get_geo() const;


const numbering<T,distributed>& get_numbering() const;
size_type size() const;
valued_type
valued_tag()
const;
const std::string&
valued()
const;
space_component<T,distributed>
operator[] (size_type i_comp);
space_component_const<T,distributed> operator[] (size_type i_comp) const;
const space_constitution<T,distributed>& get_constitution() const;
size_type degree() const;
std::string get_approx() const;
std::string stamp() const;
void dis_idof (const geo_element& K, std::vector<size_type>& dis_idof) const;
const distributor& iu_ownership() const;
const distributor& ib_ownership() const;
bool
is_blocked (size_type
size_type
iub (size_type

idof) const;
idof) const;

bool dis_is_blocked (size_type dis_idof) const;


size_type
dis_iub (size_type dis_idof) const;
const distributor& ios_ownership() const;
size_type idof2ios_dis_idof (size_type idof) const;
size_type ios_idof2dis_idof (size_type ios_idof) const;
const point_basic<T>& xdof (size_type idof) const;
const array<point_basic<T>,distributed>& get_xdofs() const;
template <class Function>
T momentum (const Function& f, size_type idof) const;
template <class Function>
point_basic<T> vector_momentum (const Function& f, size_type idof) const;

Chapter 5: Classes

67

template <class Function>


tensor_basic<T> tensor_momentum (const Function& f, size_type idof) const;
array<size_type, distributed> build_indirect_array (
const space_basic<T,distributed>& Wh, const std::string& dom_name) const;

array<size_type, distributed> build_indirect_array (


const space_basic<T,distributed>& Wh, const geo_basic<T,distributed>& bgd_ga

const std::set<size_type>& ext_iu_set() const { return base::data().ext_iu_set()


const std::set<size_type>& ext_ib_set() const { return base::data().ext_ib_set()
// comparator:

bool operator== (const space_basic<T,distributed>& V2) const { return base::data


bool operator!= (const space_basic<T,distributed>& V2) const { return ! operator
friend bool are_compatible (const space_basic<T,distributed>& V1, const space_ba
return are_compatible (V1.data(), V2.data()); }
};

5.11 test, trial - symbolic arguments in variational


expressions
(Source file: nfem/plib/test.h)

Description
These classes are used for test and trial functions involved in variational formulations.
Variational formulations could be specified by expressions, in the spirit of c++ embeded
languages. A variable of the test type represents the formal argument (the test-function)
in the definition of a linear form, as in:
geo omega ("circle");
space Xh (omega, "P1");
test v(Xh);
field lh = integrate (omega, 2*v);
For a bilinear form, the test-function represents its second formal argument, while the first
one is designed by the trial type:
trial u(Xh);
test v(Xh);
form m = integrate (omega, u*v),
a = integrate (omega, dot(grad(u),grad(v)));
The field_vf class is abble to represents either test or trial types: it could be used to
formaly define a differential operator, as:
D(u) = (grad(u)+trans(grad(u)))

68

Rheolef, the finite element system.

5.12 point - vertex of a mesh


(Source file: nfem/geo_element/point.h)

Description
Defines geometrical vertex as an array of coordinates. This array is also used as a vector of
the three dimensional physical space.

Implementation
template <class T>
class point_basic {
public:
// typedefs:
typedef
typedef
typedef
typedef

size_t
T
T
T

size_type;
element_type;
scalar_type;
float_type;

// allocators:
explicit point_basic () { _x[0] = T();

_x[1] = T();

_x[2] = T(); }

explicit point_basic (
const T& x0,
const T& x1 = 0,
const T& x2 = 0)
{ _x[0] = x0; _x[1] = x1; _x[2] = x2; }
template <class T1>
point_basic<T>(const point_basic<T1>& p)
{ _x[0] = p._x[0]; _x[1] = p._x[1]; _x[2] = p._x[2]; }

template <class T1>


point_basic<T>& operator = (const point_basic<T1>& p)
{ _x[0] = p._x[0]; _x[1] = p._x[1]; _x[2] = p._x[2]; return *this; }
#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
point_basic (const std::initializer_list<T>& il);
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
// accessors:
T& operator[](int i_coord)
{ return
const T& operator[](int i_coord) const { return
T& operator()(int i_coord)
{ return
const T& operator()(int i_coord) const { return

_x[i_coord%3];
_x[i_coord%3];
_x[i_coord%3];
_x[i_coord%3];

}
}
}
}

Chapter 5: Classes

69

// interface for CGAL library inter-operability:


const T& x() const { return _x[0]; }
const T& y() const { return _x[1]; }
const T& z() const { return _x[2]; }
T& x(){ return _x[0]; }
T& y(){ return _x[1]; }
T& z(){ return _x[2]; }
// inputs/outputs:
std::istream& get (std::istream& s, int d = 3)
{
switch (d) {
case 0 : _x[0] = _x[1] = _x[2] = 0; return s;
case 1 : _x[1] = _x[2] = 0; return s >> _x[0];
case 2 : _x[2] = 0; return s >> _x[0] >> _x[1];
default: return s >> _x[0] >> _x[1] >> _x[2];
}
}
// output
std::ostream& put (std::ostream& s, int d = 3) const;
// algebra:
bool operator== (const point_basic<T>& v) const
{ return _x[0] == v[0] && _x[1] == v[1] && _x[2] == v[2]; }
bool operator!= (const point_basic<T>& v) const
{ return !operator==(v); }
point_basic<T>& operator+= (const point_basic<T>& v)
{ _x[0] += v[0]; _x[1] += v[1]; _x[2] += v[2]; return *this; }
point_basic<T>& operator-= (const point_basic<T>& v)
{ _x[0] -= v[0]; _x[1] -= v[1]; _x[2] -= v[2]; return *this; }
point_basic<T>& operator*= (const T& a)
{ _x[0] *= a; _x[1] *= a; _x[2] *= a; return *this; }
point_basic<T>& operator/= (const T& a)
{ _x[0] /= a; _x[1] /= a; _x[2] /= a; return *this; }
point_basic<T> operator+ (const point_basic<T>& v) const
{ return point_basic<T> (_x[0]+v[0], _x[1]+v[1], _x[2]+v[2]); }
point_basic<T> operator- () const
{ return point_basic<T> (-_x[0], -_x[1], -_x[2]); }

70

Rheolef, the finite element system.

point_basic<T> operator- (const point_basic<T>& v) const


{ return point_basic<T> (_x[0]-v[0], _x[1]-v[1], _x[2]-v[2]); }
point_basic<T> operator* (const T& a) const
{ return point_basic<T> (a*_x[0], a*_x[1], a*_x[2]); }
point_basic<T> operator* (int a) const
{ return operator* (T(a)); }
point_basic<T> operator/ (const T& a) const
{ return operator* (T(1)/T(a)); }
point_basic<T> operator/ (point_basic<T> v) const
{ return point_basic<T> (_x[0]/v[0], _x[1]/v[1], _x[2]/v[2]); }
// data:
// protected:
T _x[3];
// internal:
static T _my_abs(const T& x) { return (x > T(0)) ? x : -x; }
};
typedef point_basic<Float> point;
// algebra:
template<class T>
inline
point_basic<T>
operator* (int a, const point_basic<T>& u)
{
return u.operator* (T(a));
}
template<class T>
inline
point_basic<T>
operator* (const T& a, const point_basic<T>& u)
{
return u.operator* (a);
}
template<class T>
inline
point_basic<T>
vect (const point_basic<T>& v, const point_basic<T>& w)
{
return point_basic<T> (
v[1]*w[2]-v[2]*w[1],
v[2]*w[0]-v[0]*w[2],
v[0]*w[1]-v[1]*w[0]);
}
// metrics:
template<class T>

Chapter 5: Classes

71

inline
T dot (const point_basic<T>& x, const point_basic<T>& y)
{
return x[0]*y[0]+x[1]*y[1]+x[2]*y[2];
}
template<class T>
inline
T norm2 (const point_basic<T>& x)
{
return dot(x,x);
}
template<class T>
inline
T norm (const point_basic<T>& x)
{
return sqrt(norm2(x));
}
template<class T>
inline
T dist2 (const point_basic<T>& x, const point_basic<T>& y)
{
return norm2(x-y);
}
template<class T>
inline
T dist (const point_basic<T>& x, const point_basic<T>& y)
{
return norm(x-y);
}
template<class T>
inline
T dist_infty (const point_basic<T>& x, const point_basic<T>& y)
{
return max(point_basic<T>::_my_abs(x[0]-y[0]),
max(point_basic<T>::_my_abs(x[1]-y[1]),
point_basic<T>::_my_abs(x[2]-y[2])));
}
template <class T>
T vect2d (const point_basic<T>& v, const point_basic<T>& w);
template <class T>
T mixt (const point_basic<T>& u, const point_basic<T>& v, const point_basic<T>& w);

// robust(exact) floating point predicates: return the sign of the value as (0, > 0,
// formally: orient2d(a,b,x) = vect2d(a-x,b-x)
template <class T>
int
sign_orient2d (
const point_basic<T>& a,

72

Rheolef, the finite element system.

const point_basic<T>& b,
const point_basic<T>& c);
template <class T>
int
sign_orient3d (
const point_basic<T>&
const point_basic<T>&
const point_basic<T>&
const point_basic<T>&

a,
b,
c,
d);

// compute also the value:


template <class T>
T orient2d(
const point_basic<T>& a,
const point_basic<T>& b,
const point_basic<T>& c);
// formally: orient3d(a,b,c,x) = mixt3d(a-x,b-x,c-x)
template <class T>
T orient3d(
const point_basic<T>& a,
const point_basic<T>& b,
const point_basic<T>& c,
const point_basic<T>& d);
template <class T>
std::string ptos (const point_basic<T>& x, int d = 3);
// ccomparators: lexicographic order
template<class T, size_t d>
bool
lexicographically_less (const point_basic<T>& a, const point_basic<T>& b)
{
for (typename point_basic<T>::size_type i = 0; i < d; i++) {
if (a[i] < b[i]) return true;
if (a[i] > b[i]) return false;
}
return false; // equality
}

5.13 quadrature_option_type - send options to the integrate


function
(Source file: nfem/geo_element/quadrature_option_type.h)

Chapter 5: Classes

73

Synopsys
The quadrature_option_type class is used to send options to the integrate function see
Section 6.4 [integrate algorithm], page 110. This class allows to set the family (Gauss,
Gauss-Lobatto, etc) and the polynomial degree that is exactly integrated. See also the see
Section 7.14 [quadrature iclass], page 147 for more on quadrature formulae.

Implementation
class quadrature_option_type {
public:
// typedefs:
typedef size_t size_type;
typedef enum {
gauss
= 0,
gauss_lobatto
= 1,
gauss_radau
= 2,
middle_edge
= 3,
superconvergent = 4,
max_family
= 5
} family_type; // update also family_name[] in quatrature.cc
// allocators:
quadrature_option_type(
family_type ft = quadrature_option_type::gauss,
size_type k = std::numeric_limits<size_type>::max());
quadrature_option_type (const quadrature_option_type& qopt);
quadrature_option_type& operator= (const quadrature_option_type& qopt);
// accessors & modifiers:
size_t
get_order() const;
family_type
get_family() const;
std::string
get_family_name() const;
void set_order (size_t r);
void set_family (family_type ft);
// data:
protected:
family_type
_family;
size_t
_order;
};

5.14 tensor - a N*N tensor, N=1,2,3


(Source file: nfem/geo_element/tensor.h)

74

Rheolef, the finite element system.

Synopsys
The tensor class defines a 3*3 tensor, as the value of a tensorial valued field. Basic algebra
with scalars, vectors of R^3 (i.e. the point class) and tensor objects are supported.

Implementation
template<class T>
class tensor_basic {
public:
typedef size_t size_type;
typedef T
element_type;
typedef T
float_type;
// allocators:
tensor_basic (const T& init_val = 0);
tensor_basic (T x[3][3]);
tensor_basic (const tensor_basic<T>& a);
static tensor_basic<T> eye (size_type d = 3);
#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
tensor_basic (const std::initializer_list<std::initializer_list<T> >& il);
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
// affectation:
tensor_basic<T>& operator = (const tensor_basic<T>& a);
tensor_basic<T>& operator = (const T& val);
// modifiers:
void
void
void
void

fill (const T& init_val);


reset ();
set_row
(const point_basic<T>& r, size_t i, size_t d = 3);
set_column (const point_basic<T>& c, size_t j, size_t d = 3);

// accessors:
T& operator()(size_type i, size_type j);
T operator()(size_type i, size_type j) const;
point_basic<T> row(size_type i) const;
point_basic<T> col(size_type i) const;
size_t nrow() const; // = 3, for template matrix compatibility
size_t ncol() const;
// inputs/outputs:
std::ostream& put (std::ostream& s, size_type d = 3) const;

Chapter 5: Classes

75

std::istream& get (std::istream&);


// algebra:

bool operator== (const tensor_basic<T>&) const;


bool operator!= (const tensor_basic<T>& b) const { return ! operator== (b);
template <class U>
friend tensor_basic<U> operator- (const tensor_basic<U>&);
template <class U>
friend tensor_basic<U> operator+ (const tensor_basic<U>&, const tensor_basic
template <class U>
friend tensor_basic<U> operator- (const tensor_basic<U>&, const tensor_basic
template <class U>
friend tensor_basic<U> operator* (int k, const tensor_basic<U>& a);
template <class U>
friend tensor_basic<U> operator* (const U& k, const tensor_basic<U>& a);
template <class U>
friend tensor_basic<U> operator* (const tensor_basic<U>& a, int k);
template <class U>
friend tensor_basic<U> operator* (const tensor_basic<U>& a, const U& k);
template <class U>
friend tensor_basic<U> operator/ (const tensor_basic<U>& a, int k);
template <class U>
friend tensor_basic<U> operator/ (const tensor_basic<U>& a, const U& k);
template <class U>
friend point_basic<U> operator* (const tensor_basic<U>&, const point_basic<
template <class U>
friend point_basic<U> operator* (const point_basic<U>& yt, const tensor_bas
point_basic<T> trans_mult (const point_basic<T>& x) const;
template <class U>
friend tensor_basic<U> trans
(const tensor_basic<U>& a, size_t d = 3);
template <class U>
friend tensor_basic<U> operator* (const tensor_basic<U>& a, const tensor_bas
template <class U>
friend void prod (const tensor_basic<U>& a, const tensor_basic<U>& b, tensor
size_t di=3, size_t dj=3, size_t dk=3);
// tr(a) = a00 + a11 + a22
template <class U>
friend U tr (const tensor_basic<U>& a, size_t d=3);
// a = u otimes v <==> aij = ui*vj
template <class U>
friend tensor_basic<U> otimes (const point_basic<U>& u, const point_basic<U>
template <class U>
friend tensor_basic<U> inv (const tensor_basic<U>& a, size_t d = 3);
template <class U>
friend tensor_basic<U> diag (const point_basic<U>& d);
template <class U>
friend point_basic<U> diag (const tensor_basic<U>& a);

76

Rheolef, the finite element system.

// metric and geometric transformations:


template <class U>
friend U ddot (const tensor_basic<U>&, const tensor_basic<U>&);
T determinant (size_type d = 3) const;
template <class U>
friend U determinant (const tensor_basic<U>& A, size_t d = 3);
template <class U>
friend bool invert_3x3 (const tensor_basic<U>& A, tensor_basic<U>& result);

// spectral:
// eigenvalues & eigenvectors:
// a = q*d*q^T
// a may be symmetric
// where q=(q1,q2,q3) are eigenvectors in rows (othonormal matrix)
// and
d=(d1,d2,d3) are eigenvalues, sorted in decreasing order d1 >= d2 >
// return d
point_basic<T> eig (tensor_basic<T>& q, size_t dim = 3) const;
point_basic<T> eig (size_t dim = 3) const;

// singular value decomposition:


// a = u*s*v^T
// a can be unsymmetric
// where u=(u1,u2,u3) are left pseudo-eigenvectors in rows (othonormal matri
//
v=(v1,v2,v3) are right pseudo-eigenvectors in rows (othonormal matr
// and
s=(s1,s2,s3) are eigenvalues, sorted in decreasing order s1 >= s2 >
// return s
point_basic<T> svd (tensor_basic<T>& u, tensor_basic<T>& v, size_t dim = 3)
// data:
T _x[3][3];
};
typedef tensor_basic<Float> tensor;
// nonlinear algebra:
template<class T>
tensor_basic<T> exp (const tensor_basic<T>& a, size_t d = 3);
// inputs/outputs:
template<class T>
inline
std::istream& operator>> (std::istream& in, tensor_basic<T>& a)
{
return a.get (in);
}
template<class T>
inline
std::ostream& operator<< (std::ostream& out, const tensor_basic<T>& a)
{

Chapter 5: Classes

77

return a.put (out);

}
// t += a otimes b
template<class T>
void cumul_otimes (tensor_basic<T>& t, const point_basic<T>& a, const point_basic<T>
template<class T>
void cumul_otimes (tensor_basic<T>& t, const point_basic<T>& a, const point_basic<T>

5.15 tensor3 - a third order tensor


(Source file: nfem/geo_element/tensor3.h)

Synopsys
The tensor3 class defines a fourth tensor where indices varie from zero to 2 (aka 3D physical
space).

Implementation
template<class T>
class tensor3_basic {
public:
typedef size_t size_type;
typedef T
element_type;
typedef T
float_type;
// allocators:
tensor3_basic (const T& init_val = 0);
tensor3_basic (const tensor3_basic<T>& a);
// affectation:
tensor3_basic<T>& operator= (const tensor3_basic<T>& a);
tensor3_basic<T>& operator= (const T& val);
// accessors:
T&
operator()(size_type i, size_type j, size_type k);
const T& operator()(size_type i, size_type j, size_type k) const;
// algebra
tensor3_basic<T>&
tensor3_basic<T>&
tensor_basic<T>
tensor3_basic<T>
tensor3_basic<T>

operator*=
operator/=
operator*
operator*
operator+

(const
(const
(const
(const
(const

T& k);
T& k) { return operator*= (1./k); }
point_basic<T>& v) const;
tensor_basic<T>& b) const;
tensor3_basic<T>& b) const;

78

Rheolef, the finite element system.

// data:
protected:
T _x [3][3][3];
};
typedef tensor3_basic<Float> tensor3;

5.16 tensor4 - a fouth order tensor


(Source file: nfem/geo_element/tensor4.h)

Synopsys
The tensor4 class defines a fourth tensor where indices varie from zero to 2 (aka 3D physical
space).

Implementation
template<class T>
class tensor4_basic {
public:
typedef size_t size_type;
typedef T
element_type;
typedef T
float_type;
// allocators:
tensor4_basic (const T& init_val = 0);
tensor4_basic (const tensor4_basic<T>& a);

#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
tensor4_basic (const std::initializer_list<std::initializer_list<
std::initializer_list<std::initializer_list<T> > > >& i
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
// affectation:
tensor4_basic<T>& operator= (const tensor4_basic<T>& a);
tensor4_basic<T>& operator= (const T& val);
// accessors:
T&
operator()(size_type i, size_type j, size_type k, size_type l);
const T& operator()(size_type i, size_type j, size_type k, size_type l) const;
// algebra:
tensor4_basic<T>& operator*= (const T& k);

Chapter 5: Classes

79

tensor4_basic<T>& operator/= (const T& k) { return operator*= (1./k); }


tensor4_basic<T> operator+ (const tensor4_basic<T>& b) const;
tensor4_basic<T> operator- (const tensor4_basic<T>& b) const;
// io:
std::ostream& put (std::ostream& out, size_type d=3) const;
// data:
protected:
T _x [3][3][3][3];
};
typedef tensor4_basic<Float> tensor4;
// nonlinear algebra:
template <class T>
T norm2 (const tensor4_basic<T>&);
template <class T>
T norm (const tensor4_basic<T>& a) { return sqrt(norm2(a)); }
template <class T>
tensor4_basic<T> dexp (const tensor_basic<T>& a, size_t d = 3);
// algebra:
template <class
tensor_basic<T>
template <class
tensor_basic<T>

T>
ddot (const tensor4_basic<T>&, const tensor_basic<T>&);
T>
ddot (const tensor_basic<T>&, const tensor4_basic<T>&);

5.17 array - container in distributed environment


(Source file: skit/plib2/array.h)

Synopsys
STL-like vector container for a distributed memory machine model.

Example
A sample usage of the class is:
int main(int argc, char**argv) {
environment distributed(argc, argv);
array<double> x(distributor(100), 3.14);
dout << x << endl;
}
The array<T> interface is similar to those of the std::vector<T> with the addition of some
communication features in the distributed case: write accesses with entry/assembly and
read access with dis at.

80

Rheolef, the finite element system.

Distributed write access


Loop on any dis_i that is not managed by the current processor:
x.dis_entry (dis_i) = value;
and then, after loop, perform all communication:
x.dis_entry_assembly();
After this command, each value is stored in the array, available the processor associated to
dis_i.

Distributed read access


First, define the set of indexes:
std::set<size_t> ext_idx_set;
Then, loop on dis_i indexes that are not managed by the current processor:
ext_idx_set.insert (dis_i);
After the loop, performs the communications:
x.set_dis_indexes (ext_idx_set);
After this command, each values associated to the dis_i index, and that belongs to the
index set, is now available also on the current processor as:
value = x.dis_at (dis_i);
For convenience, if dis_i is managed by the current processor, this function returns also
the value.

Note
The class takes two template parameters: one for the type T and the second for the memory
model M, that could be either M=distributed or M=sequential. The two cases are associated
to two diferent implementations, but proposes exactly the same interface. The sequential
interface propose also a supplementary constructor:
array<double,sequential> x(local_size, init_val);
This constructor is a STL-like one but could be consufused in the distributed case, since
there are two sizes: a local one and a global one. In that case, the use of the distributor,
as a generalization of the size concept, clarify the situation (see Section 5.21 [distributor
class], page 95).

Chapter 5: Classes

81

Implementation note
"scatter" via "get dis entry".
"gather" via "dis entry(dis i) = value" or "dis entry(dis i) += value". Note that += applies when T=idx set where idx set is a wrapper class of std::set<size t> ; the += operator
represents the union of a set. The operator= is used when T=double or others simple T
types without algebra. If there is a conflict, i.e. several processes set the dis i index, then
the result of operator+= depends upon the order of the process at each run and is not
deterministic. Such ambiguous behavior is not detected yet at run time.

Implementation
template <class T, class A>
class array<T,sequential,A> : public smart_pointer<array_rep<T,sequential,A> > {
public:
// typedefs:
typedef array_rep<T,sequential,A>
typedef smart_pointer<rep>

rep;
base;

typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

memory_type;
size_type;
difference_type;
value_type;
reference;
dis_reference;
iterator;
const_reference;
const_iterator;

sequential
typename rep::size_type
typename rep::difference_type
typename rep::value_type
typename rep::reference
typename rep::dis_reference
typename rep::iterator
typename rep::const_reference
typename rep::const_iterator

// allocators:

array
void resize
array
void resize

(size_type loc_size
(size_type loc_size
(const distributor&
(const distributor&

= 0,
= 0,
ownership,
ownership,

const
const
const
const

T&
T&
T&
T&

init_val
init_val
init_val
init_val

=
=
=
=

T(), const A& all


T());
T(), const A& all
T());

// local accessors & modifiers:


A get_allocator() const
size_type
size () const
size_type dis_size () const
const distributor& ownership() const
const communicator& comm() const

{
{
{
{
{

return
return
return
return
return

base::data().get_allocator(); }
base::data().size(); }
base::data().dis_size(); }
base::data().ownership(); }
ownership().comm(); }

reference
operator[] (size_type i)
{ return base::data().operator[]
const_reference operator[] (size_type i) const { return base::data().operator[]

82

Rheolef, the finite element system.

reference
operator() (size_type i)
{ return base::data().operator[]
const_reference operator() (size_type i) const { return base::data().operator[]
const_reference dis_at (size_type dis_i) const { return operator[] (dis_i); }
iterator
const_iterator
iterator
const_iterator

begin()
begin() const
end()
end() const

{
{
{
{

return
return
return
return

base::data().begin(); }
base::data().begin(); }
base::data().end(); }
base::data().end(); }

// global modifiers (for compatibility with distributed interface):

dis_reference dis_entry (size_type dis_i) { return base::data().dis_entry(dis_i)


template<class SetOp = typename default_set_op<T>::type>
void dis_entry_assembly (SetOp my_set_op = SetOp()) {}
template<class SetOp = typename default_set_op<T>::type>
void dis_entry_assembly_begin (SetOp my_set_op = SetOp()) {}
template<class SetOp = typename default_set_op<T>::type>
void dis_entry_assembly_end (SetOp my_set_op = SetOp()) {}
void dis_entry_assembly_begin() {}
void dis_entry_assembly_end()
{}
void dis_entry_assembly()
{}

void reset_dis_indexes() const {}


template<class Set> void set_dis_indexes
(const Set& ext_idx_set) const {}
template<class Set> void append_dis_indexes (const Set& ext_idx_set) const {}
template<class Set, class Map> void append_dis_entry (const Set& ext_idx_set, Ma
template<class Set, class Map> void get_dis_entry
(const Set& ext_idx_set, Ma
// apply a partition:

template<class RepSize>
void repartition (
// old_numbering for *this
const RepSize&
partition,
// old_ownership
array<T,sequential,A>& new_array,
// new_ownership (created)
RepSize&
old_numbering,
// new_ownership
RepSize&
new_numbering) const // old_ownership
{ return base::data().repartition (partition, new_array, old_numbering, new_

template<class RepSize>
void permutation_apply (
// old_numbering for *this
const RepSize&
new_numbering,
// old_ownership
array<T,sequential,A>& new_array) const
// new_ownership (already allocat
{ return base::data().permutation_apply (new_numbering, new_array); }
void reverse_permutation (
// old_ownership for
array<size_type,sequential,A>& inew2dis_iold) const
// new_ownership
{ base::data().reverse_permutation (inew2dis_iold.data()); }

Chapter 5: Classes

83

// i/o:

odiststream& put_values (odiststream& ops) const { return base::data().put_value


idiststream& get_values (idiststream& ips)
{ return base::data().get_value
template <class GetFunction>
idiststream& get_values (idiststream& ips, GetFunction get_element)
{ retu
template <class PutFunction>
odiststream& put_values (odiststream& ops, PutFunction put_element) const { retu
void dump (std::string name) const { return base::data().dump(name); }
};

Implementation
template <class T, class A>
class array<T,distributed,A> : public smart_pointer<array_rep<T,distributed,A> > {
public:
// typedefs:
typedef array_rep<T,distributed,A>
typedef smart_pointer<rep>
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

rep;
base;

distributed
memory_type;
typename rep::size_type
size_type;
typename rep::difference_type difference_type;
typename rep::value_type
value_type;
typename rep::reference
reference;
typename rep::dis_reference
dis_reference;
typename rep::iterator
iterator;
typename rep::const_reference const_reference;
typename rep::const_iterator const_iterator;
typename rep::scatter_map_type scatter_map_type;

// allocators:

array
(const distributor& ownership = distributor(), const T& init_val = T
void resize (const distributor& ownership = distributor(), const T& init_val = T
// local accessors & modifiers:
A get_allocator() const
size_type
size () const
size_type dis_size () const
const distributor& ownership() const
const communicator& comm() const

{
{
{
{
{

return
return
return
return
return

base::data().get_allocator(); }
base::data().size(); }
base::data().dis_size(); }
base::data().ownership(); }
base::data().comm(); }

reference
operator[] (size_type i)
{ return base::data().operator[]
const_reference operator[] (size_type i) const { return base::data().operator[]
reference
operator() (size_type i)
{ return base::data().operator[]

84

Rheolef, the finite element system.

const_reference operator() (size_type i) const { return base::data().operator[]


iterator
const_iterator
iterator
const_iterator

begin()
begin() const
end()
end() const

{
{
{
{

return
return
return
return

base::data().begin(); }
base::data().begin(); }
base::data().end(); }
base::data().end(); }

// global accessor:

template<class Set, class Map>


void append_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const { base::d

template<class Set, class Map>


void get_dis_entry
(const Set& ext_idx_set, Map& ext_idx_map) const { base::d

template<class Set>
void append_dis_indexes (const Set& ext_idx_set) const { base::data().append_dis
void reset_dis_indexes() const { base::data().reset_dis_indexes(); }
template<class Set>
void set_dis_indexes

(const Set& ext_idx_set) const { base::data().set_dis_in

const T& dis_at (size_type dis_i) const { return base::data().dis_at (dis_i); }

// get all external pairs (dis_i, values):


const scatter_map_type& get_dis_map_entries() const { return base::data().get_di
// global modifiers (for compatibility with distributed interface):

dis_reference dis_entry (size_type dis_i) { return base::data().dis_entry(dis_i)

template<class SetOp = typename default_set_op<T>::type>


void dis_entry_assembly_begin (SetOp my_set_op = SetOp()) { base::data().dis_ent
template<class SetOp = typename default_set_op<T>::type>
void dis_entry_assembly_end
(SetOp my_set_op = SetOp()) { base::data().dis_ent
template<class SetOp = typename default_set_op<T>::type>
void dis_entry_assembly
(SetOp my_set_op = SetOp()) { base::data().dis_ent

void dis_entry_assembly_begin() { base::data().template dis_entry_assembly_begin


void dis_entry_assembly_end()
{ base::data().template dis_entry_assembly_end<t
void dis_entry_assembly()
{ dis_entry_assembly_begin(); dis_entry_assembly
// apply a partition:
template<class RepSize>
void repartition (
const RepSize&
partition,
array<T,distributed>& new_array,
RepSize&
old_numbering,

//
//
//
//

old_numbering for *this


old_ownership
new_ownership (created)
new_ownership

Chapter 5: Classes

85

RepSize&
new_numbering) const // old_ownership
{ return base::data().repartition (partition.data(), new_array.data(), old_n

template<class RepSize>
void permutation_apply (
// old_numbering for *this
const RepSize&
new_numbering,
// old_ownership
array<T,distributed,A>& new_array) const
// new_ownership (already allocat
{ base::data().permutation_apply (new_numbering.data(), new_array.data()); }
void reverse_permutation (
// old_ownership for
array<size_type,distributed,A>& inew2dis_iold) const
// new_ownership
{ base::data().reverse_permutation (inew2dis_iold.data()); }
// i/o:

odiststream& put_values (odiststream& ops) const { return base::data().put_value


idiststream& get_values (idiststream& ips)
{ return base::data().get_value
void dump (std::string name) const
{ return base::data().dump(name); }

template <class GetFunction>


idiststream& get_values (idiststream& ips, GetFunction get_element)
{ retu
template <class PutFunction>
odiststream& put_values (odiststream& ops, PutFunction put_element) const { retu
template <class PutFunction, class A2> odiststream& permuted_put_values (
odiststream& ops, const array<size_type,distributed,A2>& perm, PutFu
{ return base::
};

5.18 asr - associative sparse matrix


(Source file: skit/plib2/asr.h)

Synopsys
Associative sparse matrix container, used during FEM assembling process.

Implementation note
Elements are stored row by row using the pair set class bqsed on the STL map class.
Implementation of asr uses array<pair set>

Implementation

template<class T, class M = rheo_default_memory_model, class A = std::allocator<T> >


class asr : public array<pair_set<T,A>, M, A> {
public:
// typedefs:
typedef pair_set<T,A>

row_type;

86

Rheolef, the finite element system.

typedef array<row_type,M,A>
typedef typename base::size_type
typedef M

base;
size_type;
memory_type;

struct dis_reference {
dis_reference (typename base::dis_reference row_dis_i, size_type dis_j)
: _row_dis_i(row_dis_i), _dis_j(dis_j) {}
dis_reference& operator+= (const T& value) {
_row_dis_i += std::pair<size_type,T>(_dis_j,value);
return *this;
}
typename base::dis_reference _row_dis_i;
size_type
_dis_j;
};
// allocators/deallocators:

asr (const A& alloc = A())


: base(distributor(), row_type(alloc), alloc), _col_ownership(), _nnz(0), _dis

asr (const distributor& row_ownership, const distributor& col_ownership, const A


: base(row_ownership, row_type(alloc), alloc), _col_ownership(col_ownership),
asr (const csr_rep<T,M>&, const A& alloc = A());
asr (const csr<T,M>&,
const A& alloc = A());
void build_from_csr (const csr_rep<T,M>&);

void resize (const distributor& row_ownership, const distributor& col_ownership)


{
base::resize (row_ownership);
_col_ownership = col_ownership;
_nnz = _dis_nnz = 0;
}
// accessors:
const communicator& comm() const { return base::comm(); }
size_type nrow () const { return base::size(); }
size_type ncol () const { return _col_ownership.size(); }
size_type nnz () const { return _nnz; }
size_type dis_nrow () const { return base::dis_size(); }
size_type dis_ncol () const { return _col_ownership.dis_size(); }
size_type dis_nnz () const { return _dis_nnz; }
const distributor& row_ownership() const { return base::ownership(); }
const distributor& col_ownership() const { return _col_ownership; }

Chapter 5: Classes

87

// modifiers:
T operator()
(size_type
i, size_type dis_j) const;
T&
semi_dis_entry (size_type
i, size_type dis_j);
dis_reference dis_entry (size_type dis_i, size_type dis_j);

// dis_entry_assembly_end is redefined in order to recompute _nnz and _dis_nnz


void dis_entry_assembly_begin() { base::dis_entry_assembly_begin (pair_set_add_o
void dis_entry_assembly_end()
{ base::dis_entry_assembly_end
(pair_set_add_o
void dis_entry_assembly()
{ dis_entry_assembly_begin(); dis_entry_assembly
// io:
odiststream& put (odiststream& ops) const;
idiststream& get (idiststream& ips);
// internal:
odiststream& put_mpi
odiststream& put_seq
odiststream& put_seq_sparse_matlab
odiststream& put_seq_matrix_market
protected:
void _recompute_nnz();
// data:
distributor _col_ownership;
size_type
_nnz;
size_type
_dis_nnz;
};

(odiststream&
(odiststream&
(odiststream&
(odiststream&

ops)
ops,
ops,
ops,

const;
size_type first_dis_i = 0)
size_type first_dis_i = 0)
size_type first_dis_i = 0)

5.19 csr - compressed sparse row matrix


(Source file: skit/plib2/csr.h)

Synopsys
Distributed compressed sparse matrix container stored row by row.

Description
Sparse matrix are compressed by rows. In distributed environment, the distribution follows
the row distributor (see Section 5.21 [distributor class], page 95).

Algebra
Adding or substracting two matrices writes a+b and a-b, respectively, and multiplying a
matrix by a scalar writes lambda*x. Thus, any linear combination of sparse matrices is
available.
Matrix-vector product writes a*x where x is a vector (see Section 5.25 [vec class], page 101).

88

Rheolef, the finite element system.

Limitations
Some basic linear algebra is still under development: a.trans_mult(x) matrix transpose
vector product, trans(a) matrix transpose, a*b matrix product.

Implementation
template<class T>
class csr<T,sequential> : public smart_pointer<csr_rep<T,sequential> > {
public:
// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

csr_rep<T,sequential>
smart_pointer<rep>
typename rep::memory_type
typename rep::size_type
typename rep::element_type
typename rep::iterator
typename rep::const_iterator
typename rep::data_iterator
typename rep::const_data_iterator

rep;
base;
memory_type;
size_type;
element_type;
iterator;
const_iterator;
data_iterator;
const_data_iterator;

// allocators/deallocators:

csr() : base(new_macro(rep())) {}
template<class A>
explicit csr(const asr<T,sequential,A>& a) : base(new_macro(rep(a))) {}
void resize (size_type loc_nrow1 = 0, size_type loc_ncol1 = 0, size_type loc_nnz
{ base::data().resize(loc_nrow1, loc_ncol1, loc_nnz1); }
void resize (const distributor& row_ownership, const distributor& col_ownership,
{ base::data().resize(row_ownership, col_ownership, nnz1); }
// allocators from initializer list (c++ 2011):
#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
csr (const std::initializer_list<csr_concat_value<T,sequential> >& init_list);
csr (const std::initializer_list<csr_concat_line<T,sequential> >& init_list);
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
// accessors:

// global sizes
const distributor& row_ownership() const { return base::data().row_ownership();
const distributor& col_ownership() const { return base::data().col_ownership();
size_type dis_nrow () const
{ return row_ownership().dis_size(); }
size_type dis_ncol () const
{ return col_ownership().dis_size(); }
size_type dis_nnz () const
{ return base::data().nnz(); }
size_type dis_ext_nnz () const
{ return 0; }
bool is_symmetric() const
{ return base::data().is_symmetric(); }

Chapter 5: Classes

89

void set_symmetry (bool is_symm) const


{ base::data().set_symmetry(is_symm); }
void set_symmetry_by_check (const T& tol = std::numeric_limits<T>::epsilon()) co
{ base::data().set_symmetry_by_check();
size_type pattern_dimension() const
{ return base::data().pattern_dimension
void set_pattern_dimension(size_type dim) const { base::data().set_pattern_dimen
T max_abs () const
{ return base::data().max_abs(); }
// local sizes
size_type nrow () const
size_type ncol () const
size_type nnz () const

{ return base::data().nrow(); }
{ return base::data().ncol(); }
{ return base::data().nnz(); }

// range on local memory


size_type row_first_index () const
size_type row_last_index () const
size_type col_first_index () const
size_type col_last_index () const

{
{
{
{

return
return
return
return

base::data().row_first_index()
base::data().row_last_index();
base::data().col_first_index()
base::data().col_last_index();

const_iterator begin() const


const_iterator end()
const
iterator begin_nonconst()
iterator end_nonconst()

{
{
{
{

return
return
return
return

base::data().begin(); }
base::data().end(); }
base::data().begin(); }
base::data().end(); }

// accessors, only for distributed (for interface compatibility)


size_type ext_nnz() const
{ return 0; }
const_iterator ext_begin() const
{ return const_iterator(); }
const_iterator ext_end()
const
{ return const_iterator(); }
iterator ext_begin_nonconst()
{ return iterator(); }
iterator ext_end_nonconst()
{ return iterator(); }
size_type jext2dis_j (size_type jext) const { return 0; }
// algebra:

// y := a*x
void mult (const vec<element_type,sequential>& x, vec<element_type,sequential>&
base::data().mult (x,y);
}
vec<element_type,sequential> operator* (const vec<element_type,sequential>& x) c
vec<element_type,sequential> y (row_ownership(), element_type());
mult (x, y);
return y;
}
void trans_mult (const vec<element_type,sequential>& x, vec<element_type,sequent
base::data().trans_mult (x,y);
}
vec<element_type,sequential> trans_mult (const vec<element_type,sequential>& x)
vec<element_type,sequential> y (col_ownership(), element_type());
trans_mult (x, y);
return y;

90

Rheolef, the finite element system.

}
// a+b, a-b, a*b
csr<T,sequential> operator+ (const csr<T,sequential>& b) const;
csr<T,sequential> operator- (const csr<T,sequential>& b) const;
csr<T,sequential> operator* (const csr<T,sequential>& b) const;
// lambda*a
csr<T,sequential>& operator*= (const T& lambda) {
base::data().operator*= (lambda);
return *this;
}
// output:
void dump (const std::string& name) const { base::data().dump(name); }
};
// lambda*a
template<class T>
inline
csr<T,sequential>
operator* (const T& lambda, const csr<T,sequential>& a)
{
csr<T,sequential> b = a;
b.operator*= (lambda);
return b;
}
// -a
template<class T>
inline
csr<T,sequential>
operator- (const csr<T,sequential>& a)
{
return T(-1)*a;
}
// trans(a)
template<class T>
inline
csr<T,sequential>
trans (const csr<T,sequential>& a)
{
csr<T,sequential> b;
a.data().build_transpose (b.data());
return b;
}

Implementation
template<class T>
class csr<T,distributed> : public smart_pointer<csr_rep<T,distributed> > {
public:

Chapter 5: Classes

91

// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

csr_rep<T,distributed>
smart_pointer<rep>
typename rep::memory_type
typename rep::size_type
typename rep::element_type
typename rep::iterator
typename rep::const_iterator
typename rep::data_iterator
typename rep::const_data_iterator

rep;
base;
memory_type;
size_type;
element_type;
iterator;
const_iterator;
data_iterator;
const_data_iterator;

// allocators/deallocators:

csr() : base(new_macro(rep())) {}
template<class A>
explicit csr(const asr<T,memory_type,A>& a) : base(new_macro(rep(a))) {}
void resize (const distributor& row_ownership, const distributor& col_ownership,
{ base::data().resize(row_ownership, col_ownership, nnz1); }
// allocators from initializer list (c++ 2011):
#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
csr (const std::initializer_list<csr_concat_value<T,distributed> >& init_list);
csr (const std::initializer_list<csr_concat_line<T,distributed> >& init_list);
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
// accessors:
// global sizes
const distributor& row_ownership() const
const distributor& col_ownership() const
size_type dis_nrow () const
size_type dis_ncol () const
size_type dis_nnz () const
size_type dis_ext_nnz () const
bool is_symmetric() const
void set_symmetry (bool is_symm) const
void set_symmetry_by_check (const T& tol

{ return base::data().row_ownership();
{ return base::data().col_ownership();
{ return row_ownership().dis_size(); }
{ return col_ownership().dis_size(); }
{ return base::data().dis_nnz(); }
{ return base::data().dis_ext_nnz(); }
{ return base::data().is_symmetric(); }
{ base::data().set_symmetry(is_symm); }
= std::numeric_limits<T>::epsilon()) co
{ base::data().set_symmetry_by_check();
size_type pattern_dimension() const
{ return base::data().pattern_dimension
void set_pattern_dimension(size_type dim) const { base::data().set_pattern_dimen
T max_abs () const
{ return base::data().max_abs(); }
// local sizes
size_type nrow () const
size_type ncol () const
size_type nnz () const

{ return base::data().nrow(); }
{ return base::data().ncol(); }
{ return base::data().nnz(); }

92

Rheolef, the finite element system.

// range on local memory


size_type row_first_index () const
size_type row_last_index () const
size_type col_first_index () const
size_type col_last_index () const

{
{
{
{

return
return
return
return

base::data().row_first_index()
base::data().row_last_index();
base::data().col_first_index()
base::data().col_last_index();

const_iterator begin() const


const_iterator end()
const
iterator begin_nonconst()
iterator end_nonconst()

{
{
{
{

return
return
return
return

base::data().begin(); }
base::data().end(); }
base::data().begin(); }
base::data().end(); }

// accessors, only for distributed


size_type ext_nnz() const
{ return base::data().ext_nnz(); }
const_iterator ext_begin() const
{ return base::data().ext_begin(); }
const_iterator ext_end()
const
{ return base::data().ext_end(); }
iterator ext_begin_nonconst()
{ return base::data().ext_begin(); }
iterator ext_end_nonconst()
{ return base::data().ext_end(); }
size_type jext2dis_j (size_type jext) const { return base::data().jext2dis_j(jex
// algebra:

// y := a*x
void mult (const vec<element_type,distributed>& x, vec<element_type,distributed>
base::data().mult (x,y);
}
vec<element_type,distributed> operator* (const vec<element_type,distributed>& x)
vec<element_type,distributed> y (row_ownership(), element_type());
mult (x, y);
return y;
}
void trans_mult (const vec<element_type,distributed>& x, vec<element_type,distri
base::data().trans_mult (x,y);
}
vec<element_type,distributed> trans_mult (const vec<element_type,distributed>& x
vec<element_type,distributed> y (col_ownership(), element_type());
trans_mult (x, y);
return y;
}
// a+b, a-b, a*b
csr<T,distributed> operator+ (const csr<T,distributed>& b) const;
csr<T,distributed> operator- (const csr<T,distributed>& b) const;
csr<T,distributed> operator* (const csr<T,distributed>& b) const;
// lambda*a
csr<T,distributed>& operator*= (const T& lambda) {
base::data().operator*= (lambda);
return *this;

Chapter 5: Classes

93

}
// output:
void dump (const std::string& name) const { base::data().dump(name); }
};
// lambda*a
template<class T>
inline
csr<T,distributed>
operator* (const T& lambda, const csr<T,distributed>& a)
{
csr<T,distributed> b = a;
b.operator*= (lambda);
return b;
}
// -a
template<class T>
inline
csr<T,distributed>
operator- (const csr<T,distributed>& a)
{
return T(-1)*a;
}
// trans(a)
template<class T>
inline
csr<T,distributed>
trans (const csr<T,distributed>& a)
{
csr<T,distributed> b;
a.data().build_transpose (b.data());
return b;
}
#endif // _RHEOLEF_HAVE_MPI
// b = f(a); f as a class-function or usual fct
template<class T, class M, class Function>
csr<T,M>
apply (Function f, const csr<T,M>& a)
{
csr<T,M> b = a;
typename csr<T,M>::size_type n = a.nrow();
typename csr<T,M>::const_iterator dia_ia = a.begin();
typename csr<T,M>::iterator
dia_ib = b.begin_nonconst();
pair_transform_second (dia_ia[0], dia_ia[n], dia_ib[0], f);
if (a.ext_nnz() != 0) {
typename csr<T,M>::const_iterator ext_ia = a.ext_begin();
typename csr<T,M>::iterator
ext_ib = b.ext_begin_nonconst();
pair_transform_second (ext_ia[0], ext_ia[n], ext_ib[0], f);

94

Rheolef, the finite element system.

}
return b;
}
template<class T, class M, class Function>
csr<T,M>
apply (T (*f)(const T&), const csr<T,M>& a)
{
return apply (std::ptr_fun(f), a);
}

5.20 dia - diagonal matrix


(Source file: skit/plib2/dia.h)

Description
The class implements a diagonal matrix. A declaration whithout any parametrers correspond to a null size matrix:
dia<Float> d;
The constructor can be invocated whith a ownership parameter (see Section 5.21 [distributor class], page 95):
dia<Float> d(ownership);
or an initialiser, either a vector (see Section 5.25 [vec class], page 101):
dia<Float> d(v);
or a csr matrix (see Section 5.19 [csr class], page 87):
dia<Float> d(a);
The conversion from dia to vec or csr is explicit.
When a diagonal matrix is constructed from a csr matrix, the definition of the diagonal of
matrix is always a vector of size row ownership which contains the elements in rows 1 to
nrow of the matrix that are contained in the diagonal. If the diagonal element falls outside
the matrix, i.e. ncol < nrow then it is defined as a zero entry.

Preconditioner interface
The class presents a preconditioner interface, as the Section 5.23 [solver class], page 97, so
that it can be used as preconditioner to the iterative solvers suite (see Section 6.11 [pcg
algorithm], page 118).

Implementation

Chapter 5: Classes

95

template<class T, class M = rheo_default_memory_model>


class dia : public vec<T,M> {
public:
// typedefs:
typedef typename vec<T,M>::size_type
typedef typename vec<T,M>::iterator
typedef typename vec<T,M>::const_iterator

size_type;
iterator;
const_iterator;

// allocators/deallocators:
explicit dia (const distributor& ownership = distributor(),
const T& init_val = std::numeric_limits<T>::max());
explicit dia (const vec<T,M>& u);
explicit dia (const csr<T,M>& a);
dia<T,M>& operator= (const T& lambda);
// preconditionner interface: solves d*x=b
vec<T,M> solve (const vec<T,M>& b) const;
vec<T,M> trans_solve (const vec<T,M>& b) const;
};
template <class T, class M>
dia<T,M> operator/ (const T& lambda, const dia<T,M>& d);
template <class T, class M>
vec<T,M> operator* (const dia<T,M>& d, const vec<T,M>& x);

5.21 distributor - data distribution table


(Source file: skit/plib2/distributor.h)

Synopsys
Used by "array"(1), "asr"(1) and "csr"(1). and such classes that distribute data as chunk.

Implementation
class distributor : public Vector<std::allocator<int>::size_type> {
public:
// typedefs:
typedef
typedef
typedef
typedef

std::allocator<int>::size_type
Vector<size_type>
_base::iterator
_base::const_iterator

size_type;
_base;
iterator;
const_iterator;

96

Rheolef, the finite element system.

typedef int
typedef communicator

tag_type;
communicator_type;

// constants:
static const size_type decide = size_type(-1);
// allocators/deallocators:
distributor(
size_type dis_size = 0,
const communicator_type& c = communicator_type(),
size_type loc_size = decide);
distributor(const distributor&);
~distributor();
void resize(
size_type dis_size = 0,
const communicator_type& c = communicator_type(),
size_type loc_size = decide);
// accessors:
const communicator_type& comm() const;
/// global and local sizes
size_type dis_size () const;
/// current process id
size_type process () const;
/// number of processes
size_type n_process () const;
/// find iproc associated to a global index dis_i: CPU=log(nproc)
size_type find_owner (size_type dis_i) const;
/// global index range and local size owned by ip-th process
size_type first_index (size_type ip) const;
size_type last_index (size_type ip) const;
size_type size (size_type ip) const;
/// global index range and local size owned by current process
size_type first_index () const;
size_type last_index () const;
size_type size () const;
/// true when dis_i in [first_index(ip):last_index(ip)[

Chapter 5: Classes

97

bool is_owned (size_type dis_i, size_type ip) const;


// the same with ip=current process
bool is_owned (size_type dis_i) const;

/// returns a new tag


static tag_type get_new_tag();
// comparators:
bool operator== (const distributor&) const;
bool operator!= (const distributor&) const;
// data:
protected:
communicator_type _comm;
};

5.22 eye - the identity matrix


(Source file: skit/plib2/eye.h)

Description
Following matlab, the name eye() is used in place of I to denote identity matrices because
I is often used as a subscript or as sqrt(-1). The dimensions of eye() are determined
by context. The preconditioner interface is usefull when calling algorithms without any
preconditioners, e.g.
int status = pcg (a, x, b, eye(), 100, 1e-7);

Implementation
class eye {
public:
eye() {}
template<class T> const vec<T>& operator* (const vec<T>& x) const { return x; }
template<class T> const vec<T>& solve (const vec<T>& x) const { return x; }
template<class T> const vec<T>& trans_solve (const vec<T>& x) const { x; }
};

5.23 solver - direct or interative solver interface


(Source file: skit/plib2/solver.h)

Description
The class implements a matrix factorization: LU factorization for an unsymmetric matrix
and Choleski fatorisation for a symmetric one.

98

Rheolef, the finite element system.

Let a be a square invertible matrix in csr format (see Section 5.19 [csr class], page 87).
csr<Float> a;
We get the factorization by:
solver<Float> sa (a);
Each call to the direct solver for a*x = b writes either:
vec<Float> x = sa.solve(b);
When the matrix is modified in a computation loop but conserves its sparsity pattern, an
efficient re-factorization writes:
sa.update_values (new_a);
x = sa.solve(b);
This approach skip the long step of the symbolic factization step.

Iterative solver
The factorization can also be incomplete, i.e. a pseudo-inverse, suitable for preconditionning
iterative methods. In that case, the sa.solve(b) call runs a conjugate gradient when the
matrix is symmetric, or a generalized minimum residual algorithm when the matrix is
unsymmetric.

Automatic choice and customization


The symmetry of the matrix is tested via the a.is symmetric() property (see Section 5.19
[csr class], page 87) while the choice between direct or iterative solver is switched from the
a.pattern dimension() value. When the pattern is 3D, an iterative method is faster and less
memory consuming. Otherwhise, for 1D or 2D problems, the direct method is prefered.
These default choices can be supersetted by using explicit options:
solver_option_type opt;
opt.iterative = true;
solver<Float> sa (a, opt);
See the solver.h header for the complete list of available options.

Implementation note
The implementation bases on the pastix library.

Implementation
template <class T, class M = rheo_default_memory_model>
class solver_basic : public smart_pointer<solver_rep<T,M> > {
public:
// typedefs:

Chapter 5: Classes

99

typedef solver_rep<T,M>
rep;
typedef smart_pointer<rep> base;
// allocator:

solver_basic ();
explicit solver_basic (const csr<T,M>& a, const solver_option_type& opt = solver_o
void update_values (const csr<T,M>& a);
// accessors:
vec<T,M> trans_solve (const vec<T,M>& b) const;
vec<T,M> solve
(const vec<T,M>& b) const;
};
// factorizations:
template <class T, class M>
solver_basic<T,M> ldlt(const csr<T,M>& a, const solver_option_type&
template <class T, class M>
solver_basic<T,M> lu (const csr<T,M>& a, const solver_option_type&
template <class T, class M>
solver_basic<T,M> ic0 (const csr<T,M>& a, const solver_option_type&
template <class T, class M>
solver_basic<T,M> ilu0(const csr<T,M>& a, const solver_option_type&

opt = solver_opt

opt = solver_opt

opt = solver_opt

opt = solver_opt

typedef solver_basic<Float> solver;

5.24 solver_abtb direct or iterative solver iterface for


mixed linear systems
(Source file: skit/plib2/solver_abtb.h)

Synopsis
solver_abtb stokes
(a,b,mp);
solver_abtb elasticity (a,b,c,mp);

Description
The solver_abtb class provides direct or iterative algorithms for some mixed problem:
[ A B^T ] [ u ]
[ Mf ]
[
] [
] = [
]
[ B -C ] [ p ]
[ Mg ]
where A is symmetric positive definite and C is symmetric positive. By default, iterative
algorithms are considered for tridimensional problems and direct methods otherwise. Such
mixed linear problems appears for instance with the discretization of Stokes problems. The

100

Rheolef, the finite element system.

C matrix can be zero and then the corresponding argument can be omitted when invoking
the constructor. Non-zero C matrix appears for of Stokes problems with stabilized P1-P1
element, or for nearly incompressible elasticity problems.

Direct algorithm
When the kernel of B^T is not reduced to zero, then the pressure p is defined up to a
constant and the system is singular. In the case of iterative methods, this is not a problem.
But when using direct method, the system is then completed to impose a constraint on the
pressure term and the whole matrix is factored one time for all.

Iterative algorithm
The preconditionned conjugate gradient algorithm is used, where the mp matrix is used as
preconditionner. See see Section 6.10 [mixed solver algorithm], page 117.

Examples
See the users manual for practical examples for the nearly incompressible elasticity, the
Stokes and the Navier-Stokes problems.

Implementation
template <class T, class M = rheo_default_memory_model>
class solver_abtb_basic {
public:
// typedefs:
typedef typename csr<T,M>::size_type size_type;
// allocators:
solver_abtb_basic ();
solver_abtb_basic (const csr<T,M>&
const solver_option_type& opt
solver_abtb_basic (const csr<T,M>&
const solver_option_type& opt

a, const csr<T,M>& b, const csr<T,M>& mp,


= solver_option_type());
a, const csr<T,M>& b, const csr<T,M>& c, const
= solver_option_type());

// accessors:

void solve (const vec<T,M>& f, const vec<T,M>& g, vec<T,M>& u, vec<T,M>& p) const;


protected:
// internal
void init();
// data:
mutable solver_option_type _opt;
csr<T,M>
_a;

Chapter 5: Classes

101

csr<T,M>
_b;
csr<T,M>
_c;
csr<T,M>
_mp;
solver_basic<T,M> _sA;
solver_basic<T,M> _sa;
solver_basic<T,M> _smp;
bool
_need_constraint;
};
typedef solver_abtb_basic<Float,rheo_default_memory_model> solver_abtb;

5.25 vec - vector in distributed environment


(Source file: skit/plib2/vec.h)

Synopsys
STL-like vector container for a sequential or distributed memory machine model. Additional
operation fom classical algebra.

Example
A sample usage of the class is:
int main(int argc, char**argv) {
environment distributed(argc, argv);
vec<double> x(100, 3.14);
dout << x << endl;
}

Implementation note
Implementation use array<T,M>.

Implementation
template <class T, class M = rheo_default_memory_model>
class vec : public array<T, M> {
public:
// typedef:
typedef array<T, M> base;
typedef typename base::size_type
typedef std::ptrdiff_t
#ifdef TODO
// pb compile avec boost sur foehn:
typedef typename base::difference_type
#endif // TODO
typedef basic_range<size_type, difference_type>

size_type;
difference_type;

difference_type;
range_type;

102

Rheolef, the finite element system.

typedef
typedef
typedef
typedef

typename
typename
typename
typename

base::reference
base::const_reference
base::iterator
base::const_iterator

reference;
const_reference;
iterator;
const_iterator;

// allocator/deallocator:
vec (const distributor& ownership,
const T& init_val = std::numeric_limits<T>::max());
vec(size_type dis_size = 0,
const T& init_val = std::numeric_limits<T>::max());
void resize (
const distributor& ownership,
const T& init_val = std::numeric_limits<T>::max());
void resize (
size_type size = 0,
const T& init_val = std::numeric_limits<T>::max());
// accessors:
const_reference operator[] (size_type i) const;
reference
operator[] (size_type i);
T max_abs () const;
// range:
vec(const
vec(const
vec<T,M>&
vec<T,M>&

vec_range<T,M>& vr);
vec_range_const<T,M>& vr);
operator= (const vec_range<T,M>& vr);
operator= (const vec_range_const<T,M>& vr);

vec_range_const<T,M> operator[] (const range_type& r) const;


vec_range<T,M>
operator[] (const range_type& r);
// assignment to a constant:
vec<T,M>& operator= (const int& expr);
vec<T,M>& operator= (const T& expr);
// expression template:
template<typename Expr>
vec (const vec_expr<Expr>& expr);
template<typename Expr>

Chapter 5: Classes

103

vec<T,M>& operator= (const vec_expr<Expr>& expr);


// initializer list (c++ 2011):

#ifdef _RHEOLEF_HAVE_STD_INITIALIZER_LIST
vec (const std::initializer_list<vec_concat_value<T,M> >& init_list);
vec<T,M>& operator= (const std::initializer_list<vec_concat_value<T,M> >& init_l
#endif // _RHEOLEF_HAVE_STD_INITIALIZER_LIST
};

5.26 irheostream, orheostream - large data streams


(Source file: util/lib/rheostream.h)

Abstract
This class provides a stream interface for large data management. File decompresion is
assumed using gzip and a recursive seach in a directory list is provided for input.
orheostream foo("NAME", "suffix");
is like
ofstream foo("NAME.suffix").
However, if NAME does not end with .suffix, then .suffix is added, and compression
is done with gzip, adding an additional .gz suffix.
Conversely,
irheostream foo("NAME","suffix");
is like
ifstream foo("NAME.suffix").
However, we look at a search path environment variable RHEOPATH in order to find NAME
while suffix is assumed. Moreover, gzip compressed files, ending with the .gz suffix is
assumed, and decompression is done.
Finally, a set of useful functions are provided.

Description
The following code:
irheostream is("results", "data");
will recursively look for a results[.data[.gz]] file in the directory mentionned by the
RHEOPATH environment variable.
For instance, if you insert in our ".cshrc" something like:

104

Rheolef, the finite element system.

setenv RHEOPATH ".:/home/dupont:/usr/local/math/demo"


the process will study the current directory ., then, if neither square.data.gz nor
square.data exits, it scan all subdirectory of the current directory. Then, if file is not
founded, it start recusively in /home/dupond and then in /usr/local/math/demo.
File decompression is performed by using the gzip command, and data are pipe-lined
directly in memory.
If the file start with . as ./square or with a / as /home/oscar/square, no search
occurs and RHEOPATH environment variable is not used.
Also, if the environment variable RHEOPATH is not set, the default value is the current
directory ..
For output stream:
orheostream os("newresults", "data");
file compression is assumed, and "newresults.data.gz" will be created.
File loading and storing are mentionned by a message, either:
! load "./results.data.gz"
or:
! file "./newresults.data.gz" created.
on the clog stream. By adding the following:
clog << noverbose;
you turn off these messages (see Section 8.1 [iorheo ialgorithm], page 169).

Implementation

class irheostream : public io::filtering_stream<io::input> {


public:
irheostream() : io::filtering_stream<io::input>() {}
irheostream(const std::string& name, const std::string& suffix = std::string());
virtual ~irheostream();
void open (const std::string& name, const std::string& suffix = std::string());
void close();
protected:
std::ifstream _ifs;
};
static const bool dont_gzip = false;
class orheostream : public io::filtering_stream<io::output> {
public:
orheostream() : io::filtering_stream<io::output>() {}
orheostream(const std::string& name, const std::string& suffix = std::string(),
bool use_gzip = true);
virtual ~orheostream();

Chapter 5: Classes

105

void open (const std::string& name, const std::string& suffix = std::string(),


bool use_gzip = true);
void flush();
void close();
protected:
std::ofstream _ofs;
bool
_use_gzip;
std::string
_full_name;
};
std::string itos (std::string::size_type i);
std::string ftos (const Float& x);
// catch first occurence of string in file
bool scatch (std::istream& in, const std::string& ch, bool full_match = true);
// has_suffix("toto.suffix", "suffix") -> true
bool has_suffix (const std::string& name, const std::string& suffix);
// "toto.suffix" --> "toto"
std::string delete_suffix (const std::string& name, const std::string& suffix);
// "/usr/local/dir/toto.suffix" --> "toto.suffix"
std::string get_basename (const std::string& name);
// "/usr/local/dir/toto.suffix" --> "/usr/local/dir"
std::string get_dirname (const std::string& name);

// "toto" --> "/usr/local/math/data/toto.suffix"


std::string get_full_name_from_rheo_path (const std::string& rootname, const std::st
// "." + "../geodir" --> ".:../geodir"
void append_dir_to_rheo_path (const std::string& dir);
// "../geodir" + "." --> "../geodir:."
void prepend_dir_to_rheo_path (const std::string& dir);
bool file_exists (const std::string& filename);
// string to float
bool is_float (const std::string&);
Float to_float (const std::string&);
// in TMPDIR environment variable or "/tmp" by default
std::string get_tmpdir();

106

Rheolef, the finite element system.

Chapter 6: Algorithms

107

6 Algorithms
6.1 adapt - mesh adaptation
(Source file: nfem/plib/adapt.h)

Synopsys
geo adapt (const field& phi); geo adapt (const field& phi, const adapt option type& opts);

Description
The function adapt implements the mesh adaptation procedure, based on the gmsh
(isotropic) or bamg (anisotropic) mesh generators. The bamg mesh generator is the default in two dimension. For dimension one or three, gmsh is the only generator supported
yet. In the two dimensional case, the gmsh correspond to the opts.generator="gmsh".
The strategy based on a metric determined from the Hessian of a scalar governing field,
denoted as phi, and that is supplied by the user. Let us denote by H=Hessian(phi) the
Hessian tensor of the field phi. Then, |H| denote the tensor that has the same eigenvector
as H, but with absolute value of its eigenvalues:
|H| = Q*diag(|lambda_i|)*Qt
The metric M is determined from |H|. Recall that an isotropic metric is such that
M(x)=hloc(x)^(-2)*Id where hloc(x) is the element size field and Id is the identity
d*d matrix, and d=1,2,3 is the physical space dimension.

Gmsh isotropic metric


max_(i=0..d-1)(|lambda_i(x)|)*Id
M(x) = ----------------------------------------err*hcoef^2*(sup_y(phi(y))-inf_y(phi(y)))
Notice that the denominator involves a global (absolute) normalization sup_y(phi(y))inf_y(phi(y)) of the governing field phi and the two parameters opts.err, the target
error, and opts.hcoef, a secondary normalization parameter (defaults to 1).

Bamg anisotropic metric


There are two approach for the normalization of the metric. The first one involves a global
(absolute) normalization:
|H(x))|
M(x) = ----------------------------------------err*hcoef^2*(sup_y(phi(y))-inf_y(phi(y)))
The first one involves a local (relative) normalization:

108

Rheolef, the finite element system.

|H(x))|
M(x) = ----------------------------------------err*hcoef^2*(|phi(x)|, cutoff*max_y|phi(y)|)
Notice that the denominator involves a local value phi(x). The parameter is provided by
the optional variable opts.cutoff; its default value is 1e-7. The default strategy is the local
normalization. The global normalization can be enforced by setting opts.additional="AbsError".
When choosing global or local normalization ?
When the governing field phi is bounded, i.e. when err*hcoef^2*(sup_y(phi(y))-inf_
y(phi(y))) will converge versus mesh refinement to a bounded value, the global normalization defines a metric that is mesh-independent and thus the adaptation loop will converge.
Otherwise, when phi presents singularities, with unbounded values (such as corner singularity, i.e. presents peacks when represented in elevation view), then the mesh adaptation
procedure is more difficult. The global normalization divides by quantities that can be very
large and the mesh adaptation can diverges when focusing on the singularities. In that
case, the local normalization is preferable. Moreover, the focus on singularities can also be
controled by setting opts.hmin not too small.
The local normalization has been choosen as the default since it is more robust. When your
field phi does not present singularities, then you can swith to the global numbering that
leads to a best equirepartition of the error over the domain.

Implementation

struct adapt_option_type {
typedef std::vector<int>::size_type size_type;
std::string generator;
bool isotropic;
Float err;
Float errg;
Float hcoef;
Float hmin;
Float hmax;
Float ratio;
Float cutoff;
size_type n_vertices_max;
size_type n_smooth_metric;
bool splitpbedge;
Float thetaquad;
Float anisomax;
bool clean;
std::string additional;
bool double_precision;
Float anglecorner; // angle below which bamg considers 2 consecutive edge to be
// the same spline
adapt_option_type() :
generator(""),

Chapter 6: Algorithms

109

isotropic(true), err(1e-2), errg(1e-1), hcoef(1), hmin(0.0001), hmax(0.3), r


n_vertices_max(50000), n_smooth_metric(1),
splitpbedge(true), thetaquad(std::numeric_limits<Float>::max()),
anisomax(1e6), clean(false), additional("-RelError"), double_precision(false
anglecorner(0)
{}
};
template <class T, class M>
geo_basic<T,M>
adapt (
const field_basic<T,M>& phi,
const adapt_option_type& options = adapt_option_type());

6.2 damped_newton damped Newton nonlinear algorithm


(Source file: nfem/plib/damped_newton.h)

Description
Nonlinear damped Newton algorithm for the resolution of the following problem:
F(u) = 0
A simple call to the algorithm writes:
my_problem P;
field uh (Vh);
damped_newton (P, uh, tol, max_iter);
In addition to the members required for the Newton algorithm (see Section 6.7 [newton
algorithm], page 113), the space_norm and duality_product are required for the damped
Newton line search algorithm:
class my_problem {
public:
...
Float space_norm
(const field& uh) const;
Float duality_product (const field& mrh, const field& msh) const;
};

Implementation

template <class Problem, class Field, class Real, class Size>


int damped_newton (Problem P, Field& u, Real& tol, Size& max_iter, odiststream* p_de
return damped_newton(P, newton_identity_preconditioner(), u, tol, max_iter, p_derr
}

110

Rheolef, the finite element system.

6.3 damped_newton damped Newton nonlinear algorithm


(Source file: nfem/plib/damped-newton.h)

Description
Nonlinear damped Newton algorithm for the resolution of the following problem:
F(u) = 0
A simple call to the algorithm writes:
my_problem P;
field uh (Vh);
damped_newton (P, uh, tol, max_iter);
In addition to the members required for the Newton algorithm (see Section 6.7 [newton
algorithm], page 113), the space_norm and duality_product are required for the damped
Newton line search algorithm:
class my_problem {
public:
...
Float space_norm
(const field& uh) const;
Float duality_product (const field& mrh, const field& msh) const;
};

Implementation

template <class Problem, class Field, class Real, class Size>


int damped_newton (Problem P, Field& u, Real& tol, Size& max_iter, odiststream* p_de
return damped_newton(P, newton_identity_preconditioner(), u, tol, max_iter, p_derr
}

6.4 integrate - integrate a function or an expression


(Source file: nfem/plib/integrate.h)

Description
Integrate an expression over a domain by using a quadrature formulae. There are three
main usages of the integrate function, depending upon the type of the expression. (i) When
the expression is a numerical one, it leads to a numerical value. (ii) When the expression
involves a symbolic test-function see Section 5.11 [test class], page 67, the result is a linear
form, represented by the field class. (iii) When the expression involves both symbolic
trial- and test-functions see Section 5.11 [test class], page 67, the result is a bilinear form,
represented by the field class.

Chapter 6: Algorithms

111

Synopsys
template <class T, class M, class Expr>
T integrate (const geo_basic<T,M>& omega, Expr expr,
quadrature_option_type qopt)
template <class T, class M, class Expr>
field integrate (const geo_basic<T,M>& omega, VFExpr expr,
quadrature_option_type qopt)
template <class T, class M, class Expr>
form integrate (const geo_basic<T,M>& omega, VFExpr expr,
form_option_type fopt)

Example
Float f (const point& x);
...
quadrature_option_type qopt;
Float value = integrate (omega, f, qopt);
field lh = integrate (omega, f*v, qopt);
The last argument specifies the quadrature formulae used for the computation of the integral. The expression can be any function, classs-function or any linear or nonlinear field
expression see Section 5.4 [field class], page 41.

Default arguments
In the case of a linear form, the domain is optional: by default it is the full domain definition
of the test function.
field l1h = integrate (f*v, qopt);
When the integration is perfomed on a subdomain, this subdomain simply replace the first
argument and a domain name could also be used:
field l2h = integrate (omega["boundary"], f*v, qopt);
field l3h = integrate ("boundary", f*v, qopt);
The quadrature formulae is required, except when a test and/or trial function is provided
in the expression to integrate. In that case, the quadrature formulae is deduced from the
space containing the test (or trial) function. When a test function is suppied, let k be
its polynomial degree. Then the default quadrature is choosen to be exact at least for
2*k+1 polynoms. When both a test and trial functions are suppied, let k1 and k2 be their
polynomial degrees. Then the default quadrature is choosen to be exact at least for k1+k2+1
polynoms. Also, when the expression is a constant, the quadrature function is optional: in
that case, the constant is also optional and the following call:
Float meas = integrate (omega);
is valid and returns the measure of the domain.

112

Rheolef, the finite element system.

6.5 interpolate - Lagrange interpolation of a function


(Source file: nfem/plib/interpolate.h)

Description
The function interpolation implements the Lagrange interpolation of a function or a
class-function.

Synopsys
template <class Function> field interpolate (const space& Xh, const Function& f);

Example
The following code compute the Lagrange interpolation pi_h_u of u(x).
Float u(const point& x);
...
geo omega("square");
space Xh (omega, "P1");
field pi_h_u = interpolate (Xh, u);

Advanced example
It is possible the replace the function u by a variable of the field type that represents a
picewise polynomial function: this invocation allows the reinterpolation of a field on another
mesh or with another approximation.
geo omega2 ("square2");
space X2h (omega2, "P1");
field uh2 = interpolate (X2h, pi_h_u);

Implementation
// TODO: un peu general... utiliser des specialisation des classes-fonctions:
//
function<Float(const point&)>
//
function<point(const point&)>
//
function<tensor(const point&)>
template <class T, class M, class Function>
inline
field_basic<T,M>
interpolate (const space_basic<T,M>& Xh, const Function& f)

6.6 level_set - compute a level set from a function


(Source file: nfem/plib/level_set.h)

Synopsys
geo level set (const field& fh);

Chapter 6: Algorithms

113

Description
Given a function fh defined in a domain Lambda, compute the level set defined by {x in
Lambda, fh(x) = 0}. This level set is represented by the geo class.

Options
The option class leve_set_option_type controls the slit of quadrilaterals into triangles for
tridimensional intersected surface and also the zero machine precision, epsilon.

Implementation
struct level_set_option_type {
bool split_to_triangle;
Float epsilon;
level_set_option_type()
: split_to_triangle(true),
epsilon(100*std::numeric_limits<Float>::epsilon())
{}
};
template <class T, class M>
geo_basic<T,M> level_set (
const field_basic<T,M>& fh,
const level_set_option_type& opt = level_set_option_type());

6.7 newton Newton nonlinear algorithm


(Source file: nfem/plib/newton.h)

Description
Nonlinear Newton algorithm for the resolution of the following problem:
F(u) = 0
A simple call to the algorithm writes:
my_problem P;
field uh (Vh);
newton (P, uh, tol, max_iter);
The my_problem class may contains methods for the evaluation of F (aka residue) and its
derivative:
class my_problem {
public:
my_problem();
field residue
(const field& uh) const;
Float dual_space_norm (const field& mrh) const;
void update_derivative (const field& uh) const;
field derivative_solve (const field& mrh) const;

114

Rheolef, the finite element system.

};
The dual_space_norm returns a scalar from the weighted residual field term mrh returned
by the residue function: this scalar is used as stopping criteria for the algorithm. The
update_derivative and derivative_solver members are called at each step of the Newton algorithm. See the example p_laplacian.h in the users documentation for more.

Implementation

template <class Problem, class Field>


int newton (Problem P, Field& uh, Float& tol, size_t& max_iter, odiststream *p_derr
if (p_derr) *p_derr << "# Newton:" << std::endl << "# n r" << std::endl << std::
for (size_t n = 0; true; n++) {
Field rh = P.residue(uh);
Float r = P.dual_space_norm(rh);
if (p_derr) *p_derr << n << " " << r << std::endl << std::flush;
if (r <= tol) { tol = r; max_iter = n; return 0; }
if (n == max_iter) { tol = r; return 1; }
P.update_derivative (uh);
Field delta_uh = P.derivative_solve (-rh);
uh += delta_uh;
}
}

6.8 riesz - approximate a Riesz representer


(Source file: nfem/plib/riesz.h)

Synopsys
template <class Function>
field riesz (const space& Xh, const Expr& expr,
quadrature_option_type qopt = default_value);
template <class Function>
field riesz (const space& Xh, const Expr& expr,
const geo& domain, quadrature_option_type qopt = default_value);

Note
This function has been now suppersetted by the integrate function see Section 6.4 [integrate algorithm], page 110. The old-fashioned code:
field l1h = riesz (Xh, f);
field l2h = riesz (Xh, f, "boundary");
writes now:
test v (Xh);
field l1h = integrate (f*v);

Chapter 6: Algorithms

115

field l2h = integrate ("boundary", f*v);


The riesz function is still present for backward compatibility purpose.

Description
Let f be any continuous function, its Riesz representer in the finite element space Xh on the
domain Omega is defind by:
/
|
dual(lh,vh) = |
f(x) vh(x) dx
|
/ Omega
for all vh in Xh, where dual denotes the duality between Xh and its dual. As Xh is a finite
dimensional space, its dual is identified as Xh and the duality product as the Euclidian one.
The Riesz representer is thus the lh field of Xh where its i-th degree of freedom is:
/
|
dual(lh,vh) = |
f(x) phi_i(x) dx
|
/ Omega
where phi i is the i-th basis function in Xh. The integral is evaluated by using a quadrature
formula. By default the quadrature formule is the Gauss one with the order equal to 2*k1 where $k is the polynomial degree in Xh. Alternative quadrature formula and order is
available by passing an optional variable to riesz.
The function riesz implements the approximation of the Riesz representer by using some
quadrature formula for the evaluation of the integrals. Its argument can be any function,
class-function or linear or nonlinear expressions mixing fields and continuous functions.

Example
The following code compute the Riesz representant, denoted by lh of f(x), and the integral
of f over the domain omega:
Float
...
space
field
Float

f(const point& x);


Xh (omega_h, "P1");
lh = riesz (Xh, f);
int_f = dual(lh, 1);

Options
An optional argument specifies the quadrature formula used for the computation of the
integral. The domain of integration is by default the mesh associated to the finite element
space. An alternative domain dom, e.g. a part of the boundary can be supplied as an extra
argument. This domain can be also a band associated to the banded level set method.

116

Rheolef, the finite element system.

Implementation
template <class T, class M, class Function>
field_basic<T,M>
riesz (
const space_basic<T,M>&
Xh,
const Function&
f,
const quadrature_option_type& qopt
= quadrature_option_type(quadrature_option_type::max_family,0))

Implementation
template <class T, class M, class Function>
field_basic<T,M>
riesz (
const space_basic<T,M>&
Xh,
const Function&
f,
const geo_basic<T,M>&
dom,
const quadrature_option_type& qopt
= quadrature_option_type(quadrature_option_type::max_family,0))

Implementation
template <class T, class M, class Function>
field_basic<T,M>
riesz (
const space_basic<T,M>&
Xh,
const Function&
f,
std::string
dom_name,
const quadrature_option_type& qopt
= quadrature_option_type(quadrature_option_type::max_family,0))

Implementation
template <class T, class M, class Function>
field_basic<T,M>
riesz (
const space_basic<T,M>&
Xh,
const Function&
f,
const band_basic<T,M>&
gh,
const quadrature_option_type& qopt
= quadrature_option_type(quadrature_option_type::max_family,0))

6.9 diag - get diagonal part of a matrix


(Source file: skit/plib2/diag.h)

Chapter 6: Algorithms

117

Description
This function get the diagonal part of a matrix.
csr<Float> a;
dia<Float> d = diag(a);

Todo
Build a csr matrix from a diagonal one or from a vector:
dia<Float>
csr<Float>
vec<Float>
csr<Float>

d;
a = diag(d);
u;
b = diag(u);

Implementation
template<class T, class M>
dia<T,M> diag (const csr<T,M>& a)

6.10 pcg_abtb, pcg_abtbc, pminres_abtb, pminres_abtbc


solvers for mixed linear problems
(Source file: skit/plib2/mixed_solver.h)

Synopsis
template <class Matrix, class Vector, class Solver, class Preconditioner, class
int pcg_abtb (const Matrix& A, const Matrix& B, Vector& u, Vector& p,
const Vector& Mf, const Vector& Mg, const Preconditioner& S1,
const Solver& inner_solver_A, Size& max_iter, Real& tol,
odiststream *p_derr = 0, std::string label = "pcg_abtb");

template <class Matrix, class Vector, class Solver, class Preconditioner, class
int pcg_abtbc (const Matrix& A, const Matrix& B, const Matrix& C, Vector& u, Vec
const Vector& Mf, const Vector& Mg, const Preconditioner& S1,
const Solver& inner_solver_A, Size& max_iter, Real& tol,
odiststream *p_derr = 0, std::string label = "pcg_abtbc");
The synopsis is the same with the pminres algorithm.

Examples
See the users manual for practical examples for the nearly incompressible elasticity, the
Stokes and the Navier-Stokes problems.

118

Rheolef, the finite element system.

Description
Preconditioned conjugate gradient algorithm on the pressure p applied to the stabilized
stokes problem:
[ A B^T ] [ u ]
[ Mf ]
[
] [
] = [
]
[ B -C ] [ p ]
[ Mg ]
where A is symmetric positive definite and C is symmetric positive and semi-definite. Such
mixed linear problems appears for instance with the discretization of Stokes problems with
stabilized P1-P1 element, or with nearly incompressible elasticity. Formaly u = inv(A)*(Mf
- B^T*p) and the reduced system writes for all non-singular matrix S1:
inv(S1)*(B*inv(A)*B^T)*p = inv(S1)*(B*inv(A)*Mf - Mg)
Uzawa or conjugate gradient algorithms are considered on the reduced problem. Here, S1 is
some preconditioner for the Schur complement S=B*inv(A)*B^T. Both direct or iterative
solvers for S1*q = t are supported. Application of inv(A) is performed via a call to a solver
for systems such as A*v = b. This last system may be solved either by direct or iterative
algorithms, thus, a general matrix solver class is submitted to the algorithm. For most
applications, such as the Stokes problem, the mass matrix for the p variable is a good S1
preconditioner for the Schur complement. The stoping criteria is expressed using the S1
matrix, i.e. in L2 norm when this choice is considered. It is scaled by the L2 norm of the
right-hand side of the reduced system, also in S1 norm.

6.11 pcg conjugate gradient algorithm.


(Source file: skit/plib2/pcg.h)

Synopsis
template <class Matrix, class Vector, class Preconditioner, class Real>
int pcg (const Matrix &A, Vector &x, const Vector &b,
const Preconditioner &M, int &max_iter, Real &tol, odiststream *p_derr=0);

Example
The simplest call to pcg has the folling form:
size_t max_iter = 100;
double tol = 1e-7;
int status = pcg(a, x, b, EYE, max_iter, tol, &derr);

Description
pcg solves the symmetric positive definite linear system Ax=b using the Conjugate Gradient
method.

Chapter 6: Algorithms

119

The return value indicates convergence within max iter (input) iterations (0), or no convergence within max iter iterations (1). Upon successful return, output arguments have the
following values:
x

approximate solution to Ax = b

max_iter

the number of iterations performed before the tolerance was reached

tol

the residual after the final iteration

Note

pcg is an iterative template routine.


pcg follows the algorithm described on p. 15 in
Templates for the solution of linear systems: building blocks for iterative methods, 2nd Edition, R. Barrett, M. Berry, T. F. Chan, J. Demmel, J. Donato, J. Dongarra, V. Eijkhout, R.
Pozo, C. Romine, H. Van der Vorst, SIAM, 1994, ftp.netlib.org/templates/templates.ps.
The present implementation is inspired from IML++ 1.2 iterative method library, http://math.nist.gov/im

Implementation

template <class Matrix, class Vector, class Vector2, class Preconditioner, class Rea
int pcg(const Matrix &A, Vector &x, const Vector2 &Mb, const Preconditioner &M,
Size &max_iter, Real &tol, odiststream *p_derr = 0, std::string label = "cg"
{
Vector b = M.solve(Mb);
Real norm2_b = dot(Mb,b);
if (norm2_b == Real(0)) norm2_b = 1;
Vector Mr = Mb - A*x;
Real norm2_r = 0;
if (p_derr) (*p_derr) << "[" << label << "] #iteration residue" << std::endl;
Vector p;
for (Size n = 0; n <= max_iter; n++) {
Vector r = M.solve(Mr);
Real prev_norm2_r = norm2_r;
norm2_r = dot(Mr, r);
if (p_derr) (*p_derr) << "[" << label << "] " << n << " " << ::sqrt(norm2_r/
if (norm2_r <= sqr(tol)*norm2_b) {
tol = ::sqrt(norm2_r/norm2_b);
max_iter = n;
return 0;
}
if (n == 0) {
p = r;
} else {
Real beta = norm2_r/prev_norm2_r;
p = r + beta*p;
}
Vector Mq = A*p;
Real alpha = norm2_r/dot(Mq, p);

120

Rheolef, the finite element system.

x += alpha*p;
Mr -= alpha*Mq;
}
tol = ::sqrt(norm2_r/norm2_b);
return 1;
}

6.12 pgmres generalized minimum residual method


(Source file: skit/plib2/pgmres.h)

Synopsis

template <class Matrix, class Vector, class Preconditioner,


class SmallMatrix, class SmallVector, class Real, class Size>
int pgmres (const Matrix &A, Vector &x, const Vector &b, const Preconditioner &M,
SmallMatrix &H, const SmallVector& dummy,
Size m, Size &max_iter, Real &tol);

Example
The simplest call to pgmres has the folling form:
double tol = 1e-7;
size_t max_iter = 100;
size_t m = 6;
boost::numeric::ublas::matrix<double> H(m+1,m+1);
vec<double,sequential> dummy;
int status = pgmres (a, x, b, ic0(a), H, dummy, m, max_iter, tol);

Description
pgmres solves the unsymmetric linear system Ax = b using the generalized minimum residual method.
The return value indicates convergence within max iter (input) iterations (0), or no convergence within max iter iterations (1). Upon successful return, output arguments have the
following values:
x

approximate solution to Ax = b

max_iter

the number of iterations performed before the tolerance was reached

tol

the residual after the final iteration

In addition, M specifies a preconditioner, H specifies a matrix to hold the coefficients of the


upper Hessenberg matrix constructed by the pgmres iterations, m specifies the number of
iterations for each restart.
pgmres requires two matrices as input, A and H. The matrix A, which will typically be
a sparse matrix) corresponds to the matrix in the linear system Ax=b. The matrix H,

Chapter 6: Algorithms

121

which will be typically a dense matrix, corresponds to the upper Hessenberg matrix H that
is constructed during the pgmres iterations. Within pgmres, H is used in a different way
than A, so its class must supply different functionality. That is, A is only accessed though
its matrix-vector and transpose-matrix-vector multiplication functions. On the other hand,
pgmres solves a dense upper triangular linear system of equations on H. Therefore, the class
to which H belongs must provide H(i,j) operator for element acess.

Note

It is important to remember that we use the convention that indices are 0-based. That
is H(0,0) is the first component of the matrix H. Also, the type of the matrix must be
compatible with the type of single vector entry. That is, operations such as H(i,j)*x(j) must
be able to be carried out.
pgmres is an iterative template routine.
pgmres follows the algorithm described on p. 20 in Templates for the solution of linear
systems: building blocks for iterative methods, 2nd Edition, R. Barrett, M. Berry, T. F.
Chan, J. Demmel, J. Donato, J. Dongarra, V. Eijkhout, R. Pozo, C. Romine, H. Van der
Vorst, SIAM, 1994, ftp.netlib.org/templates/templates.ps.
The present implementation is inspired from IML++ 1.2 iterative method library, http://math.nist.gov/im

Implementation
template <class SmallMatrix, class Vector, class SmallVector, class Size>
void
Update(Vector &x, Size k, SmallMatrix &h, SmallVector &s, Vector v[])
{
SmallVector y = s;
// Back solve:
for (int i = k; i >= 0; i--) {
y(i) /= h(i,i);
for (int j = i - 1; j >= 0; j--)
y(j) -= h(j,i) * y(i);
}
for (Size j = 0; j <= k; j++) {
x += v[j] * y(j);
}
}
template<class Real>
void GeneratePlaneRotation(Real &dx, Real &dy, Real &cs, Real &sn)
{
if (dy == Real(0)) {
cs = 1.0;
sn = 0.0;
} else if (abs(dy) > abs(dx)) {
Real temp = dx / dy;
sn = 1.0 / ::sqrt( 1.0 + temp*temp );
cs = temp * sn;
} else {

122

Rheolef, the finite element system.

Real temp = dy / dx;


cs = 1.0 / ::sqrt( 1.0 + temp*temp );
sn = temp * cs;
}
}
template<class Real>
void ApplyPlaneRotation(Real &dx, Real &dy, Real &cs, Real &sn)
{
Real temp = cs * dx + sn * dy;
dy = -sn * dx + cs * dy;
dx = temp;
}
template <class Matrix, class Vector, class Preconditioner,
class SmallMatrix, class SmallVector, class Real, class Size>
int
pgmres (const Matrix &A, Vector &x, const Vector &b, const Preconditioner &M,
SmallMatrix &H, const SmallVector&, const Size &m, Size &max_iter, Real &tol)
{
odiststream* p_derr = &derr;
std::string label = "pgmres";
if (p_derr) (*p_derr) << "[" << label << "] #iteration residue" << std::endl;
Vector w;
SmallVector s(m+1), cs(m+1), sn(m+1);
Size i;
Size j = 1;
Size k;
Real resid;
Real normb = norm(M.solve(b));
Vector r = M.solve(b - A * x);
Real beta = norm(r);
if (normb == Real(0)) {
normb = 1;
}
resid = norm(r) / normb;
if (resid <= tol) {
tol = resid;
max_iter = 0;
return 0;
}
Vector *v = new Vector[m+1];
while (j <= max_iter) {
v[0] = r * (1.0 / beta);
// ??? r / beta
s = 0.0;
s(0) = beta;
for (i = 0; i < m && j <= max_iter; i++, j++) {
w = M.solve(A * v[i]);
for (k = 0; k <= i; k++) {
H(k, i) = dot(w, v[k]);
w -= H(k, i) * v[k];

Chapter 6: Algorithms

123

}
H(i+1, i) = norm(w);
v[i+1] = w * (1.0 / H(i+1, i)); // ??? w / H(i+1, i)
for (k = 0; k < i; k++) {
ApplyPlaneRotation(H(k,i), H(k+1,i), cs(k), sn(k));
}
GeneratePlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
ApplyPlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
ApplyPlaneRotation(s(i), s(i+1), cs(i), sn(i));
resid = abs(s(i+1)) / normb;
if (p_derr) (*p_derr) << "[" << label << "] " << j << " " << resid << std::end
if (resid < tol) {
Update(x, i, H, s, v);
tol = resid;
max_iter = j;
delete [] v;
return 0;
}

}
Update(x, m - 1, H, s, v);
r = M.solve(b - A * x);
beta = norm(r);
resid = beta / normb;
if (p_derr) (*p_derr) << "[" << label << "] " << j << " " << resid << std::endl;
if (resid < tol) {
tol = resid;
max_iter = j;
delete [] v;
return 0;
}
}
tol = resid;
delete [] v;
return 1;
}

6.13 pminres conjugate gradient algorithm.


(Source file: skit/plib2/pminres.h)

Synopsis

template <class Matrix, class Vector, class Preconditioner, class Real>


int pminres (const Matrix &A, Vector &x, const Vector &b, const Preconditioner &
int &max_iter, Real &tol, odiststream *p_derr=0);

Example
The simplest call to pminres has the folling form:

124

Rheolef, the finite element system.

size_t max_iter = 100;


double tol = 1e-7;
int status = pminres(a, x, b, EYE, max_iter, tol, &derr);

Description
pminres solves the symmetric positive definite linear system Ax=b using the Conjugate
Gradient method.
The return value indicates convergence within max iter (input) iterations (0), or no convergence within max iter iterations (1). Upon successful return, output arguments have the
following values:
x

approximate solution to Ax = b

max_iter

the number of iterations performed before the tolerance was reached

tol

the residual after the final iteration

Note
pminres follows the algorithm described in "Solution of sparse indefinite systems of linear equations", C. C. Paige and M. A. Saunders, SIAM J. Numer. Anal., 12(4), 1975.
For more, see http://www.stanford.edu/group/SOL/software.html and also the PhD "Iterative methods for singular linear equations and least-squares problems", S.-C. T. Choi,
Stanford University, 2006, http://www.stanford.edu/group/SOL/dissertations/sou-chengchoi-thesis.pdf at page 60. The present implementation style is inspired from IML++ 1.2
iterative method library, http://math.nist.gov/iml++.

Implementation
template <class Matrix, class Vector, class Preconditioner, class Real, class Size>
int pminres(const Matrix &A, Vector &x, const Vector &Mb, const Preconditioner &M,
Size &max_iter, Real &tol, odiststream *p_derr = 0, std::string label = "minres")
{
Vector b = M.solve(Mb);
Real norm_b = sqrt(fabs(dot(Mb,b)));
if (norm_b == Real(0.)) norm_b = 1;
Vector Mr = Mb - A*x;
Vector z = M.solve(Mr);
Real beta2 = dot(Mr, z);
Real norm_r = sqrt(fabs(beta2));
if (p_derr) (*p_derr) << "[" << label << "] #iteration residue" << std::endl;
if (p_derr) (*p_derr) << "[" << label << "] 0 " << norm_r/norm_b << std::endl;
if (beta2 < 0 || norm_r <= tol*norm_b) {
tol = norm_r/norm_b;
max_iter = 0;
dis_warning_macro ("beta2 = " << beta2 << " < 0: stop");
return 0;

Chapter 6: Algorithms

}
Real beta = sqrt(beta2);
Real eta = beta;
Vector Mv = Mr/beta;
Vector u = z/beta;
Real c_old = 1.;
Real s_old = 0.;
Real c = 1.;
Real s = 0.;
Vector u_old (x.ownership(), 0.);
Vector Mv_old (x.ownership(), 0.);
Vector w
(x.ownership(), 0.);
Vector w_old (x.ownership(), 0.);
Vector w_old2 (x.ownership(), 0.);
for (Size n = 1; n <= max_iter; n++) {
// Lanczos
Mr = A*u;
z = M.solve(Mr);
Real alpha = dot(Mr, u);
Mr = Mr - alpha*Mv - beta*Mv_old;
z = z - alpha*u - beta*u_old;
beta2 = dot(Mr, z);
if (beta2 < 0) {
dis_warning_macro ("pminres: machine precision problem");
tol = norm_r/norm_b;
max_iter = n;
return 2;
}
Real beta_old = beta;
beta = sqrt(beta2);
// QR factorisation
Real c_old2 = c_old;
Real s_old2 = s_old;
c_old = c;
s_old = s;
Real rho0 = c_old*alpha - c_old2*s_old*beta_old;
Real rho2 = s_old*alpha + c_old2*c_old*beta_old;
Real rho1 = sqrt(sqr(rho0) + sqr(beta));
Real rho3 = s_old2 * beta_old;
// Givens rotation
c = rho0 / rho1;
s = beta / rho1;
// update
w_old2 = w_old;
w_old = w;
w = (u - rho2*w_old - rho3*w_old2)/rho1;
x += c*eta*w;
eta = -s*eta;
Mv_old = Mv;

125

126

Rheolef, the finite element system.

u_old = u;
Mv = Mr/beta;
u = z/beta;
// check residue
norm_r *= s;
if (p_derr) (*p_derr) << "[" << label << "] " << n << " " << norm_r/norm_b << st
if (norm_r <= tol*norm_b) {
tol = norm_r/norm_b;
max_iter = n;
return 0;
}
}
tol = norm_r/norm_b;
return 1;
}

6.14 puzawa Uzawa algorithm.


(Source file: skit/plib2/puzawa.h)

Synopsis

template <class Matrix, class Vector, class Preconditioner, class Real>


int puzawa (const Matrix &A, Vector &x, const Vector &b, const Preconditioner &M
int &max_iter, Real &tol, const Real& rho, odiststream *p_derr=0);

Example
The simplest call to puzawa has the folling form:
size_t max_iter = 100;
double tol = 1e-7;
int status = puzawa(A, x, b, EYE, max_iter, tol, 1.0, &derr);

Description
puzawa solves the linear system A*x=b using the Uzawa method. The Uzawa method is
a descent method in the direction opposite to the gradient, with a constant step length
rho. The convergence is assured when the step length rho is small enough. If matrix A
is symmetric positive definite, please uses pcg that computes automatically the optimal
descdnt step length at each iteration.
The return value indicates convergence within max iter (input) iterations (0), or no convergence within max iter iterations (1). Upon successful return, output arguments have the
following values:
x

approximate solution to Ax = b

max_iter

the number of iterations performed before the tolerance was reached

tol

the residual after the final iteration

Chapter 6: Algorithms

127

Implementation

template < class Matrix, class Vector, class Preconditioner, class Real, class Size>
int puzawa(const Matrix &A, Vector &x, const Vector &Mb, const Preconditioner &M,
Size &max_iter, Real &tol, const Real& rho,
odiststream *p_derr, std::string label)
{
Vector b = M.solve(Mb);
Real norm2_b = dot(Mb,b);
Real norm2_r = norm2_b;
if (norm2_b == Real(0)) norm2_b = 1;
if (p_derr) (*p_derr) << "[" << label << "] #iteration residue" << std::endl;
for (Size n = 0; n <= max_iter; n++) {
Vector Mr = A*x - Mb;
Vector r = M.solve(Mr);
norm2_r = dot(Mr, r);
if (p_derr) (*p_derr) << "[" << label << "] " << n << " " << sqrt(norm2_r/no
if (norm2_r <= sqr(tol)*norm2_b) {
tol = sqrt(norm2_r/norm2_b);
max_iter = n;
return 0;
}
x -= rho*r;
}
tol = sqrt(norm2_r/norm2_b);
return 1;
}

6.15 catchmark - iostream manipulator


(Source file: util/lib/catchmark.h)

Description
The catchmark is used for building labels used for input-output of vector-valued fields (see
Section 5.4 [field class], page 41):
cin >> catchmark("f")
>> fh;
cout << catchmark("u")
<< uh
<< catchmark("w")
<< wh
<< catchmark("psi") << psih;
Assuming its value for output is "u", the corresponding labels will be "#u0", "#u1", "#u2",
...

Implementation
class catchmark {
public:
catchmark(const std::string& x);

128

Rheolef, the finite element system.

const std::string& mark() const { return _mark; }


friend std::istream& operator >> (std::istream& is, const catchmark& m);
friend std::ostream& operator << (std::ostream& os, const catchmark& m);
protected:
std::string _mark;
};

Chapter 7: Internal classes

129

7 Internal classes
7.1 basis - polynomial basis
(Source file: nfem/plib/basis.h)

Synopsys
The basis class defines functions that evaluates a polynomial basis and its derivatives on a
point. The polynomial basis is designated by a string, e.g. "P0", "P1", "P2", "bubble",...
indicating the basis. The basis depends also of the reference element: triangle, square,
tetrahedron (see Section 7.15 [reference element iclass], page 149). For instance, on a square,
the "P1" string designates the common Q1 four-nodes basis on the reference square.
The nodes associated to the Lagrange polynomial basis are also available by its associated
accessor.

Implementation note
The basis class is a see Section 7.21 [smart pointer iclass], page 159) class on a basis_rep
class that is a pure virtual base class for effective bases, e.g. basis P1, basis P1, etc.

Implementation
template<class T>
class basis_basic : public smart_pointer<basis_rep<T> > {
public:
// typedefs:
typedef basis_rep<T>
typedef smart_pointer<rep>
typedef typename basis_rep<T>::size_type

rep;
base;
size_type;

// allocators:
basis_basic (std::string name = "");
// accessors:
std::string name() const;
size_type
degree() const;
size_type
size (reference_element hat_K) const;
void hat_node(
reference_element
std::vector<point_basic<T> >&
void hat_node(
reference_element

hat_K,
hat_node) const;
hat_K,

130

Rheolef, the finite element system.

typename std::vector<point_basic<T> >::iterator hat_node) const;


void eval(
reference_element
hat_K,
const point_basic<T>& hat_x,
std::vector<T>&
values) const;
void eval(
reference_element
hat_K,
const point_basic<T>&
hat_x,
typename std::vector<T>::iterator values) const;
void grad_eval(
reference_element
hat_K,
const point_basic<T>&
hat_x,
std::vector<point_basic<T> >& values) const;
void grad_eval(
reference_element
hat_K,
const point_basic<T>&
hat_x,
typename std::vector<point_basic<T> >::iterator values) const;
};
typedef basis_basic<Float> basis;

7.2 domain_indirect - a named part of a finite element mesh


(Source file: nfem/plib/domain_indirect.h)

Description
The domain_indirect class defines a container for a part of a finite element mesh. This
describes the connectivity of edges or faces. This class is usefull for boundary condition
setting.

Implementation note
The domain class is splitted into two parts. The first one is the domain_indirect class,
that contains the main renumbering features: it acts as a indirect on a geo class(see Section 5.9 [geo class], page 55). The second one is the domain class, that simply contains
two smart pointers: one on a domain_indirect and the second on the geo where renumbering is acting. Thus, the domain class develops a complete geo-like interface, via the
geo_abstract_rep pure virtual class derivation, and can be used by the space class (see
Section 5.10 [space class], page 63). The split between domain indirect and domain is necessary, because the geo class contains a list of domain indirect. It cannot contains a list
of domain classes, that refers to the geo class itself: a loop in reference counting leads to a
blocking situation in the automatic deallocation.

Implementation

template <>
class domain_indirect_basic<sequential> : public smart_pointer<domain_indirect_rep<s

Chapter 7: Internal classes

131

public:
// typedefs:
typedef
typedef
typedef
typedef
typedef

domain_indirect_rep<sequential> rep;
smart_pointer<rep>
base;
rep::size_type
size_type;
rep::iterator_ioige
iterator_ioige;
rep::const_iterator_ioige const_iterator_ioige;

// allocators:
domain_indirect_basic ();
template <class T>
domain_indirect_basic (
const geo_basic<T,sequential>&
const std::string&
size_type
const communicator&
const std::vector<size_type>&

omega,
name,
map_dim,
comm,
ie_list);

template <class U>


domain_indirect_basic (
array<geo_element_auto<heap_allocator<size_type> >,sequential, heap_allocato
d_tmp,
const geo_basic<U, sequential>& omega,
std::vector<index_set>*
ball);
void resize (size_type n);
// accessors:
size_type size()
const;
size_type dis_size() const;
const distributor& ownership() const;
const_iterator_ioige
const_iterator_ioige
iterator_ioige
iterator_ioige

ioige_begin() const;
ioige_end()
const;
ioige_begin();
ioige_end();

const geo_element_indirect& oige (size_type ioige) const;


void set_name (std::string name);
void set_map_dimension (size_type map_dim);
std::string name ()
const;
size_type map_dimension () const;

132

Rheolef, the finite element system.

// i/o:

odiststream& put (odiststream&) const;


template <class T>
idiststream& get (idiststream& ips, const geo_rep<T,sequential>& omega, std::vec
};

Implementation

template <>
class domain_indirect_basic<distributed> : public smart_pointer<domain_indirect_rep<
public:
// typedefs:
typedef domain_indirect_rep<distributed> rep;
typedef smart_pointer<rep>
base;
typedef rep::size_type
size_type;
// allocators:
domain_indirect_basic ();
template<class T>
domain_indirect_basic (
const geo_basic<T,distributed>& omega,
const std::string&
name,
size_type
map_dim,
const communicator&
comm,
const std::vector<size_type>& ie_list);
// accessors/modifiers:
size_type size()
const;
size_type dis_size() const;
const distributor& ownership() const;
const geo_element_indirect& oige (size_type ioige) const;
void set_name (std::string name);
void set_map_dimension (size_type map_dim);
std::string name () const;
size_type map_dimension () const;
// distributed specific acessors:
const distributor& ini_ownership() const;
size_type ioige2ini_dis_ioige (size_type ioige) const;
size_type ini_ioige2dis_ioige (size_type ini_ioige) const;

Chapter 7: Internal classes

133

// i/o:
template <class T>
idiststream& get (idiststream& ips, const geo_rep<T,distributed>& omega);
template <class T>
odiststream& put (odiststream& ops, const geo_rep<T,distributed>& omega) const;
};

7.3 form_element - bilinear form on a single element


(Source file: nfem/plib/form_element.h)

Synopsys
The form_element class defines functions that compute a bilinear form defined between
two polynomial basis on a single geometrical element. This bilinear form is represented by
a matrix.
The bilinear form is designated by a string, e.g. "mass", "grad grad", ... indicating the
form. The form depends also of the geometrical element: triangle, square, tetrahedron (see
Section 7.8 [geo element iclass], page 137).

Implementation note
The form_element class is managed by (see Section 7.21 [smart pointer iclass], page 159).
This class uses a pointer on a pure virtual class form_element_rep while the effective code
refers to the specific concrete derived classes: mass, grad grad, etc.

Implementation
template <class T, class M>
class form_element : public smart_pointer<form_element_rep<T,M> > {
public:
// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef
typedef

form_element_rep<T,M>
smart_pointer<rep>
typename rep::size_type
typename rep::vertex_type
typename rep::space_type
typename rep::geo_type
typename rep::coordinate_type

// constructors:
form_element ();
form_element (
std::string
const space_type&

name,
X,

rep;
base;
size_type;
vertex_type;
space_type;
geo_type;
coordinate_type;

134

Rheolef, the finite element system.

const space_type&
Y,
const geo_type&
omega,
const quadrature_option_type& qopt);
form_element (
std::string
name,
const space_type&
X,
const space_type&
Y,
const geo_type&
omega,
const geo_type&
subdomain,
const quadrature_option_type& qopt);
// accessors & modifier:

void operator() (const geo_element& K, ublas::matrix<T>& m) const;


bool is_symmetric () const;
void first_dis_idof (const geo_element& K, std::vector<size_type>& dis_idy) con
void second_dis_idof (const geo_element& K, std::vector<size_type>& dis_jdx) con
size_type first_subgeo_dimension() const;
size_type second_subgeo_dimension() const;
// for scalar-weighted forms:
void set_weight (const field_basic<T,M>& wh) const;
template<class Function>
void set_weight (Function w) const;
template<class Function>
void set_weight (
const Function&
w_expr,
const geo_basic<T,M>&
w_omega) const;
bool is_weighted() const;
// for banded level set method:
bool is_on_band() const;
const band_basic<T,M>& get_band() const;
void set_band (const band_basic<T,M>& bh) const;
};

7.4 geo_domain - a named part of a finite element mesh that


behaves as a mesh
(Source file: nfem/plib/geo_domain.h)

Description
The geo_domain class defines a container for a part of a finite element mesh. This class
re-describes the vertices, edges or faces in a compact way, i.e. by skipping unused elements
from the surrounding mesh.

Chapter 7: Internal classes

135

Implementation note
The geo_domain class conserves the link to the original mesh such that fields defined on a
geo_domain can inter-operate with fields defined on the surrounding mesh.

7.5 geo_domain_indirect_rep - a named part of a finite


element mesh
(Source file: nfem/plib/geo_domain_indirect.h)

Description
The geo_domain_indirect_rep class defines a container for a part of a finite element mesh.
This describes the connectivity of edges or faces. This class is usefull for boundary condition
setting.

Implementation note
The geo_domain_indirect_rep class is splitted into two parts. The first one is the domain_
indirect class, that contains the main renumbering features: it acts as an indirection on a
geo class(see Section 5.9 [geo class], page 55). The second one is the geo class itself, named
here the background geo. Thus, the geo_domain_indirect class develops a complete geolike interface, via the geo_abstract_rep pure virtual class derivation, and can be used by
the space class (see Section 5.10 [space class], page 63).
The split between domain_indirect and geo_domain_indirect is necessary, because the
geo class contains a list of domain indirect. The geo class cannot contains a list of geo_
domain_indirect classes, that refers to the geo class itself: a loop in reference counting
leads to a blocking situation in the automatic deallocation.

7.6 numbering - global degree of freedom numbering


(Source file: nfem/plib/numbering.h)

Synopsys
The numbering class defines methods that furnish global numbering of degrees of freedom.
This numbering depends upon the degrees of polynoms on elements and upon the continuity
requirement at inter-element boundary. For instance the "P1" continuous finite element
approximation has one degree of freedom per vertice of the mesh, while its discontinuous
counterpart has dim(basis) times the number of elements of the mesh, where dim(basis) is
the size of the local finite element basis.

Implementation
template <class T, class M = rheo_default_memory_model>
class numbering : public smart_pointer<numbering_rep<T,M> > {
public:

136

Rheolef, the finite element system.

// typedefs:
typedef numbering_rep<T,M> rep;
typedef smart_pointer<rep> base;
typedef size_t
size_type;
// allocators:
numbering (std::string name = "");
numbering (numbering_rep<T,M>* ptr);
~numbering() {}
// accessors & modifiers:
bool is_initialized() const { return base::operator->() != 0; }
std::string name() const;
size_type degree () const;
void set_degree (size_type degree) const;
bool is_continuous()
const;
bool is_discontinuous() const { return !is_continuous(); }
bool has_compact_support_inside_element()
const;
const basis_basic<T>& get_basis() const { return base::data().get_basis(); }

size_type
ndof
(const geo_size& gs, size_type map_dim) const;
size_type dis_ndof
(const geo_size& gs, size_type map_dim) const;
void
dis_idof
(const geo_size& gs, const geo_element& K, std::vector<size_t
void set_ios_permutations (const class geo_basic<T,M>& omega,
array<size_type,M>&
idof2ios_dis_idof,
array<size_type,M>&
ios_idof2dis_idof) const;
// comparator:
bool operator== (const numbering<T,M>& y) const {
if (! is_initialized() && ! y.is_initialized()) return true;
if (! is_initialized() || ! y.is_initialized()) return false;
return name() == y.name();
}
// i/o:
void dump(std::ostream& out = std::cerr) const;
};

7.7 edge - Edge reference element


(Source file: nfem/geo_element/edge.icc)

Description
The edge reference element is K = [0,1].

Chapter 7: Internal classes

137

0---------1
x
Curved high order Pk edges (k >= 1), in 2d or 3d geometries, are supported. These edges
have internal nodes, numbered as:
0----2----1
0--2--3--1
0-2-3-4-1
P2
P3
P4

Implementation
const
const
const
const

size_t dimension = 1;
size_t measure = 1;
size_t n_vertex = 2;
point vertex [n_vertex] = {
point(0),
point(1) };

7.8 geo_element - element of a mesh


(Source file: nfem/geo_element/geo_element_v4.h)

Description
Defines geometrical elements and sides as a set of vertice and edge indexes. This element
is obtained after a Piola transformation from a reference element (see Section 7.15 [reference element iclass], page 149). Indexes are related to arrays of edges and vertices. These
arrays are included in the description of the mesh. Thus, this class is related of a given
mesh instance (see Section 5.9 [geo class], page 55).

Example
This is the test of geo element:
geo_element_auto<> K;
K.set_name(t) ;
cout << "n_vertices: " << K.size()
<< endl
<< "n_edges
: " << K.n_edges()
<< endl
<< "dimension : " << K.dimension() << endl << endl;
for(geo_element::size_type i = 0; i < K.size(); i++)
K[i] = i*10 ;
for(geo_element::size_type i = 0; i < K.n_edges(); i++)
K.set_edge(i, i*10+5) ;
cout << "vertices: local -> global" << endl;
for (geo_element::size_type vloc = 0; vloc < K.size(); vloc++)
cout << vloc << "-> " << K[vloc] << endl;
cout << endl
<< "edges: local -> global" << endl;
for (geo_element::size_type eloc = 0; eloc < K.n_edges(); eloc++) {
geo_element::size_type vloc1 = subgeo_local_vertex(1, eloc, 0);
geo_element::size_type vloc2 = subgeo_local_vertex(1, eloc, 1);
cout << eloc << "-> " << K.edge(eloc) << endl

138

Rheolef, the finite element system.

<< "local_vertex_from_edge(" << eloc


<< ") -> (" << vloc1 << ", " << vloc2 << ")" << endl;
}

7.9 hack array - container in distributed environment


(Source file: nfem/geo_element/hack_array.h)

Synopsys
STL-like vector container for a distributed memory machine model. Contrarily to array<T>,
here T can have a size only known at compile time. This class is used when T is a geo element
raw class, i.e. T=geo element e raw. The size of the geo element depends upon the oder and
is known only at run-time. For efficiency purpose, the hack array allocate all geo elements
of the same variant (e.g. edge) and order in a contiguous area, since the coreesponding
element size is constant.

Example
A sample usage of the class is:
std::pair<size_t,size_t> param (reference_element::t, 3); // triangle, order=3
hack_array<geo_element_raw> x (distributor(100), param);
The hack array<T> interface is similar to those of the array<T> one.

Object requirement
There are many pre-requises for the template objet type T:
class T : public T::generic_type {
typedef variant_type;
typedef raw_type;
typedef genetic_type;
typedef automatic_type;
static const variant_type _variant;
static size_t _data_size(const parameter_type& param);
static size_t _value_size(const parameter_type& param);
};
class T::automatic_type : public T::generic_type {
automatic_type (const parameter_type& param);
};
class T::generic_type {
typedef raw_type;
typedef iterator;
typedef const_iterator;
iterator _data_begin();
const_iterator _data_begin() const;
};
ostream& operator<< (ostream&, const T::generic_type&);

Chapter 7: Internal classes

139

Implementation
template <class T, class A>
class hack_array<T,sequential,A> : public smart_pointer<hack_array_seq_rep<T,A> > {
public:
// typedefs:
typedef hack_array_seq_rep<T,A>
typedef smart_pointer<rep>
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

rep;
base;

sequential
typename rep::size_type
typename rep::value_type
typename rep::reference
typename rep::dis_reference
typename rep::iterator
typename rep::const_reference
typename rep::const_iterator
typename rep::parameter_type

memory_type;
size_type;
value_type;
reference;
dis_reference;
iterator;
const_reference;
const_iterator;
parameter_type;

// allocators:
hack_array (const A& alloc = A());
hack_array (size_type loc_size,
const parameter_type& param, const A&
void resize
(const distributor& ownership, const parameter_type& param);
hack_array (const distributor& ownership, const parameter_type& param, const A&
void resize
(size_type loc_size,
const parameter_type& param);
// local accessors & modifiers:
A get_allocator() const
size_type
size () const
size_type dis_size () const
const distributor& ownership() const
const communicator& comm() const

{
{
{
{
{

return
return
return
return
return

base::data().get_allocator(); }
base::data().size(); }
base::data().dis_size(); }
base::data().ownership(); }
ownership().comm(); }

reference
operator[] (size_type i)
{ return base::data().operator[]
const_reference operator[] (size_type i) const { return base::data().operator[]
const_reference dis_at (size_type dis_i) const { return base::data().operator[]
iterator
const_iterator
iterator
const_iterator

begin()
begin() const
end()
end() const

{
{
{
{

return
return
return
return

base::data().begin(); }
base::data().begin(); }
base::data().end(); }
base::data().end(); }

// global accessors (for compatibility with distributed interface):

140

Rheolef, the finite element system.

template<class Set> void append_dis_indexes (const Set& ext_idx_set) const {}


void update_dis_entries() const {}
// global modifiers (for compatibility with distributed interface):
dis_reference dis_entry (size_type dis_i) { return operator[] (dis_i); }
void dis_entry_assembly()
{}
template<class SetOp>
void dis_entry_assembly(SetOp my_set_op)
{}
template<class SetOp>
void dis_entry_assembly_begin (SetOp my_set_op) {}
template<class SetOp>
void dis_entry_assembly_end (SetOp my_set_op)
{}
// apply a partition:

#ifdef TODO
template<class RepSize>
void repartition (
// old_numbering for *this
const RepSize&
partition,
// old_ownership
hack_array<T,sequential,A>& new_array,
// new_ownership (created)
RepSize&
old_numbering,
// new_ownership
RepSize&
new_numbering) const // old_ownership
{ return base::data().repartition (partition, new_array, old_numbering, new_

template<class RepSize>
void permutation_apply (
// old_numbering for *this
const RepSize&
new_numbering,
// old_ownership
hack_array<T,sequential,A>& new_array) const
// new_ownership (already al
{ return base::data().permutation_apply (new_numbering, new_array); }
#endif // TODO
// i/o:

odiststream& put_values (odiststream& ops) const { return base::data().put_value


idiststream& get_values (idiststream& ips)
{ return base::data().get_value
template <class GetFunction>
idiststream& get_values (idiststream& ips, GetFunction get_element)
{ retu
template <class PutFunction>
odiststream& put_values (odiststream& ops, PutFunction put_element) const { retu
#ifdef TODO
void dump (std::string name) const { return base::data().dump(name); }
#endif // TODO
};

Implementation

template <class T, class A>


class hack_array<T,distributed,A> : public smart_pointer<hack_array_mpi_rep<T,A> > {

Chapter 7: Internal classes

141

public:
// typedefs:
typedef hack_array_mpi_rep<T,A>
typedef smart_pointer<rep>
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

rep;
base;

distributed
memory_type;
typename rep::size_type
size_type;
typename rep::value_type
value_type;
typename rep::reference
reference;
typename rep::dis_reference
dis_reference;
typename rep::iterator
iterator;
typename rep::parameter_type parameter_type;
typename rep::const_reference const_reference;
typename rep::const_iterator const_iterator;
typename rep::scatter_map_type scatter_map_type;

// allocators:
hack_array (const A& alloc = A());
hack_array (const distributor& ownership, const parameter_type& param, const A&
void resize
(const distributor& ownership, const parameter_type& param);
// local accessors & modifiers:
A get_allocator() const
size_type
size () const
size_type dis_size () const
const distributor& ownership() const
const communicator& comm() const

{
{
{
{
{

return
return
return
return
return

base::data().get_allocator(); }
base::data().size(); }
base::data().dis_size(); }
base::data().ownership(); }
base::data().comm(); }

reference
operator[] (size_type i)
{ return base::data().operator[]
const_reference operator[] (size_type i) const { return base::data().operator[]
iterator
const_iterator
iterator
const_iterator

begin()
begin() const
end()
end() const

{
{
{
{

return
return
return
return

base::data().begin(); }
base::data().begin(); }
base::data().end(); }
base::data().end(); }

// global accessor:

template<class Set, class Map>


void append_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const { base::d

template<class Set, class Map>


void get_dis_entry
(const Set& ext_idx_set, Map& ext_idx_map) const { base::d
template<class Set>

142

Rheolef, the finite element system.

void append_dis_indexes (const Set& ext_idx_set) const { base::data().append_dis


template<class Set>
void set_dis_indexes

(const Set& ext_idx_set)

{ base::data().set_dis_indexes

const_reference dis_at (size_type dis_i) const { return base::data().dis_at (dis

// get all external pairs (dis_i, values):


const scatter_map_type& get_dis_map_entries() const { return base::data().get_di
void update_dis_entries() const { base::data().update_dis_entries(); }
// global modifiers (for compatibility with distributed interface):
dis_reference dis_entry (size_type dis_i)

{ return base::data().dis_entry(

void dis_entry_assembly()

{ return base::data().dis_entry_

template<class SetOp>
void dis_entry_assembly
(SetOp my_set_op) { return base::data().dis_entry_
template<class SetOp>
void dis_entry_assembly_begin (SetOp my_set_op) { return base::data().dis_entry_
template<class SetOp>
void dis_entry_assembly_end
(SetOp my_set_op) { return base::data().dis_entry_
// apply a partition:

template<class RepSize>
void repartition (
// old_numbering for *this
const RepSize&
partition,
// old_ownership
hack_array<T,distributed>& new_array,
// new_ownership (created)
RepSize&
old_numbering,
// new_ownership
RepSize&
new_numbering) const // old_ownership
{ return base::data().repartition (partition.data(), new_array.data(), old_n

#ifdef TODO
template<class RepSize>
void permutation_apply (
// old_numbering for *this
const RepSize&
new_numbering,
// old_ownership
hack_array<T,distributed,A>& new_array) const
// new_ownership (already al
{ base::data().permutation_apply (new_numbering.data(), new_array.data()); }

void reverse_permutation (
// old_ownership for
hack_array<size_type,distributed,A>& inew2dis_iold) const
// new_ownership
{ base::data().reverse_permutation (inew2dis_iold.data()); }
#endif // TODO
// i/o:

Chapter 7: Internal classes

143

odiststream& put_values (odiststream& ops) const { return base::data().put_value


idiststream& get_values (idiststream& ips)
{ return base::data().get_value
#ifdef TODO
void dump (std::string name) const
{ return base::data().dump(name); }
#endif // TODO
template <class GetFunction>
idiststream& get_values (idiststream& ips, GetFunction get_element)
{ return base::data().get_values(ips, get_element); }
template <class PutFunction>
odiststream& put_values (odiststream& ops, PutFunction put_element) const
{ return base::data().put_values(ops, put_element); }

template <class PutFunction, class Permutation>


odiststream& permuted_put_values (
odiststream&
ops,
const Permutation&
perm,
PutFunction
put_element) const
{ return base::data().permuted_put_values (ops, perm.data(), put_elemen
};

7.10 hexahedron - Hexaedron reference element


(Source file: nfem/geo_element/hexahedron.icc)

Description
The hexahedron reference element is [-1,1]^3.
^ z
|
4----------7
|\\
|\\
| \\
| \\
| \\
| \\
|
5------+---6
|
|
|
|
0---+------3 - | ---> y
\\ |
\\ |
\\ |
\\ |
\\|
\\|
1----------2
\\
x
Curved high order Pk hexaedra (k >= 1) in 3d geometries are supported. These hexaedra
have additional edge-nodes, face-nodes and internal volume-nodes.

144

Rheolef, the finite element system.

These nodes are numbered as


first vertex, then edge-node, following the edge numbering order and orientation, then facenodes following the face numbering order and orientation, and finally the face internal nodes,
following the hexaedron lattice. See below for edges and faces numbering and orioentation.
4----19----7
|\\
|\\
|16
23 | 18
12 \\ 21
15 \\
|
5----17+---6
|22 | 26 | 25|
0---+-11---3
|
\\ 13
24 \\ 14
8 | 20
10|
\\|
\\|
1-----9----2
P2

Numbering
The orientation is such that triedra (01, 03, 04) is direct and all faces, see from exterior, are
in the direct sens. References: P. L. Georges, "Generation automatique de maillages", page
24-, coll RMA, 16, Masson, 1994. Notice that the edge-nodes and face-nodes numbering
slighly differ from those used in the gmsh mesh generator when using high-order elements.
This difference is handled by the msh2geo mesh file converter (see Section 4.4 [msh2geo
command], page 22).

Implementation
const
const
const
const

size_t dimension = 3;
Float measure = 8;
size_t n_vertex = 8;
point vertex [n_vertex] = {
point(-1,-1,-1 ),
point( 1,-1,-1 ),
point( 1, 1,-1 ),
point(-1, 1,-1 ),
point(-1,-1, 1 ),
point( 1,-1, 1 ),
point( 1, 1, 1 ),
point(-1, 1, 1 ) };
const size_t n_face = 6;
const size_t face [n_face][4] = {
{0, 3, 2, 1 },
{0, 4, 7, 3 },
{0, 1, 5, 4 },
{4, 5, 6, 7 },
{1, 2, 6, 5 },
{2, 3, 7, 6 } };

Chapter 7: Internal classes

145

const size_t n_edge = 12;


const size_t edge [n_edge][2] = {
{0, 1 },
{1, 2 },
{2, 3 },
{3, 0 },
{0, 4 },
{1, 5 },
{2, 6 },
{3, 7 },
{4, 5 },
{5, 6 },
{6, 7 },
{7, 4 } };

7.11 point - Point reference element


(Source file: nfem/geo_element/point.icc)

Description
The point reference element is defined for convenience. It is a 0-dimensional element with
measure equal to 1.

Implementation
const size_t dimension = 0;
const size_t measure = 1;

7.12 prism - Prism reference element


(Source file: nfem/geo_element/prism.icc)

Description
The prism reference element is
K = { 0 < x < 1 and 0 < y < 1-x and -1 < z < 1 }

Numbering
The orientation is such that triedra (01, 02, 03) is direct and all faces, see from exterior,
are in the direct sens. References: P. L. Georges, "Generation automatique de maillages",
page 24-, coll RMA, 16, Masson, 1994.
z
3 ---- 5
| .
|
4 . |
|

146

Rheolef, the finite element system.

|
|
|
|
|
|
|
0 . . .2
|
.
1 .

Implementation
const
const
const
const

const
const

const
const

size_t dimension = 3;
Float measure = 1;
size_t n_vertex = 6;
point vertex [n_vertex]
point( 0, 0,-1 ),
point( 1, 0,-1 ),
point( 0, 1,-1 ),
point( 0, 0, 1 ),
point( 1, 0, 1 ),
point( 0, 1, 1 ) };
size_t n_face = 5;
size_t face [n_face][4]
{ 0, 2, 1, size_t(-1)
{ 3, 4, 5, size_t(-1)
{ 0, 1, 4, 3 },
{ 1, 2, 5, 4 },
{ 0, 3, 5, 2 } };
size_t n_edge = 9;
size_t edge [n_edge][2]
{ 0, 1 },
{ 1, 2 },
{ 2, 0 },
{ 0, 3 },
{ 1, 4 },
{ 2, 5 },
{ 3, 4 },
{ 4, 5 },
{ 5, 3 } };

= {

= {
},
},

= {

7.13 quadrangle - Quadrangular reference element


(Source file: nfem/geo_element/quadrangle.icc)

Description
The quadrangular reference element is [-1,1]^2.

Numbering
y

Chapter 7: Internal classes

3---------2
|
|
|
|
|
|
|
|
0---------1

147

Curved high order Pk quadrangles (k >= 1), in 2d or 3d geometries, are supported. These
quadrangles have additional edge-nodes and face-nodes.

These nodes are numbered as


first vertex, then edge-node, following the edge numbering order and orientation, and finally
the face internal nodes, following the quadrangle lattice. See below for edge numbering and
orientation.
3-----6-----2
|
|
|
|
7
8
5
|
|
|
|
0-----4-----1
P2

3---9---8---2
|
|
10 14 15
7
|
|
11 12 13
6
|
|
0---4---5---1
P3

Implementation
const
const
const
const

size_t dimension = 2;
Float measure = 4;
size_t n_vertex = 4;
point vertex [n_vertex] = {
point(-1,-1),
point( 1,-1),
point( 1, 1),
point(-1, 1) };
const size_t n_edge = 4;
const size_t edge [n_edge][2] = {
{ 0, 1 },
{ 1, 2 },
{ 2, 3 },
{ 3, 0 } };

7.14 quadrature - quadrature formulae on the reference


lement
(Source file: nfem/geo_element/quadrature.h)

148

Rheolef, the finite element system.

Synopsys
The quadrature class defines a container for a quadrature formulae on the reference element
(see Section 7.15 [reference element iclass], page 149). This container stores the nodes
coordinates and the weights.

The constructor takes two arguments


the reference element K and the order r of the quadrature formulae. The formulae is exact
when computing the integral of a polynom p that degree is less or equal to order r.
n
/
___
| p(x) dx = \
p(x_q) w_q
/ K
/__
q=1

Limitations
The formulae is optimal when it uses a minimal number of nodes n. Optimal quadrature formula are hard-coded in this class. Not all reference elements and orders are yet
implemented. This class will be completed in the future.

Implementation
template<class T>
class quadrature : public smart_pointer<quadrature_rep<T> > {
public:
// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef

quadrature_rep<T>
smart_pointer<rep>
typename rep::size_type
typename rep::family_type
typename rep::const_iterator
typename rep::orientation_type

rep;
base;
size_type;
family_type;
const_iterator;
orientation_type;

// allocators:
quadrature (quadrature_option_type opt = quadrature_option_type())
: base(new_macro(rep(opt))) {}
// modifiers:
void set_order (size_type order) { base::data().set_order(order); }
void set_family (family_type ft) { base::data().set_family(ft); }
// accessors:

Chapter 7: Internal classes

149

size_type
get_order() const { return base::data().get_order();}
family_type
get_family() const { return base::data().get_family();}
std::string
get_family_name() const { return base::data().get_family_name();}
const quadrature_option_type& get_options() const { return base::data().get_opti
size_type
size (reference_element hat_K) const { return base::data().size(
const_iterator begin (reference_element hat_K) const { return base::data().begin
const_iterator end
(reference_element hat_K) const { return base::data().end(h
const weighted_point<T>& operator() (reference_element hat_K, size_type q) const
{ return base::data().opera
template<class U>
friend std::ostream& operator<< (std::ostream& os, const quadrature<U>& q) {
return os << q.data(); }
// side accessor:
void side_initialize (
reference_element
tilde_K,
size_type
loc_isid,
reference_element
hat_S,
size_type
shift,
orientation_type
orient) const {
base::data().side_initialize (tilde_K, loc_isid, hat_S, shift, orient);
}
};

7.15 reference_element - reference element


(Source file: nfem/geo_element/reference_element.h)

Synopsys
The reference_element class defines all supported types of geometrical elements in one,
two and three dimensions. The set of supported elements are designate by a letter
p

point (dimension 0)

edge (dimension 1)

triangle(dimension 2)

quadrangle(dimension 2)

tetrahedron(dimension 3)

prism(dimension 3)

hexaedron(dimension 3)

Implementation
class reference_element {

150

Rheolef, the finite element system.

public:
// typedefs:
typedef std::vector<int>::size_type size_type;
// defines variant_type { p, t, q ..., H, ...};
// in an automatically generated file :
typedef size_type variant_type;
static const variant_type
p = 0,
e = 1,
t = 2,
q = 3,
T = 4,
P = 5,
H = 6,
max_variant = 7;
// allocators/deallocators:
reference_element (variant_type x = max_variant)
: _x(x) { assert_macro (x >= 0 && x <= max_variant, "invalid type " << x); }
// initializers:

void set_variant (variant_type x) { _x = x; }


void set_variant (size_type n_vertex, size_type dim) { _x = variant (n_vertex, d
void set_name
(char name);
// accessors:

variant_type variant() const { return _x; }


char name() const { return _name[_x]; }
size_type dimension() const { return _dimension[_x]; }
size_type size() const { return _n_vertex[_x]; }
size_type n_subgeo(size_type subgeo_dim) const { return n_subgeo (variant(), sub
size_type n_edge() const { return n_subgeo(1); }
size_type n_face() const { return n_subgeo(2); }
size_type subgeo_size (size_type subgeo_dim, size_type loc_isid) const {
return subgeo_n_node (_x, 1, subgeo_dim, loc_isid); }
size_type subgeo_local_vertex(size_type subgeo_dim, size_type loc_isid, size_typ
return subgeo_local_node (_x, 1, subgeo_dim, loc_isid, loc_jsidvert); }
// TODO: use template<class T> instead of Float
const point_basic<Float>& vertex (size_type iloc) const;
friend Float measure (reference_element hat_K);
Float side_measure (size_type loc_isid) const;

Chapter 7: Internal classes

151

void side_normal (size_type loc_isid, point_basic<Float>& hat_n) const;


// helpers:
static
static
static
static
static
static

variant_type variant
variant_type variant
char
name
size_type dimension
size_type n_vertex
size_type n_node

static
static
static
static
static

size_type
size_type
size_type
size_type
size_type

(char name);
(size_type n_vertex, size_type dim);
(variant_type variant) { return _name
[variant]
(variant_type variant) { return _dimension[variant]
(variant_type variant) { return _n_vertex [variant]
(variant_type variant, size_type order);

n_sub_edge
(variant_type variant);
n_sub_face
(variant_type variant);
n_subgeo
(variant_type variant, size_type subgeo_dim);
subgeo_n_node (variant_type variant, size_type order, size_type
subgeo_local_node (variant_type variant, size_type order, size_

static variant_type first_variant_by_dimension (size_type dim) {


return _first_variant_by_dimension[dim]; }
static variant_type last_variant_by_dimension (size_type dim) {
return _first_variant_by_dimension[dim+1]; }

static size_type first_inod_by_variant (variant_type variant, size_type order, v


static size_type last_inod_by_variant (variant_type variant, size_type order, v
{ return first_inod_by_variant (variant, order, subgeo_variant+1); }
static size_type first_inod (variant_type variant, size_type order, size_type su
{ return first_inod_by_variant (variant, order, first_variant_by_dimension(su
static size_type last_inod (variant_type variant, size_type order, size_type su
{ return first_inod_by_variant (variant, order, last_variant_by_dimension(su
static void init_local_nnode_by_variant (size_type order, boost::array<size_type
protected:
// constants:
static
static
static
static

const
const
const
const

char
_name [max_variant];
size_type _dimension [max_variant];
size_type _n_vertex [max_variant];
variant_type _first_variant_by_dimension[5];

// data:
variant_type _x;
};

7.16 tetrahedron - Tetraedron reference element


(Source file: nfem/geo_element/tetrahedron.icc)

152

Rheolef, the finite element system.

Description
The tetrahedron reference element is
K = { 0 < x < 1 and 0 < y < 1-x and 0 < z < 1-x-y }
z
.
,/
/
3
,/|\\
,/ | \\
,/
.
\\
,/
|
\\
,/
|
\\
0-----------.--------2 --> y
\\.
|
,/
\\.
|
,/
\\.
. ,/
\\. |/
1
\\.
x
Curved high order Pk tetrahedra (k >= 1) in 3d geometries are supported. These tetrahedra
have additional edge-nodes, face-nodes and internal volume-nodes.

These nodes are numbered as


first vertex, then edge-node, following the edge numbering order and orientation, then facenodes following the face numbering order and orientation, and finally the face internal nodes,
following the tetrahedron lattice. See below for edges and faces numbering and orioentation.
3
,/|\\
,/ | \\
,7
.
9
,/
|
\\
,/
8
\\
0--------6--.--------2
\\.
|
,/
\\.
|
,5
4.
. ,/
\\. |/
1
P2

Numbering
The orientation is such that triedra (01, 02, 03) is direct, and all faces, see from exterior, are
in the direct sens. References: P. L. Georges, "Generation automatique de maillages", page

Chapter 7: Internal classes

153

24-, coll RMA, 16, Masson, 1994. Notice that the edge-nodes and face-nodes numbering
slighly differ from those used in the gmsh mesh generator when using high-order elements.
This difference is handled by the msh2geo mesh file converter (see Section 4.4 [msh2geo
command], page 22).

Implementation
const
const
const
const

const
const

const
const

size_t dimension = 3;
Float measure = Float(1.)/Float(6.);
size_t n_vertex = 4;
point vertex [n_vertex] = {
point( 0, 0, 0 ),
point( 1, 0, 0 ),
point( 0, 1, 0 ),
point( 0, 0, 1 ) };
size_t n_face = 4;
size_t face [n_face][3] = {
{ 0, 2, 1 },
{ 0, 3, 2 },
{ 0, 1, 3 },
{ 1, 2, 3 } };
size_t n_edge = 6;
size_t edge [n_edge][2] = {
{ 0, 1 },
{ 1, 2 },
{ 2, 0 },
{ 0, 3 },
{ 1, 3 },
{ 2, 3 } };

7.17 triangle - Triangle reference element


(Source file: nfem/geo_element/triangle.icc)

Description
The triangle reference element is
K = { 0 < x < 1 and 0 < y < 1-x }

Numbering
y
2
| +
|
+
|
+
|
+
0---------1

154

Rheolef, the finite element system.

Curved high order Pk triangles (k >= 1), in 2d or 3d geometries, are supported. These
triangles have additional edge-nodes and face-nodes.

These nodes are numbered as


first vertex, then edge-node, following the edge numbering order and orientation, and finally
the face internal nodes, following the triangle lattice. See below for edge numbering and
orientation.
2
2
2
| +
| +
| +
|
+
7
6
9
8
5
4
|
+
10 14 7
|
+
8
9
5
11 12 13 6
|
+
|
+
|
+
0-----3-----1
0---3---4---1
0--3--4--5--1
P2
P3
P4

Implementation
const
const
const
const

size_t dimension = 2;
Float measure = 0.5;
size_t n_vertex = 3;
point vertex [n_vertex] = {
point(0, 0),
point(1, 0),
point(0, 1) };
const size_t n_edge = 3;
const size_t edge [n_edge][2] = {
{ 0, 1 },
{ 1, 2 },
{ 2, 0 } };

7.18 index set - a set of indexes


(Source file: skit/plib2/index_set.h)

Synopsys
A class for: l = {1,3,...9} i.e. a wrapper for STL set<size_t> with some assignment
operators, such as l1 += l2. This class is suitable for use with the array<T> class, as
array<index_set> (see Section 5.17 [array class], page 79).

Implementation
class index_set : public std::set<std::size_t> {
public:
// typedefs:

Chapter 7: Internal classes

typedef std::set<std::size_t>
typedef std::size_t
typedef std::size_t

155

base;
value_type;
size_type;

// allocators:
index_set ();
index_set (const index_set& x);
index_set& operator= (const index_set& x);
template <int N>
index_set& operator= (size_type x[N]);
void clear ();
// basic algebra:
void
insert
(size_type dis_i);
// a := a union {dis_i}
index_set& operator+= (size_type dis_i);
// idem
index_set& operator+= (const index_set& b); // a := a union b
// a := a union b
void inplace_union
(const index_set& b);
void inplace_intersection (const index_set& b);

// c := a union b
friend void set_union
(const index_set& a, const index_set& b, index_set& c
friend void set_intersection (const index_set& a, const index_set& b, index_set& c
// io:
friend std::istream& operator>> (std::istream& is, index_set& x);
friend std::ostream& operator<< (std::ostream& os, const index_set& x);
// boost mpi:
template <class Archive>
void serialize (Archive& ar, const unsigned int version);
};

7.19 pair set - a set of (index,value) pair


(Source file: skit/plib2/pair_set.h)

Synopsys
A class for: l = {(0,3.3),...(7,8.2)} i.e. a wrapper for STL map<size_t,T> with some
assignment operators, such as l1 += l2. This class is suitable for use with the array<T>
class, as array<pair_set> (see Section 5.17 [array class], page 79).

156

Rheolef, the finite element system.

Todo
template <T,A> with A=std::allocator or heap allocator

Implementation
template<class T, class A = std::allocator<std::pair<std::size_t,T> > >
class pair_set: public std::map<std::size_t, T, std::less<std::size_t>, A> {
public:
// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef

std::size_t
size_type;
std::pair<size_type,T>
pair_type;
std::pair<const size_type,T>
const_pair_type;
pair_type
value_type;
A
allocator_type;
std::map<size_type, T, std::less<size_type>, allocator_type>
base;
typedef typename base::iterator
iterator;
typedef typename base::const_iterator const_iterator;
// allocators:
pair_set (const A& alloc = A());
pair_set (const pair_set<T,A>& x, const A& alloc = A());
pair_set<T,A>& operator= (const pair_set<T,A>& x);
void clear ();
// basic algebra: semantic of a sparse vector
pair_set<T,A>& operator+= (const pair_type&
x); // c := a union {x}
template<class B>
pair_set<T,A>& operator+= (const pair_set<T,B>& b); // c := a union b
// boost mpi:
template <class Archive>
void serialize (Archive& ar, const unsigned int version);
};
// io:
template <class T, class A>
std::istream& operator>> (std::istream& is,
pair_set<T,A>& a);
template <class T, class A>
std::ostream& operator<< (std::ostream& os, const pair_set<T,A>& b);

7.20 heap allocator - heap-based allocator


(Source file: util/lib/heap_allocator.h)

Chapter 7: Internal classes

157

Description
Heap allocators are generally used when there is a lot of allocation and deallocation of small
objects. For instance, this is often the case when dealing with std::list and std::map.
Heap-based allocator is conform to the STL specification of allocators. It does not "free"
the memory until the heap is destroyed.
This allocator handles an a priori unlimited area of memory: a sequence of growing chunks
are allocated. For a limited memory handler in the same spirit, see "stack allocator"(9).

Example
typedef map <size_t, double, less<size_t>, heap_allocator<pair<size_t,double> >
map_type a;
a.insert (make_pair (0, 3.14));
a.insert (make_pair (1, 1.17));
for (map_type::iterator iter = a.begin(), last = a.end(); iter != last; iter++)
cout << (*iter).first << " " << (*iter).second << endl;
}

Implementation
template <typename T>
class heap_allocator {
protected:
struct handler_type; // forward declaration:
public:
// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef
typedef

size_t
std::ptrdiff_t
T*
const T*
T&
const T&
T

size_type;
difference_type;
pointer;
const_pointer;
reference;
const_reference;
value_type;

// constructors:
heap_allocator() throw()
: handler (new handler_type)
{
}
heap_allocator (const heap_allocator& ha) throw()
: handler (ha.handler)
{
++handler->reference_count;
}

158

Rheolef, the finite element system.

template <typename U>


heap_allocator (const heap_allocator<U>& ha) throw()
: handler ((typename heap_allocator<T>::handler_type*)(ha.handler))
{
++handler->reference_count;
}
~heap_allocator() throw()
{
check_macro (handler != NULL, "unexpected null mem_info");
if (--handler->reference_count == 0) delete handler;
}
// Rebind to allocators of other types
template <typename U>
struct rebind {
typedef heap_allocator<U> other;
};
// assignement:
heap_allocator& operator= (const heap_allocator& ha)
{
handler = ha.handler;
++handler->reference_count;
return *this;
}
// utility functions:

pointer
address (reference r)
const { return &r; }
const_pointer address (const_reference c) const { return &c; }
size_type
max_size() const { return std::numeric_limits<size_t>::max() / siz
// in-place construction/destruction

void construct (pointer p, const_reference c)


{
// placement new operator:
new( reinterpret_cast<void*>(p) ) T(c);
}
// C++ 2011: default construct a value of type T at the location referenced by p
void construct (pointer p) { new ( reinterpret_cast<void*>(p) ) T(); }
void destroy (pointer p)
{
// call destructor directly:
(p)->~T();
}
// allocate raw memory

Chapter 7: Internal classes

159

pointer allocate (size_type n, const void* = NULL)


{
return pointer (handler->raw_allocate (n*sizeof(T)));
}
void deallocate (pointer p, size_type n)
{
// No need to free heap memory
}
const handler_type* get_handler() const {
return handler;
}
// data:
protected:
handler_type* handler;
template <typename U> friend class heap_allocator;
};

7.21 smart_pointer, smart_pointer_clone - reference counted


safe pointer with true copy semantic
(Source file: util/lib/smart_pointer.h)

Description
Here is a convenient way to implement a true copy semantic, by using shallow copies and
reference counting, in order to minimise memory copies. This concept is generally related
to the smart pointer method for managing memory.
The true semantic copy is defined as follows: if an object A is assigned to B, such as A = B,
every further modification on A or B does not modify the other.
Notice that this class differs from the boost::shared\_ptr class that implements safe
pointers without the true copy semantic.

Clone variant
The smart_pointer_clone variant uses a T* T::clone() const member function instead
of the usual T::T() copy constructor for obtaining a true copy of the data. This variant is
motivated as follows: when using hierarchies of derived classes (also known as polymorphic
classes), the usual copy is not possible because c++ copy constructors cannot be virtual, so
you cannot make a copy this way. This is a well-known problem with C++s implementation
of polymorphism.
We uses a solution to the non-virtual copy constructor problem which is suggested by Ellis
and Stroustrup in "The Annotated LRM". The solution is to require the T class to provide
a virtual clone method for every class which makes a copy using new and the correct
copy constructor, returning the result as a pointer to the superclass T. Each subclass of

160

Rheolef, the finite element system.

T overloads this function with its own variant which copies its own type. Thus the copy
operation is now virtual and furthermore is localised to the individual subclass.

Nocopy variant
This variant of the smart pointer is designed for use on objects that cannot (or must not)
be copied. An example would be when managing an object that contains, say, a file handle.
It is essential that this not be copied because then you get the problem of deciding which
copy is responsible for closing the file. To avoid the problem, wrap the file handle in a class
and then manage a unique instance of it using a smart_pointer_nocopy. This ensures that
the file handle cannot be copied and is closed when the last alias is destroyed.
The interface to the nocopy variant is the same as smart_pointer but with all operations
that perform copying forbidden. In fact, because all three variants are instances of a common
superclass, the forbidden methods do exist but will cause an error and exit if they are called.
The following modifiers cannot be used because they use copying of the pointed-to object
and will thereore cause an error:
T* operator-> ();
T& operator* ();
T* pointer ();
T& data ();

Eferences
[1] A. Geron and F. Tawbi,
Pour mieux developper avec C++ : design pattern, STL, RTTI et smart pointers,
InterEditions, 1999. Page 118.
[2] STLplus, http://stlplus.sourceforge.net/stlplus3/docs/smart_ptr.html
for the clone and nocopy variants.

Implementation
template <class T, class C>
class smart_pointer_base {
public:
// allocators:
smart_pointer_base (T* p = 0);
smart_pointer_base (const smart_pointer_base<T,C>&);
smart_pointer_base<T,C>& operator= (const smart_pointer_base<T,C>&);
~smart_pointer_base ();
// accessors:
const T* pointer
const T& data

() const;
() const;

Chapter 7: Internal classes

161

const T* operator-> () const;


const T& operator* () const;
// modifiers:
T*
T&
T*
T&

pointer
data
operator->
operator*

();
();
();
();

// implementation:
private:
struct counter {
T* _p;
int _n;
counter (T* p = 0);
~counter ();
int operator++ ();
int operator-- ();
};
counter *_count;
#ifndef TO_CLEAN
public:
int reference_counter() const { return _count != 0 ? _count->_n : -1; }
#endif // TO_CLEAN
};

7.22 stack allocator - stack-based allocator


(Source file: util/lib/stack_allocator.h)

Description
Stack-based allocator, conform to the STL specification of allocators. Designed to use stackbased data passed as a parameter to the allocator constructor. Does not "free" the memory.
Assumes that if the allocator is copied, stack memory is cleared and new allocations begin
at the bottom of the stack again.
Also works with any memory buffer, including heap memory. If the caller passes in heap
memory, the caller is responsible for freeing the memory.
This allocator handles a limited area of memory: if this limit is reached, a "std::bad alloc"
exception is emmited. For a non-limited memory handler in the same spirit, see "heap allocator"(9).

Example

const size_t stack_size = 1024;


vector<unsigned char> stack (stack_size);
stack_allocator<double> stack_alloc (stack.begin().operator->(), stack.size());
typedef map <size_t, double, less<size_t>, stack_allocator<pair<size_t,double> >

162

Rheolef, the finite element system.

map_type a (less<size_t>(), stack_alloc);


a.insert (make_pair (0, 3.14));
a.insert (make_pair (1, 1.17));
for (map_type::iterator iter = a.begin(), last = a.end(); iter != last; iter++)
cout << (*iter).first << " " << (*iter).second << endl;
}

Implementation
template <typename T>
class stack_allocator {
protected:
struct handler_type; // forward declaration:
public:
// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef
typedef

size_t
std::ptrdiff_t
T*
const T*
T&
const T&
T

size_type;
difference_type;
pointer;
const_pointer;
reference;
const_reference;
value_type;

// constructors:
stack_allocator() throw()
: handler (new handler_type)
{
}
stack_allocator (unsigned char* stack, size_t stack_size) throw()
: handler (new handler_type (stack, stack_size))
{
warning_macro ("stack_allocator cstor");
}
stack_allocator (const stack_allocator& sa) throw()
: handler (sa.handler)
{
++handler->reference_count;
}
template <typename U>
stack_allocator (const stack_allocator<U>& sa) throw()
: handler ((typename stack_allocator<T>::handler_type*)(sa.handler))
{
++handler->reference_count;
}
~stack_allocator() throw()

Chapter 7: Internal classes

163

{
warning_macro ("stack_allocator dstor");
check_macro (handler != NULL, "unexpected null mem_info");
if (--handler->reference_count == 0) delete handler;
}
// Rebind to allocators of other types
template <typename U>
struct rebind {
typedef stack_allocator<U> other;
};
// assignement:
stack_allocator& operator= (const stack_allocator& sa)
{
handler = sa.handler;
++handler->reference_count;
return *this;
}
// utility functions:

pointer
address (reference r)
const { return &r; }
const_pointer address (const_reference c) const { return &c; }
size_type
max_size() const { return std::numeric_limits<size_t>::max() / siz
// in-place construction/destruction

void construct (pointer p, const_reference c)


{
// placement new operator:
new( reinterpret_cast<void*>(p) ) T(c);
}
// C++ 2011: default construct a value of type T at the location referenced by p
void construct (pointer p) { new ( reinterpret_cast<void*>(p) ) T(); }
void destroy (pointer p)
{
// call destructor directly:
(p)->~T();
}
// allocate raw memory
pointer allocate (size_type n, const void* = NULL)
{
warning_macro ("allocate "<<n<<" type " << typename_macro(T));
check_macro (handler->stack != NULL, "unexpected null stack");
void* p = handler->stack + handler->allocated_size;

164

Rheolef, the finite element system.

handler->allocated_size += n*sizeof(T);
if (handler->allocated_size + 1 > handler->max_size) {
warning_macro ("stack is full: throwing...");
throw std::bad_alloc();
}
return pointer (p);
}
void deallocate (pointer p, size_type n)
{
warning_macro ("deallocate "<<n<<" type "<<typename_macro(T));
// No need to free stack memory
}
const handler_type* get_handler() const {
return handler;
}
// data:
protected:
struct handler_type {
unsigned char* stack;
size_t
allocated_size;
size_t
max_size;
size_t
reference_count;
handler_type()
: stack (NULL),
allocated_size (0),
max_size (0),
reference_count (1)
{
warning_macro ("stack_allocator::mem_info
}
handler_type (unsigned char* stack1, size_t
: stack (stack1),
allocated_size (0),
max_size (size1),
reference_count (1)
{
warning_macro ("stack_allocator::mem_info
}
~handler_type()
{
warning_macro ("stack_allocator::mem_info
}

cstor NULL");
size1)

cstori: size="<<max_size);

dstor: size="<<max_size);

};
handler_type* handler;
template <typename U> friend class stack_allocator;

Chapter 7: Internal classes

165

};
// Comparison
template <typename T1>
bool operator==( const stack_allocator<T1>& lhs, const stack_allocator<T1>& rhs) thr
{
return lhs.get_handler() == rhs.get_handler();
}
template <typename T1>
bool operator!=( const stack_allocator<T1>& lhs, const stack_allocator<T1>& rhs) thr
{
return lhs.get_handler() != rhs.get_handler();
}

7.23 Vector - STL vector<T> with reference counting


(Source file: util/lib/Vector.h)

Description
The class implement a reference counting wrapper for the STL vector<T> container class,
with shallow copies. See also: The standard template library, by Alexander Stephanov and
Meng Lee.
This class provides the full vector<T> interface specification an could be used instead of
vector<T>.

Note
The write accessors
T& operator[](size_type)
as in v[i] may checks the reference count for each access. For a loop, a better usage is:
Vector<T>::iterator i = v.begin();
Vector<T>::iterator last = v.end();
while (i != last) { ...}
and the reference count check step occurs only two time, when accessing via begin() and
end().
Thus, in order to encourage users to do it, we declare private theses member functions. A
synonym of operator[] is at.

Implementation
template<class T>
class Vector : private smart_pointer<vector_rep<T> > {
public:

166

Rheolef, the finite element system.

// typedefs:
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

iterator;
const_iterator;
pointer;
reference;
const_reference;
size_type;
difference_type;
value_type;
reverse_iterator;
const_reverse_iterator;

// allocation/deallocation:
explicit Vector (size_type n = 0, const T& value = T ());
Vector (const_iterator first, const_iterator last);
void reserve (size_type n);
void swap (Vector<T>& x) ;
// accessors:
iterator
begin ();
const_iterator
begin () const;
iterator
end ();
const_iterator
end ()
const;
reverse_iterator
rbegin();
const_reverse_iterator
rbegin() const;
reverse_iterator
rend();
const_reverse_iterator
rend() const;
size_type size () const;
size_type max_size () const;
size_type capacity () const;
bool empty () const;
void resize (size_type sz, T v = T ()); // non-standard ?
private:
const_reference operator[] (size_type n) const;
reference operator[] (size_type n);
public:
const_reference at (size_type n) const; // non-standard ?
reference at (size_type n);
reference
front ();
const_reference
front () const;
reference
back ();
const_reference
back () const;
// insert/erase:
void push_back (const T& x);

Chapter 7: Internal classes

167

iterator insert (iterator position, const T& x = T ());


void insert (iterator position, size_type n, const T& x);
void insert (iterator position, const_iterator first, const_iterator last);
void pop_back ();
void erase (iterator position);
void erase (iterator first, iterator last);
};

168

Rheolef, the finite element system.

Chapter 8: Internal algorithms

169

8 Internal algorithms

8.1 iorheo - input and output functions and manipulation


(Source file: util/lib/iorheo.h)

Small pieces of code


input geo in standard file format:
cin >> g;
output geo in standard file format:
cout << g;
output geo in gnuplot format:
cout << gnuplot << g;

Description
output manipulators enable the selection of some pretty graphic options, in an elegant
fashion.

Boolean manipulators
The boolean manipulators set an internal optional flag. Each option has its negative counterpart, as verbose and noverbose, by adding the no prefix.
cout << noverbose << a;
verbose

trace some details, such as loading, storing or unix command operations on


cerr. Default is on.

clean

delete temporary files during graphic outputs. Default is on.

execute

run unix operations, such as gnuplot or plotmtv or vtk. Note that the corresponding files are created. Default is on.

transpose
perform transposition when loading/soring a csr matrix from Harwell-Boeing
file. This feature is available, since the file format store matrix in transposed
format. Default is off.
logscale

when using matrix sparse postscript plot manipulator ps and color. The color
scale is related to a logarithmic scale.

170

Rheolef, the finite element system.

fill
grid
shrink
tube
ball
full
stereo
cut
iso
split

when using the vtk or mayavi manipulators for a mesh or a field.

volume

volume rendering by using ray cast functions.

velocity
deformation
Vector-valued fields are rendered by using arrows (velocity) or deformed
meshes (deformation). For vtk or plotmtv rendering.
elevation
Scalar valued fields in two dimension are rendered by using a tridimensionnal
surface elevation. For vtk or plotmtv rendering.
fastfieldload
try to reuse the supplied space. Default is on.

File format manipulators


The format manipulator group applies for streams. Its value is an enumerated type, containing the following possibilities:
rheo

use the default textual input/output file format. For instance, this is .geo for
meshes, .field for discretized functions. This default format is specified in
the corresponding class documentation (see also Section 5.9 [geo class], page 55
and Section 5.4 [field class], page 41). This is the default.

bamg

uses .bamg Frederic Hechts bidimensional anisotropic mesh generator file format for geo input/output operation.

tetgen

uses .node .ele and .face Hang Sis tridimensional mesh generator file
format for geo input/output operation.

mmg3d

uses .mmg3d Cecile Dobrzynskis tridimensional anisotropic mesh generator


file format for geo input/output operation.

gmsh

uses .gmsh gmsh Christophe Geuzaine and Jean-Francois Remacle mesh generator file format for geo input/output operation.

gmsh_pos

uses .gmsh_pos gmsh Christophe Geuzaine and Jean-Francois Remacle mesh


metric file format for geo adapt input/output operation.

grummp

uses .m (bidimensional) or .v (tridimensionnal) Carl Ollivier-Gooch s mesh


generator file format for geo input/output operation.

Chapter 8: Internal algorithms

171

qmg

uses .qmg Stephen A. Vavasiss mesh generator file format for geo input/output
operation.

vtkdata

uses .vtk mesh file format for geo input/output operations. This file format
is suitable for graphic treatment.

vtkpolydata
uses .vtk polydata (specific for polygonal boundaries) mesh file format for
geo input/output operations. This file format is suitable for graphic treatment.
cemagref

uses .cemagref surface mesh (topography, with a z cote). This file format is
used at Cemagref (french research center for mountains, http://www.cemagref.fr).

dump

output an extensive listing of the class data structure. This option is used for
debugging purpose.

hb

uses .hb Harwell-Boeing file format for sparse matrix input/output operation.
This is the default.

matrix_market
uses .mm Matrix-Market file format for sparse matrix input/output operation.
ml
matlab

uses .m Matlab file format for sparse matrix output operation.

sparse_matlab
uses .m Matlab sparse file format for sparse matrix output operation.
ps

uses .ps postscript for sparse matrix output operation.

vtk

for mesh and field outputs. Generate .vtk data file and the .tcl command
script file and run the vtk command on the .tcl.

mayavi

for field outputs. Generate .vtk data file and the .py command script file
and run the python command on the .py associated to the mayavi/vtk library.

geomview

for boundary cad outputs. Generate .off data file and run the geomview
command.

gnuplot

for mesh and field outputs. Generate .gdat data file and the .plot command
script file and run the gnuplot command on the .plot.

plotmtv

for mesh and field outputs. Generate .mtv data file and run the plotmtv
command.

x3d

for mesh output. Generate .x3d data file and run the x3d command. This
tool has fast rotation rendering.

atom

for mesh output. Generate .atom data file and run the PlotM command.
Tridimensional mesh rendering is performed as a chemical molecule: nodes as
balls and edges as tubes. The PlotM tool is developped at Cornell University
Laboratory of Atomic and Solid State Physics (LASSP) in a Joint Study with
IBM, with support by the Materials Science Center and Corning Glassworks.

172

Rheolef, the finite element system.

Color manipulators
The color manipulator group acts for sparse matrix postscript output. Its value is an
enumerated type, containing three possibilities:
cout << color << a;
cout << gray << b;
cout << black_and_white << c;
The default is to generate a color postcript file. Conversely, its act for field rendering, via
mayavi.

Valuated manipulators
Some manipulators takes an agument that specifies a value.
cout << geomview << bezieradapt << subdivide(5) << my_cad_boundary;
cout << vtk << iso << isovalue(2.5) << my_mesh;
cout << velocity << plotmtv << vectorscale(0.1) << uh;
See also Section 6.15 [catchmark algorithm], page 127 for input-output of vector-valued
fields.
isovalue float
n_isovalue int
n_isovalue_negative int
vectorscale float
subdivide float
image_format string
The argument is any valid image format, such as png, jpg or pdf, that could
be handled by the corresponding graphic render.

8.2 typename_macro, pretty_typename_macro - type demangler


and pretty printer
(Source file: util/lib/pretty_name.h)

Description
These preprocessor macro-definitions are usefull when dealing with complex types as generated by imbricted template technics: they print in clear a complex type at run-time.
typeid_name_macro obtains a human readable type in a std::tring form by calling the
system typeid function and then a demangler. When this type is very long, pretty_name_
macro prints also it in a multi-line form with a pretty indentation.

Examples
typedef map <size_t, double, less<size_t>, heap_allocator<pair<size_t,double> > >
cout << typeid_name_macro (map_type);

Chapter 8: Internal algorithms

173

Implementation
extern std::string typeid_name (const char* name, bool do_indent);

/// @brief get string from a type, with an optional pretty-printing for complex type
#define
typename_macro(T) typeid_name(typeid(T).name(), false)
#define pretty_typename_macro(T) typeid_name(typeid(T).name(), true)

/// @brief get string type from a variable or expression


template <class T> std::string
typename_of (T x) { return
typename_mac
template <class T> std::string pretty_typename_of (T x) { return pretty_typename_mac

174

Rheolef, the finite element system.

Chapter 9: Internal others

175

9 Internal others
9.1 acinclude autoconf macros
(Source file: config/acinclude.m4)

Description
These macros test for particular system featutres that rheolef uses. These tests print the
messages telling the user which feature they are looking for and what they find. They cache
their results for future configure runs. Some of these macros set some shell variable, defines
some output variables for the config.h header, or performs Makefile macros subsitutions.
See autoconf documentation for how to use such variables.

Synopsis
Follows a list of particular check required for a successfull installation.
RHEO_CHECK_GINAC
Check to see if GiNaC library exists. If so, set the shell variable rheo_have_ginac to "yes",
defines HAVE GINAC and substitues INCLUDES GINAC and LADD GINAC for adding
in CFLAGS and LIBS, respectively, If not, set the shell variable rheo have ginac to "no".
RHEO_CHECK_CLN
Check to see if library -lcln exists. If so, set the shell variable rheo_have_cln to "yes", defines HAVE CLN and substitues INCLUDES CLN and LADD CLN for adding in CFLAGS
and LIBS, respectively, If not, set the shell variable no "no". Includes and libraries path
are searched from a given shell variable rheo_dir_cln. This shell variable could be set
for instance by an appropriate --with-cln=value dir cln option. The default value is
/usr/local/math.
RHEO_CHECK_SPOOLES_2_0
Check to see if spooles library has old version 2.0 since FrontMtx_factorInpMtx profile
has changed in version 2.2. If so, defines HAVE SPOOLES 2 0. This macro is called by
RHEO CHECK SPOOLES.
RHEO_CHECK_TAUCS
Check to see if taucs library and headers exists. If so, set the shell variable "rheo have taucs"
to "yes", defines HAVE TAUCS and substitues INCLUDES TAUCS and LADD TAUCS
for adding in CXXFLAGS and LIBS, respectively, If not, set the shell variable to
"no". Includes and libraries options are given shell variable $rheo ldadd taucs and
$rheo incdir taucs. These shell variables could be set for instance by appropriates "withtaucs-ldadd="rheo ldadd taucs and "with-taucs-includes="rheo incdir taucs options.
RHEO_CHECK_BOOST_UBLAS
Check to see if boost headers exists. If so, set the shell variable "rheo have boost" to "yes",
defines HAVE BOOST and substitues INCLUDES BOOST for adding in CXXFLAGS, and
LDADD BOOST for adding in LIBS. If not, set the shell variable to "no". Includes options

176

Rheolef, the finite element system.

are given in the shell variables $rheo incdir boost and $rheo libdir boost. These shell variables could be set for instance by appropriates "with-boost-includes="rheo incdir boost
and "with-boost-libdir="rheo libdir boost options.
RHEO_CHECK_ZLIB
Check to see if zlib library and headers exists. If so, set the shell variable "rheo have zlib"
to "yes", defines HAVE ZLIB and substitues INCLUDES ZLIB and LADD ZLIB for
adding in CXXFLAGS and LIBS, respectively, If not, set the shell variable to "no".
Includes and libraries path are searched from given shell variable $rheo dir zlib/lib and
$rheo incdir zlib. Default value for $rheo incdir zlib is $rheo dir zlib/include. These shell
variables could be set for instance by appropriates "with-zlib="dir zlib and "with-zlibincludes="incdir zlib options.
RHEO_CHECK_SPOOLES
Check to see if spooles library and headers exists. If so, set the shell variable "rheo have spooles"
to "yes", defines HAVE SPOOLES and substitues INCLUDES SPOOLES and LADD SPOOLES
for adding in CXXFLAGS and LIBS, respectively, If not, set the shell variable to "no".
Includes and libraries path are searched from given shell variable "rheo libdir spooles"
and "rheo incdir spooles". These shell variables could be set for instance by appropriates
"with-spooles="libdir spooles and "with-spooles-includes="incdir spooles options.
RHEO_CHECK_UMFPACK
Check to see if umfpack library and headers exists. If so, set the shell variable "rheo have umfpack"
to "yes", defines HAVE UMFPACK and substitues INCLUDES UMFPACK and LADD UMFPACK
for adding in CXXFLAGS and LIBS, respectively, If not, set the shell variable to "no".
Includes and libraries path are searched from given shell variable "rheo libdir umfpack"
and "rheo incdir umfpack". These shell variables could be set for instance by appropriates "with-umfpack="libdir umfpack and "with-umfpack-includes="incdir umfpack
options.
RHEO_CHECK_MALLOC_DBG
Check to see if malloc debug library -lmalloc dbg and corresponding header <malloc dbg.h>
exists. If so, set the shell variable rheo_have_malloc_dbg to "yes", defines HAVE MALLOC DBG,
add -Idir malloc dbg/include to CFLAGS, add dir malloc dbg/lib/libmalloc_dbg.a
to LIBS. Here, dir malloc dbg is the directory such that dir malloc dbg/bin appears in
PATH and the command dir malloc dbg/bin/malloc_dbg exists. If not, set the variable
to "no". Set also LIBS MALLOC DBG to these flags.
RHEO_CHECK_DMALLOC
Check whether the dmalloc package exists and set the corresponding shell value "rheo have dmalloc"
and HAVE DMALLOC (in Makefile.am and config.h) accordingly, create LDADD DMALLOC
and LDADD DMALLOCXX Makefile.am variables.
RHEO_CHECK_NAMESPACE
Check whether the namespace
compile the following code:
namespace
struct
}
namespace

feature is supported by the C++ compiler. value. So, try to


computers {
keyboard { int getkey() const { return 0; } };
music {

Chapter 9: Internal others

177

struct keyboard { void playNote(int note); };


}
namespace music {
void keyboard::playNote(int note) { }
}
using namespace computers;
int main() {
keyboard x;
int z = x.getkey();
music::keyboard y;
y.playNote(z);
return 0;
}
If it compile, set the corresponding shell variable "rheo have namespace" to "yes" and
defines HAVE NAMESPACE. If not, set the variable no "no".
RHEO_CHECK_STD_NAMESPACE
Some compilers (e.g. GNU C++ 2.7.2) does not support the full namespace feature. Nevertheless, they support the "std:" namespace for the C++ library. is supported by the C++
compiler. The following code is submitted to the compiler:
#include<vector.h>
extern "C" void exit(int);
int main() {
std::vector<int> x(3);
return 0;
}
If it compile, set the corresponding shell variable "rheo have std namespace" to "yes" and
defines HAVE STD NAMESPACE. If not, set the variable no "no".
RHEO_PROG_GNU_MAKE
Find command make and check whether make is GNU make. If so, set the corresponding
shell variable "rheo prog gnu make" to "yes" and substitues no print directory option to
"no-print-directory". If not, set the shell variable no "no".
RHEO_CHECK_ISTREAM_RDBUF
RHEO_CHECK_IOS_BP
Check to see if "iostream::rdbuf(void*)" function exists, that set the "ios" buffer of a stream.
Despite this function is standard, numerous compilers does not furnish it. a common implementation is to set directly the buffer variable. For instance, the CRAY C++ compiler implements this variable as "ios::bp". These two functions set the shell variables
"rheo have istream rdbuf" and "rheo have ios bp" and define HAVE ISTREAM RDBUF
and HAVE IOS BP respectively.
RHEO_CHECK_IOS_SETSTATE
Check to see if "ios::setstate(long)" function exists, that set the "ios" state variable of a
stream. Despite this function is standard, numerous compilers does not furnish it. a common implementation is to set directly the buffer variable. For instance, the CRAY C++ com-

178

Rheolef, the finite element system.

piler does not implements it. This function set the shell variables "rheo have ios setstate"
and define HAVE IOS SETSTATE.
RHEO_CHECK_FILEBUF_INT
RHEO_CHECK_FILEBUF_FILE
RHEO_CHECK_FILEBUF_FILE_MODE
Check wheter "filebuf::filebuf(int fileno)", "filebuf::filebuf(FILE* fd)" exist, or "filebuf::filebuf(FILE* fd, ios::openmode)" exist, respectively. If so, set the corresponding
shell variable "rheo have filebuf int" (resp. "rheo have filebuf file") to "yes" and defines
HAVE FILEBUF INT, (resp. HAVE FILEBUF FILE). If not, set the variable no "no".
Notes that there is no standardisation of this function in the "c++" library. Nevertheless,
this fonctionality is usefull to open a pipe stream class, as "pstream(3)".
RHEO_CHECK_GETTIMEOFDAY
Check whether the "gettimeofday(timeval*, timezone*)" function exists and set the corresponding shell value "rheo have gettimeofday" and define HAVE GETTIMEOFDAY accordingly.
RHEO_CHECK_WIERDGETTIMEOFDAY
This is for Solaris, where they decided to change the CALLING SEQUENCE OF gettimeofday! Check whether the "gettimeofday(timeval*)" function exists and set the corresponding
shell value "rheo have wierdgettimeofday" and define HAVE WIERDGETTIMEOFDAY
accordingly.
RHEO_CHECK_BSDGETTIMEOFDAY
For BSD systems, check whether the "BSDgettimeofday(timeval*, timezone*)" function exists and set the corresponding shell value "rheo have bsdgettimeofday" and define
HAVE BSDGETTIMEOFDAY accordingly.
RHEO_CHECK_AMICCLK
Check whether the clock "amicclk()" function exists and set the corresponding shell value
"rheo have amicclk" and define HAVE AMICCLK accordingly.
RHEO_CHECK_TEMPLATE_FULL_SPECIALIZATION
Check whether the template specialization syntax "template<>" is supported by the compiler value. So, try to compile, run and check the return value for the following code:
template<class T> struct toto {
int tutu() const { return 1; }
};
template<> struct toto<float> {
int tutu() const { return 0; }
};
main() {
toto<float> x;
return x.tutu();
}
If so, set the corresponding shell variable "rheo have template full specialization" to "yes"
and defines HAVE TEMPLATE FULL SPECIALIZATION. If not, set the variable no "no".
RHEO_CHECK_ISNAN_DOUBLE

Chapter 9: Internal others

179

RHEO_CHECK_ISINF_DOUBLE
RHEO_CHECK_FINITE_DOUBLE
RHEO_CHECK_INFINITY
RHEO_CHECK_ABS_DOUBLE
RHEO_CHECK_SQR_DOUBLE
Check whether the funtions
bool isnan(double);
bool isinf(double);
bool finite(double);
double infinity();
double abs();
double sqr();
are supported by the compiler, respectively. If so, set the corresponding shell variable
"rheo have xxx" to "yes" and defines HAVE XXX. If not, set the variable no "no".
RHEO_CHECK_FLEX
Check to see if the "flex" command and the corresponding header "FlexLexer.h" are available. If so, set the shell variable "rheo have flex" to "yes" and substitues FLEX to "flex"
and FLEXLEXER H to the full path for FlexLexer.h If not, set the shell variable no "no".
RHEO_PROG_CC_INTEL
Check wheter we are using INTEL C++ compiler. If so, set the shell variable "ac cv prog icc"
to "yes" and define HAVE INTEL CXX. If not, set the shell variable no "no". The shell
variable is also exported for sub-shells, such as ltconfig from libtool.
RHEO_RECOGNIZE_CXX
Check wheter we are able to recognize the C++ compiler. Tested compilers:
The GNU
C++ compiler that defines: __GNUC__ (egcs-1.1.1)
The INTEL C++ compiler that defines: __ICC
(ICPC-12)

If so, substitue RECOGNIZED CXX to a specific compilers rule file, e.g, "${top srcdir}/config/gnu cxx.mk
for a subsequent Makefile include. If not, substitue to "/dev/null". Substitutes also EXTRA LDFLAGS. Raw cc is the C compiler associated to the C++ one. By this way C and
C++ files are handled with a .c suffix. Special C files that requiere the cc compiler, such as
"alloca.c" use some specific makefile rule.
usage example:
AC_PROG_CC(gcc cc icc cl)
AC_PROG_CXX(c++ g++ cxx icpc KCC CC CC cc++ xlC aCC)
RHEO_RECOGNIZE_CXX
RHEO_GXX2011_PRE
Check for the "-std=c++0x" support for g++. Requires a recent version of the GNU C++
compiler (>= 4.5).
RHEO_GXX2011

180

Rheolef, the finite element system.

Check for the "-std=c++11" support for g++. Requires a recent version of the GNU C++
compiler (>= 4.7).
RHEO_OPTIMIZE_CXX
Set some optimization flags associated to the recognized C++ compiler and platform.
RHEO_CHECK_LATEX_HYPEREF
Check whether the hyperref LaTeX package exists and set the corresponding shell value
"rheo have latex hyperref" and HAVE LATEX HYPEREF (for Makefiles) accordingly.
RHEO_CHECK_MPI
Check for the "mpirun" command, the corresponding header "mpi.h" and library "-lmpi"
are available. If so, set the shell variable "rheo have mpi" to "yes", and substitues MPIRUN
to "mpirun" and RUN to "mpirun -np 2", INCLUDES MPI and LDADD MPI. If not, set
the shell variable no "no".
RHEO_CHECK_PARMETIS
Check for the "parmetis" and "metis" libraries. Defines HAVE PARMETIS and substitues
INCLUDES PARMETIS and LDADD PARMETIS. Requires the MPI library.
RHEO_CHECK_SCOTCH
Check for the "scotch" distributed mesh partitioner libraries. Defines HAVE SCOTCH and
substitues INCLUDES SCOTCH and LDADD SCOTCH. Requires the MPI library.
RHEO_CHECK_BOOST
Check for the "boost" library. Defines HAVE BOOST and substitues LDADD BOOST and
INCLUDES BOOST.
RHEO_CHECK_BLAS
Check for the "blas" basic linear algebra subroutines library. Defines HAVE BLAS and
substitues LDADD BLAS and INCLUDES BLAS.
RHEO_CHECK_SCALAPACK
Check for the "scalapack" basic linear algebra subroutines library. Defines HAVE SCALAPACK
and substitues LDADD SCALAPACK and INCLUDES SCALAPACK.
RHEO_CHECK_TRILINOS
Check for the "trilinos" distributed preconditioner libraries. Defines HAVE TRILINOS
and substitues INCLUDES TRILINOS and LDADD TRILINOS. Requires the MPI and
SCOTCH libraries.
RHEO_CHECK_PASTIX
Check for the "pastix" sequential or distributed direct solver libraries, depending on
the "rheo use distributed" shell variable. Defines HAVE PASTIX and substitues INCLUDES PASTIX and LDADD PASTIX.
RHEO_CHECK_MUMPS
Check for the "mumps" distributed direct solver libraries. Defines HAVE MUMPS and
substitues INCLUDES MUMPS and LDADD MUMPS. Requires the MPI and SCOTCH
libraries.
RHEO_CHECK_STD_INITIALIER_LIST

Chapter 9: Internal others

181

Some compilers (e.g. GNU C++ 4.4.x) does not support the std::initializer list feature.
Set the corresponding shell variable "rheo have std initializer list" to "yes" and defines
HAVE STD INITIALIZER LIST. If not, set the variable no "no".
RHEO_CHECK_CGAL
Check for the "cgal" computational geometry library. Defines HAVE CGAL and substitues
INCLUDES CGAL and LDADD CGAL.
RHEO_DEBIAN_FIX_LIBTOOL
Fix rpath libtool issue for debian packaging. See also http://wiki.debian.org/RpathIssue

182

Rheolef, the finite element system.

Chapter 10: FAQ for developers

183

10 FAQ for developers


This list of Frequently Asked Questions intended for Rheolef developers and maintainers.
Im looking for new questions (with answers, better answers, or both. Please, send suggestions to Pierre.Saramito@imag.fr.

10.1 How to regenerate the configure script


The configure script and makefiles are automatically produced from file configure.ac
and Makefile.am by using the autoconf and automake commands. Enter:
bootstrap

10.1.1 In which order does the things build ?


Let us look at with details the configure files flow:
[acinclude.m4] -----> aclocal* -----------> [aclocal.m4]
[configure.ac] -+
----------------+---> autoconf* ----------> configure
[aclocal.m4] ---+
[Makefile.am] ------> automake* ----------> Makefile.in
[config.h.in] -+
+-> config.h
|
|
Makefile.in ---+----> configure* -------+-> Makefile
|
|
[config.mk.in] +
+-> config.mk

10.1.2 What means these commands ?


Let us review the list of commands:
aclocal

take acinclude.m4 and build aclocal.m4. The arguments specifies that


these files are located in the config/ directory.

automake

translate every Makefile.am and then build a Makefile.in.

autoconf

translate configure.ac in configure which is an executable shell script.


The arguments specifies that aclocal.m4 is located in the config/ dirctory.
All this files are machine independent.

configure
the automatically generated script, scan the machine and translate config.h.in,
config.mk.in and every Makefile.in into config.h, config.mk and every Makefile, respectively. At this step, all produced files are machine
dependent.

184

Rheolef, the finite element system.

10.2 How to save my version ?


First, check that our distribution is valid
make distcheck
First, check that your modifications are not in conflict with others. Go to the top source
directory and enter:
make status

10.2.1 Easy: no conflicts with another developer


A listing of labeled files appears:
Modified
skit/lib/blas1_tst.c
Update
skit/lib/blas2_tst.c
Its mean that you have modified blas1_tst.c. Another concurrent developer has modified
blas2_tst.c, and your local file version is not up-to-date. There is no conflict, labeled
by a *Merge* label.
First, update your local version:
make update
Before to store your version of the Rheolef distribution, check the consistency by running
rnon-regression tests:
make distcheck
When all tests are ok:
make save
and enter a change log comment terminated by the ctrl-D key.
Check now that your version status is the most up-to-date Rheolef distribution:
make status

10.2.2 I have conflicts with another developer


The listing issued by make status looks like:
Modified
skit/lib/blas1_tst.c
Update
skit/lib/blas2_tst.c
*Merge*
skit/lib/blas3_tst.c
Its mean that you and another developer have modified at least one common line in
blas3_tst.c. Moreover, the developer has already saved his version in a previous Rheolef
distribution. You have now to merge these modifications. Thus, enter:
cd skit/lib
mv blas3_tst.c blas3_tst.c.new
cvs update blas3_tst.c
sdiff blas3_tst.c blas3_tst.c.new | more
and then edit blas3_tst.c to integrate the modifications of blas3_tst.c.new, generated
by another developer. When it is done, go to the top directory and enter,
make status
It prints new:

Chapter 10: FAQ for developers

185

Modified
skit/lib/blas1_tst.c
Update
skit/lib/blas2_tst.c
Modified
skit/lib/blas3_tst.c
The situation becomes mature:
make update
It will update the blas2_tst.c. Finally,
make save
that will save modified blas1_tst.c and blas3_tst.c.

10.2.3 I have deleted a source file...


I have entered:
rm Makefile.am
...aie !
How to restaure the file, now ?
Enter:
cvs update Makefile.am
You restaure the last available version of the missing file in the most up-to-date Rheolef
distribution.

186

Rheolef, the finite element system.

Appendix A: GNU General Public License

187

Appendix A GNU General Public License


Version 2, June 1991
c 1989, 1991 Free Software Foundation, Inc.
Copyright
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble
The licenses for most software are designed to take away your freedom to share and change
it. By contrast, the GNU General Public License is intended to guarantee your freedom
to share and change free softwareto make sure the software is free for all its users. This
General Public License applies to most of the Free Software Foundations software and to
any other program whose authors commit to using it. (Some other Free Software Foundation
software is covered by the GNU Library General Public License instead.) You can apply it
to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public
Licenses are designed to make sure that you have the freedom to distribute copies of free
software (and charge for this service if you wish), that you receive source code or can get
it if you want it, that you can change the software or use pieces of it in new free programs;
and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these
rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you
must give the recipients all the rights that you have. You must make sure that they, too,
receive or can get the source code. And you must show them these terms so they know
their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this
license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each authors protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by
someone else and passed on, we want its recipients to know that what they have is not the
original, so that any problems introduced by others will not reflect on the original authors
reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid
the danger that redistributors of a free program will individually obtain patent licenses, in
effect making the program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyones free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.

188

Rheolef, the finite element system.

TERMS AND CONDITIONS FOR COPYING,


DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed
by the copyright holder saying it may be distributed under the terms of this General
Public License. The Program, below, refers to any such program or work, and a
work based on the Program means either the Program or any derivative work under
copyright law: that is to say, a work containing the Program or a portion of it, either
verbatim or with modifications and/or translated into another language. (Hereinafter,
translation is included without limitation in the term modification.) Each licensee is
addressed as you.
Activities other than copying, distribution and modification are not covered by this
License; they are outside its scope. The act of running the Program is not restricted,
and the output from the Program is covered only if its contents constitute a work based
on the Program (independent of having been made by running the Program). Whether
that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Programs source code as you
receive it, in any medium, provided that you conspicuously and appropriately publish
on each copy an appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any warranty; and give
any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your
option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a
work based on the Program, and copy and distribute such modifications or work under
the terms of Section 1 above, provided that you also meet all of these conditions:
a. You must cause the modified files to carry prominent notices stating that you
changed the files and the date of any change.
b. You must cause any work that you distribute or publish, that in whole or in part
contains or is derived from the Program or any part thereof, to be licensed as a
whole at no charge to all third parties under the terms of this License.
c. If the modified program normally reads commands interactively when run, you
must cause it, when started running for such interactive use in the most ordinary
way, to print or display an announcement including an appropriate copyright notice
and a notice that there is no warranty (or else, saying that you provide a warranty)
and that users may redistribute the program under these conditions, and telling
the user how to view a copy of this License. (Exception: if the Program itself is
interactive but does not normally print such an announcement, your work based
on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections
of that work are not derived from the Program, and can be reasonably considered
independent and separate works in themselves, then this License, and its terms, do not
apply to those sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based on the Program,
the distribution of the whole must be on the terms of this License, whose permissions

Appendix A: GNU General Public License

189

for other licensees extend to the entire whole, and thus to each and every part regardless
of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to
work written entirely by you; rather, the intent is to exercise the right to control the
distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the
Program (or with a work based on the Program) on a volume of a storage or distribution
medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2)
in object code or executable form under the terms of Sections 1 and 2 above provided
that you also do one of the following:
a. Accompany it with the complete corresponding machine-readable source code,
which must be distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
b. Accompany it with a written offer, valid for at least three years, to give any third
party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium customarily
used for software interchange; or,
c. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form
with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code
for all modules it contains, plus any associated interface definition files, plus the scripts
used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major components (compiler,
kernel, and so on) of the operating system on which the executable runs, unless that
component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from
a designated place, then offering equivalent access to copy the source code from the
same place counts as distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly
provided under this License. Any attempt otherwise to copy, modify, sublicense or
distribute the Program 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.
5. You are not required to accept this License, since you have not signed it. However,
nothing else grants you permission to modify or distribute the Program or its derivative
works. These actions are prohibited by law if you do not accept this License. Therefore,
by modifying or distributing the Program (or any work based on the Program), you

190

Rheolef, the finite element system.

indicate your acceptance of this License to do so, and all its terms and conditions for
copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the
recipient automatically receives a license from the original licensor to copy, distribute
or modify the Program subject to these terms and conditions. You may not impose
any further restrictions on the recipients exercise of the rights granted herein. You are
not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any
other reason (not limited to patent issues), conditions are imposed on you (whether by
court order, agreement or otherwise) that contradict the conditions of this License, they
do not excuse you from the conditions of this License. If you cannot distribute so as
to satisfy simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Program at all. For
example, if a patent license would not permit royalty-free redistribution of the Program
by all those who receive copies directly or indirectly through you, then the only way
you could satisfy both it and this License would be to refrain entirely from distribution
of the Program.
If any portion of this section is held invalid or unenforceable under any particular
circumstance, the balance of the section is intended to apply and the section as a
whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other
property right claims or to contest validity of any such claims; this section has the
sole purpose of protecting the integrity of the free software distribution system, which
is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on
consistent application of that system; it is up to the author/donor to decide if he or
she is willing to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence
of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either
by patents or by copyrighted interfaces, the original copyright holder who places the
Program under this License may add an explicit geographical distribution limitation
excluding those countries, so that distribution is permitted only in or among countries
not thus excluded. In such case, this License incorporates the limitation as if written
in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General
Public License from time to time. Such new versions will be similar in spirit to the
present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a
version number of this License which applies to it and any later version, you have
the option of following the terms and conditions either of that version or of any later
version published by the Free Software Foundation. If the Program does not specify a
version number of this License, you may choose any version ever published by the Free
Software Foundation.

Appendix A: GNU General Public License

191

10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software
which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two
goals of preserving the free status of all derivatives of our free software and of promoting
the sharing and reuse of software generally.

NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED
ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT
LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

END OF TERMS AND CONDITIONS

192

Rheolef, the finite element system.

How to Apply These Terms to Your New Programs


If you develop a new program, and you want it to be of the greatest possible use to the public,
the best way to achieve this is to make it free software which everyone can redistribute and
change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the
start of each source file to most effectively convey the exclusion of warranty; and each file
should have at least the copyright line and a pointer to where the full notice is found.
one line to give the programs name and an idea of what it does.
Copyright (C) 19yy name of author
This program is
modify it under
as published by
of the License,

free software; you can redistribute it and/or


the terms of the GNU General Public License
the Free Software Foundation; either version 2
or (at your option) any later version.

This program is distributed in the hope that it will be useful,


but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an
interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type show w. This is free software, and you are welcome
to redistribute it under certain conditions; type show c
for details.
The hypothetical commands show w and show c should show the appropriate parts of the
General Public License. Of course, the commands you use may be called something other
than show w and show c; they could even be mouse-clicks or menu itemswhatever suits
your program.
You should also get your employer (if you work as a programmer) or your school, if any,
to sign a copyright disclaimer for the program, if necessary. Here is a sample; alter the
names:
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program Gnomovision
(which makes passes at compilers) written
by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice

Appendix A: GNU General Public License

193

This General Public License does not permit incorporating your program into proprietary
programs. If your program is a subroutine library, you may consider it more useful to permit
linking proprietary applications with the library. If this is what you want to do, use the
GNU Library General Public License instead of this License.

194

Rheolef, the finite element system.

Concept Index

195

Concept Index
A

animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13, 38
axisymmetric coordinate system . . . . . . . . . . . 23, 29
axisymmetric geometry . . . . . . . . . . . . . . . . . . . . . . . 53

image file format . . . . . . . . . . . . . . . . . . . . . 16, 21, 172


incompresible elasticity . . . . . . . . . . . . . . . . . . 99, 117
installing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3, 34
integrate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
iterative solver . . . . . . . . . . . . . . . . 118, 120, 123, 126

B
bilinear form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

C
cemagref topographic mesh . . . . . . . . . . . . . . . . . 171
Choleski factorization . . . . . . . . . . . . . . . . . . . . . . . . 97
configure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
conjugate gradien algorithm . . . . . . . . . . . . . . 99, 117
conjugate gradient algorithm . . . . . . . . . . . . 118, 123
continuation methods . . . . . . . . . . . . . . . . . . . . . 13, 38
corner singularity . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

D
debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6, 176
deformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
diagonal matrix . . . . . . . . . . . . . . . . . . . . . . . . . 94, 116
direct solver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

E
edge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
elevation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 170
environment sanity check writes. . . . . . . . . . . . . . . 34

F
FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
finite element method. . . . . . . . . . . . . . . . . . . . 99, 117

G
generalized minimum residual method . . . . . . . . 120
geometrical element . . . . . . . . . . . . . . . . . . . . 133, 137
graphic render . . . . . . . . . . . . . . . . . . 16, 21, 169, 172

H
hexaedron . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

L
Lagrange-Galerkin method . . . . . . . . . . . . . . . . . . . 39
local matrix inversion . . . . . . . . . . . . . . . . . . . . . . . . 53

M
Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mass lumping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
mesh . . . . . . . . . . . . . . . . . . . . . . 22, 23, 25, 27, 29, 31
mesh boundary . . . . . . . . . . . . . . . . . . . . 130, 134, 135
mesh graphic representation . . . . . . . . . . . . . . . . . . 19
mesh order. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26, 31
method of characteristic . . . . . . . . . . . . . . . . . . . . . . 39
mixed linear problem . . . . . . . . . . . . . . . . . . . . 99, 117
multifrontal linear solver . . . . . . . . . . . . . . . . . . . . 4, 8

N
Newton method . . . . . . . . . . . . . . . . . . . 109, 110, 113
nonlinear problem . . . . . . . . . . . . . . . . . 109, 110, 113
numbering, global degree of freedom . . . . . . . . . 135

O
out-of-core sparse linear solver . . . . . . . . . . . . . . . . . 8

P
plotting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15, 19
plotting data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
plotting mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
polynomial basis . . . . . . . . . . . . . . . . . . . . . . . 129, 135
porting the code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
preconditioner . . . . . . . . . . . . . . . . . . . . . 118, 123, 126
prism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
projection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 17

196

Q
quadrangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
quadrature formula . . . . . . . . . . . . . . . . . . . . . . . . . 114
quadrature formulae . . . . . . . . . . . . . . . . . 39, 72, 147
quarature formula . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

R
reference counting . . . . . . . . . . . . . . . . . . . . . . . . . . 159
reference element . . . . 129, 136, 143, 145, 146, 149,
151, 153
RHEOPATH environment variable . . . . . 13, 16, 20,
103
riesz representer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

Rheolef, the finite element system.

Stokes problem . . . . . . . . . . . . . . . . . . . . . . . . . . 99, 117


stream function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
supernodal factorization . . . . . . . . . . . . . . . . . . . . . . 97

T
tensor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
tensor3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
tensor4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
tetrahedron . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
time-dependent problems . . . . . . . . . . . . . . . . . 13, 38
topography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 171
triangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

U
S
shallow copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
smart pointer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
sparse matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
stabilized mixed finite element method . . . . 99, 117
standard template library (STL) . . . . . . . . . . . . . . . 5
stereo 3D rendering . . . . . . . . . . . . . . . . . . . . . . . . 21

Uzawa algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

V
velocity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
version management . . . . . . . . . . . . . . . . . . . . . . . . 185
vorticity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Program Index

197

Program Index
B
bamg2geo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
branch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

geo . . . . . . . . . . . . . . . . . . . . . . . . 19, 22, 23, 25, 27, 29


gmsh . . . . . . . . . . . . . . . . . . . . . . . . 26, 29, 31, 143, 151

L
C

latex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

configure. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

M
D
dmalloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6, 176

mfield . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 172


mkgeo_ball . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
mkgeo_grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
mkgeo_ugrid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
msh2geo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143, 151

field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 15

R
G

rheolef-config . . . . . . . . . . . . . . . . . . . . . . . . . . . 4, 34

198

Rheolef, the finite element system.

Class Index

199

Class Index
A

adapt_option_type . . . . . . . . . . . . . . . . . . . . . . . . . 107

orheostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

basis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129, 133

permutation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68, 73

C
catchmark. . . . . . . . . . . . . . . . . . . . . . . . . . 16, 127, 172
csr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97, 116, 169

Q
quadrature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72, 147

D
dia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94, 116
domain_indirect . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

R
reference element . . . . . . . . . . . . . . . . . . . . . . . . . 137
reference_element . . . . . . . . 72, 129, 137, 147, 149

F
field . . . . . . . . . . 37, 38, 73, 107, 112, 114, 127, 169
Float . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

smart_pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
smart_pointer_clone . . . . . . . . . . . . . . . . . . . . . . . 159
solver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
space . . . . . . . . . . . . . . . . . . . . . . . . . . 39, 63, 112, 114

geo . . . . . . . . . . . . . 19, 37, 39, 68, 107, 112, 137,


geo_domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
geo_domain_indirect_rep . . . . . . . . . . . . . . . . . .
geo_element . . . . . . . . . . . . . . . . . . . . . . . . . . . 133,

169
134
135
137

I
iorheo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103, 169
irheostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

T
tensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
tensor3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
tensor4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

V
N
numbering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133, 135

vec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94, 97, 116


Vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

200

Rheolef, the finite element system.

Approximation Index

201

Approximation Index
P0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

P1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

202

Rheolef, the finite element system.

Function Index

203

Function Index
A

adapt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
append_dir_to_rheo_path . . . . . . . . . . . . . . . . . . 103

level_set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37, 112

D
damped\_newton. . . . . . . . . . . . . . . . . . . . . . . . 109, 110
delete_suffix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
dual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

N
newton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
normal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

P
F
fastfieldload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
file_exists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
ftos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

G
get_basename . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
get_dirname . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
get_full_name_from_rheo_path . . . . . . . . . . . . . 103

pcg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117,
pcg\_abtb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
pcg\_abtbc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
pminres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117,
pminres\_abtb . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
pminres\_abtbc . . . . . . . . . . . . . . . . . . . . . . . . . . . .
prepend_dir_to_rheo_path . . . . . . . . . . . . . . . . .
puzawa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

118
117
117
123
117
117
103
126

Q
qmr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

H
has_suffix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

I
integrate. . . . . . . . . . . . . . . . . . . . . . . . . . 53, 110, 115
interpolate . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41, 112
itos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

R
riesz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39, 114

S
scatch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

204

Rheolef, the finite element system.

File Format Index

205

File Format Index


.
.1, .3,... unix manual pages . . . . . . . . . . . . . . . . . 3
.atom PlotM mesh . . . . . . . . . . . . . . . . . . . . 169, 170
.bamg bamg mesh . . . . . . . . . . . . . . . . . . . 23, 31, 170
.bamg mesh file . . . . . . . . . . . . . . . . . . . . . . . . . 16, 20
.bamg_bb data file . . . . . . . . . . . . . . . . . . . . . . . . . . 16
.branch family of fields . . . . . . . . . . . . . . . . . . . . . 13
.cemagref cemagref topographic mesh . . . . . . 171
.dmn domain names . . . . . . . . . . . . . . . . . . . . . . . . . 23
.ele tetgen mesh elements . . . . . . . . . . . . . . . . . 170
.face tetgen mesh boundary faces . . . . . . . . . . 170
.field field . . . . . . . . . . . . . . . . . . . . 14, 15, 169, 170
.gdat gnuplot data . . . . . . . . . . . . . . . . . . . . . . . . 169
.geo mesh . . . . . . . . . . . 22, 23, 25, 27, 29, 169, 170
.gif image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16, 21
.gmsh gmsh mesh . . . . . . . . . . . . . . . . . . . . . . . . . . 170
.gmsh mesh file . . . . . . . . . . . . . . . . . . . . . . . . . 16, 21
.gmsh_pos data file . . . . . . . . . . . . . . . . . . . . . . . . . 16
.gmsh_pos gmsh metric mesh . . . . . . . . . . . . . . . 170
.gz gzip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
.hb Harwell-Boeing matrix. . . . . . . . . . . . . 169, 170
.info GNU info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
.jpg image . . . . . . . . . . . . . . . . . . . . . . . . . 16, 21, 172
.m grummp bidimensionnal mesh . . . . . . . . . . . 170
.m matlab matrix . . . . . . . . . . . . . . . . . . . . . . . . . . 170
.mesh mmg3d mesh . . . . . . . . . . . . . . . . . . . . . . . . 170
.mm Matrix-Market matrix . . . . . . . . . . . . . . . . . 169

.msh gmsh mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22


.mtv plotmtv . . . . . . . . . . . . . . . . . . . . . . . . . 169, 170
.node tetgen mesh nodes . . . . . . . . . . . . . . . . . . . 170
.off geomview data . . . . . . . . . . . . . . . . . . . . . . . 169
.pdf image . . . . . . . . . . . . . . . . . . . . . . . . . 16, 21, 172
.plot gnuplot script. . . . . . . . . . . . . . . . . . . 169, 170
.png image . . . . . . . . . . . . . . . . . . . . . . . . . 16, 21, 172
.ps image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16, 21
.ps postscript. . . . . . . . . . . . . . . . . . . . . . . . . . . 3, 170
.py python script file (for mayavi visualization
tool) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
.tcl tool command language . . . . . . . . . . . . . . . 169
.v grummp tridimensionnal mesh . . . . . . . . . . . 170
.vtk mesh file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
.vtk visualization toolkit . . . . . . . . . . . . . . 169, 170
.x3d x3d mesh . . . . . . . . . . . . . . . . . . . . . . . . 169, 170

A
acinclude.m4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

C
configure.ac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

M
Makefile.am . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

206

Rheolef, the finite element system.

Related Tool Index

207

Related Tool Index


A

aclocal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
autoconf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175, 183
automake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
intel c++ compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
irix, operating system . . . . . . . . . . . . . . . . . . . . . . . . . 5

B
bamg . . . . . . . . . . . . . . . . . . . . . . . . . . 16, 20, 21, 23, 31
bamg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
bamg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
bash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
blas, basic linear algebra subroutines . . . . . . . . . . . 7
boost, extensions of the c++ standard template
library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
boost, generic dense/sparse matrix library . . . . . . 6

C
cgal, computational geometry library . . . . . . . . . 4, 8
cln, arbitrary precision float library . . . . . . . . . . . . 6
cray c++ compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
cray unicos, operating system . . . . . . . . . . . . . . . . . . 5
csh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
cvs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

K
kai c++ compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

M
mac osx, operating system . . . . . . . . . . . . . . . . . . . . . 5
make . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3, 185
Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3, 6
man . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
mayavi . . . . . . . . . . . . . . . . . . . . . . . . . . . 5, 16, 21, 171
mmg3d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
mpi, message passing interface . . . . . . . . . . . . . . . . . 4
msh2geo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
mumps, distributed direct solver . . . . . . . . . . . . . . . 7
mumps, multifrontal massively distributed sparse
direct solver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

D
debian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
dmalloc, debug runtime library . . . . . . . . . . . . 6, 176
doubledouble, quadruple precision library . . . . . . . 6

G
geomview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
ghostview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
ginac, not a computer algebra system . . . . . . . . . . 5
gmsh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5, 16, 21, 22
gmsh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
gnu c++ compiler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
gnuplot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
gnuplot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
gnuplot . . . . . . . . . . . . . . . . . . . . . . . . 16, 21, 169, 170
gzip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

H
hpux, operating system . . . . . . . . . . . . . . . . . . 4, 5, 34

P
paraview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
paraview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
parmetis, distributed mesh partitioner . . . . . . . . . . 7
pastix, distributed direct solver . . . . . . . . . . . . . . . . 7
pastix, multifrontal solver library . . . . . . . . . . . . . 97
PlotM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169, 170
plotmtv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
plotmtv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169, 170

S
scalapack, scalable linear algebra package . . . . . . .
scotch, distributed mesh partitioner . . . . . . . . . . . .
scotch, mesh partitioner . . . . . . . . . . . . . . . . . . . . . . .
sh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
spooles, multifrontal solver library . . . . . . . . . . . . .

7
7
4
3
8

208

T
taucs, out-of-core sparse solver library . . . . . . . . . . 8
tetgen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
trilinos, distributed incomplete choleski
factorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
trilinos, large-scale object-oriented solvers
framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Rheolef, the finite element system.

umfpack, sequential multifrontal solver library . . 8

V
vtk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
vtk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20, 169, 170

X
U

x3d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

Short Contents
1
Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2
Installing rheolef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3
Reporting Bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4
Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5
Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6
Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
7
Internal classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
8
Internal algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
9
Internal others . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
10 FAQ for developers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
Appendix A GNU General Public License . . . . . . . . . . . . . . . 187
Concept Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
Program Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Class Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Approximation Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Function Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
File Format Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Related Tool Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

ii

Rheolef, the finite element system.

iii

Table of Contents
1

Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Installing rheolef . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1 Reading the documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Using and alternative installation directory . . . . . . . . . . . . . . . .
2.3 Requiered libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4 Highly recommended libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.5 Run-time optional tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6 Build-time extra tools for rheolef developpers . . . . . . . . . . . . . .
2.7 Portability issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.8 Future configure options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9 The directory structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3
3
4
4
5
5
5
8
9

Reporting Bugs. . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.1
4.2
4.3
4.4
4.5
4.6

branch handle a family of fields . . . . . . . . . . . . . . . . . . . . . . . 13


field plot a field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
geo - plot a finite element mesh . . . . . . . . . . . . . . . . . . . . . . . . . 19
msh2geo - convert gmsh mesh in geo format . . . . . . . . . . . . . . 22
bamg2geo - convert bamg mesh in geo format . . . . . . . . . . . . . 23
mkgeo_ball build an unstructured mesh of an ellipsoid, in
2d or 3d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.7 mkgeo_grid build a strutured mesh of a parallelotope, in 1d,
2d or 3d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.8 mkgeo_ugrid build an unstructured mesh of a parallelotope,
in 1d, 2d or 3d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.9 bamg - bidimensional anisotropic mesh generator . . . . . . . . . . 31
4.10 rheolef-config get installation directories . . . . . . . . . . . 34

Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.1 band - compute the band arround a level set . . . . . . . . . . . . .
5.2 branch - a parameter-dependent sequence of field . . . . . . . . .
5.3 characteristic - the Lagrange-Galerkin method
implemented . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4 field - piecewise polynomial finite element field . . . . . . . . . .
5.5 field_functor - a functor wrapper suitable for field
expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.6 form - representation of a finite element bilinear form . . . . .
5.7 form_option_type - send options to the integrate function
.......................................................
5.8 trial, test, generic - symbolic forms arguments . . . . . . . .

37
38
39
41
47
48
53
54

iv

Rheolef, the finite element system.


5.9 geo - finite element mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.10 space piecewise polynomial finite element space . . . . . . . 63
5.11 test, trial - symbolic arguments in variational expressions
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.12 point - vertex of a mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.13 quadrature_option_type - send options to the integrate
function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
5.14 tensor - a N*N tensor, N=1,2,3 . . . . . . . . . . . . . . . . . . . . . . . . 73
5.15 tensor3 - a third order tensor . . . . . . . . . . . . . . . . . . . . . . . . . 77
5.16 tensor4 - a fouth order tensor . . . . . . . . . . . . . . . . . . . . . . . . . 78
5.17 array - container in distributed environment . . . . . . . . . . . . 79
5.18 asr - associative sparse matrix . . . . . . . . . . . . . . . . . . . . . . . . . 85
5.19 csr - compressed sparse row matrix . . . . . . . . . . . . . . . . . . . . 87
5.20 dia - diagonal matrix. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
5.21 distributor - data distribution table . . . . . . . . . . . . . . . . . . 95
5.22 eye - the identity matrix. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
5.23 solver - direct or interative solver interface . . . . . . . . . . . . . 97
5.24 solver_abtb direct or iterative solver iterface for mixed
linear systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
5.25 vec - vector in distributed environment . . . . . . . . . . . . . . . . 101
5.26 irheostream, orheostream - large data streams . . . . . . . . 103

Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
6.1
6.2
6.3
6.4
6.5
6.6
6.7
6.8
6.9
6.10

adapt - mesh adaptation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


damped_newton damped Newton nonlinear algorithm . . .
damped_newton damped Newton nonlinear algorithm . . .
integrate - integrate a function or an expression . . . . . . . .
interpolate - Lagrange interpolation of a function . . . . . .
level_set - compute a level set from a function . . . . . . . . .
newton Newton nonlinear algorithm . . . . . . . . . . . . . . . . . .
riesz - approximate a Riesz representer . . . . . . . . . . . . . . . .
diag - get diagonal part of a matrix . . . . . . . . . . . . . . . . . . . .
pcg_abtb, pcg_abtbc, pminres_abtb, pminres_abtbc
solvers for mixed linear problems . . . . . . . . . . . . . . . . . . . . . . . .
6.11 pcg conjugate gradient algorithm. . . . . . . . . . . . . . . . . . . .
6.12 pgmres generalized minimum residual method . . . . . . . .
6.13 pminres conjugate gradient algorithm. . . . . . . . . . . . . . . .
6.14 puzawa Uzawa algorithm. . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.15 catchmark - iostream manipulator . . . . . . . . . . . . . . . . . . . . .

107
109
110
110
112
112
113
114
116
117
118
120
123
126
127

Internal classes . . . . . . . . . . . . . . . . . . . . . . . . . . 129


7.1
7.2

basis - polynomial basis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129


domain_indirect - a named part of a finite element mesh
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
7.3 form_element - bilinear form on a single element . . . . . . . . 133
7.4 geo_domain - a named part of a finite element mesh that
behaves as a mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
7.5 geo_domain_indirect_rep - a named part of a finite element
mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
7.6 numbering - global degree of freedom numbering . . . . . . . . 135
7.7 edge - Edge reference element . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.8 geo_element - element of a mesh . . . . . . . . . . . . . . . . . . . . . . . 137
7.9 hack array - container in distributed environment . . . . . . . . 138
7.10 hexahedron - Hexaedron reference element . . . . . . . . . . . . . 143
7.11 point - Point reference element . . . . . . . . . . . . . . . . . . . . . . . 145
7.12 prism - Prism reference element . . . . . . . . . . . . . . . . . . . . . . . 145
7.13 quadrangle - Quadrangular reference element . . . . . . . . . . 146
7.14 quadrature - quadrature formulae on the reference lement
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
7.15 reference_element - reference element . . . . . . . . . . . . . . . . 149
7.16 tetrahedron - Tetraedron reference element . . . . . . . . . . . 151
7.17 triangle - Triangle reference element . . . . . . . . . . . . . . . . . 153
7.18 index set - a set of indexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
7.19 pair set - a set of (index,value) pair . . . . . . . . . . . . . . . . . . . . 155
7.20 heap allocator - heap-based allocator . . . . . . . . . . . . . . . . . . 156
7.21 smart_pointer, smart_pointer_clone - reference counted
safe pointer with true copy semantic . . . . . . . . . . . . . . . . . . . . 159
7.22 stack allocator - stack-based allocator. . . . . . . . . . . . . . . . . . 161
7.23 Vector - STL vector<T> with reference counting . . . . . . . 165

Internal algorithms . . . . . . . . . . . . . . . . . . . . . . 169


8.1 iorheo - input and output functions and manipulation . . . 169
8.2 typename_macro, pretty_typename_macro - type demangler
and pretty printer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

Internal others . . . . . . . . . . . . . . . . . . . . . . . . . . 175


9.1 acinclude autoconf macros . . . . . . . . . . . . . . . . . . . . . . . . . . 175

10

FAQ for developers . . . . . . . . . . . . . . . . . . . . . 183


10.1

How to
10.1.1
10.1.2
10.2 How to
10.2.1
10.2.2
10.2.3

regenerate the configure script . . . . . . . . . . . . . . .


In which order does the things build ? . . . . . . . . .
What means these commands ? . . . . . . . . . . . . . . .
save my version ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Easy: no conflicts with another developer . . . . .
I have conflicts with another developer . . . . . . . .
I have deleted a source file... . . . . . . . . . . . . . . . . . .

183
183
183
184
184
184
185

vi

Rheolef, the finite element system.

Appendix A

GNU General Public License . . 187

Preamble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
AND MODIFICATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
How to Apply These Terms to Your New Programs . . . . . . . . . . . 192

Concept Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195


Program Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Class Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Approximation Index . . . . . . . . . . . . . . . . . . . . . . . 201
Function Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
File Format Index. . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Related Tool Index . . . . . . . . . . . . . . . . . . . . . . . . . 207

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy