Skip to content

solver.gradient() takes the adjoint of an unconverged forward solve and returns a wrong-signed number #804

Description

@lmoresi

_adjoint_support documents that an unconverged solve is refused ("a linearisation about a state the solve never reached is not the adjoint of anything"), caught after the fact by _record_solve_outcome. That catch is on the recorded/transcript path. A direct solver.solve() followed by solver.gradient(...) is not refused.

Reproduced on scratch/adjoint-merge (82e697b): softmin viscoplastic box, snes_max_it = 2.

forward reason -5                       # DIVERGED_MAX_IT
gradient RETURNED {eta_min: 0.2197}     # converged answer: -0.1423 (FD agrees to 4e-8)

Wrong sign, no warning. Script: ~/+Simulations/adjoint_note_checks/unconverged_refusal.py.

UWTN 2026-020 (draft) currently states that "the library refuses to take the adjoint of a solve that did not converge", so either the guard moves into adjoint_solve/gradient (check snes.getConvergedReason() > 0 on the solver that did the solving) or the note's sentence goes. The first seems right: the note's argument — a multiplier is undefined off the constraint manifold — is exactly why this should be an error rather than a number.

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