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.
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.
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.
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.
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.
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.
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.
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.
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().
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.
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.
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.
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.
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.