diff --git a/docs/src/manual/constraints.md b/docs/src/manual/constraints.md index 638c640063..f2fbb490bf 100644 --- a/docs/src/manual/constraints.md +++ b/docs/src/manual/constraints.md @@ -10,28 +10,54 @@ PDEs can in general be subjected to a number of constraints, g_I(\boldsymbol{a}) = 0, \quad I = 1 \text{ to } n_c ``` -where ``g`` are (non-linear) constraint equations, $\boldsymbol{a}$ is a vector of the +where `g` are (non-linear) constraint equations, $\boldsymbol{a}$ is a vector of the degrees of freedom, and ``n_c`` is the number of constraints. There are many ways to enforce these constraints, e.g. penalty methods and Lagrange multiplier methods. A special -case is when the constraint equations are affine/linear, in which they can be enforced in a -special way. This is explained below. +case is when the constraint equations are affine/linear, explained below. ## Affine constraints Affine (or linear) constraints can be written as ```math -a_i = \sum_j C_{ij} a_j + g_i +a_1 = 5a_2 + 3a_3 + 1 \\ +a_4 = 2a_3 + 6a_5 \\ +\dots ``` -or in matrix form +where $a_1$, $a_2$ etc. are system degrees of freedom. In Ferrite, we can account for +such constraint using the `ConstraintHandler`: + +```julia +ch = ConstraintHandler(dh) +lc1 = AffineConstraint(1, [2 => 5.0, 3 => 3.0], 1) +lc2 = AffineConstraint(1, [3 => 2.0, 5 => 6.0], 0) +add!(ch, lc1) +add!(ch, lc2) +``` + +When creating the sparsity pattern for the stiffness matrix, it is important to also include the `ConstraintHandler` +as an argument because the affine constraints will affect the sparsity pattern: + +```julia +K = create_sparsity_pattern(dh, ch) +``` + +When solving the system, we account for the affine constraints in the same way as we account for +`Dirichlet` boundary conditions; by first calling `apply!(K, f, ch)`. This will condense `K` and `f` inplace (i.e +no new matrix will be created). Note however that we must also call `apply!` on the solution vector after +solving the system to enforce the affine constraints (calling `apply!` after solving the system is not needed +when we only have `Dirichlet` boundary conditions) + +```julia +# ... +# Assemble K and f... + +apply!(K, f, ch) +a = K\f +apply!(a, ch) # enforces affine constraints -```math -\boldsymbol{a}_c = \boldsymbol{C} \boldsymbol{a}_f + \boldsymbol{g} ``` -where ``\boldsymbol{a}_c`` is a vector of the constrained dofs, ``\boldsymbol{a}_f`` is a -vector of free dofs, ``\boldsymbol{g}`` contains possible inhomogeneities, and -``\boldsymbol{C}`` is matrix defining the connectivity between constrained and free dofs. ...