Skip to content

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

Draft
pbrubeck wants to merge 8 commits into
mainfrom
pbrubeck/form-interp-tsfc
Draft

TSFC: support same-mesh ufl.Interpolate in Form kernels#5258
pbrubeck wants to merge 8 commits into
mainfrom
pbrubeck/form-interp-tsfc

Conversation

@pbrubeck

@pbrubeck pbrubeck commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Description

  • Support same-mesh Interpolate nodes in normal TSFC Form kernels.
  • Fuse standalone Interpolate and Form(Interpolate) codegen.
  • Corollary: native mat_type="aij" support for same-mesh Interpolation across MixedFunctionSpaces
  • Corollary: interpolation into VertexOnlyMesh also goes through the unified TSFC codegen.
  • Kept cross-mesh interpolation on BaseFormAssembler.

Depends on
FEniCS/ufl#497
firedrakeproject/fiat#261

def is_modified_terminal(v):
"Check if v is a terminal or a terminal wrapped in terminal modifier types."
while not v._ufl_is_terminal_:
while not (v._ufl_is_terminal_ or isinstance(v, Interpolate)):

@pbrubeck pbrubeck Jul 16, 2026

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.

introduce a helper function is_fem_terminal()

@pbrubeck pbrubeck Jul 16, 2026

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.

Here we need to make sure the dual_arg is indeed a terminal, because TSFC would have to generate a completely separate kernel to be globally assembled beforehand. For now, let the non-terminal dual_arg case be dispatched to BaseFormAssembler

Comment thread tsfc/fem.py
value_dict = {}
for alpha, table in per_derivative.items():
table_qi = gem.Indexed(table, beta + zeta)
if not hasattr(vec_beta, "index_ordering"):

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.

hasattr is an antipattern, check isinstance instead

Comment thread tsfc/ufl_utils.py
preserve_geometry_types = (CellVolume, FacetArea)


class InterpolateMapper(MultiFunction):

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.

DAGTraverser

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
(k, subdomain_id) for k in kernels for subdomain_id in k.kinfo.subdomain_id
)

def _compile_interpolate(self):

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.

This could be fused into the rest of the form assembly

Comment thread firedrake/assemble.py Outdated
Comment thread firedrake/assemble.py
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
if len(self._form.arguments()) == 2 and not self._diagonal:
if not self._bcs:
return None

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.

put this back

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

summands = []
argument_multiindices = ctx.argument_multiindices
if hasattr(argument_multiindices, "values"):

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.

Is this to check if we have a dict or None?

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.

Ah, right we have mismatching conventions: Form uses a tuple and Inteprolate uses a dict

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
integrand_exprs = builder.compile_integrand(integral.integrand(), params, ctx)
integral_exprs = builder.construct_integrals(integrand_exprs, params)
builder.stash_integrals(integral_exprs, params, ctx)
params["mode"] = "vanilla"

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.

Is this hiding a bug?

Comment on lines +832 to +834
from firedrake.assemble import (
OneFormAssembler, TwoFormAssembler, ZeroFormAssembler,
)

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.

TODO: let get_assembler do the dispatch

Comment thread tsfc/driver.py
for mesh, subelement in zip(
domain.iterable_like(element), element.sub_elements
)
]

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.

Some of this could live in compute_form_data

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.

1 participant