Mesh.cell_size() returns a P0 field filled from self._radii, which _get_mesh_sizes computes as the RMS distance from each cell's vertices to the NEAREST centroid found by a kd-tree over the centroids this rank holds. Near a partition boundary the nearest centroid is a different cell than in serial (the neighbour set is truncated), so the field, and everything scaled by it (the SUPG tau of the Eulerian solvers, the Nitsche penalty gamma mu / h), depends on the partition.
Measured on the Kovasznay-flow test of the SUPG Navier-Stokes solver (feature/navier-stokes-supg, res 8, three steps from the exact solution, solver tolerance 1e-11 so the linear solve is not the cause):
| tau built on |
np 1 error |
np 2 error |
difference |
a constant h (get_min_radius) |
0.0023408316563576 |
0.0023408316563546 |
1e-15 |
mesh.cell_size() |
0.0024855792696189 |
0.0024843274043763 |
5e-4 |
The plain Stokes solve and the tau = 0 (Galerkin) step on the same mesh are partition-independent to 1e-12, so the cell-size field is the only rank-dependent input. The scalar SUPG parallel test (test_1077) did not catch it because at its Courant number tau is dominated by the transient term and h barely enters.
The fix is a purely local definition of the size, each cell's vertices against its own centroid, which is identical on any partition and equal to the present value on a regular mesh; on an irregular mesh it is the same quantity without the neighbour's centroid occasionally standing in. Implemented alongside the Navier-Stokes SUPG solver, where it was found.
Underworld development team with AI support from Claude Code
Mesh.cell_size()returns a P0 field filled fromself._radii, which_get_mesh_sizescomputes as the RMS distance from each cell's vertices to the NEAREST centroid found by a kd-tree over the centroids this rank holds. Near a partition boundary the nearest centroid is a different cell than in serial (the neighbour set is truncated), so the field, and everything scaled by it (the SUPG tau of the Eulerian solvers, the Nitsche penalty gamma mu / h), depends on the partition.Measured on the Kovasznay-flow test of the SUPG Navier-Stokes solver (feature/navier-stokes-supg, res 8, three steps from the exact solution, solver tolerance 1e-11 so the linear solve is not the cause):
get_min_radius)mesh.cell_size()The plain Stokes solve and the tau = 0 (Galerkin) step on the same mesh are partition-independent to 1e-12, so the cell-size field is the only rank-dependent input. The scalar SUPG parallel test (test_1077) did not catch it because at its Courant number tau is dominated by the transient term and h barely enters.
The fix is a purely local definition of the size, each cell's vertices against its own centroid, which is identical on any partition and equal to the present value on a regular mesh; on an irregular mesh it is the same quantity without the neighbour's centroid occasionally standing in. Implemented alongside the Navier-Stokes SUPG solver, where it was found.
Underworld development team with AI support from Claude Code