Let be a triangular (2d) or tetrahedral (3d) mesh of
corresponding
to the following data structure:
Scalar finite elements :
Let
be the finite dimensional space spanned by
the
-Lagrange (scalar) basis functions
where
denotes the space of all polynomials defined over T of total
degree less than or equal to
The functions
satisfy
Then we have on
,
such that
.
A -Lagrange (scalar) finite element matrix is of the generic form
where is the bilinear differential operator (order
)
defined for all
by
and
and
are given functions on
We can notice that is a sparse matrix due to
support properties of
functions.
Let
The element matrix
, associated to
, is the
matrix defined by
where is the
-th local basis function associated
to the
-th element.
For examples,
the Mass matrix is defined by
The corresponding bilinear differential operator is completely defined with
,
and
the Stiffness matrix is defined by
The corresponding bilinear differential operator is completely defined with
,
and
Vector finite elements :
The dimension of the space is
in dimension we have two natural basis :
the global alternate basis
defined by
and the global block basis
defined by
in dimension we have two natural basis :
the global alternate basis defined by
and the global block basis defined by
A -Lagrange (vector) finite element matrix in
basis
is of the generic form
where is the bilinear differential operator (order
)
defined by
and is a bilinear differential operator of scalar type.
For example, in dimension the Elastic Stiffness matrix is defined by
where
is the strain tensor respectively and
is the Hooke matrix
Then the bilinear differential operator associated to this matrix is given by
We present now three algorithms (base, OptV1 and OptV2 versions) for assembling this kind of matrix.
Note
These algorithms can be successfully implemented in various interpreted languages under some assumptions. For all versions, it must have a sparse matrix implementation. For OptV1 and OptV2 versions, we also need a particular sparse matrix constructor (see Sparse matrix requirement). And, finally, OptV2 also required that the interpreted languages support classical vectorization operations. Here is the current list of interpreted languages for which we have successfully implemented these three algorithms :
- Python with Numpy and Scipy modules,
- Matlab,
- Octave,
- Scilab
Due to support properties of -Lagrange basis functions, we have the classical algorithm :
Note
We recall the classical matrix assembly in dimension with
In fact, for each element we add its element matrix to the global sparse matrix (lines 4 to 10 of the previous algorithm). This operation is illustrated in the following figure in 2d scalar fields case :
The repetition of elements insertion in sparse matrix is very expensive.
The interpreted language must contain a function to generate a sparse matrix M from three 1d arrays of same length Ig, Jg and Kg such that M(Ig(k),Jg(k))=Kg(k) . Furthermore, the elements of Kg having the same indices in Ig and Jg must be summed.
Obviously, this kind of function exists in compiled languages. For example, in C language, one can use the SuiteSparse from T. Davis and with Nvidia GPU, one can use Thrust library.
The idea is to create three global 1d-arrays
and
allowing the storage of the element matrices as well as the position of their elements in the global matrix.
The length of each array is
(i.e.
for
and
for
).
Once these arrays are created, the matrix assembly is obtained with one of the previous commands.
To create these three arrays, we first define three local 1d-arrays
and
of
elements obtained from a generic element matrix
of
dimension
:
From these arrays, it is then possible to build the three global arrays
and
of size
defined,
by
So, for each triangle , we have
Then, a simple algorithm can build these three arrays using a loop over each triangle.
We present the optimized version 2 algorithm where no loop is used.
We define three 2d-arrays that allow to store all the element matrices
as well as their positions in the global matrix. We denote by
and
these
arrays, defined
by
(1)
The three local arrays
and
are thus stored
in the
column of the global arrays
and
respectively.
A natural way to build these three arrays consists in using a loop through the triangles
in which we insert the local arrays column-wise
The natural construction of these three arrays is done column-wise. So, for each array there are
columns to compute, which depends on the mesh size.
To vectorize, we must fill these arrays by row-wise operations and then for each array there are
rows to compute. We recall that
does not depend on the mesh size.
These rows insertions are represented in Figure 49 . We can also remark that,
, with
where, in scalar fields case,
and in vector fields case,
As we can see in Figures 50 and 51,
it is quite easy to vectorize and
computations in scalar fields case
by filling these arrays lines by lines :
Using vectorization tools, we can compute and
in one line. The vectorized algorithms in 2d and 3d scalar fields are represented by Figure 52.
In vector fields case, we construct the tabular such that
Then we can vectorize
and
computations in vector fields case.
We represent in Figure 53 these operations in 2d.
Now, it remains to vectorize the computation of array
which contains all the element matrices associated to
or
:
it should be done by row-wise vector operations.
We now describe a vectorized construction of array associated to a generic
bilinear form
. For the mesh element
, the element matrix is then given by