Revert PR #172 (integrals regression) + xfail CellWiseIntegral parity tests#174
Merged
Conversation
…field-cloning bug While reverting PR #172 (which broke Integral.evaluate), audited the sister CellWiseIntegral class — the PR's premise was that CellWiseIntegral "already takes the right path". It does not: 1. CellWiseIntegral.evaluate() referenced self.dim (no such attribute), so any call to the class crashed with AttributeError before exhibiting the deeper bug. This commit fixes it to self.mesh.dim. 2. With the typo fixed, CellWiseIntegral exhibits the same field-cloning bug that broke Integral in PR #172: cloning mesh.dm and attaching a fresh single-field discretisation, but then integrating against mesh.dm.getGlobalVec() (packed for the multi-field layout), produces a ~2x over-count on the unit square. CellWiseIntegral has zero pre-existing test coverage. This commit adds two regression tests marked xfail with a clear reason; they will start passing once CellWiseIntegral is rewritten to integrate against mesh.dm + getDS() directly (the pre-PR-172 Integral pattern). An inline TODO(BUG) comment in the source points at the same write-up. Underworld development team with AI support from Claude Code
Contributor
There was a problem hiding this comment.
Pull request overview
Reverts PR #172’s DM-cloning approach in Integral.evaluate() to restore correctness (avoiding DOF layout mismatches), and adds xfail parity tests documenting that CellWiseIntegral.evaluate() currently produces incorrect results due to the same DM/Vec layout mismatch.
Changes:
- Reverted
Integral.evaluate()to compute integrals directly onmesh.dm/mesh.dm.getDS()(instead of cloning and creating a single-field DS per call). - Added
CellWiseIntegralparity tests (xfail) for constants and a mesh variable integrand. - Fixed a
CellWiseIntegraldimension typo (self.dim→self.mesh.dim) and added an inline TODO describing the known bug.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/underworld3/cython/petsc_maths.pyx |
Reverts Integral.evaluate() to shared DM/DS path; updates CellWiseIntegral.evaluate() to use self.mesh.dim and adds TODO about known DM/Vec mismatch. |
tests/test_0501_integrals.py |
Adds xfail parity tests for CellWiseIntegral to document current incorrect behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Explicit destroy of the clone at the end keeps long runs bounded. | ||
| mesh = self.mesh | ||
| self.dm = self.mesh.dm # .clone() | ||
| mesh=self.mesh |
Comment on lines
+303
to
+311
| # TODO(BUG): clone+createDefault+createDS gives dmc a single P1 field, | ||
| # but cgvec is packed for mesh.dm's multi-field layout — the integral | ||
| # reads the wrong DOFs and over-counts by ~2x on the unit square. | ||
| # Same bug as PR #172 (reverted in PR #173-followup). Tests in | ||
| # tests/test_0501_integrals.py::test_cellwise_integrate_* are xfail | ||
| # until this is rewritten to integrate against mesh.dm + getDS() | ||
| # directly (the pre-PR-172 Integral pattern). | ||
| cdef DM dmc = self.mesh.dm.clone() | ||
| cdef FE fec = FE().createDefault(self.dim, 1, False, -1) | ||
| cdef FE fec = FE().createDefault(self.mesh.dim, 1, False, -1) |
Comment on lines
310
to
314
| cdef DM dmc = self.mesh.dm.clone() | ||
| cdef FE fec = FE().createDefault(self.dim, 1, False, -1) | ||
| cdef FE fec = FE().createDefault(self.mesh.dim, 1, False, -1) | ||
| dmc.setField(0, fec) | ||
| dmc.createDS() | ||
|
|
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
PR #172 ("Perf: clone DM in
Integral.evaluate()(3× speedup; closes #171 narrative)") introduced a regression that broke 4 tests intests/test_0501_integrals.py. CI on the merged commit (fe05c63) and ondevelopment's HEAD shows these failures. This PR reverts #172 to restore correctness, and adds parity test coverage for the sisterCellWiseIntegralclass — which the original PR claimed worked but never actually has.What broke
The change in #172 was:
The integrand reads through
dmc's single-field DS, but the vector being integrated (cgvec) was packed formesh.dm's full multi-field layout. The DOFs read are wrong, producing ~2× over-counts on simple cases and NaN/0 on derivative integrands. All four failing tests are explained by this mismatch.Performance ground truth (#171)
The PR's stated motivation was to fix linear-time growth in
t_volover long convection runs (5 s → 833 s over ~3000 calls). The PR itself notes it could not reproduce the slowdown locally (200 calls × 100-cell mesh stayed flat). The fix was speculative; correctness on the failing tests was lost in exchange for an unverified perf benefit. Issue #171 should be reopened with a real reproducer before any further attempt.What's in this PR
Revert
fe05c63— restores the pre-Perf: clone DM in Integral.evaluate() (3× speedup; closes #171 narrative) #172Integral.evaluate()(usesmesh.dm+mesh.dm.getDS()directly).CellWiseIntegral parity tests (xfail) — the sister class had zero test coverage. While auditing, found two latent bugs:
self.dimtypo (it should beself.mesh.dim) — fixed; the class would crash withAttributeErrorbefore now.CellWiseIntegralexhibits the same field-cloning bug as Perf: clone DM in Integral.evaluate() (3× speedup; closes #171 narrative) #172 — sum of per-cell volumes returns 2.0 instead of 1.0 on the unit square.The two new tests (
test_cellwise_integrate_constants,test_cellwise_integrate_meshvar) are markedxfailwith a clear reason. They will start passing whenCellWiseIntegral.evaluate()is rewritten to use the samemesh.dm + getDS()pattern that the revertedIntegralalready uses.Inline
TODO(BUG)inCellWiseIntegral.evaluate()pointing at the same write-up.Test plan
pytest tests/test_0501_integrals.py -v— 9 passed, 3 xfailed (1 pre-existing + 2 new with documented reasons)Underworld development team with AI support from Claude Code