Skip to content

Add PETSc nullspace support to Stokes - #91

Merged
lmoresi merged 2 commits into
underworldcode:developmentfrom
gthyagi:feature/stokes-nullspace
Mar 25, 2026
Merged

Add PETSc nullspace support to Stokes#91
lmoresi merged 2 commits into
underworldcode:developmentfrom
gthyagi:feature/stokes-nullspace

Conversation

@gthyagi

@gthyagi gthyagi commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds generalized PETSc nullspace support to the Underworld Stokes saddle-point solver.

What changed

  • Added petsc_use_pressure_nullspace to register the constant-pressure gauge mode on the coupled Stokes operator.
  • Added petsc_velocity_nullspace_basis to register one or more exact velocity nullspace modes alongside the pressure mode.
  • The solver now builds an orthonormal Stokes nullspace basis and attaches it to the operator and preconditioner matrices before each solve path, including after setFromOptions() reconfiguration.
  • Cached nullspace objects are cleared when the solver DM / field layout is rebuilt.
  • The solver checks for conflicting pressure Dirichlet BCs and raises a clear error instead of attaching an invalid pressure nullspace.
  • The Stokes nullspace docstrings now document exact shell rigid-body rotation modes and how to register them:
    • 2-D annulus: (-y, x)
    • 3-D spherical shell: (0, -z, y), (z, 0, -x), (-y, x, 0)
  • Added or updated regression coverage in:
    • tests/test_1013_stokes_pressure_nullspace.py
    • tests/test_1014_stokes_shell_nullspace.py

Why this is important

Incompressible Stokes pressure is only defined up to an additive constant. Making singular Stokes systems solvable by imposing a pressure Dirichlet condition, especially on an entire boundary, is stronger than the mathematical requirement and can change the solution.

This PR follows the standard PETSc approach instead:

  • register the algebraic nullspace during the solve, and
  • choose the reported pressure gauge afterward by subtracting a mean or applying another normalization.

This matters for annulus and spherical-shell benchmarks, including cases like the Thieulot k=0 branch, where pressure gauge freedom is real and boundary-wide pressure pinning is not the right tool. It also provides a clean path for exact shell rigid-rotation nullspaces when the PDE and boundary conditions truly admit them.

PETSc precedent

This follows the same pattern used in PETSc Stokes examples, where PETSc builds and attaches a nullspace instead of forcing pressure pointwise on a boundary:

Validation

  • pixi run -e amr-dev pytest tests/test_1013_stokes_pressure_nullspace.py tests/test_1014_stokes_shell_nullspace.py -q

These tests pass locally and cover both the pressure-only nullspace path and shell-style pressure-plus-rotation nullspace bases.

@gthyagi
gthyagi requested a review from lmoresi as a code owner March 24, 2026 14:14
@gthyagi

gthyagi commented Mar 24, 2026

Copy link
Copy Markdown
Contributor Author

Copying the reviewer-response summary from #90 here for reference:

Addressing the review items directly:

  1. Branch naming
  • I renamed the working branch on the fork to feature/stokes-nullspace.
  • GitHub does not let me change the head branch of an existing PR, so #90 itself still points to codex/petsc-pressure-nullspace.
  • To reopen this review thread, I restored codex/petsc-pressure-nullspace as an alias that points to the same commit as feature/stokes-nullspace.
  • So the naming convention is implemented on the branch itself, but this specific PR cannot be retargeted to the renamed head branch.
  1. Rigid-body modes design question
  • Implemented.
  • The Stokes nullspace support is now generalized beyond the constant-pressure mode.
  • A new petsc_velocity_nullspace_basis property allows multiple exact velocity nullspace modes to be registered alongside the pressure mode.
  • The docstrings now document the annulus rigid rotation (-y, x) and the three spherical-shell rigid rotations (0, -z, y), (z, 0, -x), and (-y, x, 0), plus how to set them on Stokes.
  1. @pytest.mark.level_3
  • Not changed intentionally.
  • This test remains level_3 because it executes a real Stokes solve. The mesh is small and runtime is short, but by the project testing definitions it is still a solver / physics test rather than a lightweight setup-only test.
  1. _pressure_dirichlet_bcs field id
  • Implemented.
  • The old hardcoded {1} fallback is removed.
  • _pressure_dirichlet_bcs() now uses self.p.field_id exclusively and raises a clear error if the pressure field is unavailable.
  1. Repeated nullspace attach calls after setFromOptions()
  • Implemented.
  • The repeated reattach calls remain, and there is now an inline comment explaining that PETSc may rebuild operator state after setFromOptions(), so the nullspace must be reattached before each solve path.
  • The comment is placed once before the first repeated call rather than duplicated at every identical call site.
  1. PETSc-style validation against conflicting pressure BCs
  • Implemented.
  • The solver now checks for pressure Dirichlet BCs before attaching the Stokes nullspace and raises a clear error if they are present.
  1. Extra validation added
  • Implemented.
  • The original pressure-nullspace regression test was kept and strengthened.
  • A new shell test covers pressure plus rigid-rotation nullspace bases for a 2-D annulus and a 3-D spherical shell.

The current fork branches feature/stokes-nullspace and codex/petsc-pressure-nullspace both point to the same latest commit so this reopened PR now includes the recent implementation updates as well.

@gthyagi gthyagi changed the title Add PETSc pressure nullspace support to Stokes Add PETSc nullspace support to Stokes Mar 24, 2026

@lmoresi lmoresi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good - I'm happy to see this generalised to introduce null spaces into the stokes solver for velocity as well. We should add these to the individual meshes, since those are the places where we actually know what the null space should be.

@lmoresi
lmoresi merged commit c3e365e into underworldcode:development Mar 25, 2026
2 checks passed
lmoresi added a commit that referenced this pull request Mar 25, 2026
Setting stokes.petsc_use_nullspace = True enables:
  1. Constant-pressure nullspace (petsc_use_pressure_nullspace)
  2. Velocity rotation modes from mesh.nullspace_rotations

This auto-populates petsc_velocity_nullspace_basis from the mesh
geometry, so users don't need to construct rotation modes manually.

For annulus: 1 pressure + 1 rotation = 2 modes
For spherical shell: 1 pressure + 3 rotations = 4 modes
For box: 1 pressure + 0 rotations = 1 mode

Existing PR #91 tests pass unchanged.

Underworld development team with AI support from Claude Code
lmoresi added a commit that referenced this pull request Mar 31, 2026
Setting stokes.petsc_use_nullspace = True enables:
  1. Constant-pressure nullspace (petsc_use_pressure_nullspace)
  2. Velocity rotation modes from mesh.nullspace_rotations

This auto-populates petsc_velocity_nullspace_basis from the mesh
geometry, so users don't need to construct rotation modes manually.

For annulus: 1 pressure + 1 rotation = 2 modes
For spherical shell: 1 pressure + 3 rotations = 4 modes
For box: 1 pressure + 0 rotations = 1 mode

Existing PR #91 tests pass unchanged.

Underworld development team with AI support from Claude Code
lmoresi added a commit that referenced this pull request Apr 7, 2026
Setting stokes.petsc_use_nullspace = True enables:
  1. Constant-pressure nullspace (petsc_use_pressure_nullspace)
  2. Velocity rotation modes from mesh.nullspace_rotations

This auto-populates petsc_velocity_nullspace_basis from the mesh
geometry, so users don't need to construct rotation modes manually.

For annulus: 1 pressure + 1 rotation = 2 modes
For spherical shell: 1 pressure + 3 rotations = 4 modes
For box: 1 pressure + 0 rotations = 1 mode

Existing PR #91 tests pass unchanged.

Underworld development team with AI support from Claude Code
@gthyagi
gthyagi deleted the feature/stokes-nullspace branch April 8, 2026 01:47
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.

2 participants