class SparseVanka< number >
Point-wise Vanka preconditioning. This class does Vanka preconditioning on a point-wise base. Vanka preconditioners are used for saddle point problems like Stoke's problem or problems arising in optimization where Lagrange multiplier occur and let Netwon's matrix have a zero block. With these matrices the application of Jacobi or Gauss-Seidel methods is impossible, because some diagonal elements are zero in the rows of the Lagrange multiplier. The approach of Vanka is to solve a small (usually indefinite) system of equations for each Langrange multiplie variable (we will also call the pressure in Stokes' equation a Langrange multiplier since it can be interpreted as such).
Objects of this class are constructed by passing a vector of indices of the degrees of freedom of the Lagrange multiplier. In the actual preconditioning method, these rows are traversed in the order in which the appear in the matrix. Since this is a Gau▀-Seidel like procedure, remember to have a good ordering in advance (for transport dominated problems, Cuthill-McKee algorithms are a good means for this, if points on the inflow boundary are chosen as starting points for the renumbering).
For each selected degree of freedom, a local system of equations is built by the degree of freedom itself and all other values coupling immediately, i.e. the set of degrees of freedom considered for the local system of equations for degree of freedom
i itself and all
j such that the element
(i,j) is a nonzero entry in the sparse matrix under consideration. The elements
(j,i) are not considered. We now pick all matrix entries from rows and columns out of the set of degrees of freedom just described out of the global matrix and put it into a local matrix, which is subsequently inverted. This system may be of different size for each degree of freedom, depending for example on the local neighborhood of the respective node on a computational grid.
The right hand side is built up in the same way, i.e. by copying all entries that coupled with the one under present consideration, but it is augmented by all degrees of freedom coupling with the degrees from the set described above (i.e. the DoFs coupling second order to the present one). The reason for this is, that the local problems to be solved shall have Dirichlet boundary conditions on the second order coupling DoFs, so we have to take them into account but eliminate them before actually solving; this elimination is done by the modification of the right hand side, and in the end these degrees of freedom do not occur in the matrix and solution vector any more at all.
This local system is solved and the values are updated into the destination vector.
Remark: the Vanka method is a non-symmetric preconditioning method.
Example of Use
This little example is taken from a program doing parameter optimization. The Lagrange multiplier is the third component of the finite element used. The system is solved by the GMRES method.
signature = signature = false;
signature = true;
vector<bool> selected_dofs (dof.n_dofs(), false);
gmres.solve (global_matrix, solution, right_hand_side,
At present, the local matrices are built up such that the degree of freedom associated with the local Lagrange multiplier is the first one. Thus, usually the upper left entry in the local matrix is zero. It is not clear to me (W.B.) whether this might pose some problems in the inversion of the local matrices. Maybe someone would like to check this.
- Instantiations for this template are provided for
<float> and <double>; others can be generated in application programs (see the section on Template instantiations in the manual).
- Guido Kanschat, Wolfgang Bangerth; 1999, 2000
Definition at line 30 of file sparse_vanka.h.
template<typename number >
|DEAL_II_NAMESPACE_OPEN SparseVanka< number >::SparseVanka
||const SparseMatrix< number > &
||const std::vector< bool > &
||const unsigned int
Constructor. Gets the matrix for preconditioning and a bit vector with entries
true for all rows to be updated. A reference to this vector will be stored, so it must persist longer than the Vanka object. The same is true for the matrix.
M which is passed here may or may not be the same matrix for which this object shall act as preconditioner. In particular, it is conceivable that the preconditioner is build up for one matrix once, but is used for subsequent steps in a nonlinear process as well, where the matrix changes in each step slightly.
false, then the inverses of the local systems are computed now; if the flag is
true, then they are computed every time the preconditioner is applied. This saves some memory, but makes preconditioning very slow. Note also, that if the flag is
false, then the contents of the matrix
M at the time of calling this constructor are used, while if the flag is
true, then the values in
M at the time of preconditioning are used. This may lead to different results, obviously, of
n_threads determines how many threads shall be used in parallel when building the inverses of the diagonal blocks. This parameter is ignored if not in multithreaded mode. By default, this variable is set to the value of
Definition at line 29 of file sparse_vanka.templates.h.
References Assert, SparseVanka< number >::compute_inverses(), StandardExceptions::ExcDimensionMismatch(), SparseMatrix< number >::m(), and SparseMatrix< number >::n().
template<typename number >
template<typename number2 >
|void SparseVanka< number >::apply_preconditioner
||Vector< number2 > &
||const Vector< number2 > &
||const std::vector< bool > *const
Apply the inverses corresponding to those degrees of freedom that have a
true value in
dof_mask, to the
src vector and move the result into
dst. Actually, only values for allowed indices are written to
dst, so the application of this function only does what is announced in the general documentation if the given mask sets all values to zero
The reason for providing the mask anyway is that in derived classes we may want to apply the preconditioner to parts of the matrix only, in order to parallelize the application. Then, it is important to only write to some slices of
dst, in order to eliminate the dependencies of threads of each other.
If a null pointer is passed instead of a pointer to the
dof_mask (as is the default value), then it is assumed that we shall work on all degrees of freedom. This is then equivalent to calling the function with a
vmult of this class of course calls this function with a null pointer
Definition at line 195 of file sparse_vanka.templates.h.
References Assert, FullMatrix< number >::begin(), SparsityPattern::column_number(), FullMatrix< number >::end(), StandardExceptions::ExcDimensionMismatch(), SparsityPattern::max_entries_per_row(), SparsityPattern::row_length(), and Vector< number >::size().