Skip to content

FlowProblem: drop a stray cell-index assignment in updateMaxWaterSaturation_ - #7296

Merged
bska merged 1 commit into
OPM:masterfrom
hnil:pr/maxwatsat-cell-index-bug
Aug 14, 2026
Merged

bska merged 1 commit into
OPM:masterfrom
hnil:pr/maxwatsat-cell-index-bug

Conversation

@hnil

@hnil hnil commented Aug 7, 2026

Copy link
Copy Markdown
Member

maxWaterSaturation_ is a std::vector<Scalar> sized by grid cells and indexed by element index everywhere it is used (FlowProblem.hpp:1170, :1395, :1594, :1845, FlowGenericProblem_impl.hpp:621). It has no time dimension, so

this->maxWaterSaturation_[/*timeIdx=*/1] = this->maxWaterSaturation_[/*timeIdx=*/0];

does not shift a time level — it overwrites cell 1's running maximum with cell 0's. The per-cell update that follows only ever raises values, so cell 1 keeps the wrong maximum whenever cell 0 is the larger of the two.

updateMinPressure_() is the structural twin on the same ROCKCOMP path and has no such line.

Effect

Larger than expected. On spe1/SPE1CASE2_ROCK2DTR:

master this PR
Overall Newton iterations 866 583
UNSMRY, UNRST differ
INIT identical

Corrupting one cell's water-saturation maximum feeds a wrong rock-compaction multiplier into that cell for the rest of the run, and the solver pays for it.

compareECLFiles_flow+SPE1CASE2_ROCK2DTR fails on this branch — it is the only failure out of 580 — because the stored reference was generated with the bug present. The reference needs regenerating in opm-tests; happy to open that PR if this is agreed.

Context

Found while auditing #7198. This line is the sole reason that rolling maxWaterSaturation_ back across a failed timestep changes results: every other quantity in that snapshot is a plain monotone extremum recomputed from the restored solution, hence idempotent, and each measures inert when its restore is removed. This one is not, purely because of this assignment.

@hnil hnil added the manual:bugfix This PR is a bug fix and should be noted in the manual label Aug 7, 2026
@hnil
hnil requested a review from akva2 August 7, 2026 16:35
@hnil
hnil requested a review from bska August 7, 2026 16:40
@bska

bska commented Aug 7, 2026

Copy link
Copy Markdown
Member

jenkins build this please

@bska

bska commented Aug 7, 2026

Copy link
Copy Markdown
Member

jenkins build this failure_report please

@akva2

akva2 commented Aug 10, 2026

Copy link
Copy Markdown
Member

@totto82 the intended history buffer update came in with 890d34a, please confirm it was a c'n'p woopsie, and not a wrong data structure woopsie.

@hnil

hnil commented Aug 10, 2026

Copy link
Copy Markdown
Member Author

Correction to my own PR text: I first wrote that SPE1CASE2_ROCK2DTR was byte-identical with and without this change. That was a stale build — it is not.

Rerun cleanly: master 866 Newton iterations, this branch 583. UNSMRY and UNRST differ, INIT does not. So the bug is not latent at all; it makes that deck materially harder to solve.

The one CI failure is that same deck, because the stored reference encodes the buggy result. It needs regenerating.

…ration_

maxWaterSaturation_ is a std::vector<Scalar> sized by the number of grid
cells and indexed by element index everywhere it is used.  It has no
time dimension, so

    maxWaterSaturation_[/*timeIdx=*/1] = maxWaterSaturation_[/*timeIdx=*/0];

does not shift a time level -- it overwrites cell 1's running maximum
with cell 0's.  Since the per-cell update that follows only ever raises
the value, cell 1 keeps the wrong maximum whenever cell 0 is the larger
of the two.

The structurally identical updateMinPressure_(), which serves the same
ROCKCOMP path, has no such line.

Only affects ROCKCOMP runs, and only cell 1.  SPE1CASE2_ROCK2DTR is
byte-identical with and without this change, because cells 0 and 1 reach
the same maximum there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hnil
hnil force-pushed the pr/maxwatsat-cell-index-bug branch from 5be6a08 to 4afc278 Compare August 11, 2026 12:06

@atgeirr atgeirr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be merged.

I see something else suboptimal here: Instead of return true on line 1366 (and others) we should use the (false or true) values returned from updateMaxWaterSaturation_() calls inside updateProperty_() and pass the or-ed value all the way out. As is not, we return true irregardless of updating any max saturation.

@atgeirr

atgeirr commented Aug 14, 2026

Copy link
Copy Markdown
Member

jenkins build this update_data please

@hnil

hnil commented Aug 14, 2026

Copy link
Copy Markdown
Member Author

jenkins build this update_data please

jenkins4opm pushed a commit to jenkins4opm/opm-tests that referenced this pull request Aug 14, 2026
Reason: PR OPM/opm-simulators#7296

opm-common     = cf5f36dce04b5a7d8bfce4bd5b25e0259e958e03
opm-grid       = e94a7386ca9d62104c329214d28e65f2e2da44dd
opm-simulators = 5ea8262a692c13c8f831fc2595831cac0a19d36c

### Changed Tests ###

  * spe1case2_rock2dtr
@bska

bska commented Aug 14, 2026

Copy link
Copy Markdown
Member

jenkins build this opm-tests=1560 please

bska added a commit to OPM/opm-tests that referenced this pull request Aug 14, 2026

@bska bska left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Very good. The new reference solutions have been installed on the CI system so I'll merge this to bring in the fix.

@bska
bska merged commit 2dac047 into OPM:master Aug 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

manual:bugfix This PR is a bug fix and should be noted in the manual

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants