Introduce RimDataFilterCollection on RimEclipseCase to hold filter
configuration that is shared across all views of the case. Each
RimEclipseView gets a RimDataFilterInViewCollection of
RimDataFilterInView wrappers that auto-sync with the case-level list
and expose an independent on/off toggle per view. The wrapper's
applyToCellVisibility delegates to the wrapped RimCellFilter via the
existing unified virtual, so property, range, and combined filters all
work uniformly.
RimDataFilterCollection is built on caf::PdmObjectCollection<RimCellFilter>
and emits a filtersChanged signal on add/remove/reorder/child changes.
The wrapper collection mirrors RimSurfaceInViewCollection's sync pattern:
new wrappers default to checked, removed sources drop their wrappers,
and the wrapper list follows the case order. Per-view wrappers feed into
RivReservoirViewPartMgr::computePropertyVisibility after the existing
view-level property-filter loop.
The RicNew*Feature commands now route into a selected RimDataFilterCollection,
and the existing combined-filter path is generalized to allow combined
filters living under either a per-view RimEclipsePropertyFilterCollection
or the new case-level collection. Several Asserted ancestor lookups in
RimEclipsePropertyFilter, RimCellFilter and RimEclipseResultDefinition
that assumed a Rim3dView ancestor were relaxed to the non-asserting
variant with graceful fallbacks, so case-level filters can be created
and edited without a host view.
Backwards compatible: empty Data Filter collection is a no-op,
existing per-view RimEclipsePropertyFilterCollection and
RimCellFilterCollection paths are unchanged. GeoMech parity deferred.
Replace the dynamic_cast dispatch in RimPolygonCollection::loadData() with a
virtual loadData() on RimPolygonContainer. The base recurses through
subCollections; RimPolygonFile overrides to load file data. The folder
RimPolygonCollection no longer needs its own loadData().
Move RimPolygonFile::canAddSubCollection() and RimPolygonInView::sourceItem()
implementations from headers to .cpp.
Simplify std::unexpected calls in RimcNestedCollectionBase by removing
redundant explicit QString construction.
Port RimSurfaceCollection, RimPolygonCollection and the polygon-in-view
side onto the new caf::PdmNestedCollection framework, replacing the
per-class folder plumbing (m_subCollections field, topmost-folder flag,
add/remove/find sub-collection, factory, "new folder" command) with the
shared base.
- RimSurfaceCollection and RimPolygonCollection now derive from
caf::PdmNestedCollection. Each constructor uses the generic folder
icon and exposes a static createTopmost() that marks the top instance
and applies the branded domain icon; RimOilField calls the factory.
- RimPolygonInViewCollection uses the new RimNestedMirrorCollectionInView
helper, and a new RimPolygonContainer carries the source-side polygon
link.
- RicNewSurfaceCollectionFeature is removed; the generic
RicNewNestedCollectionFeature drives the "Add Folder" action against
both collections.
- Update callers (RimAnnotationCollection, RimEnsembleSurface, polygon
command features) and the scripting wrapper (RimcSurfaceCollection),
plus the Python add-folder binding and polygon test.
Generalise the per-domain "Add Folder" command and the scripting-side
add-folder method so they work against any container that exposes
caf::PdmNestedCollectionBase.
- RicNewNestedCollectionFeature: command feature that walks the
selected PdmObject up to the nearest PdmNestedCollectionBase ancestor
and calls addNewSubCollection(). Hidden via canAddSubCollection() for
leaf containers.
- RimcNestedCollectionBase: scripting wrapper exposing the same
add-sub-collection action through the Python interface, so generated
Python bindings get the operation for free on every derived class.
Neither is wired to a concrete collection yet; the per-domain features
remain in place until the migration commit replaces them.
IconProvider::operator= copied a new resource-string but never cleared
the existing m_pixmap. icon() prefers the pixmap when present, so a
pixmap-based default stamped earlier (e.g. by a base class) would
silently shadow a later resource-string-only assignment in a derived
class.
Reset m_pixmap in operator= so resource-string-only assignments fully
replace pixmap-based ones, and cover the replacement semantics with a
caf::IconProvider regression test: default-overwriting-pixmap,
resource-string-overwriting-pixmap and pixmap-overwriting-pixmap.
Needed for the upcoming nested-collection migration where a base class
stamps a folder pixmap and the topmost instance applies a branded
resource-string icon on top.
Introduce a shared base for tree-shaped folder containers that hold a
list of leaf items together with a list of subcontainers of the same
kind. Replaces the per-class plumbing (subcollections field, top-folder
flag, add/remove/find sub-collection, factory) that is duplicated across
RimSurfaceCollection, RimPolygonCollection and similar candidates.
- caf::PdmNestedCollectionBase: non-templated PdmObject base exposing
collection-name, add-new-subcollection, leaf-check and topmost-folder
marking for generic command features and script methods.
- caf::PdmNestedCollection<SelfT, ItemT>: CRTP template that owns the
typed m_subCollections field and inherits the m_items array from
PdmObjectCollection<ItemT>. Provides allItems(), find-sub-collection,
and a typed factory hook.
- RimNestedMirrorCollectionInView: view-side analogue for in-view
collections that mirror a nested source collection, with orphan-sweep
+ find-or-create + reorder sync.
Design rationale (templated vs non-templated, break-even on derived
class count) lives in docs/pdm-nested-collection-design.md.
No callers migrated in this commit.
The StrEnum-based API (rips/enums.py, generated AppEnum classes) requires
Python 3.11+. Align the docs and copilot-instructions with setup.py.cmake,
which already declares >=3.11.
The property/porosity/data-type arguments accept either a typed StrEnum
(rips.PropertyType.DYNAMIC_NATIVE) or a plain string ("DYNAMIC_NATIVE").
Keep both forms visible to users:
- soil_average_sync.py and input_prop_test_sync.py now use string
arguments and point at their _async counterparts for the typed-enum
form. The sync/async examples otherwise mirror each other, so each
pair documents one form.
- Add test_10k_property_strings to exercise available_properties,
active_cell_property, grid_property, and set_active_cell_property
(including data_type="INTEGER") with strings only, so a future
refactor that narrows the accepted types would fail the suite.
Instance.launch and Instance.find now always either return a connected
Instance or raise RipsError, so their return type narrows from
Optional[Instance] to Instance. In launch(), the unreachable `if pid:`
guard around the Popen result and the trailing `return None` are
removed; the only failure paths raise RipsError.
Update the PythonExamples that previously branched on a None return:
- Drop `if resinsight is None: exit(1)` style guards and `if resinsight
is not None:` wrappers; dedent the body where applicable.
- export_corner_point_grid.py used the None check as a fallback to
launch ResInsight; rewrite as try/except rips.RipsError so the
fallback still works.
- instance_example.py is repurposed as a try/except example for
reporting connection failure.
Extend type annotations across the rest of rips.case beyond the property
and enum methods typed in the previous commit. Adds parameter and return
types to the command wrappers (replace, export_*, create_*, import_*),
the simple getters (time_steps, reservoir_boundingbox,
distance_to_closest_fault, days_since_start, view, views, create_view,
simulation_wells, coarsening_info), the selected-cells and NNC accessors
(selected_cells*, nnc_connections*, nnc_connections_{static,dynamic,
generated}_values*), and the private grpc helpers
(__custom_init__, __request, __generate_property_input_iterator,
__generate_property_input_chunks, __nnc_connections_values_async,
__nnc_values_generator_to_list, __generate_nnc_property_input_chunks).
Uses Iterator[X] for grpc streaming responses, List[X] for collected
sequences, the proto message types from Case_pb2 / Properties_pb2 /
NNCProperties_pb2 / Definitions_pb2 for typed payloads, Optional and
Union[str, List[str]] for nullable or coerced-list parameters, and Any
for the heterogeneous _execute_command return values. No runtime
behavior changes; mypy --strict is clean on case.py.
The previous commit auto-generated StrEnum classes for caf::AppEnum scriptable
fields, but the hand-written gRPC API in rips.case still accepted bare strings
for proto-backed enums (PropertyType, PropertyDataType, NNCPropertyType) and
the AppEnum-backed PorosityModelType.
Add a new rips.enums module with hand-written StrEnum classes for the three
proto-only enums and reuse the auto-generated PorosityModelType from
resinsight_classes. Re-export the new enums from the rips package and narrow
the parameter type hints across cell_count, cell_info_for_active_cells,
available_properties, active_cell_property, selected_cell_property,
grid_property, set_active_cell_property, set_grid_property,
active_cell_centers, active_cell_corners, set_nnc_connections_values, and
grid_property_for_positions (sync and async variants).
Existing string arguments keep working because StrEnum members are strings
and protobuf's EnumTypeWrapper.Value accepts both. A new
test_10k_grid_property_strenum asserts string and enum forms return the same
data.
Auto-generate enum.StrEnum classes from cafPdmPythonGenerator for every
caf::AppEnum-backed scriptable field, deduplicated by C++ AppEnum type.
Generated PdmObject attributes and method arguments now reference the
typed enum (e.g. self.depth_type: DepthType = DepthType.MEASURED_DEPTH)
instead of bare str. Member names are sanitized against Python keywords
and identifier rules (None -> None_, R-G -> R_G).
Existing scripts that pass plain strings keep working because StrEnum
members are strings; the wire format is unchanged.
Bumps python_requires to >=3.11 (StrEnum). Adds an Enum branch in
PdmObjectBase.__convert_to_grpc_value so future IntEnum use is also
handled.
Move the element-type include from each migrated collection header into
its .cpp, leaving only a forward declaration in the header. Follows the
pattern from 9e4d79159 for RimJobCollection, made possible by the
constructor-time PdmObject base check.
Replace the class-level static_assert with a DerivedFromPdmObject concept
checked inside the constructor body. The constructor is lazily instantiated,
so T can be forward-declared at the point PdmObjectCollection<T> is used
as a base class.
Migrated to the templated base, preserving each collection's existing XML
field keyword for project-file backward compatibility:
- RimEnsembleFractureStatisticsCollection
- RimEclipseInputPropertyCollection
- RimPlotDataFilterCollection
- RimGeoMechContourMapViewCollection
- RimIntersectionResultsDefinitionCollection
- RimCustomObjectiveFunctionCollection
- RimStimPlanModelTemplateCollection
- RimEnsembleWellLogsCollection
- RimEclipseContourMapViewCollection
- RimSeismicViewCollection
- RimGridInfoCollection
- RimEclipseStatisticsCaseCollection
- RimWellIASettingsCollection
- RimVfpDataCollection
External callers that accessed the old public/named array fields directly
(RimEclipseInputPropertyCollection::inputProperties,
RimEclipseStatisticsCaseCollection::cases) now use addItem/items() from
the base. RimCustomObjectiveFunction.h replaced its include of the
collection header with a forward declaration to break the new include
cycle introduced by the migration.
RimEnsembleFileSetCollection, RimJobCollection, RimQuickAccessCollection,
RimRefinementRegionCollection and RimFractureTemplateCollection now inherit
from the templated caf::PdmObjectCollection<T> base, reusing the shared
add/insert/delete/items plumbing introduced for RimValveTemplateCollection.
XML field keywords are preserved on every collection so existing project
files continue to load.
Bind a PdmProxyValueField that inverts the Z sign to the Points group in
RimPolygon's property panel, mirroring the pattern already used by
RimExtrudedCurveIntersection. The raw m_pointsInDomainCoords field keeps
its XYZ semantics, scriptable keyword, and serialization unchanged.
Fixes#12106.
The bare "// Overrides" comment is now redundant since the override keyword on
each method already conveys the same information. Qualified comments like
"// Overrides from BaseClass" carry additional information and are kept.
Replace inline bar-to-Pascal magic constants with RiaEclipseUnitTools::barToPascal
for initial stress and pore pressure parameters passed to the Well Impact Analysis
exporter. Behavior is unchanged; both sites previously multiplied by 100000.0.
Fixes#5840.
isFaceNormalsOutwards lazily computes whether cell face normals point outward
and caches the answer in m_isFaceNormalsOutwardsComputed. setFlipAxis was
mirroring the node coordinates without resetting that cache, so any consumer
that had triggered the lazy computation before the user toggled Flip X/Y kept
the pre-flip answer. The well-path/cell intersection in
RigEclipseWellLogExtractor::calculateIntersection then inverted the
entering/leaving flag the wrong way, causing the proper-pair filter in
populateReturnArrays to discard every intermediate cell along a perforation
interval - only the start and end cells survived through the
well-starts/ends-inside-a-cell fallback.
Reset m_isFaceNormalsOutwardsComputed when the flip state actually changes.
Add unit tests covering all four combinations of Flip X / Flip Y for both the
data-level node mirroring and the well-path/cell intersection (freshly-built
grid and interactive-toggle scenarios).
When a project file persisted FlipXAxis or FlipYAxis as true, the flag was
restored to the PdmField but never propagated to the grid nodes during
RimEclipseResultCase::importGridAndResultMetaData. Only the UI change handler
applied the flip, so on reload the grid stayed un-flipped while the checkbox
appeared active.
Mirror the call already present in RimEclipseInputCase and RimRoffCase by
invoking setFlipAxis before computeCachedData.
Remove the hard floor against m_defaultPerspectiveNearPlaneDistance
(0.05) when computing the perspective near plane from the closest
bounding-box corner. For very small models the closest corner can sit
within that distance, and clamping pushed the near plane past the
model so it was clipped entirely; parallel projection was unaffected
because its near plane scales directly with the bbox.
The zero/negative guard at the end of the block is the actual safety
net, and the maxFarNearRatio constraint still protects depth-buffer
precision when geometry spans both very close and very distant
corners.
Expose XYZ extent and XY UTM offset as user-editable fields in the
Customize Mock Model dialog instead of hard-coding them in
RimEclipseResultCase. Defaults match the previous hard-coded values
(6000/12000/500 extent, 400000/6000000 offset).
Switch the message parameter from const QString& to std::string_view so
callers with std::string in hand no longer need a QString::fromStdString
wrapper. The internal duration formatting still uses QString::arg, fed
from a single QString::fromUtf8 conversion.
Callers passing QString locals are updated with .toStdString() at the
call site.
Move the QMessageBox-displaying helper out of the logging utility into a
dedicated UI class. RiaLogging.h no longer pulls QMessageBox/QWidget into
the ~270 files that include it. Behavior is preserved: showError displays
the dialog when running interactively (and not under regression tests),
then forwards the text to RiaLogging::error.
Restore m_filePathInCache_OBSOLETE as a read-only field (write disabled)
so existing projects that stored the well path in WellPathFilePathInCache
can still be loaded. In initAfterRead, look up the cache file in the
current project's cache directory and copy the path into m_filePath.
Wrap the discarded calls to the [[nodiscard]] std::expected-returning
transformKeywordsInDeckFile in EXPECT_TRUE(...has_value()) to silence
C4834 and assert that the transformation succeeded.
Robustness fixes in RivPipeGeometryGenerator:
- updateFilteredPipeCenterCoords: drop NaN/Inf input coords. The main loop
now skips iterations where any of the three sampled coords is undefined,
and the trailing endpoint walks back to the last finite coord so the
segment-to-result bookkeeping invariant holds.
- computeExtrudedCoordsAndNormals: stop asserting on parallel plane/ray
intersections (these can occur at very sharp bends due to numerical
issues) and return early when the extruded node count does not match the
expected cross-section node count.
Move the loops, lookups, and QString machinery out of
AppEnum<T>::EnumMapper into a new non-template AppEnumMapperBase defined
in cafAppEnum.cpp. Each member is now compiled once for the whole
program rather than once per enum type, cutting build time and binary
size for a class template instantiated across hundreds of enums.
AppEnum<T> becomes a thin static_cast shim around the base methods.
Enum values are stored as int in the mapping; a static_assert rejects
enum types whose underlying type is wider than int. The widest
underlying type currently in use in ResInsight is short, so all current
instantiations are unaffected.
Use std::optional<int> for the mapper default value, and assert against
an empty mapping in defaultValue() (the prior code returned m_mapping[0]
unconditionally, which is undefined behavior on empty).
Document why mapper() uses an explicit init flag rather than
std::call_once or a magic-static lambda: setUp() re-enters mapper() via
addItem, so anything that locks on first init would deadlock.
First-access must therefore be single-threaded, as already exercised by
BaseTest.CreateObjectInMultipleThreads.
Add AppEnumTest.MappingRoundTrip covering text <-> enum, index <-> enum,
isValid, and the failure paths of setFromText / setFromIndex (resets to
default, returns false).
Stop changing RimWellPathCollection::wellPathVisibility from the Hide Grid
Geometry and Show All Geometry features. Hide still activates the well path
collection so well paths are drawn when grid cells are hidden.
Remove the SSIHUB cache mechanism (m_filePathInCache, isStoredInCache,
setupBeforeSave, updateFilePathsFromProjectPath) from RimFileWellPath. The
cache path was triggered whenever the well path's id field was non-empty,
which JSON imports populate, causing m_filePath to be cleared on save.
The heartbeat introduced in db871296c closed the gRPC channel after a
single missed ping (2s deadline). On Windows CI under load this fired
during normal operations, leaving every subsequent test stuck on a
dead channel.
Track consecutive failures inside the heartbeat loop and only declare
the connection lost after failure_threshold (default 3) consecutive
failures. A successful ping resets the counter. Per-ping deadline
raised from 2s to 5s, and below-threshold failures log a warning so
transient slowness is still visible.
After the heartbeat closes a dead-server channel, gRPC raises
ValueError("Cannot invoke RPC on closed channel!") rather than a
grpc.RpcError, which slipped past the existing pdmobject wrappers and
surfaced to the user as a bare ValueError nested in a traceback.
- pdmobject add_method decorator and _call_pdm_method_void /
_return_value / _return_optional_value now also catch the
closed-channel ValueError and translate it to RipsError.
- well_path.add_well_log no longer rewraps every exception as
RuntimeError. Cleanup of temporary key-value entries still runs, but
the original typed exception (e.g. RipsError with code/details) is
re-raised so callers can inspect it.
Surface gRPC failure context to Python script authors instead of
silently returning sentinel values or raising bare gRPC errors.
- RipsError now carries code/details/location and a from_rpc_error()
helper. Existing single-arg construction stays valid.
- Stop swallowing grpc.RpcError in case.__grid_count for non-NOT_FOUND
failures and in instance._check_connection_and_version, so the
underlying status is propagated.
- pdmobject add_method decorator and _call_pdm_method_* attach
code/details to the raised RipsError; existing message text is
preserved so pytest match=... assertions keep working.
- Instance.start_heartbeat / stop_heartbeat / check_alive provide an
opt-in background ping that flips a sticky lost-connection flag and
raises a readable RipsError from check_alive() if the server dies.
- Server side: GetPdmObject in RiaGrpcAppService, RiaGrpcCaseService
and RiaGrpcProjectService no longer return Status::OK with an empty
reply when the underlying object is missing; they return NOT_FOUND
/ INTERNAL with a descriptive message. Other RiaGrpc*Service files
audited and already return non-OK with text on error paths.
Replace the fatal CAF_ASSERT in calculateCondensedTransmissibilities() with an
early return when no external cells are present. The fracture export pipeline
now yields no completions for such fractures instead of aborting the process.
Fixes#13940.
Set CMAKE_FIND_PACKAGE_TARGETS_GLOBAL so Qt:: targets pulled in by subdirectory find_package() calls (qwt, cafPdmXml, cafUserInterface, etc.) are visible at consumer scope. Silences Qt 6.10 __qt_internal_walk_libs warnings about OpenGLWidgets, Xml and Svg targets being mentioned but not declared.