mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 22:50:25 -05:00
#13398 Python: Add API for custom well path segments
Add Python GRPC interface support for creating and managing custom segment intervals for multi-segment wells. This provides API parity with the existing GUI functionality. Changes: - Add createInterval() method to RimCustomSegmentIntervalCollection - Add GRPC method addCustomSegmentInterval to RimcWellPathCompletionSettings - Add validation to prevent creating intervals with start_md >= end_md - Add Python test test_custom_segment_intervals.py with validation test - Add usage example to modeled_well_path.py Follows the pattern established by diameter roughness intervals. Fixes #13398.
This commit is contained in:
1 parent
e34d36ee99
commit
a71fb9ad19
6 files changed
+194
No files matched your search
+13
@@ -38,6 +38,19 @@ RimCustomSegmentIntervalCollection::~RimCustomSegmentIntervalCollection()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimCustomSegmentInterval* RimCustomSegmentIntervalCollection::createInterval( double startMD, double endMD )
|
||||
{
|
||||
auto* interval = new RimCustomSegmentInterval();
|
||||
interval->setStartMD( startMD );
|
||||
interval->setEndMD( endMD );
|
||||
|
||||
addInterval( interval );
|
||||
return interval;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -33,6 +33,9 @@ public:
|
||||
RimCustomSegmentIntervalCollection();
|
||||
~RimCustomSegmentIntervalCollection() override;
|
||||
|
||||
// Domain-specific interval creation
|
||||
RimCustomSegmentInterval* createInterval( double startMD, double endMD );
|
||||
|
||||
// Validation
|
||||
std::map<QString, QString> validate( const QString& configName = "" ) const override;
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include "RimcWellPathCompletionSettings.h"
|
||||
|
||||
#include "RimCustomSegmentInterval.h"
|
||||
#include "RimCustomSegmentIntervalCollection.h"
|
||||
#include "RimDiameterRoughnessInterval.h"
|
||||
#include "RimDiameterRoughnessIntervalCollection.h"
|
||||
#include "RimMswCompletionParameters.h"
|
||||
@@ -29,6 +31,10 @@ CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimWellPathCompletionSettings,
|
||||
RimcWellPathCompletionSettings_addDiameterRoughnessInterval,
|
||||
"AddDiameterRoughnessInterval" );
|
||||
|
||||
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimWellPathCompletionSettings,
|
||||
RimcWellPathCompletionSettings_addCustomSegmentInterval,
|
||||
"AddCustomSegmentInterval" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -88,3 +94,65 @@ QString RimcWellPathCompletionSettings_addDiameterRoughnessInterval::classKeywor
|
||||
{
|
||||
return RimDiameterRoughnessInterval::classKeywordStatic();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimcWellPathCompletionSettings_addCustomSegmentInterval::RimcWellPathCompletionSettings_addCustomSegmentInterval( caf::PdmObjectHandle* self )
|
||||
: caf::PdmObjectCreationMethod( self )
|
||||
{
|
||||
CAF_PDM_InitObject( "Add Custom Segment Interval" );
|
||||
CAF_PDM_InitScriptableField( &m_startMD, "StartMd", 0.0, "Start Measured Depth" );
|
||||
CAF_PDM_InitScriptableField( &m_endMD, "EndMd", 100.0, "End Measured Depth" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<caf::PdmObjectHandle*, QString> RimcWellPathCompletionSettings_addCustomSegmentInterval::execute()
|
||||
{
|
||||
auto completionSettings = self<RimWellPathCompletionSettings>();
|
||||
if ( !completionSettings )
|
||||
{
|
||||
return std::unexpected( QString( "Completion settings is null. Cannot add custom segment interval." ) );
|
||||
}
|
||||
|
||||
auto mswParams = completionSettings->mswCompletionParameters();
|
||||
if ( !mswParams )
|
||||
{
|
||||
return std::unexpected( QString( "MSW completion parameters is null. Cannot add custom segment interval." ) );
|
||||
}
|
||||
|
||||
auto intervalCollection = mswParams->customSegmentIntervals();
|
||||
if ( !intervalCollection )
|
||||
{
|
||||
return std::unexpected( QString( "Custom segment interval collection is null. Cannot add interval." ) );
|
||||
}
|
||||
|
||||
// Validate that end MD is greater than start MD
|
||||
if ( m_endMD() <= m_startMD() )
|
||||
{
|
||||
return std::unexpected(
|
||||
QString( "End MD must be greater than Start MD. Start MD: %1, End MD: %2" ).arg( m_startMD() ).arg( m_endMD() ) );
|
||||
}
|
||||
|
||||
// Create new interval
|
||||
auto* newInterval = intervalCollection->createInterval( m_startMD(), m_endMD() );
|
||||
|
||||
if ( !newInterval )
|
||||
{
|
||||
return std::unexpected( QString( "Failed to create custom segment interval." ) );
|
||||
}
|
||||
|
||||
completionSettings->updateAllRequiredEditors();
|
||||
|
||||
return newInterval;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimcWellPathCompletionSettings_addCustomSegmentInterval::classKeywordReturnedType() const
|
||||
{
|
||||
return RimCustomSegmentInterval::classKeywordStatic();
|
||||
}
|
||||
@@ -42,4 +42,22 @@ private:
|
||||
caf::PdmField<double> m_endMD;
|
||||
caf::PdmField<double> m_diameter;
|
||||
caf::PdmField<double> m_roughnessFactor;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimcWellPathCompletionSettings_addCustomSegmentInterval : public caf::PdmObjectCreationMethod
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimcWellPathCompletionSettings_addCustomSegmentInterval( caf::PdmObjectHandle* self );
|
||||
|
||||
std::expected<caf::PdmObjectHandle*, QString> execute() override;
|
||||
QString classKeywordReturnedType() const override;
|
||||
|
||||
private:
|
||||
caf::PdmField<double> m_startMD;
|
||||
caf::PdmField<double> m_endMD;
|
||||
};
|
||||
@@ -79,6 +79,14 @@ print(
|
||||
f"Added diameter roughness intervals: {interval1.start_md}-{interval1.end_md}m and {interval2.start_md}-{interval2.end_md}m"
|
||||
)
|
||||
|
||||
# Add custom segment intervals to define explicit segment boundaries for MSW export
|
||||
segment1 = completions_settings.add_custom_segment_interval(start_md=3200, end_md=3250)
|
||||
segment2 = completions_settings.add_custom_segment_interval(start_md=3250, end_md=3320)
|
||||
segment3 = completions_settings.add_custom_segment_interval(start_md=3320, end_md=3400)
|
||||
print(
|
||||
f"Added custom segment intervals: {segment1.start_md}-{segment1.end_md}m, {segment2.start_md}-{segment2.end_md}m, {segment3.start_md}-{segment3.end_md}m"
|
||||
)
|
||||
|
||||
# Optionally update the MSW settings
|
||||
msw_settings = well_path.msw_settings()
|
||||
msw_settings.custom_values_for_lateral = False
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import pytest
|
||||
|
||||
import rips
|
||||
|
||||
|
||||
def test_custom_segment_intervals(rips_instance, initialize_test):
|
||||
"""Test the custom segment intervals Python GRPC interface"""
|
||||
|
||||
# Create a test well
|
||||
well_path_coll = rips_instance.project.well_path_collection()
|
||||
well_path = well_path_coll.add_new_object(rips.ModeledWellPath)
|
||||
well_path.name = "Test Well for Custom Segments"
|
||||
|
||||
completions_settings = well_path.completion_settings()
|
||||
assert completions_settings is not None, "Completion settings should not be None"
|
||||
|
||||
# Test creating first interval
|
||||
interval1 = completions_settings.add_custom_segment_interval(
|
||||
start_md=100, end_md=200
|
||||
)
|
||||
|
||||
# Assertions to verify the first interval
|
||||
assert interval1 is not None, "First interval should not be None"
|
||||
assert interval1.start_md == 100
|
||||
assert interval1.end_md == 200
|
||||
|
||||
# Test creating a second interval with different values
|
||||
interval2 = completions_settings.add_custom_segment_interval(
|
||||
start_md=250, end_md=350
|
||||
)
|
||||
|
||||
# Assertions to verify the second interval
|
||||
assert interval2 is not None, "Second interval should not be None"
|
||||
assert interval2.start_md == 250
|
||||
assert interval2.end_md == 350
|
||||
|
||||
# Test default values
|
||||
interval3 = completions_settings.add_custom_segment_interval()
|
||||
|
||||
assert interval3 is not None, "Third interval with defaults should not be None"
|
||||
assert interval3.start_md == 0.0
|
||||
assert interval3.end_md == 100.0
|
||||
|
||||
|
||||
def test_custom_segment_interval_properties(rips_instance, initialize_test):
|
||||
"""Test modifying custom segment interval properties"""
|
||||
|
||||
# Create a test well
|
||||
well_path_coll = rips_instance.project.well_path_collection()
|
||||
well_path = well_path_coll.add_new_object(rips.ModeledWellPath)
|
||||
well_path.name = "Test Well for Property Modification"
|
||||
|
||||
completions_settings = well_path.completion_settings()
|
||||
|
||||
# Create an interval
|
||||
interval1 = completions_settings.add_custom_segment_interval(
|
||||
start_md=100, end_md=200
|
||||
)
|
||||
|
||||
# Test modifying interval properties
|
||||
interval1.start_md = 150
|
||||
assert interval1.start_md == 150
|
||||
|
||||
interval1.end_md = 250
|
||||
assert interval1.end_md == 250
|
||||
|
||||
|
||||
def test_custom_segment_interval_invalid_range(rips_instance, initialize_test):
|
||||
"""Test creating interval with invalid range (start_md > end_md) fails"""
|
||||
|
||||
# Create a test well
|
||||
well_path_coll = rips_instance.project.well_path_collection()
|
||||
well_path = well_path_coll.add_new_object(rips.ModeledWellPath)
|
||||
well_path.name = "Test Well for Invalid Range"
|
||||
|
||||
completions_settings = well_path.completion_settings()
|
||||
|
||||
# Attempt to create an interval with start_md > end_md. Should fail.
|
||||
with pytest.raises(rips.RipsError, match="End MD must be greater than Start MD"):
|
||||
completions_settings.add_custom_segment_interval(start_md=200, end_md=100)
|
||||
|
||||
# Also test equal values (start_md == end_md), which should also fail
|
||||
with pytest.raises(rips.RipsError, match="End MD must be greater than Start MD"):
|
||||
completions_settings.add_custom_segment_interval(start_md=150, end_md=150)
|
||||
Reference in new issue
Block a user