For many problems it pays to define a (weighted flux) quantity of
interest as a weighted residual:
Q(u) := R(u,phi)
against a lift function (i.e. only important on the Dirichlet
This can give a higher-order-accurate estimate of the QoI, and it can
fix an otherwise ill-defined adjoint problem by replacing an irregular
forcing function dQ/du with a boundary condition z_\Gamma = phi.
For various reasons you might want to add a "remainder" term, though:
Q(u) := R(u,phi) + S(u). Perhaps your QoI has a non-flux component,
perhaps your flux needs a discontinuous weighting function but you
only have continuous phi_h available, whatever.
When doing various adjoint tricks, we might need independent access to
both Q and S.
My current proposal is to:
1) Change the current System::assemble_qoi behavior. The user_QoI
would now be reinterpreted as an assembly only of S(u). The new
assemble_qoi would call user_QoI to evaluate S(u) and would then check
for any heterogeneous adjoint Dirichlet constraints to (if necessary)
evaluate and add in R(u,phi).
The obvious alternatives are:
2) Keep assemble_qoi as-is, interpreting it as a full assembly of
Q(u). Force/allow the user to integrate R(u,phi) manually if they're
using a heterogeneous QoI. Add a virtual function
("System::assemble_qoi_remainder"?) which defaults to a call to
user_QoI but which would be reimplemented by heterogeneous QoI apps to
give an assembly of S(u) alone.
3) Keep assemble_qoi as-is, interpreting it as a full assembly of
Q(u). No new APIs are added. When S(u) is needed, user code is asked
for Q(u) but then library code evaluates and subtracts off R(u,phi).
All these possibilities are backwards compatible for anyone not using
adjoint dirichlet boundaries.
Although I don't like the "change of API interpretation" in (1), I
think it's preferable to the "extra work for users" in (2) or the
"extra work for users which is often redundant" in (3).
Anyone else have suggestions or preferences?