Commit Graph
451 Commits
Author SHA1 Message Date
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
Kristian Bendiksen 42d46cf1a8 #14345 Property Filter: Allow bounds without result limits 2026-09-16 10:53:31 +02:00
Kristian Bendiksen 99ce6daf58 #14345 Grid Calculation: Fix additional ensemble selection 2026-09-16 10:53:31 +02:00
Kristian Bendiksen 0ba20f0b65 #14345 Grid Calculation: Add destination ensemble 2026-09-16 10:53:31 +02:00
Kristian Bendiksen 5a7e043837 #14345 Add Data Filters to grid ensembles
Add a data filter collection to RimReservoirGridEnsemble, so filters
can be defined once for the ensemble instead of per realization. The
filters are bound to the main case of the ensemble for configuration,
and evaluated per case as elsewhere.

The filter creation commands are available from a Data Filters submenu
on the ensemble node, and the collection node is hidden while empty,
matching the case-level behavior. The grid calculation data filter
options include the filters of the ensemble the destination case
belongs to.
2026-09-16 10:53:31 +02:00
Kristian Bendiksen e9b28c1b02 #14345 Add per-case cell filter evaluation with source case override
Add a sourceCaseOverride parameter to RimCellFilter::applyToCellVisibility.
When set, property filters evaluate against the override case's result
values instead of the case the filter is bound to, allowing the same
filter definition to be evaluated against each case in an ensemble.
Combined filters forward the override to their children, and geometry
based filters ignore it.

Add RimCellFilterTools::computeReservoirCellVisibility, which evaluates
a cell filter against a given case for all grids and returns the
visibility indexed by reservoir cell index. Range filters propagate the
parent grid visibility into LGR cells, matching the filtered geometry
of a 3d view.

Also add RimCellFilter::setFilterMode.
2026-09-16 10:53:31 +02:00
Kristian Bendiksen 0ad61a004a #14345 Grid Calculation: replace undefined values with default value in aggregations
Aggregation functions like sum() in the expression parser include all
values in the input vector. Undefined values (HUGE_VAL) could leak into
the aggregation input when a grid case group member has fewer time steps
on disk than the main case it inherits result meta data from, or when a
cell is active in the calculation case but has no value in the source
data. This produced infinite sums for some realizations, while the
histogram statistics ignore undefined values.

Replace undefined values in the aggregation input with the default value
0.0, matching the histogram semantics, and log a warning per case and
variable when values were replaced.
2026-09-16 10:53:31 +02:00
Magne Sjaastad 0579dbb468 Move time-step control and grid-only hooks from Rim3dView to RimGridView
* #14760 Move time-step control and grid-only hooks from Rim3dView to RimGridView
* #14760 Store named 3D visualization models in a shared collection instead of per-model fields
2026-09-16 08:44:00 +02:00
Magne Sjaastad 7fa9d0c5bf #14741 Add command-feature test infrastructure
Add the ResInsight-featuretests executable: a headless GUI test harness (RiaFeatureTestModelBuilder, RiaFeatureTestTreeView), a runner that triggers Ric*Feature commands through their QAction (RicFeatureExecutionRunner), a generic execution sweep over every registered feature (RicFeatureSweep-Test, RicFeatureExecutionSweep-Test, RicFeatureSubprocessSweep-Test, RicFeatureSweepDenylist), and supporting CMake wiring. Adds RiaRegressionTestRunner::setRunningRegressionTests() so tests can suppress modal dialogs, and shares RimMockSummaryCase as a common test model under TestModels.
2026-09-15 08:15:59 -04:00
Kristian Bendiksen 58b9f46a95 RifReaderOpmCommon: Compute restart data size locally 2026-09-14 11:59:32 +02:00
Magne Sjaastad 90a4282783 #14727 Fix ensemble filter by summary value for oscillating rate vectors
RimEnsembleCurveFilter::applyFilter() (SUMMARY_VALUE mode) only compared
the value at the last time step inside the selected time range against
the filter's value range, discarding the result of every earlier time
step. For monotonically increasing cumulative vectors (e.g. FOPT) this
coincidentally matched user expectations, but for rate vectors (e.g.
FOPR) that oscillate at high frequency between zero and a non-zero
value, the outcome depended arbitrarily on whether the last time step
happened to land on zero or not.

The filter now excludes a realization if any time step inside the
selected time range has a value outside the selected value range, i.e.
all time steps in range must be inside the value range for the
realization to be kept. This makes the behavior consistent between
FOPT and FOPR style vectors.

Added a regression test reproducing the oscillating-rate scenario, and
updated the existing performance test to describe and exercise the new
semantics.
2026-09-14 03:10:24 -04:00
Magne Sjaastad 8776a2e2bf #14703 Grid statistics: Fix missing results for computed dynamic results like riPORV*SOIL
RimEclipseStatisticsCaseEvaluator::addNamedResult() sized the destination
statistics containers (MEAN/P10/P50/P90/etc.) using the time step count of
an arbitrary first result found in the source case (existingResults()[0]).

Results computed by ResInsight, such as riPORV*SOIL and riPORV*SGAS, do not
have their own time step info populated until they are actually computed,
so existingResults()[0] can end up being an unrelated result, including a
static one (e.g. PORV) with only a single time step. Using its size to
size the destination containers collapsed the statistics for all dynamic
results to a single time step, silently dropping the results for every
other time step, i.e. no results were shown for riPORV*SOIL / riPORV*SGAS.

Fix by using RigCaseCellResultsData::maxTimeStepCount() to find the source
result with the most time steps, and use its time step info both for the
destination time step metadata and for sizing the destination containers,
instead of depending on an arbitrary source result.

Added a unit test reproducing the ensemble statistics computation for
riPORV*SOIL across two source cases.
2026-09-12 04:53:16 -04:00
Jørgen Herje c49f298a7d [ri-cloud-api]: Add grid data from sumo using api (#14653)
Add grid data from Sumo using ri-cloud-api

Load Eclipse grid data (roff) from Sumo as RimReservoirGridEnsemble, one case per realization, with async fetch of grid properties per timestep.

- New: RiaSumoGrid (transport), RifReaderSumoGridProperty (lazy property reader), RimReservoirGridEnsembleSumo, RimRoffCaseSumo, and a "Create Reservoir Grid Ensemble" command.
- Shared grid: IJK dimensions compared before download; one RigMainGrid is reused across the ensemble when they match, each realization still parses its own ACTNUM before releasing geometry.
- Rename folders: Summary/Sumo -> Summary/Cloud, RimSumoDataSource -> Cloud/ (PDM keywords unchanged, old project files still load).
- UI: cloud data sources also shown in the 3D window's Data Sources dock.
- Fix: realizations no longer lost on project reload; realizations missing data are now reported instead of silently skipped.
2026-09-10 10:33:58 +02:00
Kristian Bendiksen 71c5b5a97d #14612 Simulator Events: Remove Orion project naming 2026-09-09 13:01:26 +02:00