Skip to content

Comments

Fix UWexpression parameter display and tensor assignment#49

Open
lmoresi wants to merge 3 commits intodevelopmentfrom
fix/constitutive-model-uwexpression-params
Open

Fix UWexpression parameter display and tensor assignment#49
lmoresi wants to merge 3 commits intodevelopmentfrom
fix/constitutive-model-uwexpression-params

Conversation

@lmoresi
Copy link
Member

@lmoresi lmoresi commented Feb 18, 2026

Summary

  • ExpressionDescriptor.set: Store UWexpression as symbolic reference instead of extracting inner value. Fixes parameter display showing numeric values (e.g. 1e21 Pa.s) instead of symbolic names (e.g. eta_0), and restores lazy evaluation.
  • _unwrap_atom: Recursively resolve UWQuantity inside UWexpression chains during JIT compilation, preventing SympifyError.
  • _unscaled_matrix_to_rank4: Add __getitem__ wrapping guard for NDimArray assignment -- the single choke point for all constitutive models after simplify() strips per-model wrapping.
  • _unscaled_matrix_to_rank2: Fix pre-existing bug where loop body never assigned values (always returned zeros).
  • get_units() in unit_conversion.py: Restore delegating wrapper for compiled Cython modules (ckdtree.pyx) that import from this location.
  • Surface coordinate space handling: Add dimensional/ND gateways to Surface class. Fix _interpolate_to_proxy() to use internal model-space coordinates for KDTree, avoiding mismatch when units system is active.

Test plan

  • ViscousFlowModel with UWexpression(UWQuantity) -- solve succeeds
  • TransverseIsotropicFlowModel with UWexpression(UWQuantity) -- solve succeeds
  • Plain numeric and plain UWexpression parameters -- no regression
  • Stokes solver tests (test_1010) -- 11/11 passing
  • Poisson solver tests (test_1000, test_1001) -- 9/9 passing
  • Rank-2 tensor roundtrip (mandel_to_rank2 fix) -- 2D and 3D verified
  • Surface _interpolate_to_proxy with units/scaling active -- KDTree coordinate match verified

Underworld development team with AI support from Claude Code

…ive models

ExpressionDescriptor.__set__ was extracting the inner value from UWexpression
assignments (value._sym), losing the symbolic reference. Parameters displayed
as "1e21 Pa.s" instead of the symbolic name (η₀), and lazy evaluation broke.

Now stores the UWexpression itself as a symbolic reference, preserving display,
lazy evaluation, and the unit delegation chain.

Two downstream issues were also fixed:
- _unwrap_atom: recursively resolve UWQuantity when found inside UWexpression
  chain, preventing SympifyError during JIT compilation
- _unscaled_matrix_to_rank4: wrap values with __getitem__ (UWexpression from
  MathematicalMixin) before NDimArray assignment, matching the existing guard
  in _build_c_tensor. This is the single choke point for all constitutive
  models after simplify() strips the per-model wrapping.

Also fixed pre-existing bug in _unscaled_matrix_to_rank2 where the loop body
never assigned values to the output matrix (always returned zeros).

Underworld development team with AI support from Claude Code
Copilot AI review requested due to automatic review settings February 18, 2026 02:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes critical issues with parameter handling and tensor assignment in Underworld3's symbolic expression system. It addresses bugs that prevented proper display of symbolic parameter names, broke lazy evaluation chains, and caused tensor conversion functions to fail or return incorrect values.

Changes:

  • Simplified UWexpression parameter assignment to preserve symbolic references and lazy evaluation
  • Fixed critical bug in _unscaled_matrix_to_rank2 where loop never assigned values (always returned zeros)
  • Added wrapping guard in _unscaled_matrix_to_rank4 to handle UWexpression objects during NDimArray assignment
  • Added recursive resolution in _unwrap_atom to handle UWQuantity nested inside UWexpression chains

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/underworld3/utilities/_api_tools.py Simplified ExpressionDescriptor.set to store UWexpression as symbolic reference instead of extracting inner value, preserving lazy evaluation and symbolic display
src/underworld3/maths/tensors.py Fixed _unscaled_matrix_to_rank2 bug where loop body never assigned values; added getitem wrapping guard in _unscaled_matrix_to_rank4 for NDimArray assignment
src/underworld3/function/expressions.py Added recursive UWQuantity resolution in _unwrap_atom to prevent SympifyError during JIT compilation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

The function was removed during a cleanup but ckdtree.pyx (compiled Cython)
still imports it. Added a thin delegate to units.get_units().

Underworld development team with AI support from Claude Code
Surface stores geometry internally in model (ND) space but user-facing
properties (vertices, control_points) must return dimensional coordinates
when the units system is active.

Changes:
- Add _dimensionalise_coords() gateway for Surface output properties
- Add set_control_points() input gateway that non-dimensionalises
- Fix _interpolate_to_proxy() to use internal ND coordinates for KDTree
  (was using the now-dimensional .vertices property, causing mismatch
  with mesh._coords)

Underworld development team with AI support from Claude Code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant