Commit Graph
464 Commits
Author SHA1 Message Date
Magne Sjaastad 9ac6ad3bec #14903: Avoid duplicate dock window ids for copied plots
Copies and plots created from templates kept the source DockWindowId. The dock
manager identifies dock widgets by name, so the earlier dock widget was deleted on
dock state restore, leaving a dangling pointer that crashed in setActiveViewer.

- Do not copy DockWindowId; copies get a new id
- Assign a new id if a dock widget with the same name exists
- Use QPointer for the dock widget
2026-10-12 18:49:08 +02:00
Magne Sjaastad 92e269ef4d #14901: Guard against crashes from corrupt Eclipse files and incomplete frustum
- RifEclipseOutputFileTools::timeSteps: avoid integer division by zero when
  the restart file has no INTEHEAD
- libecl ecl_grid: return NULL when the main EGRID grid cannot be created,
  and skip NNCHEAD blocks that cannot be read
- libecl well_info: skip wells when the restart header cannot be read
- cvf::Frustum::isOutside: do not assert on an incomplete frustum, cull nothing

Fixes #14901.
2026-10-12 17:16:11 +02:00
Kristian Bendiksen b0f2044746 #14823 Group nested hybrid LGRs per refinement level in the Grids tree 2026-10-12 15:12:48 +02:00
Kristian Bendiksen 3d8912ba6c #14794 Cell filter: Use original parent IJK for IJK range filters on nested hybrid grids
For nested hybrid grids, IJK range filters (I/J/K slices and IJK filters)
now refer exclusively to the original (coarse) grid IJK. Nested-grid local
IJK values are no longer offered, and every cell, including cells in all
refinement levels, is mapped to the original IJK of its top-most parent.

- Add RigNestedHybridGridLayout describing how original cells are embedded
  in the flat grid, shared by the LGR reconstruction and the IJK mapping
- RigMainGrid: store the layout and compute the original IJK of any cell on
  demand by following the parent cell chain, without per-cell storage
- Range filter UI: slider limits, clamping, defaults and active cell range
  use the original grid dimensions; grid selection is hidden
- Evaluate range filters on all grids using the original IJK in the 3D view,
  combined filters and data filters
- 3D view context menu slices use the original IJK of the picked cell
- Add unit tests for the layout, the IJK mapping against OLDIJK, and slice
  filtering across refinement levels
2026-10-12 15:12:48 +02:00
Magne Sjaastad ab96c520bd #14895: Improve stability when importing malformed input files
* #14895: Fix null grid dereference when importing mismatching GRDECL
* #14895: Fix out-of-bounds read in perforation interval import
* #14895: Validate connectivity indices in VTK import
* #14895: Fix heap overflow for odd PORV count in dual porosity cases
* #14895: Update roffcpp to validate array lengths when parsing ROFF files
2026-10-12 09:40:23 +02:00
Magne Sjaastad 4126d25ea0 #14882: Fix missing-field-initializer warning in RigWellPathFormations-Test
Explicitly initialize the optional topXY member when constructing
RigWellPathFormation via aggregate initialization in the test helper,
avoiding a GCC -Wmissing-field-initializers warning.

Fixes #14882.
2026-10-08 15:37:58 +02:00
Magne Sjaastad bc62af3bb5 #14878: Fix stale well picks, import errors and overlapping zones 2026-10-08 12:44:14 +02:00
Magne Sjaastad 6c42ba5ae0 #14878: Add well-pick zone filtering to RFT cross plot and tornado plot
Let the RFT parameter cross plot reference a RimWellFormationsFile and use its
well-pick formations to filter/group data by zone, pushed down to the tornado
plot and RFT correlation sub plots.
2026-10-08 12:44:14 +02:00
Magne Sjaastad 37cacc9a41 #14878: Add FMU well-picks data model (RigWellPathFormations, RimWellFormationsFile/Collection)
Parse depth-based FMU well-pick formations.csv files in RifWellPathFormationReader
and expose them as a project-level RimWellFormationsCollection of RimWellFormationsFile
objects. RigWellPathFormations becomes a value type with top/base MD and TVD depths
per formation, independent from the existing K-layer-index .lyr formation names.
2026-10-08 12:44:14 +02:00
Magne Sjaastad fe887270e5 #14878: Add RifCsvHtmlTableTools for CSV content preview
Generic helper to render CSV file content as an HTML table, used to preview
well formations.csv content in the UI.
2026-10-08 12:44:14 +02:00
Magne Sjaastad cf36012cd2 Modernize well pick reader and RigWellPathFormations, add tests
Return values instead of out-parameters, and move the error dialog
from the reader to the importer so the reader can be unit tested.
Fix crash in level detection when erasing while iterating.
2026-10-07 13:37:23 +02:00
Magne Sjaastad 07d8153852 #14803 Extract well log along radial grid axis by depth
A well in a radial grid is on the grid axis or on a face between angular cells, so no cells are intersected. Fall back to the innermost cell column placed by depth. Fixes empty PLT and RFT grid curves.
2026-10-07 13:37:02 +02:00
Magne Sjaastad 7fa10b3e59 #14853: Fix region-to-region curve values missing for most ensemble realizations
Region-to-region addresses were reconstructed as "R1 - R2" (with spaces) when
looking up keywords for ensemble realizations without a pre-built address map,
but opm-common's on-disk keyword format has no spaces ("R1-R2"). This caused
silent data loss for region-to-region vectors (RGFT*, ROFT*, RWFT*, etc.) in
all but one ensemble realization.

Fix formatUiTextRegionToRegion() to use "R1-R2", and add a regression test.

Fixes #14853.
2026-10-06 13:38:27 +02:00
Magne Sjaastad b35b481ff1 Extract RFT cross plot static helpers into RimRftCrossPlotTools, add unit tests
- Move depthTypeAbbreviation(), computePressureSamplesPerCase() and
  computeMeanPressurePerCase() out of RimParameterRftCrossPlot into a new
  standalone RimRftCrossPlotTools namespace, shared by RimParameterRftCrossPlot
  and RimRftTornadoPlot (removing duplicated code in the latter).
- Extract pure, reader-independent helpers filterPressuresByDepthRange() and
  computeMean() so the depth filtering and averaging logic can be unit tested
  without RFT reader/ensemble mocks.
- Add RimRftCrossPlotTools-Test.cpp with gtest cases covering depth range
  filtering (disabled, inclusive bounds, out-of-range, mismatched sizes) and
  mean computation (empty/normal), plus depth type abbreviation.

Move RimWellLogRftCurve::rftCurveDepthValues into RimRftCrossPlotTools

This static helper's only caller was already RimRftCrossPlotTools::computePressureSamplesPerCase, so move it alongside the other RFT cross plot/tornado plot helpers for consistency.
2026-10-06 11:18:06 +02:00
Kristian Bendiksen f8b20a3f44 Add missing function headers in cpp files 2026-10-05 19:56:36 +02:00
Magne Sjaastad 9bfd91df90 Workflows: Add RimWorkflowVec3Binding for Vec3-typed config fields
Recognizes Vec3-shaped object schemas ({x, y, z} number properties)
structurally in RimWorkflowDescribeTools and dispatches them to a new
RimWorkflowVec3Binding in RimWorkflowTaskInput::createBinding(). Stores
the value as a cvf::Vec3d field, parses JSON object defaults, and emits
a YAML flow-mapping ({x: .., y: .., z: ..}) matching the taskmaestro
Vec3 pydantic model shape.
2026-10-05 19:56:36 +02:00
Kristian Bendiksen 65942d455d Workflows: Read workflow schemas with the taskmaestro CLI
Replace the rips.taskmaestro_helper introspect subcommand with
`python -m taskmaestro workflow describe --json`. RimWorkflowDescribeTools
converts the describe output (JSON schemas, depends_on, config_values)
into the workflow graph used by the Workflow UI. This also adds support
for collect dependencies and maps rips.Reservoir to EclipseCase pickers.
2026-10-05 19:56:36 +02:00
Magne Sjaastad 63eaa1266d Address review feedback on crash-fix batch
- Camera::fitView/computeFitViewEyePosition: derive one corrected, non-parallel up vector and use it consistently for right, upNorm, planeTop and the final setFromLookAt(), instead of only repairing the right vector. Previously the degenerate (parallel dir/up) case still produced a singular view matrix because up itself was never corrected. Added a regression test exercising fitView() end-to-end (not just computeFitViewEyePosition()) that checks the resulting direction/up/right form a valid orthonormal basis.
- RimViewController::updateCameraLink/updateTimeStepLink: guard against ownerViewLinker()->masterView() being null (RimViewLinker::setMasterView(nullptr) is a supported state), not only against a null view linker.
- RicHistogramPlotTools: use RiaGuiApplication::isRunning() before calling RiaGuiApplication::instance(), since instance() itself asserts when there is no running GUI application.
- RimDockWindowController::updateViewerWidget: create the view widget before the dock widget, so a failed view-widget creation does not leave a dock widget allocated without a dock manager (which deleteDockWidget() cannot clean up).
- RimStimPlanModelCalculator::calculateFormation: avoid continue via a small lambda, and reject double values outside the range of int before the static_cast to avoid undefined behavior.
2026-10-05 19:56:10 +02:00
Magne Sjaastad 1a6c29a319 Fix crash in Camera::computeFitViewEyePosition with parallel dir/up
dir^up becomes a zero vector when the view direction and up vector are parallel, producing an invalid zero-normal plane. Plane::distanceToOrigin() then asserts/aborts (CVF_ASSERT, always active). Fall back to an arbitrary axis to compute a valid right vector in this degenerate case.
2026-10-05 19:56:10 +02:00
Magne Sjaastad b22a2e3106 Fix crash in RimViewController::masterView when detached from view linker
RimViewController::masterView() dereferenced ownerViewLinker() without a
null check, causing a crash when the controller has been detached from
its RimViewLinker parent (e.g. mid-destruction, after the owning
child-array field has already erased it but before delete runs).

The same unguarded ownerViewLinker() dereference existed in several other
methods: isActive(), isCameraLinked(), isTimeStepLinked(),
isResultColorControlled(), isLegendDefinitionsControlled(),
isPropertyFilterOveridden(), updateOverrides(),
updateDuplicatedPropertyFilters(), updateCameraLink(),
updateTimeStepLink(), updateResultColorsControl(),
updateLegendDefinitions() and applyCellFilterCollectionByUserChoice().
All now store ownerViewLinker() in a local and null-check it before use,
matching the pattern already used in isCellFiltersControlled().
2026-10-05 19:56:10 +02:00
Magne Sjaastad 7f99498072 Fix crash in RimDockWindowController when view widget creation fails
Guarded two unconditional null derefs: dockWidget->setWidget(viewWidget) when viewWidget creation fails, and viewPdmObject() in handleViewerDeletion() when no view has ever been assigned to control. Added regression test for the handleViewerDeletion() case; the setWidget() path requires a running GUI/main window and isn't reachable from the headless unit test harness.
2026-10-05 19:56:10 +02:00
Magne Sjaastad b5b34fcf9b Fix crash synchronizing 2D intersection views when owner case or view is null
synchronize2dIntersectionViews() could crash in two ways: when the view's ownerCase() is null, and when the collection has no Rim3dView ancestor at all (e.g. mid-destruction after detaching from the PDM tree, where firstAncestorOrThisOfTypeAsserted<Rim3dView>() returns null since CAF_ASSERT is compiled out in release). Both cases are now guarded.
2026-10-05 19:56:10 +02:00
Magne Sjaastad a6a2f349b6 Fix crash in RigStimPlanFractureDefinition::minY/maxY on empty Ys 2026-10-05 19:56:10 +02:00
Magne Sjaastad a94358cc0d Drop implicit include dirs from per-file HDF5 include property
A system HDF5 reports /usr/include. CMake filters implicit dirs from
target include directories but not from the source-file
INCLUDE_DIRECTORIES property, so -I/usr/include reached the command line
and broke #include_next <math.h> in <cmath> on gcc-toolset.
2026-10-05 13:27:50 +02:00
Magne Sjaastad 4ab0938c2d #14806 Faults: Compute unnamed fault faces in parallel and only from positive faces (#14836)
* #14806 Faults: Compute unnamed fault faces in parallel and only from 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.

* #14806 Faults: Add unit tests for parallel unnamed fault face computation

Build a small in-memory grid (no file, no view) with geometric faults at
every I interface, and verify that calculateFaults() finds all unnamed
fault faces, keeps them ordered by native cell index (the per-thread
results are appended in thread order), and separates faces touching an
inactive cell into the dedicated inactive fault face list.
2026-10-03 09:16:23 +02:00
Magne Sjaastad 6b96df134e #14806 Cell search tree: Group cells in leaves and store leaf ids 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.
2026-10-03 07:57:03 +02:00
Magne Sjaastad c5c0e05012 Fix ensemble contour map GENERATED result statistics and caching bugs (#14813)
Fixes a set of related bugs affecting ensemble contour maps that use a GENERATED (grid calculation) result, plus a related bug where switching a view's case lost generated results.
2026-10-02 15:08:30 +02:00
Magne Sjaastad b6704429cd Scope GRPC/ODB/OpenVDS/HDF5 build flags to avoid full rebuilds
- Remove unused SOURCE_GROUP_HEADER_FILES from GrpcInterface CMakeLists
- Scope the following defines to the files that need it ENABLE_GRPC, USE_ODB_API , USE_OPENVDS, USE_HDF5 
- RifOdbReader.cpp copied an odb_InstanceRepository by value, which
  fails to compile under MSVC's strict conformance mode due to an
  ambiguous implicit copy constructor in the vendor headers (diamond
  inheritance). Use a reference instead, since it was only ever read
  from.
2026-10-02 12:24:29 +02:00
Magne Sjaastad fa5ba28b0d Fix macOS build: add missing <iomanip> include for std::setw in remaining test files 2026-10-01 09:17:51 +02:00
Magne Sjaastad 7f7e710b16 Fix macOS build: add missing <iomanip> include for std::setw 2026-10-01 07:59:58 +02:00
Magne Sjaastad b28051e3d5 #14797 Add RigContourMapPeakFinder to find local maxima in contour maps
Union-find sweep from highest to lowest value computes the prominence of each peak. Peaks are filtered on prominence and edge contact, ranked by prominence or value, and thinned by minimum distance. Flat shoulders and plateaus are rejected, and prominence is measured against the minimum of each connected data region.
2026-09-30 16:26:04 +02:00
Magne Sjaastad 6c09ad66d9 Fix macOS build: add missing <iomanip> include for std::setw 2026-09-30 07:25:31 +02:00
Magne Sjaastad 64b53b0612 #14710 Show active data filter as overlay text in contour map view
Refresh the label when the filter selection changes and repaint immediately, as this happens outside a display model rebuild.
2026-09-28 10:30:12 +02:00
Magne Sjaastad bb8af7bbbd #14710 Compute per-time-step visible cells for dynamic data filters
A static property with an active dynamic filter now produces a contour map per time step. Adds a synthetic ensemble fixture with unified restart files, as the OPM reader used for statistics does not support per-step restart files.
2026-09-28 10:30:12 +02:00
Magne Sjaastad cf75dbf58e #14710 Warn when loading a project with the obsolete formation filter
Keep the removed formation filter fields as obsolete so old projects still parse, and warn that the filter is no longer applied.
2026-09-28 10:30:12 +02:00
Magne Sjaastad 9911c49d2b #14710 Support ensemble data filters in ensemble contour maps
Replace the built-in formation filter with ensemble data filters. Load ensemble data filters after project read, and parent new views before assigning the case so the ensemble filter collection is resolved correctly.
2026-09-28 10:30:12 +02:00
Magne Sjaastad d3ce3146fd Guard result metadata copy against a main case without results 2026-09-28 09:18:41 +02:00
Magne Sjaastad 0db64b400b Catch roff parse errors when checking for grid data 2026-09-28 09:18:41 +02:00
Magne Sjaastad 17e8c96e00 Use resdata reader for cases with non-unified restart files
The opm-common reader only reads unified restart files (UNRST). When the
opm-common reader was selected in preferences, cases with one restart file per
time step (X0000, X0001, ...) were opened without dynamic results.

- Fall back to the resdata reader when there is no unified restart file but
  non-unified restart files are present.
- Unit tests using dynamic results check that the result and time step exist
  before accessing them, so a missing result fails the test instead of
  crashing the test executable.
2026-09-27 21:13:13 +02:00
Magne Sjaastad 20a6373104 #14780 Add unit tests for grouping mode None with varied folder structures
Add a test covering a flat 'realization-N/CASE.EXT' folder structure
(no iter-N level) grouped with EnsembleGroupingMode::NONE, verifying
all files end up in a single best-effort ensemble. Also add a test
confirming empty input produces no bogus ensemble entry.
2026-09-24 08:16:29 +02:00
Magne Sjaastad 3437cf9b94 #14778 Fix crashes from unguarded pointer and index accesses
* Skip deleted plot widgets in RiuMultiPlotBook::visiblePlotWidgets
* Guard missing calculation in detectCyclicCalculation
* Guard invalid node index in RigFemPart node lookups
* Guard null well path in RimWellLogExtractionCurve::extractGeomData
* Guard unopened case in RimGridCalculation::removeDependentObjects
* Guard empty subset in createLateralAtMeasuredDepth
2026-09-22 08:23:00 +02:00
Kristian Bendiksen 4d2a868079 #14766 Fix potentially uninitialised object used for accumulation
RigStatisticsCalculator::mobileVolumeWeightedMean() accumulated into a sum
from an out-parameter that callees were not required to write. Every
implementation of the per time step overload has early-return paths that
leave the value untouched, as does RigWeightedMeanCalc::weightedMeanOverCells,
so indeterminate stack memory could be summed and presented in the UI.

Return std::optional<double> from the computation layer instead of using an
out-parameter, making "value not available" explicit and impossible to ignore:

- RigWeightedMeanCalc::weightedMeanOverCells
- RigStatisticsCalculator::mobileVolumeWeightedMean and all overrides

Time steps without a computable mean no longer contribute to the accumulated
sum, and are excluded from the divisor. Previously they would either add
garbage or, with a naive zero initialisation, bias the average towards zero.

RigStatisticsDataCache keeps the existing HUGE_VAL marker on its public API
via value_or(), so behaviour seen by RigHistogramData and the overlay info
is unchanged apart from the fix.

Also:
- Set m_isVolumeWeightedMeanCalculated in the per time step cache, which was
  never assigned, so the cached value was recomputed on every call.
- Remove a duplicated ensureKnownResultLoaded() call in
  RigEclipseNativeVisibleCellsStatCalc.

Fixes #14766
2026-09-21 18:36:27 +02:00
Kristian Bendiksen 0eba9e8ef7 #14752 Well Target Mapping: use view-independent data filters 2026-09-18 12:36:43 +02:00
JJ e0c1f23e6e Support for ensemble jobs (#14773)
Initial support for running well planning opm flow jobs for ensembles
2026-09-17 14:03:54 +02:00
Magne Sjaastad 044454b9b1 Auto-assign Y-axis for ensemble curve sets based on unit/vector match
Extends the existing single-curve auto axis assignment (unit and summary vector matching, then alternating left/right) to also cover RimEnsembleCurveSet. Previously ensemble curve sets were always placed on the default left axis, so e.g. FOPT and FOPR ensembles ended up on the same axis despite differing units.

- Add RimEnsembleCurveSet::unitNameY(), looked up from the first available summary case reader in the ensemble.
- Move X and Y axis assignment from RimSummaryPlot to new RimSummaryPlotTools. Y-axis assignment takes a RiaSummaryAddressModifier::CurveAddressProvider, and compares against both curves and curve sets in the plot.
- RimEnsembleCurveSetCollection::addCurveSet gains an autoAssignPlotAxis flag (default true, matching addCurveAndUpdate for single curves).

Also fixes a bug in the summary plot editor where ensemble curve sets manually assigned to different Y-axes collapsed onto the same axis when clicking OK. The PdmPtrField axis reference does not resolve across the cloned preview and target plots. Add RimEnsembleCurveSet::findOrAssignLeftOrRightAxisY() to capture and re-apply the axis explicitly.

Add RimSummaryPlot-Test.cpp with unit tests for axis auto-assignment of curves and ensemble curve sets.

Fixes #14728
2026-09-16 06:28:50 -04:00
Kristian Bendiksen f32d59775b Python: Reject summary writes for unsupported case types 2026-09-16 11:37:59 +02:00
Kristian Bendiksen 52e212e24f #14667 Completions: Simplify segment interval properties 2026-09-16 11:35:13 +02:00
Kristian Bendiksen 63bcc22485 #14667 Completions: Move MSW settings to segments 2026-09-16 11:35:13 +02:00
Magne Sjaastad cfb9e5765e #14761 Find summary data files when file name contains multiple dots
QFileInfo::baseName() truncates at the first dot, so the ESMRY and h5 files were not found for realizations like CASE.V2-0.SMSPEC. Without an UNSMRY file the realization was opened as an empty summary case. Use completeBaseName() to strip only the extension.
2026-09-16 05:06:47 -04:00
Kristian Bendiksen 26314940a3 #14345 Property Filter: Use view case for ensemble filters 2026-09-16 10:53:31 +02:00