Lecture 17 introduced the Sequential Quadratic Hamiltonian method from the Pontryagin point of view. This lecture records the implementation now added to the deal.II code base. The important point is that the code is not a full all-at-once Newton or SQP solver. It is a callback-based SQH driver, specialized here to a distributed Poisson control problem with an plus cutoff control cost.
The new implementation is split into two layers:
SQH<VectorType>incodes/dealii/include/sqh.h, a generic algorithmic loop that knows how to accept and reject Hamiltonian updates;Poisson<dim>incodes/dealii/include/poisson_sqh.handcodes/dealii/source/poisson_sqh.cc, a concrete finite element problem that supplies state solves, adjoint solves, cost evaluation, distances, and the pointwise Hamiltonian maximizer.
The executable codes/dealii/execs/poisson_sqh.cc only initializes MPI,
reads the parameter file through PoissonParameters<dim>, constructs a
Poisson<dim> object, and calls run_sqh().
Mathematical Problem Implemented¶
Let . The code builds a hypercube mesh on this domain and solves a distributed control problem governed by the Poisson equation
with Dirichlet boundary values prescribed by the parameter
Exact solution expression. The control is a discontinuous finite element
field, while the state and adjoint are continuous finite element fields.
The objective functional implemented in Poisson<dim>::cost_function is
The parameters are:
, from
L2 control parameter (alpha);, from
L1 control parameter (beta);, from
Cutoff parameter for L^1 (s);, from
Target expression;, from
Right hand side expression.
Notice the exact cutoff used in the code:
This is not the shifted Huber-like expression ; it is literally the product implemented by
par.beta * (std::abs(u) * (std::abs(u) > par.cutoff_s))at quadrature points.
The weak state equation assembled by assemble_rhs() and solved by solve()
is
The adjoint right-hand side assembled by assemble_adjoint_rhs() is
Therefore the adjoint solve is
with homogeneous Dirichlet boundary conditions.
With the sign convention used by the code, the local Hamiltonian contribution relevant for the control update can be read as
away from the cutoff discontinuity. The forcing term and terms independent of do not affect the pointwise maximization. The SQH regularized Hamiltonian is
where is the current control value.
Ignoring the cutoff in the derivative of the nonsmooth term, the pointwise
maximizer implemented in argmax_u_of_H() is obtained from the two signs of
:
The code returns if and otherwise returns . This is the standard scalar soft-threshold structure associated with the nonsmooth term, expressed in the Hamiltonian maximization convention used here.
Discretization and Linear Algebra¶
The implementation uses two finite element spaces:
FE_Q<dim>for the state and adjoint ;FE_DGQ<dim>for the control .
The state stiffness matrix is assembled once per mesh by
MatrixCreator::create_laplace_matrix(). Both the state and adjoint solves
reuse this matrix and a Trilinos AMG preconditioner inside a CG solve.
The control update is pointwise at quadrature points, but the result must be stored in the DG control space. The code therefore:
evaluates , , and at quadrature points;
computes the scalar Hamiltonian maximizer at each quadrature point;
assembles these values as a control-space right-hand side;
applies a cellwise inverse DG mass matrix to recover the control coefficient vector.
The inverse control mass matrix is assembled cell by cell in
assemble_system(). Since the control space is discontinuous, this inverse
is local to each cell and can be inserted directly into the global sparse
matrix.
The distances used by SQH are true distances computed by
VectorTools::integrate_difference():
Sketch of the SQH Algorithm¶
The implementation follows the robust SQH algorithm from Lecture 17, with
the names used in SQHParameters:
Initial epsilon: initial ;Increase factor for epsilon (sigma): ;Decrease factor for epsilon (zeta): ;Eta: in the sufficient decrease test;Tolerance: stopping tolerance for the control update;Max iterations: maximum number of outer trials.
The actual loop in SQH<VectorType>::optimize() is:
Solve the forward problem for the initial control:
Store the initial cost:
For each trial index , solve the adjoint equation at the last accepted pair:
Compute a trial control by pointwise maximization:
Solve the state equation for the trial control:
Compute
Reject the trial if
On rejection, the code restores the previous state and control, increases
logs the new value of , and repeats from the adjoint and Hamiltonian update step.
Accept the trial otherwise. On acceptance, the code decreases
stores the cost, squared control distance, state distance, and accepted iterate, and emits the accepted-iteration callback.
Stop when
The code records the histories of , , , and
. If deal.II was configured with HDF5 support
(DEAL_II_WITH_HDF5), these histories are written to sqh_log.h5.
The implementation follows the notation of Lecture 17: the control distance
callback returns the norm, and SQH::optimize() squares it to form
This squared quantity is used in the sufficient decrease test, the stopping
test, and the HDF5 history dataset tau.
Mermaid Diagram of the Algorithm¶
Mermaid Diagram of the Code¶
The generic SQH class and the Poisson specialization¶
The generic SQH class stores only algorithmic state. It does not know what a PDE is. Its public interface consists of user-supplied callbacks:
solve_forward_problem(y,u);solve_adjoint_problem(p,y,u);cost_function(y,u);pointwise_argmax_u(u,y,p,w,eps);control_distance(u,w);state_distance(y,yd).
This makes the SQH loop reusable for other problems, provided they can supply the same operations.
The Poisson specialization supplies those callbacks in its constructor. In particular:
the forward callback assembles the right-hand side from and solves the Poisson equation;
the adjoint callback assembles the right-hand side and solves the homogeneous adjoint equation;
the cost callback integrates the tracking, control, and cutoff terms over cells;
the Hamiltonian callback computes the pointwise scalar maximizer and projects it back into the DG control space;
the accepted and rejected iteration callbacks optionally write VTU files, depending on the corresponding parameters.
The result is a compact implementation of the lecture-17 SQH idea:
global PDE solves for state and adjoint, local Hamiltonian optimization for the control, and adaptive regularization through accept/reject decisions.