Skip to content

Map region arrays onto the leaf grid for LGR (EQLNUM, PVTNUM, SWATINIT, FIP) - #7244

Open
hnil wants to merge 4 commits into
OPM:masterfrom
hnil:pr/lgr-region-arrays-on-leaf
Open

Map region arrays onto the leaf grid for LGR (EQLNUM, PVTNUM, SWATINIT, FIP)#7244
hnil wants to merge 4 commits into
OPM:masterfrom
hnil:pr/lgr-region-arrays-on-leaf

Conversation

@hnil

@hnil hnil commented Jul 29, 2026

Copy link
Copy Markdown
Member

What

Region arrays (EQLNUM, PVTNUM, SWATINIT, FIPNUM and the datum-pressure regions) are read from the input grid field properties but then indexed by leaf cell. Without LGRs the leaf coincides with the input grid, so this is correct. With a CARFIN the leaf has more cells and a different ordering, and the arrays are silently misused.

Each case is mapped onto the leaf with LookUpData::assignFieldProps{Int,Double}OnLeaf, so a refined cell inherits its parent cell's value. That is the identity on an unrefined grid, so non-LGR runs are byte-identical.

Why it matters

These are wrong-answer bugs on decks upstream already supports, not new-feature enablers:

  • EQLNUMequilnum() copied the input-grid array into a leaf-sized vector with std::ranges::transform, misaligning coarse cells and leaving every refined cell in equil region 1. Refined cells then equilibrate against the wrong OWC, so the refined region initialises at the wrong water saturation.
  • PVTNUMsetRegionPvtIdx() indexed the input-grid array by a leaf cell index. Out of bounds for refined cells; once a region's first cell was refined this surfaced as "table has 0 sampling points".
  • SWATINIT — input-grid values copied into a leaf-indexed vector.
  • FIPNUM and the FIP region arrayscreateLocalRegion_ built the array from the input grid and then only resize()d it to the leaf cell count. std::vector::resize keeps the existing values and zero-pads the appended entries, so every refined leaf cell got region 0 and was dropped from the FIP/field sums. FPR is the FIPNUM-region pressure sum, so excluding the refined cells — which sit near the well, at a different pressure — biases the reported field pressure while the per-cell maps stay correct.
  • Datum-region pressures — the PPO/PPG/PPW and RPP* keywords build a RegionPhasePoreVolAverage from PVTNUM/FIP arrays and index it by leaf cell, reading past the end of the input-grid arrays.

The last commit is a guard rather than a fix: the solvent/polymer/biofilm/MICP initial conditions (SSOL, SPOLY, SPOLYMW, SMICR, SBIOF, SOXYG, SUREA, SCALC) are read the same way and would need the same treatment. LGR is black-oil only today, so this fails early with a clear message instead of producing silently wrong results.

How to reproduce

flow opm-tests/lgr/SPE1CASE1_CARFIN.DATA

Compare FPR and the initial SWAT in the refined region against the equivalent unrefined run. This PR changes simulation output on LGR decks — that is the point; the previous values were wrong. Non-LGR output is unchanged.

The quantified effect was measured on an internal two-phase LGR model (not in opm-tests): FPR absolute error against the reference dropped from 9.06 to 0.055, matching the non-LGR baseline of ~0.12, serially and at np=2; initial SWAT moved from a gross WOC error to the same ~2% per-cell spread as the non-LGR case.

Implementation notes

  • Uses only existing opm-grid API — LookUpData / assignFieldPropsIntOnLeaf (opm/grid/LookUpData.hh). No grid-side change is needed.
  • equilnum() now takes the GridView, which LookUpData requires.
  • In OutputBlackoilModule, the mapped arrays are captured by value in the lookup lambda so they outlive the constructor; decltype(auto) is kept for the required reference-to-vector semantics.
  • needsTranslation=false throughout, preserving the previous raw get_int values.

Testing

Built and run against opm-common and opm-grid master. Non-LGR regression cases unchanged.

hnil and others added 4 commits July 29, 2026 11:08
Equilibration read EQLNUM, PVTNUM and SWATINIT straight from the input-grid
field properties and indexed them by leaf cell. Without LGRs the leaf coincides
with the input grid, so this is correct. With an LGR the leaf has more cells and
a different ordering, so:
 - EQLNUM: equilnum() copied the input-grid array into a leaf-sized vector with
   std::ranges::transform, misaligning coarse cells and leaving every refined
   cell in equil region 1. Refined cells then used the wrong OWC, raising the
   water-oil contact (the reported symptom: LGR initialized far too wet, mobile
   water mean ~0.675 vs ~0.567 in the reference; non-LGR matched).
 - PVTNUM: setRegionPvtIdx() indexed the input-grid PVTNUM by a leaf cell index
   (out of bounds for refined cells -> garbage PVT region -> 'table has 0
   sampling points' once a region's first cell was refined).
 - SWATINIT: copied input-grid values into a leaf-indexed vector.

Map each through LookUpData::assignFieldProps{Int,Double}OnLeaf, so a refined
cell inherits its parent cell's value. This is the identity for unrefined grids,
so non-LGR cases are byte-identical; equilnum now takes the GridView (LookUpData
needs it).

Verified: model2_lgr TEST_LGR_INJ1_NOTHPRES initial SWAT now matches the
reference within ~2% per cell - the same OPM-vs-reference spread as the non-LGR
case (was a gross WOC error before). No regression: non-LGR, single-level LGR
(SPE1CASE1_CARFIN1) and nested LGR (serial + np=2) still equilibrate and run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tc.)

createLocalRegion_ built each FIP region array (FIPNUM, ...) from the input-grid
field property and then only resize()d it to the leaf cell count. std::vector
resize keeps the existing (input-grid) values and zero-pads the appended entries,
so with an LGR every refined leaf cell got region 0 and was dropped from the
FIP/field region sums. The field pressure FPR (and FPRP, region FIP) are computed
as the FIPNUM-region sum, so excluding the ~10k refined cells (near the well,
different pressure) made FPR wrong by ~4% while per-cell maps stayed correct.

Map the region array onto the leaf with LookUpData::assignFieldPropsIntOnLeaf so
a refined cell inherits its parent cell's region (identity without LGRs, so
non-LGR runs are unchanged), then keep the existing non-interior -> region 0
masking.

Verified on model2_lgr: FPR vs the reference improves from abs 9.06 to 0.055
(matching the non-LGR baseline ~0.12), serial and at np=2; nolgr FPR unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The PPO/PPG/PPW and RPP* datum-pressure summary keywords build a
RegionPhasePoreVolAverage from PVTNUM/FIP region arrays read on the input grid,
then index them by leaf cell. With LGRs the leaf is larger, so refined cells read
past the end of the input-grid arrays (out of bounds / wrong region). Map each
region array onto the leaf via LookUpData (refined cell inherits its parent's
region; identity without LGRs) and capture the mapped arrays by value in the
lookup lambda so they outlive in the stored callable. Verified: an LGR deck with
RPPO now runs; black-oil non-LGR output unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…il only)

These extension initial conditions (SSOL, SPOLY, SPOLYMW, SMICR, SBIOF, SOXYG,
SUREA, SCALC) are read from the input-grid field properties and indexed by leaf
cell without mapping refined cells to their parent, so they would be wrong/out of
bounds under LGR. LGR is supported for black-oil only; fail early with a clear
message when an LGR/CARFIN deck also enables one of these extensions, instead of
producing silently wrong results.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@hnil
hnil requested review from akva2 and arturcastiel July 29, 2026 09:31
@hnil hnil added the manual:bugfix This PR is a bug fix and should be noted in the manual label Jul 29, 2026
@hnil
hnil removed the request for review from arturcastiel August 2, 2026 17:29
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.

1 participant