Skip to content

Hu–Zhang–Zhang element - #295

Open
BorisAndrews wants to merge 3 commits into
firedrakeproject:mainfrom
BorisAndrews:BorisAndrews/hu-zhang-zhang
Open

BorisAndrews wants to merge 3 commits into
firedrakeproject:mainfrom
BorisAndrews:BorisAndrews/hu-zhang-zhang

Conversation

@BorisAndrews

Copy link
Copy Markdown

Summary

Adds a lowest-order H(grad curl)-conforming element on tetrahedra, based on the element of Hu, Zhang and Zhang, A Family of Finite Element Stokes Complexes in Three Dimensions, SINUM 60(1), 2022 (doi:10.1137/20M1358700). It is registered as "Hu-Zhang-Zhang" / "HZZ", degree 1, with covariant Piola mapping.

The element completes the Stokes complex

CG1 --grad--> HZZ --curl--> GN --div--> DG0,

where GN is the existing GuzmanNeilanFirstKindH1. The goal is to have access to a 3D Stokes complex with H(grad curl) (instead of the H2 --grad--> H1(curl) --curl--> ... Stokes complex) in Firedrake. This allows for streamfunction formulations of incompressible flow with a GN velocity, with fewer global DoFs (4V + E rather than 3V + F + C).

The element

  • DoFs (18): curl u at the 4 vertices, plus tangential moments on the 6 edges. The edge functionals are the lowest-order Nedelec ones.
  • Shape functions: C0 piecewise quartics on the Alfeld split whose curl lies in the Guzmán–Neilan space.

This is a gauge variant of the paper's element

For a fiddly reason, the space is not quite the one constructed in the paper. The DoFs, the curl of the space, H(grad curl)-conformity and exactness of the complex all match. The curl-free part of the shape functions does not.

The paper addresses this part with a correction built from Poincaré operators based at the origin. That correction would not be invariant under affine maps, so I don't know if the physical space would be recoverable from the reference cell by a basis transformation. HuZhangZhangSpace instead defines the extended space via four conditions:

  • curl u lies in the extended GN space;
  • u·t is constant on each edge;
  • a Koszul gauge on each face;
  • the same gauge in the interior, against C1 bubbles on the Alfeld split.

Each condition is invariant under covariant Piola. The resulting space differs from the paper's by gradients; I've made this explicit in the docstrings.

Basis transformation

finat.HuZhangZhang is a PhysicallyMappedElement. Its DoFs are GN functionals composed with the curl, so its transformation is assembled from GuzmanNeilanFirstKindH1.basis_transformation. The only new ingredient is that the normal face moments of the curl aren't DoFs; we get them as the sums of the edge moments by Stokes.

Tests

  • test/FIAT/unit/test_hu_zhang_zhang.py, on the reference cell and on a distorted cell:
    • DoF layout;
    • grad CG1 ⊆ HZZ;
    • curl HZZ ⊆ GN, with rank of the curl equal to dim − 3;
    • curl of the reduced 18-DoF space lies in reduced GN;
    • tangential traces of basis functions not associated with a face vanish on that face.
  • test_zany_mapping.py::test_hu_zhang_zhang, which compares the FInAT transformation with the element constructed directly on a physical cell.
  • The full test/FIAT/unit and test/finat suites pass locally, and make lint is clean. These were run against fenics-ufl 2025.3, not UFL main.

Firedrake-level checks were also run locally; they are not included in this PR. On distorted structured and unstructured tetrahedral meshes, serially and on 2 MPI ranks:

  • the jumps of ψ×n and of curl ψ across facets are about 1e-13;
  • a Stokes solve for the streamfunction in HZZ, with no-slip imposed as zero Dirichlet data on ψ, reproduces the GN–DG0 velocity to about 1e-12.

Limitations

  • Lowest order only; degree != 1 raises NotImplementedError.
  • interpolate into HZZ, and nonzero DirichletBC data, are not supported.
  • The transformation relies on GN's facet DoF layout (normal moment first, then the tangential ones), so a change there would need matching changes here.
  • UFL has no H(grad curl) Sobolev space, so the family's registered as HCurl.

AI use

This was developed in part by Claude Code (Opus 5), in particular including verification of the implementation, and the test files.

@connorjward

Copy link
Copy Markdown

I just want to flag our AI contribution policy:

The contributor must be in a position to license the code under our licences. This means for example that 'mechanical work' (e.g. search and replace) is likely to be acceptable, but code with a substantive creative/scientific element is unlikely to be so because of the risk of code from other projects being reproduced verbatim in breach of their licences.

Can you comment on this?

@BorisAndrews

Copy link
Copy Markdown
Author

Eh, so I used it to write the tests and check my code. The latter part of that though it did find errors and make suggestions, that I did then act upon, so I'd call that a "substantive creative/scientific element" I guess! Will just close — it's easier that way (and who else is on a hunt for whacky elements like Hu–Zhang–Zhang but me anyway haha)

@pefarrell

Copy link
Copy Markdown

Can we reconsider this PR? I for one think it would be wonderful to have Hu-Zhang-Zhang and expect I would use it for real problems.

I would describe writing tests more like 'mechanical work' than with a substantial creative/scientific element.

More importantly, it's extremely unlikely that there's a FIAT implementation of HZZ out there on the internet that has not been contributed back to Firedrake, so I estimate the 'risk of code from other projects being reproduced verbatim in breach of their licenses' to be extremely low.

@connorjward

Copy link
Copy Markdown

Yeah I think that the contribution as described should be fine. Just thought it important to check.

@connorjward connorjward reopened this Sep 18, 2026
@BorisAndrews

Copy link
Copy Markdown
Author

Sorry, I just got a little nervous and didn't want to go against the policy. I agree with Patrick though. Indeed Kaibo (i.e. Hu) wasn't aware of Hu–Zhang–Zhang being implemented anywhere.

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