Skip to content

#14806 Improve performance of geometry computations when opening a grid - #14807

Draft
magnesj wants to merge 6 commits into
OPM:devfrom
magnesj:grid-open-geometry-performance
Draft

magnesj wants to merge 6 commits into
OPM:devfrom
magnesj:grid-open-geometry-performance

Conversation

@magnesj

@magnesj magnesj commented Sep 27, 2026

Copy link
Copy Markdown
Member

Closes #14806

Speeds up the geometry computations done when opening a grid. One commit per change:

  • NNC: Only test candidates in the neighbor pillar column for I and J fault faces. Most overlap tests were for cells outside the column that only touch the fault face along an edge. This intentionally changes the computed NNCs: edge contacts and a small number of non-zero area overlaps outside the column are no longer generated. Fault faces and NNCs from the simulator are unchanged.
  • Cell search tree: Group cells in leaves and store leaf ids in flat arrays. At least 8 cells along K per leaf (one cell per leaf gave a very deep tree), and no std::vector<int> per leaf. findIntersectingCells() filters the result per cell, so it returns the same cells as a tree with one cell per leaf. This also fixes grids above 4M cells, which previously got all cells of a leaf. Nested LGR cells and LGR cells in invalid main grid cells are included in the grouped tree.
  • NNC: Use move semantics for RigConnection. No behavior change.
  • Faults: Compute unnamed fault faces in parallel and only from positive faces. Same fault faces in the same order.

Timings (seconds, 12 threads, four large models)

Step A B C D
computeCachedData (search tree) 2.51 → 0.80 0.30 → 0.08 1.66 → 0.35 2.19 → 0.54
calculateFaults 1.41 → 0.21 0.13 → 0.02 0.63 → 0.08 0.94 → 0.16
NNC processing 14.0 → 6.1 0.43 → 0.22 – 0.92 → 0.52
Total 19.7 → 9.3 1.53 → 0.87 3.47 → 1.46 5.8 → 2.8

Testing

  • Compared hashes of fault faces, simulator NNCs (incl. polygons) and computed NNC cell pairs against dev on all four models. The last three commits give identical results.
  • New unit test RigMainGridSearchTree-Test.cpp compares findIntersectingCells() against checking every cell, including LGR cells, on TEST10K_FLT_LGR_NNC.
  • Unit tests pass, except 11 tests that also fail on dev (RimWellTargetMapping*, RimCellFilterToolsTest.EnsembleDataFilterInViewUsesViewCase, RimCellFilterToolsTest.PropertyFilterVisibilityPerCase).

… I and J fault faces

Computing additional NNCs spent most of its time running quad overlap tests on
candidate cells outside the neighbor pillar column. Most of these touch the
fault face along an edge only. Restrict candidates for I and J faces to the
neighbor column. This intentionally skips a small number of non-zero area
overlaps outside the column.
…in flat arrays

Building the cell search tree was dominated by one small std::vector<int>
allocation per leaf, and a tree with one cell per leaf becomes very deep for
large grids.

- BoundingBoxTree: Store leaf ids in flat arrays, and move the input data
  instead of copying it. The tree shape is unchanged. Queries no longer copy
  the ids of each leaf.
- RigMainGrid: Always group at least 8 cells along K in each leaf.
  findIntersectingCells() removes cells not intersecting the query bounding
  box, so the result is the same set of cells as for a tree with one cell per
  leaf. This also applies to very large grids, which previously got the
  cells of the whole leaf.
- Include cells of nested LGRs and LGR cells in invalid main grid cells in
  the grouped tree, as the previous tree with one cell per leaf did.
RigConnection had user-defined copy operations and no move operations, so
sorting in remove_duplicates() and merging connections copied the polygon of
every connection.

- Remove the member-wise copy operations, so the implicit noexcept move
  operations are used.
- Take the polygon by value and move it into the connection.
- Add move overloads of RigConnectionContainer::push_back(), and use them when
  collecting the computed connections.
- Avoid copying each native connection when building the set of cell pairs.
…om positive faces

- A negative I or J face is the positive face of the neighbor cell with a lower
  index, and is already handled when that neighbor is processed. Only visit the
  positive faces.
- Each cell only writes the fault index of its own positive faces and the
  opposite faces of its neighbors, so process the cells in parallel. The
  thread results are appended in thread order, so the fault faces keep the
  same order as before.
…tion

The NNC geometry computation now only tests candidates in the neighbor pillar column for I/J fault faces, intentionally producing fewer NNCs (edge contacts and small non-zero-area overlaps outside the column are no longer generated). Update the test assertion from 3416 to 3345 to match.
…rectly

RigConnectionContainer was a thin wrapper around std::vector<RigConnection> with no added value beyond push_back/reserve/remove_duplicates. Replace it everywhere with std::vector<RigConnection> and inline the remaining container-merge and deduplication logic at their single call sites.

This branch has not been deployed

No deployments
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.

Improve performance of geometry computations when opening a grid

1 participant