Dirichlet boundary conditions¶
Strong Dirichlet boundary conditions are imposed by providing a list
of DirichletBC
objects. The class
documentation provides the syntax, this document explains the
mathematical formulation of the boundary conditions in Firedrake, and
their implementation.
Mathematical background¶
To understand how Firedrake applies strong (Dirichlet) boundary conditions, it is necessary to write the variational problem to be solved in residual form: find \(u \in V\) such that:
This is the natural form of a nonlinear problem. A linear problem is frequently written: find \(u \in V\) such that:
However, this form can trivially be rewritten in residual form by defining:
In the general case, \(F\) will be always linear in \(v\) but may be nonlinear in \(u\).
When we impose a strong (Dirichlet, essential) boundary condition on \(u\), we are substituting the constraint:
for the original equation on \(\Gamma_D\), where \(\Gamma_D\) is some subset of the domain boundary. To impose this constraint, we first split the function space \(V\):
where \(V_\Gamma\) is the space spanned by those functions in the basis of \(V\) which are non-zero on \(\Gamma_D\), and \(V_0\) is the space spanned by the remaining basis functions (i.e. those basis functions which vanish on \(\Gamma_D\)).
In Firedrake we always have a nodal basis for \(V\), \(\phi_V = \{\phi_i\}\), and we will write \(\phi^0\) and \(\phi^\Gamma\) for the subsets of that basis which span \(V_0\) and \(V_\Gamma\) respectively.
We can similarly write \(v\in V\) as \(v_0+v_\Gamma\) and use the linearity of \(F\) in \(v\):
If we impose a Dirichlet condition over \(\Gamma_D\) then we no longer impose the constraint \(F(u; v_\Gamma)=0\) for any \(v_\Gamma\in V_\Gamma\). Instead, we need to impose a term which is zero when \(u\) satisfies the boundary conditions, and non-zero otherwise. So we define:
where \(g_i\) indicates the evaluation of \(g(x)\) at the node associated with \(\phi_i\). Note that the stipulation that \(F_\Gamma(u; v)\) must be linear in \(v\) is sufficient to extend the definition to any \(v\in V_\Gamma\).
This means that the full statement of the problem in residual form becomes: find \(u\in V\) such that:
Solution strategy¶
The system of equations will be solved by a gradient-based nonlinear solver, of which a simple and illustrative example is a Newton solver. Firedrake applies this solution strategy to linear equations too, although in that case only one iteration of the nonlinear solver will ever be required or executed.
We write \(u = u_i\phi_i\) as the current iteration of the solution and write \(\mathrm{U}\) for the vector whose components are the coefficients \(u_i\). Similarly, we write \(u^*\) for the next iterate and \(\mathrm{U}^*\) for the vector of its coefficients. Then a single step of Newton is given by:
where \(\mathrm{F}(u)_i = \hat F(u; \phi_i)\) and \(J\) is the Jacobian matrix defined by the Gâteaux derivative of \(F\):
The actual Jacobian matrix is given by:
where \(\phi_i\), \(\phi_j\) are the ith and jth basis functions of \(V\). Our definition of the modified residual \(\hat F\) produces some interesting results for the boundary condition rows of \(J\):
In other words, the rows of \(J\) corresponding to the boundary condition nodes are replaced by the corresponding rows of the identity matrix. Note that this does not depend on the value that the boundary condition takes, only on the set of nodes to which it applies.
This means that if, as in Newton’s method, we are solving the system:
then we can immediately write that part of the solution corresponding to the boundary condition rows:
Based on this, define:
Next, let’s consider a 4-way decomposition of J. Define:
Clearly we may write:
As an illustration, assume in some example that the boundary nodes are numbered first in the global system, followed by the remaining nodes. Then (disregarding parts of the matrices which are zero), we can write:
Note again that this is merely illustrative: the decomposition of J works in exactly the same way for any numbering of the nodes.
Using forward substitution, this enables us to rewrite the linear system as:
We can now make two observations. First, the matrix \(J^{00} + J^{\Gamma\Gamma}\) preserves the symmetry of \(J\). That is to say, if \(J\) has any of the following properties, then \(J^{00} + J^{\Gamma\Gamma}\) will too:
symmetry
positive (semi-)definiteness
skew-symmetry
diagonal dominance
Second, if the initial value of \(u\) passed into the Newton iteration satisfies the Dirichlet boundary conditions, then \(\hat{\mathrm{U}}^\Gamma=0\) at every stage of the algorithm. Hence the system to be solved at each iteration is:
A similar argument applies to other nonlinear solution algorithms such as line search Newton.
Implementation¶
Variational problems¶
Both linear and nonlinear PDEs are solved in residual form in Firedrake using the PETSc SNES interface. In the case of linear systems, a single step of Newton is employed.
In the following we will use F
for the residual Form
and J
for the Jacobian Form
. In both cases these
forms do not include the Dirichlet boundary conditions. Additionally
u
will be the solution Function
.
Strong boundary conditions are applied as follows:
Before the solver starts, the initial value
u
provided by the user is modified at the boundary condition nodes to satisfy the boundary conditions.Each time the solver assembles the Jacobian matrix, the following happens.
J
is assembled using modified indirection maps in which the boundary condition node indices have been replaced by negative values. PETSc interprets these negative indices as an instruction to drop the corresponding entry. The result is the matrix \(J^{00}\).The boundary node row diagonal entries of
J
are set to 1. This produces the matrix \(J^{00} + J^{\Gamma\Gamma}\)
Each time the solver assembles the residual, the following happens.
F
is assembled using unmodified indirection maps taking no account of the boundary conditions. This results in an assembled residual which is correct on the non-boundary condition nodes but contains spurious values in the boundary condition entries.The entries of
F
corresponding to boundary condition nodes are set to zero.
Linear systems¶
Linear systems (i.e. systems in which the matrix is pre-assembled) are solved with boundary conditions as follows:
When the user calls
assemble(a)
to assemble the bilinear forma
, no actual assembly takes place. Instead, Firedrake returns aMatrix
object that records the fact that it is intended to be assembled froma
.At the
solve()
call, Firedrake determines which boundary conditions to apply in the following priority order: first, boundary conditions supplied to thesolve()
call. If no boundary conditions are supplied to thesolve()
call, then any boundary conditions applied whenassemble()
was called on A are used, as are any boundary conditions subsequently added withapply()
.In the linear system case, the Jacobian
Form
isa
. Using this and the boundary conditions, Firedrake assembles and solves: