2026-09-04 15:23:32 +02:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// 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 "RimSegmentCollection.h"
|
|
|
|
|
|
|
|
|
|
#include "RiaEclipseUnitTools.h"
|
|
|
|
|
#include "RimCustomSegmentInterval.h"
|
|
|
|
|
#include "RimCustomSegmentIntervalCollection.h"
|
|
|
|
|
#include "RimDiameterRoughnessInterval.h"
|
|
|
|
|
#include "RimDiameterRoughnessIntervalCollection.h"
|
|
|
|
|
#include "RimMswCompletionParameters.h"
|
|
|
|
|
#include "RimSegmentInterval.h"
|
|
|
|
|
#include "RimWellPath.h"
|
|
|
|
|
|
|
|
|
|
#include "cafCmdFeatureMenuBuilder.h"
|
|
|
|
|
#include "cafPdmFieldScriptingCapability.h"
|
|
|
|
|
#include "cafPdmObjectScriptingCapability.h"
|
|
|
|
|
#include "cafPdmUiObjectEditorHandle.h"
|
|
|
|
|
#include "cafPdmUiTreeOrdering.h"
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
#include <limits>
|
|
|
|
|
|
|
|
|
|
namespace caf
|
|
|
|
|
{
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
template <>
|
|
|
|
|
void RimSegmentCollection::ReferenceMDEnum::setUp()
|
|
|
|
|
{
|
|
|
|
|
addItem( RimSegmentCollection::ReferenceMDType::AUTO_REFERENCE_MD, "GridEntryPoint", "Grid Entry Point", { "GridIntersectionRefMD" } );
|
|
|
|
|
addItem( RimSegmentCollection::ReferenceMDType::MANUAL_REFERENCE_MD, "UserDefined", "User Defined", { "ManualRefMD" } );
|
|
|
|
|
setDefault( RimSegmentCollection::ReferenceMDType::AUTO_REFERENCE_MD );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
template <>
|
|
|
|
|
void RimSegmentCollection::PressureDropEnum::setUp()
|
|
|
|
|
{
|
|
|
|
|
addItem( RimSegmentCollection::PressureDropType::HYDROSTATIC, "H--", "Hydrostatic" );
|
|
|
|
|
addItem( RimSegmentCollection::PressureDropType::HYDROSTATIC_FRICTION, "HF-", "Hydrostatic + Friction" );
|
|
|
|
|
addItem( RimSegmentCollection::PressureDropType::HYDROSTATIC_FRICTION_ACCELERATION, "HFA", "Hydrostatic + Friction + Acceleration" );
|
|
|
|
|
setDefault( RimSegmentCollection::PressureDropType::HYDROSTATIC_FRICTION );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
template <>
|
|
|
|
|
void RimSegmentCollection::LengthAndDepthEnum::setUp()
|
|
|
|
|
{
|
|
|
|
|
addItem( RimSegmentCollection::LengthAndDepthType::INC, "INC", "Incremental" );
|
|
|
|
|
addItem( RimSegmentCollection::LengthAndDepthType::ABS, "ABS", "Absolute" );
|
|
|
|
|
setDefault( RimSegmentCollection::LengthAndDepthType::ABS );
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-09 14:36:40 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
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 );
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
} // namespace caf
|
|
|
|
|
|
|
|
|
|
CAF_PDM_SOURCE_INIT( RimSegmentCollection, "SegmentCollection" );
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
RimSegmentCollection::RimSegmentCollection()
|
|
|
|
|
{
|
2026-10-09 14:36:40 +02:00
|
|
|
CAF_PDM_InitScriptableObject( "Segments", ":/Segment.svg", "", "SegmentCollection" );
|
2026-09-04 15:23:32 +02:00
|
|
|
|
|
|
|
|
CAF_PDM_InitScriptableFieldWithScriptKeywordNoDefault( &m_refMDType, "RefMDType", "ReferenceMdType", "Reference MD Type" );
|
|
|
|
|
CAF_PDM_InitScriptableFieldWithScriptKeyword( &m_refMD, "RefMD", "UserDefinedReferenceMd", 0.0, "User Defined Reference MD" );
|
|
|
|
|
CAF_PDM_InitScriptableField( &m_customValuesForLateral, "CustomValuesForLateral", false, "Custom Values for Lateral" );
|
|
|
|
|
|
|
|
|
|
const auto unitSystem = RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
|
|
|
|
CAF_PDM_InitScriptableField( &m_linerDiameter, "LinerDiameter", defaultLinerDiameter( unitSystem ), "Liner Inner Diameter" );
|
|
|
|
|
CAF_PDM_InitScriptableField( &m_roughnessFactor, "RoughnessFactor", defaultRoughnessFactor( unitSystem ), "Roughness Factor" );
|
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_segmentIntervals, "Intervals", "Segment Intervals" );
|
|
|
|
|
|
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_pressureDrop, "PressureDrop", "Pressure Drop" );
|
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_lengthAndDepth, "LengthAndDepth", "Length and Depth" );
|
|
|
|
|
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 );
|
2026-10-09 14:36:40 +02:00
|
|
|
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" );
|
2026-09-04 15:23:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
RimSegmentCollection::ReferenceMDType RimSegmentCollection::referenceMDType() const
|
|
|
|
|
{
|
|
|
|
|
return m_refMDType();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::manualReferenceMD() const
|
|
|
|
|
{
|
|
|
|
|
if ( m_refMDType == ReferenceMDType::AUTO_REFERENCE_MD ) return std::numeric_limits<double>::infinity();
|
|
|
|
|
return m_refMD();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::linerDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const
|
|
|
|
|
{
|
|
|
|
|
auto* wellPath = firstAncestorOrThisOfTypeAsserted<RimWellPath>();
|
|
|
|
|
double diameter = m_linerDiameter();
|
|
|
|
|
if ( !wellPath->isTopLevelWellPath() && !m_customValuesForLateral() )
|
|
|
|
|
{
|
|
|
|
|
if ( const auto* topLevelWell = wellPath->topLevelWellPath() )
|
|
|
|
|
{
|
|
|
|
|
diameter = topLevelWell->segmentCollection()->linerDiameter();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( wellPath->unitSystem() == RiaDefines::EclipseUnitSystem::UNITS_FIELD && unitSystem == RiaDefines::EclipseUnitSystem::UNITS_METRIC )
|
|
|
|
|
return RiaEclipseUnitTools::feetToMeter( diameter );
|
|
|
|
|
if ( wellPath->unitSystem() == RiaDefines::EclipseUnitSystem::UNITS_METRIC && unitSystem == RiaDefines::EclipseUnitSystem::UNITS_FIELD )
|
|
|
|
|
return RiaEclipseUnitTools::meterToFeet( diameter );
|
|
|
|
|
return diameter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::linerDiameter() const
|
|
|
|
|
{
|
|
|
|
|
return m_linerDiameter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::roughnessFactor( RiaDefines::EclipseUnitSystem unitSystem ) const
|
|
|
|
|
{
|
|
|
|
|
auto* wellPath = firstAncestorOrThisOfTypeAsserted<RimWellPath>();
|
|
|
|
|
double roughness = m_roughnessFactor();
|
|
|
|
|
if ( !wellPath->isTopLevelWellPath() && !m_customValuesForLateral() )
|
|
|
|
|
{
|
|
|
|
|
if ( const auto* topLevelWell = wellPath->topLevelWellPath() )
|
|
|
|
|
{
|
|
|
|
|
roughness = topLevelWell->segmentCollection()->roughnessFactor();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( wellPath->unitSystem() == RiaDefines::EclipseUnitSystem::UNITS_FIELD && unitSystem == RiaDefines::EclipseUnitSystem::UNITS_METRIC )
|
|
|
|
|
return RiaEclipseUnitTools::feetToMeter( roughness );
|
|
|
|
|
if ( wellPath->unitSystem() == RiaDefines::EclipseUnitSystem::UNITS_METRIC && unitSystem == RiaDefines::EclipseUnitSystem::UNITS_FIELD )
|
|
|
|
|
return RiaEclipseUnitTools::meterToFeet( roughness );
|
|
|
|
|
return roughness;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::roughnessFactor() const
|
|
|
|
|
{
|
|
|
|
|
return m_roughnessFactor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
RimSegmentCollection::PressureDropEnum RimSegmentCollection::pressureDrop() const
|
|
|
|
|
{
|
|
|
|
|
return m_pressureDrop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
RimSegmentCollection::LengthAndDepthEnum RimSegmentCollection::lengthAndDepth() const
|
|
|
|
|
{
|
|
|
|
|
return m_lengthAndDepth();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::maxSegmentLength() const
|
|
|
|
|
{
|
|
|
|
|
return m_enforceMaxSegmentLength() ? m_maxSegmentLength() : std::numeric_limits<double>::infinity();
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-09 14:36:40 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::setReferenceMDType( ReferenceMDType refType )
|
|
|
|
|
{
|
|
|
|
|
m_refMDType = refType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::setManualReferenceMD( double manualRefMD )
|
|
|
|
|
{
|
|
|
|
|
m_refMD = manualRefMD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::setLinerDiameter( double diameter )
|
|
|
|
|
{
|
|
|
|
|
m_linerDiameter = diameter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::setRoughnessFactor( double roughnessFactor )
|
|
|
|
|
{
|
|
|
|
|
m_roughnessFactor = roughnessFactor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::setPressureDrop( PressureDropType pressureDropType )
|
|
|
|
|
{
|
|
|
|
|
m_pressureDrop = pressureDropType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::setLengthAndDepth( LengthAndDepthType lengthAndDepthType )
|
|
|
|
|
{
|
|
|
|
|
m_lengthAndDepth = lengthAndDepthType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
RimSegmentInterval* RimSegmentCollection::findIntervalAtMD( double md, const std::optional<QDateTime>& exportDate ) const
|
|
|
|
|
{
|
|
|
|
|
for ( auto* interval : intervals() )
|
|
|
|
|
{
|
|
|
|
|
if ( interval && interval->containsMD( md ) && ( !exportDate.has_value() || interval->isActiveOnDate( *exportDate ) ) )
|
|
|
|
|
return interval;
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::getDiameterAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const
|
|
|
|
|
{
|
2026-09-11 14:26:31 +02:00
|
|
|
if ( auto* interval = findIntervalAtMD( md, std::nullopt ) ) return interval->diameter( unitSystem );
|
2026-09-04 15:23:32 +02:00
|
|
|
return linerDiameter( unitSystem );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::getRoughnessAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const
|
|
|
|
|
{
|
2026-09-11 14:26:31 +02:00
|
|
|
if ( auto* interval = findIntervalAtMD( md, std::nullopt ) ) return interval->roughnessFactor( unitSystem );
|
2026-09-04 15:23:32 +02:00
|
|
|
return roughnessFactor( unitSystem );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::getDiameterAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem, const QDateTime& exportDate ) const
|
|
|
|
|
{
|
2026-09-11 14:26:31 +02:00
|
|
|
if ( auto* interval = findIntervalAtMD( md, exportDate ) ) return interval->diameter( unitSystem );
|
2026-09-04 15:23:32 +02:00
|
|
|
return linerDiameter( unitSystem );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::getRoughnessAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem, const QDateTime& exportDate ) const
|
|
|
|
|
{
|
2026-09-11 14:26:31 +02:00
|
|
|
if ( auto* interval = findIntervalAtMD( md, exportDate ) ) return interval->roughnessFactor( unitSystem );
|
2026-09-04 15:23:32 +02:00
|
|
|
return roughnessFactor( unitSystem );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
std::vector<RimSegmentInterval*> RimSegmentCollection::intervals() const
|
|
|
|
|
{
|
|
|
|
|
return m_segmentIntervals.childrenByType();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
caf::PdmChildArrayField<RimSegmentInterval*>& RimSegmentCollection::intervalsField()
|
|
|
|
|
{
|
|
|
|
|
return m_segmentIntervals;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
RimSegmentInterval* RimSegmentCollection::createInterval( double startMD, double endMD, double diameter, double roughness )
|
|
|
|
|
{
|
|
|
|
|
auto* interval = new RimSegmentInterval;
|
|
|
|
|
interval->setStartMD( startMD );
|
|
|
|
|
interval->setEndMD( endMD );
|
|
|
|
|
interval->setDiameter( diameter );
|
|
|
|
|
interval->setRoughnessFactor( roughness );
|
|
|
|
|
addInterval( interval );
|
|
|
|
|
return interval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::addInterval( RimSegmentInterval* interval )
|
|
|
|
|
{
|
|
|
|
|
m_segmentIntervals.push_back( interval );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::removeInterval( RimSegmentInterval* interval )
|
|
|
|
|
{
|
|
|
|
|
m_segmentIntervals.removeChild( interval );
|
|
|
|
|
delete interval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::removeAllIntervals()
|
|
|
|
|
{
|
|
|
|
|
m_segmentIntervals.deleteChildren();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
bool RimSegmentCollection::hasIntervals() const
|
|
|
|
|
{
|
|
|
|
|
return !m_segmentIntervals.empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::updateOverlapVisualFeedback()
|
|
|
|
|
{
|
|
|
|
|
auto segmentIntervals = intervals();
|
|
|
|
|
for ( auto* interval : segmentIntervals )
|
|
|
|
|
{
|
|
|
|
|
bool hasOverlap = std::ranges::any_of( segmentIntervals,
|
|
|
|
|
[interval]( const RimSegmentInterval* other )
|
|
|
|
|
{ return interval != other && interval->overlaps( other ); } );
|
|
|
|
|
interval->updateOverlapVisualFeedback( hasOverlap );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
std::vector<std::pair<double, double>> RimSegmentCollection::getSegmentIntervals() const
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::pair<double, double>> result;
|
|
|
|
|
for ( auto* interval : intervals() )
|
|
|
|
|
{
|
|
|
|
|
if ( interval && interval->isValidInterval() ) result.emplace_back( interval->startMD(), interval->endMD() );
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-09 14:36:40 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
/// 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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
bool RimSegmentCollection::hasCustomSegmentIntervals() const
|
|
|
|
|
{
|
|
|
|
|
return hasIntervals();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::setUnitSystemSpecificDefaults()
|
|
|
|
|
{
|
|
|
|
|
auto* wellPath = firstAncestorOrThisOfTypeAsserted<RimWellPath>();
|
|
|
|
|
m_linerDiameter = defaultLinerDiameter( wellPath->unitSystem() );
|
|
|
|
|
m_roughnessFactor = defaultRoughnessFactor( wellPath->unitSystem() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::updateFromTopLevelWell( const RimSegmentCollection* topLevelWellParameters )
|
|
|
|
|
{
|
2026-10-09 14:36:40 +02:00
|
|
|
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();
|
2026-09-04 15:23:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::importLegacyData( const RimMswCompletionParameters* legacyParameters )
|
|
|
|
|
{
|
|
|
|
|
if ( !legacyParameters ) return;
|
|
|
|
|
|
|
|
|
|
const bool hasLegacyData = legacyParameters->referenceMDType() != RimMswCompletionParameters::ReferenceMDType::AUTO_REFERENCE_MD ||
|
|
|
|
|
legacyParameters->storedReferenceMD() != 0.0 || legacyParameters->customValuesForLateral() ||
|
|
|
|
|
legacyParameters->linerDiameter() != defaultLinerDiameter( RiaDefines::EclipseUnitSystem::UNITS_METRIC ) ||
|
|
|
|
|
legacyParameters->roughnessFactor() != defaultRoughnessFactor( RiaDefines::EclipseUnitSystem::UNITS_METRIC ) ||
|
|
|
|
|
legacyParameters->diameterRoughnessMode() != RimMswCompletionParameters::DiameterRoughnessMode::UNIFORM ||
|
|
|
|
|
legacyParameters->pressureDrop() != RimMswCompletionParameters::PressureDropType::HYDROSTATIC_FRICTION ||
|
|
|
|
|
legacyParameters->lengthAndDepth() != RimMswCompletionParameters::LengthAndDepthType::ABS ||
|
|
|
|
|
legacyParameters->enforceMaxSegmentLength() || legacyParameters->storedMaxSegmentLength() != 200.0 ||
|
|
|
|
|
!legacyParameters->diameterRoughnessIntervals()->intervals().empty() ||
|
|
|
|
|
!legacyParameters->customSegmentIntervals()->intervals().empty();
|
|
|
|
|
if ( !hasLegacyData ) return;
|
|
|
|
|
|
2026-09-11 14:26:31 +02:00
|
|
|
m_refMDType = static_cast<ReferenceMDType>( static_cast<int>( legacyParameters->referenceMDType() ) );
|
|
|
|
|
m_refMD = legacyParameters->storedReferenceMD();
|
|
|
|
|
m_customValuesForLateral = legacyParameters->customValuesForLateral();
|
|
|
|
|
m_linerDiameter = legacyParameters->linerDiameter();
|
|
|
|
|
m_roughnessFactor = legacyParameters->roughnessFactor();
|
|
|
|
|
m_pressureDrop = static_cast<PressureDropType>(
|
|
|
|
|
static_cast<int>( static_cast<RimMswCompletionParameters::PressureDropType>( legacyParameters->pressureDrop() ) ) );
|
|
|
|
|
m_lengthAndDepth = static_cast<LengthAndDepthType>(
|
2026-09-04 15:23:32 +02:00
|
|
|
static_cast<int>( static_cast<RimMswCompletionParameters::LengthAndDepthType>( legacyParameters->lengthAndDepth() ) ) );
|
|
|
|
|
m_enforceMaxSegmentLength = legacyParameters->enforceMaxSegmentLength();
|
|
|
|
|
m_maxSegmentLength = legacyParameters->storedMaxSegmentLength();
|
|
|
|
|
|
|
|
|
|
removeAllIntervals();
|
2026-09-11 14:26:31 +02:00
|
|
|
if ( legacyParameters->diameterRoughnessMode() == RimMswCompletionParameters::DiameterRoughnessMode::INTERVALS )
|
2026-09-04 15:23:32 +02:00
|
|
|
{
|
2026-09-11 14:26:31 +02:00
|
|
|
for ( auto* oldInterval : legacyParameters->diameterRoughnessIntervals()->intervals() )
|
|
|
|
|
{
|
|
|
|
|
auto* interval =
|
|
|
|
|
createInterval( oldInterval->startMD(), oldInterval->endMD(), oldInterval->diameter(), oldInterval->roughnessFactor() );
|
|
|
|
|
interval->enableCustomStartDate( oldInterval->useCustomStartDate() );
|
|
|
|
|
interval->setCustomStartDate( oldInterval->customStartDate() );
|
|
|
|
|
}
|
2026-09-04 15:23:32 +02:00
|
|
|
}
|
|
|
|
|
|
2026-09-11 14:26:31 +02:00
|
|
|
constexpr double boundTolerance = 1.0e-6;
|
2026-09-04 15:23:32 +02:00
|
|
|
for ( auto* oldInterval : legacyParameters->customSegmentIntervals()->intervals() )
|
|
|
|
|
{
|
|
|
|
|
const auto currentIntervals = intervals();
|
|
|
|
|
const auto matchingInterval =
|
|
|
|
|
std::ranges::find_if( currentIntervals,
|
|
|
|
|
[oldInterval]( const RimSegmentInterval* interval )
|
|
|
|
|
{
|
|
|
|
|
return std::abs( interval->startMD() - oldInterval->startMD() ) <= boundTolerance &&
|
|
|
|
|
std::abs( interval->endMD() - oldInterval->endMD() ) <= boundTolerance;
|
|
|
|
|
} );
|
|
|
|
|
if ( matchingInterval == currentIntervals.end() )
|
2026-09-11 14:26:31 +02:00
|
|
|
{
|
2026-09-04 15:23:32 +02:00
|
|
|
createInterval( oldInterval->startMD(), oldInterval->endMD(), legacyParameters->linerDiameter(), legacyParameters->roughnessFactor() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-09-11 14:26:31 +02:00
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::defaultLinerDiameter( RiaDefines::EclipseUnitSystem unitSystem )
|
|
|
|
|
{
|
|
|
|
|
return unitSystem == RiaDefines::EclipseUnitSystem::UNITS_METRIC ? 0.152 : 0.5;
|
|
|
|
|
}
|
2026-09-11 14:26:31 +02:00
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
double RimSegmentCollection::defaultRoughnessFactor( RiaDefines::EclipseUnitSystem unitSystem )
|
|
|
|
|
{
|
|
|
|
|
return unitSystem == RiaDefines::EclipseUnitSystem::UNITS_METRIC ? 1.0e-5 : 3.28e-5;
|
|
|
|
|
}
|
2026-09-11 14:26:31 +02:00
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
|
|
|
|
{
|
2026-09-11 14:26:31 +02:00
|
|
|
if ( changedField == &m_refMDType ) updateAllRequiredEditors();
|
2026-09-04 15:23:32 +02:00
|
|
|
if ( changedField == &m_enforceMaxSegmentLength )
|
|
|
|
|
{
|
|
|
|
|
m_maxSegmentLength.uiCapability()->setUiHidden( !m_enforceMaxSegmentLength() );
|
|
|
|
|
caf::PdmUiObjectEditorHandle::updateUiAllObjectEditors();
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-09-11 14:26:31 +02:00
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
|
|
|
|
|
{
|
2026-10-09 14:36:40 +02:00
|
|
|
menuBuilder << "RicCreateSegmentIntervalFeature";
|
2026-09-04 15:23:32 +02:00
|
|
|
if ( hasIntervals() ) menuBuilder << "RicDeleteSegmentIntervalFeature";
|
|
|
|
|
}
|
2026-09-11 14:26:31 +02:00
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
|
|
|
|
{
|
|
|
|
|
auto* wellPath = firstAncestorOrThisOfTypeAsserted<RimWellPath>();
|
|
|
|
|
const bool isMetric = wellPath->unitSystem() == RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
|
|
|
|
m_linerDiameter.uiCapability()->setUiName( isMetric ? "Liner Inner Diameter [m]" : "Liner Inner Diameter [ft]" );
|
|
|
|
|
m_roughnessFactor.uiCapability()->setUiName( isMetric ? "Roughness Factor [m]" : "Roughness Factor [ft]" );
|
|
|
|
|
|
|
|
|
|
if ( wellPath->isTopLevelWellPath() )
|
|
|
|
|
{
|
|
|
|
|
uiOrdering.add( &m_refMDType );
|
|
|
|
|
uiOrdering.add( &m_refMD );
|
|
|
|
|
m_refMD.uiCapability()->setUiHidden( m_refMDType == ReferenceMDType::AUTO_REFERENCE_MD );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uiOrdering.add( &m_customValuesForLateral );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto* diameterGroup = uiOrdering.addNewGroup( "Diameter and Roughness" );
|
2026-09-11 14:26:31 +02:00
|
|
|
diameterGroup->add( &m_linerDiameter );
|
|
|
|
|
diameterGroup->add( &m_roughnessFactor );
|
2026-09-04 15:23:32 +02:00
|
|
|
|
|
|
|
|
if ( wellPath->isTopLevelWellPath() )
|
|
|
|
|
{
|
|
|
|
|
uiOrdering.add( &m_pressureDrop );
|
|
|
|
|
uiOrdering.add( &m_lengthAndDepth );
|
2026-10-09 14:36:40 +02:00
|
|
|
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 );
|
2026-09-04 15:23:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool readOnly = !wellPath->isTopLevelWellPath() && !m_customValuesForLateral();
|
|
|
|
|
m_linerDiameter.uiCapability()->setUiReadOnly( readOnly );
|
|
|
|
|
m_roughnessFactor.uiCapability()->setUiReadOnly( readOnly );
|
|
|
|
|
m_segmentIntervals.uiCapability()->setUiReadOnly( readOnly );
|
|
|
|
|
uiOrdering.skipRemainingFields( true );
|
|
|
|
|
}
|
2026-09-11 14:26:31 +02:00
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
|
|
|
|
{
|
|
|
|
|
for ( auto* interval : intervals() )
|
|
|
|
|
uiTreeOrdering.add( interval );
|
|
|
|
|
uiTreeOrdering.skipRemainingChildren( true );
|
|
|
|
|
}
|
2026-09-11 14:26:31 +02:00
|
|
|
|
2026-09-04 15:23:32 +02:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
///
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
void RimSegmentCollection::initAfterRead()
|
|
|
|
|
{
|
|
|
|
|
if ( m_linerDiameter() == std::numeric_limits<double>::infinity() && m_roughnessFactor() == std::numeric_limits<double>::infinity() )
|
|
|
|
|
setUnitSystemSpecificDefaults();
|
|
|
|
|
}
|