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.
They are not planned as part of the file format. PERFID on a completion event is now an unknown-attribute error like any other unrecognized key, and DSHIFT on keyword events is forwarded unchanged instead of being stripped with a warning. FILTER keeps its ignore-with-warning behavior outside PERFORATION events.
GenerateSchedule gains an AdditionalDates parameter (ISO date strings). The dates are merged, deduplicated and sorted with the event dates and each becomes a DATES keyword even when no events fall on it, ensuring a summary report at that date in Eclipse/Flow. They are deliberately not filtered by the last applied timestamp.
The ORIONEVENTS 2.0 format gains a top-level REPORT <date-expr> directive (date variables and day arithmetic supported). Parsed dates are collected on OrionDocument.report_dates and surfaced by the applier as sorted ISO strings on ApplyReport.report_dates, ready to pass to generate_schedule_text(additional_dates=...).
Declare FILTER HIPORO with a qualified result name (static.PORO) and
reference it from the first perforation, passing case= to the applier
and printing the attached filter per materialized perforation interval.
The FILTER parts are included only when the project has a loaded case,
so the example keeps working in caseless projects.
Add a FILTER declaration (referenced by two perforations) and an inline
filter expression to the shipped well_events.orion sample, and extend
import_orion_events.py to pass case= to the applier and list the
combined data filters created from the declarations. Skip schedule
generation gracefully when no events were applied, and give FilterExpr
a __str__ returning the raw expression so variable listings stay
readable.
Add a typed FILTER declaration to the ORIONEVENTS 2.0 grammar, e.g.
FILTER POROPERM = "PORO > 0.4 AND PERMX > 100.0". A PERFORATION event
references it with FILTER=POROPERM or supplies an inline quoted
expression. When applied, each used filter is materialized as a
case-level combined data filter (one property filter per term, one-sided
inclusive bounds, AND/OR combine mode) and attached to the perforation.
Unqualified result names are searched in STATIC_NATIVE, DYNAMIC_NATIVE
then GENERATED results; a TYPE. qualifier restricts the search. Missing
results raise before any event is applied. apply_orion_document gains an
optional case= parameter defaulting to the project's first case.
RimWellEventPerf carries a RimCellFilter ptr-field with scriptable
AddFilter/cell_filter methods, and the filter is copied onto the
RimPerforationInterval when the timeline materializes completions.
Deleting PDM objects on a worker thread is not safe. PdmObjectHandle::prepareForDelete()
mutates state owned by other objects, it nulls the guarded pointers held by other objects
and clears m_pointersReferencingMe, an unsynchronised std::set that every PdmPointer
construction and destruction touches. Destroying an object off the main thread therefore
races with the main thread on the shared object graph. See issue 14491.
Profiling a summary ensemble teardown shows the mechanism does not pay for itself. Releasing
397 Drogon realizations takes 0.24 s sequentially and 0.24 s in parallel, and for a heavy
case the parallel release is slower than the sequential one, because free() is serialised
inside the allocator. The PDM bookkeeping itself is 0.4 to 2.8 percent of the teardown.
Remove the class and deleteChildrenAsync(), and delete synchronously instead. The call sites
that used clearWithoutDelete() and a manual delete loop to work around the race can now call
deleteChildren() directly. Add caf::PdmObjectHandleTools::deleteObjects() for the case where
the objects are no longer owned by a child array field.
The observer disconnection from issue 12262 does not depend on clearWithoutDelete(). ~Signal()
unregisters itself from every observer, so a deleted child detaches itself. That fix addressed
the async race, where ~Signal() mutated the observer list from a worker thread. The unit test
is updated to assert the observed signal count directly instead of relying on a crash.
Relocate import_orion_events.py and well_event_schedule_orion.py from
wells_and_fractures to a new experimental folder, and update the doc
reference in docs/orionEvents.md accordingly.
Roll back the __getattr__ lazy-import hook in rips/__init__.py. The hook
existed only so that a plain import rips would expose rips.orion_events
as an attribute; that eager exposure is also what triggered runpy's
found in sys.modules warning under python -m rips.orion_events.
Instead do not auto-expose the submodule from the package and have the
two examples import rips.orion_events explicitly, which is idiomatic and
warning-free.
Extend the 2.0 format to cover the full WellEventTimeline API demonstrated
by well_event_schedule.py.
Add built-in TUBING, VALVE and STATE event types mapping to
add_tubing_event, add_valve_event (including the AICD parameters) and
add_state_event, validated with the same required/unknown-attribute
handling as PERFORATION.
Pass any other event type inside a WELL block through generically as an
Eclipse well keyword via add_well_keyword_event with the well name
injected, so WRFTPLT, WCONPROD and the rest work without enumeration.
Event types that closely resemble a misspelled built-in are handled by
the on_unknown_event policy with a did-you-mean hint instead of being
passed through.
Add a SCHEDULE block: a bare SCHEDULE line opens a block of well-less
keyword events (RPTRST, GRUPTREE, TUNING, ...) applied through
add_keyword_event; completion events in a SCHEDULE block are rejected.
Parsed schedule events live in OrionDocument.schedule_events.
Accept ISO datetimes in event dates (@2024-05-15T14:45:30.500); the
time-of-day survives into the generated DATES keyword's TIME field with
millisecond precision. Day-offset arithmetic applies to datetimes too.
Ship well_event_schedule_orion.py, an ORIONEVENTS counterpart to
well_event_schedule.py, and extend the test suite from 55 to 70 tests
including an integration test that applies every event kind and verifies
the generated schedule text.
Replace the 1.0 grammar with a version 2.0 designed to be easier to parse
and easier to write. Variables are now typed: DATE, DURATION (whole days)
and WELL alias declarations replace the untyped SET, and using a variable
of the wrong type produces an error citing both the use and declaration
site. Well blocks open with an explicit WELL keyword (alias or
double-quoted literal name), quoting is double quotes throughout, and
date arithmetic accepts signed chains of integers and DURATION variables
such as @START + RAMP - 2. ORIONEVENTS 1.x headers are rejected with a
migration message.
FILTER and PERFID are no longer parse errors; any KEY=VALUE attribute
parses and the applier warns and ignores the not-yet-supported keys
(FILTER, PERFID, DSHIFT) while still applying the rest of the event.
The parser now recovers per line and reports every error in one pass via
OrionParseError.errors, unknown variables, event types and keywords get
difflib-based did-you-mean hints, and a stdlib-only validator CLI runs as
python3 -m rips.orion_events <file>. The eager orion_events import in
rips/__init__.py is replaced by a PEP 562 lazy import so the -m entry
point does not trigger runpy's double-import warning.
Update the shipped sample file and example script to the 2.0 syntax and
extend the test suite from 27 to 55 tests covering typed declarations,
offset arithmetic, alias resolution, multi-error diagnostics and the CLI.
Add a pure-Python parser (rips.orion_events) that reads an ORIONEVENTS
text file into a structured representation, plus an applier that drives
the existing WellEventTimeline API to create perforation, WCONHIST and
WELTARG events.
The parser is split into a stdlib-only Layer A (parse_orion_events ->
OrionDocument) that is unit-testable without a running ResInsight, and a
Layer B applier (apply_orion_document) that maps the document onto
add_perf_event/add_well_keyword_event and resolves well names via the
project. RADIUS is mapped to diameter, dated SET variables support '+ N'
day arithmetic, and FILTER/PERFID are reserved but currently raise a
located error while DSHIFT is ignored with a warning.
Ship a documented grammar in the module docstring, a clean sample input
(example_input_files/well_events.orion), a runnable example
(import_orion_events.py), and tests covering parsing, mapping and an
end-to-end integration test against a loaded case.
* #14411 Enforce name uniqueness for surfaces, polygons and folders
Names must be unique among siblings sharing the same parent folder. Items in different folders may keep identical names, and comparison is case sensitive.
Siblings are the objects held by the same caf::PdmChildArrayField. Items and folders live in two distinct child arrays in caf::PdmNestedCollection, so a folder and an item may share a name under the same parent.
The Python API gets an OnNameConflict flag on AddFolder, CreatePolygon, ImportSurface and NewRegularSurface, supporting FAIL (default), AUTO_RENAME and OVERWRITE. NewSurface is left out, as grid case surfaces derive their tree label from the case and K index and carry no name of their own.
Compute the depth related geometry properties (DEPTH, DX, DY, DZ, TOPS, BOTTOM) in RimCornerPointCase::createFromCoordinatesArray and replaceGridFromCoordinatesArray, matching the behavior when importing a grid from file. The computation is guarded by the same autoComputeDepthRelatedProperties preference used by the file importers.
Address review feedback on #14199: deleting and recreating the legend left
views bound to the old legend pointing at a deleted object. Add
RimColorLegendCollection::updateColorLegend and a matching UpdateColorLegend
scriptable method that mutate the existing custom legend (name and items) so
referring views keep their binding and are notified once. A new legend is only
created when none is registered for the result or the registered legend is a
standard legend.
set_discrete_property_category_names now performs a single atomic call instead
of delete + create + per-item appends. The empty-dict removal path still uses
DeleteColorLegend.
RimColorLegendCollection::deleteColorLegend erased the default-legend map
entry before looking the legend up, so findDefaultLegendForResult always
returned null and the old legend was never removed from m_customColorLegends.
Each set_discrete_property_category_names call for the same property left an
orphaned legend behind and appended a new one.
Look up the legend before erasing the map key, and guard against deleting a
standard legend that may have been registered as a default.
The return value of copyPdmObjectFromRipsToCaf was discarded when copying method parameters in CallPdmObjectMethod. Check the std::expected result and return a gRPC INVALID_ARGUMENT status (with telemetry and logging) when parameter validation fails, instead of silently proceeding to execute the method.
Make RiaGrpcCommandService::assignPdmObjectValues return std::expected<void, QString> so the result of copyPdmObjectFromRipsToCaf is no longer discarded. Validation failures are now propagated up and returned to the client as a gRPC INVALID_ARGUMENT status instead of being silently ignored. This also resolves the C4834 [[nodiscard]] build warning.
Carries the "Fault Distance" rename through to the C++ class names, file
names, PDM/scriptable keywords and the Python API (add_fault_distance,
class FaultDistance). The RicNewFaultDistanceResultFeature command class
keeps its name.