Skip to content

Analytic normal for add_rotated_freeslip_bc fails on any mesh after the first (unwrap canonicalises coordinates to the first mesh's frame) #501

Description

@lmoresi

In rotated_bc._boundary_velocity_nodes, an analytic (sympy) normal is unwrapped and then validated with

stray = set().union(*[c.free_symbols for c in comps]) - set(solver.mesh.X)

unwrap(...) canonicalises coordinate BaseScalars onto the FIRST mesh's coordinate frame (multi-mesh symbol identity), so on any mesh created after the first, the unwrapped x is not mesh.X[0] by identity even though it prints identically. The stray check then raises

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

for a normal correctly written in that mesh's own mesh.X.

Reproducer (second mesh in one session):

import sympy, underworld3 as uw
from underworld3.function.expressions import unwrap
m1 = uw.meshing.UnstructuredSimplexBox(cellSize=0.2)
m2 = uw.meshing.UnstructuredSimplexBox(cellSize=0.15)
x, y = m2.X
u = sympy.sympify(unwrap(x - 0.5, keep_constants=False, return_self=False))
print(u.free_symbols - set(m2.X))   # {N.x}  — same object as m1's x

Fix (already applied to the fault-side twin fault_contact._compiled_normal_override on feature/fault-split-node, where the check was mirrored from rotated_bc): re-tag the unwrapped symbols by NAME onto the solver's own mesh.X before the stray check and the lambdify:

by_name = {str(xk): xk for xk in solver.mesh.X}
retag = {s: by_name[str(s)] for c in comps for s in c.free_symbols
         if str(s) in by_name and s is not by_name[str(s)]}
if retag:
    comps = [c.subs(retag) for c in comps]

Genuine stray symbols (names not matching any coordinate) are still caught. Note lambdify was already coincidentally correct when the check passed, because it binds by printed name.

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