Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/underworld3/discretisation/discretisation_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,20 @@ def _deform_mesh(self, new_coords: numpy.ndarray, verbose=False):
self.dm.setCoordinatesLocal(coord_vec)
self.nuke_coords_and_rebuild()

# Rebuild the _coords array view. nuke_coords_and_rebuild may
# replace the coordinate vector internally (createCoordinateSpace),
# leaving self._coords as a stale numpy view of the old buffer.
import underworld3.utilities
old_callbacks = getattr(self._coords, "_callbacks", [])
self._coords = underworld3.utilities.NDArray_With_Callback(
numpy.ndarray.view(
self.dm.getCoordinatesLocal().array.reshape(-1, self.cdim)
),
owner=self,
)
Comment on lines +1290 to +1296

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

When rebuilding self._coords, only the callback functions are preserved. Any existing NDArray_With_Callback state (e.g. _callback_enabled from disable_callbacks() or _disable_inplace_operators) is reset to defaults, which can silently change behavior for callers that intentionally disabled callbacks. Consider copying these flags from the old self._coords onto the new instance (and copy the callback list rather than referencing it) so the wrapper rebuild is behavior-preserving beyond just the callback functions.

Suggested change
old_callbacks = getattr(self._coords, "_callbacks", [])
self._coords = underworld3.utilities.NDArray_With_Callback(
numpy.ndarray.view(
self.dm.getCoordinatesLocal().array.reshape(-1, self.cdim)
),
owner=self,
)
old_coords = self._coords
sentinel = object()
old_callbacks = list(getattr(old_coords, "_callbacks", []))
old_callback_enabled = getattr(old_coords, "_callback_enabled", sentinel)
old_disable_inplace_operators = getattr(
old_coords, "_disable_inplace_operators", sentinel
)
self._coords = underworld3.utilities.NDArray_With_Callback(
numpy.ndarray.view(
self.dm.getCoordinatesLocal().array.reshape(-1, self.cdim)
),
owner=self,
)
if old_callback_enabled is not sentinel:
self._coords._callback_enabled = old_callback_enabled
if old_disable_inplace_operators is not sentinel:
self._coords._disable_inplace_operators = (
old_disable_inplace_operators
)

Copilot uses AI. Check for mistakes.
for cb in old_callbacks:
self._coords.add_callback(cb)

return

def _legacy_access(self, *writeable_vars: "MeshVariable"):
Expand Down
Loading