Commit Graph
396 Commits
Author SHA1 Message Date
Kristian Bendiksen e3e09c0d1f #14772 Python: Add WellPath.export_geometry as object method and forward exportWellPaths to it
RimWellPath_exportGeometry writes the well path to a .dev file in an
explicit folder. RicfExportWellPaths resolves the well path names (empty
means all) and the WELLPATHS export folder from the command file
executor, then forwards to it per well path.
Project.export_well_paths() in Python is kept and emits a
DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 147a60ceec #14772 Python: Add Project.import_formation_names and Case.set_formation_names as object methods and forward importFormationNames to them
The legacy command combined import and assignment with an applyToCaseId.
This is split into RimProject_importFormationNames (returns the
FormationNames object) and RimCase_setFormationNames (takes the
object). RimFormationNames is made scriptable so it can be returned and
passed. RicfImportFormationNames forwards to both.

Project.import_formation_names() in Python keeps its signature, now
returns the FormationNames object, and gains an apply_to_all_cases
flag (default True, matching the old behavior).
Case.import_formation_names() is kept and emits a DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen b60ccf1f83 #14772 Python: Add WellPathCollection.import_well_log_files as object method and forward importWellLogFiles to it
RimWellPathCollection_importWellLogFiles imports LAS files given
explicitly and/or all LAS files in a folder. RicfImportWellLogFiles
forwards to it.

Project.import_well_paths() and Project.import_well_log_files() in
Python now call the object methods on the well path collection. Their
signatures and return values are unchanged, so no deprecation.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 6548c4f4db #14772 Python: Add Project.create_grid_case_group as object method and forward createGridCaseGroup to it
RimProject_createGridCaseGroup returns the created group object.
RicfCreateGridCaseGroup forwards to it and wraps the group id and name
in the legacy createGridCaseGroupResult. The hand-written Python
wrapper is removed since the generated method has the same signature.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 739f3744f6 #14772 Python: Add Project.load_case as object method and forward loadCase to it
RimProject_loadCase loads a grid case from file and returns the case
object. RicfLoadCase forwards to it and wraps the case id in the legacy
loadCaseResult. The hand-written Python Project.load_case() wrapper is
removed since the generated method has the same signature and returns
the most-derived case class.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen cc1f09b665 #14772 Python: Add EclipseCase.create_saturation_pressure_plots as object method and forward createSaturationPressurePlots to it
RimEclipseResultCase_createSaturationPressurePlots exposes the time step
(the legacy command hardcodes 0) and returns an error when no plots
could be created. It only shows the plot window when a GUI is running;
the legacy code dereferenced RiaGuiApplication::instance()
unconditionally. RicfCreateSaturationPressurePlots resolves the cases
and loops, treating per-case failures as warnings as before.

The hand-written Case.create_saturation_pressure_plots() Python wrapper
is removed since the generated EclipseCase method shadows it.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 3ce81c4eca #14772 Python: Add GridCaseGroup.replace_source_cases as object method and forward replaceSourceCases to it
RimIdenticalGridCaseGroup_replaceSourceCases takes the grid file paths
directly (instead of a list file) and an optional ProjectFile, following
the same design as Case.replace_grid. RicfReplaceSourceCases reads the
list file and the executor's last project path and forwards to it.
Project.replace_source_cases() in Python is kept and emits a
DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 1eabb5f5f6 #14772 Forward computeCaseGroupStatistics to RimcEclipseStatisticsCase_computeStatistics
Add an UpdateViews parameter to the existing object method. The legacy
command calls computeStatisticsAndUpdateViews() (which also creates a
view if none exists) while the object method only computes; the default
(false) keeps the object method behavior and the Ricf forwarder passes
true. RicfComputeCaseGroupStatistics resolves the statistics cases and
loops over them.

GridCaseGroup.compute_statistics(case_ids=...) in Python now loops over
statistics_cases() and emits a DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 111741b365 #14772 Forward createStatisticsCase to RimcIdenticalGridCaseGroup_createStatisticsCase
Add a PopulateResultSelection parameter to the existing object method.
The legacy command selects all available properties (via
createAndAppendStatisticsCase) while the object method created an
empty selection; the default (false) keeps the object method behavior
and the Ricf forwarder passes true. The created case now gets a case id
assigned in both paths.

Add RicfForwarding::findCaseGroup() and findStatisticsCase().
2026-09-22 14:19:23 +02:00
Kristian Bendiksen eda2d73fed #14772 Forward scaleFractureTemplate to RimcFractureTemplate_setScaleFactors
Add a typed setter to the existing RimcFractureTemplate_setScaleFactors
object method and let RicfScaleFractureTemplate forward to it via
RicfForwarding::findFractureTemplate(). Make RimFractureTemplate::m_id
scriptable (read-only) so templates can be looked up by id from Python.

Project.scale_fracture_template(template_id=...) in Python now resolves
the template object and calls FractureTemplate.set_scale_factors(),
emitting a DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen dbd9e50f5f #14772 Python: Add EclipseCase.export_flow_characteristics as object method and forward exportFlowCharacteristics to it
RimEclipseResultCase_exportFlowCharacteristics has the same arguments
as the legacy command (lists only, no scalar shorthand).
RicfExportFlowCharacteristics forwards to it.

The hand-written Case.export_flow_characteristics() Python wrapper is
removed: the generated EclipseCase method has the same name and
argument names and shadows it for all cases the command applies to.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 6e3e6e738f #14772 Python: Add Reservoir.create_multiple_fractures as object method and forward createMultipleFractures to it
RimEclipseCase_createMultipleFractures takes WellPath objects and a
FractureTemplate object instead of names and ids. The
MultipleFractures::Action enum is moved from the Ricf header to
RicCreateMultipleFracturesFeature.h so the object method does not
depend on CommandFileInterface, and is registered as the Python
StrEnum MultipleFracturesAction.

Add RicfForwarding::findFractureTemplate(). RicfCreateMultipleFractures
resolves names/ids and forwards to the object method.

The hand-written Case.create_multiple_fractures(template_id=...,
well_path_names=...) Python wrapper is removed: the generated
Reservoir method has the same name and shadows it. The test is updated
to the object based signature.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen afa816826b #14772 Forward exportLgrForCompletions to RimEclipseCase_exportLgrForCompletions
RicfExportLgrForCompletions resolves well path names and the LGRS
export folder from the command file executor and forwards to the
object method. Add Python tests for both LGR object methods.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen e54363133e #14772 Python: Add Reservoir.create_lgr_for_completions and export_lgr_for_completions as object methods
RimEclipseCase_createLgrForCompletions and
RimEclipseCase_exportLgrForCompletions take WellPath objects and
expose refinement and split type. Lgr::SplitType is registered as the
Python StrEnum LgrSplitType. RicfCreateLgrForCompletions forwards to
the create method. Case.create_lgr_for_completion() in Python is kept
and emits a DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen b40d19f55f #14772 Python: Add Reservoir.export_msw_completions as object method and forward exportMsw to it
RimEclipseCase_exportMswCompletions takes WellPath objects and an
explicit export folder. RicfExportMsw resolves the well path name and
export folder and forwards to it. Case.export_msw() in Python is kept
and emits a DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen afe8f39f6b #14772 Python: Add Reservoir.export_completions as object method and forward exportWellPathCompletions to it
RimEclipseCase_exportCompletions takes WellPath objects (empty list
means all visible well paths) and an explicit export folder, and
exposes all completion export settings. The existing enums
ExportSplit, CompdatExport and PressureDepletionWBHPSource are
registered as Python StrEnums CompletionExportSplit,
CompdatExportType and TransScalingWbhpSource.

RicfExportWellPathCompletions resolves well path names to objects and
the export folder from the command file executor, then forwards to the
object method. Case.export_well_path_completions() in Python is kept
and emits a DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 001a515c68 #14772 Python: Add EclipseView.export_visible_cells as object method and forward exportVisibleCells to it
RimEclipseView_exportVisibleCells writes a FLUXNUM/MULTNUM/ACTNUM
keyword based on cell visibility in the view and requires an explicit
export file. The export keyword reuses
RicSaveEclipseInputVisibleCellsUi::ExportKeyword, registered as the
Python StrEnum VisibleCellsExportKeyword.

RicSaveEclipseInputVisibleCellsFeature::exportVisibleCells() is split
out of executeCommand() to return errors via std::expected instead of
only logging them.

RicfExportVisibleCells resolves the export folder from the command file
executor's CELLS export path and forwards to the object method. The
hand-written View.export_visible_cells() wrapper is removed since the
generated EclipseView method shadows it.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 1f06f02b39 #14772 Python: Add EclipseView.export_current_property and forward exportPropertyInViews to it
RimEclipseView_exportCurrentProperty exports the cell result shown in
the view at its current time step to a GRDECL style text file, and
requires an explicit export file. RicfExportPropertyInViews selects the
views by id/name, resolves the default file names from the command file
executor's PROPERTIES export folder, and forwards to it for each view.

The method is named exportCurrentProperty rather than exportProperty to
avoid shadowing the legacy View.export_property() wrapper (different
signature) in the generated Python class hierarchy. The legacy wrapper
is kept and emits a DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen d2078613a8 #14772 Python: Add Reservoir.export_property as object method and forward exportProperty to it
RimEclipseCase_exportProperty writes a cell property to a GRDECL style
text file and requires an explicit export file. RicfExportProperty
resolves the default file name from the command file executor's
PROPERTIES export folder and forwards to it.

The hand-written Case.export_property() wrapper is removed. The
generated Reservoir.export_property() has the same argument names and
shadows the base class wrapper anyway, so a deprecation shim would
never be reached.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 77c32a3fa5 #14772 Python: Add snapshot export object methods and forward exportSnapshots to them
- Add RimViewWindow_exportSnapshot on RimViewWindow (3D views and
  plots) with explicit ExportFolder, Prefix, Width, Height and
  FileFormat parameters. Generated as ViewWindow.export_snapshot().
- Add RimProject_exportSnapshots for exporting all views and/or plots
  with a ContentType parameter. Generated as Project.export_snapshots().
- Add RiaDefines::SnapshotFileFormat and SnapshotContentType enums,
  registered as Python StrEnums.
- Extract single-item exportSnapshotOfView()/exportSnapshotOfPlot()
  from the RicSnapshotAll*ToFileFeature loops so the object methods
  and the legacy loops share the implementation.
- RicfExportSnapshots resolves the export folder from the command file
  executor and forwards to the object methods.

Python: the hand-written ViewWindow.export_snapshot() wrapper is
removed (generated method is compatible). PlotWindow.export_snapshot()
and Project.export_snapshots() keep their legacy argument names
(file_prefix, output_format, snapshot_type, plot_format) as deprecated
aliases. Case.export_snapshots_of_all_views() is deprecated in favor
of View.export_snapshot().

Also fix Case.views(), which compared the view id to the case id and
therefore never returned any views.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen ee28576c48 #14772 Python: Add View.set_time_step as object method and forward setTimeStep to it
Rim3dView_setTimeStep validates the time step against the owner case
and updates the view. RicfSetTimeStep forwards to it, looping over all
views of the case when viewId is -1. The hand-written Python
View.set_time_step() wrapper is removed since the generated method has
the same name and signature.

Also fix the argument description of the new Rimc methods: the whatsThis
text is the third variadic argument of CAF_PDM_InitScriptableField.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen e87e372c7b #14772 Python: Add View.clone as object method and forward cloneView to it
Rim3dView_clone copies an Eclipse or GeoMech view into the same case
and returns the new view. RicfCloneView forwards to it. Add a
project-wide RicfForwarding::findView(viewId) helper. The hand-written
Python View.clone() wrapper is removed since the generated method has
the same name and signature.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen bdef98203b #14772 Python: Add Case.create_view as object method and forward createView to it
RimCase_createView creates a 3D view in an Eclipse or GeoMech case and
returns it. RicfCreateView forwards to it and wraps the view id in the
legacy createViewResult. The hand-written Python create_view() wrapper
is removed since the generated method has the same name and signature.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen 3eb63c0b8e #14772 Python: Add Case.replace_grid and forward replaceCase to it
First step in modernizing the command file interface: move the
implementation of legacy Ricf commands into object-oriented Rimc
methods, and let the Ricf command forward to them.

- Add RimCase_replaceGrid (PdmVoidObjectMethod on RimCase) with
  NewGridFile and optional ProjectFile parameters. Works for both
  Eclipse result cases and GeoMech cases. Generated in Python as
  Case.replace_grid().
- Add RicfCommandForwarding helpers for resolving ids to objects and
  converting std::expected results to PdmScriptResponse.
- RicfSingleCaseReplace::execute() now resolves the case and the
  executor's last project path, then forwards to RimCase_replaceGrid.
  Command file syntax and Commands.proto are unchanged.
- Case.replace() in Python is kept as a thin wrapper over
  replace_grid() and emits a DeprecationWarning.
2026-09-22 14:19:23 +02:00
Kristian Bendiksen ef1ad39723 Python: Reject overwriting source summary vectors 2026-09-16 11:37:59 +02:00
Kristian Bendiksen dc1cc8e243 #14667 Python: Update tubing event interval test 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 d0d472aaa2 #14723 Python: Pin grpcio-tools to keep protobuf 6 gencode loadable
grpcio-tools 1.82.0+ (including its 1.82.0 pre-releases) bundles a
protoc that emits protobuf 7.35.x gencode, which no protobuf 6 runtime
can load. Pin grpcio-tools below that (excluding pre-releases via the
'.dev0' trick, since a plain '<1.82' bound already let a 1.82.0rc
release slip through once) and add a CI check that verifies the
generated *_pb2.py files stay within the protobuf floor declared in
pyproject.toml.

Only the load-bearing bounds are kept: protobuf's '>=6.33.5' floor
(must match the emitted gencode) and grpcio-tools' '<1.82.0.dev0'
ceiling. Non-load-bearing bounds (protobuf's '<8', grpcio-tools'
'>=1.81') were dropped since they don't change dependency resolution
or protect against anything the above doesn't already cover.
2026-09-11 05:46:28 -04:00
Kristian Bendiksen 71c5b5a97d #14612 Simulator Events: Remove Orion project naming 2026-09-09 13:01:26 +02:00
Kristian Bendiksen f38332b2e6 #14648 Reduce the risk of changed behaviour for text values in lists
A quote or an opening bracket is only given special meaning when it is the first character of a value. Brackets and parentheses are treated as ordinary characters for text based values, as nested containers are not possible for these types. Text values are then parsed as before, also when they contain unbalanced brackets, parentheses or quotes.

Items in a tuple are not quoted by the Python client, as the tuple parser does not support quoted strings.

Add unit tests for text values containing separator characters, white space, file paths, numbers, nested containers and 3D vectors.
2026-09-09 11:19:44 +02:00
Kristian Bendiksen 5ed45b8f19 #14648 Python: Support strings containing commas in list arguments
Lists sent from Python over gRPC are serialized as text, and the list parser split on every comma, also commas inside a string. A category name like "Coal,Calcite" was therefore split in two, and set_discrete_property_category_names() failed with "CategoryValues and CategoryNames must have matching sizes".

The list parser is now quote-aware, and ignores commas inside quoted strings and inside nested brackets and parentheses. A quoted item is parsed as a quoted string also when the surrounding text is unquoted, as is the case for text coming from Python. The Python client quotes and escapes strings in lists and tuples when they contain separator characters.

Add unit tests for the field serialization and a Python test for the category names.
2026-09-09 11:19:44 +02:00
Kristian Bendiksen 275b120688 #14683 Python: Generalize gRPC resource limit error 2026-09-07 18:58:05 +02:00
Kristian Bendiksen 2e5a3a3d17 #14683 Python: Preserve positional heartbeat callback 2026-09-07 18:58:05 +02:00
Kristian Bendiksen 35614d160e #14683 Serve liveness requests on the gRPC server thread
Requests are queued by the completion queue thread and processed from the main
thread. A long running request, or an open progress dialog in the GUI, therefore
left every request unanswered for as long as that operation lasted, including
the liveness checks a client uses to decide whether ResInsight is still there.

Let a callback declare that it touches no application state, and serve those
directly on the completion queue thread instead of queueing them. GetVersion is
the only such callback, since it reads compile-time constants only. Everything
that touches the project or the data model is still processed on the main
thread, so no request can observe or modify the data model while another one is
running.

The allocated callback list is now used from both threads and is guarded by a
mutex. Shutdown takes a lock before flagging that it is in progress, so that it
waits for any dispatch already running on the completion queue thread and no new
request handler can be registered on a queue that is about to be shut down.

During a blocking call of 3.25 s, 65 pings were answered with a maximum latency
of 6.2 ms. Before this change none of them were answered until the call
completed.
2026-09-07 18:58:05 +02:00
Kristian Bendiksen 32f97bd862 #14683 Raise the gRPC message size limit for large payloads
A schedule generated from a full production history, or a large raw text block
imported into the event timeline, easily exceeds the gRPC default limit of 4 MB.
Such a call failed with "Received message larger than max (5119402 vs 4194304)"
even though both sides were healthy.

Raise the limit to 128 MB on the server and use a matching limit for the client
channels. A schedule of 19.5 MB is now returned without error.
2026-09-07 18:58:05 +02:00
Kristian Bendiksen 16ad832689 #14683 Python: Add context to connection and message size errors
A call that failed because the connection went away surfaced the raw gRPC text,
typically "Channel closed!", which says nothing about what happened. Translate
such failures through a single helper that explains that the connection to
ResInsight was lost while the call was running, and that names the message size
limit when that is the cause. The gRPC code and details are still carried on the
RipsError for callers that branch on them.
2026-09-07 18:58:05 +02:00
Kristian Bendiksen b0496f82d6 #14683 Python: Do not treat a busy ResInsight as a dead one
ResInsight serves gRPC requests from its main thread, so a long running call
leaves the heartbeat pings unanswered for as long as that call runs. The
heartbeat counted those timeouts as connection failures and closed the channel,
which aborted the very call the user was waiting for. The client reported
"RipsError: Channel closed!" while the ResInsight process was alive and well.

Classify a ping that fails with DEADLINE_EXCEEDED or RESOURCE_EXHAUSTED as a
busy server and never count it towards the failure threshold. Only failures
that indicate a broken connection declare the connection lost. A new
busy_warning_sec argument controls when a warning is logged for a server that
has been unresponsive for a while, so long operations are visible without being
killed.

Keep the process handle from Instance.launch so the heartbeat can check whether
ResInsight actually exited. A dead process is now detected immediately and
reported with its exit code instead of a bare channel error, and check_alive()
repeats that diagnosis.
2026-09-07 18:58:05 +02:00
Kristian Bendiksen 4e0abb456f Fix crash when deleting a sub plot of a multi plot in console mode
RimMultiPlot::recreatePlotWidgets() dereferenced the viewer unconditionally. The viewer does not exist in console mode, so deleting a summary plot from Python through the generic PdmObject delete() crashed ResInsight in onChildDeleted(). Return early when there is no viewer, matching the other viewer accesses in RimMultiPlot.

Add Python regression tests for deleting a single summary plot inside a multi plot and for deleting a whole multi plot, and an example showing how project tree objects are removed with delete().
2026-09-07 14:11:02 +02:00
Kristian Bendiksen e2dc024854 Python: Create ensemble curve sets when creating summary plot for ensemble
new_summary_plot() with an ensemble and an address string created an empty
plot. The address filters were applied to an empty list of summary cases, and
no curve sets were created. Use the summary cases of the ensemble, and make
sure the summary addresses are created before the address filters are applied.

Add example script showing how to create summary plots for an ensemble.
2026-09-04 15:32:09 +02:00
Kristian Bendiksen 7867205468 #14639 Orion Events: Allow signed operand in date arithmetic
A term operand had to be an unsigned integer or a DURATION variable, so
"DATE STARTUP = 2026-08-28 + -2" was rejected as a malformed declaration
instead of subtracting two days.

Accept an optional sign on the operand in date and duration expressions, and
share one pattern between the terms of a date expression and the UNTIL terms
of INSERT_DATE so the two cannot drift apart.

Fractional day offsets are still unsupported.
2026-09-01 11:56:59 +02:00
Kristian Bendiksen 98e39bc02f #14636 Orion Events: List COMMENT as valid item name
COMMENT is accepted on all keywords and is stored on the event instead of
being passed as keyword data, so it is not part of the item names reported
by opm-common. The validation error listed only the opm-common items, giving
no hint that COMMENT is allowed when a user mistyped it as COMMENTS.

Append COMMENT to the list of valid item names in the error message. Only the
diagnostic is affected, COMMENT is still handled as event metadata.
2026-09-01 11:56:59 +02:00
Kristian Bendiksen 1336eba81d #14635 Orion Events: Use well name alias for generic keywords 2026-09-01 11:56:59 +02:00
Kristian Bendiksen 3117b69069 #14637 Orion Events: Use perforation diameter 2026-09-01 11:56:59 +02:00
Kristian Bendiksen ebf0ef0cc0 #14637 #14641 Orion Events: Emit END first after date 2026-09-01 11:56:59 +02:00
Kristian Bendiksen d226e10e89 #14637 Orion Events: Rename report date directive 2026-09-01 11:56:59 +02:00
Kristian Bendiksen 753cd65672 #14637 Orion Events: Remove date prefix 2026-09-01 11:56:59 +02:00
Kristian Bendiksen b00471dce2 #14614 Orion Events: Add menu item for importing events from file
Add RicImportOrionEventsFeature to File -> Import -> Well Data and the well
path collection context menu. The feature opens a file dialog and launches
the Python interpreter asynchronously with the new --apply mode of the
rips.orion_events CLI, which connects back to the running instance through
RESINSIGHT_GRPC_PORT and applies the events to the well event timeline.
Output is shown in the Process Monitor panel.
2026-08-28 13:22:33 +02:00
Kristian Bendiksen 0cbb5f5935 #14615 Orion Events: Preserve historical keyword values 2026-08-27 10:14:27 +02:00
Kristian Bendiksen f88136eb6a #14573 Orion Events: Add recurring report dates 2026-08-26 14:28:42 +02:00
Kristian Bendiksen 74ffc822f2 #14538 Well path: Preserve renamed file well name
The renamed well path name is serialized correctly, but reopening the project reloads the source well path file and overwrites the saved name with the name from that file. The reload flag only protected the completion export name, despite the loader also updating the displayed well path name.

Only initialize the well path and export names from the source file during first import. Subsequent data reloads preserve the names stored in the project while continuing to refresh geometry and metadata.

Add an RMS well round-trip test that renames an imported well, saves and reopens the project, and verifies that the custom name is retained.
2026-08-25 08:25:20 +02:00