Select H(div)/H(curl) components with a Delta - #270
Merged
Conversation
This was referenced Jul 29, 2026
pbrubeck
force-pushed
the
pbrubeck/fix/dual-enriched
branch
from
July 29, 2026 18:27
bdb3b8b to
e3ada2f
Compare
pbrubeck
force-pushed
the
pbrubeck/hdivcurl-delta
branch
from
July 29, 2026 18:27
d28018d to
a75a245
Compare
Author
|
Closed by mistake, not merged. Reordering the stack so that this PR sits below #268 put this branch's commit into Reopened as #271 — same branch, same commit ( |
pbrubeck
added a commit
to firedrakeproject/firedrake
that referenced
this pull request
Jul 29, 2026
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>
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.
An H(div) or H(curl) element is a sum of blocks, each mapping the value of a
wrapped tensor product element into one component of a vector. The transformers
expressed that by padding a
ListTensorwith zeros:Contracting two such blocks over the value index cannot cancel the pairs that map
to different components, because the zeros are entries of a tensor rather than a
property of the expression. So an interpolation between two H(div) spaces keeps
every pair of blocks in the kernel, including the ones that are identically zero.
Select the component with a
Deltainstead:A contraction of two blocks then carries a product of Deltas, which delta
elimination cancels unless the blocks map to the same component. The transform now
takes the value index and returns the component it selects, rather than returning a
list of components to be indexed.
Paired with firedrakeproject/firedrake#5297, which contracts each block once
unconcatenatehas separated them — that is where the Deltas meet pairwise.Neither PR does anything on its own.
Effect
Coarse to fine interpolation, as p-multigrid prolongation. Kernel stack
temporaries and wall clock:
Form assembly is unchanged — identical kernel sizes and times to within noise.
gem.optimise.contractionalready pulled theseListTensors out to be outermost sothat each entry could be factorised, so form compilation had already recovered the
structure by another route. The win is specific to dual evaluation.
Testing
Full FIAT suite. In Firedrake, matrix-free
mult/multTransposeagainst theassembled matrix, and an interpolate/restrict round trip, for NCF/NCE on hexahedra
and RTCF/RTCE on quadrilaterals, spectral and fdm variants.
Note on
is_orthogonalIt now contracts the two maps with the gem interpreter, which neither belongs in an
element constructor nor scales. That is a deliberate temporary workaround and is
flagged with a
TODO: the products of Deltas already say which components coincide,so this should be read off symbolically, without the interpreter and without delta
elimination.
🤖 Generated with Claude Code