Skip to content

Adjoint sensitivity silently omits a parameter that enters through a Dirichlet datum #762

Description

@lmoresi

solver.sensitivity(mu, m) (and so solver.gradient(...)) integrates mu . dR/dm over the volume and adds the facet part for a parameter in a natural condition. A parameter that appears only in an essential datum, u|Γ = g(m), contributes nothing, and nothing says so: the gradient comes back zero for a lid velocity or a wall value used as a control.

The missing term is the reaction one. With our convention Kᵀμ = -∂J/∂u,

dJ/dm |_BC = μ_Iᵀ K_IΓ ∂g/∂m = (Kᵀμ)_Γ · ∂g/∂m

since μ_Γ = 0. K_IΓ is not available: PETSc's global vector holds only the unconstrained dofs, and its local residual assembly skips the constrained rows too (ADD_VALUES drops them), so neither the assembled matrix nor a residual evaluation carries them.

Design: assemble Kᵀμ on every node, constrained ones included, as the FEM load ∫ φ f0_adj(μ) + ∇φ · f1_adj(μ) of the adjoint templates on an unconstrained copy of the unknown's space (the load assembler uw.adjoint.dual_on already does this for misfit duals), then dot the constrained rows with ∂g/∂m evaluated at the boundary nodes, honouring the order in which PETSc inserts boundary values where boundaries meet. For Stokes the pressure adjoint enters through the transposed divergence block. Until that lands, a parameter found in an essential datum should be refused loudly rather than dropped.

Found while validating the adjoint against a run with a prescribed wall velocity as the control (branch feature/discrete-adjoint, PR #744).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions