Conversation
pbrubeck
changed the base branch from
pbrubeck/interpolate-holes
to
pbrubeck/pullback-apply-inverse-holes
September 8, 2026 01:04
pbrubeck
changed the base branch from
pbrubeck/pullback-apply-inverse-holes
to
pbrubeck/pullback-apply-inverse
September 8, 2026 01:13
pbrubeck
force-pushed
the
pbrubeck/pullback-apply-inverse
branch
from
September 8, 2026 10:51
3ea4e9d to
6f6b47d
Compare
pbrubeck
force-pushed
the
pbrubeck/interpolate-reference-lowering
branch
2 times, most recently
from
September 10, 2026 23:09
6931489 to
6cdee45
Compare
A form compiler evaluates an Interpolate on the reference cell of its target element, so the operand has to be mapped there and the result pulled back for the integrand that holds it. TSFC did this in a pass of its own, before it called compute_form_data, and carried its own copy of the inverse maps. apply_interpolate_pullbacks does it here, at the start of compute_form_data and under the same switch as the other pull backs, on top of the pull backs' apply_inverse. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0155wQMTMSGiF9a6TbyTVK5P
Both interpolation pull back passes were the older MultiFunction style, while the rest of the algorithms package has moved to DAGTraverser. InterpolatePullbackApplier becomes a DAGTraverser, with the Interpolate rule a postorder handler, and apply_interpolate_pullbacks maps it over the integrands directly, as the traverser walks the DAG itself. apply_inverse_pullback keeps its signature for TSFC and now wraps InversePullbackApplier, which carries the element and the fallback domain as traverser state. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BP8aGcL37egqaMX9zXAYgX
FunctionPullbackApplier was the last MultiFunction in the module, so it joins the interpolation pass as a DAGTraverser: the form argument rule dispatches on FormArgument and the traverser's own memoisation replaces memoized_handler. apply_inverse_pullback goes back to being a plain function. It is a rule on a single node, not a traversal: it must not recurse into its argument, or the interpolations there would be lowered a second time by the pass that runs after it. Wrapping it in a traverser only hid that. The two traversers are separate passes because compute_form_data runs them at different points, with derivative expansion and degree estimation in between. Neither pass had tests. test_apply_function_pullbacks covers the pull back of form arguments in a form, the round trip of apply_inverse_pullback against each pull back (through cancel_jacobian_products, which cancels the Jacobian factors the two maps insert), its shape and domain checks, and the lowering of plain, nested and in-form interpolations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
FormArgument itself declares neither ufl_function_space nor ufl_element, so annotating the handler with it fails mypy. Its subclasses Argument and Coefficient are what actually reach the rule, and both carry them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pbrubeck
force-pushed
the
pbrubeck/pullback-apply-inverse
branch
from
September 10, 2026 23:40
3a43502 to
fbdb7d7
Compare
pbrubeck
force-pushed
the
pbrubeck/interpolate-reference-lowering
branch
from
September 10, 2026 23:40
6cdee45 to
ea2bddd
Compare
|
This is something I also experienced when trying to add interpolate to FFCx. Great to resolve it at the source. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
A form compiler evaluates an
Interpolateon the reference cell of its target element. The operand therefore has to be mapped to that reference cell, and the result pulled back to the physical cell for the integrand that holds it. TSFC did that in a pass of its own, run just before it calledcompute_form_data, and carried its own copy of the inverse Piola maps to do it.This moves the step into UFL:
apply_inverse_pullback(expr, element, domain)maps a physical expression onto an element's reference cell, checking the shape on the way in and out. It is the inverse of whatFunctionPullbackApplierdoes to a form argument, and it is TSFC'sapply_mappingwith the maps themselves replaced bypullback.apply_inverse.InterpolatePullbackApplierrewrites eachInterpolatein an integrand, andapply_interpolate_pullbacksmaps it over a form.compute_form_dataruns it at the start, underdo_apply_function_pullbacks, so the operand a form compiler sees is the one the target element dual-evaluates. It runs before the other lowering, which is where TSFC's own pass ran, so the estimated degrees and everything downstream see the same form they see today.The node is built as a
ufl.Interpolaterather than by reconstructing the one in the integrand, because the mapped operand no longer has the physical value shape that a subclass may check.Stacking
Based on #71, which gives the pull backs their
apply_inverse, which in turn is based onpbrubeck/interpolate-holes(FEniCS#497), whereInterpolate.ufl_elementcomes from.Those are the same branches as FEniCS#511 and FEniCS#512, which propose the same two commits upstream against
main.Firedrake's side of the move — deleting
apply_mapping,InterpolatePullbackApplierand the pre-pass intsfc/driver.py, 200 lines in all — is onpbrubeck/form-interp-tsfc. With this branch in place,tests/tsfcand the interpolation, assembly, multigrid and vertex-only suites are green.🤖 Generated with Claude Code
https://claude.ai/code/session_0155wQMTMSGiF9a6TbyTVK5P