fix(ddt): units-active semi-Lagrangian trace-back (#267)#277
Merged
Conversation
SemiLagrangian.update_pre_solve crashed for any unit-bearing model in the time
loop:
ValueError: Cannot subtract arrays with incompatible units:
'meter' and 'meter / second'
Root cause: the trace-back is performed in the mesh's NON-DIMENSIONAL (DM)
coordinate space (evaluate()/global_evaluate treat plain arrays as DM coords,
and DM point-location uses DM values 0..L_model, NOT dimensional metres). But
the has_units branch kept dimensional coords (mesh.X.coords ~ metres) and
velocity (m/s) and left dt a unitless float, so:
- coords[m] - v[m/s]*dt[dimensionless] -> unit subtraction crash, and
- even patched, dimensional coords (~1e9) fed to a DM that locates in 0..1000
space would mislocate.
Fix: route the whole trace-back through ND/DM space regardless of units —
departure point from psi_star[i].coords_nd (== .coords for a non-units model;
the ND reduction of the dimensional coords when units are active), velocity
non-dimensionalised, dt non-dimensional. Both the node-velocity and
midpoint-velocity legs are corrected. The non-units path is unchanged (it
already used exactly this ND logic).
Verified: units-active AdvDiffusionSLCN now runs and tracks the equivalent
non-dimensional run to ~1e-3 (the small residual is the constitutive diffusivity
scaling under units, a separate concern, not the trace-back). Non-units SL
regression unchanged (test_0855/0610/1054/1100 pass; test_1110 fails identically
with/without this change — a pre-existing MG DMCreateInjection issue). New
regression: tests/test_1056_units_slcn_traceback.py.
Unblocks the time-loop half of #263 (Tutorial_Thermal_Convection_Units).
Underworld development team with AI support from Claude Code
Member
Author
|
Self-review: routes the SL trace-back through ND/DM space (the non-units path's existing logic); removes the broken dimensional branch. Repro fixed, regression test passes (2/2), non-units SL suite unchanged (the one annulus failure is a pre-existing MG issue, identical with/without). Merging for the release. |
This was referenced Jun 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #267 —
SemiLagrangian.update_pre_solvecrashed for any unit-bearing model in the time loop:Root cause
The SL trace-back is performed in the mesh's non-dimensional (DM) coordinate space —
evaluate/global_evaluatetreat plain arrays as DM coords, and DM point-location uses DM values (0..L_model, not dimensional metres). Thehas_unitsbranch instead kept dimensional coords (mesh.X.coords≈ metres, ~1e9) and velocity (m/s) and leftdta unitless float, socoords[m] − v[m/s]·dt[dimensionless]raised — and even patched, dimensional coords fed to a DM that locates in0..1000space would mislocate.Fix
Route the whole trace-back through ND/DM space regardless of units:
psi_star[i].coords_nd(==.coordsfor a non-units model; the ND reduction of dimensional coords when units are active),dtnon-dimensional.Both RK2 legs (node-velocity and midpoint-velocity) corrected. The non-units path is unchanged — it already used exactly this ND logic; the fix just removes the broken parallel dimensional branch.
Verification
AdvDiffusionSLCNnow runs and tracks the equivalent non-dimensional run to ~1e-3 (the small residual is the constitutive diffusivity scaling under units — a separate concern, not the trace-back; advection-magnitude-independent).test_0855(oldframe SL),test_0610(NS SLCN),test_1054,test_1100pass.test_1110_advDiffAnnulusfails identically with and without this change — a pre-existingPCSetUp_MG/DMCreateInjectionmultigrid issue, unrelated.tests/test_1056_units_slcn_traceback.py(runs + nondim-equivalence).Unblocks the time-loop half of #263 (
Tutorial_Thermal_Convection_Units).Underworld development team with AI support from Claude Code