2. Implementation and use in Code_Aster#
The use of the multi-frontend method is accessible by the operator NUME_DDL, in the following way:
nu = NUME_DDL (matr_rigi = matr, storage = 'MORSE',
renum = 'MD'
or renum= 'MDA',
or renum= 'METIS');
Two other renumbering methods are available: Approximate Minimum Degree (MDA), which is a variant of the minimum degree method, and a nested dissection method (METIS). They are described briefly in Appendices 1 and 2. Simply replace the renum value with MDA, or METIS.
This method is also directly available under the SOLVEUR keyword in MECA_STATIQUE, STAT_NON_LINE,, DYNA_NON_LINE, THER_LINEAIRE, THER_NON_LINE with the same logic.
Next, the operator FACTORISER will be used, the call being the same as in the case of a matrix stored in profile mode.
In NUME_DDL, we indicate that the matrix to be factored is arranged according to the MORSE mode and that one of the two renumberations of the « minimum degree » is requested, or a renumbering by nested dissection (METIS).
In this case, NUME_DDL performs the first three phases seen above:
renumbering,
symbolic factorization,
Execution sequence.
Since a recent development, renumbering is performed on the nodes (in the sense of interpolation), and no longer on the degrees of freedom. This saves calculation time and ensures compliance with the initial order of the degrees of freedom within the nodes (this is sometimes necessary in the incompressible case where the pressure must be numbered after the movements). The « double-lagrange » numbering constraint governing the degrees of freedom affected by the boundary condition is also respected.
In addition, NUME_DDL prepares the block breakdown of the factored matrix. In fact, we saw that at each elimination, the columns of the factored matrix were arranged in a table. These columns will only be used during the descend/ascent. They are never used to calculate other columns. So there is no point in having them all in memory. They are stored, in the Code_Aster, as a collection of JEVEUX objects of variable length. These objects, blocks of columns, must nevertheless satisfy the following constraint: each block corresponds to an integer number of « supernodes ». It is therefore not possible to have the columns of the same « supernode » on several blocks.
Since we don’t know how much space in memory is available during numerical factorization, we decide in NUME_DDL that the maximum length of each block will be the max. (on all SNs) by the sum of the lengths of the columns in \(\mathit{SN}\).
\(L{b}_{\text{max}}=\underset{\mathrm{SNi}}{\mathrm{Max}}(\sum _{k\in \mathrm{SNi}}\mathrm{longueur}({\mathrm{col.}}_{k}))\text{},\text{}\text{(en abrégé)}\)
The FACTORISER operator uses the pointers created by NUME_DDL and the initial matrix MORSE. It creates the factored matrix in the form of a collection of JEVEUX objects, as we saw earlier. A provisional data structure is also required. It concerns frontal matrices. There are two cases:
the stack of front-end matrices can hold the entire array in memory (in a one-dimensional array), in this case, an object JEVEUX is allocated and the multifrontal algorithm then manages this space itself, by placing the « mother » front-end matrix in place of the « daughter » matrices,
it does not fit and, in this case, it is created as a collection of JEVEUX objects, each front-end matrix being an object. To eliminate the « supernode » \(i\) you need simultaneously in memory:
the factorized block to which \(\mathrm{SNi}\) belongs
the front-end matrix object :math:`i` as well as all the « daughter » front-end matrices from :math:`i` that will be**destroyed* after their use.
The front-end matrix \(i\) will be kept in memory until it is used and destroyed. We could, as was done before, release each front-end matrix after its creation in the sense of JEVEUX. This can then result, in case of low available memory, in disk storage that is prohibitive in volume. Indeed, a destruction of object JEVEUX does not cause the destruction of its image on disk, and the sum of the lengths of the front matrices is enormous.
In summary, it is necessary to be able to simultaneously store in memory:
a block of the factored one,
the stack of front matrices, in a single object if that fits, in several objects otherwise.
Therefore, « enough » memory is needed to use the multifrontend method. The second way to store the battery allows execution when the memory is sufficient, but crumbled.
When the memory is insufficient, you must restart the execution of FACTORISER with a larger memory.