Skip to content

Repair the dual basis on QUAD8 and TRI6 faces - #4536

Open
Andreas-Lepak wants to merge 1 commit into
libMesh:develfrom
Andreas-Lepak:transformed-dual-basis-quad8-tri6
Open

Repair the dual basis on QUAD8 and TRI6 faces#4536
Andreas-Lepak wants to merge 1 commit into
libMesh:develfrom
Andreas-Lepak:transformed-dual-basis-quad8-tri6

Conversation

@Andreas-Lepak

Copy link
Copy Markdown

compute_dual_shape_coeffs builds the dual basis from D = diag(\int N_k), but that weight is
exactly 0 at a TRI6 vertex -- leaving those vertex dual shape functions identically zero -- and -1/3
at a QUAD8 corner. Neither is diagnosed.

This biorthogonalizes against the locally quadratic transformed basis of Popp et al. (2012, Sec.
4.4.1) on those two element types, which reduces to a sparse update of D with no extra solve. The
transform is the identity everywhere else and alpha = 0 reproduces diag(d) exactly, so nothing
else changes, there is nothing to regold, and no API changes.

New QUAD8/TRI6 cases in dual_shape_verification_test fail without the fix. Full unit suite passes;
MOOSE first-order dual mortar output is bit-identical before and after.

Refs idaholab/moose#33558

The weight \int N_k used to build the biorthogonal dual basis is not
positive on the serendipity quadratic faces. It is exactly 0 at a TRI6
vertex, which leaves those vertex dual shape functions identically zero,
and -1/3 at a QUAD8 corner, which flips the sign of any per-node
normalization built from it. Neither case is currently diagnosed.

Biorthogonalize instead against the locally quadratic transformed basis
of Popp et al., SIAM J. Sci. Comput. 34(4):B421-B446, 2012, Sec. 4.4.1,
on exactly those two element types. Each vertex absorbs a fraction alpha
of its adjacent mid-edge shapes and each mid-edge shape is scaled by
1 - 2*alpha; making the dual biorthogonal to that basis replaces D by
T^-1 diag(T d), which for this T reduces to a sparse update of D needing
no extra linear solve. With alpha = 1/5 the transformed weights are
strictly positive (QUAD8 -> 1/5 and 4/5, TRI6 -> 1/15 and 1/10) and the
partition of unity is preserved, so the dual basis still reproduces
constants.

The transform is the identity on every other element type, and the
alpha = 0 limit reproduces diag(d) exactly, so all other dual bases are
unchanged. dual_shape_verification_test gains QUAD8 and TRI6 cases
covering positivity, reproduction of constants, and biorthogonality
against the transformed basis.

Refs idaholab/moose#33558

Co-authored-by: Claude <noreply@anthropic.com>
@roystgnr

roystgnr commented Sep 2, 2026

Copy link
Copy Markdown
Member

I've started up CI.

Walk me through the math on this, and make sure I'm not misunderstanding? The standard dual basis on these elements can't be made to satisfy both biorthogonality and the partition-of-unity property at once without going degenerate, so we do a slight change-of-basis on the primal bases and then we find a dual to that changed basis instead? How does that work at the application level, when we no longer have a dual to the original basis but we aren't exposing the altered basis?

I think I'm okay with this, under the circumstances (though it pains me to see a non-serendipity element behaving as badly and requiring as much of a hack as a serendipity!), but we've got to document what's going on in the headers, not just the implementation. Somehow I was an idiot and approved the original addition of FEBase::get_dual_phi() without a Doxygen comment, but let's fix that now. "get_dual_phi()" at least used to do what it said on the tin, but if we want "get_dual_phi()" to actually mean "get_dual_phi_but_maybe_not_our_dual_just_close_enough()" then we're going to need a comment to warn users of that.

@moosebuild

Copy link
Copy Markdown

Job Coverage, step Generate coverage on 676a4ae wanted to post the following:

Coverage

0a0a9d #4536 676a4a
Total Total +/- New
Rate 65.94% 65.94% +0.01% 100.00%
Hits 79392 79407 +15 8
Misses 41014 41007 -7 0

Diff coverage report

Full coverage report

This comment will be updated on new commits.

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.

3 participants