Summary
Repeated linear Stokes solves with rotated strong free-slip boundary conditions
grow resident memory substantially on every timestep. In an 8-rank Zhong et al.
(2008) A1 thermal-convection run on a 16 GiB Apple Silicon Mac, aggregate Python
RSS reached 54-59 GiB before macOS watchdog panics/restarts.
This is distinct from the constrained-multiplier scaling problem in #244. Single
rotated solves are accurate and fast; the failure appears during repeated
transient solves because the rotated path reconstructs PETSc matrices and the
fieldsplit/GAMG solver hierarchy for every call.
Reproducer
Benchmark script:
Detailed postmortem:
The unsafe production case used cellsize=1/8, P2/P1, 8 MPI ranks, and rotated
free slip. The mesh had only about 48,202 Stokes unknowns, so solution-vector
storage does not explain the observed memory.
Crash evidence
| Run |
Aggregate Python RSS before failure |
Per-rank RSS |
System state |
| 1 |
54.29 GiB |
6.17-7.28 GiB |
watchdog panic |
| 2 |
59.14 GiB |
7.05-7.60 GiB |
watchdog panic |
| 3 |
59.18 GiB |
7.12-7.61 GiB |
watchdog panic |
At failure, the compressed-segment pool was effectively full and macOS had
created 41-42 swapfiles.
Bounded coarse probes
Serial cellsize=1/4 repeated-solve probes isolate the boundary-condition path:
| BC / experiment |
RSS increase |
Approx. increase per subsequent solve |
| Rotated free slip |
+102.03 MiB over initialization and 12 solves |
8.54 MiB/solve |
Rotated, explicitly destroy prior _rotated_freeslip_info |
+88.65 MiB over 11 subsequent solves |
8.06 MiB/solve |
| Native Nitsche |
+25.57 MiB over 9 subsequent solves |
2.84 MiB/solve and near plateau |
Destroying the Python-visible prior result does not remove the slope. This points
below the retained result dictionary, most likely to repeated PETSc
matrix/preconditioner setup.
Current code path
For every linear solve, solve_rotated_freeslip() currently:
- computes
J and Jp;
- copies the original operator;
- builds
Q and Q^T;
- forms
Ahat = Q J Q^T with PtAP;
- creates the pressure mass matrix, nullspaces, fieldsplit KSP/PC, and GAMG
hierarchy;
- solves;
- destroys only the immediate KSP context.
The nonlinear rotated path already demonstrates in-call reuse by updating
Ahat and the pressure block in place across Newton iterations. The linear
transient path has no persistent cross-call workspace.
Proposed fix
Add a persistent linear rotated-free-slip workspace owned by the Stokes solver:
- cache geometry-dependent rotation data (
Q, Q^T, constrained rows);
- reuse/update
Ahat and the pressure block in place;
- retain and reuse the fieldsplit KSP/PC and GAMG hierarchy when the operator is
unchanged;
- refresh only the RHS when forcing changes;
- invalidate and destroy the cache when mesh topology, rotated BCs,
discretisation, or operator coefficients change;
- retain the reaction vector required by rotated topography without retaining
unnecessary copies of A and b.
Acceptance criteria
- A 25-50 solve coarse transient reproducer reaches a bounded post-warmup RSS
plateau.
- The KSP/PC/GAMG objects are reused when only the RHS changes.
- Changing body force produces the correct updated velocity and pressure.
- Serial and MPI results remain numerically equivalent to the uncached
implementation.
- Cache invalidation is covered for structural/operator changes.
- Rotated boundary traction/topography postprocessing remains correct.
Related issues
Summary
Repeated linear Stokes solves with rotated strong free-slip boundary conditions
grow resident memory substantially on every timestep. In an 8-rank Zhong et al.
(2008) A1 thermal-convection run on a 16 GiB Apple Silicon Mac, aggregate Python
RSS reached 54-59 GiB before macOS watchdog panics/restarts.
This is distinct from the constrained-multiplier scaling problem in #244. Single
rotated solves are accurate and fast; the failure appears during repeated
transient solves because the rotated path reconstructs PETSc matrices and the
fieldsplit/GAMG solver hierarchy for every call.
Reproducer
Benchmark script:
Detailed postmortem:
The unsafe production case used
cellsize=1/8, P2/P1, 8 MPI ranks, and rotatedfree slip. The mesh had only about 48,202 Stokes unknowns, so solution-vector
storage does not explain the observed memory.
Crash evidence
At failure, the compressed-segment pool was effectively full and macOS had
created 41-42 swapfiles.
Bounded coarse probes
Serial
cellsize=1/4repeated-solve probes isolate the boundary-condition path:_rotated_freeslip_infoDestroying the Python-visible prior result does not remove the slope. This points
below the retained result dictionary, most likely to repeated PETSc
matrix/preconditioner setup.
Current code path
For every linear solve,
solve_rotated_freeslip()currently:JandJp;QandQ^T;Ahat = Q J Q^TwithPtAP;hierarchy;
The nonlinear rotated path already demonstrates in-call reuse by updating
Ahatand the pressure block in place across Newton iterations. The lineartransient path has no persistent cross-call workspace.
Proposed fix
Add a persistent linear rotated-free-slip workspace owned by the Stokes solver:
Q,Q^T, constrained rows);Ahatand the pressure block in place;unchanged;
discretisation, or operator coefficients change;
unnecessary copies of
Aandb.Acceptance criteria
plateau.
implementation.
Related issues
concern but a different formulation.
for individual solves.
and memory behavior.