From be86986d9eb8c9709d8b3ad0e3f6af7abc0c2f8c Mon Sep 17 00:00:00 2001 From: hnil Date: Thu, 15 Oct 2026 09:44:43 +0200 Subject: [PATCH 1/2] Scripting: geomechanical cell result The cell result of a geomechanical view could not be read or set from Python. Make RimGeoMechResultDefinition (position, field and component) and the view's cell result scriptable, as for grid views: cr = geomech_view.cell_result() cr.result_position_type = "ELEMENT_NODAL" cr.result_field_name = "SE" cr.result_component_name = "S1" cr.update() On update the UI fields are synced and the result loaded, as for the grid result definition. rips View.case() now also works for geomechanical views, so View.export_snapshot() does. Co-Authored-By: Claude Opus 5.5 --- .../GeoMech/RimGeoMechCellColors.cpp | 4 ++++ .../GeoMech/RimGeoMechResultDefinition.cpp | 22 ++++++++++++++----- .../GeoMech/RimGeoMechResultDefinition.h | 1 + .../GeoMech/RimGeoMechView.cpp | 3 ++- GrpcInterface/Python/rips/view.py | 3 +++ GrpcInterface/RiaGrpcPdmObjectService.cpp | 6 +++++ 6 files changed, 32 insertions(+), 7 deletions(-) diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechCellColors.cpp b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechCellColors.cpp index 4219273eead..d03d6fde4ef 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechCellColors.cpp +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechCellColors.cpp @@ -24,6 +24,8 @@ #include "RimViewController.h" #include "RimViewLinker.h" +#include "cafPdmObjectScriptingCapability.h" + CAF_PDM_SOURCE_INIT( RimGeoMechCellColors, "GeoMechResultSlot" ); //-------------------------------------------------------------------------------------------------- @@ -32,6 +34,8 @@ CAF_PDM_SOURCE_INIT( RimGeoMechCellColors, "GeoMechResultSlot" ); RimGeoMechCellColors::RimGeoMechCellColors() : legendConfigChanged( this ) { + CAF_PDM_InitScriptableObjectWithNameAndComment( "Color Result", ":/CellResult.png", "", "", "GeoMechCellColors", "Geomechanical cell colors" ); + CAF_PDM_InitFieldNoDefault( &legendConfig, "LegendDefinition", "Color Legend" ); legendConfig = new RimRegularLegendConfig(); legendConfig->changed.connect( this, &RimGeoMechCellColors::onLegendConfigChanged ); diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechResultDefinition.cpp b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechResultDefinition.cpp index ae773d48ad5..8c1265f002e 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechResultDefinition.cpp +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechResultDefinition.cpp @@ -48,6 +48,8 @@ #include "RimViewLinker.h" #include "RimWellPath.h" +#include "cafPdmFieldScriptingCapability.h" +#include "cafPdmObjectScriptingCapability.h" #include "cafPdmUiDoubleValueEditor.h" #include "cafPdmUiTreeSelectionEditor.h" @@ -77,15 +79,15 @@ CAF_PDM_SOURCE_INIT( RimGeoMechResultDefinition, "GeoMechResultDefinition" ); //-------------------------------------------------------------------------------------------------- RimGeoMechResultDefinition::RimGeoMechResultDefinition() { - CAF_PDM_InitObject( "Color Result", ":/CellResult.png" ); + CAF_PDM_InitScriptableObjectWithNameAndComment( "Color Result", ":/CellResult.png", "", "", "GeoMechResult", "A geomechanical result definition" ); - CAF_PDM_InitFieldNoDefault( &m_resultPositionType, "ResultPositionType", "Result Position" ); + CAF_PDM_InitScriptableFieldNoDefault( &m_resultPositionType, "ResultPositionType", "Result Position" ); m_resultPositionType.uiCapability()->setUiHidden( true ); - CAF_PDM_InitField( &m_resultFieldName, "ResultFieldName", QString( "" ), "Field Name" ); + CAF_PDM_InitScriptableField( &m_resultFieldName, "ResultFieldName", QString( "" ), "Field Name" ); m_resultFieldName.uiCapability()->setUiHidden( true ); - CAF_PDM_InitField( &m_resultComponentName, "ResultComponentName", QString( "" ), "Component" ); + CAF_PDM_InitScriptableField( &m_resultComponentName, "ResultComponentName", QString( "" ), "Component" ); m_resultComponentName.uiCapability()->setUiHidden( true ); CAF_PDM_InitField( &m_timeLapseBaseTimestep, "TimeLapseBaseTimeStep", RigFemResultAddress::noTimeLapseValue(), "Base Time Step" ); @@ -541,11 +543,19 @@ void RimGeoMechResultDefinition::initAfterRead() { if ( m_resultComponentName() == "STM" || m_resultComponentName() == "SEM" ) m_resultComponentName = "SM"; + updateUiFieldsFromActiveResult(); + + m_timeLapseBaseTimestep.uiCapability()->setUiReadOnly( resultPositionType() == RIG_WELLPATH_DERIVED ); +} + +//-------------------------------------------------------------------------------------------------- +/// Sync the UI fields after the result fields are set directly, e.g. from scripting +//-------------------------------------------------------------------------------------------------- +void RimGeoMechResultDefinition::updateUiFieldsFromActiveResult() +{ m_resultPositionTypeUiField = m_resultPositionType; m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() ); m_compactionRefLayerUiField = m_compactionRefLayer; - - m_timeLapseBaseTimestep.uiCapability()->setUiReadOnly( resultPositionType() == RIG_WELLPATH_DERIVED ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechResultDefinition.h b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechResultDefinition.h index 3398acdb0e2..32049898e94 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechResultDefinition.h +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechResultDefinition.h @@ -55,6 +55,7 @@ class RimGeoMechResultDefinition : public RimFemResultObserver, public RimChecka RigGeoMechCaseData* ownerCaseData() const; bool hasResult(); void loadResult(); + void updateUiFieldsFromActiveResult(); void setAddWellPathDerivedResults( bool addWellPathDerivedResults ); RigFemResultAddress resultAddress() const; diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp index 2ae4152e947..cd28f6186c9 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechView.cpp @@ -76,6 +76,7 @@ #include "cafDisplayCoordTransform.h" #include "cafFrameAnimationControl.h" #include "cafOverlayScalarMapperLegend.h" +#include "cafPdmFieldScriptingCapability.h" #include "cafPdmUiTreeOrdering.h" #include "cafProgressInfo.h" @@ -96,7 +97,7 @@ RimGeoMechView::RimGeoMechView() { CAF_PDM_InitScriptableObject( "Geomechanical View", ":/3DViewGeoMech16x16.png", "", "The Geomechanical 3d View" ); - CAF_PDM_InitFieldNoDefault( &cellResult, "GridCellResult", "Color Result", ":/CellResult.png" ); + CAF_PDM_InitScriptableFieldWithScriptKeywordNoDefault( &cellResult, "GridCellResult", "CellResult", "Color Result", ":/CellResult.png" ); cellResult = new RimGeoMechCellColors(); CAF_PDM_InitFieldNoDefault( &m_tensorResults, "TensorResults", "Tensor Results" ); diff --git a/GrpcInterface/Python/rips/view.py b/GrpcInterface/Python/rips/view.py index 29c812671ab..de0e7568fbc 100644 --- a/GrpcInterface/Python/rips/view.py +++ b/GrpcInterface/Python/rips/view.py @@ -202,6 +202,9 @@ def extract_address(address) -> int: @add_method(View) def case(self): """Get the case the view belongs to""" + if not hasattr(self, "eclipse_case"): # geomechanical views are children of their case + return self.ancestor(rips.case.Case) + project = self.ancestor(rips.project.Project) eclipse_case_addr = extract_address(self.eclipse_case) diff --git a/GrpcInterface/RiaGrpcPdmObjectService.cpp b/GrpcInterface/RiaGrpcPdmObjectService.cpp index d32257a100a..55fae4a7092 100644 --- a/GrpcInterface/RiaGrpcPdmObjectService.cpp +++ b/GrpcInterface/RiaGrpcPdmObjectService.cpp @@ -25,6 +25,7 @@ #include "RiaOpenTelemetryManager.h" #include "RimEclipseResultDefinition.h" +#include "RimGeoMechResultDefinition.h" #include "RimProject.h" #include "cafPdmAbstractFieldScriptingCapability.h" @@ -458,6 +459,11 @@ grpc::Status RiaGrpcPdmObjectService::UpdateExistingPdmObject( grpc::ServerConte resultDefinition->updateUiFieldsFromActiveResult(); resultDefinition->loadResult(); } + if ( auto geoMechResultDefinition = dynamic_cast( matchingObject ) ) + { + geoMechResultDefinition->updateUiFieldsFromActiveResult(); + geoMechResultDefinition->loadResult(); + } matchingObject->updateAllRequiredEditors(); RimProject::current()->scheduleCreateDisplayModelAndRedrawAllViews(); From fd5d20b2af0b574739128538248b5cc5eaa1f010 Mon Sep 17 00:00:00 2001 From: hnil Date: Fri, 16 Oct 2026 13:34:37 +0200 Subject: [PATCH 2/2] Python: put the view.case() comment on its own line for ruff format Co-Authored-By: Claude Opus 5.5 --- GrpcInterface/Python/rips/view.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GrpcInterface/Python/rips/view.py b/GrpcInterface/Python/rips/view.py index de0e7568fbc..76b57090977 100644 --- a/GrpcInterface/Python/rips/view.py +++ b/GrpcInterface/Python/rips/view.py @@ -202,7 +202,8 @@ def extract_address(address) -> int: @add_method(View) def case(self): """Get the case the view belongs to""" - if not hasattr(self, "eclipse_case"): # geomechanical views are children of their case + # Geomechanical views are children of their case + if not hasattr(self, "eclipse_case"): return self.ancestor(rips.case.Case) project = self.ancestor(rips.project.Project)