Skip to content

Rotated-BC analytic-normal guard false-positive when a second mesh exists at reaction read-out (multi-mesh unwrap identity) #445

Description

@lmoresi

The new analytic-normal validation in _boundary_velocity_nodes (development, 2026-07)
raises

ValueError: analytic normal for boundary 'Upper' contains symbols ['N.x', 'N.y']
that are not mesh coordinates

on a NORMAL that was correctly built from the solver's own mesh.X — but only when a
SECOND mesh has been created before the recovery call. Reproduce: build mesh A + Stokes

  • add_rotated_freeslip_bc(normal = X/|X| from mesh A) + solve (passes — guard OK at
    solve time); build mesh B (a second annulus); then call
    solverA.boundary_normal_traction(...) -> guard fires. Same call BEFORE mesh B exists:
    fine.

Mechanism (suspected): the guard unwraps the stored normal at read-out time
(unwrap(normal[0,k], keep_constants=False)) and compares free symbols against
set(solver.mesh.X) by identity; with two meshes alive the expression-registry
cross-talk returns coordinate BaseScalars that are not identical to mesh A's — the
multi-mesh symbol-identity class (see SYMBOL_DISAMBIGUATION design note).

Impact: any workflow that solves on one mesh and reads the reaction after constructing
another mesh (comparison studies, A/B harnesses) hard-fails. Workaround: read
reactions before constructing the next mesh. Fix direction: compare by symbol NAME
within the solver's coordinate system, or unwrap against the solver's own registry
scope rather than the global one.

Found while running the #438 TI pre-test (results in that thread).

Underworld development team with AI support from Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions