Skip to content

p-multigrid: remove custom interpolation code - #5289

Open
pbrubeck wants to merge 2 commits into
pbrubeck/hdivcurl-deltafrom
pbrubeck/remove-pmg-parloop
Open

p-multigrid: remove custom interpolation code#5289
pbrubeck wants to merge 2 commits into
pbrubeck/hdivcurl-deltafrom
pbrubeck/remove-pmg-parloop

Conversation

@pbrubeck

@pbrubeck pbrubeck commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Stack

Merge in this order, each PR retargets to main once the one above it lands:

# PR what
1 firedrakeproject/fiat#269 gem: sum factorise independent contractions
2 firedrakeproject/fiat#271 FInAT: select H(div)/H(curl) components with a Delta
3 firedrakeproject/fiat#268 FInAT: dual evaluate on each sub-element's own points
4 #5295 tsfc: dual evaluation against a Cofunction
5 #5289 p-multigrid: remove custom interpolation
6 #5297 tsfc: contract each block after unconcatenating

2 and 6 are a pair: neither is worth anything alone, though 2 is harmless on its
own — it changes how a component is selected, not what is selected.
5 and 6 are siblings on 4, in either order.

Only 4 carries a DROP BEFORE MERGE commit, pinning FIAT to
pbrubeck/fix/dual-enriched, which is now the top of the FIAT stack; 5 and 6
inherit it. Drop it once the FIAT side has landed.

Removes ~1050 lines of hand-written interpolation machinery from
firedrake/preconditioners/pmg.pyStandaloneInterpolationMatrix,
MixedInterpolationMatrix, kronmxv, get_permutation_to_nodal_elements,
evaluate_dual and friends — and replaces the p-multigrid transfer operators with
the generic assemble(interpolate(TrialFunction(cV), fV)). The helpers that are still
needed move to firedrake/preconditioners/fdm.py.

Stacked on #5295, which fixes the matrix-free adjoint interpolation this now relies on.
Also needs firedrakeproject/fiat#268 — see the DROP BEFORE MERGE commit, which
applies to both PRs in the stack.

Bugs this exposed

Routing the transfers through the generic interpolation path uncovered three defects
that the bespoke code had been bypassing. Two are fixed in the PRs below this one; the
Firedrake-side ones are in the second commit here:

  • Rectangular matrices got the wrong bcs. Assembling a two-form Interpolate
    matrix-free passed the same bcs as both the row and the column bcs of the
    ImplicitMatrixContext, and left on_diag at its default of True. Neither holds
    when interpolating between two different spaces: applying the target space's bcs to
    the source side raised Cofunction defined on incompatible FunctionSpace, and
    on_diag made multTranspose write the row values into the column vector. The bcs
    are now split by the space they are defined on, as the assembled path already does,
    and on_diag is set from whether the two spaces coincide. A bc on a component of a
    mixed space is defined on an IndexedProxyFunctionSpace rather than on the space
    itself, so the comparison walks up to the top-level parent — without that, bcs on a
    mixed space were silently dropped from both lists and the preconditioner degraded
    (test_p_multigrid_mixed needed 8 iterations instead of 7).

  • Nullspace coarsening used a deleted API. coarsen_nullspace called
    interpolate.getNestSubMatrix(i, i), which only MixedInterpolationMatrix provided.
    It now recurses over the sub-spaces and builds the interpolation matrix locally.

Testing

suite result
tests/firedrake/regression/test_fdm.py 16 passed
tests/firedrake/multigrid/test_p_multigrid.py 23 passed
tests/firedrake/multigrid 338 passed, 22 skipped
interpolation regression suites 175 passed
make srclint clean

Matrix-free mult/multTranspose were also compared against the assembled matrix
across 47 element/mesh combinations, all agreeing to machine precision.

🤖 Generated with Claude Code

Comment thread firedrake/interpolation.py Outdated
return Interpolate(expr, V, **kwargs)


def _bc_root(bc: DirichletBC) -> WithGeometry:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interpolation seems like a strange place to have this. Maybe put it as a method on BCBase?

Comment on lines +371 to +374
if is_dual(Vrow):
Vrow = Vrow.dual()
if is_dual(Vcol):
Vcol = Vcol.dual()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if is_dual(Vrow):
Vrow = Vrow.dual()
if is_dual(Vcol):
Vcol = Vcol.dual()
Vcol = Vcol.dual()

Comment thread firedrake/interpolation.py Outdated
pbrubeck and others added 2 commits July 30, 2026 00:28
Assembling a two-form Interpolate matrix-free passed the same bcs as both
the row and the column bcs of the ImplicitMatrixContext, and left on_diag
at its default of True.  Neither holds for interpolation between two
different spaces: applying the target space's bcs to the source side
raised "Cofunction defined on incompatible FunctionSpace", and on_diag
made multTranspose try to write the row values into the column vector.

Split the bcs by the space they are defined on, as the assembled path
already does, and set on_diag from whether the two spaces coincide.  A bc
on a component of a mixed space is defined on an IndexedProxyFunctionSpace
rather than on the space itself, so compare against the top-level parent,
which BCBase.function_space now returns on request.

Coarsen the p-multigrid nullspace with a locally built interpolation
matrix, rather than through getNestSubMatrix, which only the removed
MixedInterpolationMatrix provided.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pbrubeck
pbrubeck force-pushed the pbrubeck/remove-pmg-parloop branch from 3d81cdf to 33be7ba Compare July 29, 2026 23:29
@pbrubeck
pbrubeck changed the base branch from pbrubeck/fix/dual-enriched to pbrubeck/hdivcurl-delta July 29, 2026 23:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

base:main Run this PR using a main (dev) build

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants