mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
#14772 Python: Add GeoMechCase.create_well_bore_stability_plot as object method and forward createWellBoreStabilityPlot to it
RimGeoMechCase_createWellBoreStabilityPlot takes a WellPath object and a time step and returns the plot. WBS parameters cannot be passed as a method argument (child objects are not supported as gRPC method parameters), so the C++ setter is available for the Ricf forwarder and the Python wrapper copies a WbsParameters object into the created plot's Parameters child instead. The Python wrapper moves from Case to GeoMechCase, accepts both a WellPath object and (deprecated) a well path name, and keeps the optional parameters argument.
This commit is contained in:
1 parent
6a2e7a2a21
commit
54c5ef7dad
6 files changed
+223
-58
No files matched your search
+22
-42
@@ -17,21 +17,17 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#include "RicfCreateWellBoreStabilityPlotFeature.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include "WellLogCommands/RicNewWellBoreStabilityPlotFeature.h"
|
||||
#include "RicfCommandForwarding.h"
|
||||
|
||||
#include "RimGeoMechCase.h"
|
||||
#include "RimGeoMechView.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimWbsParameters.h"
|
||||
#include "RimWellBoreStabilityPlot.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimcGeoMechCase.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RicfCreateWbsPlotResult, "createWbsPlotResult" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -62,48 +58,32 @@ RicfCreateWellBoreStabilityPlotFeature::RicfCreateWellBoreStabilityPlotFeature()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmScriptResponse RicfCreateWellBoreStabilityPlotFeature::execute()
|
||||
{
|
||||
RimProject* project = RimProject::current();
|
||||
const QString commandName = classKeyword();
|
||||
|
||||
std::vector<RimGeoMechCase*> geoMechCases = project->descendantsIncludingThisOfType<RimGeoMechCase>();
|
||||
auto rimCase = RicfForwarding::findCase( m_caseId() );
|
||||
if ( !rimCase ) return RicfForwarding::errorResponse( rimCase.error(), commandName );
|
||||
|
||||
RimGeoMechCase* chosenCase = nullptr;
|
||||
for ( RimGeoMechCase* geoMechCase : geoMechCases )
|
||||
auto* geoMechCase = dynamic_cast<RimGeoMechCase*>( rimCase.value() );
|
||||
if ( !geoMechCase )
|
||||
{
|
||||
if ( geoMechCase->caseId() == m_caseId() )
|
||||
{
|
||||
chosenCase = geoMechCase;
|
||||
break;
|
||||
}
|
||||
return RicfForwarding::errorResponse( QString( "Could not find GeoMech case with id %1" ).arg( m_caseId() ), commandName );
|
||||
}
|
||||
|
||||
RimWellPath* chosenWellPath = nullptr;
|
||||
for ( RimWellPath* wellPath : project->allWellPaths() )
|
||||
{
|
||||
if ( wellPath->name() == m_wellPath() )
|
||||
{
|
||||
chosenWellPath = wellPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RimWellPath* wellPath = RimProject::current()->wellPathByName( m_wellPath() );
|
||||
if ( !wellPath ) return RicfForwarding::errorResponse( QString( "Could not find well path '%1'" ).arg( m_wellPath() ), commandName );
|
||||
|
||||
if ( chosenCase && chosenWellPath && m_timeStep() >= 0 )
|
||||
{
|
||||
if ( !chosenWellPath->wellPathGeometry() )
|
||||
{
|
||||
QString error =
|
||||
QString( "The well path %1 has no geometry. Cannot create a Well Bore Stability Plot" ).arg( chosenWellPath->name() );
|
||||
RiaLogging::error( error.toStdString() );
|
||||
return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error );
|
||||
}
|
||||
RimGeoMechCase_createWellBoreStabilityPlot method( geoMechCase );
|
||||
method.setWellPath( wellPath );
|
||||
method.setTimeStep( m_timeStep() );
|
||||
method.setParameters( m_wbsParameters() );
|
||||
|
||||
RimWellBoreStabilityPlot* wbsPlot =
|
||||
RicNewWellBoreStabilityPlotFeature::createPlot( chosenCase, chosenWellPath, m_timeStep(), m_wbsParameters() );
|
||||
caf::PdmScriptResponse response;
|
||||
response.setResult( new RicfCreateWbsPlotResult( wbsPlot->id() ) );
|
||||
return response;
|
||||
}
|
||||
auto result = method.execute();
|
||||
if ( !result ) return RicfForwarding::errorResponse( result.error(), commandName );
|
||||
|
||||
QString error = QString( "createWellBoreStabilityPlot: Could not find GeoMech case with id %1" ).arg( m_caseId() );
|
||||
RiaLogging::error( error.toStdString() );
|
||||
return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error );
|
||||
auto* plot = dynamic_cast<RimWellBoreStabilityPlot*>( result.value() );
|
||||
if ( !plot ) return RicfForwarding::errorResponse( "Created object is not a Well Bore Stability plot", commandName );
|
||||
|
||||
caf::PdmScriptResponse response;
|
||||
response.setResult( new RicfCreateWbsPlotResult( plot->id() ) );
|
||||
return response;
|
||||
}
|
||||
@@ -47,6 +47,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcNestedCollectionBase.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcCase.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcViewWindow.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcGeoMechCase.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})
|
||||
@@ -0,0 +1,99 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2026- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimcGeoMechCase.h"
|
||||
|
||||
#include "WellLogCommands/RicNewWellBoreStabilityPlotFeature.h"
|
||||
|
||||
#include "RimGeoMechCase.h"
|
||||
#include "RimWbsParameters.h"
|
||||
#include "RimWellBoreStabilityPlot.h"
|
||||
#include "RimWellPath.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
|
||||
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimGeoMechCase, RimGeoMechCase_createWellBoreStabilityPlot, "createWellBoreStabilityPlot" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimGeoMechCase_createWellBoreStabilityPlot::RimGeoMechCase_createWellBoreStabilityPlot( caf::PdmObjectHandle* self )
|
||||
: caf::PdmObjectCreationMethod( self )
|
||||
{
|
||||
CAF_PDM_InitObject( "Create Well Bore Stability Plot", "", "", "Create a Well Bore Stability plot for a well path in this case" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_wellPath, "WellPath", "Well Path", "", "", "Well path to create the plot for" );
|
||||
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", 0, "Time Step", "", "", "Zero-based time step index" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGeoMechCase_createWellBoreStabilityPlot::setWellPath( RimWellPath* wellPath )
|
||||
{
|
||||
m_wellPath = wellPath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGeoMechCase_createWellBoreStabilityPlot::setTimeStep( int timeStep )
|
||||
{
|
||||
m_timeStep = timeStep;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGeoMechCase_createWellBoreStabilityPlot::setParameters( const RimWbsParameters* parameters )
|
||||
{
|
||||
m_parameters = parameters;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<caf::PdmObjectHandle*, QString> RimGeoMechCase_createWellBoreStabilityPlot::execute()
|
||||
{
|
||||
auto* geoMechCase = self<RimGeoMechCase>();
|
||||
if ( !geoMechCase ) return std::unexpected( "No GeoMech case is available." );
|
||||
|
||||
RimWellPath* wellPath = m_wellPath();
|
||||
if ( !wellPath ) return std::unexpected( "No well path specified." );
|
||||
|
||||
if ( !wellPath->wellPathGeometry() )
|
||||
{
|
||||
return std::unexpected(
|
||||
QString( "The well path %1 has no geometry. Cannot create a Well Bore Stability Plot" ).arg( wellPath->name() ) );
|
||||
}
|
||||
|
||||
if ( m_timeStep() < 0 ) return std::unexpected( "Time step must be non-negative." );
|
||||
|
||||
RimWellBoreStabilityPlot* plot = RicNewWellBoreStabilityPlotFeature::createPlot( geoMechCase, wellPath, m_timeStep(), m_parameters );
|
||||
if ( !plot ) return std::unexpected( "Could not create Well Bore Stability plot." );
|
||||
|
||||
return plot;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimGeoMechCase_createWellBoreStabilityPlot::classKeywordReturnedType() const
|
||||
{
|
||||
return RimWellBoreStabilityPlot::classKeywordStatic();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2026- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObjectHandle.h"
|
||||
#include "cafPdmObjectMethod.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
class RimWellPath;
|
||||
class RimWbsParameters;
|
||||
|
||||
//==================================================================================================
|
||||
/// Create a Well Bore Stability plot for a well path in this GeoMech case.
|
||||
///
|
||||
/// The plot is created with default parameters. Adjust them through the returned plot's Parameters
|
||||
/// child object, or pass a RimWbsParameters object from C++ via setParameters().
|
||||
//==================================================================================================
|
||||
class RimGeoMechCase_createWellBoreStabilityPlot : public caf::PdmObjectCreationMethod
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimGeoMechCase_createWellBoreStabilityPlot( caf::PdmObjectHandle* self );
|
||||
|
||||
void setWellPath( RimWellPath* wellPath );
|
||||
void setTimeStep( int timeStep );
|
||||
void setParameters( const RimWbsParameters* parameters );
|
||||
|
||||
std::expected<caf::PdmObjectHandle*, QString> execute() override;
|
||||
QString classKeywordReturnedType() const override;
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimWellPath*> m_wellPath;
|
||||
caf::PdmField<int> m_timeStep;
|
||||
|
||||
const RimWbsParameters* m_parameters = nullptr;
|
||||
};
|
||||
@@ -59,6 +59,7 @@ from .resinsight_classes import (
|
||||
PropertyType as PropertyType,
|
||||
Reservoir as Reservoir,
|
||||
WellBoreStabilityPlot as WellBoreStabilityPlot,
|
||||
WellPath as WellPath,
|
||||
WbsParameters as WbsParameters,
|
||||
)
|
||||
|
||||
@@ -892,37 +893,55 @@ def set_grid_property(
|
||||
raise IndexError
|
||||
|
||||
|
||||
@add_method(Case)
|
||||
@add_method(GeoMechCase)
|
||||
def create_well_bore_stability_plot(
|
||||
self,
|
||||
well_path: str,
|
||||
well_path: Union[str, WellPath],
|
||||
time_step: int,
|
||||
parameters: Optional[WbsParameters] = None,
|
||||
) -> Optional[WellBoreStabilityPlot]:
|
||||
) -> WellBoreStabilityPlot:
|
||||
"""Create a new well bore stability plot
|
||||
|
||||
Arguments:
|
||||
well_path(str): well path name
|
||||
well_path(WellPath or str): well path object or well path name
|
||||
time_step(int): time step
|
||||
parameters(WbsParameters): optional parameters copied into the created plot
|
||||
|
||||
Returns:
|
||||
:class:`rips.generated.generated_classes.WellBoreStabilityPlot`
|
||||
"""
|
||||
pb2_parameters = None
|
||||
if isinstance(well_path, str):
|
||||
warnings.warn(
|
||||
"GeoMechCase.create_well_bore_stability_plot(well_path=<name>) is deprecated, pass a WellPath object instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=3,
|
||||
)
|
||||
project = self.ancestor(rips.project.Project)
|
||||
well_path_object = project.well_path_by_name(well_path)
|
||||
if well_path_object is None:
|
||||
raise RipsError(f"Could not find well path '{well_path}'")
|
||||
well_path = well_path_object
|
||||
|
||||
plot = self._call_pdm_method_return_value(
|
||||
"createWellBoreStabilityPlot",
|
||||
WellBoreStabilityPlot,
|
||||
well_path=well_path,
|
||||
time_step=time_step,
|
||||
)
|
||||
|
||||
if parameters is not None:
|
||||
assert isinstance(parameters, WbsParameters)
|
||||
pb2_parameters = parameters.pb2_object()
|
||||
plot_parameters = plot.parameters()
|
||||
if plot_parameters is not None:
|
||||
# Copy the public field values only; private members hold the gRPC connection
|
||||
for attribute in dir(parameters):
|
||||
if attribute.startswith("_"):
|
||||
continue
|
||||
value = getattr(parameters, attribute)
|
||||
if not callable(value):
|
||||
setattr(plot_parameters, attribute, value)
|
||||
plot_parameters.update()
|
||||
|
||||
plot_result = self._execute_command(
|
||||
createWellBoreStabilityPlot=Cmd.CreateWbsPlotRequest(
|
||||
caseId=self.id,
|
||||
wellPath=well_path,
|
||||
timeStep=time_step,
|
||||
wbsParameters=pb2_parameters,
|
||||
)
|
||||
)
|
||||
project = self.ancestor(rips.project.Project)
|
||||
plot = project.plot(view_id=plot_result.createWbsPlotResult.viewId)
|
||||
return plot
|
||||
|
||||
|
||||
|
||||
@@ -459,3 +459,13 @@ def test_create_saturation_pressure_plots_requires_data(rips_instance, initializ
|
||||
case = rips_instance.project.load_case(case_path)
|
||||
with pytest.raises(rips.RipsError):
|
||||
case.create_saturation_pressure_plots()
|
||||
|
||||
|
||||
def test_create_well_bore_stability_plot_is_geomech_only(
|
||||
rips_instance, initialize_test
|
||||
):
|
||||
# No GeoMech test data is available; verify the method is exposed on the right class
|
||||
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(case_path)
|
||||
assert not hasattr(case, "create_well_bore_stability_plot")
|
||||
assert hasattr(rips.GeoMechCase, "create_well_bore_stability_plot")
|
||||
Reference in new issue
Block a user