solver.boundary_flux(boundary, normal=...) — the consistent-boundary-flux
back-calculation — reads correctly on an ordinary Stokes solve and returns
values of order 1e12 on Stokes_Constrained.
Measured
SolCx, StructuredQuadBox(elementRes=(32, 32)), free slip on all four walls,
normal = [[0, 1]] on Top, compared against SolCx.topography_top (mean
removed, corners excluded):
| solver |
Top held by |
max abs(CBF) |
vs exact |
Stokes |
add_dirichlet_bc((None, 0.0), "Top") |
0.381 |
rel 0.082, corr +0.997 |
Stokes |
add_rotated_freeslip_bc(0.0, "Top") |
0.497 |
rel 0.087, corr +0.996 |
Stokes_Constrained |
add_constraint_bc(0.0, "Top") |
~1e12 |
uncorrelated (corr 0.03) |
Exact peak is 0.379. The constrained solve itself is fine — velocity error
8.8e-06 at eta_B = 1e6, and its recovered n·σ·n matches the exact to 0.075 —
so this is the flux primitive on that solver, not the solve.
Likely _assemble_volume_reaction() picking up the multiplier field's rows or
the augmented-Lagrangian boundary stiffness (r = 1e4·μ, which the SolCx step
makes 1e10 on the stiff half); the magnitude is consistent with the latter.
Why it matters
It is the natural cross-check for #607: at convergence the momentum row's
boundary term satisfies
M_Γ (h + r(n·u − g)) = −(A·u − b)|_Γ
so h + r(n·u − g) IS the CBF traction de-smeared by the boundary mass. Being
able to read both off one solve is how that identity gets verified, and at the
moment it cannot be. Across two separate solves the corrected multiplier and the
rotated CBF reaction agree to 3–5%, which is inside each route's own error.
Reproduction: examples/solcx.py in UWTN 2026-016.
Underworld development team with AI support from Claude Code
solver.boundary_flux(boundary, normal=...)— the consistent-boundary-fluxback-calculation — reads correctly on an ordinary
Stokessolve and returnsvalues of order 1e12 on
Stokes_Constrained.Measured
SolCx,
StructuredQuadBox(elementRes=(32, 32)), free slip on all four walls,normal = [[0, 1]]onTop, compared againstSolCx.topography_top(meanremoved, corners excluded):
Topheld byStokesadd_dirichlet_bc((None, 0.0), "Top")Stokesadd_rotated_freeslip_bc(0.0, "Top")Stokes_Constrainedadd_constraint_bc(0.0, "Top")Exact peak is 0.379. The constrained solve itself is fine — velocity error
8.8e-06 at
eta_B = 1e6, and its recoveredn·σ·nmatches the exact to 0.075 —so this is the flux primitive on that solver, not the solve.
Likely
_assemble_volume_reaction()picking up the multiplier field's rows orthe augmented-Lagrangian boundary stiffness (
r = 1e4·μ, which the SolCx stepmakes 1e10 on the stiff half); the magnitude is consistent with the latter.
Why it matters
It is the natural cross-check for #607: at convergence the momentum row's
boundary term satisfies
so
h + r(n·u − g)IS the CBF traction de-smeared by the boundary mass. Beingable to read both off one solve is how that identity gets verified, and at the
moment it cannot be. Across two separate solves the corrected multiplier and the
rotated CBF reaction agree to 3–5%, which is inside each route's own error.
Reproduction:
examples/solcx.pyin UWTN 2026-016.Underworld development team with AI support from Claude Code