Summary
With the units system active (unit-bearing mesh/variables), NavierStokesSLCN / AdvDiffusionSLCN fail in the semi-Lagrangian trace-back:
ValueError: Cannot subtract arrays with incompatible units: 'meter' and 'meter / second'
Root cause
SemiLagrangian.update_pre_solve computes the trace-back midpoint (src/underworld3/systems/ddt.py:2651):
mid_pt_coords = coords - v_at_node_pts * (0.5 * dt_for_calc)
In the has_units branch, coords is UnitAwareArray[meter] and v_at_node_pts is [meter/second], but dt_for_calc is left as a plain (dimensionless) float (ddt.py:2519):
if has_units:
if hasattr(dt, "to"):
dt_for_calc = dt.to("second")
else:
dt_for_calc = dt # comment says 'treat as seconds' but leaves it unitless
so v[m/s] * dt[dimensionless] = [m/s] and the subtraction [m] - [m/s] raises.
Naively attaching seconds would fix the units but be numerically wrong: a CFL dt computed in nondimensional model-time is not SI seconds — it must be reconciled with the dimensional coords/velocity via the model time-scale. The sibling not has_units branch already does the consistent thing (nondimensionalise coords, velocity and dt together).
Fix direction
Make the units-active trace-back internally consistent — either dimensionalise dt to seconds via the model time-scale in the has_units path, or (cleaner) always perform the trace-back nondimensionally (strip units from coords/velocity/dt together, as the not has_units branch does) regardless of has_units.
Reproduction
docs/examples/Tutorial_Thermal_Convection_Units.py (PR #263) reaches the time-stepping loop and fails here. That tutorial is the natural regression test once fixed.
Exposed by PR #263 (held pending this fix).
Underworld development team with AI support from Claude Code
Summary
With the units system active (unit-bearing mesh/variables),
NavierStokesSLCN/AdvDiffusionSLCNfail in the semi-Lagrangian trace-back:Root cause
SemiLagrangian.update_pre_solvecomputes the trace-back midpoint (src/underworld3/systems/ddt.py:2651):In the
has_unitsbranch,coordsisUnitAwareArray[meter]andv_at_node_ptsis[meter/second], butdt_for_calcis left as a plain (dimensionless) float (ddt.py:2519):so
v[m/s] * dt[dimensionless] = [m/s]and the subtraction[m] - [m/s]raises.Naively attaching
secondswould fix the units but be numerically wrong: a CFLdtcomputed in nondimensional model-time is not SI seconds — it must be reconciled with the dimensional coords/velocity via the model time-scale. The siblingnot has_unitsbranch already does the consistent thing (nondimensionalise coords, velocity and dt together).Fix direction
Make the units-active trace-back internally consistent — either dimensionalise
dtto seconds via the model time-scale in thehas_unitspath, or (cleaner) always perform the trace-back nondimensionally (strip units from coords/velocity/dt together, as thenot has_unitsbranch does) regardless ofhas_units.Reproduction
docs/examples/Tutorial_Thermal_Convection_Units.py(PR #263) reaches the time-stepping loop and fails here. That tutorial is the natural regression test once fixed.Exposed by PR #263 (held pending this fix).
Underworld development team with AI support from Claude Code