Skip to content

DO NOT SQUASH merge release - #5554

Merged
pbrubeck merged 9 commits into
mainfrom
connorjward/merge-release
Oct 29, 2026
Merged

pbrubeck merged 9 commits into
mainfrom
connorjward/merge-release

Conversation

@connorjward

Copy link
Copy Markdown
Contributor

No description provided.

Ig-dolci and others added 9 commits October 22, 2026 11:19
Co-authored-by: Connor Ward <c.ward20@imperial.ac.uk>
Need to give notebook images labels - leaving them anonymous leads to
clashes.

Also fixed old reference to firedrake-update.
…d space (#5556)

* Keep DirichletBCs when a matrix-free submatrix spans a whole non-mixed space

* Apply suggestion from @pbrubeck

Co-authored-by: Pablo Brubeck <brubeck@protonmail.com>

---------

Co-authored-by: Pablo Brubeck <brubeck@protonmail.com>
#5127)

* Symbolic coarsening of DirichletBC, and bc data interpolation from other spaces

* BCBase.coefficients

* Apply suggestion from @pbrubeck

* Tape DirichletBC's internal interpolation for pyadjoint

DirichletBC data on a different FunctionSpace was interpolated via a
raw Interpolator.assemble() call, bypassing pyadjoint annotation.
Route it through the top-level assemble() instead, stashing the
Interpolate object so BaseFormAssembler reuses its cached
Interpolator.

DirichletBCBlock's adjoint also assumed the BC data lived on the same
space as the BC itself; add the cross-space case, transforming the
adjoint value through the adjoint of the (linear) interpolation
operator.

Add a regression test: a time-dependent heat equation with BC data
interpolated from a different space at each step, verified with a
Taylor test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* edit AGENTS.md

* Tape DirichletBC's internal interpolation for pyadjoint

DirichletBC data on a different FunctionSpace was interpolated via a
raw Interpolator.assemble() call, bypassing pyadjoint annotation.
Route it through the top-level assemble() instead, stashing the
Interpolate object so BaseFormAssembler reuses its cached
Interpolator.

DirichletBCBlock's adjoint also assumed the BC data lived on the same
space as the BC itself; add the cross-space case, transforming the
adjoint value through the adjoint of the (linear) interpolation
operator.

Fix two further gaps found while making a reused-DirichletBC variant
of the new test actually differentiable, rather than merely
documenting it as broken:
- DirichletBC.function_arg's setter now keeps the FloatingType's
  _ad_args in sync with the assigned value, so reusing a BC via
  set_value()/mutating its data re-tapes against the current value
  instead of the one captured at __init__.
- NonlinearVariationalSolveBlock._forward_solve now applies its own
  recovered, per-step bcs to the cached forward_nlvs solver before
  solving, instead of solving with whatever the shared DirichletBC
  objects' live state currently happens to hold.

Add a regression test, parametrized over constructing a fresh
DirichletBC each timestep vs. reusing one via NonlinearVariationalSolver,
both verified with a Taylor test.

Document the underlying patterns in AGENTS.md in generalized form, so
they transfer to future pyadjoint (or similar record/replay) bugs
beyond this specific one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Apply suggestion from @pbrubeck

* AGENTS.md: document the _ad_annotate_* mixin pattern

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* AGENTS.md: trim and reorder pyadjoint debugging lessons

Sort from cheapest diagnostic wins to deepest architectural gotchas,
and cut each lesson down to headline + one anchoring example.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Compose DirichletBC adjoint with its taped boundary-value interpolation

Make DirichletBCBlock depend on the Function the BC actually applies
(bc._function_arg) rather than the raw user-supplied value. The
interpolation (or, for elements without interpolation support, the
projection) of the boundary value is re-taped through the annotated
assemble/project when the BC is added as a dependency of another block,
so its own AssembleBlock/ProjectBlock supplies the adjoint, TLM, and
recompute. This deletes the hand-rolled interpolation pullback and the
dead constant-handling machinery from DirichletBCBlock.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* AGENTS.md: rewrite pyadjoint notes as composition-first design principles

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* AGENTS.md: make pyadjoint principles generic

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Annotate Projector.project instead of rebuilding a Projector per update

DirichletBC's projection fallback goes back to one cached Projector per
boundary value: rebuilding a solver stack on every function_arg access
crashes when the accessor fires inside PCSetUp_MG's coarsening callback
(gmg on extruded hierarchies, where NCE/NCF cannot interpolate). The
projection stays on the tape through a new ProjectorMixin that
annotates ProjectorBase.project, taping one ProjectBlock per call
against the current source value.

Also locate the DirichletBCBlocks in test_bdy_control by type rather
than by tape position, since the taped boundary-value interpolation
now precedes them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* AGENTS.md: branch pairing, CI triage, and PETSc-callback lessons

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* AGENTS.md: add design and debugging method

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Add CLAUDE.md importing AGENTS.md

Claude Code auto-loads CLAUDE.md from the repository root; the
@AGENTS.md import inlines the agent instructions so they reach every
session without relying on convention or memory.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* adjoint AGENTS.md

* Apply suggestion from @pbrubeck

* Apply suggestion from @pbrubeck

* Drop unrelated AGENTS.md files

* Remove unused firedrake.matrix import from bcs.py

The import was left over from a merge resolution. firedrake.matrix
imports DirichletBC from firedrake.bcs, so the import was circular and
made `import firedrake` fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Clone DirichletBCs in the replay problem

The problem that NonlinearVariationalSolver clones for replay copied the
coefficients of F and J but kept the user's DirichletBCs, so a replay
applied whatever boundary value the BC held at that time. The clone now
reconstructs each DirichletBC with a copy of its boundary value, shared
with F when the value is also a coefficient of F, and the checkpointed
value is assigned before each replay. This replaces the reassignment of
the cloned problem's bcs on every solve.

Also shorten the comments on how DirichletBC is taped, and rename a
local variable in EquationBCSplit.coefficients to match
NonlinearVariationalSolver.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Probe the dual basis to choose interpolation or projection in DirichletBC

The DirichletBC setter tried to interpolate the boundary value and fell
back to projection on any NotImplementedError raised inside assemble.
It now checks V.finat_element.dual_basis first, as in #5258, and builds
either the interpolation or the Projector.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Add second-order Taylor test for time-dependent Dirichlet BC

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
@pbrubeck
pbrubeck merged commit a591c14 into main Oct 29, 2026
5 of 7 checks passed
@pbrubeck
pbrubeck deleted the connorjward/merge-release branch October 29, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants