* @ingroup dofs
*
* This module deals with constraints on degrees of
- * freedom. The central class to deal with constraints is the ConstraintMatrix
- * class.
+ * freedom. The central class to deal with constraints is the
+ * AffineConstraints class.
*
* Constraints typically come from several sources, for example:
* - If you have Dirichlet-type boundary conditions, $u|_{\partial\Omega}=g$,
* at the location of degree
* of freedom 12 has the value 42. Such constraints are generated by
* those versions of the VectorTools::interpolate_boundary_values
- * function that take a ConstraintMatrix argument (though there are
+ * function that take a AffineConstraints argument (though there are
* also other ways of dealing with Dirichlet conditions, using
* MatrixTools::apply_boundary_values, see for example step-3 and step-4).
* - If you have boundary conditions that set a certain part of the
* solution. An example of this is given in the step-11 tutorial program.
*
* In all of these examples, constraints on degrees of freedom are linear
- * and possibly inhomogeneous. In other words, the always have
+ * and possibly inhomogeneous. In other words, they always have
* the form $x_{i_1} = \sum_{j=2}^M a_{i_j} x_{i_j} + b_i$. The deal.II
* class that deals with storing and using these constraints is
- * ConstraintMatrix. The naming stems from the fact that the class
- * originally only stored the (sparse) matrix $a_{i_j}$. The class name
- * component "matrix" no longer makes much sense today since the class has
- * learned to also deal with inhomogeneities $b_i$.
+ * AffineConstraints.
*
*
* <h3>Eliminating constraints</h3>
* the sparsity pattern of the sparse matrices used in finite element
* calculations and is thus a quite expensive operation. The general scheme of
* things is then that you build your system, you eliminate (condense) away
- * constrained nodes using the ConstraintMatrix::condense() functions, then
+ * constrained nodes using the AffineConstraints::condense() functions, then
* you solve the remaining system, and finally you compute the values of
* constrained nodes from the values of the unconstrained ones using the
- * ConstraintMatrix::distribute() function. Note that the
- * ConstraintMatrix::condense() function is applied to matrix and right hand
- * side of the linear system, while the ConstraintMatrix::distribute()
+ * AffineConstraints::distribute() function. Note that the
+ * AffineConstraints::condense() function is applied to matrix and right hand
+ * side of the linear system, while the AffineConstraints::distribute()
* function is applied to the solution vector. This is the method used in
* the first few tutorial programs, see for example step-6.
*
* implement for %parallel computations where a process may not have access
* to elements of the matrix. We therefore offer a second way of
* building linear systems, using the
- * ConstraintMatrix::add_entries_local_to_global() and
- * ConstraintMatrix::distribute_local_to_global() functions discussed
+ * AffineConstraints::add_entries_local_to_global() and
+ * AffineConstraints::distribute_local_to_global() functions discussed
* below. The resulting linear systems are equivalent to those one gets after
- * calling the ConstraintMatrix::condense() functions.
+ * calling the AffineConstraints::condense() functions.
*
* @note Both ways of applying constraints set the value of the matrix
* diagonals to constrained entries to a <i>positive</i> entry of the same
* "step-31".
*
* <li>
- * There may not be a ConstraintMatrix::condense() function for the matrix
+ * There may not be an AffineConstraints::condense() function for the matrix
* you use (this is, for example, the case for the PETSc and Trilinos
* wrapper classes where we have no access to the underlying representation
* of the matrix, and therefore cannot efficiently implement the
- * ConstraintMatrix::condense() operation). This is the case discussed
+ * AffineConstraints::condense() operation). This is the case discussed
* in step-17, step-18, step-31, and step-32.
* </ul>
*
* matrices and vectors, and similarly build a sparsity pattern in the
* condensed form at the time it is set up originally.
*
- * The ConstraintMatrix class offers support for these operations as well. For
- * example, the ConstraintMatrix::add_entries_local_to_global() function adds
+ * The AffineConstraints class offers support for these operations as well. For
+ * example, the AffineConstraints::add_entries_local_to_global() function adds
* nonzero entries to a sparsity pattern object. It not only adds a given
* entry, but also all entries that we will have to write to if the current
* entry corresponds to a constrained degree of freedom that will later be
* eliminated. Similarly, one can use the
- * ConstraintMatrix::distribute_local_to_global() functions to directly
+ * AffineConstraints::distribute_local_to_global() functions to directly
* distribute entries in vectors and matrices when copying local contributions
* into a global matrix or vector. These calls make a subsequent call to
- * ConstraintMatrix::condense() unnecessary. For examples of their use see the
+ * AffineConstraints::condense() unnecessary. For examples of their use see the
* tutorial programs referenced above.
*
* Note that, despite their name which describes what the function really
- * does, the ConstraintMatrix::distribute_local_to_global() functions has to
+ * does, the AffineConstraints::distribute_local_to_global() functions has to
* be applied to matrices and right hand side vectors, whereas the
- * ConstraintMatrix::distribute() function discussed below is applied to the
+ * AffineConstraints::distribute() function discussed below is applied to the
* solution vector after solving the linear system.
*
*
*
* After solving the condensed system of equations, the solution vector has to
* be "distributed": the modification to the original linear system that
- * results from calling ConstraintMatrix::condense leads to a linear system
+ * results from calling AffineConstraints::condense() leads to a linear system
* that solves correctly for all degrees of freedom that are unconstrained but
* leaves the values of constrained degrees of freedom undefined. To get the
* correct values also for these degrees of freedom, you need to "distribute"
* the unconstrained values also to their constrained colleagues. This is done
- * by the ConstraintMatrix::distribute() function.
+ * by the AffineConstraints::distribute() function.
* The operation of distribution undoes the
* condensation process in some sense, but it should be noted that it is not
* the inverse operation. Basically, distribution sets the values of the
* respective condense function is called without any matrix (or if the matrix
* has already been condensed before).
*
- * The use of ConstraintMatrix for implementing Dirichlet boundary conditions
- * is discussed in the step-22 tutorial program. A further example that applies
- * the ConstraintMatrix is step-41. The situation here is little more complicated,
- * because there we have some constraints which are not at the boundary.
- * There are two ways to apply inhomogeneous constraints after creating the
- * ConstraintMatrix:
+ * The use of the AffineConstraints class for implementing Dirichlet
+ * boundary conditions is discussed in the step-22 tutorial program. A
+ * further example that utilizes AffineConstraints is step-41. The
+ * situation here is little more complicated, because there we have some
+ * constraints which are not at the boundary. There are two ways to apply
+ * inhomogeneous constraints after creating an AffineConstraints object:
*
* First approach:
- * - Apply the ConstraintMatrix::distribute_local_to_global() function to the
+ * - Apply the AffineConstraints::distribute_local_to_global() function to the
* system matrix and the right-hand-side with the parameter
* use_inhomogeneities_for_rhs = false (i.e., the default)
* - Set the solution to zero in the inhomogeneous constrained components
- * using the ConstraintMatrix::set_zero() function (or start with a solution
+ * using the AffineConstraints::set_zero() function (or start with a solution
* vector equal to zero)
* - solve() the linear system
- * - Apply ConstraintMatrix::distribute() to the solution
+ * - Apply AffineConstraints::distribute() to the solution
*
* Second approach:
- * - Use the ConstraintMatrix::distribute_local_to_global() function with the parameter
- * use_inhomogeneities_for_rhs = true and apply it to
- * the system matrix and the right-hand-side
+ * - Use the AffineConstraints::distribute_local_to_global() function with
+ * the parameter use_inhomogeneities_for_rhs = true and apply it to the
+ * system matrix and the right-hand-side
* - Set the concerning components of the solution to the inhomogeneous
- * constrained values (for example using ConstraintMatrix::distribute())
+ * constrained values (for example using AffineConstraints::distribute())
* - solve() the linear system
- * - Depending on the solver now you have to apply the ConstraintMatrix::distribute()
- * function to the solution, because the solver could change the constrained
- * values in the solution. For a Krylov based solver this should not be strictly
- * necessary, but it is still possible that there is a difference between the
- * inhomogeneous value and the solution value in the order of machine precision,
- * and you may want to call ConstraintMatrix::distribute() anyway if you have
- * additional constraints such as from hanging nodes.
+ * - Depending on the solver now you have to apply the
+ * AffineConstraints::distribute() function to the solution, because the
+ * solver could change the constrained values in the solution. For a
+ * Krylov based solver this should not be strictly necessary, but it is
+ * still possible that there is a difference between the inhomogeneous
+ * value and the solution value in the order of machine precision, and
+ * you may want to call AffineConstraints::distribute() anyway if you
+ * have additional constraints such as from hanging nodes.
*
* Of course, both approaches lead to the same final answer but in different
- * ways. Using the first approach (i.e., when using use_inhomogeneities_for_rhs = false
- * in ConstraintMatrix::distribute_local_to_global()), the linear system we
+ * ways. Using the first approach (i.e., when using
+ * <code>use_inhomogeneities_for_rhs = false</code>
+ * in AffineConstraints::distribute_local_to_global()), the linear system we
* build has zero entries in the right hand side in all those places where a
* degree of freedom is constrained, and some positive value on the matrix
* diagonal of these lines. Consequently, the solution vector of the linear
* system will have a zero value for inhomogeneously constrained degrees of
- * freedom and we need to call ConstraintMatrix::distribute() to give these
+ * freedom and we need to call AffineConstraints::distribute() to give these
* degrees of freedom their correct nonzero values.
*
* On the other hand, in the second approach, the matrix diagonal element and
* the matrix is empty with the exception of the diagonal entry, and
* $b_{13}/A_{13,13}=42$ so that the solution of $Ax=b$ must satisfy
* $x_{13}=42$ as desired). As a consequence, we do not need to call
- * ConstraintMatrix::distribute() after solving to fix up inhomogeneously
+ * AffineConstraints::distribute() after solving to fix up inhomogeneously
* constrained components of the solution, though there is also no harm in
* doing so.
*
* match the values we want for them at the solution. We can again
* circumvent this problem by setting the corresponding elements of the
* solution vector to their correct values, by calling
- * ConstraintMatrix::distribute() <i>before</i> solving the linear system
+ * AffineConstraints::distribute() <i>before</i> solving the linear system
* (and then, as necessary, a second time after solving).
*
* In addition to these considerations, consider the case where we have
* inhomogeneous constraints of the kind $x_{3}=\tfrac 12 x_1 + \tfrac 12$,
* e.g., from a hanging node constraint of the form $x_{3}=\tfrac 12 (x_1 +
* x_2)$ where $x_2$ is itself constrained by boundary values to $x_2=1$.
- * In this case, the ConstraintMatrix can of course not figure out what
- * the final value of $x_3$ should be and, consequently, can not set the
- * solution vector's third component correctly. Thus, the second approach will
- * not work and you should take the first.
+ * In this case, the AffineConstraints container can of course not figure
+ * out what the final value of $x_3$ should be and, consequently, can not
+ * set the solution vector's third component correctly. Thus, the second
+ * approach will not work and you should take the first.
*
*
* <h3>Dealing with conflicting constraints</h3>
* - If you want the hanging node constraints to win, then first build
* these through the DoFTools::make_hanging_node_constraints() function.
* Then interpolate the boundary values using
- * VectorTools::interpolate_boundary_values() into the same ConstraintMatrix
- * object. If the latter function encounters a boundary node that already
- * is constrained, it will simply ignore the boundary values at this
- * node and leave the constraint untouched.
+ * VectorTools::interpolate_boundary_values() into the same
+ * AffineConstraints object. If the latter function encounters a boundary
+ * node that already is constrained, it will simply ignore the boundary
+ * values at this node and leave the constraint untouched.
* - If you want the boundary value constraint to win, build the hanging
* node constraints as above and use these to assemble the matrix using
- * the ConstraintMatrix::distribute_local_to_global() function (or,
+ * the AffineConstraints::distribute_local_to_global() function (or,
* alternatively, assemble the matrix and then use
- * ConstraintMatrix::condense() on it). In a second step, use the
+ * AffineConstraints::condense() on it). In a second step, use the
* VectorTools::interpolate_boundary_values() function that returns
* a std::map and use it as input for MatrixTools::apply_boundary_values()
* to set boundary nodes to their correct value.
*
* Either behavior can also be achieved by building two separate
- * ConstraintMatrix objects and calling ConstraintMatrix::merge function with
- * a particular second argument.
+ * AffineConstraints objects and calling AffineConstraints::merge()
+ * function with a particular second argument.
*
*
* <h3>Applying constraints indirectly with a LinearOperator</h3>
* assume that we can apply it to a vector but can not necessarily access
* individual matrix entries. $b$ is the corresponding right hand side of a
* system of linear equations $A\,x=b$. The matrix $C$ describes the
- * homogeneous part of the linear constraints stored in a ConstraintMatrix
- * and the vector $k$ is the vector of corresponding inhomogeneities. More
- * precisely, the ConstraintMatrix::distribute() operation applied on a
- * vector $x$ is the operation
+ * homogeneous part of the linear constraints stored in an
+ * AffineConstraints object and the vector $k$ is the vector of
+ * corresponding inhomogeneities. More precisely, the
+ * AffineConstraints::distribute() operation applied on a vector $x$ is the
+ * operation
* @f[
x \leftarrow C\,x+k.
* @f]
*
* // ...
*
- * // system_matrix - unconstrained and assembled system matrix
- * // right_hand_side - unconstrained and assembled right hand side
- * // constraint_matrix - a ConstraintMatrix object
- * // solver - an appropriate, iterative solver
- * // preconditioner - a preconditioner
+ * // system_matrix - unconstrained and assembled system matrix
+ * // right_hand_side - unconstrained and assembled right hand side
+ * // affine_constraints - an AffineConstraints object
+ * // solver - an appropriate, iterative solver
+ * // preconditioner - a preconditioner
*
* const auto op_a = linear_operator(system_matrix);
- * const auto op_amod = constrained_linear_operator(constraint_matrix, op_a);
- * Vector<double> rhs_mod = constrained_right_hand_side(constraint_matrix,
+ * const auto op_amod = constrained_linear_operator(affine_constraints, op_a);
+ * Vector<double> rhs_mod = constrained_right_hand_side(affine_constraints,
* op_a,
* right_hand_side);
*
* solver.solve(op_amod, solution, rhs_mod, preconditioner);
- * constraint_matrix.distribute(solution);
+ * affine_constraints.distribute(solution);
* @endcode
*/