#14804 MSW export: Segmentation controls per interval and around perforations

Add fixed, min and max segment length per segment interval (fixed is exclusive with min/max, min and max can be combined), connect COMPSEGS rows to the nearest segment node, and add collection options for a single segment before the first and after the last perforation.
This commit is contained in:
Magne Sjaastad committed 2026-10-12 19:12:08 +02:00
1 parent 2f7de9469f
commit d8f346e9ab
22 files changed
+1866 -149

No files matched your search

@@ -73,6 +73,17 @@ void RimSegmentCollection::LengthAndDepthEnum::setUp()
setDefault( RimSegmentCollection::LengthAndDepthType::ABS );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <>
void RimSegmentCollection::CompsegsSegmentNumberEnum::setUp()
{
addItem( RimSegmentCollection::CompsegsSegmentNumberType::ASSIGNED_BY_SIMULATOR, "AssignedBySimulator", "Assigned by Simulator (1*)" );
addItem( RimSegmentCollection::CompsegsSegmentNumberType::EXPORTED, "Exported", "Exported" );
setDefault( RimSegmentCollection::CompsegsSegmentNumberType::ASSIGNED_BY_SIMULATOR );
}
} // namespace caf
CAF_PDM_SOURCE_INIT( RimSegmentCollection, "SegmentCollection" );
@@ -82,7 +93,7 @@ CAF_PDM_SOURCE_INIT( RimSegmentCollection, "SegmentCollection" );
//--------------------------------------------------------------------------------------------------
RimSegmentCollection::RimSegmentCollection()
{
CAF_PDM_InitScriptableObject( "Segments", ":/CompletionsSymbol16x16.png", "", "SegmentCollection" );
CAF_PDM_InitScriptableObject( "Segments", ":/Segment.svg", "", "SegmentCollection" );
CAF_PDM_InitScriptableFieldWithScriptKeywordNoDefault( &m_refMDType, "RefMDType", "ReferenceMdType", "Reference MD Type" );
CAF_PDM_InitScriptableFieldWithScriptKeyword( &m_refMD, "RefMD", "UserDefinedReferenceMd", 0.0, "User Defined Reference MD" );
@@ -98,6 +109,18 @@ RimSegmentCollection::RimSegmentCollection()
CAF_PDM_InitScriptableField( &m_enforceMaxSegmentLength, "EnforceMaxSegmentLength", false, "Enforce Max Segment Length" );
CAF_PDM_InitScriptableField( &m_maxSegmentLength, "MaxSegmentLength", 200.0, "Max Segment Length" );
m_maxSegmentLength.uiCapability()->setUiHidden( true );
CAF_PDM_InitScriptableField( &m_singleSegmentBeforeFirstPerforation,
"SingleSegmentBeforeFirstPerforation",
false,
"Single Segment Before First Perforation" );
CAF_PDM_InitScriptableField( &m_singleSegmentAfterLastPerforation,
"SingleSegmentAfterLastPerforation",
false,
"Single Segment After Last Perforation" );
CAF_PDM_InitScriptableFieldNoDefault( &m_compsegsSegmentNumber, "CompsegsSegmentNumber", "COMPSEGS Segment Number (ISEG)" );
m_compsegsSegmentNumber.uiCapability()->setUiToolTip(
"Export the segment each COMPSEGS connection belongs to, or leave it to the simulator to assign the segment" );
}
//--------------------------------------------------------------------------------------------------
@@ -201,6 +224,54 @@ double RimSegmentCollection::maxSegmentLength() const
return m_enforceMaxSegmentLength() ? m_maxSegmentLength() : std::numeric_limits<double>::infinity();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSegmentCollection::setSingleSegmentBeforeFirstPerforation( bool enable )
{
m_singleSegmentBeforeFirstPerforation = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSegmentCollection::setSingleSegmentAfterLastPerforation( bool enable )
{
m_singleSegmentAfterLastPerforation = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSegmentCollection::singleSegmentBeforeFirstPerforation() const
{
return m_singleSegmentBeforeFirstPerforation();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSegmentCollection::singleSegmentAfterLastPerforation() const
{
return m_singleSegmentAfterLastPerforation();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSegmentCollection::exportCompsegsSegmentNumber() const
{
return m_compsegsSegmentNumber() == CompsegsSegmentNumberType::EXPORTED;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSegmentCollection::setCompsegsSegmentNumber( CompsegsSegmentNumberType segmentNumberType )
{
m_compsegsSegmentNumber = segmentNumberType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -389,6 +460,22 @@ std::vector<std::pair<double, double>> RimSegmentCollection::getSegmentIntervals
return result;
}
//--------------------------------------------------------------------------------------------------
/// Valid intervals with a fixed, min or max segment length rule, active on the export date if given
//--------------------------------------------------------------------------------------------------
std::vector<const RimSegmentInterval*> RimSegmentCollection::segmentationIntervals( const std::optional<QDateTime>& exportDate ) const
{
std::vector<const RimSegmentInterval*> result;
for ( auto* interval : intervals() )
{
if ( !interval || !interval->isValidInterval() ) continue;
if ( exportDate.has_value() && !interval->isActiveOnDate( *exportDate ) ) continue;
if ( interval->fixedSegmentLength().has_value() || interval->minSegmentLength().has_value() || interval->maxSegmentLength().has_value() )
result.push_back( interval );
}
return result;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -412,12 +499,15 @@ void RimSegmentCollection::setUnitSystemSpecificDefaults()
//--------------------------------------------------------------------------------------------------
void RimSegmentCollection::updateFromTopLevelWell( const RimSegmentCollection* topLevelWellParameters )
{
m_refMDType = topLevelWellParameters->m_refMDType();
m_refMD = topLevelWellParameters->m_refMD();
m_pressureDrop = topLevelWellParameters->m_pressureDrop();
m_lengthAndDepth = topLevelWellParameters->m_lengthAndDepth();
m_enforceMaxSegmentLength = topLevelWellParameters->m_enforceMaxSegmentLength();
m_maxSegmentLength = topLevelWellParameters->m_maxSegmentLength();
m_refMDType = topLevelWellParameters->m_refMDType();
m_refMD = topLevelWellParameters->m_refMD();
m_pressureDrop = topLevelWellParameters->m_pressureDrop();
m_lengthAndDepth = topLevelWellParameters->m_lengthAndDepth();
m_enforceMaxSegmentLength = topLevelWellParameters->m_enforceMaxSegmentLength();
m_maxSegmentLength = topLevelWellParameters->m_maxSegmentLength();
m_compsegsSegmentNumber = topLevelWellParameters->m_compsegsSegmentNumber();
m_singleSegmentBeforeFirstPerforation = topLevelWellParameters->m_singleSegmentBeforeFirstPerforation();
m_singleSegmentAfterLastPerforation = topLevelWellParameters->m_singleSegmentAfterLastPerforation();
}
//--------------------------------------------------------------------------------------------------
@@ -515,7 +605,7 @@ void RimSegmentCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedF
//--------------------------------------------------------------------------------------------------
void RimSegmentCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
{
menuBuilder << "RicNewSegmentIntervalFeature";
menuBuilder << "RicCreateSegmentIntervalFeature";
if ( hasIntervals() ) menuBuilder << "RicDeleteSegmentIntervalFeature";
}
@@ -548,8 +638,13 @@ void RimSegmentCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrd
{
uiOrdering.add( &m_pressureDrop );
uiOrdering.add( &m_lengthAndDepth );
uiOrdering.add( &m_enforceMaxSegmentLength );
uiOrdering.add( &m_maxSegmentLength );
uiOrdering.add( &m_compsegsSegmentNumber );
auto* segmentationGroup = uiOrdering.addNewGroup( "Segmentation" );
segmentationGroup->add( &m_enforceMaxSegmentLength );
segmentationGroup->add( &m_maxSegmentLength );
segmentationGroup->add( &m_singleSegmentBeforeFirstPerforation );
segmentationGroup->add( &m_singleSegmentAfterLastPerforation );
}
const bool readOnly = !wellPath->isTopLevelWellPath() && !m_customValuesForLateral();
@@ -60,9 +60,16 @@ public:
INC
};
using ReferenceMDEnum = caf::AppEnum<ReferenceMDType>;
using PressureDropEnum = caf::AppEnum<PressureDropType>;
using LengthAndDepthEnum = caf::AppEnum<LengthAndDepthType>;
enum class CompsegsSegmentNumberType
{
ASSIGNED_BY_SIMULATOR,
EXPORTED
};
using ReferenceMDEnum = caf::AppEnum<ReferenceMDType>;
using PressureDropEnum = caf::AppEnum<PressureDropType>;
using LengthAndDepthEnum = caf::AppEnum<LengthAndDepthType>;
using CompsegsSegmentNumberEnum = caf::AppEnum<CompsegsSegmentNumberType>;
RimSegmentCollection();
@@ -75,6 +82,9 @@ public:
PressureDropEnum pressureDrop() const;
LengthAndDepthEnum lengthAndDepth() const;
double maxSegmentLength() const;
bool singleSegmentBeforeFirstPerforation() const;
bool singleSegmentAfterLastPerforation() const;
bool exportCompsegsSegmentNumber() const;
void setReferenceMDType( ReferenceMDType refType );
void setManualReferenceMD( double manualRefMD );
@@ -82,6 +92,9 @@ public:
void setRoughnessFactor( double roughnessFactor );
void setPressureDrop( PressureDropType pressureDropType );
void setLengthAndDepth( LengthAndDepthType lengthAndDepthType );
void setCompsegsSegmentNumber( CompsegsSegmentNumberType segmentNumberType );
void setSingleSegmentBeforeFirstPerforation( bool enable );
void setSingleSegmentAfterLastPerforation( bool enable );
double getDiameterAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const;
double getRoughnessAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const;
@@ -98,6 +111,7 @@ public:
void updateOverlapVisualFeedback();
std::vector<std::pair<double, double>> getSegmentIntervals() const;
std::vector<const RimSegmentInterval*> segmentationIntervals( const std::optional<QDateTime>& exportDate ) const;
bool hasCustomSegmentIntervals() const;
void setUnitSystemSpecificDefaults();
@@ -132,4 +146,8 @@ private:
caf::PdmField<LengthAndDepthEnum> m_lengthAndDepth;
caf::PdmField<bool> m_enforceMaxSegmentLength;
caf::PdmField<double> m_maxSegmentLength;
caf::PdmField<bool> m_singleSegmentBeforeFirstPerforation;
caf::PdmField<bool> m_singleSegmentAfterLastPerforation;
caf::PdmField<CompsegsSegmentNumberEnum> m_compsegsSegmentNumber;
};
@@ -28,6 +28,7 @@
#include "cafCmdFeatureMenuBuilder.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiCheckBoxAndTextEditor.h"
#include "cafPdmUiDoubleSliderEditor.h"
#include "cafPdmUiDoubleValueEditor.h"
#include "cafPdmUiTreeOrdering.h"
@@ -41,7 +42,7 @@ CAF_PDM_SOURCE_INIT( RimSegmentInterval, "SegmentInterval" );
//--------------------------------------------------------------------------------------------------
RimSegmentInterval::RimSegmentInterval()
{
CAF_PDM_InitScriptableObject( "Segment Interval", ":/WellPathComponent16x16.png", "", "SegmentInterval" );
CAF_PDM_InitScriptableObject( "Segment Interval", ":/Segment.svg", "", "SegmentInterval" );
CAF_PDM_InitScriptableField( &m_startMD, "StartMd", 0.0, "Start MD" );
CAF_PDM_InitScriptableField( &m_endMD, "EndMd", 0.0, "End MD" );
CAF_PDM_InitScriptableField( &m_diameter,
@@ -53,6 +54,13 @@ RimSegmentInterval::RimSegmentInterval()
RimSegmentCollection::defaultRoughnessFactor( RiaDefines::EclipseUnitSystem::UNITS_METRIC ),
"Roughness Factor" );
CAF_PDM_InitField( &m_fixedSegmentLength, "FixedSegmentLength", std::make_pair( false, 50.0 ), "Fixed Segment Length" );
m_fixedSegmentLength.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxAndTextEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_minSegmentLength, "MinSegmentLength", std::make_pair( false, 10.0 ), "Min Segment Length" );
m_minSegmentLength.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxAndTextEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_maxSegmentLength, "MaxSegmentLength", std::make_pair( false, 100.0 ), "Max Segment Length" );
m_maxSegmentLength.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxAndTextEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_useCustomStartDate, "UseCustomStartDate", false, "Custom Start Date" );
CAF_PDM_InitField( &m_startDate, "StartDate", QDateTime::currentDateTime(), "Start Date" );
}
@@ -158,6 +166,60 @@ void RimSegmentInterval::setRoughnessFactor( double roughness )
m_roughnessFactor = roughness;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::optional<double> RimSegmentInterval::fixedSegmentLength() const
{
if ( m_fixedSegmentLength().first && m_fixedSegmentLength().second > 0.0 ) return m_fixedSegmentLength().second;
return std::nullopt;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::optional<double> RimSegmentInterval::minSegmentLength() const
{
if ( m_minSegmentLength().first && m_minSegmentLength().second > 0.0 ) return m_minSegmentLength().second;
return std::nullopt;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::optional<double> RimSegmentInterval::maxSegmentLength() const
{
if ( m_maxSegmentLength().first && m_maxSegmentLength().second > 0.0 ) return m_maxSegmentLength().second;
return std::nullopt;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSegmentInterval::setFixedSegmentLength( std::optional<double> length )
{
m_fixedSegmentLength = std::make_pair( length.has_value(), length.value_or( m_fixedSegmentLength().second ) );
if ( length ) enforceSegmentationRules( &m_fixedSegmentLength );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSegmentInterval::setMinSegmentLength( std::optional<double> length )
{
m_minSegmentLength = std::make_pair( length.has_value(), length.value_or( m_minSegmentLength().second ) );
if ( length ) enforceSegmentationRules( &m_minSegmentLength );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSegmentInterval::setMaxSegmentLength( std::optional<double> length )
{
m_maxSegmentLength = std::make_pair( length.has_value(), length.value_or( m_maxSegmentLength().second ) );
if ( length ) enforceSegmentationRules( &m_maxSegmentLength );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -307,7 +369,7 @@ void RimSegmentInterval::fieldChangedByUi( const caf::PdmFieldHandle* changedFie
{
if ( changedField == &m_startMD || changedField == &m_endMD )
{
uiCapability()->setUiName( QString( "%1 - %2" ).arg( m_startMD() ).arg( m_endMD() ) );
updateUiName();
// Validate interval
if ( m_startMD >= m_endMD )
@@ -323,6 +385,17 @@ void RimSegmentInterval::fieldChangedByUi( const caf::PdmFieldHandle* changedFie
}
}
const bool segmentationEnabled = ( changedField == &m_fixedSegmentLength && m_fixedSegmentLength().first ) ||
( changedField == &m_minSegmentLength && m_minSegmentLength().first ) ||
( changedField == &m_maxSegmentLength && m_maxSegmentLength().first );
if ( segmentationEnabled ) enforceSegmentationRules( changedField );
if ( changedField == &m_fixedSegmentLength || changedField == &m_minSegmentLength || changedField == &m_maxSegmentLength )
{
updateUiName();
uiCapability()->updateConnectedEditors();
}
updateConnectedEditors();
}
@@ -339,12 +412,23 @@ void RimSegmentInterval::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
m_endMD.uiCapability()->setUiName( isMetric ? "End MD [m]" : "End MD [ft]" );
m_diameter.uiCapability()->setUiName( isMetric ? "Diameter [m]" : "Diameter [ft]" );
m_roughnessFactor.uiCapability()->setUiName( isMetric ? "Roughness Factor [m]" : "Roughness Factor [ft]" );
m_fixedSegmentLength.uiCapability()->setUiName( isMetric ? "Fixed Segment Length [m]" : "Fixed Segment Length [ft]" );
m_minSegmentLength.uiCapability()->setUiName( isMetric ? "Min Segment Length [m]" : "Min Segment Length [ft]" );
m_maxSegmentLength.uiCapability()->setUiName( isMetric ? "Max Segment Length [m]" : "Max Segment Length [ft]" );
}
uiOrdering.add( &m_startMD );
uiOrdering.add( &m_endMD );
uiOrdering.add( &m_diameter );
uiOrdering.add( &m_roughnessFactor );
auto* intervalGroup = uiOrdering.addNewGroup( "Interval" );
intervalGroup->add( &m_startMD );
intervalGroup->add( &m_endMD );
auto* diameterGroup = uiOrdering.addNewGroup( "Diameter and Roughness" );
diameterGroup->add( &m_diameter );
diameterGroup->add( &m_roughnessFactor );
auto* segmentationGroup = uiOrdering.addNewGroup( "Segmentation" );
segmentationGroup->add( &m_fixedSegmentLength );
segmentationGroup->add( &m_minSegmentLength );
segmentationGroup->add( &m_maxSegmentLength );
}
//--------------------------------------------------------------------------------------------------
@@ -352,7 +436,19 @@ void RimSegmentInterval::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
//--------------------------------------------------------------------------------------------------
void RimSegmentInterval::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
{
uiCapability()->setUiName( QString( "%1 - %2" ).arg( m_startMD() ).arg( m_endMD() ) );
updateUiName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSegmentInterval::updateUiName()
{
QString name = QString( "%1 - %2" ).arg( m_startMD() ).arg( m_endMD() );
if ( auto fixedLength = fixedSegmentLength() ) name += QString( " (fixed %1)" ).arg( *fixedLength );
if ( auto minLength = minSegmentLength() ) name += QString( " (min %1)" ).arg( *minLength );
if ( auto maxLength = maxSegmentLength() ) name += QString( " (max %1)" ).arg( *maxLength );
uiCapability()->setUiName( name );
}
//--------------------------------------------------------------------------------------------------
@@ -365,6 +461,25 @@ void RimSegmentInterval::updateConnectedEditors()
m_endMD.uiCapability()->updateConnectedEditors();
m_diameter.uiCapability()->updateConnectedEditors();
m_roughnessFactor.uiCapability()->updateConnectedEditors();
m_fixedSegmentLength.uiCapability()->updateConnectedEditors();
m_minSegmentLength.uiCapability()->updateConnectedEditors();
m_maxSegmentLength.uiCapability()->updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
/// Fixed length cannot be combined with min/max length. Min and max length can be combined.
//--------------------------------------------------------------------------------------------------
void RimSegmentInterval::enforceSegmentationRules( const caf::PdmFieldHandle* activeField )
{
if ( activeField == &m_fixedSegmentLength )
{
m_minSegmentLength = std::make_pair( false, m_minSegmentLength().second );
m_maxSegmentLength = std::make_pair( false, m_maxSegmentLength().second );
}
else
{
m_fixedSegmentLength = std::make_pair( false, m_fixedSegmentLength().second );
}
}
//--------------------------------------------------------------------------------------------------
@@ -27,6 +27,8 @@
#include <QDateTime>
#include <QString>
#include <optional>
class RimWellPath;
namespace caf
@@ -62,6 +64,14 @@ public:
void setDiameter( double diameter );
void setRoughnessFactor( double roughness );
// Segmentation. Fixed length cannot be combined with min/max length, min and max length can be combined.
std::optional<double> fixedSegmentLength() const;
std::optional<double> minSegmentLength() const;
std::optional<double> maxSegmentLength() const;
void setFixedSegmentLength( std::optional<double> length );
void setMinSegmentLength( std::optional<double> length );
void setMaxSegmentLength( std::optional<double> length );
// Date tracking
void enableCustomStartDate( bool enable );
void setCustomStartDate( const QDate& date );
@@ -103,7 +113,9 @@ protected:
private:
void updateConnectedEditors();
void updateUiName();
QString generateDisplayLabel() const;
void enforceSegmentationRules( const caf::PdmFieldHandle* activeField );
private:
caf::PdmField<double> m_startMD;
@@ -111,6 +123,10 @@ private:
caf::PdmField<double> m_diameter;
caf::PdmField<double> m_roughnessFactor;
caf::PdmField<std::pair<bool, double>> m_fixedSegmentLength;
caf::PdmField<std::pair<bool, double>> m_minSegmentLength;
caf::PdmField<std::pair<bool, double>> m_maxSegmentLength;
caf::PdmField<bool> m_useCustomStartDate;
caf::PdmField<QDateTime> m_startDate;
};