Skip to content

TSFC: support same-mesh ufl.Interpolate in Form kernels - #5258

Open
pbrubeck wants to merge 140 commits into
pbrubeck/fix-minmax-writefrom
pbrubeck/form-interp-tsfc
Open

pbrubeck wants to merge 140 commits into
pbrubeck/fix-minmax-writefrom
pbrubeck/form-interp-tsfc

Conversation

@pbrubeck

@pbrubeck pbrubeck commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

TSFC now compiles same-mesh ufl.Interpolate nodes in normal Form kernels, and this PR ports the feature from PyOP2 to pyop3.

  • Standalone Interpolate and Form(Interpolate) share one code generation path.
  • Same-mesh interpolation across a MixedFunctionSpace supports mat_type="aij" natively.
  • Interpolation into a VertexOnlyMesh uses the same TSFC code generation.
  • Cross-mesh interpolation stays on BaseFormAssembler.

SameMeshInterpolator no longer builds its own op3.loops. It sends the interpolation through the form assembler:

 SameMeshInterpolator._get_callable
-  _build_interpolation_callables      # hand-built op3.loop per sub-expression
+  get_form_assembler(Interpolate, access=...)
+    tsfc_interface.compile_form(..., access)
+      as_pyop3_local_kernel(ast, nargs, access)
+        op3.Function(..., requires_zeroed_output_arguments=True)

MIN and MAX are reduced into the output as MIN_WRITE and MAX_WRITE. TSFC kernels add their result to the output argument, so pyop3 starts these temporaries from zero (see #5543).

TwoFormAssembler._apply_bc now takes the field label of a BC from the BC's own space. Before, a rectangular form such as an interpolation from W = V * V into V failed.

Stacked on #5543, which adds MIN/MAX reductions to pyop3 kernel calls.
Depends on firedrakeproject/fiat#294.

Fixes #5468

Evidence

  • Before (merge of main without the fixes): 7 failures in tests/firedrake/regression/test_interpolate.py
    test_subset_interpolation_reduction[min|max]     -> all entries stay at ±finfo.max
    test_interpolate_periodic_coords_reduction[...]  -> [inf]
    test_mixed_space_bcs                             -> MultipleUniqueEntriesException
    
    After:
    serial: interpolation, cross-mesh, vertex-only, MG grid transfer, pyop3 loop and TSFC tests  1006 passed
    serial: BC, mixed, real-space, matrix and assembly regression tests                           740 passed
    mpiexec -n 2  -m "parallel[2]" interpolation and vertex-only tests                            32 passed
    mpiexec -n 3  -m "parallel[3]" interpolation and vertex-only tests                           271 passed
    

Merge Danger

Door: two-way

Blast Radius: interpolation

All same-mesh interpolation, and the Form kernels that contain it, now go through TSFC and the form assembler. op3.Function gets a new attribute, so kernel caches from before this change must be cleared with firedrake-clean.

The CI commits marked DROP BEFORE MERGE install the FIAT branch and must be dropped before merging.

Contribution assisted by Claude Code (Claude Opus 5.5).

🤖 Generated with Claude Code

Comment thread tsfc/modified_terminals.py
Comment thread tsfc/fem.py Outdated
Comment thread tsfc/ufl_utils.py Outdated
Comment thread firedrake/assemble.py Outdated
@pbrubeck
pbrubeck marked this pull request as draft July 16, 2026 11:18
@pbrubeck

Copy link
Copy Markdown
Contributor Author

This PR should reimplement SameMeshInterpolator as a dispatcher to {Zero|One|Two}FormAssembler. We want to unify the TSFC codepaths for Form assembly and same-mesh interpolation.

Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread tests/firedrake/regression/test_adjoint_operators.py
Comment thread tsfc/fem.py Outdated
Comment thread demos/plate_bending_mitc/plate_bending_mitc.py.rst Outdated
@pbrubeck
pbrubeck force-pushed the pbrubeck/form-interp-tsfc branch from a844911 to f7f5ee3 Compare July 17, 2026 14:42
Comment thread tsfc/driver.py Outdated
Comment thread firedrake/interpolation.py Outdated
Comment thread tsfc/driver.py Outdated
Comment thread firedrake/interpolation.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread demos/plate_bending_mitc/plate_bending_mitc.py.rst Outdated
Comment thread demos/plate_bending_mitc/plate_bending_mitc.py.rst Outdated
@pbrubeck
pbrubeck force-pushed the pbrubeck/form-interp-tsfc branch from f6d360f to 3537776 Compare August 26, 2026 17:13
pbrubeck and others added 9 commits October 14, 2026 00:20
Move get_runtime_tabulation_coordinates next to the other VertexOnlyMesh
map helpers in interpolation.py, so that assemble.py does not add code
inside _GlobalKernelBuilder or to imports that pyop3 rewrites.

Keep unchanged the lines that pyop3 edits nearby: the firedrake.mesh
import in interpolation.py, the cell-size assignment in set_cell_sizes,
and the tsfc imports in mg/kernels.py. Move the new interpolation tests
away from the test that pyop3 skips.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The type pyop2.types.access.Access has no documentation that Sphinx can
link to. Name the access descriptor in the parameter description, so
that the docs need no extra nitpick exception.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kernel calls with MIN_WRITE or MAX_WRITE access now pack a temporary
that starts from the identity of the reduction, and unpack it with a
"min" or "max" assignment. Assignments of type "min" and "max" now get
their intents from assignment_type_as_intent, so they can be put in
a loop.

Fixes #5524

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port the feature from PyOP2 to pyop3. The conflict resolutions come from
pbrubeck/pyop3/form-interp-tsfc-port (927acc0), which ports the feature
onto the pyop3 branch at eb98a70. The changes on main since eb98a70
are applied on top of that port. The result differs from the port only by
those changes, with two exceptions:

* firedrake/__init__.py exports both CommMismatchError from main and
  MismatchingFunctionSpaceError from the feature.
* firedrake/interpolation.py does not take the change on main from
  float(f) to f.dat.global_data.item() in SameMeshInterpolator. The port
  assembles the interpolation through get_form_assembler, which returns
  zero-form results from ZeroFormAssembler. Therefore, the code that
  main changed no longer exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TSFC kernels add their result to the output argument. A MIN_WRITE or
MAX_WRITE temporary that starts from the identity of the reduction
therefore stays at the identity. op3.Function now takes
requires_zeroed_output_arguments, like the PyOP2 Kernel did. When it is
set, these temporaries start from zero. as_pyop3_local_kernel sets it
for TSFC kernels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stack the feature on #5543, which supports MIN and MAX reductions in pyop3.

firedrake/interpolation.py keeps the feature's version. #5543 changes
SameMeshInterpolator._get_tensor to accept MIN_RW and MAX_RW. The feature
removes _get_tensor, and its Interpolator.__init__ already converts MIN_RW
and MAX_RW to MIN_WRITE and MAX_WRITE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TwoFormAssembler._apply_bc required the row and column axes of the matrix
to have the same field label for the index of the boundary condition.
A rectangular form, such as an interpolation from a mixed space into a
single space, does not satisfy this, and test_mixed_space_bcs failed.
The label now comes from the field axis of the space of the boundary
condition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pbrubeck
pbrubeck removed this pull request from stack #5493 October 22, 2026 13:57
@pbrubeck
pbrubeck changed the base branch from main to pbrubeck/fix-minmax-write October 22, 2026 13:57
@pbrubeck
pbrubeck added this pull request to stack #5550 October 22, 2026 13:57
Comment thread tests/firedrake/regression/test_interp_dual.py Outdated
Comment thread tests/firedrake/regression/test_interp_dual.py Outdated
Comment thread tests/firedrake/regression/test_interp_dual.py Outdated
Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py Outdated

This branch has not been deployed

No deployments
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: Interpolating an expression whose Constant vanishes under differentiation fails an assertion in PyOP2

3 participants