Getfem Userdoc
Getfem Userdoc
Release 5.4.2
1 Introduction 1
2 How to install 3
5 Catch errors 11
6 Build a mesh 13
6.1 Add an element to a mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
6.2 Remove an element from a mesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
6.3 Simple structured meshes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
6.4 Mesh regions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
6.5 Methods of the getfem::mesh object . . . . . . . . . . . . . . . . . . . . . . . . . 17
6.6 Using dal::bit_vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
6.7 Face numbering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
6.8 Save and load meshes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
9 Mesh refinement 33
i
10.2 Some basic examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
10.3 Derivation order and symbolic differentiation . . . . . . . . . . . . . . . . . . . . . . . 38
10.4 C++ Call of the assembly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
10.5 C++ assembly examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
10.6 Script languages call of the assembly . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
10.7 The tensors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
10.8 The variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
10.9 The constants or data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
10.10 Test functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
10.11 Gradient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
10.12 Hessian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
10.13 Predefined scalar functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
10.14 User defined scalar functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
10.15 Derivatives of defined scalar functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
10.16 Binary operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
10.17 Unary operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
10.18 Parentheses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
10.19 Explicit vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
10.20 Explicit matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
10.21 Explicit tensors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
10.22 Access to tensor components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
10.23 Constant expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
10.24 Special expressions linked to the current position . . . . . . . . . . . . . . . . . . . . . 48
10.25 Print command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
10.26 Reshape a tensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
10.27 Trace, Deviator, Sym and Skew operators . . . . . . . . . . . . . . . . . . . . . . . . . 49
10.28 Nonlinear operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
10.29 Macro definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
10.30 Explicit Differentiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
10.31 Explicit Gradient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
10.32 Interpolate transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
10.33 Element extrapolation transformation . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
10.34 Evaluating discontinuities across inter-element edges/faces . . . . . . . . . . . . . . . . 55
10.35 Double domain integrals or terms (convolution - Kernel - Exchange integrals) . . . . . . 56
10.36 Elementary transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
10.37 Xfem discontinuity evaluation (with mesh_fem_level_set) . . . . . . . . . . . . . . . . 58
10.38 Storage of sub-expressions in a getfem::im_data object during assembly . . . . . . . . . 59
ii
14 Incorporate new finite element methods in GetFEM 73
20 Compute derivatives 93
iii
23.19 Linear incompressibility (or nearly incompressibility) brick . . . . . . . . . . . . . . . 126
23.20 Mass brick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
23.21 Bilaplacian and Kirchhoff-Love plate bricks . . . . . . . . . . . . . . . . . . . . . . . 128
23.22 Mindlin-Reissner plate model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
23.23 The model tools for the integration of transient problems . . . . . . . . . . . . . . . . . 131
23.24 Small sliding contact with friction bricks . . . . . . . . . . . . . . . . . . . . . . . . . 139
23.25 Large sliding/large deformation contact with friction bricks . . . . . . . . . . . . . . . 151
27 ALE Support for object having a large rigid body motion 193
27.1 ALE terms for rotating objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
27.2 ALE terms for a uniformly translated part of an object . . . . . . . . . . . . . . . . . . 196
30 References 247
Bibliography 249
iv
Index 253
v
vi
CHAPTER 1
Introduction
The GetFEM project focuses on the development of a generic and efficient C++ library for finite element
methods elementary computations. The goal is to provide a library allowing the computation of any
elementary matrix (even for mixed finite element methods) on the largest class of methods and elements,
and for arbitrary dimension (i.e. not only 2D and 3D problems).
It offers a complete separation between integration methods (exact or approximated), geometric trans-
formations (linear or not) and finite element methods of arbitrary degrees. It can really relieve a more
integrated finite element code of technical difficulties of elementary computations.
Examples of available finite element method are : Pk on simplices in arbitrary degrees and dimensions,
Qk on parallelepipeds, P1, P2 with bubble functions, Hermite elements, elements with hierarchic basis
(for multigrid methods for instance), discontinuous Pk or Qk, XFem, Argyris, HCT, Raviart-Thomas,
etc.
The addition of a new finite element method is straightforward. Its description on the reference element
must be provided (in most of the cases, this is the description of the basis functions, and nothing more).
Extensions are provided for Hermite elements, piecewise polynomial, non-polynomial and vectorial
elements, XFem.
The library also includes the usual tools for finite elements such as assembly procedures for classi-
cal PDEs, interpolation methods, computation of norms, mesh operations, boundary conditions, post-
processing tools such as extraction of slices from a mesh, etc.
GetFEM can be used to build very general finite elements codes, where the finite elements, integration
methods, dimension of the meshes, are just some parameters that can be changed very easily, thus al-
lowing a large spectrum of experimentations. Numerous examples are available in the tests directory
of the distribution.
GetFEM has only a (very) experimental meshing procedure (and produces regular meshes), hence it is
generally necessary to import meshes. Imports formats currently known by GetFEM are GiD, Gmsh and
emc2 mesh files. However, given a mesh, it is possible to refine it automatically.
Copyright © 2004-2022 GetFEM project.
The text of the GetFEM website and the documentations are available for modification and reuse under
the terms of the GNU Free Documentation License
1
User Documentation, Release 5.4.2
GetFEM is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version along with the GCC Runtime Library Exception either version
3.1 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 Lesser General Public License and GCC
Runtime Library Exception for more details. You should have received a copy of the GNU Lesser
General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
2 Chapter 1. Introduction
CHAPTER 2
How to install
Since we use standard GNU tools, the installation of the GetFEM library is somewhat standard. See the
download and install page for more details for the installations on the different plateforms.
3
User Documentation, Release 5.4.2
The linear algebra library used by GetFEM is Gmm++ which is now a separate library. Please see the
GMM++ user documentation.
Note that GetFEM includes (since release 1.7) its own version of SuperLU 3.0 (see SuperLU web site)
hence a direct sparse solver is available out of the box. Note that an option of the ./configure file
allows to disable the included version of SuperLU in order to use a pre-installed version.
A small interface to MUMPS is also provided (see MUMPS web1 or MUMPS web2). See the file gmm/
gmm_MUMPS_interface.h. In order to use MUMPS, you have to indicates some options to the
configure shell:
alternatively, the option --enable-mumps will search for an installed MUMPS library. Note that
if both the sequential and the parallel version is installed on your system (especially on Debian
and Ubuntu), the default version will be the parallel one. To select the sequential one it is nec-
essary to add the option --with-mumps="-lsmumps_seq -ldmumps_seq -lcmumps_seq
-lzmumps_seq".
For instance if you want to use the sequential version of MUMPS with double and complex double:
where ...F90libs... are the libraries of the fortran compiler used to compile MUMPS (these are
highly dependant on the fortran 90 compiler used, the ./configure script should detect the options
relative to the default fortran 90 compiler on your machine and display it – for example, with the intel
ifort compiler, it is -L/opt/icc8.0/lib -lifport -lifcoremt -limf -lm -lcxa
-lunwind -lpthread)
5
User Documentation, Release 5.4.2
Of course, each different problem should require a different parallelization adapted to its specificities in
order to obtain a good load balancing. You may build your own parallelization using the mesh regions
to parallelize assembly procedures.
Nevertheless, the brick system offers a generic parallelization based on Open MPI (communication
between processes), METIS (partition of the mesh) and MUMPS (parallel sparse direct solver). It is
available with the compiler option -D GETFEM_PARA_LEVEL=2 and the library itself has to be com-
piled with the option --enable-paralevel=2 of the configure script. Initial MPI parallelization of
GetFEM has been designed with the help of Nicolas Renon from CALMIP, Toulouse.
When the configure script is run with the option --enable-paralevel=2, it searches for MPI,
METIS and parallel MUMPS libraries. If the python interface is built, it searches also for MPI4PY
library. In that case, the python interface can be used to drive the parallel version of getfem (the
other interfaces has not been parallelized for the moment). See demo_parallel_laplacian.py in the inter-
face/test/python directory.
With the option -D GETFEM_PARA_LEVEL=2, each mesh used is implicitly partitionned (using
METIS) into a number of regions corresponding to the number of processors and the assembly pro-
cedures are parallelized. This means that the tangent matrix and the constraint matrix assembled in the
model_state variable are distributed. The choice made (for the moment) is not to distribute the vectors.
So that the right hand side vectors in the model_state variable are communicated to each processor (the
sum of each contribution is made at the end of the assembly and each processor has the complete vector).
Note that you have to think to the fact that the matrices stored by the bricks are all distributed.
A model of C++ parallelized program is tests/elastostatic.cc. To run it in parallel you have
to launch for instance:
7
User Documentation, Release 5.4.2
If you do not perform a make install, do not forget to first set the shell variable PYTHONPATH to the
python-getfem library with for instance:
export PYTHONPATH=my_getfem_directory/interface/src/python
Parallelization of getfem is still considered a “work in progress”. A certain number of procedure are still
remaining sequential. Of course, a good test to see if the parallelization of your program is correct is to
verify that the result of the computation is indeed independent of the number of process.
• Assembly procedures
Most of assembly procedures (in getfem/getfem_assembling.h) have a parameter cor-
responding to the region in which the assembly is to be computed. They are not paral-
lelized themselves but aimed to be called with a different region in each process to dis-
tribute the job. Note that the file getfem/getfem_config.h contains a procedures called
MPI_SUM_SPARSE_MATRIX allowing to gather the contributions of a distributed sparse ma-
trix.
The following assembly procedures are implicitly parallelized using the option -D
GETFEM_PARA_LEVEL=2:
– computation of norms (asm_L2_norm, asm_H1_norm, asm_H2_norm . . . , in
getfem/getfem_assembling.h),
– asm_mean_value (in getfem/getfem_assembling.h),
– error_estimate (in getfem/getfem_error_estimate.h).
This means in particular that these functions have to be called on each processor.
• Mesh_fem object
The dof numbering of the getfem::mesh_fem object remains sequential and is executed on each
process. The parallelization is to be done. This could affect the efficiency of the parallelization
for very large and/or evoluting meshes.
• Model object and bricks
The model system is globally parallelized, which mainly means that the assembly procedures
of standard bricks use a METIS partition of the meshes to distribute the assembly. The tan-
gent/stiffness matrices remain distibuted and the standard solve call the parallel version of
MUMPS (which accept distributed matrices).
For the moment, the procedure actualize_sizes() of the model object remains sequential
and is executed on each process. The parallelization is to be done.
Some specificities:
– The explicit matrix brick: the given matrix is considered to be distributed. If it is not, only
add it on the master process (otherwise, the contribution will be multiplied by the number of
processes).
– The explicit rhs brick: the given vector is not considered to be distributed. Only the given
vector on the master process is taken into account.
– Constraint brick: The given matrix and rhs are not considered to be distributed. Only the
given matrix and vector on the master process are taken into account.
– Concerning contact bricks, only integral contact bricks are fully parallelized for the moment.
Nodal contact bricks work in parallel but all the computation is done on the master process.
Catch errors
Errors used in GetFEM are defined in the file gmm/gmm_except.h. In order to make easier the error
catching all errors derive from the type std::logic_error defined in the file stdexcept of the
S.T.L.
A standard procedure, GMM_STANDARD_CATCH_ERROR, is defined in gmm/gmm_except.h. This
procedure catches all errors and prints the error message when an error occurs. It can be used in the
main procedure of the program as follows:
int main(void) {
try {
... main program ...
} GMM_STANDARD_CATCH_ERROR;
}
11
User Documentation, Release 5.4.2
Build a mesh
As a preliminary, you may want to read this short introduction to the GetFEM glossary.
GetFEM has its own structure to store meshes defined in the files getfem/
bgeot_mesh_structure.h and getfem/getfem_mesh.h. The main structure is defined in
getfem/getfem_mesh.h by the object getfem::mesh.
This object is able to store any element in any dimension even if you mix elements with different dimen-
sions.
There is only a (very) experimental meshing procedure in GetFEM to mesh complex geometries. But
you can easily load a mesh from any format (some procedures are in getfem/getfem_import.h
to load meshes from some public domain mesh generators).
The structure getfem::mesh may also contain a description about a region of the mesh, such as
a boundary or a set of elements. This is handled via a container of convexes and convex faces,
getfem::mesh_region. We refer to [remacle2003] for a discussion on mesh representation.
getfem::mesh mymesh;
then you have two ways to insert a new element to this mesh: from a list of points or from a list of
indexes of already existing points.
To enter a new point on a mesh use the method:
i = mymesh.add_point(pt);
where pt is of type bgeot::base_node. The index i is the index of this point on the mesh. If the
point already exists in the mesh, a new point is not inserted and the index of the already existing point
is returned. A mesh has a principal dimension, which is the dimension of its points. It is not possible to
have points of different dimensions in a same mesh.
13
User Documentation, Release 5.4.2
j = mymesh.add_convex(pgt, it);
std::vector<bgeot::size_type> ind(3);
ind[0] = mymesh.add_point(bgeot::base_node(0.0, 0.0, 0.0));
ind[1] = mymesh.add_point(bgeot::base_node(0.0, 1.0, 0.0));
ind[2] = mymesh.add_point(bgeot::base_node(0.0, 0.0, 1.0));
mymesh.add_convex(bgeot::simplex_geotrans(2,1), ind.begin());
mymesh.add_simplex(2, ind.begin());
It is also possible to give directly the list of points with the function:
mymesh.add_convex_by_points(pgt, itp);
std::vector<bgeot::base_node> pts(3);
pts[0] = bgeot::base_node(0.0, 0.0, 0.0);
pts[1] = bgeot::base_node(0.0, 1.0, 0.0);
pts[2] = bgeot::base_node(0.0, 0.0, 1.0);
mymesh.add_convex_by_points(bgeot::simplex_geotrans(2,1), pts.begin());
mymesh.add_simplex_by_points(2, pts.begin());
mymesh.add_parallelepiped(N, it);
mymesh.add_parallelepiped_by_points(N, itp);
mymesh.add_prism(N, it);
mymesh.add_prism_by_points(N, itp);
The order of the points in the array of points is not important for simplices (except if you care about the
orientation of your simplices). For other elements, it is important to respect the vertex order shown in
Vertex numeration for usual first order elements (first order elements).
Note that a general rule, including for higher order transformations, is that the vertex numeration follows
the one of the corresponding Lagrange finite element method (see Appendix A. Finite element method
list).
mymesh.sup_convex(i);
For parallelepiped domains, it is possible to obtain structured meshes with simplices, parallelepipeds or
prisms elements from three functions defined in getfem/getfem_regular_meshes.h.
The simplest function to use is:
which fills the mesh m with a regular mesh of simplices/parallelepipeds/prisms (depending on the value
of pgt). The number of cells in each direction is given by nsubdiv. The following example builds a
mesh of quadratic triangles on the unit square (the mesh can be scaled and translated afterwards):
std::vector<getfem::size_type> nsubdiv(2);
nsubdiv[0] = 10; nsubdiv[1] = 20;
regular_unit_mesh(m, nsubdiv, bgeot::simplex_geotrans(2,2));
where mymesh is a mesh variable in which the structured mesh will be built, N is the dimension (limited
to 4 for simplices, 5 for prisms, unlimited for parallelepipeds), org is of type bgeot::base_node
and represents the origin of the mesh, ivect is an iterator on an array of N vectors to build the paral-
lelepiped domain, iref is an iterator on an array of N integers representing the number of division on
each direction.
For instance, to build a mesh with tetrahedrons for a unit cube with 10 × 10 × 10 cells one can write:
getfem::mesh mymesh;
bgeot::base_node org(0.0, 0.0, 0.0);
std::vector<bgeot::base_small_vector> vect(3);
vect[0] = bgeot::base_small_vector(0.1, 0.0, 0.0);
vect[1] = bgeot::base_small_vector(0.0, 0.1, 0.0);
vect[2] = bgeot::base_small_vector(0.0, 0.0, 0.1);
std::vector<int> ref(3);
ref[0] = ref[1] = ref[2] = 10;
getfem::parallelepiped_regular_simplex_mesh(mymesh, 3, org, vect.begin(),
˓→ref.begin());
Note: base_node and base_small_vector are almost identical, they are both ‘’small” vector
classes (they cannot store more than 16 elements), used to describe geometrical points, and geometrical
vectors. Their memory footprint is lower than a std::vector.
getfem::mesh::neighbor_of_convex(ic, f)
gives the index of the first elements in mesh having the common face of local index f of element
ic except element ic. return size_type(-1) if none is found.
getfem::mesh::is_convex_having_neighbor(ic, f)
return whether or not the element ic has a neighbor with respect to its face of local index f.
getfem::mesh::clear()
delete all elements and points from the mesh.
getfem::mesh::optimize_structure()
compact the structure (renumbers points and convexes such that there is no hole in their number-
ing).
getfem::mesh::trans_of_convex(i)
return the geometric transformation of the element of index i (in a
bgeot::pgeometric_trans). See dp for more details about geometric transforma-
tions.
getfem::mesh::normal_of_face_of_convex(ic, f, pt)
gives a bgeot::base_small_vector representing an outward normal to the element at the
face of local index f at the point of local coordinates (coordinates in the element of reference) pt.
The point pt has no influence if the geometric transformation is linear. This is not a unit normal,
the norm of the resulting vector is the ratio between the surface of the face of the reference element
and the surface of the face of the real element.
getfem::mesh::convex_area_estimate(ic)
gives an estimate of the area of convex ic.
getfem::mesh::convex_quality_estimate(ic)
gives a rough estimate of the quality of element ic.
getfem::mesh::convex_radius_estimate(ic)
gives an estimate of the radius of element ic.
getfem::mesh::region(irg)
return a getfem::mesh_region. The region is stored in the mesh, and can contain a set of
convex numbers and or convex faces.
getfem::mesh::has_region(irg)
returns true if the region of index irg has been created.
The methods of the convexes/convex faces container getfem::mesh_region are:
getfem::mesh_region::add(ic)
add the convex of index ic to the region.
getfem::mesh_region::add(ic, f)
add the face number f of the convex ic.
getfem::mesh_region::sup(ic)
getfem::mesh_region::sup(ic, f)
remove the convex or the convex face from the region.
getfem::mesh_region::is_in(ic)
getfem::mesh_region::is_in(ic, f)
return true if the convex (or convex face) is in the region.
getfem::mesh_region::is_only_faces()
return true if the region does not contain any convex.
getfem::mesh_region::is_only_convexes()
return true if the region does not contain any convex face.
getfem::mesh_region::index()
return a dal::bit_vector containing the list of convexes which are stored (or whose faces
are stored) in the region.
Iteration over a getfem::mesh_region should be done with getfem::mr_visitor:
The numeration of faces on usual elements is given in figure faces numeration for usual elements.
Note that, while the convexes and the points are globally numbered in a getfem::mesh object, there
is no global numbering of the faces, so the only way to refer to a given face, is to give the convex number,
and the local face number in the convex.
In getfem/getfem_mesh.h, two methods are defined to load meshes from file and write meshes to
a file.
getfem::mesh::write_to_file(const std::string &name)
save the mesh into a file.
getfem::mesh::read_from_file(const std::string &name)
load the mesh from a file.
The following is an example of how to load a mesh and extract information on it:
#include <getfem/getfem_mesh.h>
getfem::mesh mymesh;
Here the string fmtfilename must contain a descriptor of the file format (“gid”, “gmsh”, “cdb”,
“noboite”, “am_fmt”, “emc2_mesh”, or “structured”), followed by a colon and the file name
(if there is not format descriptor, it is assumed that the file is a native getfem mesh and the
mesh::read_from_file() method is used). Example:
getfem::mesh m;
getfem::import_mesh("gid:../tests/meshes/tripod.GiD.msh",m);
can be used in an equivalent manner with the string fmt being one of the aforementioned format speci-
fiers.
The “gid” format specifier is for meshes generated by GiD and “gmsh” is for meshes generated by the
open-source mesh generator Gmsh. The “cdb” format specifier is for reading meshes from ANSYS
models exported in blocked format with the CDWRITE command. Currently the ANSYS element types
42,45,73,82,87,89,90,92,95,162,182,183,185,186,187 and 191 can be imported, this however does not
include any finite element techology linked to these elements but only their geometry. The “noboite”
format is for TetMesh-GHS3D, and the “am_fmt” and “emc2_mesh” are for files built with EMC2 (but
2D only).
The “structured” format is just a short specification for regular meshes: the rest of fmtfilename in
that case is not a filename, but a string whose format is following:
getfem::import_mesh("structured:GT='GT_PK(2,1)';"
"NSUBDIV=[5,5];"
"ORG=[0,0];"
(continues on next page)
where GT is the name of the geometric transformation, NSUBDIV a vector of the number of subdivisions
in each coordinate (default value 2), ORG is the origin of the mesh (default value [0,0,...]), SIZES
is a vector of the sizes in each direction (default value [1, 1, ...] and if NOISED=1 the nodes
of the interior of the mesh are randomly “shaken” (default value NOISED=0). In that string, all the
parameters are optional except GT.
getfem::mesh_fem mf(mymesh);
where mymesh is an already existing mesh. The structure will be linked to this mesh and will react
when modifications will be done on it.
It is possible to specify element by element the finite element method, so that mesh_fem’s of mixed
types can be treated, even if they contain elements with different dimensions. For usual elements, the
connection between two elements is done when the two elements are compatibles (same degrees of
freedom on the common face). A numeration of the degrees of freedom is automatically done with
a Cuthill Mc Kee like algorithm. You have to keep in mind that there is absolutely no connection
between the numeration of vertices of the mesh and the numeration of the degrees of freedom. Every
getfem::mesh_fem object has its own numeration.
There are three levels in the getfem::mesh_fem object:
• The element level: one finite element method per element. It is possible to mix the dimensions of
the elements and the property to be vectorial or scalar.
• The optional vectorization/tensorization (the qdim in getfem jargon, see glossary). For instance to
represent a displacement or a tensor field in continuum mechanics. Scalar elements are used com-
ponentwise. Note that you can mix some intrinsic vectorial elements (Raviart-Thomas element
for instance) which will not be vectorized and scalar elements which will be.
• The optional additional linear transformation (reduction) of the degrees of freedom. It consists
in defining two matrices, the reduction matrix and the extension matrix. The reduction matrix
should transform the basic dofs into the reduced dofs (the number of reduced dofs should be less
23
User Documentation, Release 5.4.2
or equal than the number of basic dofs). The extension matrix should describe the inverse trans-
formation. The product of the reduction matrix with the extension matrix should be the identity
matrix (ensuring in particular that the two matrices are of maximal rank). This optional transfor-
mation can be used to reduce the finite element space to a certain region (tipically a boundary) or
to prescribe some matching conditions between non naturally compatible fems (for instance fems
with different degrees).
One has to keep in mind this construction manipulating the degrees of freedom of a
getfem::mesh_fem object.
To select a particular finite element method on a given element, use the method:
mf.set_finite_element(i, pf);
where i is the index of the element and pf is the descriptor (of type getfem::pfem, basically a
pointer to an object which inherits from getfem::virtual_fem) of the finite element method.
Alternative forms of this member function are:
which set the finite elements for either the convexes listed in the bit_vector cvs, or all the convexes
of the mesh. Note that the last method makes a call to the method:
which defines the default finite element method which will be automatically added on new elements of
the mesh (this is very useful, for instance, when a refinement of the mesh is performed).
Descriptors for finite element methods and integration methods are available thanks to the following
function:
where "name of method" is to be chosen among the existing methods. A name of a method can be
retrieved thanks to the following functions:
A non exhaustive list (see Appendix A. Finite element method list or getfem/getfem_fem.h for
exhaustive lists) of finite element methods is given by:
• "FEM_PK(n,k)": Classical 𝑃𝐾 methods on simplexes of dimension n with degree k polyno-
mials.
• "FEM_QK(n,k)": Classical 𝑄𝐾 methods on parallelepiped of dimension n. Tensorial product
of degree k 𝑃𝐾 method on the segment.
• "FEM_PK_PRISM(n,k)": Classical methods on prism of dimension n. Tensorial product of
two degree k 𝑃𝐾 method.
• "FEM_PRODUCT(a,b)": Tensorial product of the two polynomial finite element method a and
b.
• "FEM_PK_DISCONTINUOUS(n,k)": discontinuous 𝑃𝐾 methods on simplexes of dimension
n with degree k polynomials.
An alternative way to obtain a Lagrange polynomial fem suitable for a given geometric transformation
is to use:
7.2 Examples
For instance if one needs to have a description of a 𝑃1 finite element method on a triangle, the way to
set it is:
where i is still the index of the triangle. It is also possible to select a particular method directly on a
set of element, passing to mf.set_finite_element a dal::bit_vector instead of a single
index. For instance:
mf.set_finite_element(mymesh.convex_index(),
getfem::fem_descriptor("FEM_PK(2, 1)"));
7.2. Examples 25
User Documentation, Release 5.4.2
If the finite element represents an unknown which is a vector field, the method mf.set_qdim(Q)
allows set the target dimension for the definition of the target dimension 𝑄.
If the target dimension 𝑄 is set to a value different of 1, the scalar FEMs (such as 𝑃𝑘 fems etc.) are
automatically “vectorized” from the mesh_fem object point of view, i.e. each scalar degree of freedom
appears 𝑄 times in order to represent the 𝑄 components of the vector field. If an intrinsically vectorial
element is used, the target dimension of the fem and the one of the mesh_fem object have to match. To
sum it up,
• if the fem of the 𝑖𝑡ℎ element is intrinsically a vector FEM, then:
mf.get_qdim() == mf.fem_of_element(i)->target_dim()
&&
mf.nb_dof_of_element(i) == mf.fem_of_element(i).nb_dof()
Additionally, if the field to be represented is a tensor field instead of a vector field (for instance the stress
or strain tensor field in elasticity), it is possible to specify the tensor dimensions with the methods:
mf.set_qdim(dim_type M, dim_type N)
mf.set_qdim(dim_type M, dim_type N, dim_type O, dim_type P)
mf.set_qdim(const bgeot::multi_index &mii)
respectively for a tensor field of order two, four and arbitrary (but limited to 6). For most of the opera-
tions, this is equivalent to declare a vector field of the size the product of the dimensions. However, the
declared tensor dimensions are taken into account into the high level generic assembly. Remember that
the components inside a tensor are stored in Fortran order.
At this level are defined the basic degrees of freedom. Some methods of the getfem::mesh_fem
allows to obtain information on the basic dofs:
getfem::mesh_fem::nb_basic_dof_of_element(i)
gives the number of basic degrees of freedom on the element of index i.
getfem::mesh_fem::ind_basic_dof_of_element(i)
gives a container (an array) with all the global indexes of the basic degrees of freedom of element
of index i.
getfem::mesh_fem::point_of_basic_dof(i, j)
gives a bgeot::base_node which represents the point associated with the basic dof of local
index j on element of index i.
getfem::mesh_fem::point_of_basic_dof(j)
gives a bgeot::base_node which represents the point associated with the basic dof of global
index j.
getfem::mesh_fem::reference_point_of_basic_dof(i, j)
gives a bgeot::base_node which represents the point associated with the basic dof of local
index j on element of index i in the coordinates of the reference element.
getfem::mesh_fem::first_convex_of_basic_dof(j)
gives the index of the first element on which the basic degree of freedom of global index j is
defined.
getfem::mesh_fem::nb_basic_dof()
gives the total number of different basic degrees of freedom.
getfem::mesh_fem::get_qdim()
gives the target dimension Q.
getfem::mesh_fem::basic_dof_on_region(i)
Return a dal::bit_vector which represents the indices of basic dof which are in the set of
convexes or the set of faces of index i (see the getfem::mesh object).
getfem::mesh_fem::dof_on_region(i)
Return a dal::bit_vector which represents the indices of dof which are in the set of con-
vexes or the set of faces of index i (see the getfem::mesh object). For a reduced mesh_fem,
a dof is lying on a region if its potential corresponding shape function is nonzero on this region.
The extension matrix is used to make the correspondence between basic and reduced dofs.
As described above, it is possible to provide two matrices, a reduction matrix 𝑅 and an extension matrix
𝐸 which will describe a linear transformation of the degrees of freedom. If 𝑉 is the vector of basic
degrees of freedom, then 𝑈 = 𝑅𝑉 will be the vector of reduced degrees of freedom. Contrarily, given a
vector 𝑈 of reduced dof, 𝑉 = 𝐸𝑈 will correspond to a vector of basic dof. In simple cases, 𝐸 will be
simply the transpose of 𝑅. NOTE that every line of the extension matrix should be sparse. Otherwise,
each assembled matrix will be plain !
A natural condition is that 𝑅𝐸 = 𝐼 where 𝐼 is the identity matrix.
getfem::mesh_fem::nb_dof()
gives the total number of different degrees of freedom. If the optional reduction is used, this will
be the number of columns of the reduction matrix. Otherwise it will return the number of basic
degrees of freedom.
getfem::mesh_fem::is_reduced()
return a boolean. True if the reduction is used.
getfem::mesh_fem::reduction_matrix()
return a const reference to the reduction matrix 𝑅.
getfem::mesh_fem::extension_matrix()
return a const reference to the extension matrix 𝐸.
getfem::mesh_fem::set_reduction_matrices(R, E)
Set the reduction and extension matrices to R and E and validate their use.
getfem::mesh_fem::set_reduction(b)
Where 𝑏 is a boolean. Cancel the reduction if 𝑏 is false and validate it if b is true. If b is true, the
extension and reduction matrices have to be set previously.
getfem::mesh_fem::reduce_to_basic_dof(idof)
Set the reduction and extension matrices corresponding to keep only the basic dofs present in
idof. The parameter idof is either a dal::bit_vector or a std::set<size_type>.
This is equivalent to the use of a getfem::partial_mesh_fem object.
to get a classical polynomial mesh_fem of order 𝐾 on the given mymesh. The returned mesh_fem will
be destroyed automatically when its linked mesh is destroyed. All the mesh_fem built by this function
are stored in a cache, which means that calling this function twice with the same arguments will return
the same mesh_fem object. A consequence is that you should NEVER modify this mesh_fem!
getfem::partial_mesh_fem partial_mf(mf);
where kept_dof and rejected_elt are some dal::bit_vector. kept_dof is the list of dof
indices of the original mesh_fem mf to be kept. rejected_elt is an optional parameter that contains
a list of element indices on which the getfem::partial_mesh_fem states that there is no finite
element method. This is to avoid unnecessary computations during assembly procedures.
The description of an integration method on a whole mesh is done thanks to the structure
getfem::mesh_im, defined in the file getfem/getfem_mesh_im.h. Basically, this struc-
ture describes the integration method on each element of the mesh. One can instantiate a
getfem::mesh_im object as follows:
getfem::mesh_im mim(mymesh);
where mymesh is an already existing mesh. The structure will be linked to this mesh and will react
when modifications will be done on it (for example when the mesh is refined, the integration method
will be also refined).
It is possible to specify element by element the integration method, so that element of mixed types can
be treated, even if the dimensions are different.
To select a particular integration method on a given element, one can use:
mim.set_integration_method(i, ppi);
where i is the index of the element and ppi is the descriptor of the integration method. Alternative
forms of this member function are:
which set the integration method for either the convexes listed in the bit_vector cvs, or all the convexes
of the mesh.
The list of all available descriptors of integration methods is in the file getfem/
getfem_integration.h. Descriptors for integration methods are available thanks to the
following function:
29
User Documentation, Release 5.4.2
where "name of method" is to be chosen among the existing methods. A name of a method can be
retrieved with:
Note: Note that "IM_QUAD(3)" is not able to integrate exactly the base functions of the
"FEM_QK(2,3)" finite element! Since its base function are tensorial product of 1D poly-
nomials of degree 3, one would need to use "IM_QUAD(7)" (6 is not available). Hence
"IM_GAUSS_PARALLELEPIPED(2,k)" should always be preferred over "IM_QUAD(2*k)"
since it has less integration points.
getfem::pintegration_method ppi =
getfem::classical_exact_im(bgeot::pgeometric_trans pgt);
These functions return an exact (i.e. analytical) integration method, or select an approximate integration
method which is able to integrate exactly polynomials of degree <= d (at least) for convexes defined
with the specified geometric transformation.
Once an integration method is defined on a mesh, it is possible to obtain information on it with the
following methods (the list is not exhaustive).
mim.convex_index()
Set of indexes (a dal::bit_vector) on which an integration method is defined.
mim.linked_mesh()
Gives a reference to the linked mesh.
mim.int_method_of_element(i)
Gives a descriptor on the integration method defined on element of index i.
mim.clear()
Clear the structure. There are no further integration method defined on the mesh.
Mesh refinement
Mesh refinement with the Bank et all method (see [bank1983]) is available in dimension 1, 2 or
3 for simplex meshes (segments, triangles and tetrahedrons). For a given object mymesh of type
getfem::mesh, the method:
mymesh.Bank_refine(bv);
refines the elements whose indices are stored in bv (a dal::bit_vector object). The conformity of
the mesh is kept thanks to additional refinement (the so called green triangles). Information about green
triangles (in Figure Example of Bank refinement in 2D) is stored on the mesh object to gather them for
further refinements (see [bank1983]).
Mesh refinement is most of the time coupled with an a posteriori error estimate. A very basic error
estimate is available in the file getfem/getfem_error_estimate.h:
where mim is the integration method (a getfem::mesh_im object), mf is the finite element method
on which the unknown has been computed (a getfem::mesh_fem object), U is the vector of degrees
of freedom of the unknown, err is a sufficiently large vector in which the error estimate is computed
for each element of the mesh, and rg is a mesh region bulild from elements on which the error estimate
should be computed (a getfem::mesh_region object).
This basic error estimate is only valid for order two problems and just compute the sum of the jump in
normal derivative across the elements on each edge (for two-dimensional problems) or each face (for
33
User Documentation, Release 5.4.2
three-dimensional problems). This means that for each face 𝑒 of the mesh the following quantity is
computed:
∫︁
|[[𝜕𝑛 𝑢]]|2 𝑑Γ,
𝑒
where [[𝜕𝑛 𝑢]] is the jump of the normal derivative. Then, the error estimate for a given element is the
sum of the computed quantities on each internal face multiplied by the element diameter. This basic
error estimate can be taken as a model for more elaborated ones. It uses the high-level generic assembly
and the neighbor_element interpolate transformation (see Evaluating discontinuities across inter-
element edges/faces).
This section presents what is now the main generic assembly of GetFEM. It is a high-level generic
assembly in the sense that it is based on Generic Weak Form Language (GWFL, [GetFEM2020]) to
describe the weak formulation of boundary value problems of partial differential equations. A symbolic
differentiation algorithm is used. It simplifies a lot the approximation of nonlinear coupled problems
since only the weak form is necessary to be described, the tangent system being automatically computed.
Moreover, GWFL is compiled into optimized instructions before the evaluation on each integration point
in order to obtain a an optimal computational cost.
The header file to be included to use the high-level generic assembly procedures in C++ is getfem/
generic_assembly.h.
35
User Documentation, Release 5.4.2
• Gradients: Spatial gradients of variables or test functions are identified by the prefix Grad_
followed by the variable name or by Test_ or Test2_ followed itself by the variable
name. This is available for FEM variables only. For instance Grad_u, Grad_pressure,
Grad_electric_field and Grad_Test_u, Grad_Test2_v. For vector fields, Div_u
and Div_Test_u are some shortcuts for Trace(Grad_u) and Trace(Grad_Test_u),
respectively.
• Hessians: The Hessian of a variable or test function is identified by the prefix Hess_ followed
by the variable name or by Test_ or Test2_ followed itself by the variable name. This is
available for FEM variables only. For instance Hess_u, Hess_v, Hess_p, Hess_Test2_v,
Hess_Test_p, Hess_Test_pressure.
• A certain number of predefined scalar functions (sin(t), cos(t), pow(t,u), sqrt(t),
sqr(t), Heaviside(t), . . . ). A scalar function can be applied to scalar or vec-
tor/matrix/tensor expressions. It applies componentwise. For functions having two arguments
(pow(t,u), min(t,u) . . . ) if two non-scalar arguments are passed, the dimension have to be
the same. For instance “max([1;2],[0;3])” will return “[1;3]”.
• A certain number of operations: +, -, *, /, :, ., .*, ./, @, ', Cross_product(v1,v2).
• A certain number of linear operator: Trace(M), Sym(M), Skew(M), . . .
• A certain number of nonlinear operator: Norm(V), Det(M), Sym(M), Skew(M), . . .
• Some constants: pi, meshdim (the dimension of the current mesh), qdim(u) and qdims(u)
the dimensions of the variable u (the size for fixed size variables and the dimension of the vector
field for FEM variables), Id(n) the identity 𝑛 × 𝑛 matrix.
• Parentheses can be used to change the operations order in a standard way. For instance (1+2)*4
or (u+v)*Test_u are valid expressions.
• The access to a component of a vector/matrix/tensor can be done by following a term by a left
parenthesis, the list of components and a right parenthesis. For instance [1,1,2](3) is correct
and will return 2. Note that indices are assumed to begin by 1 (even in C++ and with the python
interface). A colon can replace the value of an index in a Matlab like syntax.
• Explicit vectors: For instance [1;2;3;4] is an explicit vector of size four. Each component can
be an expression.
• Explicit matrices: For instance [1,3;2,4] and [[1,2],[3,4]] denote the same 2x2 matrix.
Each component can be an expression.
• Explicit fourth order tensors: example of explicit 3x2x2x2 fourth order tensor in the
nested format: [[[[1,2,3],[1,2,3]],[[1,2,3],[1,2,3]]],[[[1,2,3],[1,2,
3]],[[1,2,3],[1,2,3]]]].
• X is the current coordinate on the real element, X(i) is its i-th component.
• Normal is the outward unit normal vector to a boundary, when integrating on a domain
boundary, or the unit normal vector to a level-set when integrating on a level-set with a
mesh_im_level_set method. In the latter case, the normal vector is in the direction of the
level-set function gradient.
• Reshape(t, i, j, ...): Reshape a vector/matrix/tensor. Note that all tensors in GetFEM
are stored in the Fortran order.
• A certain number of linear and nonlinear operators (Trace, Norm, Det, Deviator,
Contract, . . . ). The nonlinear operators cannot be applied to test functions.
where my_f is the expression of the source term. If now the equation is
−div 𝑎∇𝑢 = 𝑓, in Ω,
for a a scalar coefficient, the corresponding assembly string is:
a*Grad_u.Grad_Test_u - my_f*Test_u
where a has to be declared as a scalar constant or a scalar field. Not that is is also possible to describe it
explicitly. For instance the problem
sin(X(1)+X(2))*Grad_u.Grad_Test_u - my_f*Test_u
−div 𝜎(𝑢) = 𝑓, in Ω,
for 𝑢 a vector field and 𝜎(𝑢) = 𝜆div 𝑢 + 𝜇(∇𝑢 + (∇𝑢)𝑇 ) when isotropic linear elasticity is considered.
The corresponding assembly string to describe the weak formulation can be written:
or:
Here again, the coefficients lambda and mu can be given constants, or scalar field or explicit expression
or even expression coming from some other variables in order to couples some problems. For instance,
if the coefficients depends on a temperature field one can write:
where theta is the temperature which can be the solution to a Poisson equation:
"Grad_theta.Grad_Test_theta - my_f*Grad_Test_theta"
and my_f1 and my_f2 are some given functions. Note that in that case, the problem is nonlinear due
to the coupling, even if the two functions my_f1 and my_f2 are linear.
The derivation order of the assembly string is automatically detected. This means that if no test functions
are found, the order will be considered to be 0 (potential energy), if first order test functions are found,
the order will be considered to be 1 (weak formulation) and if both first and second order test functions
are found, the order will be considered to be 2 (tangent system).
In order to perform an assembly (see next section), one should specify the order (0, 1 or 2). If an order
1 string is furnished and an order 2 assembly is required, a symbolic differentiation of the expression is
performed. The same if an order 0 string is furnished and if an order 1 or 2 assembly is required. Of
course, the converse is not true. If an order 1 expression is given and an order 0 assembly is expected, no
integration is performed. This should not be generally not possible since an arbitrary weak formulation
do not necessary derive from a potential energy.
The standard way to use the generic assembly is to furnish order 1 expressions (i.e. a weak formulation).
If a potential energy exists, one may furnish it. However, it will be derived twice to obtain the tangent
system which could result in complicated expressions. For nonlinear problems, it is not allowed to
furnish order 2 expressions directly. The reason is that the weak formulation is necessary to obtain the
residual. So nothing could be done with a tangent term without having the corresponding order 1 term.
IMPORTANT REMARK: Note that for coupled problems, a global potential frequently do not exists.
So that the part of problems directly defined with a potential may be difficult to couple. To illustrate this,
if you defined a potential with some parameters (elasticity coefficients for instance), and the coupling-
consists in a variation of these coefficients with respect to another variable, then the weak formulation do
not consist of course in the derivative of the potential with respect to the coefficients which has generally
no sense. This is the reason why the definition through a potential should be the exception.
Note that the most natural way to use the generic assembly is by the use of the generic assembly bricks
of the model object, see Section Generic assembly bricks. It is however also possible to use the high
level generic assembly on its own.
The generic assembly is driven by the object getfem::ga_workspace defined in getfem/
getfem_generic_assembly.h.
There is two ways to define a getfem::ga_workspace object. It can depend on a model (see The
model description and basic model bricks) and should be declared as:
getfem::ga_workspace workspace(model);
with model a previously define getfem::model object. In that case the variable and constant consid-
ered are the one of the model. The second way it to define an independent getfem::ga_workspace
object by:
getfem::ga_workspace workspace;
In that case, the variable and constant have to be added to the workspace. This can be done thanks to the
following methods:
workspace.add_fixed_size_variable(name, I, V);
workspace.add_fixed_size_constant(name, V);
where name is the variable/constant name (see in the next sections the restriction on possible names),
mf is the getfem::mesh_fem object describing the finite element method, I is an object of class
gmm::sub_interval indicating the interval of the variable on the assembled vector/matrix and V is
a getfem::base_vector being the value of the variable/constant. The last method add a constant
defined on an im_data object imd which allows to store scalar/vector/tensor field informations on the
integration points of an mesh_im object.
Once it is declared and once the variables and constant are declared, it is possible to add assembly string
to the workspace with:
where "my expression" is the assembly string, mim is a getfem::mesh_im object and rg if an
optional valid region of the mesh corresponding to mim.
As it is explained in the previous section, the order of the string will be automatically detected and a
symbolic differentiation will be performed to obtain the corresponding tangent term.
Once assembly strings are added to the workspace, is is possible to call:
workspace.assembly(order);
where order should be equal to 0 (potential energy), 1 (residual vector) or 2 (tangent term, or stiffness
matrix for linear problems). The result of the assembly is available as follows:
By default, the assembled potential, vector and matrix is initialized to zero at the beginning of the
assembly. It is however possible (and recommended) to set the assembly vector and matrix to external
ones to perform an incremental assembly. The two methods:
workspace.set_assembled_vector(getfem::base_vector &V);
workspace.set_assembled_matrix(getfem::model_real_sparse_matrix &K);
allows to do so. Be aware to give a vector and a matrix of the right dimension.
Note also that the method:
workspace.clear_expressions();
allows to cancel all furnished expressions and allows to re-use the same workspace for another assembly.
It is also possible to call the generic assembly from the Python/Scilab/Octave/Matlab interface. See
gf_asm command of the interface for more details.
−div ∇𝑢 = 𝑓, in Ω,
getfem::ga_workspace workspace;
getfem::size_type nbdof = mf.nb_dof();
getfem::base_vector U(nbdof);
workspace.add_fem_variable("u", mf, gmm::sub_interval(0, nbdof), U);
workspace.add_expression("Grad_u.Grad_Test_u", mim);
getfem::model_real_sparse_matrix K(nbdof, nbdof);
workspace.set_assembled_matrix(K);
workspace.assembly(2);
getfem::ga_workspace workspace;
getfem::size_type nbdofu = mf_u.nb_dof();
getfem::size_type nbdofp = mf_p.nb_dof();
getfem::base_vector U(nbdofu);
getfem::base_vector P(nbdofp);
getfem::base_vector vmu(1); vmu[0] = mu;
workspace.add_fem_variable("u", mf_u, gmm::sub_interval(0, nbdofu), U);
workspace.add_fem_variable("p", mf_p, gmm::sub_interval(nbdofu, nbdofp),
˓→P);
workspace.add_fixed_size_constant("mu", vmu);
workspace.add_expression("2*mu*Sym(Grad_u):Grad_Test_u"
"- p*Trace(Grad_Test_u) - Test_p*Trace(Grad_u)",
˓→mim);
getfem::model_real_sparse_matrix K(nbdofu+nbdofp, nbdofu+nbdofp);
workspace.set_assembled_matrix(K);
workspace.assembly(2);
where, here, mf_u and mf_p are supposed to be some already declared getfem::mesh_fem objects
defined on the same mesh, mim a already declared getfem::mesh_im object and mu is the Lame
coefficient. It is also possible to perform the assembly of the sub-matrix of this system separately.
Let us see now how to perform the assembly of a source term. The weak formulation of a volumic
source term is
∫︁
𝑓 𝑣𝑑𝑥
Ω
where 𝑓 is the source term and 𝑣 the test function. The corresponding assembly can be written:
getfem::ga_workspace workspace;
getfem::size_type nbdofu = mf_u.nb_dof();
getfem::base_vector U(nbdofu);
workspace.add_fem_variable("u", mf_u, gmm::sub_interval(0, nbdofu), U);
workspace.add_fem_constant("f", mf_data, F);
workspace.add_expression("f*Test_u", mim);
getfem::base_vector L(nbdofu);
workspace.set_assembled_vector(L);
workspace.assembly(1);
if the source term is describe on a finite element mf_data and the corresponding vector of degrees of
freedom F. Explicit source terms are also possible. For instance:
getfem::ga_workspace workspace;
getfem::size_type nbdofu = mf_u.nb_dof();
getfem::base_vector U(nbdofu);
workspace.add_fem_variable("u", mf_u, gmm::sub_interval(0, nbdofu), U);
workspace.add_expression("sin(X(1)+X(2))*Test_u", mim);
getfem::base_vector L(nbdofu);
workspace.set_assembled_vector(L);
workspace.assembly(1);
is also valid. If the source term is a boundary term (in case of a Neumann condition) the only difference
is that the mesh region corresponding to the boundary have to be given as follows:
where 𝜆, 𝜇 are the Lamé coefficients and 𝐸 is the strain tensor given by 𝐸 = (∇𝑢 + (∇𝑢)𝑇 +
(∇𝑢)𝑇 ∇𝑢)/2.
This is possible to perform the assembly of the corresponding tangent problem as follows:
getfem::ga_workspace workspace;
getfem::size_type nbdofu = mf_u.nb_dof();
getfem::base_vector vlambda(1); vlambda[0] = lambda;
getfem::base_vector vmu(1); vmu[0] = mu;
workspace.add_fem_variable("u", mf_u, gmm::sub_interval(0, nbdofu), U);
workspace.add_fixed_size_constant("lambda", vlambda);
workspace.add_fixed_size_constant("mu", vmu);
workspace.add_expression("lambda*sqr(Trace(Grad_u+Grad_u'+Grad_u'*Grad_u))"
"+ mu*Trace((Grad_u+Grad_u'+Grad_u'*Grad_u)"
"*(Grad_u+Grad_u'+Grad_u'*Grad_u))", mim);
getfem::base_vector L(nbdofu);
workspace.set_assembled_vector(V);
workspace.assembly(1);
getfem::model_real_sparse_matrix K(nbdofu, nbdofu);
workspace.set_assembled_matrix(K);
workspace.assembly(2);
and to adapt a Newton-Raphson algorithm to solve that nonlinear problem. Of course the expression is
rather repetitive and it would be preferable to define some intermediate nonlinear operators. However,
note that repeated expressions are automatically detected and computed only once in the assembly.
The last example is the assembly of the stiffness matrix of an order four problem, the Kirchhoff-Love
plate problem:
getfem::ga_workspace workspace;
getfem::size_type nbdofu = mf_u.nb_dof();
getfem::base_vector vD(1); vD[0] = D;
getfem::base_vector vnu(1); vnu[0] = nu;
workspace.add_fem_variable("u", mf_u, gmm::sub_interval(0, nbdofu), U);
workspace.add_fixed_size_constant("D", vD);
workspace.add_fixed_size_constant("nu", vnu);
workspace.add_expression("D*(1-nu)*(Hess_u:Hess_Test_u) -"
"D*nu*Trace(Hess_u)*Trace(Hess_Test_u)", mim);
getfem::model_real_sparse_matrix K(nbdofu, nbdofu);
workspace.set_assembled_matrix(K);
workspace.assembly(2);
For the use with Python, Scilab, Octave or Matlab interfaces, see the respective documentation, in
particular the gf_asm command and the model object.
Basically, what is manipulated in GWFL are tensors. This can be order 0 tensors in scalar expressions
(for instance in 3+sin(pi/2)), order 1 tensors in vector expressions (such as X.X or Grad_u if u is
a scalar variable), order 2 tensors for matrix expressions and so on. For efficiency reasons, the language
manipulates tensors up to order six. The language could be easily extended to support tensors of order
greater than six but it may lead to inefficient computations. When an expression contains test functions
(as in Trace(Grad_Test_u) for a vector field u), the computation is done for each test functions,
which means that the tensor implicitly have a supplementary component. This means that, implicitly,
the maximal order of manipulated tensors are in fact six (in Grad_Test_u:Grad_Test2_u there
are two components implicitly added for first and second order test functions).
Order four tensors are necessary for instance to express elasticity tensors or in general to obtain the
tangent term for vector valued unknowns.
A list of variables should be given to the ga_worspace object (directly or through a model object).
The variables are described on a finite element method or can be a simple vector of unknowns. This
means that it is possible also to couple algebraic equations to pde ones on a model. A variable name
should begin by a letter (case sensitive) or an underscore followed by a letter, a number or an underscore.
Some name are reserved, this is the case of operators names (Det, Norm, Trace, Deviator, . . . ) and
thus cannot be used as variable names. The name should not begin by Test_, Test2_, Grad_, Div_
or Hess_. The variable name should not correspond to a predefined function (sin, cos, acos . . . )
and to constants (pi, Normal, X, Id . . . ).
A list of constants could also be given to the ga_worspace object. The rule are the same as for the
variables but no test function can be associated to constants and there is no symbolic differentiation with
respect to constants. Scalar constants are often defined to represent the coefficients which intervene in
constitutive laws. Additionally, constants can be some scalar/vector/tensor fields defined on integration
points via a im_data object (for instance for some implementation of the approximation of constitutive
laws such as plasticity).
Each variable is associated with first order and second order test functions. The first order test function
are used in the weak formulation (which derive form the potential equation if it exists) and the second
order test functions are used in the tangent system. For a variable u the associated test functions are
Test_u and Test2_u. The assembly string have to be linear with respect to test functions. As a result
of the presence of the term Test_u on a assembly string, the expression will be evaluated for each
shape function of the finite element corresponding to the variable u. On a given element, if the finite
element have N shape functions ans if u is a scalar field, the value of Test_u will be the value of each
shape function on the current point. So Test_u return if face a vector of N values. But of course, this
is implicit in the language. So one do not have to care about this.
10.11 Gradient
The gradient of a variable or of test functions are identified by Grad_ followed by the vari-
able name or by Test_ followed itself by the variable name. This is available for FEM
variables (or constants) only. For instance Grad_u, Grad_v, Grad_p, Grad_pressure,
Grad_electric_field and Grad_Test_u, Grad_Test_v, Grad_Test_p,
Grad_Test_pressure, Grad_Test_electric_field. The gradient is either a vector
for scalar variables or a matrix for vector field variables. In the latter case, the first index corresponds
to the vector field dimension and the second one to the index of the partial derivative. Div_u and
Div_Test_u are some optimized shortcuts for Trace(Grad_u) and Trace(Grad_Test_u),
respectively.
10.12 Hessian
Similarly, the Hessian of a variable or of test functions are identified by Hess_ followed
by the variable name or by Test_ followed itself by the variable name. This is avail-
able for FEM variables only. For instance Hess_u, Hess_v, Hess_p, Hess_pressure,
Hess_electric_field and Hess_Test_u, Hess_Test_v, Hess_Test_p,
Hess_Test_pressure, Hess_Test_electric_field. The Hessian is either a matrix
for scalar variables or a third order tensor for vector field variables. In the latter case, the first index
corresponds to the vector field dimension and the two remaining to the indices of partial derivatives.
A certain number of predefined scalar functions can be used. The exhaustive list is the following and for
most of them are equivalent to the corresponding C function:
• sqr(t) (the square of t, equivalent to t*t), pow(t, u) (t to the power u), sqrt(t) (square
root of t), exp(t), log(t), log10(t)
• sin(t), cos(t), tan(t), asin(t), acos(t), atan(t), atan2(t, u)
• sinh(t), cosh(t), tanh(t), asinh(t), acosh(t), atanh(t)
• erf(t), erfc(t)
• sinc(t) (the cardinal sine function sin(t)/t)
• Heaviside(t) (0 for 𝑡 < 0, 1 for 𝑡 ≥ 0)
• sign(t)
• abs(t)
• reg_pos_part(t, eps) ((𝑡 − 𝑒𝑝𝑠/2 − 𝑡2 /(2𝑒𝑝𝑠))𝐻(𝑡 − 𝑒𝑝𝑠) + 𝑡2 𝐻(𝑡)/(2𝑒𝑝𝑠))
• max(t, u), min(t, u)
• pos_part(t) (𝑡𝐻(𝑡))
• sqr_pos_part(t) ((𝑡𝐻(𝑡))2 )
• neg_part(t) (−𝑡𝐻(−𝑡)), max(t, u), min(t, u)
• sqr_neg_part(t) ((𝑡𝐻(−𝑡))2 )
A scalar function can be applied to a scalar expression, but also to a tensor one. If is is applied to a
tensor expression, is is applied componentwise and the result is a tensor with the same dimensions. For
functions having two arguments (pow(t,u), min(t,u) . . . ) if two non-scalar arguments are passed, the
dimension have to be the same. For instance “max([1;2],[0;3])” will return “[0;3]”.
It is possible to add a scalar function to the already predefined ones. Note that the generic assembly
consider only scalar function with one or two parameters. In order to add a scalar function to the generic
assembly, one has to call:
where name is the name of the function to be defined, nb_args is equal to 1 or 2. In the first call,
expr is a string describing the function in GWFL and using t as the first variable and u as the second
one (if nb_args is equal to 2). For instance, sin(2*t)+sqr(t) is a valid expression. Note that it
is not possible to refer to constant or data defined in a ga_workspace object. der1 and der2 are
the expression of the derivatives with respect to t and u. They are optional. If they are not furnished, a
symbolic differentiation is used if the derivative is needed. If der1 and der2 are defined to be only a
function name, it will be understand that the derivative is the corresponding function. In the second call,
f1 should be a C pointer on a scalar C function having one scalar parameter and in the third call, f2
should be a C pointer on a scalar C function having two scalar parameters.
Additionally,:
bool ga_function_exists(name)
ga_undefine_function(name)
cancel the definition of an already define function (it has no action if the function does not exist) which
allow to redefine a function.
It is possible to refer directly to the derivative of defined functions by adding the prefix Derivative_
to the function name. For instance, Derivative_sin(t) will be equivalent to cos(t). For two
arguments functions like pow(t,u) one can refer to the derivative with respect to the second argument
with the prefix Derivative_2_ before the function name.
10.18 Parentheses
Parentheses can be used in a standard way to change the operation order. If no parentheses are indicated,
the usually priority order are used. The operations + and - have the lower priority (with no distinction),
then *, /, :, ., .*, ./, @ with no distinction and the higher priority is reserved for the unary operators
- and '.
GWFL allows to define explicit vectors (i.e. order 1 tensors) with the notation [a,b,c,d,e], i.e. an
arbitrary number of components separated by a comma (note the separation with a semicolon [a;b;c;
d;e] is also permitted), the whole vector beginning with a right bracket and ended by a left bracket. The
components can be some numeric constants, some valid expressions and may also contain test functions.
In the latter case, the vector has to be homogeneous with respect to the test functions. This means that a
construction of the type [Test_u; Test_v] is not allowed. A valid example, with u as a scalar field
variable is [5*Grad_Test_u(2), 2*Grad_Test_u(1)]. Note also that using the quite opertor
(transpose), an expression [a,b,c,d,e]' stands for ‘row vector‘, i.e. a 1x5 matrix.
Similarly to explicit vectors, it is possible to define explicit matrices (i.e. order 2 tensors) with the nota-
tion [[a,b],[c,d]], i.e. an arbitrary number of columns vectors separated by a comma (the syntax
[a,c;b,d] of lines separated by a semicolon is also permitted). For instance [[11,21],[12,
22],[13,23]] and [11,12,13;21,22,23] both represent the same 2x3 matrix. The compo-
nents can be some numeric constants, some valid expressions and may also contain test functions.
Explicit tensors of any order are permitted with the nested format. A tensor of order n is written
as a succession of tensor of order n-1 of equal dimensions and separated by a comma. For in-
stance [[[[1,2,3],[1,2,3]],[[1,2,3],[1,2,3]]],[[[1,2,3],[1,2,3]],[[1,2,
3],[1,2,3]]]] is a fourth order tensor. Another possibility is to use the syntax Reshape([1,2,
3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3], 3, 2, 2, 2) where the com-
ponents have to be given in Fortran order.
The access to a component of a vector/matrix/tensor can be done by following a term by a left parenthe-
sis, the list of components and a right parenthesis. For instance [1,1,2](3) is correct and is returning
2 as expected. Note that indices are assumed to begin by 1 (even in C++ and with the python interface).
The expressions [1,1;2,3](2,2) and Grad_u(2,2) are also correct provided that u is a vector
valued declared variable. Note that the components can be the result of a constant computation. For
instance [1,1;2,3](1+1,a) is correct provided that a is a declared constant but not if it is declared
as a variable. A colon can replace the value of an index in a Matlab like syntax for instance to access to
a line or a column of a matrix. [1,1;2,3](1,:) denotes the first line of the matrix [1,1;2,3]. It
can also be used for a fourth order tensor.
• X is the current coordinate on the real element (i.e. the position on the mesh of the current
Gauss point on which the expression is evaluated), X(i) is its i-th component. For instance
sin(X(1)+X(2)) is a valid expression on a mesh of dimension greater or equal to two.
• Normal the outward unit normal vector to a boundary when integration on a boundary is per-
formed.
For debugging purpose, the command Print(a) is printing the tensor a and pass it unchanged. For
instance Grad_u.Print(Grad_Test_u) will have the same effect as Grad_u.Grad_Test_u
but printing the tensor Grad_Test_u for each Gauss point of each element. Note that constant terms
are printed only once at the beginning of the assembly. Note also that the expression could be derived
so that the derivative of the term may be printed instead of the term itself.
The command Reshape(t, i, j, ...) reshapes the tensor t (which could be an expres-
sion). The only constraint is that the number of components should be compatible. For instance
Reshape(Grad_u, 1, meshdim) is equivalent to Grad_u' for u a scalar variable. Note that
the order of the components remain unchanged and are classically stored in Fortran order for compati-
bility with Blas/Lapack.
Trace, Deviator, Sym and Skew operators are linear operators acting on square matrices:
• Trace(m) gives the trace (sum of diagonal components) of a square matrix m.
• Deviator(m) gives the deviator of a square matrix m. It is equivalent to m -
Trace(m)*Id(m_dim)/m_dim, where m_dim is the dimension of m.
• Sym(m) gives the symmetric part of a square matrix m, i.e. (m + m')/2.
• Skew(m) gives the skew-symmetric part of a square matrix m, i.e. (m - m')/2.
The four operators can be applied on test functions. Which means that for instance both
Trace(Grad_u) and Trace(Grad_Test_u) are valid when Grad_u is a square matrix (i.e. u a
vector field of the same dimension as the mesh).
GWFL provides some predefined nonlinear operator. Each nonlinear operator is available together with
its first and second derivatives. Nonlinear operator can be applied to an expression as long as this
expression do not contain some test functions.
• Norm(v) for v a vector or a matrix gives the euclidean norm of a vector or a Frobenius norm of
a matrix.
• Norm_sqr(v) for v a vector or a matrix gives the square of the euclidean norm of a vector or
of the Frobenius norm of a matrix. For a vector this is equivalent to v.v and for a matrix to m:m.
• Normalized(v) for v a vector or a matrix gives v divided by its euclidean (for vectors) or
Frobenius (for matrices) norm. In order to avoid problems when v is close to 0, it is implemented
as Normalized_reg(v, 1E-25). Use with care. Think that the derivative at the origin of
Normalized(v)*Norm(v) is wrong (it vanishes) and very different from the derivative of v.
• Normalized_reg(v, eps) for v a vector or a matrix gives a regularized version of
Normalized(v) : v/sqrt(|v|*|v|+eps*eps).
• Ball_projection(v, r) for v a vector or a matrix and r a scalar, gives the projection of v
on the ball of radius r and center the origin.
• Det(m) gives the determinant of a square matrix m.
• Inv(m) gives the inverse of a square matrix m. The second derivative is not available since it is
an order 6 tensor. This means that Inv(m) cannot be used in the description of a potential energy.
• Expm(m) gives the exponential of a square matrix m.
• Logm(m) gives the logarithm of a square matrix m.
• Matrix_I2(m) gives the second invariants of a square matrix m which is defined by
(sqr(Trace(m)) - Trace(m*m))/2.
• Matrix_J1(m) gives the modified first invariant of a square matrix defined by
Trace(m)pow(Det(m),-1/3).
• Matrix_J2(m) gives the modified first invariant of a square matrix defined by
Matrix_I2(m)*pow(Det(m),-2/3).
GWFL allows the use of macros that are either predefined in the model or ga_workspace object or
directly defined at the begining of an assembly string. The definition into a ga_workspace or model
object is done as follows:
workspace.add_macro(name, expr)
or:
model.add_macro(name, expr)
The definition of a macro into an assembly string is inserted before any regular expression, separated by
a semicolon with the following syntax:
where name is he macro name which then can be used in GWFL and contains also the macro parameters,
expr is a valid expression of GWFL (which may itself contain some macro definitions). For instance,
a valid macro with no parameter is:
model.add_macro("my_transformation", "[cos(alpha)*X(1);sin(alpha)*X(2)]");
where alpha should be a valid declared variable or data. A valid macro with two parameters is for
instance:
model.add_macro("ps(a,b)", "a.b");
Parameter are allowed to be post-fixed to Grad_, Hess_, Test_ and Test2_ prefixes, so that the
following assembly string is valid:
workspace.del_macro(name)
model.del_macro(name)
Note that a macro defined at the begining of an assembly string is only defined in the assembly string
and cannot be used later without being added in a model or ga_workspace object.
The macros are expanded inline at the lexical analysis phase. Note that a the compilation phase, the
repeated expressions are automatically factorized and computed only once.
The workspace object automatically differentiate terms that are of lower deriation order. However,
it is also allowed to explicitly differentiate an expression with respect to a variable. One interest is
that the automatic differentiation performs a derivative with respect to all the declared variables of
model/workspace but this is not necessarily the expected behavior when using a potential energy, for
instance. The syntax is:
Diff(expression, variable)
Diff(u.u, u)
2*(u.Test_u)
So that:
Grad_u:Grad_test_u + Diff(u.u, u)
is a valid expression. A third argument can be added to the Diff command to specify the direction:
in that case, it replaces the Test_variable by the expression direction which has to be of the
same dimension as variable. It computes the derivative of expression with respect to variable
in the direction direction. For instance:
Diff(u.u, u, v)
2*(u.v)
Grad(expression)
It will be computed as far as it is possible. The limitations come from the fact that GetFEM is limited to
second order derivative of shape function and nonlinear operators are supposed to provide only first and
second order derivatives.
Of course:
Grad(u)
is equivalent to:
Grad_u
for a varible u.
The Interpolate operation allows to compute integrals between quantities which are either defined
on different part of a mesh or even on different meshes. It is a powerful operation which allows to
compute mortar matrices or take into account periodic conditions. However, one have to remember that
it is based on interpolation which may have a non-negligible computational cost.
In order to use this functionality, the user have first to declare to the workspace or to the model object an
interpolate transformation which described the map between the current integration point and the point
lying on the same mesh or on another mesh.
Different kind of transformations can be described. Several kinds of transformations has been imple-
mented. The first one, described hereafter is a transformation described by an expression. A second one
corresponds to the raytracing contact detection (see Raytracing interpolate transformation). Some other
transformations (neighbor element and element extrapolation) are describe in the next sections.
The transformation defined by an expression can be added to the workspace or the model thanks to the
command:
add_interpolate_transformation_from_expression
(workspace, transname, source_mesh, target_mesh, expr);
or:
add_interpolate_transformation_from_expression
(model, transname, source_mesh, target_mesh, expr);
where workspace is a workspace object, model a model object, transname is the name given
to the transformation, source_mesh the mesh on which the integration occurs, target_mesh the
mesh on which the interpolation is performed and expr is a regular expression of GWFL which may
contains reference to the variables of the workspace/model.
For instance, an expression:
add_interpolate_transformation_from_expression
(model, "my_transformation", my_mesh, my_mesh, "X-[1;0]");
will allow to integrate some expressions at the current position with a shift of -1 with respect to the first
coordinate. This simple kind of transformation can be used to prescribe a periodic condition.
Of course, one may used more complex expressions such as:
add_interpolate_transformation_from_expression
(model, "my_transformation", my_mesh, my_second_mesh, "[X[1]cos(X[2]);
˓→X[1]sin(X[2])]");
add_interpolate_transformation_from_expression
(model, "my_transformation", my_mesh, my_mesh, "X+u");
Interpolate(Normal, transname)
Interpolate(X, transname)
Interpolate(element_K, transname)
Interpolate(element_B, transname)
Interpolate(u, transname)
Interpolate(Grad_u, transname)
Interpolate(Div_u, transname)
Interpolate(Hess_u, transname)
Interpolate(Test_u, transname)
Interpolate(Grad_Test_u, transname)
Interpolate(Div_Test_u, transname)
Interpolate(Hess_Test_u, transname)
(Interpolate(u,my_transformation)-u)*lambda
Interpolate_filter(transname, expr, i)
where transname is the name of the transformation, expr is the expression to be evaluated and i
value of the returned integer identifier for which the expression have to be computed. Note that i can
be ommited, in that case, the expression is evaluated for a nonzero identifier (i.e. when a corresponding
point has been found). For instance, the previous assembly expression to prescribe the equality of a
variable u with its interpolation could be writtne:
Interpolate_filter(transmane, Interpolate(u,my_transformation)-u)*lambda)
+ Interpolate_filter(transmane, lambda*lambda, 0)
In that case, the equality will only be prescribed in the part of the domain where the transformation
succeed and in the other part, the mulitplier is enforced to vanish.
CAUTION: You have to think that when some variables are used in the transformation, the computation
of the tangent system takes into account these dependence. However, the second derivative of a trans-
formation with respect to a variable used has not been implemented. Thus, such a transformation is not
allowed in the definition of a potential since it cannot be derived twice.
A specific transformation (see previous section) is defined in order to allows the evaluation of certain
quantities by extrapolation with respect to another element (in general a neighbor element). This is
not strictly speaking a transformation since the point location remain unchanged, but the evaluation
is made on another element extrapolating the shape functions outside it. This transformation is used
for stabilization term in fictitious domain applications (with cut elements) where it is more robust to
extrapolate some quantities on a neighbor element having a sufficiently large intersection with the real
domain than evaluating them on the current element if it has a small intersection with the real domain.
The functions allowing to add such a transformation to a model or a workspace are:
add_element_extrapolation_transformation
(model, transname, my_mesh, std::map<size_type, size_type> &elt_corr);
add_element_extrapolation_transformation
(workspace, transname, my_mesh, std::map<size_type, size_type> &elt_corr);
The map elt_corr should contain the correspondences between the elements where the transformation is
to be applied and the respective elements where the extrapolation has to be made. On the element not
listed in the map, no transformation is applied and the evaluation is performed normally on the current
element.
The following functions allow to change the element correspondence of a previously added element
extrapolation transformation:
set_element_extrapolation_correspondence
(model, transname, std::map<size_type, size_type> &elt_corr);
set_element_extrapolation_correspondence
(workspace, transname, std::map<size_type, size_type> &elt_corr);
Interpolate(Normal, neighbor_element)
Interpolate(X, neighbor_element)
Interpolate(u, neighbor_element)
Interpolate(Grad_u, neighbor_element)
Interpolate(Div_u, neighbor_element)
Interpolate(Hess_u, neighbor_element)
Interpolate(Test_u, neighbor_element)
Interpolate(Grad_Test_u, neighbor_element)
Interpolate(Div_Test_u, neighbor_element)
Interpolate(Hess_Test_u, neighbor_element)
are available (as with any other interpolate transformation) and compute a field on the current point
but on the neighbor element. Of course, Interpolate(X, neighbor_element) as no spe-
cific interest since it returns the same result as X. Similarly, in most cases, Interpolate(Normal,
neighbor_element) will return the opposite of Normal except for instance for 2D shell element
in a 3D mesh where it has an interest.
The jump on a variable u can be computed with:
u-Interpolate(u, neighbor_element)
Note that the region representing the set of all internal faces of a mesh can be obtained thanks to the
function:
where mr is an optional mesh region. If mr is specified only the face internal with respect to this region
are returned. An important aspect is that each face is represented only once and is arbitrarily chosen
between the two neighbor elements.
In some very special cases, it can be interesting to compute an integral on the direct product of two
domains, i.e. a double integral such as for instance
∫︁ ∫︁
𝑘(𝑥, 𝑦)𝑢(𝑥)𝑣(𝑦)𝑑𝑦𝑑𝑥,
Ω1 Ω2
where 𝑘(𝑥, 𝑦) is a given kernel, 𝑢 a quantity defined on Ω1 and 𝑣 a quantity defined on Ω2 , eventually
with Ω1 and Ω2 the same domain. This can be interesting either to compute such an integral or to define
an interaction term between two variables defined on two different domains.
CAUTION: Of course, this kind of term have to be used with great care, since it naturally leads to fully
populated stiffness or tangent matrices.
GWFL furnishes a mechanism to compute such a term. First, the secondary domain has to be declared
in the workspace/model with its integration methods. The addition of a standard secondary domain can
be done with one of the two following functions:
where model or workspace is the model or workspace where the secondary domain has to be de-
clared, domain_name is a string for the identification of this domain together with the mesh region
and integration method, mim the integration method and region a mesh region. Note that with these
standard secondary domains, the integration is done on the whole region for each element of the primary
domain. It can be interesting to implement specific secondary domains restricting the integration to the
necessary elements with respect to the element of the primary domain. A structure is dedicated to this
in GetFEM.
Once a secondary domain has been declared, it can be specified that a GWFL expression
has to be assembled on the direct product of a current domain and a secondary domain,
adding the name of the secondary domain to the add_expression method of the workspace
object or using add_linear_twodomain_term, add_nonlinear_twodomain_term or
add_twodomain_source_term functions:
For the utilisation with the Python/Scilab/Octave/Matlab interface, see the documentation on gf_asm
command and the model object.
Inside an expression of GWFL, one can refer to the unit normal vector to a boundary, to the current
position or to the value of a variable thanks to the expressions:
Secondary_domain(Normal)
Secondary_domain(X)
Secondary_domain(u)
Secondary_domain(Grad_u)
Secondary_domain(Div_u)
Secondary_domain(Hess_u)
Secondary_domain(Test_u)
Secondary_domain(Grad_Test_u)
Secondary_domain(Div_Test_u)
Secondary_domain(Hess_Test_u)
exp(Norm(X-Secondary_domain(X)))*u*Secondary_domain(u)
model.add_elementary_transformation(transname, pelementary_transformation)
where u is one of the FEM variables of the model/workspace, and dest is an optional parameter
which should be a variable or data name of the model and will correspond to the target fem of the
transformation. If omitted, by default, the transformation is from the fem of the first variable to itself.
A typical transformation is the the one for the projection on rotated RT0 element for two-dimensional
elements which is an ingredient of the MITC plate element. It can be added thanks to the function
(defined in src/getfem/getfem_linearized_plates.h):
add_2D_rotated_RT0_projection(model, transname)
Some other transformations are available for the use into Hybrid High-Order methods (HHO methods,
see Tools for HHO (Hybrid High-Order) methods for more information). These transformations corre-
spond to the reconstruction of the gradient of a variable or the variable itself, the HHO methods having
separated discretizations on the interior of the element and on its faces. The different transformations
can be added with the functions (defined in src/getfem/getfem_HHO.h):
add_HHO_reconstructed_gradient(model, transname);
add_HHO_reconstructed_symmetrized_gradient(model, transname);
When using a fem cut by a level-set (using fem_level_set or mesh_fem_level_set objects), it is often
interesting to integrate the discontinuity jump of a variable, or the jump in gradient or the average value.
For this purpose, GWFL furnishes the following expressions for u a FEM variable:
Xfem_plus(u)
Xfem_plus(Grad_u)
Xfem_plus(Div_u)
Xfem_plus(Hess_u)
Xfem_plus(Test_u)
Xfem_plus(Test_Grad_u)
Xfem_plus(Test_Div_u)
Xfem_plus(Test_Hess_u)
Xfem_minus(u)
Xfem_minus(Grad_u)
Xfem_minus(Div_u)
Xfem_minus(Hess_u)
Xfem_minus(Test_u)
Xfem_minus(Test_Grad_u)
Xfem_minus(Test_Div_u)
Xfem_minus(Test_Hess_u)
which are only available when the evaluation (integration) is made on the curve/surface separat-
ing two zones of continuity, i.e. on the zero level-set of a considered level-set function (using a
mesh_im_level_set object). For instance, a jump in the variable u will be given by:
Xfem_plus(u)-Xfem_minus(u)
(Xfem_plus(u)+Xfem_minus(u))/2
The value Xfem_plus(u) is the value of u on the side where the corresponding level-set function is
positive and Xfem_minus(u) the value of u on the side where the level-set function is negative.
Additionally, note that, when integrating on a level-set with a mesh_im_level_set object, Normal
stands for the normal unit vector to the level-set in the direction of the gradient of the level-set function.
workspace.add_assignment_expression(dataname, expr,
region = mesh_region::all_convexes(), order = 1, before = false)
It adds expression expr to be evaluated at assembly time and being assigned to the data dataname which
has to be of im_data type. order represents the order of assembly where this assignement has to be done
(potential(0), weak form(1) or tangent system(2) or at each order(-1)). The default value is 1. If before
= 1, the the assignement is performed before the computation of the other assembly terms, such that the
data can be used in the remaining of the assembly as an intermediary result (be careful that it is still
considered as a data, no derivation of the expression is performed for the tangent system). If before = 0
(default), the assignement is done after the assembly terms.
Additionally, In a model, the method:
model.clear_assembly_assignments()
This section present the first version of generic assembly procedure which has been implemented in
GetFEM and is now considered as deprecated. It allows to make the assembly of arbitrary matrices in the
linear case. In the nonlinear case, some special “non_linear_term” object have to be implemented, which
could be a bit tricky and obliges to use very low-level internal tools of GetFEM. The generic weak form
language (GWFL) has been developed to circumvent these difficulties (see Compute arbitrary terms -
high-level generic assembly procedures - Generic Weak-Form Language (GWFL)).
As it can be seen in the file getfem/getfem_assembling.h, all the previous assembly procedures
use a getfem::generic_assembly object and provide it an adequate description of what must be
done. For example, the assembly of a volumic source term for a scalar FEM is done with the following
excerpt of code:
getfem::generic_assembly assem;
assem.push_im(mim);
assem.push_mf(mf);
assem.push_mf(mfdata);
assem.push_data(F);
assem.push_vec(B);
assem.set("Z=data(#2);"
"V(#1)+=comp(Base(#1).Base(#2))(:,j).Z(j);");
assem.assembly();
The first instructions declare the object, and set the data that it will use: a mesh_im object which holds
the integration methods, two mesh_fem objects, the input data F, and the destination vector B.
The input data is the vector 𝐹 , defined on mfdata. One wants to evaluate 𝑗 𝑓𝑗 ( Ω 𝜑𝑖 𝜓 𝑗 ). The
∑︀ ∫︀
instruction must be seen as something that will be executed for each convex cv of the mesh. The terms
#1 and #2 refer to the first mesh_fem and the second one (i.e. mf and mfdata). The instruction
Z=data(#2); means that for each convex, the “tensor” Z will receive the values of the first data
argument provided with push_data, at indexes corresponding to the degrees of freedom attached to
the convex of the second (#2) mesh_fem (here, Z = F[mfdata.ind_dof_of_element(cv)]).
The part V(#1)+=... means that the result of the next expression will be accumulated into the output
61
User Documentation, Release 5.4.2
vector (provided with push_vec). Here again, #1 means that we will write the result at indexes
corresponding to the degrees of freedom of the current convex with respect to the first (#1) mesh_fem.
The right hand side comp(Base(#1).Base(#2))(:,j).Z(j) contains two operations. The first
one is a computation∫︀ of𝑖 a𝑗 tensor on the convex: comp(Base(#1).Base(#2)) is evaluated as a 2-
dimensions tensor, 𝜑 𝜓 , for all degrees of freedom 𝑖 of mf and 𝑗 of mfdata attached to the current
convex. The next∑︀part is a reduction operation, C(:,j).Z(j): each named index (here 𝑗) is summed,
i.e. the result is 𝑗 𝑐𝑖,𝑗 𝑧𝑗 .
The integration method used inside comp(Base(#1).Base(#2)) is taken from mim. If you need
to use integration methods from another mesh_im object, you can specify it as the first argument of
comp, for example comp(\%2, Base(#1).Grad(#2)) will use the second mesh_im object (New
in getfem++-2.0).
An other example is the assembly of the stiffness matrix for a vector Laplacian:
getfem::generic_assembly assem;
assem.push_im(mim);
assem.push_mf(mf);
assem.push_mf(mfdata);
assem.push_data(A);
assem.push_mat(SM);
assem.set("a=data$1(#2);"
"M$1(#1,#1)+=sym(comp(vGrad(#1).vGrad(#1).Base(#2))(:,j,k,:,j,k,
˓→p).a(p))");
assem.assembly();
Now the output is written in a sparse matrix, inserted with assem.push_mat(SM). The $1 in
M$1(#1,#1) just indicates that we refer to the first matrix “pushed” (it is optional, but if the as-
sembly builds two matrices, the second one must be referred this way). The sym function ensure that
the result is symmetric (if this is not done, some round-off errors may cancel the symmetricity, and the
assembly will be a little bit slower). Next, the comp part evaluates a 7D tensor,
∫︁
𝜕𝑘 𝜙𝑖𝑗 𝜕𝑛 𝜙𝑙𝑚 𝜓 𝑝 ,
where 𝜙𝑖𝑗 is a 𝑗𝑡ℎ component of the 𝑖𝑡ℎ base function of mf and 𝜓 𝑝 is a (scalar) base function of the
second mesh_fem. Since we want to assemble
∫︁ ∑︁
𝑎(𝑥).∇𝜑𝑖 .∇𝜑𝑗 , with 𝑎(𝑥) = 𝑎𝑝 𝜓 𝑝 (𝑥),
𝑝
In the comp function, vGrad was used instead of Grad since we said that we were assembling a
vector Laplacian: that is why each vGrad part has three dimensions (dof number, component number,
and derivative number). For a scalar Laplacian, we could have used comp(Grad(#1).Grad(#1).
Base(#2))(:,k,:,k,p).a(p). But the vector form has the advantage to work in both vector and
scalar case.
The last instruction, assem.assembly(), does evaluate the expression on each convex. For an as-
sembly over a boundary just call assem.assembly(rg), where rg is a getfem::mesh_region
object. rg might also be a number, in that case the mesh region taken into account is mim.
linked_mesh().region(rg).
The third example shows how to compute the 𝐿2 norm of a scalar or vector field on a mesh boundary:
assem.push_im(mim);
assem.push_mf(mf);
assem.push_data(U);
std::vector<scalar_type> v(1);
assem.push_vec(v);
assem.set("u=data(#1);"
"V()+=u(i).u(j).comp(vBase(#1).vBase(#1))(i,k,j,k)");
assem.assembly(boundary_number);
This one is easy to read. When assembly returns, v[0] will contain
∑︁ (︂∫︁ )︂
𝑢𝑖 𝜙𝑖𝑘 𝑢𝑗 𝜙𝑗𝑘
𝑖,𝑗,𝑘 𝑏𝑜𝑢𝑛𝑑𝑎𝑟𝑦
The fourth and last example shows an (sub-optimal) assembly of the linear elasticity problem with a
complete Hooke tensor:
assem.set("h=data$1(qdim(#1),qdim(#1),qdim(#1),qdim(#1),#2);"
"t=comp(vGrad(#1).vGrad(#1).Base(#2));"
"e=(t{:,2,3,:,5,6,:}+t{:,3,2,:,5,6,:}+t{:,2,3,:,6,5,:}+t{:,3,2,:,
˓→6,5,:})/4;"
"M(#1,#1)+= sym(e(:,j,k,:,m,n,p).h(j,k,m,n,p))");
where ℎ is the Hooke tensor, and : means the scalar product between matrices. Since we assume it is
not constant, ℎ is given on the second mesh_fem: ℎ𝑖𝑗𝑘𝑙 (𝑥) = 𝑝 ℎ𝑝𝑖𝑗𝑘𝑙 𝜓 𝑝 . Hence the first line declares
∑︀
that the first data “pushed” is indeed a five-dimensions tensor, the first fourth ones being all equal to the
target dimension of the first mesh_fem, and the last one being equal to the number of degrees of freedom
of the second mesh_fem. The comp part still computes the same 7D tensor than for the vector Laplacian
case. From this tensor, one evaluates 𝜀(𝜙𝑖 )𝑗𝑘 𝜀(𝜑𝑙 )𝑚𝑛 𝜓 𝑝 via permutations, and finally the expression is
reduced against the hook tensor.
• Base(#i): evaluate the value of the base functions of the ith mesh_fem
• Grad(#i): evaluate the value of the gradient of the base functions of the ith mesh_fem
• Hess(#i): evaluate the value of the Hessian of the base functions of the ith mesh_fem
• Normal(): evaluate the unit normal (should not be used for volumic integrations !)
• NonLin$x(#mf1,... #mfn): evaluate the xth non-linear term (inserted with
push_nonlinear_term(pnonlinear_elem_term)) using the listed mesh_fem
objects.
• GradGT(), GradGTInv(): evaluate the gradient (and its inverse) of the geometric transforma-
tion of the current convex.
Note: you may reference any data object inside the comp command, and perform reductions inside the
comp(). This feature is mostly interesting for speeding up assembly of nonlinear terms (see the file
getfem/getfem_nonlinear_elasticity.h for an example of use).
Slices may be mixed with reduction operations t(:,4,i,i) takes a slice at index 4 of the second
dimension, and reduces the diagonal of dimension 3 and 4. Please note that index numbers for slices
start at 1 and not 0 !!
mdim(#2) is evaluated as the mesh dimension associated to the second mesh_fem, while qdim(#2)
is the target dimension of the mesh_fem.
The diagonal of a tensor can be obtained with t{:,:,3,3} (which is strictly equivalent to t{1,2,
3,3}: the colon is just here to improve the readability). This is the same operator than for permutation
operations. Note that t{:,:,1,1} or t{:,:,4,4} are not valid operations.
The print command can be used to see the tensor: "print comp(Base(#1));" will print the
integrals of the base functions for each convex.
If there is more than one data array, output array or output sparse matrix, one can use data$2, data$3,
V$2, M$2,. . .
Procedures defined in the file getfem/getfem_assembling.h allow the assembly of stiffness ma-
trices, mass matrices and boundary conditions for a few amount of classical partial differential equation
problems. All the procedures have vectors and matrices template parameters in order to be used with
any matrix library.
CAUTION: The assembly procedures do not clean the matrix/vector at the begining of the assembly in
order to keep the possibility to perform several assembly operations on the same matrix/vector. Conse-
quently, one has to clean the matrix/vector before the first assembly operation.
where Ω is an open domain of arbitrary dimension, Γ𝐷 and Γ𝑁 are parts of the boundary of Ω, 𝑢(𝑥)
is the unknown, 𝑎(𝑥) is a given coefficient, 𝑓 (𝑥) is a given source term, 𝑈 (𝑥) the prescribed value of
𝑢(𝑥) on Γ𝐷 and 𝐹 (𝑥) is the prescribed normal derivative of 𝑢(𝑥) on Γ𝑁 . The function to be called to
assemble the stiffness matrix is:
where
• SM is a matrix of any type having the right dimension (i.e. mfu.nb_dof()),
• mim is a variable of type getfem::mesh_im defining the integration method used,
• mfu is a variable of type getfem::mesh_fem and should define the finite element method for
the solution,
65
User Documentation, Release 5.4.2
• mfd is a variable of type getfem::mesh_fem (possibly equal to mfu) describing the finite
element method on which the coefficient 𝑎(𝑥) is defined,
• A is the (real or complex) vector of the values of this coefficient on each degree of freedom of
mfd.
Both mesh_fem should use the same mesh (i.e. &mfu.linked_mesh() == &mfd.
linked_mesh()).
It is important to pay attention to the fact that the integration methods stored in mim, used to compute the
elementary matrices, have to be chosen of sufficient order. The order has to be determined considering
the polynomial degrees of element in mfu, in mfd and the geometric transformations for non-linear
cases. For example, with linear geometric transformations, if mfu is a 𝑃𝐾 FEM, and mfd is a 𝑃𝐿
FEM, the integration will have to be chosen ∫︀ of order ≥ 2(𝐾 − 1) + 𝐿, since the elementary integrals
computed during the assembly of SM are ∇𝜙𝑖 ∇𝜙𝑗 𝜓𝑘 (with 𝜙𝑖 the basis functions for mfu and 𝜓𝑖 the
basis functions for mfd).
To assemble the source term, the function to be called is:
where B is a vector of any type having the correct dimension (still mfu.nb_dof()), mim is a vari-
able of type getfem::mesh_im defining the integration method used, mfd is a variable of type
getfem::mesh_fem (possibly equal to mfu) describing the finite element method on which 𝑓 (𝑥) is
defined, and V is the vector of the values of 𝑓 (𝑥) on each degree of freedom of mfd.
The function asm_source_term also has an optional argument, which is a reference to
a getfem::mesh_region (or just an integer i, in which case mim.linked_mesh().
region(i) will be considered). Hence for the Neumann condition on Γ𝑁 , the same function:
is used again, with nbound is the index of the boundary Γ𝑁 in the linked mesh of mim, mfu and mfd.
There is two manner (well not really, since it is also possible to use Lagrange multipliers, or to use
penalization) to take into account the Dirichlet condition on Γ𝐷 , changing the linear system or explicitly
reduce to the kernel of the Dirichlet condition. For the first manner, the following function is defined:
where nbound is the index of the boundary Γ𝐷 where the Dirichlet condition is applied, R is the vector
of the values of 𝑅(𝑥) on each degree of freedom of mfu. This operation should be the last one because
it transforms the stiffness matrix SM. It works only for Lagrange elements. At the end, one obtains the
discrete system:
[𝑆𝑀 ]𝑈 = 𝐵,
multiplier defined by mf_mult. The fem mf_mult could be often chosen equal to mf_u except when
mf_u is too “complex”.
This function just assemble these constraints into a new linear system 𝐻𝑢 = 𝑅, doing some additional
simplification in order to obtain a “simple” constraints matrix.
Then, one should call:
which will return a vector 𝑈𝑑 which satisfies the Dirichlet condition, and an orthogonal basis 𝑁 of the
kernel of 𝐻. Hence, the discrete system that must be solved is:
and the solution is $U=N U_{int}+U_d$. The output matrix 𝑁 should be a 𝑛𝑏𝑑𝑜𝑓 × 𝑛𝑏𝑑𝑜𝑓 (sparse)
matrix but should be resized to ncols columns. The output vector 𝑈𝑑 should be a 𝑛𝑏𝑑𝑜𝑓 vector. A big
advantage of this approach is to be generic, and do not prescribed for the finite element method mf_u
to be of Lagrange type. If mf_u and mf_d are different, there is implicitly a projection (with respect to
the 𝐿2 norm) of the data on the finite element mf_u.
If you want to treat the more general scalar elliptic equation div(𝐴(𝑥)∇𝑢), where 𝐴(𝑥) is square matrix,
you should use:
The matrix data A should be defined on mfdata. It is expected as a vector representing a 𝑛 × 𝑛 × 𝑛𝑏𝑑𝑜𝑓
tensor (in Fortran order), where 𝑛 is the mesh dimension of mfu, and 𝑛𝑏𝑑𝑜𝑓 is the number of dof of
mfdata.
The following function assembles the stiffness matrix for linear elasticity:
where SM is a matrix of any type having the right dimension (i.e. here mfu.nb_dof()), mim is a
variable of type getfem::mesh_im defining the integration method used, mfu is a variable of type
getfem::mesh_fem and should define the finite element method for the solution, mfd is a variable
of type getfem::mesh_fem (possibly equal to mfu) describing the finite element method on which
the Lamé coefficient are defined, LAMBDA and MU are vectors of the values of Lamé coefficients on each
degree of freedom of mfd.
Caution: Linear elasticity problem is a vectorial problem, so the target dimension of mfu (see
mf.set_qdim(Q)) should be the same as the dimension of the mesh.
In order to assemble source term, Neumann and Dirichlet conditions, same functions as in previous
section can be used.
It is also possible to obtain mass matrix on a boundary with the same function:
getfem::asm_mass_matrix(M, mim, mf1, mf2, nbound);
where nbound is the region index in mim.linked_mesh(), or a mesh_region object.
Once a solution has been computed, it is quite easy to extract any quantity of interest on it with the
interpolation functions for instance for post-treatment.
where mf1 is a variable of type getfem::mesh_fem and describes the finite element method on
which the source field U is defined, mf2 is the finite element method on which U will be interpolated.
extrapolation is an optional parameter. The values are 0 not to allow the extrapolation, 1 for an
extrapolation of the exterior points near the boundary and 2 for the extrapolation of all exterior points
(could be expensive).
The dimension of U should be a multiple of mf1.nb_dof(), and the interpolated data V should be
correctly sized (multiple of mf2.nb_dof()).
. . . important:
``mf2`` should be of Lagrange type for the interpolation to make sense but
˓→the
meshes linked to ``mf1`` and ``mf2`` may be different (and this is the
interest of this function). There is no restriction for the dimension of
˓→the
domain (you can interpolate a 2D mesh on a line etc.).
If you need to perform more than one interpolation between the same finite element methods, it might
be more efficient to use the function:
69
User Documentation, Release 5.4.2
where M is a row matrix which will be filled with the linear map representing the interpolation (i.e.
such that V = MU). The matrix should have the correct dimensions (i.e. mf2.nb_dof()``x``mf1.
nb_dof()). Once this matrix is built, the interpolation is done with a simple matrix multiplication:
gmm::mult(M, U, V);
It is possible to extract some arbitrary expressions on possibly several fields thanks to GWFL and the
interpolation functions.
This is specially dedicated to the model object (but it can also be used with a ga_workspace object).
For instance if md is a valid object containing some defined variables u (vectorial) and p (scalar), one
can interpolate on a Lagrange finite element method an expression such as p*Trace(Grad_u). The
resulting expression can be scalar, vectorial or tensorial. The size of the resulting vector is automatically
adapted.
The high-level generic interpolation functions are defined in the file getfem/
getfem_generic_assembly.h.
There is different interpolation functions corresponding to the interpolation on a Lagrange fem on the
same mesh, the interpolation on a cloud on points or on a getfem::im_data object.
Interpolation on a Lagrange fem:
where workspace is a getfem::ga_workspace object which aims to store the different variables
and data (see Compute arbitrary terms - high-level generic assembly procedures - Generic Weak-Form
Language (GWFL)), mf is the getfem::mesh_fem object reresenting the Lagrange fem on which
the interpolation is to be done and result is a beot::base_vector which store the interpolatin.
Note that the workspace should contain the epression to be interpolated.
where md is a getfem::model object (containing the variables and data), expr (std::string object)
is the expression to be interpolated, mf is the getfem::mesh_fem object reresenting the Lagrange
fem on which the interpolation is to be done, result is the vector in which the interpolation is stored
and rg is the optional mesh region.
Interpolation on a cloud of points:
where md is a getfem::model object (containing the variables and data), expr (std::string object)
is the expression to be interpolated, mti is a getfem::mesh_trans_inv object which stores the
cloud of points (see getfem/getfem_interpolation.h), result is the vector in which the
interpolation is stored, extrapolation is an option for extrapolating the field outside the mesh for
outside points, rg is the optional mesh region and nbpoints is the optional maximal number of points.
Interpolation on an im_data object (on the Gauss points of an integration method):
where md is a getfem::model object (containing the variables and data), expr (std::string object)
is the expression to be interpolated, imd is a getfem::im_data object which refers to a integration
method (see getfem/getfem_im_data.h), result is the vector in which the interpolation is
stored and rg is the optional mesh region.
Basically, It is sufficient to describe an element on the reference element, i.e. to describe each base
function of each degree of freedom. Intrinsically vectorial elements are supported (see for instance
Nedelec and Raviart-Thomas elements). Finite element methods that are not equivalent via the geometric
transformation (not 𝜏 -equivalent in GetFEM jargon, such as vectorial elements, Hermite elements . . . )
an additional linear transformation of the degrees of freedom depending on the real element should be
described (see the implementation of Argyris element for instance).
Please read dp for more details and see the files getfem/getfem_fem.h, getfem_fem.cc for
practical implementation.
73
User Documentation, Release 5.4.2
A perl script automatically incorporates new cubature methods from a description file. You can
see in the directory cubature such description files (with extension .IM) . For instance for
IM_TETRAHEDRON(5) the following file describes the method:
NAME = IM_TETRAHEDRON(5)
N = 3
GEOTRANS = GT_PK(3,1)
NBPT = 4
0, 0.25, 0.25, 0.25, 0.008818342151675485
1, 0.31979362782962991, 0.31979362782962991, 0.31979362782962991, 0.
˓→011511367871045398
1, 0.091971078052723033, 0.091971078052723033, 0.091971078052723033, 0.
˓→01198951396316977
1, 0.056350832689629156, 0.056350832689629156, 0.44364916731037084, 0.
˓→008818342151675485
NBF = 4 IM_TRIANGLE(5)
IM_TRIANGLE(5)
IM_TRIANGLE(5)
IM_TRIANGLE(5)
where NAME is the name of the method in GetFEM (constant integer parameter are allowed), N is the
dimension, GEOTRANS describes a valid geometric transformation of GetFEM. This geometric trans-
formation just defines the reference element on which the integration method is described. NBPT is the
number of integration node definitions. Integration node definitions include a symmetry definition such
that the total number of integration nodes would be greater than NBPT.
Composition of the integration node definition:
• an integer: 0 = no symmetry, 1 = full symmetric (x6 for a triangle, x4 for a quadrangle, x24 for a
tetrahedron . . . ),
• the N coordinates of the integration node,
• the load.
NBF is the number of faces of the reference element (should correspond to GEOTRANS). Then follows an
75
User Documentation, Release 5.4.2
already existing integration method for each face (each on a line). This is necessary to make integrations
on boundaries.
The file format is inspired from [EncyclopCubature].
Since v2.0, GetFEM offers a certain number of facilities to support Xfem and fictitious domain methods
with a cut-fem strategy. Most of these tools have been initially mainly developed by Julien Pommier for
the study published in [LA-PO-RE-SA2005].
The implementation is a fairly large generality, based on the use of level-sets, as suggested in
[SU-CH-MO-BE2001] and allows simultaneous use of a large number of level-sets which can cross.
The Xfem implementation for the discretization of the jump follows the strategy of [HA-HA2004] al-
though we had no knowledge of this work during implementation. This means that there is no degree
of freedom representing the jump across the level-set. Instead, the degrees of freedom represent the
displacement of each side of the level-set. This is essential in any way in the presence of level-set that
intersect each other because it may exist more than two different zones of continuity inside a single
element.
The cut fem strategy for fictitious domain method has been used for the first time with GetFEM for
the study published in [HA-RE2009] where a quite simple stabilization strategy is proposed. Here also,
before knowing the existence of the Work of E. Burman and P. Hanbo [bu-ha2010] on that topic.
The tools for Xfem have been then enriched by the PhD works of J. Larsy (see for instance
[LA-RE-SA2010]) the one of E. Chahine (see for instance [CH-LA-RE2011], [NI-RE-CH2011]), of S.
Amdouni (see for instance [AM-MO-RE2014], [AM-MO-RE2014b]) and of M. Fabre (see for instance
[Fa-Po-Re2015]).
Important: All the tools listed below needs the package qhull installed on your system. This package
is widely available. It computes convex hull and Delaunay triangulations in arbitrary dimension.
77
User Documentation, Release 5.4.2
Some structure are defined to manipulate level-set functions defined by piecewise polynomial func-
tion on a mesh. In the file getfem/getfem_levelset.h a level-set is represented by a func-
tion defined on a Lagrange fem of a certain degree on a mesh. The constructor to define a new
getfem::level_set is the following:
where mesh is a valid mesh of type getfem::mesh, degree is the degree of the polynomials (1 is
the default value), and with_secondary is a boolean whose default value is false. The secondary
level-set is used to represent fractures (if 𝑝(𝑥) is the primary level-set function and 𝑠(𝑥) is the secondary
level-set function, the crack is defined by 𝑝(𝑥) = 0 and 𝑠(𝑥) ≤ 0: the role of the secondary is to delimit
the crack).
Each level-set function is defined by a mesh_fem mf and the dof values over this mesh_fem, in a vec-
tor. The object getfem::level_set contains a mesh_fem and the vectors of dof for the corre-
sponding function(s). The method ls.value(0) returns the vector of dof for the primary level-set
function, so that these values can be set. The method ls.value(1) returns the dof vector for the
secondary level-set function if any. The method ls.get_mesh_fem() returns a reference on the
getfem::mesh_fem object.
Note that, in applications, the level-set function often evolves thanks to an Hamilton-Jacobi equation
(for its re-initialization for instance). See the A pure convection method which can be used in the ap-
proximation of a Hamilton-Jacobi equation.
In order to compute adapted integration methods and finite element methods to represent a field
which is discontinuous across one or several level-sets, a certain number of pre-computations have
to be done at the mesh level. In getfem/getfem_mesh_level_set.h is defined the object
getfem::mesh_level_set which handles these pre-computations. The constructor of this object
is the following:
getfem::mesh_level_set mls(mesh);
where mesh is a valid mesh of type getfem::mesh. In order to indicate that the mesh is cut by
a level-set, one has to call the method mls.add_level_set(ls), where ls is an object of type
getfem::level_set. An arbitrary number of level-sets can be added. To initialize the object or
to actualize it when the value of the level-set function is modified, one has to call the method mls.
adapt().
In particular a subdivision of each element cut by the level-set is made with simplices. Note that the
whole cut-mesh is generally not conformal.
The cut-mesh can be obtained for instance for post-treatment thanks to mls.global_cut_mesh(m)
which fill m with the cut-mesh.
For fields which are discontinuous across a level-set, integration methods have to be
adapted. The object getfem::mesh_im_level_set defined in the file getfem/
getfem_mesh_im_level_set.h defines a composite integration method for the elements
cut by the level-set. The constructor of this object is the following:
where mls is an object of type getfem::mesh_level_set, where is an enum for which possible
values are
• getfem::mesh_im_level_set::INTEGRATE_INSIDE (integrate over 𝑝(𝑥) < 0),
• getfem::mesh_im_level_set::INTEGRATE_OUTSIDE (integrate over 𝑝(𝑥) > 0),
• getfem::mesh_im_level_set::INTEGRATE_ALL,
• getfem::mesh_im_level_set::INTEGRATE_BOUNDARY (integrate over 𝑝(𝑥) = 0 and
𝑠(𝑥) ≤ 0)
The argument regular_im should be of type pintegration_method, and will be the integration
method applied on each sub-simplex of the composite integration for elements cut by the level-set.
The optional singular_im should be also of type pintegration_method and is used for crack
singular functions: it is applied to sub-simplices which share a vertex with the crack tip (the specific
integration method IM_QUASI_POLAR(..) is well suited for this purpose).
The object getfem::mesh_im_level_set can be used as a classical getfem::mesh_im ob-
ject (for instance the method mim.set_integration_method(...) allows to set the integration
methods for the elements which are not cut by the level-set).
To initialize the object or to actualize it when the value of the level-set function is modified, one has to
call the method mim.adapt().
When more than one level-set is declared on the getfem::mesh_level_set object, it is possible
to set more precisely the integration domain using the method:
mim.set_level_set_boolean_operations("desc");
where “desc” is a string containing the description of the boolean operation which defines the integration
domain. The syntax is simple, for example if there are 3 different level-set,
“a*b*c” is the intersection of the domains defined by each level-set (this is the default
behavior if this function is not called).
“a+b+c” is the union of their domains.
“c-(a+b)” is the domain of the third level-set minus the union of the domains of the two
others.
“!a” is the complementary of the domain of a (i.e. it is the domain where a(x)>0)
The first level-set is always referred to with “a”, the second with “b”, and so on.
16.4 Cut-fem
The implementation of a cut finite element method such as described in [bu-ha2010], i.e. a finite element
on a fictitious domain restricted to a smaller real domain, is possible just using the previous tools and
mainly the adapted integration method. Several examples are available on GetFEM test programs. See
for instance interface/tests/python/demo_fictitious_domain.py or interface/
tests/matlab/demo_fictitious_domain.m.
In this context, one often needs to restrict the unknown finite element field to the degrees of free-
dom whose corresponding shape function supports have an intersection with the real domain. This can
be done using the partial_mesh_fem object. See for instance interface/tests/matlab/
demo_structural_optimization.m.
Note that often, a stabilization technique have to be considered in order to treat eventual locking phe-
nomena due to element with very small intersection with the real domain for example when applying a
Dirichlet condition. See for instance [bu-ha2010], [HA-RE2009] and [Fa-Po-Re2015].
where mls is a valid mesh of type getfem::mesh_level_set and mf is the an object of type
getfem::mesh_fem which defines the finite element method used for elements which are not cut by
the level-sets.
To initialize the object or to actualize it when the value of the level-set function is modified, one has to
call the method mfls.adapt().
To represent discontinuous fields, the finite element method is enriched with discontinuous functions
which are the product of some Heaviside functions by the shape functions of the finite element method
represented by mf (see [HA-HA2004] and [Xfem] for more details).
16.6 Xfem
The Xfem (see [Xfem]) consists not only in the enrichment with some Heaviside functions (which
is done by the object getfem::mesh_fem_level_set) but also the enrichment with asymp-
totic displacement at the crack tip. There is several manner to enrich with an asymptotic displace-
ment: enrichment only on the element containing the crack tip as in [Xfem], enrichment in a fixed
size zone as in [LA-PO-RE-SA2005] or [Be-Mi-Mo-Bu2005], enrichment with a cut-off function as in
[CH-LA-RE2008] or [NI-RE-CH2011] or with an integral matching condition between the enriched and
non-enriched zones as in [CH-LA-RE2011]. The choice in Getfem fell on maximum flexibility to easily
implement all possibilities. As it is mainly a transformation of the finite element method itself, two tools
have been defined to produce some enriched finite elements:
where mf_sing should be a global ‘finite element method’, in fact just a col-
lection of global functions (with or without a cut-off function) defined thanks to
the object getfem::mesh_fem_global_function (see the file src/getfem/
getfem_mesh_fem_global_function.h) and mf_part_unity a basic scalar finite
element method. The resulting ‘‘ getfem::mesh_fem_product‘‘ is the linear combination of all
the product of the shape function of the two given finite element methods, possibly restricted to a
sub-set of degrees of freedom of the first finite element method given by the method mf_asympt.
set_enrichment(enriched_dofs).
Once the asymptotic enrichment is defined, the object getfem::mesh_fem_sum allows to produce
the direct sum of two finite element methods. For instance of the one enriched by the Heaviside functions
(getfem::mesh_fem_level_set object) and the asymptotic enrichment.
See interface/tests/matlab/demo_crack.m, interface/tests/python/
demo_crack.py or tests/crack.cc for some examples of use of these tools.
Additionally, GWFL, the generic weak form language, defines the two commands Xfem_plus and
Xfem_minus allowing to take into account the jump of any field or derivative of any field across a
level-set (see Xfem discontinuity evaluation (with mesh_fem_level_set)). This a priori allows to write
any interface law easily.
Note also that some procedures are available in the file src/getfem/getfem_crack_sif.h to
compute the stress intensity factors in 2D (restricted to homogeneous isotropic linearized elasticity).
Several tools are available to represent the solution only on a side of a levels-set or on both taking into
account the discontinuity (for Xfem approximation).
When a cut-mesh mls is used (i.e. a getfem::mesh_level_set object), is is possible to obtain
the set of all sub-elements with the command:
mls.global_cut_mesh(mcut);
where mcut has to be an empty mesh which will be fill by the sub-elements. Note that the resulting
mesh is a non-regular one in the sense that the sub-mesh of all elements are not conformal at the element
edges/faces. It is however possible to interolate on a Lagrange fem on this mesh and make a post-
treatment with it to correctly represent a discontinuous field.
Another mean to represent only the interesting part of the solution when a fictitious domain method is
used is to use the mesh slices defined by an isovalue level-set (see Producing mesh slices).
see for instance files interface/tests/matlab/demo_crack.m, interface/
tests/python/demo_fictitious_domain.py and interface/tests/matlab/
demo_structural_optimization.m.
HHO method are hybrid methods in the sense that they have both degrees of freedom located on the
element of a mesh and on the faces of the elements which represent separated approximations. HHO
method are primal methods in the sense that both the degree of freedom in the element and on the
faces represent the main unknown of the problem (no lagrange multipliers is introduced). The interest of
these methods, first developped in [Di-Er2015], [Di-Er2017] is their accuracy and their great robustness,
in particular with respect to the element shapes and their locking-free properties. Moreover, they can
be extended without difficulty to the approximation of nonlinear problems (see [AB-ER-PI2018] for
hyper-elasticity, [AB-ER-PI2019] for plasticity and [ca-ch-er2019] for contact problems).
HHO methods can be applied to arbitrary shape elements. However, the implementation in GetFEM is
for the moment limited to standard elements : simplices, quadrilaterals, hexahedrons, . . . Moreover this
implementation is still experimental and not pretending to optimality. For the moment, there is no tool
to make an automatic condensation of internal dofs.
HHO elements are composite ones having a polynomial approximation space for the interior of the
element and a polynomial approximation for each face of the element. Moreover, this is a discontinous
approximation, in the sens that no continuity is prescribed between the approximation inside the element
and the approximation on the faces, neither than between the approximations on two different faces of
the element. However, when two neighbor elements share a face, the approximation on this face is
shared by the two elements. GetFEM provide a specific method simply called FEM_HHO(fem_int,
fem_face1, fem_face2, ...) which allows to build an hybrid method from standard finite
element spaces. For instance, on a triangle, a possible HHO method can be obtained with:
The first argument to FEM_HHO(...) is the fem for the interior of the element. It has to be a discon-
tinuous FEM. The method FEM_SIMPLEX_IPK(2,2) is a discontinous method having its degrees of
freedom in the strict interior of the element, which ensure that no dof identification will be done. The
83
User Documentation, Release 5.4.2
second argument is the fem for the faces (if only one method is given, it will be applied to all faces, but it
is also possible to give a different method for each face). Their is no verification on the fact that the given
method are of discontinuous type (In fact, a method like FEM_HHO(FEM_PK(2,2), FEM_PK(1,
2)) will have no difference with FEM_PK(2,2) since the degree of freedom on the faces will be
identified with the interior ones).
For the moment, the fursnished element for interior and faces are - FEM_SIMPLEX_IPK(n,
k) : interior PK element of degree k for the simplices in dimension n (equivalent to
FEM_PK_DISCONTINUOUS(n,k,0.1)). - FEM_QUAD_IPK(n,k) : interior PK element of de-
gree k for the quadrilaterals in dimension n. - FEM_PRISM_IPK(n,k) : interior PK element of degree
k for the prisms in dimension n. - FEM_SIMPLEX_CIPK(n,k) : interior PK element on simplices
which is additionnaly connectable. Designed to be use on HHO element face. - FEM_QUAD_CIPK(k)
: interior PK element on a quadrilateral which is additionnaly connectable. Designed to be use on HHO
element face.
For a variable u, we will note 𝑢𝑇 its value in the interior of the element 𝑇 and 𝑢𝜕𝑇 its value on the
boundary of 𝑇 (corresponding to the two different approximations). The reconstruction operators are
implemeted in GetFEM as elementary transformations, as described in the section Elementary transfor-
mations.
The first reconstruction operator is the reconstructed gradient. Given a certain polynomial space 𝑉𝐺 , the
reconstructed gradient 𝐺(𝑢) will be the solution to the local problem
∫︁ ∫︁ ∫︁
𝐺(𝑢) : 𝜏 𝑑𝑥 = ∇𝑢𝑇 : 𝜏 𝑑𝑥 + (𝑢𝜕𝑇 − 𝑢𝑇 ).(𝜏 𝑛𝑇 )𝑑Γ, ∀𝜏 ∈ 𝑉𝐺
𝑇 𝑇 𝜕𝑇
where 𝑛𝑇 is the outward unit normal to 𝑇 on 𝜕𝑇 . Note that the space 𝑉 is a vector-valued one if u is a
scalar field variable (in that case, 𝐺(𝑢) : 𝜏 reduces to 𝐺(𝑢).𝜏 ) and a matrix-valued one if u is a vector
field variable.
In order to be used, the elementary transformation corresponding to this operator has first to be added to
the model by the command:
add_HHO_reconstructed_gradient(model, transname);
where transname is an arbitrary name which will designate the transformation in GWFL (the
generic weak form language). Then, it will be possible to refer to the reconstructed gradi-
ent of a variable u into GWFL as Elementary_transformation(u, HHO_grad, Gu), if
transname="HHO_grad". The third parameter of the transformation Gu should be a fem variable
or a data of the model. This variable will not be used on itself but will determine the finite element space
of the reconstruction (the space 𝑉𝐺 ).
This is an example of use with the Python interface for a two-dimensional triangule mesh m
mfu = gf.MeshFem(m, 1)
mfgu = gf.MeshFem(m, N)
mfu.set_fem(gf.Fem('FEM_HHO(FEM_SIMPLEX_IPK(2,2),FEM_SIMPLEX_CIPK(1,2))'))
mfgu.set_fem(gf.Fem('FEM_PK(2,2)'))
(continues on next page)
md = gf.Model('real')
md.add_fem_variable('u', mfu)
md.add_fem_data('Gu', mfgu)
md.add_HHO_reconstructed_gradient('HHO_Grad')
md.add_macro('HHO_Grad_u', 'Elementary_transformation(u, HHO_Grad, Gu)')
md.add_macro('HHO_Grad_Test_u', 'Elementary_transformation(Test_u, HHO_
˓→Grad, Gu)')
The macro definitions allowing to use the gradient of the variable inside weak formulations as usual. For
instance, the addition of a weak term for the Laplace equation can then be simply written:
md.add_linear_term(mim, 'HHO_Grad_u.HHO_Grad_Test_u')
Two complete examples of use are given in the test programs interface/tests/
demo_laplacian_HHO.py and interface/tests/demo_elasticity_HHO.py.
The symmetrized gradient is only for vector field variables and additionally when the vector field dimen-
sion is the same as the domain dimension. This is usually the case for instance for elasticity problems.
With the same notation as in the previous section, the reconstructed gradient 𝐺𝑠 (𝑢) will be the solution
to the local problem
∫︁ ∫︁ ∫︁
𝐺𝑠 (𝑢) : 𝜏 𝑑𝑥 = ∇𝑠 𝑢𝑇 : 𝜏 𝑑𝑥 + (𝑢𝜕𝑇 − 𝑢𝑇 ).(𝜏 𝑠 𝑛𝑇 )𝑑Γ, ∀𝜏 ∈ 𝑉𝐺
𝑇 𝑇 𝜕𝑇
add_HHO_reconstructed_symmetrized_gradient(model, transname);
A recontruction of higher order can be done using both the approximation on the interior and the ap-
proximation on the faces. The recontructed variable 𝐷(𝑢) will be the solution to the local Neumann
problem on a chosen space 𝑉𝐷
∫︁ ∫︁ ∫︁
∇𝐷(𝑢).∇𝑣𝑑𝑥 = ∇𝑢𝑇 .∇𝑣𝑑𝑥 + (𝑢𝜕𝑇 − 𝑢𝑇 ).(∇𝑣𝑛𝑇 )𝑑Γ, ∀𝑣 ∈ 𝑉𝐷
𝑇 𝑇 𝜕𝑇
The corresponding elementary transformation can be added to the model by the command:
add_HHO_reconstructed_value(model, transname);
A variant of the recontruction of a variable is the one using a symmetrized gradient. It can be used only
for vector field variables and additionally when the vector field dimension is the same as the domain
dimension. The recontructed variable 𝐷(𝑢) will be the solution to the local Neumann problem on a
chosen space 𝑉𝐷
∫︁ ∫︁ ∫︁
𝑠 𝑠 𝑠 𝑠
∇ 𝐷(𝑢).∇ 𝑣𝑑𝑥 = ∇ 𝑢𝑇 .∇ 𝑣𝑑𝑥 + (𝑢𝜕𝑇 − 𝑢𝑇 ).(∇𝑠 𝑣𝑛𝑇 )𝑑Γ, ∀𝑣 ∈ 𝑉𝐷
𝑇 𝑇 𝜕𝑇
add_HHO_reconstructed_value(model, transname);
The stabilization operators is an operator that measure in a sense the discontinuity of the approximation.
A stabilization is obtained by a penalization term using this operator. The stabilization operator 𝑆(𝑢) is
defined on the boundary space 𝑉𝜕𝑇 of the element, with the formula
where 𝐷(𝑢) is the reconstruction operator on a polynomial space one degree higher that the finite ele-
ment space used for the variable, Π𝜕𝑇 is the 𝐿2 projection onto the space of the face approximations and
Π𝑇 the 𝐿2 projection onto the space of the interior of the element.
For vector field variables having the same dimension as the domain, there exists also a stabilization
operator using the symmetrized gradient, which is defined by
The corresponding elementary transformations can be added to the model by the two commands:
add_HHO_stabilization(model, transname);
add_HHO_symmetrized_stabilization(model, transname);
Because each base function of the finite element method has to be interpolated, such a computation can
be a heavy procedure. By default, the interpolated fem object store the interpolation data.
The interpolation is made on each Gauss point of the integration methods of mim, so only this integration
method can be used in assembly procedures.
For instance if you need to compute the mass matrix between two different finite element methods
defined on two different meshes, this is an example of code which interpolate the second FEM. on the
mesh of the first FEM., assuming that mf describes the finite element method and mim is the chosen
integration method:
getfem::mesh_fem mf_interpole(mfu.linked_mesh());
pfem ifem = getfem::new_interpolated_fem(mf, mim);
dal::bit_vector nn = mfu.convex_index();
mf_interpole.set_finite_element(nn, ifem);
getfem::asm_mass_matrix(SM1, mim, mfu, mf_interpole);
del_interpolated_fem(ifem);
The object pointed by ifem contains all the information concerning the interpolation. It could use a lot
of memory. As pfem is a shared_ptr, the interpolated fem will be automatically destroyed when the last
pointer on it is destroyed. To obtain a better accuracy, it is better to refine the integration method (with
IM_STRUCTURED_COMPOSITE for instance) rather than increase its order.
89
User Documentation, Release 5.4.2
Instead of using the previous tools (interpolated and projected fems), it is possible to use a finite element
variable defined on an another mesh than the one on which an assembly is computed using the “inter-
polate transformation” tool of GWFL (the generic weak form language, see Interpolate transformations
), the finite element variables will be interpolated on each Gauss point. There is no restriction on the
dimensions of the mesh used, which means in particular that a two-dimensional fem variable can be in-
terpolated on a one-dimensional mesh (allowing the coupling of shell and beam elements, for instance).
It is also possible to use some transformations like polar coordinates to euclidean ones.
Mortar methods are supported by GetFEM. The coupling term between non matching meshes can in par-
ticular be computed using the interpolate transformations of GWFL (see Interpolate transformations).
91
User Documentation, Release 5.4.2
Compute derivatives
The file getfem/getfem_derivatives.h defines the following function to compute the gradient
of a solution:
where mf1 is a variable of type mesh_fem and describes the finite element method on which the solution
is defined, mf2 describes the finite element method to compute the gradient, U is a vector representing
the solution and should be of size mf1.nb_dof(), V is the vector on which the gradient will be
computed and should be of size N * mf2.nb_dof(), with N the dimension of the domain.
93
User Documentation, Release 5.4.2
There are essentially four ways to view the result of getfem computations:
• Scilab, Octave or Matlab, with the interface.
• The open-source Paraview, Mayavi2, PyVista or any other VTK/VTU file viewer.
• The open-source OpenDX program.
• The open-source Gmsh program.
The objects that can be exported are, mesh, mesh_fem objects, and stored_mesh_slice.
21.1 Saving mesh and mesh_fem objects for the Matlab interface
If you have installed the Scilab, Octave or Matlab interface, you can simply use
mesh_fem::write_to_file and save the solution as a plain text file, and then, load them
with the interface. For example, supposing you have a solution U on a mesh_fem mf,:
std::fstream f("solution.U",std::ios::out);
for (unsigned i=0; i < gmm::vect_size(U); ++i)
f << U[i] << "\verb+\+n";
// when the 2nd arg is true, the mesh is saved with the |mf|
mf.write_to_file("solution.mf", true);
>> U=load('solution.U');
>> mf=gfMeshFem('load','solution.mf');
>> gf_plot(mf,U,'mesh','on');
95
User Documentation, Release 5.4.2
or getfem::mesh_fem, and all except VTU can be used for exporting the more versatile
getfem::stored_mesh_slice. The corresponding four classes: getfem::vtk_export,
getfem::vtu_export, getfem::dx_export and getfem::pos_export are contained in
the file getfem/getfem_export.h.
Examples of use can be found in the examples of the tests directory.
GetFEM provides “slicers” objects which are dedicated to generating post-treatment data from meshes
and solutions. These slicers, defined in the file getfem/getfem_mesh_slicers.h take a mesh
(and sometimes a mesh_fem with a solution field) on input, and produce a set of simplices after ap-
plying some operations such as intersection with a plane, extraction of the mesh boundary, refine-
ment of each convex, extraction of isosurfaces, etc. The output of these slicers can be stored in a
getfem::stored_mesh_slice object (see the file getfem/getfem_mesh_slice.h). A
stored_mesh_slice object may be considered as a P1 discontinuous FEM on a non-conformal mesh
with fast interpolation ability. Slices are made of segments, triangles and tetrahedrons, so the convexes
of the original mesh are always simplexified.
All slicer operation inherit from getfem::slicer_action, it is very easy to create a new slicer.
Example of slicers are (some of them use a getfem::mesh_slice_cv_dof_data_base which
is just a reference to a mesh_fem mf and a field U on this mesh_fem).
getfem::slicer_none()
empty slicer.
getfem::slicer_boundary(const mesh &m, ldots)
extract the boundary of a mesh.
getfem::slicer_apply_deformation(mesh_slice_cv_dof_data_base&)
apply a deformation to the mesh , the deformation field is defined on a mesh_fem.
getfem::slicer_half_space(base_node x0, base_node n, int orient)
cut the mesh with a half space (if orient = -1 or +1), or a plane (if orient = 0), x0 being a
node of the plane, and n being a normal of the plane.
getfem::slicer_sphere(base_node x0, scalar_type R, int orient)
cut with the interior (orient``=-1), boundary (``orient``=0) or exterior
(``orient``=+1) or a sphere of center ``x0 and radius R.
getfem::slicer_cylinder(base_node x0, base_node x1, scalar_type R, int orient)
slice with the interior/boundary/exterior of a cylinder of axis (x0,x1) and radius R.
getfem::slicer_isovalues(const mesh_slice_cv_dof_data_base &mfU, scalar_type
val, int orient)
cut with the isosurface defined by the scalar field mfU and val. Keep only simplices where
:𝑢(𝑥) < 𝑣𝑎𝑙 (orient``=-1), :math:`u(x)=val` (``orient=0 or 𝑢(𝑥) > 𝑣𝑎𝑙.
getfem::slicer_mesh_with_mesh(const mesh &m2)
cut the convexes with the convexes of the mesh m2.
getfem::slicer_union(const slicer_action &sA, const slicer_action &sB)
merges the output of two slicer operations.
getfem::slicer_intersect(slicer_action &sA, slicer_action &sB)
intersect the output of two slicer operations.
getfem::slicer_complementary(slicer_action &s)
return the complementary of a slicer operation.
getfem::slicer_build_edges_mesh(mesh &edges_m)
slicer whose side-effect is to build the mesh edges_m with the edges of the sliced mesh.
getfem::slicer_build_mesh(mesh &m)
in some (rare) occasions , it might be useful to build a mesh from a slice. Note however that there
is absolutely no guaranty that the mesh will be conformal (although it is often the case).
getfem::slicer_build_stored_mesh_slice(stored_mesh_slice &sl)
record the output of the slicing operation into a stored_mesh_slice object. Note that it is of-
ten more convenient to use the stored_mesh_slice::build(...) method to achieve the
same result.
getfem::slicer_explode(c)
shrink or expand each convex with respect to its gravity center.
In order to apply these slicers, a getfem::mesh_slicer(mesh&) ob-
ject should be created, and the getfem::slicer_action are then
stacked with mesh_slicer::push_back_action(slicer_action&) and
mesh_slicer::push_front_action(slicer_action&). The slicing operation is fi-
nally executed with mesh_slicer::exec(int nrefine) (or mesh_slicer::exec(int
nrefine, const mesh_region &cvlst) to apply the operation to a subset of the mesh, or its
boundary etc.).
The nrefine parameter is very important, as the “precision” of the final result will depend on it: if
the data that is represented on the final slice is just P1 data on convexes with a linear geometric trans-
formation, nrefine = 1 is the right choice, but for P2, P3, non linear transformation etc, it is better
to refine each convex of the original mesh during the slicing operation. This allows an accurate repre-
sentation of any finite element field onto a very simple structure (linear segment/triangles/tetrahedrons
with P1 discontinuous data on them) which is what most visualization programs (gmsh, mayavi, opendx,
scilab, octave, matlab, etc.) expect.
Example of use (cut the boundary of a mesh m with a half-space, and save the result into a
stored_mesh_slice):
getfem::slicer_boundary a0(m);
getfem::slicer_half_space a1(base_node(0,0), base_node(1, 0), -1);
getfem::stored_mesh_slice sl;
getfem::slicer_build_stored_mesh_slice a2(sl);
getfem::mesh_slicer slicer(m);
slicer.push_back_action(a1);
slicer.push_back_action(a2);
int nrefine = 3;
slicer.exec(nrefine);
getfem::stored_mesh_slice sl;
sl.build(m, getfem::slicer_boundary(m),
getfem::slicer_half_space(base_node(0,0), base_node(1, 0), -1),
nrefine);
The simplest way to use these slices is to export them to VTK, OpenDX, or Gmsh.
VTK/VTU files can handle data on segment, triangles, quadrangles, tetrahedrons and hexahedrons of
first or second degree.
For example, supposing that a stored_mesh_slice sl has already been built:
In this example, the fields P and U are interpolated on the slice nodes and then written into the VTK
field.
It is also possible to export a mesh_fem mfu without having to build a slice:
vtu_export exp("output.vtu);
exp.exporting(mfu); // will save the geometrical structure of the mesh_fem
exp.write_point_data(mfp, P, "pressure"); // write a scalar field
exp.write_point_data(mfu, U, "displacement"); // write a vector field
Note however that when exporing a mesh_fem with vtk_export or vtu_export each convex/fem
of mfu will be mapped to a VTK/VTU element type. As VTK/VTU does not handle elements of degree
greater than 2, there will be a loss of precision for higher degree FEMs.
The OpenDX data file is more versatile than the VTK one. It is able to store more that one mesh, any
number of fields on these meshes etc. However, it does only handle elements of degree 1 and 0 (seg-
ments, triangles, tetrahedrons, quadrangles etc.). And each mesh can only be made of one type of ele-
ment, it cannot mix triangles and quadrangles in a same object. For that reason, it is generally preferable
to export getfem::stored_mesh_slice objects (in which non simplex elements are simplexified,
and which allows refinement of elements) than getfem::mesh_fem and getfem::mesh objects.
The basic usage is very similar to getfem::vtk_export:
getfem::dx_export exp("output.dx");
exp.exporting(sl);
exp.write_point_data(mfu, U, "displacement");
Moreover, getfem::dx_export is able to reopen a ‘.dx’ file and append new data into it. Hence
it is possible, if many time-steps are to be saved, to view intermediate results in OpenDX during the
getfem::stored_mesh_slice sl;
getfem::dx_export exp("output.dx", false);
if (N <= 2) sl.build(mesh, getfem::slicer_none(),4);
else sl.build(mesh, getfem::slicer_boundary(mesh),4);
exp.exporting(sl,true);
while (t <= T) {
...
exp.write_point_data(mf_u, U0);
exp.serie_add_object("deformation");
exp.write_point_data(mf_vm, VM);
exp.serie_add_object("von_mises_stress");
}
In this example, an OpenDX “time series” is created, for each time step, two data fields are saved: a
vector field called “deformation”, and a scalar field called “von_mises_stress”.
Note also that the dx_export::exporting_mesh_edges() function has been called. It implies
that for each mesh exported, the edges of the original mesh are also exported (into another OpenDX
mesh). In this example, you have access in OpenDX to 4 data fields: “deformation”, “deforma-
tion_edges”, “von_mises_stress” and “von_mises_stress_edges”.
The tests/dynamic_friction.net is an example of OpenDX program for these data (run it
with cd tests; dx -edit dynamic_friction.net , menu “Execute/sequencer”).
𝜕𝑈
+ 𝑉 · ∇𝑈 = 0,
𝜕𝑡
on the time intervall [0, 𝑑𝑡].
The method used is of Galerkin-Characteristic kind. It is a very simple version which is inconditionnally
stable but rather dissipative. See [ZT1989] and also the Freefem++ documentation on convect command.
The defined method works only if mf is a pure Lagrange finite element method for the moment. The
principle is to convect backward the finite element nodes by solving the ordinary differential equation:
𝑑𝑋
= −𝑉 (𝑋),
𝑑𝑡
with an initial condition corresponding to each node. This convection is made with nt steps. Then the
solution is interploated on the convected nodes.
In order to make the extrapolation not too expensive, the product 𝑑𝑡 × 𝑉 should not be too large.
Note that this method can be used to solve convection dominant problems coupling it with a splitting
scheme.
101
User Documentation, Release 5.4.2
The model description of GetFEM allows to quickly build some fem applications on complex linear or
nonlinear PDE coupled models. The principle is to propose predefined bricks which can be assembled to
describe a complex situation. A brick can describe either an equation (Poisson equation, linear elasticity
. . . ) or a boundary condition (Dirichlet, Neumann . . . ) or any relation between two variables. Once
a brick is written, it is possible to use it in very different situations. This allows a reusability of the
produced code and the possibility of a growing library of bricks. An effort has been made in order to
facilitate as much as possible the definition of a new brick. A brick is mainly defined by its contribution
in the tangent linear system to be solved.
This model description is an evolution of the model bricks of previous versions of GetFEM. Compared
to the old system, it is more flexible, more general, allows the coupling of model (multiphysics) in a
easier way and facilitates the writing of new components. It also facilitate the write of time integration
schemes for evolving PDEs.
The kernel of the model description is contained in the file getfem/getfem_models.h. The two
main objects are the model and the brick.
The aim of the model object, defined in file getfem/getfem_models.h, is to globally describe a
PDE model. It mainly contains two lists: a list of variables (related or not to the mesh_fem objects) and
data (also related or not to the mesh_fem objects) and a list of bricks. The role of the model object is to
coordinate the module and make them produce a linear system of equations. If the model is linear, this
will simply be the linear system of equation on the corresponding dofs. If the model is nonlinear, this
will be the tangent linear system. There are two versions of the model object: a real one and complex
one.
The declaration of a model object is done by:
103
User Documentation, Release 5.4.2
The parameter of the constructor is a boolean which determines whether the model deals with complex
number or real numbers. The default is false for a model dealing with real numbers.
There are different kinds of variables/data in the model. The variables are the unknown of the model.
They will be (generally) computed by solving the (tangent) linear system built by the model. Generally,
the model will have several variables. Each variable has a certain size (number of degrees of freedom)
and the different variables are sorted in alphanumeric order to form the global unknown (𝑈 in Fig. The
(tangent) linear system). Each variable will be associated to an interval 𝐼 = [𝑛1 , 𝑛2 ] which will represent
the degrees of freedom indices corresponding to this variable in the global system. The model stores
also some data (in the same format as the variables). The difference between data and variables is that
data is not an unknown of the model. The value of the data should be provided. In some cases (nonlinear
models) some variables can be considered as some data for certain terms. Variables and data are of two
kinds. They can have a fixed size, or they can depend on a finite element method (be the d.o.f. of a finite
element method).
For instance, in the situation described in Fig. The (tangent) linear system, there are four variables in the
model, namely 𝑋, 𝑌, 𝑉 and 𝑊 . The role of the model object will be to assemble the linear system, i.e.
to fill the sub matrices corresponding to each variable (𝑅𝑋,𝑋 , 𝑅𝑌,𝑌 , 𝑅𝑉,𝑉 , and 𝑅𝑊,𝑊 ) and the coupling
terms between two variables (𝑅𝑋,𝑌 , 𝑅𝑋,𝑉 , 𝑅𝑊,𝑉 , · · ·). This different contributions will be given by the
different bricks added to the model.
The main useful methods on a model object are
getfem::model::is_complex()
A boolean which says if the model deals with real or complex unknowns and data.
104 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
model degrees of freedom by the number of integration points time the size of the variable at one
integration point.
getfem::model::add_internal_im_variable(name, imd)
Add a variable defined on the integration points of the im_data object imd that will be statically
condensed out during the linearization of the problem. The variable can be scalar-valued, vector-
valued or tensor-valued depending on the dimension of imd. It does not add degrees of freedom
to the model.
getfem::model::add_im_data(name, imd)
Add a data object deignated with the string name, defined at all integration points of the im_data
object imd. The data can be scalar-valued, vector-valued or tensor-valued depending on the di-
mension of imd.
getfem::model::real_variable(name, niter = 1)
Gives the access to the vector value of a variable or data. Real version.
getfem::model::complex_variable(name, niter = 1)
Gives the access to the vector value of a variable or data. Complex version.
getfem::model::mesh_fem_of_variable(name)
Gives a reference on the mesh_fem on which the variable is defined. Throw an exception if this is
not a fem variable.
getfem::model::real_tangent_matrix()
Gives the access to tangent matrix. Real version. A computation of the tangent system have to be
done first.
getfem::model::complex_tangent_matrix()
Gives the access to tangent matrix. Complex version. A computation of the tangent system have
to be done first.
getfem::model::real_rhs()
Gives the access to right hand side vector of the linear system. real version. A computation of the
tangent system have to be done first.
getfem::model::complex_rhs()
Gives the access to right hand side vector of the linear system. Complex version. A computation
of the tangent system have to be done first.
A model brick is an object that is supposed to represent a part of a model. It aims to represent some
integral terms in a weak formulation of a PDE model. The model object will contain a list of bricks.
All the terms described by the brick will be finally assembled to build the linear system to be solved
(the tangent linear system for a nonlinear problem). For instance if a term ∫︀ Δ𝑢 is present on the pde
model (Laplacian of 𝑢) then the weak formulation will contain the term Ω ∇𝑢 · ∇𝑣 𝑑𝑥, where 𝑣 is
∫︀the test function corresponding to 𝑢. Then the role of the corresponding brick is to assemble the term
Ω ∇𝜙𝑖 ·∇𝜙𝑗 𝑑𝑥, where 𝜙𝑖 and 𝜙𝑗 are the shape functions of the finite element method describing 𝑢. This
term will be added by the model object to the global linear system on a diagonal block corresponding to
the variable 𝑢. The only role of the brick is thus to call the corresponding assembly procedure when the
model object asks for it. The construction of a brick for such a linear term is thus very simple.
Basically, the brick object will derive from the object virtual_brick defined in getfem/
getfem_models.h and should redefine the method asm_real_tangent_terms or
106 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
Note first that the design of a new brick is only necessary for special terms not covered by existing bricks
and not covered by the wide range of accessible terms (including complex coupling terms) of the generic
assembly brick (see Generic assembly bricks).
According to the spirit in which the brick has been designed, a brick should avoid as much as possible
to store additional data. The parameters of a brick should be contained in the variable and data of
the model. For instance, the parameters of a linear elasticity brick are the elasticity coefficient. This
coefficients have to be some data of the model. When the brick is called by the model object, a list of
variables and data is given to the brick. The great majority of the predefined bricks do not store any data.
This allows to instantiate such a bricks only once.
An example of a brick corresponding to the laplacian term is the following (other examples can be found
in the file getfem_models.cc which contains the very standard bricks):
gmm::clear(matl[0]);
getfem::asm_stiffness_matrix_for_homogeneous_laplacian
(matl[0], mim, mf_u, region);
}
my_Laplacian_brick(void)
{ set_flags("My Laplacian brick", true /* linear */,
true /* symmetric */,
true /* coercivity */,
true /* real version defined */,
false /* no complex version*/);
}
};
The constructor of a brick should call the method set_flags. The first parameter of this method is a
name for the brick (this allows to list the bricks of a model and facilitate their identification). The other
GMM_ASSERT1(matl.size() == 1,
"My Laplacian brick has one and only one term");
GMM_ASSERT1(mims.size() == 1,
"My Laplacian brick need one and only one mesh_im");
GMM_ASSERT1(varl.size() == 1 && datal.size() == 0,
"Wrong number of variables for my Laplacian brick");
are not mandatory and just verify that the good number of terms (1), integration methods (1), vari-
ables(1), data(0) are passed to the asm_real_tangent_terms method.
The lines:
takes the mesh_fem object from the variable on which the Laplacian term will be added and the mesh_im
object in the list of integrations methods. Finally, the lines:
gmm::clear(matl[0]);
getfem::asm_stiffness_matrix_for_homogeneous_laplacian
(matl[0], mim, mf_u, region);
call a standard assembly procedure for the Laplacian term defined in the file getfem/
getfem_assembling.h. The clear method is necessary because although it is guaran-
108 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
teed that the matrices in matl have good sizes they maybe not cleared before the call of
asm_real_tangent_terms.
Note that this simple brick has only one term and is linear. In the case of a linear brick, either the matrix
or the right hand side vector have to be filled but not both the two. Depending on the declaration of the
term. See below the integration of the brick to the model.
Let us see now a second example of a simple brick which prescribes a Dirichlet condition thanks to the
use of a Lagrange multiplier. The Dirichlet condition is of the form
𝑢 = 𝑢𝐷 on Γ,
where 𝑢 is the variable, 𝑢𝐷 is a given value and Γ is a part on the boundary of the considered domain.
The weak terms corresponding to this condition prescribed with a Lagrange multiplier are
∫︁ ∫︁
𝑢𝜇 𝑑Γ = 𝑢𝐷 𝜇 𝑑Γ, ∀𝜇 ∈ 𝑀,
Γ Γ
where 𝑀 is an appropriate multiplier space. The contributions to the global linear system can be viewed
in Fig. Contributions of the simple Dirichlet brick. The matrix 𝐵 is the “mass matrix” between the finite
element space of the variable 𝑢 and the finite element space of the multiplier 𝜇. 𝐿𝑢 is the right hand side
corresponding to the data 𝑢𝐷 .
if (mf_data)
getfem::asm_source_term(vecl[0], mim, mf_mult, *mf_data, A, region);
else
getfem::asm_homogeneous_source_term(vecl[0], mim, mf_mult, A,
˓→region);
gmm::clear(matl[0]);
getfem::asm_mass_matrix(matl[0], mim, mf_mult, mf_u, region);
}
my_Dirichlet_brick(void)
{ set_flags("My Dirichlet brick", true /* linear */,
true /* symmetric */,
false /* coercivity */,
true /* real version defined */,
false /* no complex version */);
}
};
This brick has again only one term but defines both the matrix and the right hand side parts. Two
variables are concerned, the primal variable on which the Dirichlet condition is prescribed, and the
multiplier variable which should be defined on a mesh region corresponding to a boundary (it should
be added to the model with the method add_multiplier). The term of the brick will be declared
symmetric (see the next section).
The lines:
allow to have the access to the value of the data corresponding to the right hand side of the Dirichlet
condition and to the mesh_fem on which this data is defined. If the data is constant (not described on a
fem) then mf_data is a null pointer.
The lines:
if (mf_data)
getfem::asm_source_term(vecl[0], mim, mf_mult, *mf_data, A, region);
else
getfem::asm_homogeneous_source_term(vecl[0], mim, mf_mult, A, region);
make the assembly of the right hand side. The two versions correspond to a data defined on a finite
element method or constant size data.
( + some example with a nonlinear term . . . )
110 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
In order to add a brick to a model, a certain information have to be passed to the model:
• A pointer to the brick itself.
• The set of variable names concerned with the terms of the brick.
• The set of data names concerned with the terms of the brick.
• A list of terms description.
• A list of integration methods.
• Eventually the concerned mesh region.
This is done by the call of the model object method:
The method returns the index of the brick in the model. The call of this method is rather complex
because it can be adapted to many situations. The construction of a new brick should be accompagned
to the definition of a function that adds the new brick to the model calling this method and more simple
to use.
For instance, for the simple Laplacian brick described above, this function can be defined as folows:
This function will be called by the user of your brick. The type getfem::model::varnamelist
is a std::vector<std::string> and represent an array of variable names. The type
getfem::model::mimlist is a std::vector<const getfem::mesh_im *> and repre-
sent an array of pointers to integration methods. The type getfem::model::termlist is an array
of terms description. There is two kind of terms. The terms adding only a right hand side to the linear
(tangent) system which have to be added to the list by:
tl.push_back(getfem::model::term_description(varname));
and the terms having a contribution to the matrix of the linear system which have to be added to the list
by:
In this case, the matrix term is added in the rows corresponding to the variable varname1 and the
columns corresponding to the variable varname2. The boolean being the third parameter is to de-
clare whether the term is symmetric or not. If it is symmetric and if the two variables are different
then the assembly procedure adds the corresponding term AND its transpose. The number of terms
is arbitrary. For each term declared, the brick has to fill the corresponding right hand side vector (pa-
rameter vecl of asm_real_tangent_terms above) or/and the matrix term (parameter matl of
asm_real_tangent_terms) depending on the declaration of the term. Note that for nonlinear
bricks, both the matrix and the right hand side vectors have to be filled. For linear bricks, if the right
hand side is filled for a term declared to be a matrix term, it is IGNORED.
The variable names and the data names are given in two separate arrays because the dependence of the
brick is not the same in both cases. A linear term has to be recomputed if the value of a data is changed
but not if the value of a variable is changed.
The function allowing to add the simple Dirichlet brick described above can be defined as follows:
Again, here, the term is declared symmetric and then the matrix term and its transpose will be added.
A mean to add a term either on one variable or on several ones is to directly use GWFL, the generic weak
form language described in Section Compute arbitrary terms - high-level generic assembly procedures
- Generic Weak-Form Language (GWFL). The more general way is to use:
This adds a brick to the model md, using the integration method mim, the assembly string expr on the
mesh region region. If the result is symmetric, you can specify it on the 5th argument and if it is
coercive on the 6th argument. The latter indications of symmetry and coercivness are used to determine
the right linear solver. If you are not so sure, it is preferable not to indicate anything.
However, this brick consider that the expression is nonlinear. This brick is especially indicated to obtain
nonlinear coupled terms between several variables. This means in particular that the assembly of the
term is performed at each call of the assembly of the model and that a Newton algorithm will be used to
solve the problem. If the term is indeed linear, you should use instead:
112 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
with the same arguments. Conversely, this brick alway assume that the term corresponding to expr is
linear and the assembly will be performed only once if the data used do not change. Thus, you have to
care that your expression is indeed linear (affine in fact) with respect to each variable. Otherwise, the
result is of course not guaranted. Source terms in the expression are taken into account. Still for linear
problem, it is possible to perform the assembly of a sole source term thanks to:
with again the same arguments except the symmetry and coercivness. This brick performs the assembly
of the corresponding order 1 term (residual vector) and add it as a right hand side to the problem. The
assembly will be performed only once, so the term should not depend on the variables of the model (but
could depend of course on the constants).
For instance, if one wants to solve a Poisson problem on a predefined variable u of the model, one may
use the corresponding pre-defined bricks (see below) or simply use:
where F is a pre-defined constant of the model representing the right hand side. Of course, doing so,
Newton’s algorithms will be called. So, the more appropriate manner is to use the linear bricks as
follows:
Note that for the moment, the use of GWFL is not possible for complex valued problems.
This brick adds an elliptic term on a variable of a model. The shape of the elliptic term depends both on
the variable and a given coefficient. This corresponds to a term:
−div(𝑎∇𝑢),
where 𝑎 is the coefficient and 𝑢 the variable. The coefficient can be a scalar, a matrix or an order four
tensor. The variable can be vector valued or not. This means that the brick treats several different
situations. If the coefficient is a scalar or a matrix and the variable is vector valued then the term
is added componentwise. An order four tensor coefficient is allowed for vector valued variable only.
The coefficient can be constant or described on a FEM. Of course, when the coefficient is a tensor
described on a finite element method (a tensor field) the corresponding data can be a huge vector. The
components of the matrix/tensor have to be stored with the fortran order (columnwise) in the data vector
corresponding to the coefficient (compatibility with BLAS). The symmetry and coercivity of the given
matrix/tensor is not verified (but assumed).
This brick can be added to a model md thanks to two functions. The first one is:
that adds an elliptic term relatively to the variable varname of the model with a constant coefficient
equal to 1 (a Laplacian term). This corresponds to the Laplace operator. mim is the integration method
which will be used to compute the term. region is an optional region number. If it is omitted, it is
assumed that the term will be computed on the whole mesh. The result of the function is the brick index
in the model.
The second function is:
It adds a term with an arbitrary coefficient given by the expression dataexpr which has to be a regular
expression of GWFL, the generic weak form language (like “1”, “sin(X[0])” or “Norm(u)” for instance)
even depending on model variables (except for the complex version where it has to be a declared data of
the model)
Note that very general equations can be obtained with this brick. For instance, linear anisotropic elastic-
ity can be obtained with a tensor data. When an order four tensor is used, the corresponding weak term
is the following
∫︁ ∑︁
𝑎𝑖,𝑗,𝑘,𝑙 𝜕𝑖 𝑢𝑗 𝜕𝑘 𝑣𝑙 𝑑𝑥
Ω 𝑖,𝑗,𝑘,𝑙
where 𝑎𝑖,𝑗,𝑘,𝑙 is the order four tensor and 𝜕𝑖 𝑢𝑗 is the partial derivative with respect to the 𝑖𝑡ℎ variable of
the component 𝑗 of the unknown 𝑘. 𝑣 is the test function. However, for linear isotropic elasticity, a more
adapted brick is available (see below).
The brick has a working complex version.
The aim of the Dirichlet condition brick is to prescribe a Dirichlet condition on a part of the boundary
of the domain for a variable of the model. This means that the value of this variable is prescribed on
the boundary. There is three versions of this brick (see also the section Nitsche’s method for dirichlet
and contact boundary conditions). The first version prescribe the Dirichlet thank to a multiplier. The
associated weak form of the term is the following:
∫︁ ∫︁
𝑢𝜇𝑑Γ = 𝑢𝐷 𝜇𝑑Γ, ∀𝜇 ∈ 𝑀.
Γ Γ
where 𝑢 is the variable, 𝑀 is the space of multipliers, 𝑢𝐷 is the variable and Γ the Dirichlet boundary.
For this version, an additional variable have to be added to represent the multiplier. It can be done
directly to the model or thanks to the functions below. There are three functions allowing to add a
Dirichlet condition prescribed with a multiplier. The first one is:
adding a Dirichlet condition on varname thanks to a multiplier variable multname on the mesh region
region (which should be a boundary). The value of the variable on that boundary is described by the
data dataname which should be previously defined in the model. If the data is omitted, the Dirichlet
condition is assumed to be an homogeneous one (vanishing variable on the boundary). The data can be
constant or described on an FEM. It can also be scalar or vector valued, depending on the variable. The
variable multname should be added to the model by the method add_multiplier. The function
returns the brick index in the model. The second function is:
114 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
The only difference is that multname is replaced by mf_mult which means that only the finite element
on which the multiplier will be built is given. The function adds itself the multiplier variable to the
model. The third function is very similar:
The parameter mf_mult is replaced by an integer degree indicating that the multiplier will be built
on a classical finite element method of that degree.
Note, that in all the cases, when a variable is added by the method add_multiplier of the model
object, the mesh_fem will be filtered (thank to a partial_mesh_fem_object in order to retain
only the degrees of freedom having a non vanishing contribution on the considered boundary.
Finally, the variable name of the multiplier can be obtained thank to the function:
mult_varname_Dirichlet(md, ind_brick);
where ind_brick is the brick index in the model. This function has an undefined behavior if it applied
to another kind of brick.
The second version of the Dirichlet condition brick is the one with penalization. The function allowing
to add this brick is:
The penalization consists in computing the mass matrix of the variable and add it multiplied by the penal-
ization coefficient to the stiffness matrix. The parameter mf_mult (a pointer to a getfem::mesh_fem
object) is optional. It allows to weaken the Dirichlet condition for locking situations. In that case, the
penalization matrix is of the form 𝐵 𝑇 𝐵 where 𝐵 is the “mass matrix” on the boundary between the
shape functions of the variable varname and the shape function of the multiplier space. The penalization
coefficient is added as a data of the model and can be changed thanks to the function:
The third version of the Dirichlet condition brick use a simplification of the linear system (tangent linear
system for nonlinear problems). Basically, it enforces a 1 on the diagonal components of the lines
corresponding to prescribed degrees of freedom, it completes the lines with some zeros (for symmetric
problems, it also complete the columns with some zeros) and it adapts the right-hand side accordingly.
This is a rather simple and economic way to prescribe a Dirichlet condition. However, it can only be
applied when one can identify the degrees of freedom prescribed by the the Dirichlet condition. So, it
has to be use with care with reduced finite element methods, Hermite element methods and cannot be
applied for a normal (or generalized) Dirichlet condition on vectorial problems. The function allowing
to add this brick is:
The generalized Dirichlet condition is a boundary condition of a vector field u of the type
𝐻𝑢 = 𝑟
where 𝐻 is a matrix field. The functions adding the corresponding bricks are similar to the ones of the
standard Dirichlet condition except that they need the supplementary parameter Hname which gives the
name of the data corresponding to 𝐻. This data can be a matrix field described on a scalar fem or a
constant matrix.
The pointwise constraints brick is a Dirichlet condition like brick which allows to prescribe the value of
an unknown on given points of the domain. These points are not necessarily some vertex of the mesh or
some points corresponding to degrees of freedom of the finite element method on which the unknown is
described.
For scalar field variables, given a set of 𝑁𝑝 points 𝑥𝑖 , 𝑖 = 1 · · · 𝑁𝑝 , the brick allows to prescribe the
value of the variable on these points, i.e. to enforce the condition
𝑢(𝑥𝑖 ) = 𝑙𝑖 , 𝑖 = 1 · · · 𝑁𝑝 ,
where 𝑢 is the scalar field and 𝑙𝑖 the value to be prescribed on the point 𝑥𝑖 .
For vector field variables, given a set of 𝑁𝑝 points 𝑥𝑖 , 𝑖 = 1 · · · 𝑁𝑝 , the brick allows to prescribe the
value of one component of the variable on these points, i.e. to enforce the condition
𝑢(𝑥𝑖 ) · 𝑛𝑖 = 𝑙𝑖 , 𝑖 = 1 · · · 𝑁𝑝 ,
116 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
where 𝑛𝑖 is the vector such that 𝑢(𝑥𝑖 ) · 𝑛𝑖 represent the component to be prescribed.
The brick has two versions: a penalized version and a version with multipliers. The call is the following:
respectively for the penalized version, the one with a given multiplier fixed size variable and the one
which automatically adds a multiplier variable of the right size to the model. The data dataname_pt,
dataname_unitv and dataname_val should be added first to the model. dataname_pt should be a vector
containing the coordinates of the points where to prescribed the value of the variable varname. It is
thus of size 𝑁 𝑁𝑝 where 𝑁 is the dimension of the mesh. dataname_unitv is ignored for a scalar field
variable. For a vector field variable, it should contain the vector 𝑛𝑖 . In that case, it size should be 𝑄𝑁𝑝
where 𝑄 is the dimension of the vector field. dataname_val is optional and represent the right hand side,
it should contain the components 𝑙𝑖 . The default value for 𝑙𝑖 is 0.
This brick is mainly designed to prescribe the rigid displacements for pure Neumann problems.
This brick adds a source term, i.e. a term which occurs only in the right hand side of the linear (tangent)
system build by the model. If 𝑓 denotes the value of the source term, the weak form of such a term is
∫︁
𝑓 𝑣 𝑑𝑥
Ω
where 𝑣 is the test function. The value 𝑓 can be constant or described on a finite element method.
It can also represent a Neumann condition if it is applied on a boundary of the domain.
The function to add a source term to a model is:
add_source_term_brick(md, mim,
varname, dataexpr, region = -1,
directdataname = std::string());
where md``is the model object, ``mim is the integration method, varname is the variable
of the model for which the source term is added, dataexpr has to be a regular expression of GWFL,
the generic weak form language (except for the complex version where it has to be a declared data
of the model). It has to be scalar or vector valued depending on the fact that the variable is scalar or
vector valued itself. region is a mesh region on which the term is added. If the region corresponds
to a boundary, the source term will represent a Neumann condition. directdataname is an optional
additional data which will directly be added to the right hand side without assembly.
The brick has a working complex version.
A slightly different brick, especially dedicated to deal with a Neumann condition, is added by the fol-
lowing function:
add_normal_source_term_brick(md, mim,
varname, dataexpr, region);
The difference compared to the basic source term brick is that the data should be a vector field (a matrix
field if the variable varname is itself vector valued) and a scalar product with the outward unit normal
is performed on it.
Although it will be more convenient to build a specific solver for some problems, a generic solver is
available to test your models quickly. It can also be taken as an example to build your own solver. It is
defined in src/getfem/getfem_model_solvers.h and src/getfem_model_solvers.
cc and the call is:
getfem::standard_solve(md, iter);
where md is the model object and iter is an iteration object from Gmm++. See also the next section
for an example of use.
Note that SuperLU is used as a default linear solver on “small” problems. You can also link MUMPS with
GetFEM (see section Linear algebra procedures) and use the parallel version. For nonlinear problems,
A Newton method (also called Newton-Raphson method) is used.
Note also that it is possible to disable some variables (with the method md.disable_variable(varname) of
the model object) in order to solve the problem only with respect to a subset of variables (the disabled
variables are the considered as data) for instance to replace the global Newton strategy with a fixed point
one.
Let us recall that a standard initialization for the iter object is the folowwing (see Gmm++ documentation
on gmm-iter):
where 1E-7 is the relative tolerance for the stopping criterion, 1 is the noisy option and 200 is the
maximum number of iterations. The stopping criterion of Newton’s method is build as follows. For a
relative tolerance 𝜀, the algorithm stops when:
where 𝐹 (𝑢) is the residual vector, ‖ · ‖1 is the classical 1-norm in IRn , ℎ is the search direction given
by Newton’s algorithm, 𝐿 is the norm of an estimated external loads (coming from source term and
Dirichlet bricks) and 𝑢 is the current state of the searched variable. The maximum taken with 10−25 is
to avoid pathological cases when 𝐿 and/or 𝑢 are vanishing.
118 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
int main(void) {
// Model object
getfem::model laplacian_model;
// Laplacian term on u.
getfem::add_Laplacian_brick(laplacian_model, mim, "u");
// Neumann condition.
gmm::resize(F, mf_rhs.nb_dof()*N);
getfem::interpolation_function(mf_rhs, F, sol_grad);
laplacian_model.add_initialized_fem_data("NeumannData", mf_rhs, F);
getfem::add_normal_source_term_brick
(laplacian_model, mim, "u", "NeumannData", NEUMANN_BOUNDARY_NUM);
// Dirichlet condition.
gmm::resize(F, mf_rhs.nb_dof());
getfem::interpolation_function(mf_rhs, F, sol_u);
laplacian_model.add_initialized_fem_data("DirichletData", mf_rhs, F);
getfem::add_Dirichlet_condition_with_multipliers
(laplacian_model, mim, "u", mf_u, DIRICHLET_BOUNDARY_NUM, "DirichletData
˓→");
std::vector<scalar_type> U(mf_u.nb_dof());
(continues on next page)
return 0;
}
GetFEM provides a generic implementation of Nitche’s method which allows to account for Dirichlet
type or contact with friction boundary conditions in a weak sense without the use of Lagrange multipli-
ers. The method is very attractive because it transforms a Dirichlet boundary condition into a weak term
similar to a Neumann boundary condition. However, this advantage is at the cost that the implemen-
tation of Nitche’s method is model dependent, since it requires an approximation of the corresponding
Neumann term. In order to add a boundary condition with Nitsche’s method on a variable of a model,
the corresponding brick needs to have access to an approximation of the Neumann term of all partial
differential terms applied to this variable. In the following, considering a variable 𝑢, we will denote by
the sum of all Neumann terms on this variable. Note that the Neumann term 𝐺 will often depend on
the variable 𝑢 but it may also depend on other variables of the model. This is the case for instance for
mixed formulations of incompressible elasticity. The Neumann terms depend also frequently on some
parameters of the model (elasticity coefficients . . . ) but this is assumed to be contained in its expression.
For instance, if there is a Laplace term (Δ𝑢), applied on the variable 𝑢, the Neumann term will be 𝐺 =
𝜕𝑢
where 𝑛 is the outward unit normal on the considered boundary. If 𝑢 represents the displacements of
𝜕𝑛
a deformable body, the Neumann term will be 𝐺 = 𝜎(𝑢)𝑛, where 𝜎(𝑢) is the stress tensor depending on
the constitutive law. Of course, in that case 𝐺 also depends on some material parameters. If additionally
a mixed incompressibility brick is added with a variable 𝑝 denoting the pressure, the Neumann term on
𝑢 will depend on 𝑝 in the following way: 𝐺 = 𝜎(𝑢)𝑛 − 𝑝𝑛
In order to allow a generic implementation in which the brick imposing Nitsche’s method will work for
every partial differential term applied to the concerned variables, each brick adding a partial differential
term to a model is required to give its expression via a GWFL (generic weak form language) expression.
These expressions are utilized in a special method of the model object:
which allows to automatically derive an expression for the sum of all Neumann terms, by scanning the
expressions provided by all partial differential term bricks and performing appropriate manipulations. Of
course it is required that all volumic bricks were added to the model prior to the call of this method. The
derivation of the Neumann term works only for second order partial differential equations. A generic
implementation for higher order pde would be more complicated.
120 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
Assume that the variable 𝑢 is considered and that one wants to prescribe the condition
𝐻𝑢 = 𝑔
on a part Γ𝐷 of the boundary of the considered domain. Here 𝐻 is considered equal to one in the scalar
case or can be either the identity matrix in the vectorial case either a singular matrix having only 1 or 0
as eigenvalues. This allow here to prescribe only the normal or tangent component of 𝑢. For instance if
one wants to prescribe only the normal component, 𝐻 will be chosen to be equal to 𝑛𝑛𝑇 where 𝑛 is the
outward unit normal on Γ𝐷 .
Nitsche’s method for prescribing this Dirichlet condition consists in adding the following term to the
weak formulation of the problem
∫︁
1
(𝐻𝑢 − 𝑔 − 𝛾𝐻𝐺).(𝐻𝑣) − 𝜃(𝐻𝑢 − 𝑔).(𝐻𝐷𝑢 𝐺[𝑣])𝑑Γ,
Γ𝐷 𝛾
where 𝛾 and 𝜃 are two parameters of Nitsche’s method and 𝑣 is the test function corresponding to 𝑢. The
parameter 𝜃 can be chosen positive or negative. 𝜃 = 1 corresponds to the more standard method which
leads to a symmetric tangent term in standard situations, 𝜃 = 0 corresponds to a non-symmetric method
which has the advantage of a reduced number of terms and not requiring the second derivatives of 𝐺
in the nonlinear case, and 𝜃 = −1 is a kind of skew-symmetric method which ensures an inconditonal
coercivity (which means independent of 𝛾) at least in standard situations. The parameter 𝛾 is a kind of
penalization parameter (although the method is consistent) which is taken to be 𝛾 = 𝛾0 ℎ𝑇 where 𝛾0 is
taken uniform on the mesh and ℎ𝑇 is the diameter of the element 𝑇 . Note that, in standard situations,
except for 𝜃 = −1 the parameter 𝛾0 has to be taken sufficiently small in order to ensure the convergence
of Nitsche’s method.
The bricks adding a Dirichlet condition with Nitsche’s method to a model are the following:
getfem::add_Dirichlet_condition_with_Nitsche_method
(model &md, const mesh_im &mim, const std::string &varname,
const std::string &Neumannterm,
const std::string &gamma0name, size_type region,
scalar_type theta = scalar_type(1),
const std::string &dataname = std::string());
This function adds a Dirichlet condition on the variable varname and the mesh region region.
This region should be a boundary. Neumannterm is the expression of the Neumann term (ob-
tained by the Green formula) described as an expression of GWFL. This term can be obtained with
md.Neumann_term(varname, region) once all volumic bricks have been added to the model. The Dirich-
let condition is prescribed with Nitsche’s method. dataname is the optional right hand side of the Dirich-
let condition. It could be constant or described on a fem; scalar or vector valued, depending on the
variable on which the Dirichlet condition is prescribed. gamma0name is the Nitsche’s method param-
eter. theta is a scalar value which can be positive or negative. theta = 1 corresponds to the standard
symmetric method which is conditionally coercive for gamma0 small. theta = -1 corresponds to the
skew-symmetric method which is inconditionally coercive. theta = 0 is the simplest method for which
the second derivative of the Neumann term is not necessary even for nonlinear problems. Returns the
brick index in the model.
getfem::add_normal_Dirichlet_condition_with_Nitsche_method
(model &md, const mesh_im &mim, const std::string &varname,
const std::string &Neumannterm,
(continues on next page)
23.13. Nitsche’s method for dirichlet and contact boundary conditions 121
User Documentation, Release 5.4.2
This function adds a Dirichlet condition to the normal component of the vector (or tensor) valued variable
varname and the mesh region region. This region should be a boundary. Neumannterm is the expression
of the Neumann term (obtained by the Green formula) described as an expression of GWFL. This term
can be obtained with md.Neumann_term(varname, region) once all volumic bricks have been added
to the model. The Dirichlet condition is prescribed with Nitsche’s method. dataname is the optional
right hand side of the Dirichlet condition. It could be constant or described on a fem. gamma0name
is the Nitsche’s method parameter. theta is a scalar value which can be positive or negative. theta =
1 corresponds to the standard symmetric method which is conditionally coercive for gamma0 small.
theta = -1 corresponds to the skew-symmetric method which is inconditionally coercive. theta = 0 is
the simplest method for which the second derivative of the Neumann term is not necessary even for
nonlinear problems. Returns the brick index in the model. (This brick is not fully tested)
getfem::add_generalized_Dirichlet_condition_with_Nitsche_method
(model &md, const mesh_im &mim, const std::string &varname,
const std::string &Neumannterm,
const std::string &gamma0name, size_type region, scalar_type theta,
const std::string &dataname, const std::string &Hname);
This function adds a Dirichlet condition on the variable varname and the mesh region region. This
version is for vector field. It prescribes a condition 𝐻𝑢 = 𝑟 where 𝐻 is a matrix field. The region
should be a boundary. This region should be a boundary. Neumannterm is the expression of the Neumann
term (obtained by the Green formula) described as an expression of GWFL. This term can be obtained
with md.Neumann_term(varname, region) once all volumic bricks have been added to the model. The
Dirichlet condition is prescribed with Nitsche’s method. CAUTION : the matrix H should have all
eigenvalues equal to 1 or 0. dataname is the optional right hand side of the Dirichlet condition. It could
be constant or described on a fem. gamma0name is the Nitsche’s method parameter. theta is a scalar
value which can be positive or negative. theta = 1 corresponds to the standard symmetric method which
is conditionally coercive for gamma0 small. theta = -1 corresponds to the skew-symmetric method
which is inconditionally coercive. theta = 0 is the simplest method for which the second derivative of
the Neumann term is not necessary even for nonlinear problems. Hname is the data corresponding to
the matrix field H. It has to be a constant matrix or described on a scalar fem. Returns the brick index in
the model. (This brick is not fully tested)
We describe here the use of Nitsche’s method to prescribe a contact with Coulomb friction condition
in the small deformations framework. This corresponds to a weak integral contact condition which as
some similarity with the ones which use Lagrange multipliers describe in the corresponding section, see
Weak integral contact condition
In order to simplify notations, let use denote by 𝑃𝑛,F the following map which corresponds to a couple
of projections:
This application make the projection of the normal part of 𝑥 on IR− and the tangential part on the ball
of center 0 and radius F (𝑥.𝑛)− , where F is the friction coefficient.
122 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
Using this, and considering that the sliding velocity is approximated by 𝛼(𝑢𝑇 −𝑤𝑇 ) where the expression
of 𝛼 and 𝑤𝑇 depend on the time integration scheme used (see Weak integral contact condition), Nitsche’s
term for contact with friction reads as:
∫︁
− 𝜃𝛾𝐺 · 𝐷𝑢 𝐺[𝑣]𝑑Γ
Γ𝐶
∫︁
𝐴𝑢 𝑔𝑎𝑝 𝛼𝑤𝑇 𝑣
+ 𝛾𝑃𝑛,F (𝐺 − + 𝑛+ ) · (𝜃𝐷𝑢 𝐺[𝑣] − )𝑑Γ.
Γ𝐶 𝛾 𝛾 𝛾 𝛾
where Γ𝐶 is the contact boundary, 𝐺 is the Neumann term which represents here 𝜎𝑛 the stress at the
contact boundary and 𝐴 is the 𝑑 × 𝑑 matrix
𝐴 = 𝛼𝐼𝑑 + (1 − 𝛼)𝑛𝑛𝑇
getfem::add_Nitsche_contact_with_rigid_obstacle_brick
(model &md, const mesh_im &mim, const std::string &varname_u,
const std::string &Neumannterm,
const std::string &expr_obs, const std::string &dataname_gamma0,
scalar_type theta_,
std::string dataexpr_friction_coeff,
const std::string &dataname_alpha,
const std::string &dataname_wt,
size_type region);
The constraint brick allows to add an explicit constraint on a variable. Explicit means that no integration
is done. if 𝑈 is a variable then a constraint of the type
𝐵𝑈 = 𝐿,
In the second case, a (fixed size) variable which will serve as a multiplier should be first added to the
model.
For the penalized version B should not contain a plain row, otherwise the whole tangent matrix will be
plain. The penalization parameter can be changed thanks to the function:
It is possible to change the constraints at any time thanks to the two following functions:
getfem::set_private_data_matrix(md, indbrick, B)
getfem::set_private_data_rhs(md, indbrick, L)
Two (very simple) bricks allow to add some explicit terms to the tangent system.
The function:
adds a brick which just adds the matrix B to the tangent system relatively to the variables varname1
and varname2. The given matrix should have as many rows as the dimension of varname1 and as
many columns as the dimension of varname2. If the two variables are different and if issymmetric
is set to true then the transpose of the matrix is also added to the tangent system (default is false). Set
iscoercive to true if the term does not affect the coercivity of the tangent system (default is false).
The matrix can be changed by the command:
The function:
adds a brick which just add the vector L to the right hand side of the tangent system relatively to the
variable varname. The given vector should have the same size as the variable varname. The value of
the vector can by changed by the command:
Δ𝑢 + 𝑘 2 𝑢 = . . .
where 𝑘 the wave number is a real or complex value. For a complex version, a complex model has to be
used (see tests/helmholtz.cc).
124 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
where varname is the variable on which the Helmholtz term is added and dataexpr is the wave
number.
This brick can be used to add boundary conditions of Fourier-Robin type like:
𝜕𝑢
= 𝑄𝑢
𝜕𝜈
for scalar problems, or
𝜎 · 𝜈 = 𝑄𝑢
for linearized elasticity problems. Q is a scalar field in the scalar case or a matrix field in the vectorial
case. This brick works for both real or complex terms in scalar or vectorial problems.
The function adding this brick to a model is:
add_Fourier_Robin_brick(md, mim, varname, dataexpr, region);
where dataexpr is the data of the model which represents the coefficient 𝑄. It can be an arbitrary
valid expression of GWFL, the generic weak form language (except for the complex version for which
it should be a data of the model)
Note that an additional right hand side can be added with a source term brick.
−𝑑𝑖𝑣(𝜎) = . . .
with
𝜎 = 𝜆tr(𝜀(𝑢))𝐼 + 2𝜇𝜀(𝑢)
𝜀(𝑢) = (∇𝑢 + ∇𝑢𝑇 )/2
𝜀(𝑢) is the small strain tensor, 𝜎 is the stress tensor, 𝜆 and 𝜇 are the Lamé coefficients. This represents
the system of linearized isotropic elasticity. It can also be used with 𝜆 = 0 together with the linear
incompressible brick to build the Stokes problem.
Let us recall that the relation between the Lamé coefficients an Young modulus 𝐸 and Poisson ratio 𝜈 is
𝐸𝜈 𝐸
𝜆= , 𝜇= ,
(1 + 𝜈)(1 − 2𝜈) 2(1 + 𝜈)
except for the plane stress approximation (2D model) where
𝐸𝜈 𝐸
𝜆* = 2
, 𝜇= ,
(1 − 𝜈 ) 2(1 + 𝜈)
The function which adds this brick to a model and parametrized with the Lamé coefficients is:
ind_brick = getfem::add_isotropic_linearized_elasticity_brick
(md, mim, varname, data_lambda, data_mu,
region = size_type(-1));
where dataname_lambda and dataname_mu are the data of the model representing the Lamé
coefficients.
The function which adds this brick to a model and parametrized with Young modulus and Poisson ratio
is:
ind_brick = getfem::add_isotropic_linearized_elasticity_pstrain_brick
(md, mim, varname, data_E, data_nu, region = size_type(-1));
This brick represent a plane strain approximation when it is applied to a 2D mesh (and a standard model
on a 3D mesh). In order to obtain a plane stress approximation for 2D meshes, one can use:
ind_brick = getfem::add_isotropic_linearized_elasticity_pstress_brick
(md, mim, varname, data_E, data_nu, region = size_type(-1));
For 3D meshes, the two previous bricks give the same result.
The function:
getfem::compute_isotropic_linearized_Von_Mises_or_Tresca
(md, varname, dataname_lambda, dataname_mu, mf_vm, VM, tresca_flag =
˓→false);
compute the Von Mises criterion (or Tresca if tresca_flag is set to true) on the displacement field
stored in varname. The stress is evaluated on the mesh_fem mf_vm and stored in the vector VM. It is
not valid for 2D plane stress approximation and is parametrized with Lamé coefficients. The functions:
getfem::compute_isotropic_linearized_Von_Mises
(md, varname, data_E, data_nu, mf_vm, VM);
getfem::compute_isotropic_linearized_Von_Mises
(md, varname, data_E, data_nu, mf_vm, VM);
compute the Von Mises stress, parametrized with Young modulus and Poisson ratio, the second one
being valid for 2D plane stress approximation when it is applied on a 2D mesh (the two functions give
the same result for 3D problems).
The program tests/elastostatic.cc can be taken as a model of use of a linearized isotropic
elasticity brick.
This brick adds a linear incompressibility condition (or a nearly incompressible condition) in a problem
of type:
This constraint is enforced with Lagrange multipliers representing the pressure, introduced in a mixed
formulation.
The function adding this incompressibility condition is:
126 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
ind_brick = getfem::add_linear_incompressibility
(md, mim, varname, multname_pressure, region = size_type(-1),
dataexpr_penal_coeff = std::string());
getfem::model Stokes_model;
laplacian_model.add_fem_variable("u", mf_u);
getfem::scalar_type mu = 1.0;
Stokes_model.add_initialized_data("lambda", plain_vector(1, 0.0));
Stokes_model.add_initialized_data("mu", plain_vector(1, mu));
getfem::add_isotropic_linearized_elasticity_brick(Stokes_model, mim,
"u", "lambda", "mu");
laplacian_model.add_fem_variable("p", mf_p);
getfem::add_linear_incompressibility(Stokes_model, mim, "u", "p");
plain_vector F(mf_data.nb_dof()*N);
for (int i = 0; i < mf_data.nb_dof()*N; ++i) F(i) = ...;
Stokes_model.add_initialized_fem_data("VolumicData", mf_data, F);
getfem::add_source_term_brick(Stokes_model, mim, "u", "VolumicData");
getfem::add_Dirichlet_condition_with_multipliers(Stokes_model, mim,
"u", mf_u, 1);
plain_vector U(mf_u.nb_dof());
gmm::copy(Stokes_model.real_variable("u"), U);
An example for a nearly incompressibility condition can be found in the program tests/
elastostatic.cc.
It mainly represents a mass term for transient problems but can also be used for other applications (it
can be used on a boundary). Basically, this brick adds a mass matrix on the tangent linear system with
respect to a certain variable.
The function which adds this brick to a model is:
ind_brick = getfem::add_mass_brick
(md, mim, varname, dataexpr_rho="", region = size_type(-1));
where dataexpr_rho is an optional expression representing the density 𝜌. If it is omitted, the density
is assumed to be equal to one.
adds a bilaplacian brick on the variable varname and on the mesh region region. This represent a term
Δ(𝐷Δ𝑢). where 𝐷(𝑥) is a coefficient determined
∫︀ by dataname which could be constant or described
on a f.e.m. The corresponding weak form is 𝐷(𝑥)Δ𝑢(𝑥)Δ𝑣(𝑥)𝑑𝑥.
For the Kirchhoff-Love plate model, the weak form is a bit different (and more stable than the previous
one). the function to add that term is
It adds a bilaplacian brick on the variable varname and on the mesh region region. This represent a term
Δ(𝐷Δ𝑢) where 𝐷(𝑥) is a the flexion modulus determined by dataname1. The term is integrated by
part following a Kirchhoff-Love plate model with dataname2 the poisson ratio.
There is specific bricks to add appropriate boundary conditions for fourth order partial differential equa-
tions. The first one is
which adds a Neumann term brick for Kirchhoff-Love model on the variable varname and the mesh
region region. dataname1 represents the bending moment tensor and dataname2 its divergence.
And a Dirichlet condition on the normal derivative can be prescribed thanks to the following bricks
128 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
ind = add_normal_derivative_Dirichlet_condition_with_multipliers
(md, mim, varname, multname, region, dataname = std::string(),
R_must_be_derivated = false);
ind = add_normal_derivative_Dirichlet_condition_with_multipliers
(md, mim, varname, mf_mult, region, dataname = std::string(),
R_must_be_derivated = false);
ind = add_normal_derivative_Dirichlet_condition_with_multipliers
(md, mim, varname, degree, region, dataname = std::string(),
R_must_be_derivated = false);
These bricks add a Dirichlet condition on the normal derivative of the∫︀ variable varname ∫︀ and on the
mesh region region (which should be a boundary). The general form is 𝜕𝑛 𝑢(𝑥)𝑣(𝑥) = 𝑟(𝑥)𝑣(𝑥)∀𝑣
where 𝑟(𝑥) is the right hand side for the Dirichlet condition (0 for homogeneous conditions) and 𝑣 is in
a space of multipliers defined by the variable multname (first version) or defined on the finite element
method mf_mult (second version) or simply on a Lagrange finite element method of degree degree
(third version) on the part of boundary determined by region. dataname is an optional parameter which
represents the right hand side of the Dirichlet condition. If R_must_be_derivated is set to true then the
normal derivative of dataname is considered.
The test program bilaplacian.cc is a good example of the use of the previous bricks.
This brick implements the classical Mindlin-Reissner bending model for isotropic plates.
𝑓 being a volumic force applied inside the three dimensional plate, 𝑔 + and 𝑔 − a force applied on the top
and bottom surface of the plate, 𝐸 Young’s modulus, 𝜈 Poisson’s ratio and 𝜅 the shear correction factor
(usually set to 5/6).
This strategy consists simply to use a lower order integration method to numerically compute the term
∫︁
𝐺𝜖(∇𝑢3 − 𝜃) · (∇𝑣3 − 𝜓)𝑑𝑥
Ω
This strategy is working properly at least when both the rotation and the transverse displacement is
approximated with Q1 quadrilateral element with a degree one reduced integration method (the so-called
QUAD4 element).
Another strategy comes from the MITC elements (Mixed Interpolation of Tensorial Components) which
correspond to a re-interpretation in terms of projection of some mixed methods. The most popular
element of this type is the MITC4 which correspond to the quadrilateral element Q1 with a projection of
the transverse shear term on a rotated Raviart-Thomas element of lowest degree (RT0) (see [ba-dv1985],
[br-ba-fo1989]). This means that the transverse shear term becomes
∫︁
𝐺𝜖𝑃 ℎ (∇𝑢3 − 𝜃) · 𝑃 ℎ (∇𝑣3 − 𝜓)𝑑𝑥
Ω
where 𝑃 ℎ (𝑇 ) is the elementwize 𝐿2 -projection onto the rotated RT0 space. For the moment, the only
projection implemented is the previous described one (projection on rotated RT0 space for quadrilat-
eral element). Higher degree elements and triangular elements can be found in the litterature (see
[Mi-Zh2002], [br-ba-fo1989], [Duan2014]) and will be under consideration for a future implementa-
tion. Note also that since 𝑃 ℎ (∇𝑢3 ) = ∇𝑢3 , the term reduces to
∫︁
𝐺𝜖(∇𝑢3 − 𝑃 ℎ (𝜃)) · (∇𝑣3 − 𝑃 ℎ (𝜓))𝑑𝑥
Ω
The principle of the definition of an elementary projection is explained if the description of GWFL, the
generic weak form language (see Elementary transformations) and an example can be found in the file
src/getfem_linearized_plates.cc.
130 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
size_type add_Mindlin_Reissner_plate_brick
(model, mim, mim_reduced, name_u3, name_theta, param_E,
param_nu, param_epsilon, param_kappa, variant = 2, region)
where name_u3 is name of the variable which represents the transverse displacmenent, name_theta
the variable which represents the rotation, param_E the Young Modulus, param_nu the poisson ratio,
param_epsilon the plate thickness, param_kappa the shear correction factor. Note that since this brick
uses GWFL, the parameter can be regular expression of this language. There are three variants. variant
= 0 corresponds to the an unreduced formulation and in that case only the integration method mim is
used. Practically this variant is not usable since it is subject to a strong locking phenomenon. variant =
1 corresponds to a reduced integration where mim is used for the rotation term and mim_reduced for the
transverse shear term. variant = 2 (default) corresponds to the projection onto a rotated RT0 element
of the transverse shear term. For the moment, this is adapted to quadrilateral only (because it is not
sufficient to remove the locking phenomenon on triangle elements). Note also that if you use high order
elements, the projection on RT0 will reduce the order of the approximation. Returns the brick index in
the model.
The projection on rotated RTO element can be added to a model thanks to the following function:
Although time integration scheme can be written directly using the model object by describing the
problem to be solved at each iteration, the model object furnishes some basic tools to facilitate the
writing of such schemes. These tools are based on the following basic principles:
• The original variables of the model represent the state of the system to be solved at the current
time step (say step n). This is the case even for a middle point scheme, mainly because if one
needs to apply different schemes to different variables of the system, all variable should describe
the system at a unique time step.
• Some data are added to the model to represent the state of the system at previous time steps.
For classical one-step schemes (for the moment, only one-step schemes are provided), only the
previous time step is stored. For instance if u is a variable (thus represented at step n), Previous_u,
Previous2_u, Previous3_u will be the data representing the state of the variable at the previous
time step (step n-1, n-2 and n-3).
• Some intermediate variables are added to the model to represent the time derivative (and the
second order time derivative for second order problem). For instance, if u is a variable, Dot_u
will represent the first order time derivative of u and Dot2_u the second order one. One can refer
to these variables in the model to add a brick on it or to use it in GWFL, the generic weak form
language. However, these are not considered to be independent variables, they will be linked to
their corresponding original variable (in an affine way) by the time integration scheme. Most of the
schemes need also the time derivative at the previous time step and add the data Previous_Dot_u
and possibly Previous_Dot2_u to the model.
• A different time integration scheme can be applied on each variable of the model. Note that most
of the time, multiplier variable and more generally variables for which no time derivative is used
do not need a time integration scheme.
• The data t represent the time parameter and can be used (either in GWFL or as parameter of some
bricks). Before the assembly of the system, the data t is automatically updated to the time step n.
23.23. The model tools for the integration of transient problems 131
User Documentation, Release 5.4.2
• The problem to be solved at each iteration correspond to the formulation of the transient problem
in its natural (weak) formulation in which the velocity and the acceleration are expressed by the
intermediate variables introduced. For instance, the translation into GWFL of the problem
˙ 𝑥) − Δ𝑢(𝑡, 𝑥) = sin(𝑡)
𝑢(𝑡,
(even though, of course, in this situation, the use of linear bricks is preferable for efficiency rea-
sons)
• For all implemented one-step schemes, the time step can be changed from an iteration to another
for both order one and order two in time problems (or even quasi-static problems).
• A scheme for second order in time problem (resp. first order in time) can be applied to a second or
first order in time or even to a quasi-static problem (resp. to a first order or quasi-static problem)
without any problem except that the initial data corresponding to the velocity/displacement have
to be initialized with respect ot the order of the scheme. Conversely, of course, a scheme for first
order problem cannot be applied to a second order in time problem.
𝑀 𝑈˙ = 𝐹 (𝑈 )
where 𝐹 (𝑈 ) might be nonlinear (and may depend on some other variables for coupled problems), for 𝑑𝑡
a time step, 𝑉 = 𝑈˙ and 𝑈 𝑛 , 𝑉 𝑛 the approximation of 𝑈, 𝑉 at time 𝑛𝑑𝑡, theta-method reads
{︂ 𝑛
𝑈 = 𝑈 𝑛−1 + 𝑑𝑡(𝜃𝑉 𝑛 + (1 − 𝜃)𝑉 𝑛−1 ),
𝑀 𝑉 𝑛 = 𝐹 (𝑈 𝑛 ),
for 𝜃 ∈ (0, 1] the parameter of the theta-method (for 𝜃 = 0, the method corresponds to the forward Euler
method and is not an implicit scheme) and for 𝑈 𝑛−1 , 𝑉 𝑛−1 given.
Before the first time step, 𝑈 0 should be initialized, however, 𝑉 0 is also needed (except for 𝜃 = 1).
In this example, it should correspond to 𝑀 −1 𝐹 (𝑈 0 ). For a general coupled problem where 𝑀 might
be singular, a generic precomputation of 𝑉 0 is difficult to obtain. Thus 𝑉 0 have to be furnisded also.
Alternatively (see below) the model object (and the standard solve) furnishes a mean to evaluate them
thanks to the application of a Backward Euler scheme on a (very) small time step.
The following formula can be deduced for the time derivative:
𝑈 𝑛 − 𝑈 𝑛−1 1 − 𝜃 𝑛−1
𝑉𝑛 = − 𝑉
𝜃𝑑𝑡 𝜃
When applying this scheme to a variable “u” of the model, the following affine dependent variable is
added to the model:
"Dot_u"
which represent the time derivative of the variable and can be used in some brick definition.
The following data are also added:
132 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
"Previous_u", "Previous_Dot_u"
which correspond to the values of “u” and “Dot_u” at the previous time step.
Before the solve, the data “Previous_u” (corresponding to 𝑈 0 in the example) has to be initialized (except
for 𝜃 = 1). Again, “Previous_Dot_u” has to be either initialized or pre-computed as described in the
next section. The affine dependence of “Dot_u” is thus given by:
Which means that “Dot_u” will be replaced at assembly time by its expression in term of “u” (multipied
by 1/(𝜃 *𝑑𝑡)) and in term of a constant remaining part depending on the previous time step. The addition
of this scheme to a variable is to be done thanks to:
Most of the time integration schemes (except, for instance, the backward Euler scheme) needs the pre-
computation of the first or second order time derivative before the initial time step (for instance 𝑉 0 for
the theta-method for first order problems, 𝐴0 for second order problems . . . ).
The choice is let to the user to either initialize these derivative or to ask to the model to automatically
approximate them.
The method used (for the moment) to approximate the supplementary derivatives may be explained in
the example of the solve of
𝑀 𝑈˙ = 𝐹 (𝑈 )
with a theta-method (see the previous section). In order to approximate 𝑉0 , the theta-method is applied
for 𝜃 = 1 (i.e. a backward Euler scheme) on a very small time step. This is possible since the backward
Euler do not need an initial time derivative. Then the time derivative computed thanks to the backward
Euler at the end of the very small time step is simply used as an approximation of the initial time
derivative.
For a model md, the following instructions:
model.perform_init_time_derivative(ddt);
standard_solve(model, iter);
allows to perform automatically the approximation of the initial time derivative. The parameter ddt
corresponds to the small time step used to perform the aproximation. Typically, ddt = dt/20 could be
used where dt is the time step used to approximate the transient problem (see the example below).
¨ = 𝐹 (𝑈 )
𝑀𝑈
23.23. The model tools for the integration of transient problems 133
User Documentation, Release 5.4.2
where 𝐹 (𝑈 ) might be nonlinear (and may depend on some othere variables for coupled problems), for
𝑑𝑡 a time step, 𝑉 = 𝑈˙ , 𝐴 = 𝑈
¨ and 𝑈 𝑛 , 𝑉 𝑛 , 𝐴𝑛 the approximation of 𝑈, 𝑉, 𝐴 at time 𝑛𝑑𝑡, the first oder
theta-method reads
⎧ 𝑛
⎨ 𝑈 = 𝑈 𝑛−1 + 𝑑𝑡(𝜃𝑉 𝑛 + (1 − 𝜃)𝑉 𝑛−1 ),
𝑉 𝑛 = 𝑉 𝑛−1 + 𝑑𝑡(𝜃𝐴𝑛 + (1 − 𝜃)𝐴𝑛−1 ),
𝑀 𝐴𝑛 = 𝐹 (𝑈 𝑛 ),
⎩
for 𝜃 ∈ (0, 1] the parameter of the theta-method (for 𝜃 = 0, the method correspond to the forward Euler
method and is not an implicit scheme) and for 𝑈 𝑛−1 , 𝑉 𝑛−1 , 𝐴𝑛−1 given.
At the first time step, 𝑈 0 , 𝑉 0 should be given and 𝐴0 is to be given or pre-computed (except for 𝜃 = 1).
The following formula can be deduced for the time derivative:
𝑈 𝑛 − 𝑈 𝑛−1 1 − 𝜃 𝑛−1
𝑉𝑛 = − 𝑉
𝜃𝑑𝑡 𝜃
𝑈 𝑛 − 𝑈 𝑛−1 1 1 − 𝜃 𝑛−1
𝐴𝑛 = − 2 𝑉 𝑛−1 − 𝐴
𝜃2 𝑑𝑡2 𝜃 𝑑𝑡 𝜃
When aplying this scheme to a variable “u” of the model, the following affine dependent variables are
added to the model:
"Dot_u", "Dot2_u"
which represent the first and second order time derivative of the variable and can be used in some brick
definition.
The following data are also added:
which correspond to the values of “u”, “Dot_u” and “Dot2_u” at the previous time step.
Before the solve, the data “Previous_u” and “Previous_Dot_u” (corresponding to 𝑈 0 in the example)
have to be initialized and “Previous_Dot2_u” should be either initialized or precomputed (see the previ-
ous section, and except for 𝜃 = 1). The affine dependences are thus given by:
¨ = 𝐹 (𝑈 )
𝑀𝑈
where 𝐹 (𝑈 ) might be nonlinear (and may depend on some othere variables for coupled problems), for
𝑑𝑡 a time step, 𝑉 = 𝑈˙ , 𝐴 = 𝑈
¨ and 𝑈 𝑛 , 𝑉 𝑛 , 𝐴𝑛 the approximation of 𝑈, 𝑉, 𝐴 at time 𝑛𝑑𝑡, the first oder
134 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
theta-method reads
⎧ 2
⎨ 𝑈 𝑛 = 𝑈 𝑛−1 + 𝑑𝑡𝑉 𝑛 + 𝑑𝑡2 (2𝛽𝑉 𝑛 + (1 − 2𝛽)𝑉 𝑛−1 ),
𝑉 𝑛 = 𝑉 𝑛−1 + 𝑑𝑡(𝛾𝐴𝑛 + (1 − 𝛾)𝐴𝑛−1 ),
𝑀 𝐴𝑛 = 𝐹 (𝑈 𝑛 ),
⎩
for 𝛽 ∈ (0, 1] and 𝛾 ∈ [1/2, 1] are the parameters of the Newmark scheme and for 𝑈 𝑛−1 , 𝑉 𝑛−1 , 𝐴𝑛−1
given.
At the first time step, 𝑈 0 , 𝑉 0 should be given and 𝐴0 is to be given or pre-computed (except for 𝛽 =
1/2, 𝛾 = 1).
The following formula can be deduced for the time derivative:
𝛾 𝛽 − 𝛾 𝑛−1 𝛾
𝑉𝑛 = (𝑈 𝑛 − 𝑈 𝑛−1 ) + 𝑉 + 𝑑𝑡(1 − )𝐴𝑛−1
𝛽𝑑𝑡 𝛽 2𝛽
𝑈 𝑛 − 𝑈 𝑛−1 1 𝑛−1
𝐴𝑛 = − 𝑉 − (1/2 − 𝛽)𝐴𝑛−1
𝛽𝑑𝑡2 𝛽𝑑𝑡
When aplying this scheme to a variable “u” of the model, the following affine dependent variables are
added to the model:
"Dot_u", "Dot2_u"
which represent the first and second order time derivative of the variable and can be used in some brick
definition.
The following data are also added:
which correspond to the values of “u”, “Dot_u” and “Dot2_u” at the previous time step.
Before the first solve, the data “Previous_u” and “Previous_Dot_u” (corresponding to 𝑈 0 in the example)
have to be initialized. The data “Previous_Dot2_u” is to be given or precomputed (see Precomputation
of velocity/acceleration and except for 𝛽 = 1/2, 𝛾 = 1).
The addition of this scheme to a variable is to be done thanks to:
Dot_u = 1/(6*dt)*(11*u-18*Previous_u+9*Previous2_u-2*Previous3_u)
Dot2_u = 1/(dt**2)*(2*u-5*Previous_u+4*Previous2_u-Previous3_u)
When aplying this scheme to a variable “u” of the model, the following affine dependent variables are
added to the model:
23.23. The model tools for the integration of transient problems 135
User Documentation, Release 5.4.2
"Dot_u", "Dot2_u"
which represent the first and second order time derivative of the variable and can be used in some brick
definition.
The following data are also added:
which correspond to the values of “u” at the time step n-1, n-2 n-3.
Before the solve, the data “Previous_u”, “Previous2_u” and “Previous3_u” (corresponding to 𝑈 0 in the
example) have to be initialized.
The addition of this scheme to a variable is to be done thanks to:
As it has been explained in previous sections, some intermediate variables are added to the model in
order to represent the time derivative of the variables on which the scheme is applied. Once again, if “u”
is such a variable, “Dot_u” will represent the time derivative of “u” approximated by the used scheme.
This also mean that “Dot_u” (and “Dot2_u” in order two in time problems) can be used to express the
transient terms. In GWFL, the term:
∫︁
𝑢𝑣𝑑𝑥
˙
Ω
Dot_u*Test_u
Similarly, every existing model brick of GetFEM can be applied to “Dot_u”. This is the case for instance
with:
136 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
Typically, the solve on the different time steps will take the following form:
iter.init();
getfem::standard_solve(model, iter);
model.shift_variables_for_time_integration();
}
model.shift_variables_for_time_integration();
is needed between two time step since it will copy the current value of the variables (u and Dot_u for
instance) to the previous ones (Previous_u and Previous_Dot_u).
Standard boundary conditions can of course be applied normally to the different variables of the un-
known. By default, applying Dirichlet, Neumann or contact boundary conditions to the unknown simply
means that the conditions are prescribed on the variable at the current time step n.
getfem::model model;
model.add_fem_variable("u", mf_u, 2); // Main unknown of the problem
// Dirichlet condition.
getfem::add_Dirichlet_condition_with_multipliers
(model, mim, "u", mf_u, DIRICHLET_BOUNDARY_NUM);
23.23. The model tools for the integration of transient problems 137
User Documentation, Release 5.4.2
// Iterations in time
for (scalar_type t = 0.; t < T; t += dt) {
iter.init();
getfem::standard_solve(model, iter);
...
...
...
...
138 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
The aim of these bricks is to take into account a contact condition with or without friction of an elastic
structure on a rigid foundation or between two elastic structures. These bricks are restricted to small
deformation approximation of contact (this may include large deformations on a flat obstacle).
For small deformation problems submitted a simple (compared to large deformation !) expression of
the contact with friction condition is usually used where the tangential displacement do not influence
the normal one. This is an approximation in the sense that if an obstacle is not perfectly flat, the tan-
gential displacement of course influence the point where the contact holds. This will not be the case
in small deformation where the contact condition can be considered to be described on the reference
configuration.
There are mainly two largely used discretizations of the contact with friction condition in this frame-
work: a direct nodal contact condition (usually prescribed on the displacement finite element nodes)
or a weak nodal contact condition (usually prescribed on the multiplier finite element nodes). The two
discretization leads to similar system. However, the interpretation of quantities is not the same. A third
approach is developed on Getfem contact bricks: a weak integral contact condition. It needs the compu-
tation of a non-linear integral on the contact boundary at each iteration but the numerical resolution is
potentially more scalable because it derives directly from continuous principles.
More details can be found for instance in [KI-OD1988], [KH-PO-RE2006] and [LA-RE2006].
A nodal contact condition consists in a certain number of contact nodes 𝑎𝑖 , 𝑖 = 1..𝑁𝑐 on which a contact
with (or without) friction condition is applied. The contact condition reads
where 𝜆𝑖𝑁 is the equivalent nodal contact force on 𝑎𝑖 and 𝑢𝑁 (𝑎𝑖 ) is the normal relative displacement
between the elastic solid and an obstacle or between two elastic solids. The term gap𝑖 represents the
normal gap between the two solids in the reference configuration. The friction condition reads
‖𝜆𝑖𝑇 ‖ ≤ −F 𝜆𝑖𝑁 ,
𝑢˙ 𝑇
𝜆𝑖𝑇 = F 𝜆𝑖𝑁 when 𝑢˙ 𝑇 ̸= 0,
‖𝑢˙ 𝑇 ‖
where 𝑢˙ 𝑇 is the relative slip velocity, F is the friction coefficient and 𝜆𝑖𝑇 the equivalent nodal friction
force on 𝑎𝑖 . The friction condition can be summarized by the inclusion
Given an augmentation parameter 𝑟, the contact and friction conditions can be equivalently expressed in
term of projection as
1 𝑖
(𝜆 − 𝑃]−∞,0] (𝜆𝑖𝑁 − 𝑟(𝑢𝑁 (𝑎𝑖 ) − gap𝑖 ))) = 0,
𝑟 𝑁
1 𝑖
(𝜆 − 𝑃B(−F 𝑃]−∞,0] (𝜆𝑖 −𝑟(𝑢𝑁 (𝑎𝑖 )−gap𝑖 )) (𝜆𝑖𝑇 − 𝑟𝑢˙ 𝑇 (𝑎𝑖 ))) = 0,
𝑟 𝑇 𝑁
where 𝑃𝐾 is the projection on the convex 𝐾 and B(−F 𝜆𝑖𝑁 ) is the ball of center 0 and radius −F 𝜆𝑖𝑁 .
These expressions will be used to perform a semi-smooth Newton method.
Suppose now that you approximate a linearized elasticity problem submitted to contact with friction.
Then, if 𝑈 is the vector of the unknown for the displacement you will be able to express the matrices
𝐵𝑁 and 𝐵𝑇 such that
𝑢𝑁 (𝑎𝑖 ) = (𝐵𝑁 𝑈 )𝑖 ,
(𝑢˙ 𝑇 (𝑎𝑖 ))𝑘 = (𝐵𝑇 𝑈˙ )(𝑑−1)(𝑖−1)+𝑘 ,
where 𝑑 is the dimension of the domain and 𝑘 = 1..𝑑 − 1. The expression of the elasticity problem with
contact with friction can be written as
𝑇
𝐾𝑈 = 𝐿 + 𝐵𝑁 𝜆𝑁 + 𝐵𝑇𝑇 𝜆𝑇 ,
1
− (𝜆𝑖 − 𝑃]−∞,0] (𝜆𝑖𝑁 − 𝛼𝑖 𝑟((𝐵𝑁 𝑈 )𝑖 − gap𝑖 ))) = 0, 𝑖 = 1..𝑁𝑐 ,
𝑟𝛼𝑖 𝑁
1
− (𝜆𝑖 − 𝑃B(−F 𝑃]−∞,0] (𝜆𝑖 −𝛼𝑖 𝑟((𝐵𝑁 𝑈 )𝑖 −gap𝑖 )))) (𝜆𝑖𝑇 − 𝛼𝑖 𝑟(𝐵𝑇 𝑈 − 𝐵𝑇 𝑈 0 )𝑖 )) = 0, 𝑖 = 1..𝑁𝑐 ,
𝑟𝛼𝑖 𝑇 𝑁
where 𝛼𝑖 is a parameter which can be added for the homogenization of the augmentation parameter,
(𝐵𝑇 𝑈 )𝑖 denotes here the sub-vector of indices from (𝑑−1)(𝑖−1)+1 to (𝑑−1)𝑖 for the sake of simplicity
0
and the sliding velocity 𝐵𝑇 𝑈˙ have been discretized into (𝐵𝑇 𝑈 −𝐵
Δ𝑡
𝑇𝑈 )
with 𝑈 0 the displacement at the
previous time step. Note that of course another discretization of the sliding velocity is possible and that
the time step Δ𝑡 do not appear in the expression of the friction condition since it does not influence the
direction of the sliding velocity.
In that case, the homogenization coefficient 𝛼𝑖 can be taken proportional to ℎ𝑑−2 (ℎ being the diameter
of the element). In this way, the augmentation parameter 𝑟 can be expressed in 𝑁/𝑚2 and chosen closed
to the Young modulus of the elastic body. Note that the solution is not sensitive to the value of the
augmentation parameter.
The direct nodal condition may have some drawback : locking phenomena, over-constraint. It is in
fact often more stable and for the same accuracy to use multiplier of reduced order compared to the
displacement (the direct nodal contact condition corresponds more or less to a multiplier described on
the same finite element method than the displacement).
Let 𝜙𝑖 be the shapes functions of the finite element describing the displacement and 𝜓𝑖 be the shape
functions of a finite element describing a multiplier on the contact boundary Γ𝑐 . It is assumed that the
set of admissible multiplier describing the normal stress will be
∑︁ 𝑗
Λℎ𝑁 = {𝜇ℎ𝑁 = 𝜇𝑁 𝜓𝑗 : 𝜇ℎ𝑁 (𝑎𝑖 ) ≤ 0, 𝑖 = 1..𝑁𝑐 }
where 𝑎𝑖 , 𝑖 = 1..𝑁𝑐 are the finite element nodes corresponding to the multiplier. The discrete contact
condition is now expressed in a weak form by
∫︁
(𝜇ℎ𝑁 − 𝜆ℎ𝑁 )(𝑢𝑁 − gap)𝑑Γ ≥ 0 ∀𝜇ℎ𝑁 ∈ Λℎ𝑁 .
Γ𝑐
140 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
In that case, the component 𝜆𝑖𝑁 is a contact stress (𝑁/𝑚2 ) and the matrix 𝐵𝑁 can be written
∫︁
(𝐵𝑁 )𝑖𝑗 = 𝜓𝑖 𝜙𝑗 𝑑Γ.
Γ𝑐
The matrix 𝐵𝑇 can also be written in a similar way. The friction condition can be written in a weak form
∫︁
(𝜇ℎ𝑇 − 𝜆ℎ𝑇 )𝑢˙ 𝑇 𝑑Γ ≥ 0 ∀𝜇ℎ𝑇 ∈ Λℎ𝑇 (F 𝜆ℎ𝑁 ),
Γ𝑐
except that now 𝜆𝑖𝑁 and 𝜆𝑖𝑇 are force densities, and 𝛼𝑖 has to be now chosen proportional to 1/ℎ𝑑 such
that the augmentation parameter 𝑟 can still be chosen close to the Young modulus of the elastic body.
Note that without additional stabilization technique (see [HI-RE2010]) an inf-sup condition have to be
satisfied between the finite element of the displacement and the one for the multipliers. This means in
particular that the finite element for the multiplier have to be “less rich” than the one for the displacement.
The weak integral contact formulation allows not to explicitly describe the discrete set of admissible
stress. See also Generic Nitsche’s method for contact with friction condition. The contact stress (includ-
ing the friction one) is described on a finite element space 𝑊 ℎ on the contact boundary Γ𝑐 :
{︁∑︁ }︁
𝜆ℎ ∈ 𝑊 ℎ = 𝜆𝑖 𝜓𝑖 , 𝜆𝑖 ∈ 𝐼𝑅𝑑
where 𝑑 is the dimension of the problem and 𝜓𝑖 still the shapes functions on which the contact stress is
developed. Now, given a outward unit vector 𝑛 on the contact boundary Γ𝑐 (usually the normal to the
obstacle), we make the standard decompositions:
where 𝑢ℎ is the displacement field approximated on a finite element space 𝑉 ℎ . This allows to express
the contact condition in the following way
∫︁
(𝜆ℎ𝑁 + (𝜆ℎ𝑁 − 𝑟(𝑢ℎ𝑁 − 𝑔𝑎𝑝))− )𝜇ℎ𝑁 𝑑Γ = 0 ∀𝜇ℎ ∈ 𝑊 ℎ ,
Γ𝑐
where 𝑔𝑎𝑝 is a given initial gap in reference configuration, 𝑟 is an augmentation parameter and (·)− :
𝐼𝑅 → 𝐼𝑅+ is the negative part. The friction condition can similarly be written:
∫︁
(𝜆ℎ𝑇 − 𝑃𝐵(F (𝜆ℎ −𝑟(𝑢ℎ −𝑔𝑎𝑝))− ) (𝜆ℎ𝑇 − 𝑟𝛼(𝑢ℎ𝑇 − 𝑤𝑇ℎ ))) · 𝜇ℎ𝑇 𝑑Γ = 0 ∀𝜇ℎ ∈ 𝑊 ℎ ,
𝑁 𝑁
Γ𝑐
where 𝐵(𝜌) is the closed ball of center 0 and radius 𝜌 and 𝑃𝐵(𝜌) is the orthogonal projection on it
(By convenyion, the ball reduces to the origin dor 𝜌 ≤ 0). The term 𝛼(𝑢ℎ𝑇 − 𝑤𝑇ℎ ) represent here an
approximation of the sliding velocity. The parameter 𝛼 and the field 𝑤𝑇ℎ have to be adapted with respect
to the chosen approximation. For instance, if the standard finite difference
where 𝑎(·, ·) and ℓ(𝑣) represent the remaining parts of the problem in 𝑢, for instance linear elasticity
and 𝜌 = F (𝜆ℎ𝑁 − 𝑟(𝑢ℎ𝑁 − 𝑔𝑎𝑝))− . Note that in this case, the mathematical analysis leads to choose a
value for the augmentation parameter of the kind 𝑟 = 𝑟0 /𝑟 with 𝑟0 having the dimension of a elasticity
modulus (a classical choice is the value of Young’s modulus). In order to write a Newton iteration, one
has to derive the tangent system. It can be written, reporting only the contact and friction terms and not
the right hand side:
⎧ ∫︁
⎪
⎪
⎪ · · · − 𝛿𝜆 · 𝑣𝑑Γ = · · · ∀𝑣 ℎ ∈ 𝑉 ℎ ,
⎪
⎪ ∫︁ Γ𝑐 ∫︁
⎪ 1
⎪
ℎ ℎ
− (1 − 𝐻(𝑟(𝑢𝑁 − 𝑔𝑎𝑝) − 𝜆𝑁 ))𝛿𝜆𝑁 𝜇𝑁 𝑑Γ − 𝐻(𝑟(𝑢ℎ𝑁 − 𝑔𝑎𝑝) − 𝜆𝑁 )𝛿𝑢𝑁 𝜇ℎ𝑁 𝑑Γ
⎪
⎪
𝑟 Γ𝑐 ∫︁
⎪
⎪
⎪
⎪ Γ𝑐
⎪
⎪ 1 ℎ ℎ ℎ ℎ
⎪
⎪ − (𝛿 𝜆 − 𝐷 𝑃 (𝜆
𝑥 𝐵(𝜌) 𝑇 − 𝑟𝛼(𝑢 𝑇 − 𝑤 𝑇 ))𝛿𝜆𝑇 ) · 𝜇𝑇 𝑑Γ
𝑟∫︁ Γ𝑐 𝑇
⎨
⎪
⎪
⎪ − 𝛼𝐷𝑥 𝑃𝐵(𝜌) (𝜆ℎ𝑇 − 𝑟𝛼(𝑢ℎ𝑇 − 𝑤𝑇ℎ ))𝛿𝑢𝑇 · 𝜇ℎ𝑇 𝑑Γ
Γ
⎪
⎪
⎪ ∫︁ 𝑐
⎪
(F 𝐷𝜌 𝑃𝐵(𝜌) (𝜆ℎ𝑇 − 𝑟𝛼(𝑢ℎ𝑇 − 𝑤𝑇ℎ ))𝛿𝑢𝑁 ) · 𝜇ℎ𝑇 𝑑Γ
⎪
⎪
⎪
⎪ +
∫︁Γ𝑐
⎪
⎪
F
⎪
⎪
− ( 𝐷𝜌 𝑃𝐵(𝜌) (𝜆ℎ𝑇 − 𝑟𝛼(𝑢ℎ𝑇 − 𝑤𝑇ℎ ))𝛿𝜆𝑁 ) · 𝜇ℎ𝑇 𝑑Γ = · · · ∀𝜇ℎ ∈ 𝑊 ℎ ,
⎪
⎪
⎩
Γ𝑐 𝑟
where 𝐻(·) is the Heaviside function (0 for a negative argument and 1 for a non-negative argument),
𝐷𝑥 𝑃𝐵(𝜌) (𝑥) and 𝐷𝜌 𝑃𝐵(𝜌) (𝑥) are the derivatives of the projection on 𝐵(𝜌) (assumed to vanish for 𝜌 ≤ 0)
and 𝛿𝜆 and 𝛿𝑢 are the unknown corresponding to the tangent problem.
The second version corresponds to the “symmetric” version. It is in fact symmetric in the frictionless
142 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
case only (because in this case it directly derives from the augmented Lagrangian formulation). It reads:
⎧ ∫︁
⎪
⎪
⎪
ℎ ℎ
𝑎(𝑢 , 𝑣 ) + (𝜆ℎ𝑁 − 𝑟(𝑢ℎ𝑁 − 𝑔𝑎𝑝))− 𝑣𝑁ℎ
𝑑Γ
⎪
⎪
⎪ ∫︁ Γ𝑐
In addition, GetFEM develops a method of numerical continuation for finding numerical solutions of
discretized evolutionary contact problems based on the weak integral contact condition (see Numerical
continuation and bifurcation for a general introduction). For this purpose, a parameter-dependent sliding
velocity may be added to the friction condition so that it becomes:
∫︁ (︁
)︀)︀)︁ ℎ
𝜆ℎ𝑇 − 𝑃𝐵(−F 𝜆ℎ ) 𝜆ℎ𝑇 − 𝑟 𝛼(𝑢ℎ𝑇 − 𝑤𝑇ℎ ) + (1 − 𝛾)𝑧𝑇ℎ · 𝜇𝑇 𝑑Γ = 0 ∀𝜇ℎ ∈ 𝑊 ℎ .
(︀ (︀
𝑁
Γ𝑐
Here, 𝛾 is a parameter and 𝑧𝑇ℎ is an initial sliding velocity. It is worth mentioning that if one chooses
Apart from pure Coulomb friction 𝜌 = F |𝜎𝑛 |, the weak integral contact framework in GetFEM also
supports a more generic friction law description:
In this equation 𝜌 is the admissible friction stress for a given normal stress 𝜎𝑛 , F is the coefficient
of friction, 𝜏𝑎𝑑ℎ is an adhesional (load-independent) shear stress and 𝜏𝑡𝑟𝑒𝑠𝑐𝑎 is a maximum shear stress
limit.
In order to add a frictionless contact brick you call the model object method:
getfem::add_basic_contact_brick
(md, varname_u, multname_n, dataname_r, BN, dataname_gap, dataname_
˓→alpha, aug_version);
This function adds a frictionless contact brick on varname_u thanks to a multiplier variable
multname_n. If 𝑈 is the vector of degrees of freedom on which the unilateral constraint is applied,
the matrix 𝐵𝑁 have to be such that this condition is defined by 𝐵𝑁 𝑈 ≤ 0. The constraint is prescribed
thank to a multiplier multname_n whose dimension should be equal to the number of lines of 𝐵𝑁 .
The variable dataname_r is the name of the augmentation parameter 𝑟 should be chosen in a range
144 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
of acceptable values. dataname_gap is an optional parameter representing the initial gap. It can be a
single value or a vector of value. dataname_alpha is an optional homogenization parameter for the
augmentation parameter.
The parameter aug_version indicates the augmentation strategy : 1 for the non-symmetric Alart-Curnier
augmented Lagrangian, 2 for the symmetric one, 3 for the unsymmetric method based on augmented
multipliers.
Note that is possible to change the basic contact matrix 𝐵𝑁 by using:
getfem::contact_brick_set_BN(md, indbrick);
getfem::contact_brick_set_BN(md, indbrick);
getfem::contact_brick_set_BT(md, indbrick);
Getfem user documentation). 1 for the non-symmetric Alart-Curnier augmented Lagrangian, 2 for the
symmetric one, 3 for the unsymmetric method based on augmented multipliers.
146 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
Basically, this brick computes the matrix 𝐵𝑁 and the vectors gap and alpha and calls the basic contact
brick.
getfem::add_nodal_contact_between_nonmatching_meshes_brick
(md, mim1, mim2, varname_u1, varname_u2, multname_n, multname_t,
dataname_r, dataname_friction_coeff, rg1, rg2, slave1=true, slave2=false,
aug_version=1);
This function adds a contact with friction condition between two faces of one or two elastic bodies. The
condition is applied on the variable varname_u or the variables varname_u1 and varname_u2 depending
if a single or two distinct displacement fields are given. Vectors rg1 and rg2 contain pairs of regions
expected to come in contact with each other. In case of a single region per side, rg1 and rg2 can be given
as normal integers. In the single displacement variable case the regions defined in both rg1 and rg2 refer
to the variable varname_u. In the case of two displacement variables, rg1 refers to varname_u1 and rg2
refers to varname_u2. multname_n should be a fixed size variable whose size is the number of degrees
of freedom on those regions among the ones defined in rg1 and rg2 which are characterized as “slaves”.
It represents the contact equivalent nodal normal forces. multname_t should be a fixed size variable
whose size corresponds to the size of multname_n multiplied by qdim - 1 . It represents the contact
equivalent nodal tangent (frictional) forces. The augmentation parameter r should be chosen in a range
of acceptable values (close to the Young modulus of the elastic body, see Getfem user documentation).
The friction coefficient stored in the parameter friction_coeff is either a single value or a vector of the
same size as multname_n. The optional parameters slave1 and slave2 declare if the regions defined in
rg1 and rg2 are correspondingly considered as “slaves”. By default slave1 is true and slave2 is false, i.e.
rg1 contains the slave surfaces, while rg2 the master surfaces. Preferably only one of slave1 and slave2
is set to true.
The parameter aug_version indicates the augmentation strategy : 1 for the non-symmetric Alart-Curnier
augmented Lagrangian, 2 for the symmetric one, 3 for the unsymmetric method with augmented multi-
plier and 4 for the unsymmetric method with augmented multiplier and De Saxce projection.
Basically, this brick computes the matrices 𝐵𝑁 and 𝐵𝑇 as well the vectors gap and alpha and calls the
basic contact brick.
In order to add a Hughes stabilized frictionless contact brick you call the model object method:
getfem::add_Hughes_stab_basic_contact_brick
(md, varname_u, multname_n, dataname_r, BN, DN, dataname_gap, dataname_
˓→alpha, aug_version);
This function adds a Hughes stabilized frictionless contact brick on varname_u thanks to a multi-
plier variable multname_n. If we take 𝑈 is the vector of degrees of freedom on which the unilateral
constraint is applied, and 𝜆 the multiplier Vector of contact force. Then Hughes stabilized friction-
less contact condition is defined by the matrix 𝐵𝑁 and 𝐷𝑁 have to be such that this condition is de-
fined by 𝐵𝑁 𝑈 − 𝐷𝑁 𝜆 ≤ 0. Where 𝐷𝑁 is the mass matrix relative to stabilized term. The variable
dataname_r is the name of the augmentation parameter 𝑟 should be chosen in a range of acceptable
values. dataname_gap is an optional parameter representing the initial gap. It can be a single value or
a vector of value. dataname_alpha is an optional homogenization parameter for the augmentation
parameter.
The parameter aug_version indicates the augmentation strategy : 1 for the non-symmetric Alart-Curnier
augmented Lagrangian, 2 for the symmetric one, 3 for the unsymmetric method based on augmented
multipliers.
Note that the matrix 𝐷𝑁 is a sum of the basic contact term and the Hughes stabilised term. You can
change it with:
getfem::contact_brick_set_DN(md, indbrick);
getfem::add_integral_contact_with_rigid_obstacle_brick
(md, mim, varname_u, multname_n, dataname_obs, dataname_r, region,
˓→option = 1);
This function adds a frictionless contact condition with a rigid obstacle to the model, which is defined
in an integral way. It is the direct approximation of an augmented Lagrangian formulation defined
at the continuous level. The advantage should be a better scalability: the number of Newton itera-
tions should be more or less independent of the mesh size. The condition is applied on the variable
varname_u on the boundary corresponding to region. The rigid obstacle should be described with
the data dataname_obstacle being a signed distance to the obstacle (interpolated on a finite element
method). multname_n should be a fem variable representing the contact stress. An inf-sup condition
between multname_n and varname_u is required. The augmentation parameter dataname_r
should be chosen in a range of acceptable values.
Possible values for option is 1 for the non-symmetric Alart-Curnier augmented Lagrangian method, 2
for the symmetric one, 3 for the non-symmetric Alart-Curnier method with an additional augmentation
and 4 for a new unsymmetric method. The default value is 1.
mim represents of course the integration method. Note that it should be accurate enough to integrate
efficiently the nonlinear terms involved.
getfem::add_integral_contact_with_rigid_obstacle_brick
(md, mim, varname_u, multname_n, dataname_obs, dataname_r,
dataname_friction_coeffs, region, option = 1, dataname_alpha = "",
dataname_wt = "", dataname_gamma = "", dataname_vt = "");
This function adds a contact with friction condition with a rigid obstacle to the model, which is de-
fined in an integral way. It is the direct approximation of an augmented Lagrangian formulation defined
at the continuous level. The advantage should be a better scalability: the number of Newton itera-
tions should be more or less independent of the mesh size. The condition is applied on the variable
varname_u on the boundary corresponding to region. The rigid obstacle should be described with
the data dataname_obstacle being a signed distance to the obstacle (interpolated on a finite element
method). multname_n should be a fem variable representing the contact stress. An inf-sup condition
between multname_n and varname_u is required. The augmentation parameter dataname_r
should be chosen in a range of acceptable values.
The parameter dataname_friction_coeffs contains the Coulomb friction coefficient and optionally an
adhesional shear stress threshold and the tresca limit shear stress. For constant coefficients its size is
148 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
from 1 to 3. For coefficients described on a finite element method, this vector contains a number of
single values, value pairs or triplets equal to the number of the corresponding mesh_fem’s basic dofs.
Possible values for option is 1 for the non-symmetric Alart-Curnier augmented Lagrangian method, 2
for the symmetric one, 3 for the non-symmetric Alart-Curnier method with an additional augmentation
and 4 for a new unsymmetric method. The default value is 1. Option 4, assumes pure Coulomb friction
and ignores any adhesional stress and tresca limit coefficients.
dataname_alpha and dataname_wt are optional parameters to solve evolutionary friction prob-
lems. dataname_gamma and dataname_vt denote optional data for adding a parameter-dependent
sliding velocity to the friction condition. mim represents of course the integration method. Note that it
should be accurate enough to integrate efficiently the nonlinear terms involved.
getfem::add_integral_contact_between_nonmatching_meshes_brick
(md, mim, varname_u1, varname_u2, multname_n, dataname_r,
region1, region2, option = 1);
This function adds a frictionless contact condition between nonmatching meshes to the model, which
is defined in an integral way. It is the direct approximation of an augmented Lagrangian formula-
tion defined at the continuous level. The advantage should be a better scalability: the number of
Newton iterations should be more or less independent of the mesh size. The condition is applied on
the variables varname_u1 and varname_u2 on the boundaries corresponding to region1 and
region2. multname_n should be a fem variable representing the contact stress. An inf-sup con-
dition between multname_n and varname_u1 and varname_u2 is required. The augmentation
parameter dataname_r should be chosen in a range of acceptable values.
Possible values for option is 1 for the non-symmetric Alart-Curnier augmented Lagrangian method, 2
for the symmetric one, 3 for the non-symmetric Alart-Curnier method with an additional augmentation
and 4 for a new unsymmetric method. The default value is 1.
mim represents of course the integration method. Note that it should be accurate enough to integrate
efficiently the nonlinear terms involved.
getfem::add_integral_contact_between_nonmatching_meshes_brick
(md, mim, varname_u1, varname_u2, multname, dataname_r,
dataname_friction_coeffs, region1, region2, option = 1,
dataname_alpha = "", dataname_wt1 = "", dataname_wt2 = "");
This function adds a contact with friction condition between nonmatching meshes to the model. This
brick adds a contact which is defined in an integral way. It is the direct approximation of an augmented
Lagrangian formulation defined at the continuous level. The advantage should be a better scalability:
the number of Newton iterations should be more or less independent of the mesh size. The condi-
tion is applied on the variables varname_u1 and varname_u2 on the boundaries corresponding to
region1 and region2. multname should be a fem variable representing the contact and friction
stress. An inf-sup condition between multname and varname_u1 and varname_u2 is required.
The augmentation parameter dataname_r should be chosen in a range of acceptable values.
The parameter dataname_friction_coeffs contains the Coulomb friction coefficient and optionally an
adhesional shear stress threshold and the tresca limit shear stress. For constant coefficients its size is from
1 to 3. For coefficients described on a finite element method on the same mesh as varname_u1, this
vector contains a number of single values, value pairs or triplets equal to the number of the corresponding
mesh_fem’s basic dofs.
Possible values for option is 1 for the non-symmetric Alart-Curnier augmented Lagrangian method, 2
for the symmetric one, 3 for the non-symmetric Alart-Curnier method with an additional augmentation
and 4 for a new unsymmetric method. The default value is 1. dataname_alpha, dataname_wt1
and dataname_wt2 are optional parameters to solve evolutionary friction problems. mim represents
the integration method on the same mesh as varname_u1. Note that it should be accurate enough to
integrate efficiently the nonlinear terms involved.
getfem::add_penalized_contact_with_rigid_obstacle_brick
(md, mim, varname_u, dataname_obs, dataname_r, region,
option = 1, dataname_lambda_n = "");
This function adds a frictionless penalized contact condition with a rigid obstacle to the model. The
condition is applied on the variable varname_u on the boundary corresponding to region. The
rigid obstacle should be described with the data dataname_obstacle being a signed distance to the
obstacle (interpolated on a finite element method). The penalization parameter dataname_r should
be chosen large enough to prescribe an approximate non-penetration condition but not too large not to
deteriorate too much the conditioning of the tangent system. dataname_n is an optional parameter
used if option is 2. In that case, the penalization term is shifted by lambda_n (this allows the use of an
Uzawa algorithm on the corresponding augmented dLagrangian formulation)
getfem::add_penalized_contact_with_rigid_obstacle_brick
(md, mim, varname_u, dataname_obs, dataname_r, dataname_friction_
˓→coeffs,
region, option = 1, dataname_lambda = "", dataname_alpha = "",
dataname_wt = "");
This function adds a penalized contact condition with Coulomb friction with a rigid obstacle to the
model. The condition is applied on the variable varname_u on the boundary corresponding to
region. The rigid obstacle should be described with the data dataname_obstacle being a signed dis-
tance to the obstacle (interpolated on a finite element method).
The parameter dataname_friction_coeffs contains the Coulomb friction coefficient and optionally an
adhesional shear stress threshold and the tresca limit shear stress. For constant coefficients its size is
from 1 to 3. For coefficients described on a finite element method, this vector contains a number of
single values, value pairs or triplets equal to the number of the corresponding mesh_fem’s basic dofs.
The penalization parameter dataname_r should be chosen large enough to prescribe approximate non-
penetration and friction conditions but not too large not to deteriorate too much the conditioning of the
tangent system. dataname_lambda is an optional parameter used if option is 2. In that case, the
penalization term is shifted by lambda (this allows the use of an Uzawa algorithm on the corresponding
augmented Lagrangian formulation). dataname_alpha and dataname_wt are optional parameters
to solve evolutionary friction problems.
150 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
getfem::add_penalized_contact_between_nonmatching_meshes_brick
(md, mim, varname_u1, varname_u2, dataname_r,
region1, region2, option = 1, dataname_lambda_n = "");
This function adds a penalized contact frictionless condition between nonmatching meshes to
the model. The condition is applied on the variables varname_u1 and varname_u2
on the boundaries corresponding to region1` and ``region2`. The penalization
parameter ``dataname_r should be chosen large enough to prescribe an approximate non-
penetration condition but not too large not to deteriorate too much the conditionning of the tangent
system. dataname_n is an optional parameter used if option is 2. In that case, the penalization term
is shifted by lambda_n (this allows the use of an Uzawa algorithm on the corresponding augmented
Lagrangian formulation)
getfem::add_penalized_contact_between_nonmatching_meshes_brick
(md, mim, varname_u1, varname_u2, dataname_r, dataname_friction_coeffs,
region1, region2, option = 1, dataname_lambda = "",
dataname_alpha = "", dataname_wt1 = "", dataname_wt2 = "");
This function adds a penalized contact condition with Coulomb friction between nonmatching
meshes to the model. The condition is applied on the variables varname_u1 and varname_u2
on the boundaries corresponding to region1` and ``region2`. The penalization
parameter ``dataname_r should be chosen large enough to prescribe an approximate non-
penetration condition but not too large not to deteriorate too much the conditionning of the tangent
system.
The parameter dataname_friction_coeffs contains the Coulomb friction coefficient and optionally an
adhesional shear stress threshold and the tresca limit shear stress. For constant coefficients its size is
from 1 to 3. For coefficients described on a finite element method on the same mesh as varname_u1, this
vector contains a number of single values, value pairs or triplets equal to the number of the corresponding
mesh_fem’s basic dofs.
dataname_lambda is an optional parameter used if option is 2. In that case, the penalization
term is shifted by lambda (this allows the use of an Uzawa algorithm on the corresponding augmented
Lagrangian formulation) dataname_alpha, dataname_wt1 and dataname_wt2 are optional
parameters to solve evolutionary friction problems. mim represents the integration method on the same
mesh as varname_u1. Note that it should be accurate enough to integrate efficiently the nonlinear
terms involved.
The basic tools to deal with large sliding/large deformation contact of deformable structures are acces-
sible in GWFL (the generic weak form language). Some interpolate transformations (see Interpolate
transformations) are defined to perform the contact detection and allow to integrate from a contacct
bondary to the opposite contact boundary. Some other useful tools such as the unit normal vector in the
real configuration and projections to take into account contact with Coulomb friction are also defined as
operators in GWFL.
Of course, the computational cost of large sliding/large deformation contact algorithms is greatly higher
than small sliding-small deformation ones.
In order to incorporate the contact detection in the high-level generic assembly, a specific interpolate
transformation has been defined (see Interpolate transformations for more explanations on interpolate
transformations). It is based on a raytracing contact detection has described in [KO-RE2014] and uses
the criteria described below. The interpolate transformation stores the different potential contact sur-
faces. On most of methods, potential contact surface are classified into two categories: master and slave
surface (see figure).
The slave surface is the “contactor” and the master one the “target”. Rigid obstacle are also consid-
ered. They are always master surfaces. The basic rule is that the contact is considered between a slave
surface and a master one. However, the multi-contact frame object and the GetFEM bricks allow multi-
contact situations, including contact between two master surfaces, self-contact of a master surface and
an arbitrary number of slave and master surfaces.
Basically, in order to detect the contact pairs, Gauss points or f.e.m. nodes of slave surfaces are projected
on master surfaces (see figure). If self-contact is considered, Gauss points or f.e.m. nodes of master
surface are also projected on master surfaces.
The addition of a raytracing transformation to a model:
where transname is a name given to the transformation which allows to refer to it in GWFL and d is
the release distance (see above).
152 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
The raytracing transformation is added without any slave or master contact boundary. The following
functions allows to add some boundaries to the transformation:
add_master_contact_boundary_to_raytracing_transformation(model &md,
const std::string &transname, const mesh &m,
const std::string &dispname, size_type region)
add_slave_contact_boundary_to_raytracing_transformation(model &md,
const std::string &transname, const mesh &m,
const std::string &dispname, size_type region)
where dispname is the variable name which represent the displacement on that contact boundary. The
difference between master and slave contact boundary is that the contact detection is to be performed
starting from a slave or master boundary toward a master boundary. The contact detection is not per-
formed toward a slave boundary. Consequently, only the influence boxes of the elements of the master
surfaces are computed and stored.
It is also possible to add a rigid obstacle (considered as a master surface) thanks to the function:
add_rigid_obstacle_to_raytracing_transformation(model &md,
const std::string &transname,
const std::string &expr, size_type N)
where expr is the expression of a signed distance to the obstacle using the syntax of GWFL (X being the
current position, X(0), X(1) . . . the corresponding components). For instance an expression X(0) +
5 will correspond to a flat obstacle lying on the right of the position -5 of the first coordinate. Be aware
that the expression have to be close to a signed distance, which in particular means that the gradient
norm have to be close to 1.
In order to distinguish between non-contact situations and the occurence of a contact with another de-
formable body or with a rigid obstacle, the transformation returns an integer identifier which can be used
by the Interpolate_filter command of GWFL (see Interpolate transformations). The different values:
• 0 : no contact found on this Gauss point
• 1 : contact occurs on this Gauss point with a deformable body
• 2 : contact occurs on this Gauss point with a rigid obstacle.
such that it is possible to differentiate the treatment of these three cases using:
Interpolate_filter(transname, expr1, 0)
Interpolate_filter(transname, expr2, 1)
Interpolate_filter(transname, expr3, 2)
in GWFL, where expr1, expr2 and expr3 correspond to the different terms to
be computed. The matlab interface demo program /interface/tests/matlab/
demo_large_sliding_contact.m presents an example of use.
Note that the transformation could also be directly used with a ga_workspace object if model object are
not used. See getfem/getfem_contact_and_friction_common.h for more details. Note
also that in the framework of the model object, a interfaced use of this transformation is allowed by the
model bricks described below.
A contact pair is formed by a point of a slave (or master in case of self-contact) surface and a projected
point on the nearest master surface (or rigid obstacle). The Algorithm used is summerized in figure
It is impossible to distinguish without fail between valid and invalid contact situations without a global
topological criterion (such as in [Pantz2008]), a fortiori for self-contact detection. However, this kind
of criterion can be very costly to implement. Thus, one generally implements some simple heuristic
criteria which cannot cover all the possible cases. We present such a set of criteria here. They are of
course perfectible and subject to change. First, in figure one can see a certain number of situations of
valid or invalid contact that criteria have to distinguish.
Some details on the algorithm:
• Computation of influence boxes. The influence box of an element is just an offset to its bounding
box at a distance equal to the release distance. If this strategy is used, the release distance should
not be too large compared to the element size. Otherwise, a point would correspond to a a large
number of influence box which can considerably slow down the search of contact pairs. The
influence boxes are stored in a region tree object in order to find the boxes containing a point with
an algorithm having a mean complexity in 𝑂(𝑙𝑜𝑔(𝑁 )).
154 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
156 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
• What is a potential contact pair. A potential contact pair is a pair slave point - master element
face which will be investigated. The projection of the slave point on the master surface will be
done and criteria will be applied.
• Projection algorithm. The projection of the slave point onto a master element face is done
by a parametrization of the surface on the reference element via the geometric transformation
and the displacement field. During the projection, no constraint is applied to remain inside the
element face, which means that the element face is prolongated analytically. The projection is
performed by minimizing the distance between the slave point and the projected one using the
parametrization and Newton’s and/or BFGS algorithms. If raytrace is set to true, then no
projection is computed. Instead a ray tracing from the point x in the direction of the unit normal
vector at x to find y. This means the reverse of the usual situation (x will be the projection of y).
The list of criteria:
• Criterion 1: the unit normal cone/vector should be compatible, and the two points do not
share the same element. Two unit normal vector are compatible if their scalar product are non-
positive. In case of f.e.m. node contact, since a fem node is shared generally by several elements,
a normal cone constituted of the unit normal vectors of each element is considered. Two normal
cones are compatible if at least one pair of unit normal vector have their scalar product non-
positive. In order to simplify the computation, a normal cone is reduced to a mean normal vector
if the solid angle of the normal cone is less than cut_angle a parameter of the multi-contact
frame object. This criterion allows to treat cases (B) and (K1).
• Criterion 2: the contact pair is eliminated when the search of the projection/raytrace point
do not converge. When Newton’s algorithms (and BFGS one for projection) used to compute the
projection/raytrace of the slave point on the master element surface fails to converge, the pair is
not considered. A warning is generated.
• Criterion 3 : the projected point should be inside the element. The slave point is projected on
the surface of the master element without the constraint to remain inside the face (which means
that the face is prolongated). If the orthogonal projection is outside the face, the pair is not
considered. This is the present state, however, to treat case (J3) an aditional treatment will have to
be considered (projection on the face with the constraint to remain inside it and test of the normal
cone at this point) This criterion allows to treat cases (F2), (K2), (M1) and (M2).
• Criterion 4 : the release distance is applied. If the distance between the slave point and its pro-
jection on the master surface is greater than the release distance, the contact pair is not considered.
This can treat cases (C), (E), (F1), (G), (H) if the release distance is adapted and the deformation
not too important.
• Criterion 5 : comparison with rigid obstacles. If the signed distance between the slave point and
its projection on the master surface is greater than the one with a rigid obstacle (considering that
the release distance is also first applied to rigid obstacle) then the contact pair is not considered.
• Criterion 6 : for self-contact only : apply a test on unit normals in reference configuration.
In case of self contact, a contact pair is eliminated when the slave point and the master element
belong to the same mesh and if the slave point is behind the master surface (with respect to its unit
outward normal vector) and not four times farther than the release distance. This can treat cases
(A), (C), (D), (H).
• Criterion 7 : smallest signed distance on contact pairs. Between the retained contact pairs (or
rigid obstacle) the one corresponding to the smallest signed distance is retained.
Notations: Ω ⊂ IRd denotes the reference configuration of a deformable body, possibly constituted
by several unconnected parts (see figure). Ω𝑡 is the deformed configuration and 𝜙ℎ : Ω → Ω𝑡 is the
approximated deformation on a finite element space 𝑉 ℎ . The displacement 𝑢ℎ : Ω → IRd is defined
by 𝜙ℎ (𝑋) = 𝑋 + 𝑢ℎ (𝑋). A generic point of the reference configuration Ω is denoted by 𝑋 while
the corresponding point of the deformed configuration is denoted by 𝑥 = 𝜙ℎ (𝑋). Γ𝑆 denotes a slave
boundary of Ω and Γ𝑀 a master one. The corresponding boundaries on the deformed configuration are
Γ𝑆𝑡 and Γ𝑀 𝑡 , respectively. The outward unit normal vector to the boundary (in the deformed configura-
tion) at a point 𝑥 = 𝜙ℎ (𝑋) of that boundary is denoted by 𝑛𝑥 . Finally, the notation 𝛿𝐴[𝐵] denotes the
directional derivative of the quantity 𝐴 with respect to the deformation and in the direction 𝐵. Similarly,
The notation 𝛿 2 𝐴[𝐵, 𝐶] is the second derivative in the directions 𝐵 and 𝐶.
Let 𝐽(𝜙ℎ ) be the potential energy of the system, without taking into account contact and friction con-
tributions. Typically, it includes elastic and external load potential energy. Let 𝑋𝑖 for 𝑖 ∈ 𝐼nodes the set
of finite element nodes on the slave boundary in the reference configuration. Let 𝑋𝑖 for 𝑖 ∈ 𝐼def be the
contact nodes in potential contact with the master surface of a deformable body. Let 𝑋𝑖 for 𝑖 ∈ 𝐼rig be
the contact nodes in potential contact with a rigid obstacle.
We denote by 𝑥𝑖 = 𝜙ℎ (𝑋𝑖 ) the corresponding node on the deformed configuration and 𝑦𝑖 the projection
on the master surface (or rigid obstacle) on the deformed configuration. Let 𝑌𝑖 the point on the master
surface verifying 𝑦𝑖 = 𝜙ℎ (𝑌𝑖 ). This allows to define the normal gap as
𝑔𝑖 = 𝑛𝑦 .(𝜙ℎ (𝑋𝑖 ) − 𝜙ℎ (𝑌𝑖 )) = ‖𝜙ℎ (𝑋𝑖 ) − 𝜙ℎ (𝑌𝑖 )‖Sign(𝑛𝑦 .(𝜙ℎ (𝑋𝑖 ) − 𝜙ℎ (𝑌𝑖 ))),
23.25.3 Tools of the high-level generic assembly for contact with friction
The following nonlinear operators are defined in GWFL (see Compute arbitrary terms - high-level
generic assembly procedures - Generic Weak-Form Language (GWFL)):
• Transformed_unit_vector(Grad_u, n) where Grad_u is the gradient of a displace-
ment field and n a unit vector in the reference configuration. This nonlinear operator corresponds
to
(𝐼 + ∇𝑢)−𝑇 𝑛
𝑛𝑡𝑟𝑎𝑛𝑠 =
‖(𝐼 + ∇𝑢)−𝑇 𝑛‖
158 Chapter 23. The model description and basic model bricks
User Documentation, Release 5.4.2
for 𝜏 ≤ 0 or ‖𝑞𝑇 ‖ ≤ 𝜏
{︃
0
𝜕𝜏 𝑃𝐵(𝑛,𝜏 ) (𝑞) = 𝑞𝑇
otherwise
‖𝑞𝑇 ‖
⎧
⎪
⎪ 0 for 𝜏 ≤ 0
−𝑞 · 𝑛 T − 𝑛 ⊗ 𝑞 for ‖𝑞𝑇 ‖ ≤ 𝜏
⎨
𝑛
𝜕𝑛 𝑃𝐵(𝑛,𝜏 ) (𝑞) = (︂ (︂ 𝑇 )︂ )︂
𝜏 𝑞 𝑞
⎩ − 𝑞 · 𝑛 T𝑛 − 𝑇 ⊗ 𝑇 + 𝑛 ⊗ 𝑞𝑇 otherwise.
⎪
⎪
‖𝑞𝑇 ‖ ‖𝑞𝑇 ‖ ‖𝑞𝑇 ‖
𝜕𝜆 𝑃 (𝜆, 𝑛, 𝑉𝑠 , 𝑔, 𝑓, 𝑟) = 𝜕𝑞 𝑃𝐵(𝑛,𝜏 ) + 𝜕𝜏 𝑃𝐵(𝑛,𝜏 ) ⊗ 𝜕𝜆 𝜏 + 𝐻(−𝜆 · 𝑛 − 𝑟 𝑔) 𝑛 ⊗ 𝑛,
⃒
⃒ 𝜕 𝑃 + 𝜕𝜏 𝑃𝐵(𝑛,𝜏 ) ⊗ 𝜕𝑛 𝜏
𝜕𝑛 𝑃 (𝜆, 𝑛, 𝑉𝑠 , 𝑔, 𝑓, 𝑟) = ⃒⃒ 𝑛 𝐵(𝑛,𝜏 )
+𝐻(−𝜆 · 𝑛 − 𝑟 𝑔) (𝑛 ⊗ 𝜆 − (2 𝜆 · 𝑛 + 𝑟 𝑔) 𝑛 ⊗ 𝑛 + (𝜆 · 𝑛 + 𝑟 𝑔) I) ,
𝜕𝑔 𝑃 (𝜆, 𝑛, 𝑉𝑠 , 𝑔, 𝑓, 𝑟) = 𝜕𝜏 𝑃𝐵(𝑛,𝜏 ) 𝜕𝑔 𝜏 + 𝐻(−𝜆 · 𝑛 − 𝑟 𝑔) 𝑟 𝑛
𝜕𝑓 𝑃 (𝜆, 𝑛, 𝑉𝑠 , 𝑔, 𝑓, 𝑟) = 𝜕𝜏 𝑃𝐵(𝑛,𝜏 ) 𝜕𝑓 𝜏
𝜕𝑟 𝑃 (𝜆, 𝑛, 𝑉𝑠 , 𝑔, 𝑓, 𝑟) = 𝐻(−𝜆 · 𝑛 − 𝑟 𝑔)𝑔𝑛 + 𝜕𝑞 𝑃𝐵(𝑛,𝜏 ) 𝑉𝑠 + 𝜕𝜏 𝑃𝐵(𝑛,𝜏 ) 𝜕𝑟 𝜏
This brick allows to deal with a multi-contact situation. It adds to the model a raytracing interpolate
transformation as described in a previous section whose name can be obtained by the command:
Once the brick is added to the model, the master and slave contact boundaries have to be added with the
following function:
add_contact_boundary_to_large_sliding_contact_brick(model &md,
size_type indbrick, const mesh_im &mim, size_type region,
bool is_master, bool is_slave, const std::string &u,
const std::string &lambda = "", const std::string &w = "",
bool frame_indifferent = false)
where region should be a valid mesh region number representing a boundary, is_master should
be set to true if the contact detection is to be done on that contact boundary, is_slave should
be set to true if the integration of contact terms is to be done on that boundary. Note that a contact
boundary is allowed to be both master and slave, in particular to allow self-contact detection. u
is the displacement variable. If is_slave is set to true, lambda should describe a multiplier
variable with degrees of freedom on the contact boundary (typically added to the model with the md.
add_filtered_fem_variable(...) method). Pure master contact boundary
do not need the definition of a multiplier. Additionally, ``w is for the
evolutionnary case and represents the displacement at the previous time step.
A rigid obstacle can be added to the brick with:
add_rigid_obstacle_to_large_sliding_contact_brick(model &md,
size_type indbrick, std::string expr, size_type N)
where expr is an expression using GWFL (with X is the current position) which should be a signed
distance to the obstacle. N is the mesh dimension.
160 Chapter 23. The model description and basic model bricks
CHAPTER 24
Let an algebraic problem coming from discretisation of an FEM-model can be written in the form
𝐹 (𝑈 ) = 0.
In what follows, we shall suppose that the model depends on an additional scalar parameter 𝜆 so that
𝐹 (𝑈 ) = 𝐹 (𝑈, 𝜆).
𝐹 (𝑈, 𝜆) = 0, 𝐹 : R𝑁 × R → R𝑁 .
˜ ‖𝑌 ‖𝑤 := 𝜅‖𝑈 ‖2 + 𝜆2 , ˜
√︀
⟨𝑌, 𝑌˜ ⟩𝑤 := 𝜅⟨𝑈, 𝑈
˜ ⟩ + 𝜆𝜆, 𝑌 = (𝑈, 𝜆), 𝑌˜ = (𝑈˜ , 𝜆).
the dimension of the underlying problem. Alternatively, 𝜅 can be chosen as 1/𝑁 for simplicity.
The idea of the continuation strategy is to continue smooth pieces of solution curves by a classical
predictor-corrector method and to join the smooth pieces continuously.
The particular predictor-corrector method employed is a slight modification of the inexact Moore-
Penrose continuation implemented in MATCONT [Dh-Go-Ku2003]. It computes a sequence of con-
secutive points 𝑌𝑗 lying approximately on a solution curve and a sequence of the corresponding unit
tangent vectors 𝑇𝑗 :
161
User Documentation, Release 5.4.2
To describe it, let us suppose that we have a couple (𝑌𝑗 , 𝑇𝑗 ) satisfying the relations above at our disposal.
In the prediction, an initial approximation of (𝑌𝑗+1 , 𝑇𝑗+1 ) is taken as
0 0
𝑌𝑗+1 := 𝑌𝑗 + ℎ𝑗 𝑇𝑗 , 𝑇𝑗+1 := 𝑇𝑗 ,
0 with
⎛ ⎞
𝐹 (𝑌 )
𝑙−1 ⊤ 𝑙−1
𝑙
⎜ (𝑇𝑗+1 ) (𝑌 − 𝑌𝑗+1 ) ⎟
𝐹 (𝑌, 𝑇 ) := ⎜
⎜ ⎟
𝑙−1
∇𝐹 (𝑌𝑗+1 )𝑇
⎟
⎝ ⎠
𝑙−1 𝑙−1 𝑙−1
⟨𝑇𝑗+1 , 𝑇 ⟩𝑤 − ⟨𝑇𝑗+1 , 𝑇𝑗+1 ⟩𝑤
𝑙−1 𝑙−1
and the initial approximation (𝑌𝑗+1 , 𝑇𝑗+1 ). Due to the potential non-differentiability of 𝐹 , a piecewise-
smooth variant of the Newton method is used (Algorithm 7.2.14 in [Fa-Pa2003]).
Fig. 1: Correction.
𝑙 , 𝑇 𝑙 ) is accepted for (𝑌 𝑙 𝑙 𝑙−1 ′
A couple (𝑌𝑗+1 𝑗+1 𝑗+1 , 𝑇𝑗+1 ) if ‖𝐹 (𝑌𝑗+1 )‖ ≤ 𝜀, ‖𝑌𝑗+1 − 𝑌𝑗+1 ‖𝑤 ≤ 𝜀 , and
the cosine of the angle between 𝑇𝑗+1 𝑙 and 𝑇𝑗 is greater or equal to 𝑐min . Let us note that the partial
gradient of 𝐹 (or of one of its selection functions in the case of the non-differentiability) with respect to
𝑈 is assembled analytically whereas the partial gradient with respect to 𝜆 is evaluated by forward finite
differences with an increment equal to 1e-8.
The step size ℎ𝑗+1 in the next prediction depends on how the Newton correction has been successful.
Denoting the number of iterations needed by 𝑙it , it is selected as
⎧
⎨max{ℎdec ℎ𝑗 , ℎmin } if no new couple has been accepted,
⎪
ℎ𝑗+1 := min{ℎinc ℎ𝑗 , ℎmax } if a new couple has been accepted and 𝑙it < 𝑙thr ,
⎪
ℎ𝑗 otherwise,
⎩
where 0 < ℎdec < 1 < ℎinc , 0 < 𝑙thr and 0 < ℎmin < ℎmax are given constants. At the beginning, one
sets ℎ1 := ℎinit for some ℎmin ≤ ℎinit ≤ ℎmax .
Now, let us suppose that we have approximated a piece of a solution curve corresponding to one sub-
domain of smooth behaviour of 𝐹 and we want to recover a piece corresponding to another sub-domain
of smooth behaviour. Let (𝑌𝑗 , 𝑇𝑗 ) be the last computed couple.
To approximate the tangent to the other smooth piece, we first take a point 𝑌𝑗 + ℎ𝑇𝑗 with ℎ a bit greater
than ℎmin so that this point belongs to the interior of the other sub-domain of smooth behaviour. Then
𝑇− with ∇𝐹 (𝑌𝑗 − 𝑟ℎ̃𝑇˜)𝑇− = 0. Second, 𝑌𝑗 + 𝑟ℎ̃𝑇˜ appears in the other sub-domain for ℎ̃ larger than
⊤𝑇
|𝑇+ ˜|
some positive threshold, and, for such values, ‖𝑇+ ‖‖𝑇˜‖
is close to 1 for 𝑇+ with ∇𝐹 (𝑌𝑗 + 𝑟ℎ̃𝑇˜)𝑇+ = 0.
This suggests the following procedure for selecting the desired direction of 𝑇˜: Increase the values of ℎ̃
successively from ℎmin , and when you arrive at ℎ̃ and 𝑟 ∈ {±1} such that
|𝑇 ⊤ 𝑇˜|
≈1 if ∇𝐹 (𝑌𝑗 + 𝑟ℎ̃𝑇˜)𝑇 = 0,
‖𝑇 ‖‖𝑇˜‖
take 𝑟𝑇˜ as the approximation of the tangent to the other smooth piece.
Having this approximation at our disposal, we restart the predictor-corrector with (𝑌𝑗 , 𝑟𝑇˜).
In GetFEM, the continuation is implemented for two ways of parameterization of the model:
1. The parameter 𝜆 is directly a scalar datum, which the model depends on.
2. The model is parametrised by the scalar parameter 𝜆 via a vector datum 𝑃 , which the model
depends on. In this case, one takes the linear path
𝜆 ↦→ 𝑃 (𝜆) := (1 − 𝜆)𝑃 0 + 𝜆𝑃 1 ,
where 𝑃 0 and 𝑃 1 are given values of 𝑃 , and one traces the solution set of the problem
𝐹 (𝑈, 𝑃 (𝜆)) = 0.
When tracing solutions of the system 𝐹 (𝑈, 𝜆) = 0, one may be interested in limit points (also called
fold or turning points), where the number of solutions with the same value of 𝜆 changes. These points
𝜏LP (𝑇 ) := 𝑇𝜆 , 𝑇 = (𝑇𝑈 , 𝑇𝜆 ) ∈ R𝑁 × R.
A point 𝑌¯ is called a bifurcation point of the system 𝐹 (𝑌 ) = 0 if 𝐹 (𝑌¯ ) = 0 and two or more distinct
solution curves pass through it. The following result gives a test for smooth bifurcation points (see, e.g.,
[Georg2001]):
Let 𝑠 ↦→ 𝑌 (𝑠) be a parameterization of a solution curve and 𝑌¯ := 𝑌 (¯
𝑠) be a bifurcation point. Moreover,
let 𝑇 ⊤ 𝑌˙ (¯ / Im(𝐽(𝑌¯ )), 𝐶 ∈
𝑠) > 0, 𝐵 ∈ / Im(𝐽(𝑌¯ )⊤ ), 𝑑 ∈ R and
(︂ )︂
∇𝐹 (𝑌 )
𝐽(𝑌 ) := .
𝑇⊤
(︂ )︂ (︂ )︂ (︂ )︂
𝐽(𝑌 ) 𝐵 𝑉 (𝑌 ) 0
= .
𝐶⊤ 𝑑 𝜏BP (𝑌 ) 1
Once a bifurcation point 𝑌¯ is detected by a sign change 𝜏BP (𝑌𝑗 )𝜏BP (𝑌𝑗+1 ) < 0, it can be approximated
more precisely by the predictor-corrector steps described above with a special step-length adaptation
(see Section 8.1 in [Al-Ge1997]). Namely, one can take the subsequent step lengths as
𝜏BP (𝑌𝑗+1 )
ℎ𝑗+1 := − ℎ𝑗
𝜏BP (𝑌𝑗+1 ) − 𝜏BP (𝑌𝑗 )
until |ℎ𝑗+1 | < ℎmin , which corresponds to the secant method for finding a zero of the function 𝑠 ↦→
𝜏BP (𝑌 (𝑠)).
Finally, it would be desirable to switch solution branches. To this end, we shall consider the case of the
so-called simple bifurcation point, where only two distinct solution curves intersect.
Let 𝑌˜ be an approximation of 𝑌¯ that we are given and 𝑉 (𝑌˜ ) be the first part of the solution of the
augmented system for computing the test function 𝜏BP (𝑌˜ ). As proposed in [Georg2001], one can take
𝑉 (𝑌˜ ) as a predictor direction and do one continuation step starting with (𝑌˜ , 𝑉 (𝑌˜ )) to obtain a point
on a new branch. After this continuation step has been performed successfully and a point on the new
branch has been recovered, one can proceed with usual predictor-corrector steps to trace this branch.
Recently, tools for numerical 𝑃 𝐶 1 -bifurcation have been developed in GetFEM. Let 𝐽 be a matrix
function of a real parameter now defined by
(︂ )︂ (︂ )︂
∇𝐹 (𝑌𝑗 ) ∇𝐹 (𝑌𝑗+1 )
𝐽(𝛼) := (1 − 𝛼) +𝛼 .
𝑇𝑗⊤ ⊤
𝑇𝑗+1
As proposed in [Li-Re2014hal], the following test can be used for detection of a 𝑃 𝐶 1 bifurcation point
between 𝑌𝑗 and 𝑌𝑗+1 :
(︂ )︂
𝐽(𝛼) 𝐵
𝑀 (𝛼) :=
𝐶⊤ 𝑑
(︂ )︂ (︂ )︂
𝑉 (𝛼) 0
𝑀 (𝛼) = .
𝜏BP (𝛼) 1
det 𝐽(𝛼)
𝜏BP (𝛼) =
det 𝑀 (𝛼)
provided that det 𝑀 (𝛼) is non-zero. Hence if 𝐵, 𝐶 and 𝑑 are chosen so that det 𝑀 (𝛼) is non-zero
whenever det 𝐽(𝛼) is zero, then the sign changes of det 𝐽(𝛼) are characterised by passings of 𝜏BP (𝛼)
through 0 whereas the sign changes of det 𝑀 (𝛼) by sign changes of 𝜏BP (𝛼) caused by singularities.
To conclude, the sign of det 𝐽(0) det 𝐽(1) is determined by following the behaviour of 𝜏BP (𝛼) and
monitoring the sign changes of det 𝐽(𝛼) when 𝛼 passes through [0, 1].
As justified in [Li-Re2014hal], 𝐵, 𝐶 and 𝑑 can be chosen randomly again. The increments 𝛿 of the
current values of 𝛼 are changed adaptively so that singularities of 𝜏BP are treated effectively. After each
calculation of 𝜏BP (𝛼), 𝛿 is set as follows:
⎧
⎨min{2𝛿, 𝛿max }
⎪ if |𝜏BP (𝛼) − 𝜏BP (𝛼 − 𝛿)| < 0.5𝜏fac 𝜏ref ,
𝛿 := max{0.1𝛿, 𝛿min } if |𝜏BP (𝛼) − 𝜏BP (𝛼 − 𝛿)| > 𝜏fac 𝜏ref ,
⎪
𝛿 otherwise,
⎩
where 𝛿max > 𝛿min > 0 and 𝜏fac > 0 are given constants and 𝜏ref := max{|𝜏BP (1) − 𝜏BP (0)|, 10−8 }.
When a 𝑃 𝐶 1 bifurcation point is detected between 𝑌𝑗 and 𝑌𝑗+1 , it is approximated more precisely by
a bisection-like procedure. The obtained approximation lies on the same smooth branch as 𝑌𝑗 , and the
corresponding unit tangent that points out from the corresponding region of smoothness is calculated
too.
Contrary to the smooth case, it is not clear how many branches can emanate from the 𝑃 𝐶 1 bifurcation
point and in which directions they could be sought. For this reason, continuation steps for a whole
sequence of predictor directions are tried out for finding points on new branches.
Denoting 𝑌˜ , 𝑇˜ the approximation of the bifurcation point and the corresponding tangent, respectively,
the predictor directions are taken as follows: For a couple of reference vectors 𝑉˜1 and 𝑉˜2 , one takes ±𝑉
with 𝑉 satisfying
∇𝐹 (𝑌˜ + ℎmin 𝑉˜ )𝑉 = 0, ‖𝑉 ‖𝑤 = 1,
where 𝑉˜ passes through a set of linear combinations of 𝑉˜1 and 𝑉˜2 . The total number of the linear com-
binations is given by 𝑛dir , and the reference vectors are chosen successively according to the following
strategy:
1. One takes 𝑉˜1 := −𝑇˜ and 𝑉˜2 such that
2. Let {𝑇˜1 , . . . 𝑇˜𝑛br } denote the set of unit tangents that correspond to the points from the branches
found so far and that are oriented in the directions of branching from the bifurcation point. Then
𝑉˜1 and 𝑉˜2 are taken successively as different combinations from {𝑇˜1 , . . . 𝑇˜𝑛br }.
3. If all combinations that are available so far have already been used, let 𝑉˜1 be unchanged and take
𝑉˜2 := 𝑉˜2+ with 𝑉˜2+ satisfying
(︁ (︁ 𝑉˜3 )︁)︁ ˜ +
∇𝐹 𝑌˜ + ℎmin 𝑉˜2− + 0.1 𝑉2 = 0, ‖𝑉˜2+ ‖𝑤 = 1.
‖𝑉˜3 ‖𝑤
Here, 𝑉˜2− equals the vector 𝑉˜2 employed previously and 𝑉˜3 is chosen randomly.
The total number of selections of 𝑉˜1 and 𝑉˜2 is given by 𝑛span .
More details on 𝑃 𝐶 1 numerical branching can be found in [Li-Re2015hal].
where parameter_name is the name of the model datum representing 𝜆, sfac represents the scale
factor 𝜅, and ls is the name of the solver to be used for the linear systems incorporated in the process
(e.g., getfem::default_linear_solver<getfem::model_real_sparse_matrix,
getfem::model_real_plain_vector>(model)). The real numbers h_init, h_max,
h_min, h_inc, h_dec denote ℎinit , ℎmax , ℎmin , ℎinc , and ℎdec , the integer maxit is the maximum
number of iterations allowed in the correction and thrit, maxres, maxdiff, mincos, and
maxres_solve denote 𝑙thr , 𝜀, 𝜀′ , 𝑐min , and the target residual value for the linear systems to be
solved, respectively. The non-negative integer noisy determines how detailed information has to
be displayed in the course of the continuation process (the larger value the more details), the integer
singularities determines whether the tools for detection and treatment of singular points have to
be used (0 for ignoring them completely, 1 for detecting limit points, and 2 for detecting and treating
bifurcation points, as well), and the boolean value of non-smooth determines whether only tools
for smooth continuation and bifurcation have to be used or even tools for non-smooth ones do. The
real numbers delta_max, delta_min and thrvar represent 𝛿max , 𝛿min and 𝜏fac , and the integers
ndir and nspan stand for 𝑛dir and 𝑛span , respectively.
Optionally, parameterization by a vector datum is then declared by:
S.set_parametrised_data_names(initdata_name, finaldata_name, currentdata_
˓→name);
Here, the data names initdata_name and finaldata_name should represent 𝑃 0 and 𝑃 1 , respec-
tively. Under currentdata_name, the values of 𝑃 (𝜆) have to be stored, that is, actual values of the
datum the model depends on.
Next, the continuation is initialised by:
S.init_Moore_Penrose_continuation(U, lambda, T_U, T_lambda, h);
where U should be a solution for the value of the parameter 𝜆 equal to lambda so that 𝑌0 =
(U,lambda). During this initialisation, an initial unit tangent 𝑇0 corresponding to 𝑌0 is computed in ac-
cordance with the sign of the initial value T_lambda, and it is returned in T_U, T_lambda. Moreover,
h is set to the initial step size h_init.
Subsequently, one step of the continuation is called by
S.Moore_Penrose_continuation(U, lambda, T_U, T_lambda, h, h0);
After each call, a new point on a solution curve and the corresponding tangent are returned in the vari-
ables U, lambda and T_U, T_lambda. The step size for the next prediction is returned in h. The
size of the current step is returned in the optional argument h0. According to the chosen value of
singularities, the test functions for limit and bifurcation points are evaluated at the end of each
continuation step. Furthermore, if a smooth bifurcation point is detected, the procedure for numerical
bifurcation is performed and an approximation of the branching point as well as tangents to both bi-
furcating curves are saved in the continuation object S. From there, they can easily be recovered with
member functions of S so that one can initialise the continuation to trace either of the curves next time.
Complete examples of use on a smooth problem are shown in the test programs tests/
test_continuation.cc, interface/tests/matlab/demo_continuation.m and
interface/src/scilab/demos/demo_continuation.sce, whereas interface/src/
scilab/demos/demo_continuation_vee.sce and interface/src/scilab/demos/
demo_continuation_block.sce employ also non-smooth tools.
This brick implements some classical hyperelastic constitutive law for large deformation elasticity.
Let Ω be the reference configuration and Ω𝑡 the deformed configuration of an elastic media. Then for
𝑋 ∈ Ω we will denote by Φ(𝑥) = 𝑢(𝑋) + 𝑋 the deformation. the vector field 𝑢 is the displacement
with respect to the initial position.
The Cauchy-Green tensor is defined by
𝐶 = ∇Φ𝑇 ∇Φ
𝐶 = ∇Φ𝑇 ∇Φ = 2𝐸 + 𝐼.
Both tensors 𝐸 and 𝐶 are used to describe finite strain elasticity constitutive laws.
The description of finite strain elasticity constitutive laws often requires the principal invariants of the
deformation tensors:
169
User Documentation, Release 5.4.2
The derivatives of the invariants with respect to the tensor 𝐸 in the direction 𝐻 are:
𝜕𝑖1
(𝐸; 𝐻) = 𝐼 : 𝐻 = tr 𝐻
𝜕𝐸
𝜕𝑖2
(𝐸; 𝐻) = (𝑖1 (𝐸)𝐼 − 𝐸 𝑇 ) : 𝐻 = (tr 𝐸)(tr 𝐻) − 𝐸 𝑇 : 𝐻
𝜕𝐸
𝜕𝑖3
(𝐸; 𝐻) = 𝑖3 (𝐸)(𝐸 −𝑇 ) : 𝐻 = (𝑖2 (𝐸)𝐼 − 𝑖1 (𝐸)𝐸 + 𝐸 2 ) : 𝐻 in 3D.
𝜕𝐸
We will write
𝜕𝑖1
(𝐸) = 𝐼
𝜕𝐸
𝜕𝑖2
(𝐸) = 𝑖1 (𝐸)𝐼 − 𝐸 𝑇
𝜕𝐸
𝜕𝑖3
(𝐸) = 𝑖3 (𝐸)𝐸 −𝑇 .
𝜕𝐸
Let us also recall that
𝜕(𝑀 −1 )
(𝑀 ; 𝐻) = −𝑀 −1 𝐻𝑀 −1
𝜕𝑀
The second derivatives of the invariants are fourth order tensors defined by
𝜕 2 𝑖1
(𝐸) = 0
𝜕𝐸 2
𝜕 2 𝑖2
(𝐸)𝑖𝑗𝑘𝑙 = 𝛿𝑖𝑗 𝛿𝑘𝑙 − 𝛿𝑖𝑙 𝛿𝑗𝑘
𝜕𝐸 2
𝜕 2 𝑖3 −1 −1 −1 −1
(𝐸)𝑖𝑗𝑘𝑙 = 𝑖3 (𝐸)(𝐸𝑗𝑖 𝐸𝑙𝑘 − 𝐸𝑗𝑘 𝐸𝑙𝑖 ).
𝜕𝐸 2
∑︁
The notation 𝐴 : 𝐵 denotes the Frobenius product 𝐴 : 𝐵 = 𝐴𝑖𝑗 𝐵𝑖𝑗 . This product has the following
𝑖𝑗
properties:
The stress in the reference configuration can be describe by the second Piola-Kirchhoff stress tensor
^^ = ∇Φ−1 𝜎∇Φ−𝑡 det ∇Φ where 𝜎 is the Cauchy stress tensor in the deformed configuration Ω𝑡 . An
𝜎
hyper-elastic constitutive law is given by
^ 𝜕 𝜕
𝜎
^= 𝑊 (𝐸) = 2 𝑊 (𝐶)
𝜕𝐸 𝜕𝐶
where 𝑊 is the density of strain energy of the material. The total strain energy is given by
∫︁
ℐ(𝑢) = 𝑊 (𝐸(𝑢))𝑑𝑋
Ω
because in particular
1
𝐷𝐸(𝑢; 𝑣) = (∇𝑢𝑇 ∇𝑣 + ∇𝑣 𝑇 ∇𝑢 + ∇𝑣 𝑇 + ∇𝑣)
2
1
= (∇𝑣 𝑇 (𝐼 + ∇𝑢) + (𝐼 + ∇𝑢𝑇 )∇𝑣)
2
^^ .
and 𝐴 : 𝐵 = 𝐴 : (𝐵 + 𝐵 𝑇 )/2 when A is symmetric which is the case for 𝜎
Another way is to consider the static equilibrium which can be written as follows in the reference con-
figuration:
(︁ )︁
−div (𝐼 + ∇𝑢)𝜎 ^^ = 𝑓.
The displacement 𝑢 is fixed. In order to obtain the tangent matrix, one subsitutes 𝑢 with 𝑢 + ℎ
∫︁
^ 1
(𝐼 + ∇𝑢 + ∇ℎ)𝜎 ^ (𝐸(𝑢) + 𝐸(ℎ) + (∇ℎ𝑇 ∇𝑢 + ∇𝑢𝑇 ∇ℎ)) : ∇𝑣𝑑𝑋 = 𝑙(𝑣)
Ω 2
and considers the linear part w.r.t. ℎ, which is
∫︁
∇ℎ 𝜎 ^^ (𝐸(𝑢)) : ∇𝑣𝑑𝑋+
Ω
∫︁ 2 (︂
𝜕 𝑊 ∇ℎ + ∇ℎ𝑇 + ∇ℎ𝑇 ∇𝑢 + ∇𝑢𝑇 ∇ℎ
)︂
2
: (𝐼 + ∇𝑢𝑇 )∇𝑣𝑑𝑋
Ω 𝜕𝐸 2
which is symmetric w.r.t. 𝑣 and ℎ. It can be rewritten as
∫︁
∇ℎ 𝜎 ^
^ (𝐸(𝑢)) : ∇𝑣 + 𝒜((𝐼 + ∇𝑢𝑇 )∇ℎ) : (𝐼 + ∇𝑢𝑇 )∇𝑣 𝑑𝑋
Ω
2 2
where 𝒜 is the symmetric 3 × 3 × 3 × 3 tensor given by 𝒜𝑖𝑗𝑘𝑙 = (( 𝜕𝜕𝐸𝑊2 )𝑖𝑗𝑘𝑙 + ( 𝜕𝜕𝐸𝑊2 )𝑖𝑗𝑙𝑘 )/2.
𝜆
𝑊 = 𝑖1 (𝐸)2 + 𝜇𝑖1 (𝐸 2 )
2
^
𝜎
^ = 𝜆𝑖1 (𝐸)𝐼 + 2𝜇𝐸
𝒜 = 𝜆𝑖1 (𝐻)𝐼 + 𝜇(𝐻 + 𝐻 𝑇 )
Compressible material.
^^ = 2𝑐1 𝜕𝑗1 (𝐶) + 2𝑐2 𝜕𝑗2 (𝐶) + 2𝑑1 1 − 𝑖3 (𝐶)−1/2 𝜕𝑖3 (𝐶)
(︁ )︁
𝜎
𝜕𝐶 𝜕𝐶 𝜕𝐶
2 2 )︁ 2
(︂(︁ )︂
𝜕 𝑗1 𝜕 𝑗2 −1/2 𝜕 𝑖3 1 −3/2 𝜕𝑖3 𝜕𝑖3
ℬ = 4𝑐1 (𝐶) + 4𝑐2 (𝐶) + 4𝑑1 1 − 𝑖 3 (𝐶) (𝐶) + 𝑖3 (𝐶) (𝐶) ⊗ (𝐶)
𝜕𝐶 2 𝜕𝐶 2 𝜕𝐶 2 2 𝜕𝐶 𝜕𝐶
𝒜𝑖𝑗𝑘𝑙 = (ℬ𝑖𝑗𝑘𝑙 + ℬ𝑗𝑖𝑘𝑙 )/2
Incompressible material.
The incompressibility constraint 𝑖3 (𝐶) = 1 is handled with a Lagrange multiplier 𝑝 (the pressure)
^
^ = −𝑝∇Φ∇Φ−𝑇 det ∇Φ
constraint: 𝜎 = −𝑝𝐼 ⇒ 𝜎
1 − 𝑖3 (∇Φ) = 0
∫︁
− (det ∇Φ − 1)𝑞𝑑𝑋 = 0 ∀𝑞
Ω0
∫︁
𝐵=− 𝑝(∇Φ)−𝑇 det ∇Φ : ∇𝑣𝑑𝑋
Ω0
∫︁
𝑝(∇Φ)−𝑇 (∇ℎ)𝑇 (∇Φ)−𝑇 det ∇Φ : ∇𝑣𝑑𝑋 − 𝑝(∇Φ)−𝑇 (det ∇Φ(∇Φ)−𝑇 : ∇ℎ) : ∇𝑣 𝑑𝑋
(︀ )︀
𝐾=
∫︁Ω0 ∫︁
−𝑇 −1
= 𝑇
𝑝(∇ℎ ∇Φ ) : (∇Φ ∇𝑣) det ∇Φ𝑑𝑋 − 𝑝(∇Φ−𝑇 : ∇ℎ)(∇Φ−𝑇 : ∇𝑣) det ∇Φ𝑑𝑋
Ω0 Ω0
Ciarlet-Geymonat law
𝜇 𝜆 𝜇 𝜇 𝜆
𝑊 = 𝑎 𝑖1 (𝐶) + ( − 𝑎)𝑖2 (𝐶) + ( − + 𝑎)𝑖3 (𝐶) − ( + ) log det(𝐶)
2 4 2 2 4
with 𝜆, 𝜇 the Lame coefficients and max(0, 𝜇2 − 𝜆4 ) < 𝑎 < 𝜇
2 (see [ciarlet1988]).
𝑖2 (𝐶)
𝑊 = (𝑎𝑖1 (𝐶) + 𝑏𝑖3 (𝐶)1/2 + 𝑐 + 𝑑)𝑛
𝑖3 (𝐶)
𝜕
∑︁ 𝜕𝑊 𝜕𝑖𝑗 (𝐶)
𝜕2
∑︁ ∑︁ 𝜕2𝑊 𝜕𝑖𝑘 (𝐶) 𝜕𝑖𝑗 (𝐶)
Since 𝜕𝐶 𝑊 (𝐶) = , and 𝜕𝐶 2 𝑊 (𝐶) = ⊗ +
𝜕𝑖𝑗 (𝐶) 𝜕𝐶 𝜕𝑖𝑗 (𝐶)𝜕𝑖𝑘 (𝐶) 𝜕𝐶 𝜕𝐶
𝑗 𝑗 𝑘
∑︁ 𝜕𝑊 𝜕 2 𝑖𝑗 (𝐶)
we must compute the derivatives of the strain energy function with respect to the
𝜕𝑖𝑗 (𝐶) 𝜕𝐶 2
𝑗
Cauchy-Green tensor invariants (we don’t need to compute the invariants derivatives with respect to 𝐸
𝜕𝑖 𝜕𝑖
since 𝜕𝐸𝑗 (𝐶; 𝐻) = 2 𝜕𝐶𝑗 (𝐶; 𝐻)) :
𝜕𝑊 2
𝜕 2 𝑖1 (𝐶)
= 𝑛(𝑛 − 1)𝐴2 𝑍 𝑛−2
𝜕𝑊 2 𝑐 𝑛−2
𝜕𝑖1 (𝐶)𝜕𝑖2 (𝐶) = 𝑛(𝑛 − 1)𝐴 𝑖3 (𝐶) 𝑍
𝜕𝑊 2 𝑏 𝑐𝑖2 (𝐶) 𝑛−2
𝜕𝑖1 (𝐶)𝜕𝑖3 (𝐶) = 𝑛(𝑛 − 1)𝐴( 2𝑖3 (𝐶)1/2 − 𝑖3 (𝐶)2 )𝑍
𝜕𝑊 2 𝑐2 𝑛−2
𝜕 2 𝑖2 (𝐶)
= 𝑛(𝑛 − 1) 𝑖3 (𝐶) 2𝑍
2
𝜕𝑊 𝑏 𝑐𝑖2 (𝐶) 𝑛−2 − 𝑛 𝑐2 𝑍 𝑛−1
𝜕𝑖2 (𝐶)𝜕𝑖3 (𝐶) = 𝑛(𝑛 − 1)( 2𝑖3 (𝐶)1/2 − 𝑖3 (𝐶)2 )𝑍 𝑖3 (𝐶)2
𝜕𝑊 2 𝑏 𝑐𝑖2 (𝐶) 2 𝑛−2 𝑏 𝑐𝑖2 (𝐶) 𝑛−1
𝜕𝑖3 (𝐶)2
= 𝑛(𝑛 − 1)( 2𝑖 (𝐶)1/2 − 𝑖3 (𝐶)2 ) 𝑍 + 𝑛(− 4𝑖 (𝐶) 3/2 + 2 𝑖3 (𝐶)4 )𝑍
3 3
All previous models are valid in volumic domains. Corresponding plane strain 2D models can be ob-
tained by restricting the stress tensor and the fourth order tensor 𝒜 to their plane components.
This brick represents a large strain elasticity problem. It is defined in the files getfem/
getfem_nonlinear_elasticity.h and getfem/getfem_nonlinear_elasticity.
cc. The function adding this brick to a model is
ind = getfem::add_nonlinear_elasticity_brick
(md, mim, varname, AHL, dataname, region = -1);
getfem::SaintVenant_Kirchhoff_hyperelastic_law AHL;
getfem::Ciarlet_Geymonat_hyperelastic_law AHL;
getfem::Mooney_Rivlin_hyperelastic_law AHL(compressible, neohookean);
getfem::plane_strain_hyperelastic_law AHL(pAHL);
getfem::generalized_Blatz_Ko_hyperelastic_law AHL;
The Saint-Venant Kirchhoff law is a linearized law defined with the two Lame coefficients, Ciarlet
Geymonat law is defined with the two Lame coefficients and an additional coefficient (𝜆, 𝜇, 𝑎).
The Mooney-Rivlin law accepts two optional flags, the first one determines if the material will be com-
pressible (𝑑1 ̸= 0) and the second one determines if the material is neo Hookean (𝑐2 = 0). Depending
on these flags one to three coefficients may be necessary. By default it is defined as incompressible and
non neo Hookean, thus it needs two material coefficients (𝑐1 , 𝑐2 ). In this case, it is to be used with the
large strain incompressibility condition.
The plane strain hyperelastic law takes a pointer on a hyperelastic law as a parameter and performs a 2D
plane strain approximation.
md is the model variable, mim the integration method, varname the string being the name of the
variable on which the term is added, dataname the string being the name of the data in the model
representing the coefficients of the law (can be constant or describe on a finite element method) and
region is the region on which the term is considered (by default, all the mesh).
The program nonlinear_elastostatic.cc in tests directory and
demo_nonlinear_elasticity.m in interface/tests/matlab directory are some
examples of use of this brick with or without an incompressibility condition.
Note that the addition of a new hyperelastic constitutive law consists in furnishing the expression
of the strain energy, the stress tensor and the derivative of the stress tensor. See the file getfem/
getfem_nonlinear_elasticity.cc for more details. In particular, expression of the invariants
and their derivatives are available.
A function which computes the Von Mises or Tresca stresses is also available:
VM = compute_Von_Mises_or_Tresca
(md, varname, AHL, dataname, mf_vm, VM, tresca)
It returns a vector of the degrees of freedom of the Von Mises or Tresca stress on the finite element
method mf_vm. tresca is a boolean whose value should be true for Tresca stress and false for
Von Mises stress.
det(𝐼 + ∇𝑢) = 1,
A Lagrange multiplier representing the pressure is introduced in a mixed formulation. The function
adding this brick to a model is
ind = add_nonlinear_incompressibility_brick
(md, mim, varname, multname, region = -1)
where md is the model, mim the integration method, varname the variable of the model on which the
incompressibility condition is added, multanme the multiplier variable corresponding to the pressure
(be aware that at least a linear Ladyzhenskaja-Babuska-Brezzi inf-sup condition is satisfied between the
f.e.m. of the variable and the one of the multiplier). region is an optional parameter correponding to
the mesh region on which the term is considered (by default, all the mesh).
The generic weak form language (GWFL) gives access to the hyperelastic potential and constitutive laws
implemented in GetFEM. This allows to directly use them in the language, for instance using a generic
assembly brick in a model or for interpolation of certain quantities (the stress for instance).
Here is the list of nonlinear operators in the language which can be useful for nonlinear elasticity:
The potentials:
Note that the derivatives with respect to the material parameters have not been implemented apart for the
Saint Venant Kirchhoff hyperelastic law. Therefore, it is not possible to make the parameter depend on
other variables of a model (derivatives are not necessary complicated to implement but for the moment,
only a wrapper with old implementations has been written).
Note that the coupling of models is to be done at the weak formulation level. In a general way, it is
recommended not to use the potential to define a problem. Main couplings cannot be obtained at the
potential level. Thus the use of potential should be restricted to the actual computation of the potential.
An example of use to add a Saint Venant-Kirchhoff hyperelastic term to a variable u in a model or a
ga_workspace is given by the addition of the following assembly string:
"((Id(meshdim)+Grad_u)*(Saint_Venant_Kirchhoff_PK2(Grad_u,[lambda;
˓→mu]))):Grad_Test_u"
Note that in that case, lambda and mu have to be declared data of the model/ga_workspace. It is of
course possible to replace them by explicit constants or expressions depending on several data.
Concerning the incompressible Mooney-Rivlin law, it has to be completed by an incompressibility term.
For instance by adding the following incompressibility brick:
This brick just adds the term p*(1-Det(Id(meshdim)+Grad_u)) if p is the multiplier and u the
variable which represents the displacement.
The addition of an hyperelastic term to a model can also be done thanks to the following function:
where md is the model, mim the integration method, varname the variable of the model rep-
resenting the large strain displacement, lawname is the constitutive law name which could
be Saint_Venant_Kirchhoff, Generalized_Blatz_Ko, Ciarlet_Geymonat,
Incompressible_Mooney_Rivlin, Compressible_Mooney_Rivlin,
Incompressible_Neo_Hookean, Compressible_Neo_Hookean,
Compressible_Neo_Hookean_Bonet or Compressible_Neo_Hookean_Ciarlet.
params is a string representing the parameters of the law defined as a small vector or a vector field.
The Von Mises stress can be interpolated with the following function:
where md is the model, varname the variable of the model representing the large strain displacement,
lawname is the constitutive law name (see previou brick), params is a string representing the pa-
rameters of the law, mf_vm a (preferably discontinuous) Lagrange finite element method on which
the interpolation will be done and VM a vector of type model_real_plain_vector in which the
interpolation will be stored.
We present a short introduction to small strain plasticity. We refer mainly to [SI-HU1998] and
[SO-PE-OW2008] for a more detailed presentation.
Let Ω ⊂ IR3 be the reference configuration of a deformable body and 𝑢 : Ω → IR3 be the displacement
field. Small strain plasticity is based on the additive decomposition of the small strain tensor 𝜀(𝑢) =
∇𝑢 + ∇𝑢𝑇
in
2
𝜀(𝑢) = 𝜀𝑒 + 𝜀𝑝
where 𝜀𝑒 is the elastic part of the strain tensor and 𝜀𝑝 the plastic one.
We consider
𝛼 : Ω → IRd𝛼 ,
a vector field of 𝑑𝛼 strain type internal variables (𝑑𝛼 = 0 if no internal variables are considered). We
consider also a free energy potential
𝜓(𝜀𝑒 , 𝛼),
179
User Documentation, Release 5.4.2
𝜎 : 𝜀˙𝑝 − 𝐴.𝛼˙ ≥ 0.
In the case of linearized elasticity, one has 𝜓 𝑒 (𝜀𝑒 ) = 12 (𝒜𝜀𝑒 ) : 𝜀𝑒 where 𝒜 is the fourth order elasticity
tensor. For isotropic linearized elasticity this expression reduces to 𝜓 𝑒 (𝜀𝑒 ) = 𝜇dev(𝜀𝑒 ) : dev(𝜀𝑒 ) +
1 𝑒 2
2 𝐾(tr(𝜀 )) where 𝜇 is the shear modulus and 𝐾 = 𝜆 + 2𝜇/3 is the bulk modulus.
Plastic yielding is supposed to occur when the stress attains a critical value. This limit is determined by
a yield function 𝑓 (𝜎, 𝐴) and the condition
𝑓 (𝜎, 𝐴) ≤ 0.
The surface 𝑓 (𝜎, 𝐴) = 0 is the yield surface where the plastic deformation may occur.
Let us also consider the plastic potential Ψ(𝜎, 𝐴), (convex with respect to its both variables) which
determines the plastic flow direction in the sense that the flow rule is defined as
𝜕Ψ 𝜕Ψ
𝜀˙𝑝 = 𝛾 (𝜎, 𝐴), 𝛼˙ = −𝛾 (𝜎, 𝐴),
𝜕𝜎 𝜕𝐴
with the additional complementarity condition
The variable 𝛾 is called the plastic multiplier. Note that when 𝜓(𝜀𝑒 , 𝛼), 𝑓 (𝜎, 𝐴) or Ψ(𝜎, 𝐴) are
not differentiable, subdifferentials have to be used. Associated plasticity corresponds to the choice
Ψ(𝜎, 𝐴) = 𝑓 (𝜎, 𝐴).
The weak formulation of a dynamic elastoplastic problem can be written, for an arbitrary kinematically
admissible test function 𝑣, as follows:
⃒ ∫︀ ∫︀ ∫︀
⃒
⃒ Ω 𝜌¨𝑢 · 𝑣 + 𝜎 : ∇𝑣𝑑𝑥 = Ω 𝑓 𝑣𝑑𝑥
˙ + Γ𝑁 𝑔 𝑣𝑑𝑥,
˙
⃒ 𝑢(0, 𝑥) = 𝑢0 (𝑥), 𝑢(0)
˙ = v0 (𝑥),
⃒ 𝜀𝑝 (0, 𝑥) = 𝜀𝑝 , 𝛼(0, 𝑥) = 𝛼0 ,
⃒
0
for 𝑢0 , v0 , 𝜀𝑝0 , 𝛼0 being initial values and 𝑓 and 𝑔 being prescribed forces in the interior of domain Ω and
on the part of the boundary Γ𝑁 .
Note that plasticity models are often applied on quasi-static problems which correspond to the term 𝜌¨
𝑢
being neglected.
Given a time step Δ𝑡 = 𝑡𝑛+1 − 𝑡𝑛 , from time 𝑡𝑛 to 𝑡𝑛+1 , we will denote in the sequel 𝑢𝑛 , 𝜀𝑝𝑛 and 𝛼𝑛 the
approximations at time 𝑡𝑛 of 𝑢(𝑡𝑛 ), 𝜀𝑝𝑛 (𝑡𝑛 ) and 𝛼(𝑡𝑛 ) respectively. These approximations correspond to
the chosen time integration scheme (for instance one of the proposed schemes in The model tools for the
integration of transient problems) which can be different than the time integration scheme used for the
integration of the flow rule (see below).
The plastic flow rule has to be integrated with its own time integration scheme. Among standards
schemes, the backward Euler scheme, the 𝜃-scheme (or generalized trapezoidal rule) and the generalized
mid-point scheme are the most commonly used in that context. We make here the choice of the 𝜃-scheme
(𝜃 = 1 corresponds to the backward Euler scheme as a special case).
Let 𝑢𝑛+1 be the displacement at the considered time step and 𝑢𝑛 at the previous one.
The 𝜃-scheme for the integration of the plastic flow rules reads as
𝜕Ψ 𝜕Ψ
𝜀𝑝𝑛+1 − 𝜀𝑝𝑛 = (1 − 𝜃)Δ𝑡𝛾𝑛 (𝜎𝑛 , 𝐴𝑛 ) + 𝜃Δ𝑡𝛾𝑛+1 (𝜎𝑛+1 , 𝐴𝑛+1 ), (26.1)
𝜕𝜎 𝜕𝜎
𝜕Ψ 𝜕Ψ
𝛼𝑛+1 − 𝛼𝑛 = −(1 − 𝜃)Δ𝑡𝛾𝑛 (𝜎𝑛 , 𝐴𝑛 ) − 𝜃Δ𝑡𝛾𝑛+1 (𝜎𝑛+1 , 𝐴𝑛+1 ), (26.2)
𝜕𝐴 𝜕𝐴
with the complementary condition
where 0 < 𝜃 ≤ 1 is the parameter of the 𝜃-scheme. We exclude 𝜃 = 0 because we will not consider
explicit integration of plasticity. Let us recall that 𝜃 = 1 corresponds to the backward Euler scheme and
𝜃 = 1/2 to the Crank-Nicolson scheme (or trapezoidal rule) which is a second order consistent scheme.
Note that the complementarity condition for the quantities at time step 𝑛 is prescribed at the previous
time step (𝜎𝑛 , 𝛼𝑛 , and 𝛾𝑛 are supposed to be already determined).
A solution would be to solve the whole problem with all the unknows, that is
𝑢𝑛+1 , 𝛾𝑛+1 , 𝜀𝑝𝑛+1 and 𝐴𝑛+1 . This is of course possible but would be a rather expensive strategy
because of the resulting high number of degrees of freedom. A classical strategy (the return mapping
one for instance, see [SO-PE-OW2008] or the closest point projection one) consist in integrating locally
the plastic flow on each Gauss point of the considered integration method separately, or more precisely
to consider on each Gauss point the maps
E 𝑝 : (𝑢𝑛+1 , 𝜁𝑛 , 𝜂𝑛 ) ↦→ 𝜀𝑝𝑛+1
A : (𝑢𝑛+1 , 𝜁𝑛 , 𝜂𝑛 ) ↦→ 𝛼𝑛+1
𝜕Ψ
𝜁𝑛 = 𝜀𝑝𝑛 + (1 − 𝜃)Δ𝑡𝛾𝑛 (𝜎𝑛 , 𝐴𝑛 ),
𝜕𝜎
𝜕Ψ
𝜂𝑛 = 𝛼𝑛 − (1 − 𝜃)Δ𝑡𝛾𝑛 (𝜎𝑛 , 𝐴𝑛 )
𝜕𝐴
This means in particular that (𝜀𝑝𝑛+1 , 𝛼𝑛+1 ) = (E 𝑝 (𝑢𝑛+1 , 𝜁𝑛 , 𝜂𝑛 ), A (𝑢𝑛+1 , 𝜁𝑛 , 𝜂𝑛 )) is the solution to
equations (26.1) and (26.2). Both these maps and their tangent moduli (usually called consistent tangent
moduli) are then used in the global solve of the problem with a Newton method and for 𝑢𝑛+1 the unique
remaining variable. The advantage of the return mapping strategy is that the unique variable of the
global solve is the displacement 𝑢𝑛+1 . A nonlinear solve on each Gauss point is often necessary which
is usualy performed with a local Newton method.
In GetFEM we propose both the return mapping strategy and also an alternative strategy developed
below which is mainly inspired from [PO-NI2016], [SE-PO-WO2015] and [HA-WO2009] and allow
more simple tangent moduli. It consists in keeping (a multiple of) 𝛾𝑛+1 as an additional unknown with
respect to 𝑢𝑛+1 . As we will see, this will allow a more generic treatment of the yield functions, the price
for the simplicity being this additional unknown scalar field.
First, we consider an additional (and optional) given function 𝛼(𝜎𝑛+1 , 𝐴𝑛+1 ) > 0 whose interest will
appear later on (it will allow simple local inverses) and the new unknown scalar field
𝛾𝑛+1
𝜉𝑛+1 = ,
𝛼(𝜎𝑛+1 , 𝐴𝑛+1 )
so that our two main unknows are now 𝑢𝑛+1 and 𝜉𝑛+1 . The discretized plastic flow rule integration now
reads:
𝜕Ψ 𝜕Ψ
𝜀𝑝𝑛+1 − 𝜀𝑝𝑛 = (1 − 𝜃)𝛼(𝜎𝑛 , 𝐴𝑛 )Δ𝑡𝜉𝑛 (𝜎𝑛 , 𝐴𝑛 ) + 𝜃𝛼(𝜎𝑛+1 , 𝐴𝑛+1 )Δ𝑡𝜉𝑛+1 (𝜎𝑛+1 , 𝐴𝑛+1 ),
𝜕𝜎 𝜕𝜎
(26.3)
𝜕Ψ 𝜕Ψ
𝛼𝑛+1 − 𝛼𝑛 = (1 − 𝜃)𝛼(𝜎𝑛 , 𝐴𝑛 )Δ𝑡𝜉𝑛 (𝜎𝑛 , 𝐴𝑛 ) + 𝜃𝛼(𝜎𝑛+1 , 𝐴𝑛+1 )Δ𝑡𝜉𝑛+1 (𝜎𝑛+1 , 𝐴𝑛+1 ),
𝜕𝐴 𝜕𝐴
(26.4)
𝑓 (𝜎𝑛+1 , 𝐴𝑛+1 ) ≤ 0, 𝜉𝑛+1 ≥ 0, 𝑓 (𝜎𝑛+1 , 𝐴𝑛+1 )𝜉𝑛+1 = 0. (26.5)
For 𝑢𝑛+1 and 𝜉𝑛+1 be given, we define the two maps
where the pair (𝜀𝑝𝑛+1 , 𝛼𝑛+1 ) = (E˜𝑝 (𝑢𝑛+1 , 𝜃𝜉𝑛+1 , 𝜁𝑛 , 𝜂𝑛 ), A˜(𝑢𝑛+1 , 𝜃𝜉𝑛+1 , 𝜁𝑛 , 𝜂𝑛 )) is the solution to
equations (26.3), (26.4) (without the consideration of (26.5)). We will see later, that, at least for simple
isotropic plastic flow rules, these maps have a simple expression, even sometimes a linear one with
respect to 𝑢𝑛+1 .
Still 𝑢𝑛+1 and 𝜉𝑛+1 be given the stress 𝜎𝑛+1 reads
𝜕𝜓 𝑒
𝜎𝑛+1 = (𝜀(𝑢𝑛+1 ) − 𝜀𝑝𝑛+1 ).
𝜕𝜀𝑒
𝜕𝜓 𝑝
𝐴𝑛+1 = (𝛼𝑛+1 ).
𝜕𝛼
The complementarity equation (26.5) is then prescribed with the use of a well chosen complementarity
function, as in [HA-WO2009] for 𝑟 > 0 such as:
∫︁
(𝜉𝑛+1 − (𝜉𝑛+1 + 𝑟𝑓 (𝜎𝑛+1 , 𝐴𝑛+1 ))+ )𝜆𝑑𝑥 = 0, ∀𝜆
Ω
or
∫︁
(𝑓 (𝜎𝑛+1 + (−𝑓 (𝜎𝑛+1 , 𝐴𝑛+1 ) − 𝜉𝑛+1 /𝑟)+ , 𝐴𝑛+1 ))𝜆𝑑𝑥 = 0, ∀𝜆
Ω
NOTE : The notation Δ𝜉𝑛+1 = Δ𝑡𝜉𝑛+1 is often used in the litterature. The choice here is to preserve
the distinction between the two quantities, mainly because ot the possible use of adaptative time step
: when the time step is changing, the value 𝜉𝑛 has to be multiplied by the new time step, so that it is
preferable to store 𝜉𝑛 instead of Δ𝜉𝑛 when using the 𝜃-scheme.
A plane strain approximation is a 2D problem which corresponds to the deformation of a long cylindrical
object where the strain in the length direction (assumed to be along the 𝑧 axis) is considered small
compared to the ones in the other directions and is neglected. It result in a plane strain tensor of the form
⎛ ⎞
𝜀1,1 𝜀1,2 0
𝜀(𝑢) = ⎝𝜀1,2 𝜀2,2 0⎠ .
0 0 0
We denote
(︂ )︂
𝜀1,1 𝜀1,2
𝜀¯(𝑢) =
𝜀1,2 𝜀2,2
the non neglected components of the strain tensor. In the decomposition of plastic and elastic part of the
strain tensor, we assume
and
The adaptation to the plane strain approximation to plastic model is most of the time an easy task. An
isotropic linearized elastic response reads
𝜎 = 𝜆tr(𝜀(𝑢))𝐼 + 2𝜇(𝜀(𝑢) − 𝜀𝑝 ),
and thus
𝜎 𝜀(𝑢))𝐼¯ + 2𝜇(¯
¯ = 𝜆tr(¯ 𝜀(𝑢) − 𝜀¯𝑝 ),
𝜀(𝑢)) − 2𝜇𝜀𝑝3,3
𝜎3,3 = 𝜆tr(¯
Note that in the common case where isochoric plastic strain is assumed, one has
The plane stress approximation describe generally the 2D membrane deformation of a thin plate. It
consist in prescribing the stress tensor to have only in-plane nonzero components, i.e.
⎛ ⎞
𝜎1,1 𝜎1,2 0
𝜎 = ⎝𝜎1,2 𝜎2,2 0⎠ .
0 0 0
the in-plane components of the stress tensor. For elastoplasticity, it consists generally to apply the 2D
plastic flow rule, prescribing the out-plane components of the stress tensor to be zero with the additionnal
variables 𝜀𝑒1,3 , 𝜀𝑒2,3 , 𝜀𝑒3,3 being unknown (see for instance [SO-PE-OW2008]).
For an isotropic linearized elastic response, one has 𝜎 = 𝜆tr(𝜀𝑒 ) + 2𝜇𝜀𝑒 such that
⎛ 𝑒
𝜀1,1 𝜀𝑒1,2 0
⎞
𝜀𝑒 = ⎝𝜀𝑒1,2 𝜀𝑒2,2 0 ⎠ .
0 0 𝜀𝑒3,3
with
𝜆
𝜀𝑒3,3 = − (𝜀𝑒 + 𝜀𝑒2,2 )
𝜆 + 2𝜇 1,1
so that
2𝜇𝜆
¯ = 𝜆* tr(¯
𝜎 𝜀𝑒 ) + 2𝜇¯
𝜀𝑒 with 𝜆* = (26.6)
𝜆 + 2𝜇
Moreover
(︂ )︂1/2
2 1 2
‖Dev(𝜎)‖ = ‖¯𝜎 ‖ − (tr(¯
𝜎 )) . (26.7)
3
Note that in the case where isochoric plastic strain is assumed, one still has
Tresca : 𝜌(𝜎) ≤ 𝜎𝑦 where 𝜌(𝜎) spectral radius of the Cauchy stress tensor and 𝜎𝑦 the uniaxial yield
stress (which may depend on some hardening internal variables).
√︁
2 1
Von Mises : ‖Dev(𝜎)‖ ≤ 3 𝜎𝑦 where Dev(𝜎) = 𝜎 − 3 tr(𝜎)𝐼 the deviatoric part of 𝜎 and ‖𝜎‖ =
√
𝜎 : 𝜎.
There is no internal variables and we consider an isotropic elastic response. The flow rule reads
Dev(𝜎)
𝜀˙𝑝 = 𝛾
‖Dev(𝜎)‖
√︁
This corresponds to Ψ(𝜎) = 𝑓 (𝜎) = ‖Dev(𝜎)‖ − 23 𝜎𝑦 .
The 𝜃-scheme for the integration of the plastic flow rule reads:
Dev(𝜎𝑛 ) Dev(𝜎𝑛+1 )
𝜀𝑝𝑛+1 − 𝜀𝑝𝑛 = (1 − 𝜃)𝛼(𝜎𝑛 )Δ𝑡𝜉𝑛 + 𝜃𝛼(𝜎𝑛+1 )Δ𝑡𝜉𝑛+1 .
‖Dev(𝜎𝑛 )‖ ‖Dev(𝜎𝑛+1 )‖
𝛾𝑛
Choosing the factor 𝛼(𝜎𝑛 ) = ‖Dev(𝜎𝑛 )‖ and still with 𝜉𝑛 = this gives the equation
𝛼(𝜎𝑛 )
2𝜇‖𝐵‖
1 + 2𝜇𝜃Δ𝑡𝜉𝑛+1 = √︁ ,
2
3 𝜎𝑦
and thus
(︃ √︂ )︃
2 𝜎𝑦
𝜀𝑝𝑛+1 = 𝜁𝑛 + 1− 𝐵.
3 2𝜇‖𝐵‖
𝛽tr(𝐶) ¯ 1
𝜀¯𝑝𝑛+1 = 𝐼 + 𝐶.
𝛼(𝛼 − 2𝛽) 𝛼
Moreover, for the yield condition, expression (26.7) can be used.
We consider an isotropic elastic reponse and the internal variable 𝛼 : Ω → IR being the accumulated
plastic strain which satisfies
√︂
2
𝛼˙ = 𝛾
3
For 𝐻𝑖 the isotropic hardening modulus, the linear hardening consists in
1
𝜓 𝑝 (𝛼) = 𝐻𝑖 𝛼2
2
i.e. 𝐴 = 𝐻𝑖 𝛼 and a uniaxial yield stress defined by
for 𝜎𝑦0 the initial uniaxial yield stress. The yield function (and plastic potential since this is an associated
plastic model) can be defined by
√︂
2 𝑝 2
Ψ(𝜎, 𝐴) = 𝑓 (𝜎, 𝐴) = ‖Dev(𝜎 − 𝐻𝑘 𝜀 )‖ − (𝜎𝑦0 + 𝐴),
3 3
where 𝐻𝑘 is the kinematic hardening modulus. The same computation as in the previous section leads
to
(︂ )︂
˜ 1 1
E (𝑢𝑛+1 , 𝜃Δ𝑡𝜉𝑛+1 , 𝜁𝑛 ) = 𝜁𝑛 +
𝑝
1− (2𝜇Dev(𝜀(𝑢𝑛+1 )) − 2(𝜇 + 𝐻𝑘 /3)𝜁𝑛
2(𝜇 + 𝐻𝑘 /3) 1 + 2(𝜇 + 𝐻𝑘 /3)𝜃Δ𝑡𝜉𝑛+1
√︂
2
A˜(𝑢𝑛+1 , 𝜃Δ𝑡𝜉𝑛+1 , 𝜁𝑛 , 𝜂𝑛 ) = 𝜂𝑛 + 𝜃Δ𝑡𝜉𝑛+1 ‖Dev(𝜎𝑛+1 − 23 𝐻𝑘 𝜀𝑝𝑛+1 )‖
√︂ 3
2
= 𝜂𝑛 + 𝜃Δ𝑡𝜉𝑛+1 ‖2𝜇Dev(𝜀(𝑢𝑛+1 )) − 2(𝜇 + 𝐻𝑘 /3)𝜀𝑝𝑛+1 ‖
√︂ 3
2 𝜃Δ𝑡𝜉𝑛+1
= 𝜂𝑛 + ‖2𝜇Dev(𝜀(𝑢𝑛+1 )) − 2(𝜇 + 𝐻𝑘 /3)𝜁𝑛 ‖
√︂ 3 1 + 2(𝜇 + 𝐻𝑘(︂
/3)𝜃Δ𝑡𝜉𝑛+1 )︂
2 1 1
= 𝜂𝑛 + 1− ‖2𝜇Dev(𝜀(𝑢𝑛+1 )) − 2(𝜇
3 2(𝜇 + 𝐻𝑘 /3) 1 + 2(𝜇 + 𝐻𝑘 /3)𝜃Δ𝑡𝜉𝑛+1
where 𝜁𝑛 and 𝜂𝑛 are defined by
2
𝜁𝑛 = 𝜀𝑝𝑛 + (1 − 𝜃)Δ𝑡𝜉𝑛 (Dev(𝜎𝑛 ) − 𝐻𝑘 𝜀𝑛𝑝 ) = 𝜀𝑝𝑛 + (1 − 𝜃)Δ𝑡𝜉𝑛 2𝜇Dev(𝜀(𝑢𝑛 )) − 2(𝜇 + 𝐻𝑘 /3)𝜀𝑛𝑝 ,
(︀ )︀
3
√︂ √︂
2 2 𝑛 2
𝜂𝑛 = 𝛼𝑛 + (1 − 𝜃) Δ𝑡𝜉𝑛 ‖Dev(𝜎𝑛 ) − 𝐻𝑘 𝜀𝑝 ‖ = 𝛼𝑛 + (1 − 𝜃) Δ𝑡𝜉𝑛 ‖2𝜇Dev(𝜀(𝑢𝑛 )) − 2(𝜇 + 𝐻𝑘 /3)𝜀𝑛𝑝 ‖.
3 3 3
Note that the isotropic hardening modulus do not intervene in E˜𝑝 (𝑢𝑛+1 , 𝜃Δ𝜉, 𝜀𝑝𝑛 ) but only in 𝑓 (𝜎, 𝐴).
Elimination of the multiplier (for the return mapping approach)
1 1−𝛿
Denoting 𝛿 = ,𝛽 = and 𝐵 = 2𝜇Dev(𝜀(𝑢𝑛+1 )) − 2(𝜇 +
1 + 2(𝜇 + 𝐻𝑘 /3)𝜃Δ𝑡𝜉𝑛+1 2(𝜇 + 𝐻𝑘 /3)
𝑝
𝐻𝑘 /3)𝜁𝑛 the expression for 𝜀𝑛+1 and 𝛼𝑛+1 becomes
√︂
𝑝 2 (26.8)
𝜀𝑛+1 = 𝜁𝑛 + 𝛽𝐵, 𝛼𝑛+1 = 𝜂𝑛 + 𝛽‖𝐵‖,
3
and the plastic constraint
√︂
2
𝛿‖𝐵‖ ≤ (𝜎𝑦0 + 𝐻𝑖 𝛼𝑛+1 ).
3
Thus, either we are in the elastic case, i.e. 𝜉𝑛+1 = 0, 𝛿 = 1 and
√︂
2
‖𝐵‖ ≤ (𝜎𝑦0 + 𝐻𝑖 𝜂𝑛 ),
3
√︂
2
or we are in the plastic case and 𝜉𝑛+1 > 0, 𝛿 < 1, 𝛿‖𝐵‖ = (𝜎𝑦0 + 𝐻𝑖 𝛼𝑛+1 ) and (1 − 𝛿) solves the
3
equation
√︂ (︃ √︂ )︃
2 2 𝐻𝑖
‖𝐵‖ − (1 − 𝛿)‖𝐵‖ = 𝜎𝑦0 + 𝐻𝑖 𝜂𝑛 + (1 − 𝛿)‖𝐵‖ ,
3 3 2(𝜇 + 𝐻𝑘 /3)
which leads to
(︃ √︂ )︃
2(𝜇 + 𝐻𝑘 /3) 2
1−𝛿 = ‖𝐵‖ − (𝜎𝑦0 + 𝐻𝑖 𝜂𝑛 )
‖𝐵‖(2𝜇 + 23 (𝐻𝑘 + 𝐻𝑖 )) 3
which directly gives E 𝑝 (𝑢𝑛+1 , 𝜁𝑛 , 𝜂𝑛 ) and A (𝑢𝑛+1 , 𝜁𝑛 , 𝜂𝑛 ) thanks to (26.8). The multiplier 𝜉𝑛+1 being
given by
1 1 1 𝛽
𝜉𝑛+1 = ( − 1) = .
(2(𝜇 + 𝐻𝑘 /3))𝜃Δ𝑡 𝛿 𝜃Δ𝑡 1 − 2(𝜇 + 𝐻𝑘 /3)𝛽
See for instance [GR-ST2015] for the justification of the construction of this flow rule. A Von-Mises
stress criterion together with an isotropic elastic response, no internal variables and a special type of
kinematic hardening is considered with a constraint ‖𝜀𝑝 ‖ ≤ 𝑐3 . The plastic potential and yield function
have the form
)︂⃦ √︂
𝜀𝑝 𝜀𝑝 ⃦
⃦ (︂
⃦ 𝑝 2
Ψ(𝜎) = 𝑓 (𝜎) = ⃦Dev 𝜎 − 𝑐1 𝑝 − 𝑐2 𝜀 − 𝛿 𝑝 ⃦
⃦ − 𝜎𝑦 ,
‖𝜀 ‖ ‖𝜀 ‖ ⃦ 3
𝛿 ≥ 0, ‖𝜀𝑝 ‖ ≤ 𝑐3 , 𝛿(‖𝜀𝑝 ‖ − 𝑐3 ) = 0,
𝜀𝑝
where 𝑐1 , 𝑐2 and 𝑐3 are some physical parameters. Note that has to be understood to be the whole
‖𝜀𝑝 ‖
unit ball for 𝜀𝑝 = 0.
to be done . . .
There are two versions of the generic brick. A first one when the plastic multiplier is kept as a variable
of the problem where the added term is of the form:
∫︁ ∫︁
𝜎𝑛+1 : ∇𝛿𝑢𝑑𝑥 + (𝜉𝑛+1 − (𝜉𝑛+1 + 𝑟𝑓 (𝜎𝑛+1 , 𝐴𝑛+1 ))+ )𝛿𝜉𝑑𝑥 = 0,
Ω Ω
with 𝑟 > 0 having a specific value chosen by the brick (in terms of the elasticity coefficients), and when
the return mapping strategy is selected (plastic multiplier is just a data), just the added term:
∫︁
𝜎𝑛+1 : ∇𝑣𝑑𝑥.
Ω
getfem::add_small_strain_elastoplasticity_brick
(md, mim, lawname, unknowns_type,
const std::vector<std::string> &varnames,
const std::vector<std::string> ¶ms, region = size_type(-1));
where lawname is the name of an implemented plastic law, unknowns_type indicates the choice between
a discretization where the plastic multiplier is an unknown of the problem or (return mapping approach)
just a data of the model stored for the next iteration. Remember that in both cases, a multiplier is stored
anyway. varnames is a set of variable and data names with length which may depend on the plastic law
(at least the displacement, the plastic multiplier and the plastic strain). params is a list of expressions
for the parameters (at least elastic coefficients and the yield stress). These expressions can be some data
names (or even variable names) of the model but can also be any scalar valid expression of GWFL, the
generic weak form language (such as “1/2”, “2+sin(X[0])”, “1+Norm(v)” . . . ). The last two parameters
optionally provided in params are the theta parameter of the theta-scheme (generalized trapezoidal rule)
used for the plastic strain integration and the time-step‘dt‘. The default value for theta if omitted is 1,
which corresponds to the classical Backward Euler scheme which is first order consistent. theta=1/2
corresponds to the Crank-Nicolson scheme (trapezoidal rule) which is second order consistent. Any
value between 1/2 and 1 should be a valid value. The default value of dt is ‘timestep’ which simply
indicates the time step defined in the model (by md.set_time_step(dt)). Alternatively it can be any
expression (data name, constant value . . . ). The time step can be altered from one iteration to the next
one. region is a mesh region.
The available plasticity laws are:
• “Prandtl Reuss” (or “isotropic perfect plasticity”). Isotropic elasto-plasticity with no hardening.
The variables are the displacement, the plastic multiplier and the plastic strain. The displace-
ment should be a variable and have a corresponding data having the same name preceded by
“Previous_” corresponding to the displacement at the previous time step (typically “u” and “Pre-
vious_u”). The plastic multiplier should also have two versions (typically “xi” and “Previous_xi”)
the first one being defined as data if unknowns_type = DISPLACEMENT_ONLY or as a variable
if unknowns_type = DISPLACEMENT_AND_PLASTIC_MULTIPLIER. The plastic strain should
represent a n x n data tensor field stored on mesh_fem or (preferably) on an im_data (correspond-
ing to mim). The data are the first Lame coefficient, the second one (shear modulus) and the
uniaxial yield stress. IMPORTANT: Note that this law implements the 3D expressions. If it is
used in 2D, the expressions are just transposed to the 2D. For the plane strain approximation, see
below.
• “plane strain Prandtl Reuss” (or “plane strain isotropic perfect plasticity”) The same law as the
previous one but adapted to the plane strain approximation. Can only be used in 2D.
• “Prandtl Reuss linear hardening” (or “isotropic plasticity linear hardening”). Isotropic elasto-
plasticity with linear isotropic and kinematic hardening. An additional variable compared to
“Prandtl Reuss” law: the accumulated plastic strain. Similarly to the plastic strain, it is only
stored at the end of the time step, so a simple data is required (preferably on an im_data). Two
additional parameters: the kinematic hardening modulus and the isotropic one. 3D expressions
only.
• “plane strain Prandtl Reuss linear hardening” (or “plane strain isotropic plasticity linear harden-
ing”). The same law as the previous one but adapted to the plane strain approximation. Can only
be used in 2D.
IMPORTANT : remember that small_strain_elastoplasticity_next_iter has to be called at the end of each
time step, before the next one (and before any post-treatment : this sets the value of the plastic strain and
plastic multiplier).
Additionaly, the following function allow to pass from a time step to another for the small strain plastic
brick:
getfem::small_strain_elastoplasticity_next_iter
(md, mim, lawname, unknowns_type,
const std::vector<std::string> &varnames,
const std::vector<std::string> ¶ms, region = size_type(-1));
The parameters have to be exactly the same as the ones of the add_small_strain_elastoplasticity_brick,
so see the documentation of this function for any explanations. Basically, this brick computes the plastic
strain and the plastic multiplier and stores them for the next step. Additionaly, it copies the computed
displacement to the data that stores the displacement of the previous time step (typically “u” to “Previ-
ous_u”). It has to be called before any use of compute_small_strain_elastoplasticity_Von_Mises.
The function
getfem::compute_small_strain_elastoplasticity_Von_Mises
(md, mim, lawname, unknowns_type,
const std::vector<std::string> &varnames,
const std::vector<std::string> ¶ms,
const mesh_fem &mf_vm, model_real_plain_vector &VM,
region = size_type(-1));
computes the Von Mises stress field with respect to a small strain elastoplasticity term, approximated
on mf_vm, and stores the result into VM. All other parameters have to be exactly the same as for
add_small_strain_elastoplasticity_brick. Remember that small_strain_elastoplasticity_next_iter has to
be called before any call of this function.
26.4.2 A specific brick based on the low-level generic assembly for perfect plas-
ticity
This is an previous version of a elastoplasticity brick which is restricted to isotropic perfect plasticity
and is based on the low-level generic assembly. Its specificity which could be interesting for testing is
that the flow rule is integrated on finite element nodes (not on Gauss points).
The function adding this brick to a model is:
getfem::add_elastoplasticity_brick
(md, mim, ACP, varname, previous_varname, datalambda, datamu,
˓→datathreshold, datasigma, region);
where:
• varname represents the main displacement unknown on which the brick is added (u).
• previous_varname is the displacement at the previous time step.
• datalambda and datamu are the data corresponding to the Lame coefficients.
• datathreshold represents the plastic threshold of the studied material.
• datasigma represents the stress constraint values supported by the material. It should be
composed of 2 iterates for the time scheme needed for the Newton algorithm used. Note that
the finite element method on which datasigma is defined should be able to represent the
derivative of varname.
• ACP corresponds to the type of projection to be used. It has an ab-
stract_constraints_projection type and for the moment, only exists the VM_projection
corresponding to the Von Mises one.
Be careful: datalambda, datamu and datathreshold could be constants or described on the
same finite element method.
This function assembles the tangent matrix and the right hand side vector which will be solved using a
Newton algorithm.
Additionaly, The function:
getfem::elastoplasticity_next_iter
(md, mim, varname, previous_varname, ACP, datalambda, datamu,
˓→datathreshold, datasigma);
computes the new stress constraint values supported by the material after a load or an unload (once a
solve has been done earlier) and upload the variables varname and datasigma as follows:
Then, 𝑢𝑛 and 𝜎 𝑛 contains the new values computed and one can restart the process.
The function:
getfem::compute_elastoplasticity_Von_Mises_or_Tresca
(md, datasigma, mf_vm, VM, tresca=false);
computes the Von Mises (or Tresca if tresca = true) criterion on the stress tensor stored in
datasigma . The stress is evaluated on the mesh_fem mf_vm and stored into the vector VM. Of course,
this function can be used if and only if the previous function elastoplasticity_next_iter has
been called earlier.
The function:
getfem::compute_plastic_part
(md, mim, mf_pl, varname, previous_varname, ACP, datalambda, datamu,
˓→datathreshold, datasigma, Plast);
computes on mf_pl the plastic part of the material, that could appear after a load and an unload, into
the vector Plast.
Note that datasigma should be the vector containing the new stress constraint values, i.e. after a load
or an unload of the material.
This section present a set of bricks facilitating the use of an ALE formulation for rotating bodies having
a rotational symmetry (typically a train wheel).
This strategy consists in adopting an intermediary description between an Eulerian and a Lagrangian
ones for a rotating body having a rotational symmetry. This intermediary description consist in
a rotating axes with respect to the reference configuration. See for instance [Dr-La-Ek2014] and
[Nackenhorst2004].
It is supposed that the considered body is submitted approximately to a rigid body motion
and may have additonal deformation (exptected smaller) with respect to this rigid motion, where 𝑅(𝑡) is
a rotation matrix
⎛ ⎞
cos(𝜃(𝑡)) sin(𝜃(𝑡)) 0
𝑅(𝑡) = ⎝ − sin(𝜃(𝑡)) cos(𝜃(𝑡)) 0 ⎠ ,
0 0 1
and 𝑍(𝑡) is a translation. Note that, in order to be consistent with a positive translation for a positive
angle for a rolling contact, the rotation is clockwise. This illustrated in the following figure:
Note that the description is given for a three-dimensional body. For two-dimensional bodies, the third
axes is neglected so that 𝑅(𝑡) is a 2 × 2 rotation matrix. Let us denote 𝑟(𝑡) the rotation:
⎛ ⎞
0 1 0
𝑟(𝑡, 𝑋) = 𝑅(𝑡)𝑋, and 𝐴 = ⎝ −1 0 0 ⎠ .
0 0 0
193
User Documentation, Release 5.4.2
We have then
𝑟(𝑡, ˙
˙ 𝑋) = 𝜃𝐴𝑅(𝑡)𝑋
If 𝜙(𝑡, 𝑋) is the deformation of the body which maps the reference configuration Ω0 to the deformed
configuration Ω𝑡 at time 𝑡, the ALE description consists in the decomposition of the deformation of the
cylinder in
𝜙(𝑡,
¯ 𝑋) ¯ = 𝜙(𝑋) − 𝑍(𝑡)
Thanks to the rotation symmetry of the reference configuration Ω0 :, we note that Ω̄0 = 𝑟(𝑡, Ω0 ) is
independant of 𝑡 and will serve as the new reference configuration. This is illustrated in the following
figure:
The denomination ALE of the method is justified by the fact that Ω̄0 is an intermediate configuration
which is of Euler type for the rigid motion and a Lagrangian one for the additional deformation of the
solid. If we denote
𝑢 ¯ = 𝜙(𝑡,
¯(𝑡, 𝑋) ¯ 𝑋) ¯ −𝑋
¯
the displacement with respect to this intermediate configuration, the advantage is that if this additional
displacement with respect to the rigid body motion is small, it is possible to use a small deformation
model (for instance linearized elasticity).
Due to the objectivity properties of standard constitutive laws, the expression of these laws in the inter-
mediate configuration is most of the time identical to the expression in a standard reference configuration
194 Chapter 27. ALE Support for object having a large rigid body motion
User Documentation, Release 5.4.2
except for the expression of the time derivative which are modified because the change of coordinate is
nonconstant in time :
𝜕𝜙 𝜕 𝜙¯ ˙ 𝜙𝐴 ¯ + 𝑍(𝑡),
˙
= + 𝜃∇ ¯ 𝑋
𝜕𝑡 𝜕𝑡
𝜕2𝜙 𝜕 2 𝜙¯ ˙ 𝜕 𝜙¯ 𝐴𝑋 ¯ + 𝜃˙2 div((∇𝜙𝐴 ¯ ⊗ (𝐴𝑋))¯ + 𝜃∇ ¨ 𝜙𝐴 ¯ + 𝑍(𝑡).
¨
= + 2𝜃∇ ¯ 𝑋) ¯ 𝑋
𝜕𝑡2 𝜕𝑡2 𝜕𝑡
𝜃˙𝑋
¯2
⎛ ⎞
˙ 𝑋
Note that the term 𝜃𝐴 ¯ = ⎝−𝜃˙𝑋 ¯ 1⎠ is the rigid motion velocity vector. Now, If Θ(𝑡, 𝑋) is a quantity
0
¯ = Θ(𝑡, 𝑋) , one simply
attached to the material points (for instance the temperature), then, with Θ̄(𝑡, 𝑋)
has
𝜕Θ 𝜕 Θ̄ ˙ Θ̄𝐴𝑋 ¯
= + 𝜃∇
𝜕𝑡 𝜕𝑡
This should not be forgotten that a correction has to be provided for each evolving variable for which
the time derivative intervene in the considered model (think for instance to platic flow for plasticity). So
that certain model bricks canot be used directly (plastic bricks for instance).
GetFEM bricks for structural mechanics are mainly considering the displacement as the amin unknown.
The expression for the displacement is the following:
𝜕𝑢 𝜕𝑢
¯ ˙ 𝑑 + ∇¯ ¯ + 𝑍(𝑡),
˙
= + 𝜃(𝐼 𝑢)𝐴𝑋
𝜕𝑡 𝜕𝑡
𝜕2𝑢 𝜕2𝑢¯ ˙ 𝜕𝑢¯ ¯
2
= 2
+ 2𝜃∇ 𝐴𝑋 + 𝜃˙2 div(((𝐼𝑑 + ∇¯ ¯ ⊗ (𝐴𝑋))
𝑢)𝐴𝑋) ¨ 𝑑 + ∇¯
¯ + 𝜃(𝐼 ¯ + 𝑍(𝑡).
𝑢)𝐴𝑋 ¨
𝜕𝑡 𝜕𝑡 𝜕𝑡
Assuming 𝜌0 the density in the reference configuration having a rotation symmetry, the term correspond-
ing to acceleration in the weak formulation reads (with 𝑣(𝑋) = 𝑣¯(𝑋)¯ a test function):
𝜕2𝑢
∫︁
𝜌0 2 · 𝑣𝑑𝑋 =
Ω0 𝜕𝑡
∫︁ [︂ 2 ]︂
𝜕 𝑢¯ ˙ 𝜕𝑢¯ ¯ ˙2 div(((𝐼𝑑 + ∇¯ ¯ ⊗ (𝐴𝑋))¯ + 𝜃(𝐼 ¨ 𝑑 + ∇¯ ¯ + 𝑍(𝑡)
¨ ¯
𝜌0 + 2 𝜃∇ 𝐴 𝑋 + 𝜃 𝑢 )𝐴 𝑋) 𝑢 )𝐴 𝑋 · 𝑣¯𝑑𝑋.
Ω̄0 𝜕𝑡2 𝜕𝑡
The third term in the right hand side can be integrated by part as follows:
0 𝜃˙ 2 div(((𝐼 + ∇¯ ¯ ⊗ (𝐴𝑋))
¯ · 𝑣¯𝑑𝑋¯ = − 0 (𝜃˙2 (𝐼𝑑 + ∇¯ ¯ · (∇(𝜌0 𝑣¯)𝐴𝑋)𝑑
¯ 𝑋 ¯
∫︀ ∫︀
Ω̄0 𝜌 𝑑 𝑢 )𝐴 𝑋) ∫︀Ω̄ 𝑢)𝐴𝑋))
0 ˙ 2
+ 𝜕 Ω̄0 𝜌 𝜃 (((𝐼𝑑 + ∇¯ ¯ ⊗ (𝐴𝑋))
𝑢)𝐴𝑋) ¯ 𝑁¯ · 𝑣¯𝑑Γ̄.
Since 𝑁 ¯ the outward unit normal vector on 𝜕 Ω̄0 is orthogonal to 𝐴𝑋¯ the boundary term is zero and
0 0
∇(𝜌 𝑣¯) = 𝑣¯ ⊗ ∇𝜌 + 𝜌 ∇¯ 0 ¯
𝑣 and since ∇𝜌 .(𝐴𝑋) = 0 because of the assumption on 𝜌0 to have a
0
To be adapted
ind = getfem::brick_name(parmeters);
This section present a set of bricks facilitating the use of an ALE formulation for an object being poten-
tially infinite in one direction and which whose part of interests (on which the computation is considered)
is translated uniformly in that direction (typically a bar).
Let us consider an object whose reference configuration Ω0 ∈ IRd is infinite in the direction 𝐸1 , i.e.
Ω0 = IR × 𝜔 0 where 𝜔 0 ∈ IRd−1 . At a time 𝑡, only a “windows” of this object is considered
Ω̄0 = (𝛼, 𝛽) × 𝜔 0
𝜙(𝑡,
¯ 𝑋) ¯ = 𝜙(𝑡, 𝑋), ¯ = 𝑋 − 𝑍(𝑡),
with 𝑋
where 𝑍(𝑡) = 𝑧(𝑡)𝐸1 . The interest of Ω̄0 is of course to be time independant. Of course, some special
boundary conditions have to be defined on {𝛼} × 𝜔 0 and {𝛽} × 𝜔 0 (absorbing or periodic boundary
conditions) in order to approximate the fact that the body is infinite.
If we denote
𝑢 ¯ = 𝜙(𝑡,
¯(𝑡, 𝑋) ¯ 𝑋) ¯ − 𝑋 = 𝑢(𝑡, 𝑋),
196 Chapter 27. ALE Support for object having a large rigid body motion
User Documentation, Release 5.4.2
𝜕𝜙 𝜕𝑢¯
= 𝑢𝑍˙
− ∇¯
𝜕𝑡 𝜕𝑡
𝜕2𝜙 𝜕2𝑢¯ 𝜕𝑢
¯ ˙ 𝜕2𝑢¯ ¨
= − ∇ 𝑍 + − ∇¯
𝑢𝑍.
𝜕𝑡2 𝜕𝑡2 𝜕𝑡 ˙
𝜕𝑍2
Assuming 𝜌0 the density in the reference being invariant with the considered translation, the term cor-
responding to acceleration in the weak formulation reads (with 𝑣(𝑋) = 𝑣¯(𝑋) ¯ a test function and after
integration by part):
𝜕2𝑢
∫︁
𝜌0 2 · 𝑣𝑑𝑋 =
Ω0 𝜕𝑡
∫︁ [︂ 2 ]︂ ∫︁
𝜕 𝑢¯ 𝜕𝑢
¯
𝜌0 2
− 2∇ 𝑍˙ − ∇¯ 𝑢𝑍¨ · 𝑣¯ − 𝜌0 (∇¯ ˙
𝑢𝑍).(∇¯ ˙ 𝑋
𝑣 𝑍)𝑑 ¯+ 𝜌0 (∇¯ ˙ 𝑣 (𝑍.
𝑢𝑍).¯ ˙ 𝑁¯ )𝑑Γ̄,
Ω̄0 𝜕𝑡 𝜕𝑡 𝜕 Ω̄0
where 𝑁 ¯ is the outward unit normal vector on 𝜕 Ω̄0 . Note that the last term vanishes on (𝛼, 𝛽) × 𝜕𝜔 0
but not necessarily on {𝛼} × 𝜔 0 and {𝛽} × 𝜔 0 .
198 Chapter 27. ALE Support for object having a large rigid body motion
199
User Documentation, Release 5.4.2
CHAPTER 28
Value of the function at the Value of the gradient along Value of the gradient along
node. of the first coordinate. of the second coordinate.
Value of the gradient along Value of the whole gradient Value of the normal deriva-
of the third coordinate for at the node. tive to a face.
3D elements.
Value of the second deriva- Value of the second deriva- Value of the second cross
tive along the first coordi- tive along the second coor- derivative in 2D or second
nate (twice). dinate (twice). derivative along the third
coordinate (twice) in 3D.
Let us recall that all finite element methods defined in GetFEM are declared in the file getfem_fem.h
and that a descriptor on a finite element method is obtained thanks to the function:
It is possible to define a classical 𝑃𝐾 Lagrange element of arbitrary dimension and arbitrary degree.
Each degree of freedom of such an element corresponds to the value of the function on a corresponding
node. The grid of node is the so-called Lagrange grid. Figures Examples of classical P_K Lagrange
elements on a segment.
The number of degrees of freedom for a classical 𝑃𝐾 Lagrange element of dimension 𝑃 and degree 𝐾
(𝑃 + 𝐾)! (𝐾 + 1)(𝐾 + 2)
is . For instance, in dimension 2 (𝑃 = 2), this value is and in dimension 3
𝑃 !𝐾! 2
(𝐾 + 1)(𝐾 + 2)(𝐾 + 3)
(𝑃 = 3), it is .
6
𝑃4 element, 35 d.o.f., 𝐶 0
The particular way used in GetFEM to numerate the nodes are also shown in figures segment, triangle
and tetrahedron. Using another numeration, let
𝑖0 , 𝑖1 , ...𝑖𝑃 ,
where 𝑆0 , 𝑆1 , ...𝑆𝑁 are the vertices of the simplex (for 𝐾 = 0 the particular choice 𝑎0,0,...0 =
∑︀𝑃 1
𝑛=0 𝑆𝑛 has been chosen). Then each base function, corresponding of each node 𝑎𝑖0 ,𝑖1 ,...𝑖𝑃
𝑃 +1
is defined by
𝑛 −1 (︂
𝑃 𝑖∏︁ )︂
∏︁ 𝐾𝜆𝑛 − 𝑗
𝜑𝑖0 ,𝑖1 ,...𝑖𝑃 = .
𝑗+1
𝑛=0 𝑗=0
where 𝜆𝑛 are the barycentric coordinates, i.e. the polynomials of degree 1 whose value is 1 on the vertex
𝑆𝑛 and whose value is 0 on other vertices. On the reference element, one has
𝜆𝑛 = 𝑥𝑛 , 0 ≤ 𝑛 < 𝑃,
𝜆𝑃 = 1 − 𝑥0 − 𝑥1 − ... − 𝑥𝑃 −1 .
When between two elements of the same degrees (even with different dimensions), the d.o.f. of a
common face are linked, the element is of class 𝐶 0 . This means that the global polynomial is continuous.
If you try to link elements of different degrees, you will get some trouble with the unlinked d.o.f. This is
not automatically supported by GetFEM, so you will have to support it (add constraints on these d.o.f.).
For some applications (computation of a gradient for instance) one may not want the d.o.f. of a common
face to be linked. This is why there are two versions of the classical 𝑃𝐾 Lagrange element.
Even though Lagrange elements are defined for arbitrary degrees, choosing a high degree can be prob-
lematic for a large number of applications due to the “noisy” characteristic of the lagrange basis. These
elements are recommended for the basic interpolation but for p.d.e. applications elements with hierar-
chical basis are preferable (see the corresponding section).
Classical Lagrange elements on parallelepipeds or prisms are obtained as tensor product of Lagrange el-
ements on simplices. When two elements are defined, one on a dimension 𝑃 1 and the other in dimension
𝑃 2 , one obtains the base functions of the tensorial product (on the reference element) as
1 2
𝜙 ̂︀1𝑖 (𝑥)𝜙
̂︀𝑖𝑗 (𝑥, 𝑦) = 𝜙 ̂︀2𝑗 (𝑦), 𝑥 ∈ IRP , y ∈ IRP ,
̂︀1𝑖 and 𝜙
where 𝜙 ̂︀2𝑖 are respectively the base functions of the first and second element.
The idea behind hierarchical basis is the description of the solution at different level: a rough level, a
more refined level . . . In the same discretization some degrees of freedom represent the rough descrip-
tion, some other the more rafined and so on. This corresponds to imbricated spaces of discretization.
The hierarchical basis contains a basis of each of these spaces (this is not the case in classical Lagrange
elements when the mesh is refined).
Among the advantages, the condition number of rigidity matrices can be greatly improved, it allows
local raffinement and a resolution with a multigrid approach.
some particular choices: 𝑃4 will be built with the basis of the 𝑃1 , the additional basis of the 𝑃2 then the
additional basis of the 𝑃4 .
𝑃6 will be built with the basis of the 𝑃1 , the additional basis :of the 𝑃2 then the additional basis of the
𝑃6 (not with the :basis of the 𝑃1 , the additional basis of the 𝑃3 then the :additional basis of the 𝑃6 , it is
possible to build the latter with :"FEM_GEN_HIERARCHICAL(a,b)")
The principal interest of the composite elements is to build hierarchical elements. But this tool can also
be used to build piecewise polynomial elements.
Fig. 7: RT0 elements in dimension two and three. (P+1 dof, H(div))
Fig. 8: Nedelec edge elements in dimension two and three. (P(P+1)/2 dof, H(rot))
The 1D GaussLobatto 𝑃𝐾 element is similar to the classical 𝑃𝐾 fem on the segment, but the nodes
are given by the Gauss-Lobatto-Legendre quadrature rule of order 2𝐾 − 1. This FEM is known to
lead to better conditioned linear systems, and can be used with the corresponding quadrature to perform
mass-lumping (on segments or parallelepipeds).
The polynomials coefficients have been pre-computed with Maple (they require the inversion
of an ill-conditioned system), hence they are only available for the following values of 𝐾:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 24, 32. Note that for 𝐾 = 1 and 𝐾 = 2, this is the clas-
sical 𝑃 1 and 𝑃 2 fem.
This element is close to be 𝜏 -equivalent but it is not. On the real element the value of the gradient on
vertices will be multiplied by the gradient of the geometric transformation. The matrix 𝑀 is not equal
to identity but is still diagonal.
Fig. 10: 𝑃1 Lagrange element on a segment with additional internal bubble function, 3 d.o.f., 𝐶 0
Fig. 11: 𝑃1 Lagrange element on a triangle with additional internal piecewise linear bubble function
Fig. 12: 𝑃1 Lagrange element on a triangle with additional bubble function on face 0, 4 d.o.f., 𝐶 0
Fig. 13: 𝑃1 Lagrange element on a triangle with additional d.o.f on face 0, 4 d.o.f., 𝐶 0
This element is not 𝜏 -equivalent (The matrix 𝑀 is not equal to identity). On the real element linear
combinations of 𝜙 ̂︀4 and 𝜙̂︀7 are used to match the gradient on the corresponding vertex. Idem for the two
couples (𝜙
̂︀5 , 𝜙
̂︀8 ) and (𝜙̂︀6 , 𝜙
̂︀9 ) for the two other vertices.
This element is not 𝜏 -equivalent (The matrix 𝑀 is not equal to identity). In particular, it can be used for
non-conforming discretization of fourth order problems, despite the fact that it is not 𝒞 1 .
This element is not 𝜏 -equivalent (The matrix 𝑀 is not equal to identity). On the real element linear
combinations of the transformed base functions 𝜙
̂︀𝑖 are used to match the gradient, the second derivatives
and the normal derivatives on the faces. Note that the use of the matrix 𝑀 allows to define Argyris
element even with nonlinear geometric transformations (for instance to treat curved boundaries).
This element is not 𝜏 -equivalent. This is a composite element. Polynomial of degree 3 on each
of the three sub-triangles (see figure Hsieh-Clough-Tocher (HCT) element, P_3, 12 d.o.f., C^1 and
[ciarlet1978]). It is strongly advised to use a "IM_HCT_COMPOSITE" integration method with this
finite element. The numeration of the dof is the following: 0, 3 and 6 for the lagrange dof on the first
second and third vertex respectively; 1, 4, 7 for the derivative with respects to the first variable; 2, 5, 8
for the derivative with respects to the second variable and 9, 10, 11 for the normal derivatives on face 0,
1, 2 respectively.
This element exists also in its reduced form, where the normal derivatives are assumed to be polynomial
of degree one on each edge (see figure Reduced Hsieh-Clough-Tocher (reduced HCT) element, P_3, 9
d.o.f., C^1)
This element is not 𝜏 -equivalent. This is a composite element. Polynomial of degree 3 on each of the four
sub-triangles (see figure Composite element on quadrilaterals, piecewise P_3, 16 d.o.f., C^1). At least
on the reference element it corresponds to the Fraeijs de Veubeke-Sander element (see [ciarlet1978]). It
is strongly advised to use a "IM_QUADC1_COMPOSITE" integration method with this finite element.
This element exists also in its reduced form, where the normal derivatives are assumed to be polynomial
of degree one on each edge (see figure Reduced composite element on quadrilaterals, piecewise P_3, 12
d.o.f., C^1)
GetFEM proposes some Lagrange pyramidal elements of degree 0, 1 and two based on [GR-GH1999]
and [BE-CO-DU2010]. See these references for more details. The proposed element can be raccorded
to standard 𝑃1 or 𝑃2 Lagrange fem on the triangular faces and to a standard 𝑄1 or 𝑄2 Lagrange fem on
the quatrilateral face.
𝜉0 𝜉1
𝜙
̂︀0 (𝑥, 𝑦, 𝑧) = ((1 − 𝜉4 − 2𝜉0 )(1 − 𝜉4 − 2𝜉1 ) − 𝜉4 (1 − 𝜉4 )),
(1 − 𝜉4 )2
𝜉0 𝜉1 𝜉2
𝜙
̂︀1 (𝑥, 𝑦, 𝑧) = 4 (2𝜉1 − (1 − 𝜉4 )),
(1 − 𝜉4 )2
𝜉1 𝜉2
𝜙
̂︀2 (𝑥, 𝑦, 𝜉4 ) = ((1 − 𝜉4 − 2𝜉1 )(1 − 𝜉4 − 2𝜉2 ) − 𝜉4 (1 − 𝜉4 )),
(1 − 𝜉4 )2
𝜉3 𝜉0 𝜉1
𝜙
̂︀3 (𝑥, 𝑦, 𝑧) = 4 (2𝜉0 − (1 − 𝜉4 )),
(1 − 𝜉4 )2
𝜉0 𝜉1 𝜉2 𝜉3
𝜙
̂︀4 (𝑥, 𝑦, 𝑧) = 16 ,
(1 − 𝜉4 )2
𝜉1 𝜉2 𝜉3
𝜙
̂︀5 (𝑥, 𝑦, 𝑧) = 4 (2𝜉2 − (1 − 𝜉4 )),
(1 − 𝜉4 )2
𝜉3 𝜉0
𝜙
̂︀6 (𝑥, 𝑦, 𝑧) = ((1 − 𝜉4 − 2𝜉3 )(1 − 𝜉4 − 2𝜉0 ) − 𝜉4 (1 − 𝜉4 )),
(1 − 𝜉4 )2
𝜉2 𝜉3 𝜉0
𝜙
̂︀7 (𝑥, 𝑦, 𝑧) = 4 (2𝜉3 − (1 − 𝜉4 )),
(1 − 𝜉4 )2
𝜉2 𝜉3
𝜙
̂︀8 (𝑥, 𝑦, 𝑧) = ((1 − 𝜉4 − 2𝜉2 )(1 − 𝜉4 − 2𝜉3 ) − 𝜉4 (1 − 𝜉4 )),
(1 − 𝜉4 )2
𝜉4
𝜙
̂︀9 (𝑥, 𝑦, 𝑧) = 4 𝜉0 𝜉1 ,
1 − 𝜉4
𝜉4
𝜙
̂︀10 (𝑥, 𝑦, 𝑧) = 4 𝜉1 𝜉2 ,
1 − 𝜉4
𝜉4
𝜙
̂︀11 (𝑥, 𝑦, 𝑧) = 4 𝜉3 𝜉0 ,
1 − 𝜉4
𝜉4
𝜙
̂︀12 (𝑥, 𝑦, 𝑧) = 4 𝜉2 𝜉3 ,
1 − 𝜉4
̂︀13 (𝑥, 𝑦, 𝑧) = 𝜉4 (2𝜉4 − 1).
𝜙
Fig. 22: 𝑃1 Lagrange element on a tetrahedron with additional bubble function on face 0, 5 d.o.f., 𝐶 0
This element is not 𝜏 -equivalent (The matrix 𝑀 is not equal to identity). On the real element linear
combinations of 𝜙 ̂︀8 , 𝜙
̂︀12 and 𝜙
̂︀16 are used to match the gradient on the corresponding vertex. Idem on
the other vertices.
For more information on cubature formulas, the reader is referred to [EncyclopCubature] for instance.
The integration methods are of two kinds. Exact integrations of polynomials and approximated integra-
tions (cubature formulas) of any function. The exact integration can only be used if all the elements are
polynomial and if the geometric transformation is linear.
A descriptor on an integration method is given by the function:
GetFEM furnishes a set of exact integration methods. This means that polynomials are integrated ex-
actly. However, their use is (very) limited and not recommended. The use of exact integration methods
is limited to the low-level generic assembly for polynomial 𝜏 -equivalent elements with linear transfor-
mations and for linear terms. It is not possible to use them in the high-level generic assembly.
The list of available exact integration methods is the following
237
User Documentation, Release 5.4.2
Even though a description of exact integration method exists on parallelepipeds or prisms, most of the
time the geometric transformations on such elements are nonlinear and the exact integration cannot be
used.
Newton cotes integration of order K on simplices, parallelepipeds and prisms are denoted by
"IM_NC(N,K)", "IM_NC_PARALLELEPIPED(N,K)" and "IM_NC_PRISM(N,K)" respec-
tively.
Gauss-Legendre integration on the segment of order K (with K/2+1 points) are denoted by
"IM_GAUSS1D(K)". Gauss-Lobatto-Legendre integration on the segment of order K (with K/2+1
points) are denoted by "IM_GAUSSLOBATTO1D(K)". It is only available for odd values of K. The
Gauss-Lobatto integration method can be used in conjunction with "FEM_PK_GAUSSLOBATTO1D(K/
2)" to perform mass-lumping.
(a, a) c "IM_TRIANGLE(4)"
(1-2a, a) c 6 points, order 4
(a, 1-2a) c 𝑎 =
(b, b) d 0.445948490915965
(1-2b, b) d 𝑏 =
(b, 1-2b) d 0.091576213509771
𝑐 =
0.111690794839005
𝑑 =
0.054975871827661
(a, a) h "IM_TRIANGLE(7)"
(b, a) h 13 points, order 7
(a, b) h 𝑎 =
(c, e) i 0.0651301029022
(d, c) i 𝑏 =
(e, d) i 0.8697397941956
(d, e) i 𝑐 =
(c, d) i 0.3128654960049
(e, c) i 𝑑 =
(f, f) j 0.6384441885698
(g, f) j 𝑒 =
(f, g) j 0.0486903154253
(1/3, 1/3) k 𝑓 =
0.2603459660790
𝑔 =
0.4793080678419
ℎ =
0.0266736178044
𝑖 =
0.0385568804451
𝑗 =
0.0878076287166
𝑘 =
−0.0747850222338
"IM_TRIANGLE(8)"
(see
[EncyclopCubature])
"IM_TRIANGLE(9)"
(see
[EncyclopCubature])
"IM_TRIANGLE(10)"
(see
[EncyclopCubature])
"IM_TRIANGLE(13)"
(see
[EncyclopCubature])
(1/2
√︀ ± 1/4 "IM_QUAD(3)"
1/6, 1/2) 1/4 4 points, order 3
√︀ 1/2
(1/2, ±
1/6)
References
247
User Documentation, Release 5.4.2
[AB-ER-PI2018] M. Abbas, A. Ern, N. Pignet. Hybrid High-Order methods for finite deformations of
hyperelastic materials. Computational Mechanics, 62(4), 909-928, 2018.
[AB-ER-PI2019] M. Abbas, A. Ern, N. Pignet. A Hybrid High-Order method for incremental asso-
ciative plasticity with small deformations. Computer Methods in Applied Mechanics and
Engineering, 346, 891-912, 2019.
[AL-CU1991] P. Alart, A. Curnier. A mixed formulation for frictional contact problems prone to newton
like solution methods. Comput. Methods Appl. Mech. Engrg. 92, 353–375, 1991.
[Al-Ge1997] E.L. Allgower and K. Georg. Numerical Path Following, Handbook of Numerical Analy-
sis, Vol. V (P.G. Ciarlet and J.L. Lions, eds.). Elsevier, pp. 3-207, 1997.
[AM-MO-RE2014] S. Amdouni, M. Moakher, Y. Renard, A local projection stabilization of fictitious
domain method for elliptic boundary value problems. Appl. Numer. Math., 76:60-75, 2014.
[AM-MO-RE2014b] S. Amdouni, M. Moakher, Y. Renard. A stabilized Lagrange multiplier method
for the enriched finite element approximation of Tresca contact problems of cracked elastic
bodies. Comput. Methods Appl. Mech. Engrg., 270:178-200, 2014.
[bank1983] R.E. Bank, A.H. Sherman, A. Weiser. Refinement algorithms and data structures for regular
local mesh refinement. In Scientific Computing IMACS, Amsterdam, North-Holland, pp 3-
17, 1983.
[ba-dv1985] K.J. Bathe, E.N. Dvorkin, A four-node plate bending element based on Mindlin-Reissner
plate theory and a mixed interpolation. Internat. J. Numer. Methods Engrg., 21, 367-383,
1985.
[Be-Mi-Mo-Bu2005] Bechet E, Minnebo H, Moës N, Burgardt B. Improved implementation and ro-
bustness study of the X-FEM for stress analysis around cracks. Internat. J. Numer. Methods
Engrg., 64, 1033-1056, 2005.
[BE-CO-DU2010] M. Bergot, G. Cohen, M. Duruflé. Higher-order finite elements for hybrid meshes
using new nodal pyramidal elements J. Sci. Comput., 42, 345-381, 2010.
[br-ba-fo1989] F. Brezzi, K.J. Bathe, M. Fortin. Mixed-interpolated element for Reissner-Mindlin
plates. Internat. J. Numer. Methods Engrg., 28, 1787-1801, 1989.
249
User Documentation, Release 5.4.2
[bu-ha2010] E. Burman, P. Hansbo. Fictitious domain finite element methods using cut elements: I. A
stabilized Lagrange multiplier method. Computer Methods in Applied Mechanics, 199:41-
44, 2680-2686, 2010.
[ca-re-so1994] D. Calvetti, L. Reichel and D.C. Sorensen. An implicitly restarted Lanczos method for
large symmetric eigenvalue problems. Electronic Transaction on Numerical Analysis}. 2:1-
21, 1994.
[ca-ch-er2019] K. Cascavita, F. Chouly and A. Ern Hybrid High-Order discretizations combined with
Nitsche’s method for Dirichlet and Signorini boundary conditions. hal-02016378v2, 2019
[CH-LA-RE2008] E. Chahine, P. Laborde, Y. Renard. Crack-tip enrichment in the Xfem method using
a cut-off function. Int. J. Numer. Meth. Engng., 75(6):629-646, 2008.
[CH-LA-RE2011] E. Chahine, P. Laborde, Y. Renard. A non-conformal eXtended Finite Element ap-
proach: Integral matching Xfem. Applied Numerical Mathematics, 61:322-343, 2011.
[ciarlet1978] P.G. Ciarlet. The finite element method for elliptic problems. Studies in Mathematics and
its Applications vol. 4, North-Holland, 1978.
[ciarlet1988] P.G. Ciarlet. Mathematical Elasticity. Volume 1: Three-Dimensional Elasticity. North-
Holland, 1988.
[EncyclopCubature] R. Cools, An Encyclopedia of Cubature Formulas, J. Complexity.
[Dh-Go-Ku2003] A. Dhooge, W. Govaerts and Y. A. Kuznetsov. MATCONT: A MATLAB Package for
Numerical Bifurcation Analysis of ODEs. ACM Trans. Math. Software 31, 141-164, 2003.
[Di-Er2015] D.A. Di Pietro, A. Ern. A hybrid high-order locking free method for linear elasticity on
general meshes. Comput. Methods Appl. Mech. Engrg., 283:1-21, 2015
[Di-Er2017] D.A. Di Pietro, A. Ern. Arbitrary-order mixed methods for heterogeneous anisotropic dif-
fusion on general meshes. IMA Journal of Numerical Analysis, 37(1), 40-63. 2017
[Duan2014] H. Duan. A finite element method for Reissner-Mindlin plates. Math. Comp., 83:286, 701-
733, 2014.
[Dr-La-Ek2014] A. Draganis, F. Larsson, A. Ekberg. Finite element analysis of transient thermome-
chanical rolling contact using an efficient arbitrary Lagrangian-Eulerian description. Com-
put. Mech., 54, 389-405, 2014.
[Fa-Po-Re2015] M. Fabre, J. Pousin, Y. Renard. A fictitious domain method for frictionless con-
tact problems in elasticity using Nitsche’s method. preprint, https://hal.archives-ouvertes.
fr/hal-00960996v1
[Fa-Pa2003] F. Facchinei and J.-S. Pang. Finite-Dimensional Variational Inequalities and Complemen-
tarity Problems, Vol. II. Springer Series in Operations Research, Springer, New York, 2003.
[Georg2001] K. Georg. Matrix-free numerical continuation and bifurcation. Numer. Funct. Anal. Opti-
mization 22, 303-320, 2001.
[GR-GH1999] R.D. Graglia, I.-L. Gheorma. Higher order interpolatory vector bases on pyramidal
elements IEEE transactions on antennas and propagation, 47:5, 775-782, 1999.
[GR-ST2015] D. Grandi, U. Stefanelli. The Souza-Auricchio model for shape-memory alloys Discrete
and Continuous Dynamical Systems, Series S, 8(4):723-747, 2015.
[HA-WO2009] C. Hager, B.I. Wohlmuth. Nonlinear complementarity functions for plasticity problems
with frictional contact. Comput. Methods Appl. Mech. Engrg., 198:3411-3427, 2009
250 Bibliography
User Documentation, Release 5.4.2
[HA-HA2004] A Hansbo, P Hansbo. A finite element method for the simulation of strong and weak dis-
continuities in solid mechanics. Comput. Methods Appl. Mech. Engrg. 193 (33-35), 3523-
3540, 2004.
[HA-RE2009] J. Haslinger, Y. Renard. A new fictitious domain approach inspired by the extended finite
element method. Siam J. on Numer. Anal., 47(2):1474-1499, 2009.
[HI-RE2010] Hild P., Renard Y. Stabilized lagrange multiplier method for the finite element approxi-
mation of contact problems in elastostatics. Numer. Math. 15:1, 101–129, 2010.
[KH-PO-RE2006] Khenous H., Pommier J., Renard Y. Hybrid discretization of the Signorini problem
with Coulomb friction, theoretical aspects and comparison of some numerical solvers. Ap-
plied Numerical Mathematics, 56/2:163-192, 2006.
[KI-OD1988] N. Kikuchi, J.T. Oden. Contact problems in elasticity. SIAM, 1988.
[LA-PO-RE-SA2005] Laborde P., Pommier J., Renard Y., Salaun M. High order extended finite element
method for cracked domains. Int. J. Numer. Meth. Engng., 64:354-381, 2005.
[LA-RE-SA2010] J. Lasry, Y. Renard, M. Salaun. eXtended Finite Element Method for thin cracked
plates with Kirchhoff-Love theory. Int. J. Numer. Meth. Engng., 84(9):1115-1138, 2010.
[KO-RE2014] K. Poulios, Y. Renard, An unconstrained integral approximation of large sliding fric-
tional contact between deformable solids. Computers and Structures, 153:75-90, 2015.
[LA-RE2006] P. Laborde, Y. Renard. Fixed point strategies for elastostatic frictional contact problems.
Math. Meth. Appl. Sci., 31:415-441, 2008.
[Li-Re2014] T. Ligurský and Y. Renard. A Continuation Problem for Computing Solutions of Discre-
tised Evolution Problems with Application to Plane Quasi-Static Contact Problems with
Friction. Comput. Methods Appl. Mech. Engrg. 280, 222-262, 2014.
[Li-Re2014hal] T. Ligurský and Y. Renard. Bifurcations in Piecewise-Smooth Steady-State Problems:
Abstract Study and Application to Plane Contact Problems with Friction. Computational
Mechanics, 56:1:39-62, 2015.
[Li-Re2015hal] T. Ligurský and Y. Renard. A Method of Piecewise-Smooth Numerical Branching. Z.
Angew. Math. Mech., 97:7:815–827, 2017.
[Mi-Zh2002] P. Ming and Z. Shi, Optimal L2 error bounds for MITC3 type element. Numer. Math. 91,
77-91, 2002.
[Xfem] N. Moës, J. Dolbow and T. Belytschko, A finite element method for crack growth without
remeshing. Internat. J. Numer. Methods Engrg., 46, 131-150, 1999.
[Nackenhorst2004] U. Nackenhorst, The ALE formulation of bodies in rolling contact. Theoretical foun-
dation and finite element approach. Comput. Methods Appl. Mech. Engrg., 193:4299-4322,
2004.
[NI-RE-CH2011] S. Nicaise, Y. Renard, E. Chahine, Optimal convergence analysis for the eXtended
Finite Element Method. Int. J. Numer. Meth. Engng., 86:528-548, 2011.
[Pantz2008] O. Pantz The Modeling of Deformable Bodies with Frictionless (Self-)Contacts. Archive
for Rational Mechanics and Analysis, Volume 188, Issue 2, pp 183-212, 2008.
[SCHADD] L.F. Pavarino. Domain decomposition algorithms for the p-version finite element method
for elliptic problems. Luca F. Pavarino. PhD thesis, Courant Institute of Mathematical Sci-
ences}. 1992.
Bibliography 251
User Documentation, Release 5.4.2
[PO-NI2016] K. Poulios, C.F. Niordson, Homogenization of long fiber reinforced composites including
fiber bending effects. Journal of the Mechanics and Physics of Solids, 94, pp 433-452, 2016.
[GetFEM2020] Y. Renard, K. Poulios GetFEM: Automated FE modeling of multiphysics prob-
lems based on a generic weak form language. Preprint, https://hal.archives-ouvertes.fr/
hal-02532422/document
[remacle2003] J.-F. Remacle, M.S. Shephard; An algorithm oriented mesh database. International Jour-
nal for Numerical Methods in Engineering, 58:2, pp 349-374, 2003.
[SE-PO-WO2015] A. Seitz, A. Popp, W.A. Wall, A semi-smooth Newton method for orthotropic plas-
ticity and frictional contact at finite strains. Comput. Methods Appl. Mech. Engrg. 285:228-
254, 2015.
[SI-HU1998] J.C. Simo, T.J.R. Hughes. Computational Inelasticity. Interdisciplinary Applied Mathe-
matics, vol 7, Springer, New York 1998.
[SO-PE-OW2008] E.A. de Souza Neto, D Perić, D.R.J. Owen. Computational methods for plasticity. J.
Wiley & Sons, New York, 2008.
[renard2013] Y. Renard, Generalized Newton’s methods for the approximation and resolution of fric-
tional contact problems in elasticity. Comput. Methods Appl. Mech. Engrg., 256:38-55,
2013.
[SU-CH-MO-BE2001] Sukumar N., Chopp D.L., Moës N., Belytschko T. Modeling holes and inclu-
sions by level sets in the extended finite-element method. Comput. Methods Appl. Mech.
Engrg., 190:46-47, 2001.
[ZT1989] Zienkiewicz and Taylor. The finite element method. 5th edition, volume 3 : Fluids Dynamics.
252 Bibliography
Index
A getfem::mesh::ind_points_of_convex
asm, 34, 59 (C++ function), 17
getfem::mesh::is_convex_having_neighbor
B (C++ function), 18
bgeot::convex_structure::dim (C++ getfem::mesh::neighbor_of_convex
function), 17 (C++ function), 17
bgeot::convex_structure::face_structure getfem::mesh::neighbors_of_convex
(C++ function), 17 (C++ function), 17
getfem::mesh::normal_of_face_of_convex
bgeot::convex_structure::ind_points_of_face
(C++ function), 17 (C++ function), 18
bgeot::convex_structure::nb_faces getfem::mesh::optimize_structure
(C++ function), 17 (C++ function), 18
bgeot::convex_structure::nb_points getfem::mesh::points (C++ function), 17
(C++ function), 17 getfem::mesh::points_index (C++
bgeot::convex_structure::nb_points_of_facefunction), 17
(C++ function), 17 getfem::mesh::points_of_convex
bgeot::mesh_structure::structure_of_convex(C++ function), 17
(C++ function), 17 getfem::mesh::read_from_file (C++
function), 20
F getfem::mesh::region (C++ function), 18
fem, 22 getfem::mesh::trans_of_convex (C++
function), 18
G getfem::mesh::write_to_file (C++
generic assembly, 34, 59 function), 20
getfem::mesh::clear (C++ function), 18 getfem::mesh_fem::basic_dof_on_region
getfem::mesh::convex_area_estimate (C++ function), 27
(C++ function), 18 getfem::mesh_fem::clear (C++ func-
getfem::mesh::convex_index (C++ tion), 25
function), 17 getfem::mesh_fem::convex_index
getfem::mesh::convex_quality_estimate (C++ function), 25
(C++ function), 18 getfem::mesh_fem::dof_on_region
getfem::mesh::convex_radius_estimate (C++ function), 27
(C++ function), 18 getfem::mesh_fem::extension_matrix
getfem::mesh::convex_to_point (C++ (C++ function), 27
function), 17 getfem::mesh_fem::fem_of_element
getfem::mesh::dim (C++ function), 17 (C++ function), 25
getfem::mesh::has_region (C++ func- getfem::mesh_fem::first_convex_of_basic_dof
tion), 18 (C++ function), 27
getfem::mesh_fem::get_qdim (C++
253
User Documentation, Release 5.4.2
function), 27 getfem::model::add_initialized_fem_data
getfem::mesh_fem::ind_basic_dof_of_element(C++ function), 105
(C++ function), 26 getfem::model::add_initialized_fixed_size_dat
getfem::mesh_fem::is_reduced (C++ (C++ function), 105
function), 27 getfem::model::add_initialized_scalar_data
getfem::mesh_fem::linked_mesh (C++ (C++ function), 105
function), 25 getfem::model::add_internal_im_variable
getfem::mesh_fem::nb_basic_dof (C++ function), 106
(C++ function), 27 getfem::model::add_multiplier (C++
getfem::mesh_fem::nb_basic_dof_of_element function), 105
(C++ function), 26 getfem::model::complex_rhs (C++
getfem::mesh_fem::nb_dof (C++ func- function), 106
tion), 27 getfem::model::complex_tangent_matrix
getfem::mesh_fem::point_of_basic_dof (C++ function), 106
(C++ function), 26 getfem::model::complex_variable
getfem::mesh_fem::reduce_to_basic_dof (C++ function), 106
(C++ function), 27 getfem::model::is_complex (C++ func-
getfem::mesh_fem::reduction_matrix tion), 104
(C++ function), 27 getfem::model::mesh_fem_of_variable
(C++ function), 106
getfem::mesh_fem::reference_point_of_basic_dof
(C++ function), 26 getfem::model::real_rhs (C++ func-
getfem::mesh_fem::set_reduction tion), 106
(C++ function), 27 getfem::model::real_tangent_matrix
getfem::mesh_fem::set_reduction_matrices (C++ function), 106
(C++ function), 27 getfem::model::real_variable (C++
getfem::mesh_region::add (C++ func- function), 106
tion), 18 getfem::slicer_apply_deformation
getfem::mesh_region::index (C++ (C++ function), 96
function), 19 getfem::slicer_boundary (C++ func-
getfem::mesh_region::is_in (C++ tion), 96
function), 18 getfem::slicer_build_edges_mesh
getfem::mesh_region::is_only_convexes (C++ function), 97
(C++ function), 19 getfem::slicer_build_mesh (C++ func-
getfem::mesh_region::is_only_faces tion), 97
(C++ function), 18 getfem::slicer_build_stored_mesh_slice
getfem::mesh_region::sup (C++ func- (C++ function), 97
tion), 18 getfem::slicer_complementary (C++
getfem::model::add_fem_data (C++ function), 96
function), 105 getfem::slicer_cylinder (C++ func-
getfem::model::add_fem_variable tion), 96
(C++ function), 105 getfem::slicer_explode (C++ function),
getfem::model::add_filtered_fem_variable 97
(C++ function), 105 getfem::slicer_half_space (C++ func-
getfem::model::add_fixed_size_data tion), 96
(C++ function), 105 getfem::slicer_intersect (C++ func-
getfem::model::add_fixed_size_variable tion), 96
(C++ function), 104, 105 getfem::slicer_isovalues (C++ func-
getfem::model::add_im_data (C++ tion), 96
function), 106 getfem::slicer_mesh_with_mesh (C++
getfem::model::add_im_variable function), 96
(C++ function), 105 getfem::slicer_none (C++ function), 96
254 Index
User Documentation, Release 5.4.2
M
mesh, 22
mesh_fem, 22
mim.clear() (built-in function), 31
mim.convex_index() (built-in function), 31
mim.int_method_of_element() (built-in
function), 31
mim.linked_mesh() (built-in function), 31
model bricks, 101, 103, 112–114, 117, 118,
120, 123–125, 127–129, 131, 138, 151,
160, 168, 177, 191
models, 101, 103, 112–114, 117, 118, 120, 123–
125, 127–129, 131, 138, 151, 160, 168,
177, 191
N
Nitsche’s method, 120
Index 255