Skip to content

tsfc: contract each block after unconcatenating - #5297

Open
pbrubeck wants to merge 1 commit into
pbrubeck/fix/dual-enrichedfrom
pbrubeck/hdivcurl-delta
Open

tsfc: contract each block after unconcatenating#5297
pbrubeck wants to merge 1 commit into
pbrubeck/fix/dual-enrichedfrom
pbrubeck/hdivcurl-delta

Conversation

@pbrubeck

@pbrubeck pbrubeck commented Jul 29, 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.

compile_expression_dual_evaluation had a standing TODO:

# TODO: one should apply some GEM optimisations as in assembly,
# but we don't for now.

Apply one of them: contract each assignment once unconcatenate has split the
Concatenate nodes.

This matters for H(div) and H(curl). Those elements are a sum of blocks, each
mapping into one vector component, and with firedrakeproject/fiat#271 each
block selects its component with a Delta. Before unconcatenation the blocks are
branches of a Concatenate, so the Deltas never meet; afterwards each pair of
blocks is its own assignment, the Deltas multiply, and delta elimination cancels
every pair that maps to different components.

Paired with firedrakeproject/fiat#271. Neither PR does anything on its own
without the Deltas there is nothing for the contraction to cancel, and without the
contraction the Deltas never meet.

Effect

Coarse to fine interpolation, as p-multigrid prolongation. Kernel stack
temporaries and wall clock:

temporaries time
NCF 1→4 832K → 68K 3.07×
NCE 1→4 307K → 110K 2.23×
NCE 1→3 131K → 61K 2.23×
NCF 1→3 223K → 38K 1.86×

Form assembly is unchanged; it does not go through this function.

Testing

Matrix-free mult/multTranspose against the assembled matrix, and an
interpolate/restrict round trip, for NCF/NCE on hexahedra and RTCF/RTCE on
quadrilaterals, spectral and fdm variants. Full FIAT suite on the paired branch.

🤖 Generated with Claude Code

compile_expression_dual_evaluation carried a TODO to apply the GEM
optimisations that assembly applies.  Apply one of them: contract each
assignment once unconcatenate has split the Concatenate nodes.

This matters for H(div) and H(curl).  Those elements are a sum of blocks,
each mapping into one vector component, and with firedrakeproject/fiat#270
each block selects its component with a Delta.  Before unconcatenation the
blocks are branches of a Concatenate, so the Deltas never meet; afterwards
each pair of blocks is its own assignment, the Deltas multiply, and delta
elimination cancels every pair mapping to different components.

Coarse to fine interpolation, kernel temporaries and wall clock:

    NCF 1->4  832K -> 68K   3.07x faster
    NCE 1->4  307K -> 110K  2.23x faster
    NCE 1->3  131K -> 61K   2.23x faster

Form assembly does not go through this function and is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pbrubeck
pbrubeck force-pushed the pbrubeck/hdivcurl-delta branch from f5181ab to 7a92a6e Compare July 29, 2026 23:29
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.

1 participant