Skip to content

p-multigrid: remove custom interpolation code - #5289

Open
pbrubeck wants to merge 21 commits into
mainfrom
pbrubeck/remove-pmg-parloop
Open

p-multigrid: remove custom interpolation code#5289
pbrubeck wants to merge 21 commits into
mainfrom
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#271 FInAT: select H(div)/H(curl) components with a Delta
2 firedrakeproject/fiat#268 FInAT: dual evaluate on each sub-element's own points
3 #5289 p-multigrid: remove custom interpolation

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.

Depends on firedrakeproject/fiat#268

Fixes #5391 by removing the transfer matrix cache

🤖 Generated with Claude Code

Comment thread firedrake/interpolation.py Outdated
Comment thread firedrake/interpolation.py Outdated
Comment thread firedrake/interpolation.py Outdated
@pbrubeck
pbrubeck force-pushed the pbrubeck/remove-pmg-parloop branch from 8b84e62 to 41c33c8 Compare July 29, 2026 18:30
@pbrubeck
pbrubeck force-pushed the pbrubeck/fix/dual-enriched branch 2 times, most recently from 168ee7b to 6072eee Compare July 29, 2026 23:29
@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
@pbrubeck
pbrubeck force-pushed the pbrubeck/hdivcurl-delta branch from a992610 to 537d1b5 Compare August 18, 2026 22:22
@pbrubeck
pbrubeck force-pushed the pbrubeck/remove-pmg-parloop branch from 2cdcc16 to 59e617b Compare August 18, 2026 22:22
Comment thread firedrake/functionspaceimpl.py Outdated
Comment thread firedrake/functionspaceimpl.py Outdated
@pbrubeck
pbrubeck force-pushed the pbrubeck/remove-pmg-parloop branch from e9e3a1e to 59e617b Compare August 24, 2026 22:24
pbrubeck and others added 5 commits August 26, 2026 12:44
An element whose functionals do not all evaluate on the same points is a
direct sum, and has a dual basis only on each of its sub-elements, not one
weight tensor on one point set.  Reconstructing it as a runtime Quadrature
space only ever wanted the points, so ask for those directly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
Comment thread firedrake/functionspaceimpl.py Outdated
@pbrubeck
pbrubeck requested a review from connorjward August 26, 2026 15:34
Comment thread firedrake/preconditioners/fdm.py
@pbrubeck pbrubeck added the LLM used An LLM was used in the production of this PR label Aug 26, 2026
The dual basis of a restricted element is a Concatenate, and a Cofunction
dual argument sums over the index that concatenates it.  Forming that
contraction first leaves the Concatenate indexed by a reduction index that
no assignment variable carries, so unconcatenate has nothing to split it
against and it reaches argument factorisation, which cannot break it up.

Split the pair of the dual coefficient and the tabulation first, as
assembly already does for coefficient evaluation, and contract each block
over the basis indices of its own block.

Interpolating between facet-restricted spaces, as p-multigrid does under
FacetSplitPC, raised FactorisationError before this.  The error escaped a
PETSc callback, which left the preconditioner half built, and destroying it
later segfaulted.

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

Copy link
Copy Markdown
Contributor

This is failing an awful lot of tests. Is it ready for review?

@pbrubeck

Copy link
Copy Markdown
Contributor Author

This is failing an awful lot of tests. Is it ready for review?

I'll be fixing those today. I'll ask for review when it's passing. In principle it should be a small fix to make everything pass

@connorjward

Copy link
Copy Markdown
Contributor

Can you check if this fixes #5391? I just debugged that down to it being (I think) to do with StandaloneInterpolationMatrix.

pbrubeck and others added 2 commits August 27, 2026 10:23
Every worker of the `tests/tsfc` session segfaults at its first
`compile_form`, in `petsctools.cite` -> `PETSc.Sys.registerCitation`, because
`PetscCitationsList` is still NULL: PETSc was never initialised.

`petsc4py.lib.ImportPETSc` puts the extension module straight into
`sys.modules`, bypassing the `petsc4py/PETSc.py` shim that calls
`PETSc._initialize`.  Once that has happened no later `from petsc4py import
PETSc` initialises anything.  The same fingerprint shows in the firedrake
sessions: on `main` the conftest's `import pyadjoint` initialises PETSc
before `firedrake/__init__.py` does, and `petsctools.init` warns that it is
too late; on this branch that warning never appears.

This does not reproduce locally, so record who calls `ImportPETSc` and report
the state of PETSc once collection has imported every test module.

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

Copy link
Copy Markdown
Contributor Author

Can you check if this fixes #5391? I just debugged that down to it being (I think) to do with StandaloneInterpolationMatrix.

It does fix it.

@pbrubeck

Copy link
Copy Markdown
Contributor Author

This is failing an awful lot of tests. Is it ready for review?

This is ready for review

fiat pbrubeck/fix/dual-enriched (this PR's FIAT dependency) landed
review fixes at firedrakeproject/fiat@46e28722.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjZ6kYK1tmLfm6wUxXwVtG

@connorjward connorjward left a comment

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.

In general I think this is a wonderful change.

Comment thread tsfc/driver.py
Comment thread tests/tsfc/test_dual_evaluation.py Outdated
Comment thread .github/actions/install/action.yml Outdated
Comment thread firedrake/interpolation.py Outdated
Comment thread firedrake/preconditioners/pmg.py
@pbrubeck
pbrubeck force-pushed the pbrubeck/remove-pmg-parloop branch from bd96c37 to 10666d2 Compare September 7, 2026 14:47
The Cofunction dual argument contracts over the nodes, but the basis
indices it sums were not declared as quadrature indices, so
spectral.flatten dropped them from the sum factorisation tail ordering
and the contraction ran dense.  Declare them alongside the points.

This pays off with fiat#268, which cancels Deltas over the indices a
monomial contracts, so the node sum against the dual basis of a point
evaluation element collapses rather than being carried out.  That
refactorisation also folds a constant out of an IndexSum, which
test_refactorise pins.

Interpolation between facet-restricted elements on a hexahedron costs
6.8x fewer flops at degree 11, growing as p^2.89 rather than p^4.20,
matching what the coefficient path already achieved.

Set on_diag in ImplicitMatrixContext.__init__ rather than as a class
attribute the caller overwrites, and give BCBase a parent_function_space
property in place of the function_space(parent=True) flag.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Vnd4VHtANbfmiMxSPSXSG
@pbrubeck
pbrubeck force-pushed the pbrubeck/remove-pmg-parloop branch from 10666d2 to df69102 Compare September 7, 2026 14:48
pbrubeck and others added 4 commits September 7, 2026 16:00
The exact solution of that Poisson problem lies in the space, so what the
test measures is round-off, and 1e-15 left it no margin: the error came
out at 4.8e-16 here and 1.05e-15 in CI, on either side of the bound.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F1K5upgeZTKWj9m4tHt9Vn
The folded constant this expected came from collect_monomials rebuilding
every monomial's rest from a flattened factor list, which costs flops on
form assembly.  fiat now reflattens only when a Delta cancels, so the
monomial keeps the grouping the recursion chose.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158RTiFnSyhgKbsbz11JMak
@pbrubeck
pbrubeck requested a review from connorjward September 8, 2026 12:20
connorjward
connorjward previously approved these changes Sep 8, 2026
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 LLM used An LLM was used in the production of this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: PMGPC keeps every mesh alive, so memory grows without bound when solvers are built in a loop

3 participants