mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 06:38:13 -05:00
#12718 Add diameter and roughness specification for MD intervals
Implements interval-based diameter and roughness configuration for MSW completions while maintaining backward compatibility with existing single-value approach. - Add RimDiameterRoughnessInterval class for individual MD intervals - Add RimDiameterRoughnessIntervalCollection for managing interval collections - Extend RimMswCompletionParameters with interval-specific mode support - Support both metric and field unit systems - Provide validation and overlap detection for intervals
This commit is contained in:
1 parent
79c2c792f4
commit
b0483172b1
18 files changed
+1742
-16
No files matched your search
@@ -13,6 +13,8 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewStimPlanModelPlotFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicImportEnsembleFractureStatisticsFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicImportValveTemplatesFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewDiameterRoughnessIntervalFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicDeleteDiameterRoughnessIntervalFeature.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -30,6 +32,8 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewStimPlanModelPlotFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicImportEnsembleFractureStatisticsFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicImportValveTemplatesFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewDiameterRoughnessIntervalFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicDeleteDiameterRoughnessIntervalFeature.cpp
|
||||
)
|
||||
|
||||
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RicDeleteDiameterRoughnessIntervalFeature.h"
|
||||
|
||||
#include "RimDiameterRoughnessInterval.h"
|
||||
#include "RimDiameterRoughnessIntervalCollection.h"
|
||||
#include "RimMswCompletionParameters.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPathCompletionSettings.h"
|
||||
|
||||
#include "Riu3DMainWindowTools.h"
|
||||
|
||||
#include "cafSelectionManager.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicDeleteDiameterRoughnessIntervalFeature, "RicDeleteDiameterRoughnessIntervalFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicDeleteDiameterRoughnessIntervalFeature::isCommandEnabled() const
|
||||
{
|
||||
if ( caf::SelectionManager::instance()->selectedItemOfType<RimDiameterRoughnessInterval>( caf::SelectionManager::FIRST_LEVEL ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( auto collection = caf::SelectionManager::instance()->selectedItemOfType<RimDiameterRoughnessIntervalCollection>() )
|
||||
{
|
||||
return collection && !collection->intervals().empty();
|
||||
}
|
||||
|
||||
if ( auto mswParams = caf::SelectionManager::instance()->selectedItemOfType<RimMswCompletionParameters>() )
|
||||
{
|
||||
if ( mswParams->diameterRoughnessIntervals() )
|
||||
{
|
||||
return !mswParams->diameterRoughnessIntervals()->intervals().empty();
|
||||
}
|
||||
}
|
||||
|
||||
if ( auto completionSettings = caf::SelectionManager::instance()->selectedItemOfType<RimWellPathCompletionSettings>() )
|
||||
{
|
||||
if ( auto wellPath = completionSettings->firstAncestorOrThisOfType<RimWellPath>() )
|
||||
{
|
||||
auto mswParams = wellPath->mswCompletionParameters();
|
||||
if ( mswParams && mswParams->diameterRoughnessIntervals() )
|
||||
{
|
||||
return !mswParams->diameterRoughnessIntervals()->intervals().empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicDeleteDiameterRoughnessIntervalFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
const auto intervals = caf::SelectionManager::instance()->objectsByType<RimDiameterRoughnessInterval>( caf::SelectionManager::FIRST_LEVEL );
|
||||
RimDiameterRoughnessIntervalCollection* intervalCollection = nullptr;
|
||||
|
||||
if ( !intervals.empty() )
|
||||
{
|
||||
// Delete selected intervals
|
||||
intervalCollection = intervals[0]->firstAncestorOrThisOfTypeAsserted<RimDiameterRoughnessIntervalCollection>();
|
||||
for ( RimDiameterRoughnessInterval* intervalToDelete : intervals )
|
||||
{
|
||||
intervalCollection->removeInterval( intervalToDelete );
|
||||
}
|
||||
intervalCollection->updateConnectedEditors();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delete all intervals in collection
|
||||
intervalCollection = caf::SelectionManager::instance()->selectedItemOfType<RimDiameterRoughnessIntervalCollection>();
|
||||
if ( !intervalCollection )
|
||||
{
|
||||
// Handle selection of MSW completion parameters
|
||||
auto mswParams = caf::SelectionManager::instance()->selectedItemOfType<RimMswCompletionParameters>();
|
||||
if ( mswParams && mswParams->diameterRoughnessIntervals() )
|
||||
{
|
||||
intervalCollection = mswParams->diameterRoughnessIntervals();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle selection of well path completion settings
|
||||
if ( auto completionSettings = caf::SelectionManager::instance()->selectedItemOfType<RimWellPathCompletionSettings>() )
|
||||
{
|
||||
if ( auto wellPath = completionSettings->firstAncestorOrThisOfType<RimWellPath>() )
|
||||
{
|
||||
auto mswParams = wellPath->mswCompletionParameters();
|
||||
if ( mswParams && mswParams->diameterRoughnessIntervals() )
|
||||
{
|
||||
intervalCollection = mswParams->diameterRoughnessIntervals();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( intervalCollection )
|
||||
{
|
||||
intervalCollection->removeAllIntervals();
|
||||
intervalCollection->updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
|
||||
if ( intervalCollection )
|
||||
{
|
||||
if ( intervalCollection->intervals().empty() )
|
||||
{
|
||||
Riu3DMainWindowTools::selectAsCurrentItem( intervalCollection );
|
||||
}
|
||||
|
||||
if ( RimProject* proj = RimProject::current() )
|
||||
{
|
||||
proj->scheduleCreateDisplayModelAndRedrawAllViews();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicDeleteDiameterRoughnessIntervalFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
const auto intervals = caf::SelectionManager::instance()->objectsByType<RimDiameterRoughnessInterval>( caf::SelectionManager::FIRST_LEVEL );
|
||||
if ( !intervals.empty() )
|
||||
{
|
||||
if ( intervals.size() == 1 )
|
||||
{
|
||||
actionToSetup->setText( "Delete Interval" );
|
||||
}
|
||||
else
|
||||
{
|
||||
actionToSetup->setText( QString( "Delete %1 Intervals" ).arg( intervals.size() ) );
|
||||
}
|
||||
actionToSetup->setIcon( QIcon( ":/Erase.svg" ) );
|
||||
applyShortcutWithHintToAction( actionToSetup, QKeySequence::Delete );
|
||||
}
|
||||
else if ( caf::SelectionManager::instance()->selectedItemOfType<RimDiameterRoughnessIntervalCollection>() ||
|
||||
caf::SelectionManager::instance()->selectedItemOfType<RimMswCompletionParameters>() ||
|
||||
caf::SelectionManager::instance()->selectedItemOfType<RimWellPathCompletionSettings>() )
|
||||
{
|
||||
actionToSetup->setText( "Delete All Intervals" );
|
||||
actionToSetup->setIcon( QIcon( ":/Erase.svg" ) );
|
||||
applyShortcutWithHintToAction( actionToSetup, QKeySequence::Delete );
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "cafCmdFeature.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicDeleteDiameterRoughnessIntervalFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
protected:
|
||||
bool isCommandEnabled() const override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
};
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RicNewDiameterRoughnessIntervalFeature.h"
|
||||
|
||||
#include "RimDiameterRoughnessInterval.h"
|
||||
#include "RimDiameterRoughnessIntervalCollection.h"
|
||||
#include "RimMswCompletionParameters.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPathCompletionSettings.h"
|
||||
|
||||
#include "Riu3DMainWindowTools.h"
|
||||
|
||||
#include "cafSelectionManager.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicNewDiameterRoughnessIntervalFeature, "RicNewDiameterRoughnessIntervalFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicNewDiameterRoughnessIntervalFeature::isCommandEnabled() const
|
||||
{
|
||||
return ( caf::SelectionManager::instance()->selectedItemOfType<RimDiameterRoughnessIntervalCollection>() ||
|
||||
caf::SelectionManager::instance()->selectedItemOfType<RimMswCompletionParameters>() ||
|
||||
caf::SelectionManager::instance()->selectedItemOfType<RimWellPathCompletionSettings>() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewDiameterRoughnessIntervalFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
// Try to get collection directly
|
||||
RimDiameterRoughnessIntervalCollection* intervalCollection =
|
||||
caf::SelectionManager::instance()->selectedItemOfType<RimDiameterRoughnessIntervalCollection>();
|
||||
|
||||
// If not found, try to get it from MSW completion parameters
|
||||
if ( !intervalCollection )
|
||||
{
|
||||
if ( auto mswParams = caf::SelectionManager::instance()->selectedItemOfType<RimMswCompletionParameters>() )
|
||||
{
|
||||
intervalCollection = mswParams->diameterRoughnessIntervals();
|
||||
}
|
||||
}
|
||||
|
||||
// If still not found, try to get it from well path completion settings
|
||||
if ( !intervalCollection )
|
||||
{
|
||||
if ( auto completionSettings = caf::SelectionManager::instance()->selectedItemOfType<RimWellPathCompletionSettings>() )
|
||||
{
|
||||
if ( auto wellPath = completionSettings->firstAncestorOrThisOfType<RimWellPath>() )
|
||||
{
|
||||
if ( auto mswParams = wellPath->mswCompletionParameters() )
|
||||
{
|
||||
intervalCollection = mswParams->diameterRoughnessIntervals();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( intervalCollection )
|
||||
{
|
||||
RimDiameterRoughnessInterval* newInterval = new RimDiameterRoughnessInterval;
|
||||
|
||||
// Set default values
|
||||
if ( auto wellPath = intervalCollection->firstAncestorOrThisOfType<RimWellPath>() )
|
||||
{
|
||||
if ( auto mswParams = wellPath->mswCompletionParameters() )
|
||||
{
|
||||
newInterval->setStartMD( 0 );
|
||||
newInterval->setEndMD( 2000 );
|
||||
newInterval->setDiameter( mswParams->linerDiameter() );
|
||||
newInterval->setRoughnessFactor( mswParams->roughnessFactor() );
|
||||
}
|
||||
}
|
||||
|
||||
intervalCollection->addInterval( newInterval );
|
||||
intervalCollection->updateConnectedEditors();
|
||||
|
||||
Riu3DMainWindowTools::selectAsCurrentItem( newInterval );
|
||||
|
||||
if ( RimProject* project = RimProject::current() )
|
||||
{
|
||||
project->scheduleCreateDisplayModelAndRedrawAllViews();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewDiameterRoughnessIntervalFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
actionToSetup->setText( "New Interval" );
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "cafCmdFeature.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicNewDiameterRoughnessIntervalFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
protected:
|
||||
bool isCommandEnabled() const override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
};
|
||||
@@ -736,9 +736,6 @@ void RicMswTableFormatterTools::writeWelsegsSegment( RicMswSegment*
|
||||
prevOutTVD = previousSegment->outputTVD();
|
||||
}
|
||||
|
||||
const auto linerDiameter = branch->wellPath()->mswCompletionParameters()->linerDiameter( exportInfo.unitSystem() );
|
||||
const auto roughnessFactor = branch->wellPath()->mswCompletionParameters()->roughnessFactor( exportInfo.unitSystem() );
|
||||
|
||||
auto outletSegment = previousSegment;
|
||||
for ( const auto& [subStartMD, subEndMD] : segments )
|
||||
{
|
||||
@@ -770,6 +767,9 @@ void RicMswTableFormatterTools::writeWelsegsSegment( RicMswSegment*
|
||||
segment->setOutputTVD( midPointTVD );
|
||||
segment->setSegmentNumber( *segmentNumber );
|
||||
|
||||
const auto linerDiameter = branch->wellPath()->mswCompletionParameters()->getDiameterAtMD( midPointMD, exportInfo.unitSystem() );
|
||||
const auto roughnessFactor = branch->wellPath()->mswCompletionParameters()->getRoughnessAtMD( midPointMD, exportInfo.unitSystem() );
|
||||
|
||||
formatter.add( *segmentNumber ).add( *segmentNumber );
|
||||
formatter.add( branch->branchNumber() );
|
||||
if ( outletSegment )
|
||||
|
||||
@@ -32,6 +32,8 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellPathValve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimMultipleValveLocations.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellPathAicdParameters.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDiameterRoughnessInterval.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDiameterRoughnessIntervalCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleFractureStatistics.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleFractureStatisticsCollection.h
|
||||
)
|
||||
@@ -67,6 +69,8 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellPathValve.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimMultipleValveLocations.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellPathAicdParameters.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDiameterRoughnessInterval.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDiameterRoughnessIntervalCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleFractureStatistics.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleFractureStatisticsCollection.cpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimDiameterRoughnessInterval.h"
|
||||
|
||||
#include "RiaApplication.h"
|
||||
#include "RiaEclipseUnitTools.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RimDiameterRoughnessIntervalCollection.h"
|
||||
#include "RimMswCompletionParameters.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiDoubleSliderEditor.h"
|
||||
#include "cafPdmUiDoubleValueEditor.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimDiameterRoughnessInterval, "DiameterRoughnessInterval" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDiameterRoughnessInterval::RimDiameterRoughnessInterval()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Diameter Roughness Interval", ":/WellPathComponent16x16.png", "", "DiameterRoughnessInterval" );
|
||||
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,
|
||||
"Diameter",
|
||||
RimMswCompletionParameters::defaultLinerDiameter( RiaDefines::EclipseUnitSystem::UNITS_METRIC ),
|
||||
"Diameter" );
|
||||
CAF_PDM_InitScriptableField( &m_roughnessFactor,
|
||||
"RoughnessFactor",
|
||||
RimMswCompletionParameters::defaultRoughnessFactor( RiaDefines::EclipseUnitSystem::UNITS_METRIC ),
|
||||
"Roughness Factor" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDiameterRoughnessInterval::~RimDiameterRoughnessInterval()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessInterval::startMD() const
|
||||
{
|
||||
return m_startMD;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessInterval::endMD() const
|
||||
{
|
||||
return m_endMD;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessInterval::diameter() const
|
||||
{
|
||||
return m_diameter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessInterval::diameter( RiaDefines::EclipseUnitSystem unitSystem ) const
|
||||
{
|
||||
if ( unitSystem == RiaDefines::EclipseUnitSystem::UNITS_FIELD )
|
||||
{
|
||||
return RiaEclipseUnitTools::meterToInch( m_diameter );
|
||||
}
|
||||
return m_diameter; // METRIC units - already in meters
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessInterval::roughnessFactor() const
|
||||
{
|
||||
return m_roughnessFactor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessInterval::roughnessFactor( RiaDefines::EclipseUnitSystem unitSystem ) const
|
||||
{
|
||||
if ( unitSystem == RiaDefines::EclipseUnitSystem::UNITS_FIELD )
|
||||
{
|
||||
return RiaEclipseUnitTools::meterToFeet( m_roughnessFactor );
|
||||
}
|
||||
return m_roughnessFactor; // METRIC units - already in meters
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessInterval::setStartMD( double startMD )
|
||||
{
|
||||
m_startMD = startMD;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessInterval::setEndMD( double endMD )
|
||||
{
|
||||
m_endMD = endMD;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessInterval::setDiameter( double diameter )
|
||||
{
|
||||
m_diameter = diameter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessInterval::setRoughnessFactor( double roughness )
|
||||
{
|
||||
m_roughnessFactor = roughness;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDiameterRoughnessInterval::isValidInterval() const
|
||||
{
|
||||
return m_endMD > m_startMD && m_diameter > 0.0 && m_roughnessFactor >= 0.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDiameterRoughnessInterval::overlaps( const RimDiameterRoughnessInterval* other ) const
|
||||
{
|
||||
if ( !other ) return false;
|
||||
|
||||
return m_endMD > other->startMD() && m_startMD < other->endMD();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDiameterRoughnessInterval::containsMD( double md ) const
|
||||
{
|
||||
return md >= m_startMD && md <= m_endMD;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimDiameterRoughnessInterval::diameterLabel() const
|
||||
{
|
||||
return QString( "%1 m" ).arg( m_diameter, 0, 'f', 3 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimDiameterRoughnessInterval::roughnessLabel() const
|
||||
{
|
||||
return QString( "%1 m" ).arg( m_roughnessFactor, 0, 'e', 2 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDiameterRoughnessInterval::operator<( const RimDiameterRoughnessInterval& rhs ) const
|
||||
{
|
||||
return m_startMD < rhs.m_startMD;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDiameterRoughnessInterval::isEnabled() const
|
||||
{
|
||||
return true; // Always enabled for now
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::WellPathComponentType RimDiameterRoughnessInterval::componentType() const
|
||||
{
|
||||
return RiaDefines::WellPathComponentType::CASING;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimDiameterRoughnessInterval::componentLabel() const
|
||||
{
|
||||
return generateDisplayLabel();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimDiameterRoughnessInterval::componentTypeLabel() const
|
||||
{
|
||||
return "Diameter/Roughness";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::Color3f RimDiameterRoughnessInterval::defaultComponentColor() const
|
||||
{
|
||||
return cvf::Color3f( 0.6f, 0.4f, 0.2f ); // Brown color for diameter/roughness intervals
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessInterval::applyOffset( double offsetMD )
|
||||
{
|
||||
m_startMD = m_startMD + offsetMD;
|
||||
m_endMD = m_endMD + offsetMD;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessInterval::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_startMD || changedField == &m_endMD )
|
||||
{
|
||||
// Validate interval
|
||||
if ( m_startMD >= m_endMD )
|
||||
{
|
||||
RiaLogging::warning( "Invalid interval: Start MD must be less than End MD" );
|
||||
}
|
||||
|
||||
// Update overlap visual feedback in parent collection
|
||||
auto* collection = firstAncestorOrThisOfType<RimDiameterRoughnessIntervalCollection>();
|
||||
if ( collection )
|
||||
{
|
||||
collection->updateOverlapVisualFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessInterval::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_startMD );
|
||||
uiOrdering.add( &m_endMD );
|
||||
uiOrdering.add( &m_diameter );
|
||||
uiOrdering.add( &m_roughnessFactor );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessInterval::updateConnectedEditors()
|
||||
{
|
||||
// Update any connected UI editors
|
||||
m_startMD.uiCapability()->updateConnectedEditors();
|
||||
m_endMD.uiCapability()->updateConnectedEditors();
|
||||
m_diameter.uiCapability()->updateConnectedEditors();
|
||||
m_roughnessFactor.uiCapability()->updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimDiameterRoughnessInterval::generateDisplayLabel() const
|
||||
{
|
||||
return QString( "MD %.1f-%.1f: D=%.3fm, R=%1em" ).arg( m_startMD ).arg( m_endMD ).arg( m_diameter ).arg( m_roughnessFactor );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessInterval::defaultDiameter( RiaDefines::EclipseUnitSystem unitSystem )
|
||||
{
|
||||
return RimMswCompletionParameters::defaultLinerDiameter( unitSystem );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessInterval::defaultRoughness( RiaDefines::EclipseUnitSystem unitSystem )
|
||||
{
|
||||
return RimMswCompletionParameters::defaultRoughnessFactor( unitSystem );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessInterval::updateOverlapVisualFeedback( bool hasOverlap )
|
||||
{
|
||||
if ( hasOverlap )
|
||||
{
|
||||
// Set red color for overlapping fields
|
||||
m_startMD.uiCapability()->setUiContentTextColor( Qt::red );
|
||||
m_endMD.uiCapability()->setUiContentTextColor( Qt::red );
|
||||
|
||||
// Create tooltip with overlap information
|
||||
QString tooltip = "This interval overlaps with another interval!";
|
||||
|
||||
m_startMD.uiCapability()->setUiToolTip( tooltip );
|
||||
m_endMD.uiCapability()->setUiToolTip( tooltip );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset color and tooltip
|
||||
m_startMD.uiCapability()->setUiContentTextColor( QColor() );
|
||||
m_endMD.uiCapability()->setUiContentTextColor( QColor() );
|
||||
m_startMD.uiCapability()->setUiToolTip( "" );
|
||||
m_endMD.uiCapability()->setUiToolTip( "" );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RiaDefines.h"
|
||||
#include "RimWellPathComponentInterface.h"
|
||||
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
class RimWellPath;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Represents a diameter and roughness interval for a specific measured depth range
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimDiameterRoughnessInterval : public caf::PdmObject, public RimWellPathComponentInterface
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimDiameterRoughnessInterval();
|
||||
~RimDiameterRoughnessInterval() override;
|
||||
|
||||
// Getters
|
||||
double startMD() const override;
|
||||
double endMD() const override;
|
||||
double diameter() const;
|
||||
double diameter( RiaDefines::EclipseUnitSystem unitSystem ) const;
|
||||
double roughnessFactor() const;
|
||||
double roughnessFactor( RiaDefines::EclipseUnitSystem unitSystem ) const;
|
||||
|
||||
// Setters
|
||||
void setStartMD( double startMD );
|
||||
void setEndMD( double endMD );
|
||||
void setDiameter( double diameter );
|
||||
void setRoughnessFactor( double roughness );
|
||||
|
||||
// Validation
|
||||
bool isValidInterval() const;
|
||||
bool overlaps( const RimDiameterRoughnessInterval* other ) const;
|
||||
bool containsMD( double md ) const;
|
||||
|
||||
// Display
|
||||
QString diameterLabel() const;
|
||||
QString roughnessLabel() const;
|
||||
|
||||
// Comparison for sorting
|
||||
bool operator<( const RimDiameterRoughnessInterval& rhs ) const;
|
||||
|
||||
// Overrides from RimWellPathComponentInterface
|
||||
bool isEnabled() const override;
|
||||
RiaDefines::WellPathComponentType componentType() const override;
|
||||
QString componentLabel() const override;
|
||||
QString componentTypeLabel() const override;
|
||||
cvf::Color3f defaultComponentColor() const override;
|
||||
void applyOffset( double offsetMD ) override;
|
||||
|
||||
// Public static methods for default values
|
||||
static double defaultDiameter( RiaDefines::EclipseUnitSystem unitSystem );
|
||||
static double defaultRoughness( RiaDefines::EclipseUnitSystem unitSystem );
|
||||
|
||||
// Visual feedback for overlapping intervals
|
||||
void updateOverlapVisualFeedback( bool hasOverlap );
|
||||
|
||||
protected:
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
private:
|
||||
void updateConnectedEditors();
|
||||
QString generateDisplayLabel() const;
|
||||
|
||||
private:
|
||||
caf::PdmField<double> m_startMD;
|
||||
caf::PdmField<double> m_endMD;
|
||||
caf::PdmField<double> m_diameter;
|
||||
caf::PdmField<double> m_roughnessFactor;
|
||||
};
|
||||
+479
@@ -0,0 +1,479 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimDiameterRoughnessIntervalCollection.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
#include "RimDiameterRoughnessInterval.h"
|
||||
#include "RimMswCompletionParameters.h"
|
||||
|
||||
#include "cafCmdFeatureMenuBuilder.h"
|
||||
#include "cafPdmUiTableViewEditor.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimDiameterRoughnessIntervalCollection, "DiameterRoughnessIntervalCollection" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDiameterRoughnessIntervalCollection::RimDiameterRoughnessIntervalCollection()
|
||||
{
|
||||
CAF_PDM_InitObject( "Diameter Roughness Intervals", ":/WellPathComponent16x16.png" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_intervals, "Intervals", "Intervals" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDiameterRoughnessIntervalCollection::~RimDiameterRoughnessIntervalCollection()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimDiameterRoughnessInterval*> RimDiameterRoughnessIntervalCollection::intervals() const
|
||||
{
|
||||
return m_intervals.childrenByType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::addInterval( RimDiameterRoughnessInterval* interval )
|
||||
{
|
||||
if ( interval )
|
||||
{
|
||||
m_intervals.push_back( interval );
|
||||
sortIntervalsByMD();
|
||||
updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::removeInterval( RimDiameterRoughnessInterval* interval )
|
||||
{
|
||||
if ( interval )
|
||||
{
|
||||
m_intervals.removeChild( interval );
|
||||
delete interval;
|
||||
updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::removeAllIntervals()
|
||||
{
|
||||
m_intervals.deleteChildren();
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDiameterRoughnessInterval*
|
||||
RimDiameterRoughnessIntervalCollection::createInterval( double startMD, double endMD, double diameter, double roughness )
|
||||
{
|
||||
auto* interval = new RimDiameterRoughnessInterval();
|
||||
interval->setStartMD( startMD );
|
||||
interval->setEndMD( endMD );
|
||||
interval->setDiameter( diameter );
|
||||
interval->setRoughnessFactor( roughness );
|
||||
|
||||
addInterval( interval );
|
||||
return interval;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDiameterRoughnessInterval* RimDiameterRoughnessIntervalCollection::createDefaultInterval()
|
||||
{
|
||||
auto* interval = new RimDiameterRoughnessInterval();
|
||||
addInterval( interval );
|
||||
return interval;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessIntervalCollection::getDiameterAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const
|
||||
{
|
||||
auto* interval = findIntervalAtMD( md );
|
||||
if ( interval )
|
||||
{
|
||||
return interval->diameter( unitSystem );
|
||||
}
|
||||
|
||||
// Return default if no interval found
|
||||
return RimMswCompletionParameters::defaultLinerDiameter( unitSystem );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimDiameterRoughnessIntervalCollection::getRoughnessAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const
|
||||
{
|
||||
auto* interval = findIntervalAtMD( md );
|
||||
if ( interval )
|
||||
{
|
||||
return interval->roughnessFactor( unitSystem );
|
||||
}
|
||||
|
||||
// Return default if no interval found
|
||||
return RimMswCompletionParameters::defaultRoughnessFactor( unitSystem );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDiameterRoughnessInterval* RimDiameterRoughnessIntervalCollection::findIntervalAtMD( double md ) const
|
||||
{
|
||||
for ( auto* interval : intervals() )
|
||||
{
|
||||
if ( interval && interval->containsMD( md ) )
|
||||
{
|
||||
return interval;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDiameterRoughnessIntervalCollection::hasValidIntervals() const
|
||||
{
|
||||
if ( isEmpty() ) return false;
|
||||
|
||||
for ( auto* interval : intervals() )
|
||||
{
|
||||
if ( !interval || !interval->isValidInterval() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDiameterRoughnessIntervalCollection::hasOverlappingIntervals() const
|
||||
{
|
||||
auto intervalList = intervals();
|
||||
|
||||
for ( size_t i = 0; i < intervalList.size(); ++i )
|
||||
{
|
||||
for ( size_t j = i + 1; j < intervalList.size(); ++j )
|
||||
{
|
||||
if ( intervalList[i]->overlaps( intervalList[j] ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDiameterRoughnessIntervalCollection::coversFullRange( double startMD, double endMD ) const
|
||||
{
|
||||
if ( isEmpty() ) return false;
|
||||
|
||||
auto intervalList = intervals();
|
||||
std::sort( intervalList.begin(),
|
||||
intervalList.end(),
|
||||
[]( const RimDiameterRoughnessInterval* a, const RimDiameterRoughnessInterval* b ) { return a->startMD() < b->startMD(); } );
|
||||
|
||||
double currentPos = startMD;
|
||||
for ( auto* interval : intervalList )
|
||||
{
|
||||
if ( interval->startMD() > currentPos + 1e-6 ) // Allow small gap tolerance
|
||||
{
|
||||
return false; // Gap found
|
||||
}
|
||||
currentPos = std::max( currentPos, interval->endMD() );
|
||||
}
|
||||
|
||||
return currentPos >= endMD - 1e-6; // Allow small tolerance
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<QString> RimDiameterRoughnessIntervalCollection::validateIntervals() const
|
||||
{
|
||||
std::vector<QString> issues;
|
||||
|
||||
if ( isEmpty() )
|
||||
{
|
||||
issues.push_back( "No intervals defined" );
|
||||
return issues;
|
||||
}
|
||||
|
||||
auto intervalList = intervals();
|
||||
|
||||
// Check for invalid intervals
|
||||
for ( auto* interval : intervalList )
|
||||
{
|
||||
if ( !interval->isValidInterval() )
|
||||
{
|
||||
issues.push_back( QString( "Invalid interval: MD %.1f-%.1f" ).arg( interval->startMD() ).arg( interval->endMD() ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Check for overlaps
|
||||
for ( size_t i = 0; i < intervalList.size(); ++i )
|
||||
{
|
||||
for ( size_t j = i + 1; j < intervalList.size(); ++j )
|
||||
{
|
||||
if ( intervalList[i]->overlaps( intervalList[j] ) )
|
||||
{
|
||||
issues.push_back( QString( "Overlapping intervals: MD %.1f-%.1f and MD %.1f-%.1f" )
|
||||
.arg( intervalList[i]->startMD() )
|
||||
.arg( intervalList[i]->endMD() )
|
||||
.arg( intervalList[j]->startMD() )
|
||||
.arg( intervalList[j]->endMD() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::sortIntervalsByMD()
|
||||
{
|
||||
auto intervalList = intervals();
|
||||
std::sort( intervalList.begin(),
|
||||
intervalList.end(),
|
||||
[]( const RimDiameterRoughnessInterval* a, const RimDiameterRoughnessInterval* b ) { return *a < *b; } );
|
||||
|
||||
// Rebuild the collection in sorted order
|
||||
m_intervals.clearWithoutDelete();
|
||||
for ( auto* interval : intervalList )
|
||||
{
|
||||
m_intervals.push_back( interval );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::mergeAdjacentIntervals()
|
||||
{
|
||||
sortIntervalsByMD();
|
||||
|
||||
auto intervalList = intervals();
|
||||
std::vector<RimDiameterRoughnessInterval*> mergedIntervals;
|
||||
|
||||
for ( auto* interval : intervalList )
|
||||
{
|
||||
if ( mergedIntervals.empty() )
|
||||
{
|
||||
mergedIntervals.push_back( interval );
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* lastInterval = mergedIntervals.back();
|
||||
|
||||
// Check if intervals are adjacent and have same properties
|
||||
if ( std::abs( lastInterval->endMD() - interval->startMD() ) < 1e-6 &&
|
||||
std::abs( lastInterval->diameter() - interval->diameter() ) < 1e-6 &&
|
||||
std::abs( lastInterval->roughnessFactor() - interval->roughnessFactor() ) < 1e-6 )
|
||||
{
|
||||
// Merge intervals
|
||||
lastInterval->setEndMD( interval->endMD() );
|
||||
delete interval;
|
||||
}
|
||||
else
|
||||
{
|
||||
mergedIntervals.push_back( interval );
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild collection with merged intervals
|
||||
m_intervals.clearWithoutDelete();
|
||||
for ( auto* interval : mergedIntervals )
|
||||
{
|
||||
m_intervals.push_back( interval );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDiameterRoughnessIntervalCollection::isEmpty() const
|
||||
{
|
||||
return m_intervals.empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RimDiameterRoughnessIntervalCollection::count() const
|
||||
{
|
||||
return m_intervals.size();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::updateConnectedEditors()
|
||||
{
|
||||
m_intervals.uiCapability()->updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmChildArrayField<RimDiameterRoughnessInterval*>& RimDiameterRoughnessIntervalCollection::intervalsField()
|
||||
{
|
||||
return m_intervals;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::updateOverlapVisualFeedback()
|
||||
{
|
||||
auto intervalList = intervals();
|
||||
|
||||
// First, reset all intervals to no overlap
|
||||
for ( auto* interval : intervalList )
|
||||
{
|
||||
interval->updateOverlapVisualFeedback( false );
|
||||
}
|
||||
|
||||
// Then check for overlaps and update visual feedback
|
||||
for ( size_t i = 0; i < intervalList.size(); ++i )
|
||||
{
|
||||
bool hasOverlap = false;
|
||||
|
||||
for ( size_t j = 0; j < intervalList.size(); ++j )
|
||||
{
|
||||
if ( i != j && intervalList[i]->overlaps( intervalList[j] ) )
|
||||
{
|
||||
hasOverlap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( hasOverlap )
|
||||
{
|
||||
intervalList[i]->updateOverlapVisualFeedback( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_intervals )
|
||||
{
|
||||
sortIntervalsByMD();
|
||||
updateOverlapVisualFeedback();
|
||||
}
|
||||
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_intervals );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
if ( field == &m_intervals )
|
||||
{
|
||||
auto tvAttribute = dynamic_cast<caf::PdmUiTableViewEditorAttribute*>( attribute );
|
||||
if ( tvAttribute )
|
||||
{
|
||||
tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FILL_CONTAINER;
|
||||
tvAttribute->alwaysEnforceResizePolicy = true;
|
||||
tvAttribute->minimumHeight = 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
|
||||
std::vector<caf::PdmObjectHandle*>& referringObjects )
|
||||
{
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu,
|
||||
QMenu* menu,
|
||||
QWidget* fieldEditorWidget )
|
||||
{
|
||||
caf::CmdFeatureMenuBuilder menuBuilder;
|
||||
|
||||
menuBuilder << "RicNewDiameterRoughnessIntervalFeature";
|
||||
menuBuilder << "Separator";
|
||||
menuBuilder << "RicDeleteDiameterRoughnessIntervalFeature";
|
||||
|
||||
menuBuilder.appendToMenu( menu );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDiameterRoughnessIntervalCollection::insertInterval( RimDiameterRoughnessInterval* insertBefore, RimDiameterRoughnessInterval* interval )
|
||||
{
|
||||
if ( !interval ) return;
|
||||
|
||||
size_t index = m_intervals.indexOf( insertBefore );
|
||||
if ( index < m_intervals.size() )
|
||||
m_intervals.insert( index, interval );
|
||||
else
|
||||
m_intervals.push_back( interval );
|
||||
|
||||
sortIntervalsByMD();
|
||||
updateConnectedEditors();
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RiaDefines.h"
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimDiameterRoughnessInterval;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Collection to manage diameter and roughness intervals for measured depth ranges
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimDiameterRoughnessIntervalCollection : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimDiameterRoughnessIntervalCollection();
|
||||
~RimDiameterRoughnessIntervalCollection() override;
|
||||
|
||||
// Collection management
|
||||
std::vector<RimDiameterRoughnessInterval*> intervals() const;
|
||||
void addInterval( RimDiameterRoughnessInterval* interval );
|
||||
void insertInterval( RimDiameterRoughnessInterval* insertBefore, RimDiameterRoughnessInterval* interval );
|
||||
void removeInterval( RimDiameterRoughnessInterval* interval );
|
||||
void removeAllIntervals();
|
||||
|
||||
// Interval creation
|
||||
RimDiameterRoughnessInterval* createInterval( double startMD, double endMD, double diameter, double roughness );
|
||||
RimDiameterRoughnessInterval* createDefaultInterval();
|
||||
|
||||
// Lookup methods
|
||||
double getDiameterAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const;
|
||||
double getRoughnessAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const;
|
||||
RimDiameterRoughnessInterval* findIntervalAtMD( double md ) const;
|
||||
|
||||
// Validation
|
||||
bool hasValidIntervals() const;
|
||||
bool hasOverlappingIntervals() const;
|
||||
bool coversFullRange( double startMD, double endMD ) const;
|
||||
std::vector<QString> validateIntervals() const;
|
||||
|
||||
// Sorting and organization
|
||||
void sortIntervalsByMD();
|
||||
void mergeAdjacentIntervals();
|
||||
|
||||
// Utility
|
||||
bool isEmpty() const;
|
||||
size_t count() const;
|
||||
void updateConnectedEditors();
|
||||
|
||||
// Accessor for UI integration
|
||||
caf::PdmChildArrayField<RimDiameterRoughnessInterval*>& intervalsField();
|
||||
|
||||
// Visual feedback for overlapping intervals
|
||||
void updateOverlapVisualFeedback();
|
||||
|
||||
protected:
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) override;
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
|
||||
|
||||
private:
|
||||
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
|
||||
|
||||
caf::PdmChildArrayField<RimDiameterRoughnessInterval*> m_intervals;
|
||||
};
|
||||
@@ -19,12 +19,15 @@
|
||||
#include "RimMswCompletionParameters.h"
|
||||
|
||||
#include "RiaEclipseUnitTools.h"
|
||||
#include "RimDiameterRoughnessIntervalCollection.h"
|
||||
|
||||
#include "RimWellPath.h"
|
||||
|
||||
#include "cafCmdFeatureMenuBuilder.h"
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiObjectEditorHandle.h"
|
||||
#include "cafPdmUiTableViewEditor.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
@@ -54,6 +57,14 @@ void RimMswCompletionParameters::LengthAndDepthEnum::setUp()
|
||||
addItem( RimMswCompletionParameters::LengthAndDepthType::ABS, "ABS", "Absolute" );
|
||||
setDefault( RimMswCompletionParameters::LengthAndDepthType::ABS );
|
||||
}
|
||||
|
||||
template <>
|
||||
void RimMswCompletionParameters::DiameterRoughnessModeEnum::setUp()
|
||||
{
|
||||
addItem( RimMswCompletionParameters::DiameterRoughnessMode::UNIFORM, "Uniform", "Uniform" );
|
||||
addItem( RimMswCompletionParameters::DiameterRoughnessMode::INTERVALS, "Intervals", "Intervals" );
|
||||
setDefault( RimMswCompletionParameters::DiameterRoughnessMode::UNIFORM );
|
||||
}
|
||||
} // namespace caf
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimMswCompletionParameters, "RimMswCompletionParameters" );
|
||||
@@ -85,6 +96,17 @@ RimMswCompletionParameters::RimMswCompletionParameters()
|
||||
RimMswCompletionParameters::defaultRoughnessFactor( unitSystem ),
|
||||
"Roughness Factor" );
|
||||
|
||||
// New interval-based fields
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_diameterRoughnessMode, "DiameterRoughnessMode", "Diameter Roughness Mode" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_diameterRoughnessIntervals, "DiameterRoughnessIntervals", "Diameter Roughness Intervals" );
|
||||
m_diameterRoughnessIntervals = new RimDiameterRoughnessIntervalCollection();
|
||||
m_diameterRoughnessIntervals->intervalsField().uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() );
|
||||
m_diameterRoughnessIntervals->intervalsField().uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
|
||||
m_diameterRoughnessIntervals->intervalsField().uiCapability()->setCustomContextMenuEnabled( true );
|
||||
|
||||
// Enable custom context menu on this object as well
|
||||
setCustomContextMenuEnabled( true );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_pressureDrop, "PressureDrop", "Pressure Drop" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_lengthAndDepth, "LengthAndDepth", "Length and Depth" );
|
||||
|
||||
@@ -213,6 +235,66 @@ double RimMswCompletionParameters::roughnessFactor() const
|
||||
return m_roughnessFactor();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimMswCompletionParameters::DiameterRoughnessMode RimMswCompletionParameters::diameterRoughnessMode() const
|
||||
{
|
||||
return m_diameterRoughnessMode();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimMswCompletionParameters::setDiameterRoughnessMode( DiameterRoughnessMode mode )
|
||||
{
|
||||
m_diameterRoughnessMode = mode;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimMswCompletionParameters::isUsingIntervalSpecificValues() const
|
||||
{
|
||||
return m_diameterRoughnessMode() == DiameterRoughnessMode::INTERVALS;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimMswCompletionParameters::getDiameterAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const
|
||||
{
|
||||
if ( isUsingIntervalSpecificValues() && m_diameterRoughnessIntervals() )
|
||||
{
|
||||
return m_diameterRoughnessIntervals()->getDiameterAtMD( md, unitSystem );
|
||||
}
|
||||
|
||||
// Fall back to single value
|
||||
return linerDiameter( unitSystem );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimMswCompletionParameters::getRoughnessAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const
|
||||
{
|
||||
if ( isUsingIntervalSpecificValues() && m_diameterRoughnessIntervals() )
|
||||
{
|
||||
return m_diameterRoughnessIntervals()->getRoughnessAtMD( md, unitSystem );
|
||||
}
|
||||
|
||||
// Fall back to single value
|
||||
return roughnessFactor( unitSystem );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDiameterRoughnessIntervalCollection* RimMswCompletionParameters::diameterRoughnessIntervals() const
|
||||
{
|
||||
return m_diameterRoughnessIntervals();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -314,6 +396,11 @@ void RimMswCompletionParameters::fieldChangedByUi( const caf::PdmFieldHandle* ch
|
||||
m_maxSegmentLength.uiCapability()->setUiHidden( !m_enforceMaxSegmentLength() );
|
||||
caf::PdmUiObjectEditorHandle::updateUiAllObjectEditors();
|
||||
}
|
||||
|
||||
if ( changedField == &m_diameterRoughnessMode )
|
||||
{
|
||||
updateAllRequiredEditors();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -341,8 +428,26 @@ void RimMswCompletionParameters::defineUiOrdering( QString uiConfigName, caf::Pd
|
||||
uiOrdering.add( &m_refMD );
|
||||
m_refMD.uiCapability()->setUiHidden( m_refMDType == ReferenceMDType::AUTO_REFERENCE_MD );
|
||||
|
||||
uiOrdering.add( &m_linerDiameter );
|
||||
uiOrdering.add( &m_roughnessFactor );
|
||||
// Diameter and Roughness section
|
||||
auto* diameterRoughnessGroup = uiOrdering.addNewGroup( "Diameter and Roughness" );
|
||||
diameterRoughnessGroup->add( &m_diameterRoughnessMode );
|
||||
|
||||
bool usingIntervals = m_diameterRoughnessMode() == DiameterRoughnessMode::INTERVALS;
|
||||
|
||||
if ( usingIntervals )
|
||||
{
|
||||
diameterRoughnessGroup->add( &m_diameterRoughnessIntervals->intervalsField() );
|
||||
m_linerDiameter.uiCapability()->setUiHidden( true );
|
||||
m_roughnessFactor.uiCapability()->setUiHidden( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
diameterRoughnessGroup->add( &m_linerDiameter );
|
||||
diameterRoughnessGroup->add( &m_roughnessFactor );
|
||||
m_linerDiameter.uiCapability()->setUiHidden( false );
|
||||
m_roughnessFactor.uiCapability()->setUiHidden( false );
|
||||
}
|
||||
|
||||
uiOrdering.add( &m_pressureDrop );
|
||||
uiOrdering.add( &m_lengthAndDepth );
|
||||
uiOrdering.add( &m_enforceMaxSegmentLength );
|
||||
@@ -352,11 +457,31 @@ void RimMswCompletionParameters::defineUiOrdering( QString uiConfigName, caf::Pd
|
||||
{
|
||||
uiOrdering.add( &m_customValuesForLateral );
|
||||
|
||||
uiOrdering.add( &m_linerDiameter );
|
||||
uiOrdering.add( &m_roughnessFactor );
|
||||
// Diameter and Roughness section for laterals
|
||||
auto* diameterRoughnessGroup = uiOrdering.addNewGroup( "Diameter and Roughness" );
|
||||
diameterRoughnessGroup->add( &m_diameterRoughnessMode );
|
||||
|
||||
m_linerDiameter.uiCapability()->setUiReadOnly( !m_customValuesForLateral() );
|
||||
m_linerDiameter.uiCapability()->setUiReadOnly( !m_customValuesForLateral() );
|
||||
bool usingIntervals = m_diameterRoughnessMode() == DiameterRoughnessMode::INTERVALS;
|
||||
|
||||
if ( usingIntervals )
|
||||
{
|
||||
diameterRoughnessGroup->add( &m_diameterRoughnessIntervals );
|
||||
m_linerDiameter.uiCapability()->setUiHidden( true );
|
||||
m_roughnessFactor.uiCapability()->setUiHidden( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
diameterRoughnessGroup->add( &m_linerDiameter );
|
||||
diameterRoughnessGroup->add( &m_roughnessFactor );
|
||||
m_linerDiameter.uiCapability()->setUiHidden( false );
|
||||
m_roughnessFactor.uiCapability()->setUiHidden( false );
|
||||
}
|
||||
|
||||
bool isReadOnly = !m_customValuesForLateral();
|
||||
m_linerDiameter.uiCapability()->setUiReadOnly( isReadOnly );
|
||||
m_roughnessFactor.uiCapability()->setUiReadOnly( isReadOnly );
|
||||
m_diameterRoughnessMode.uiCapability()->setUiReadOnly( isReadOnly );
|
||||
m_diameterRoughnessIntervals.uiCapability()->setUiReadOnly( isReadOnly );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,3 +529,20 @@ void RimMswCompletionParameters::updateFromTopLevelWell( const RimMswCompletionP
|
||||
m_roughnessFactor = rhs.m_roughnessFactor();
|
||||
*/
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimMswCompletionParameters::defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget )
|
||||
{
|
||||
if ( fieldNeedingMenu == &m_diameterRoughnessIntervals )
|
||||
{
|
||||
caf::CmdFeatureMenuBuilder menuBuilder;
|
||||
|
||||
menuBuilder << "RicNewDiameterRoughnessIntervalFeature";
|
||||
menuBuilder << "Separator";
|
||||
menuBuilder << "RicDeleteDiameterRoughnessIntervalFeature";
|
||||
|
||||
menuBuilder.appendToMenu( menu );
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,13 @@
|
||||
|
||||
#include "RiaDefines.h"
|
||||
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmUiGroup.h"
|
||||
|
||||
class RimDiameterRoughnessIntervalCollection;
|
||||
|
||||
class RimMswCompletionParameters : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
@@ -47,9 +50,16 @@ public:
|
||||
INC
|
||||
};
|
||||
|
||||
using ReferenceMDEnum = caf::AppEnum<ReferenceMDType>;
|
||||
using PressureDropEnum = caf::AppEnum<PressureDropType>;
|
||||
using LengthAndDepthEnum = caf::AppEnum<LengthAndDepthType>;
|
||||
enum class DiameterRoughnessMode
|
||||
{
|
||||
UNIFORM,
|
||||
INTERVALS
|
||||
};
|
||||
|
||||
using ReferenceMDEnum = caf::AppEnum<ReferenceMDType>;
|
||||
using PressureDropEnum = caf::AppEnum<PressureDropType>;
|
||||
using LengthAndDepthEnum = caf::AppEnum<LengthAndDepthType>;
|
||||
using DiameterRoughnessModeEnum = caf::AppEnum<DiameterRoughnessMode>;
|
||||
|
||||
RimMswCompletionParameters();
|
||||
~RimMswCompletionParameters() override;
|
||||
@@ -73,19 +83,30 @@ public:
|
||||
void setPressureDrop( PressureDropType pressureDropType );
|
||||
void setLengthAndDepth( LengthAndDepthType lengthAndDepthType );
|
||||
|
||||
// New interval-based methods
|
||||
DiameterRoughnessMode diameterRoughnessMode() const;
|
||||
void setDiameterRoughnessMode( DiameterRoughnessMode mode );
|
||||
bool isUsingIntervalSpecificValues() const;
|
||||
|
||||
double getDiameterAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const;
|
||||
double getRoughnessAtMD( double md, RiaDefines::EclipseUnitSystem unitSystem ) const;
|
||||
|
||||
RimDiameterRoughnessIntervalCollection* diameterRoughnessIntervals() const;
|
||||
|
||||
void setUnitSystemSpecificDefaults();
|
||||
|
||||
void updateFromTopLevelWell( const RimMswCompletionParameters* topLevelWellParameters );
|
||||
|
||||
// Public static methods for default values - used by interval classes
|
||||
static double defaultLinerDiameter( RiaDefines::EclipseUnitSystem unitSystem );
|
||||
static double defaultRoughnessFactor( RiaDefines::EclipseUnitSystem unitSystem );
|
||||
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void initAfterRead() override;
|
||||
|
||||
private:
|
||||
static double defaultLinerDiameter( RiaDefines::EclipseUnitSystem unitSystem );
|
||||
static double defaultRoughnessFactor( RiaDefines::EclipseUnitSystem unitSystem );
|
||||
void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<ReferenceMDEnum> m_refMDType;
|
||||
@@ -95,6 +116,10 @@ private:
|
||||
caf::PdmField<double> m_linerDiameter;
|
||||
caf::PdmField<double> m_roughnessFactor;
|
||||
|
||||
// New interval-based fields
|
||||
caf::PdmField<DiameterRoughnessModeEnum> m_diameterRoughnessMode;
|
||||
caf::PdmChildField<RimDiameterRoughnessIntervalCollection*> m_diameterRoughnessIntervals;
|
||||
|
||||
caf::PdmField<PressureDropEnum> m_pressureDrop;
|
||||
caf::PdmField<LengthAndDepthEnum> m_lengthAndDepth;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcRegularSurface.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcPerforationInterval.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcValveTemplateCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcWellPathCompletionSettings.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -70,6 +71,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcRegularSurface.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcPerforationInterval.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcValveTemplateCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcWellPathCompletionSettings.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimcWellPathCompletionSettings.h"
|
||||
|
||||
#include "RimDiameterRoughnessInterval.h"
|
||||
#include "RimDiameterRoughnessIntervalCollection.h"
|
||||
#include "RimMswCompletionParameters.h"
|
||||
#include "RimWellPathCompletionSettings.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
|
||||
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimWellPathCompletionSettings,
|
||||
RimcWellPathCompletionSettings_addDiameterRoughnessInterval,
|
||||
"AddDiameterRoughnessInterval" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimcWellPathCompletionSettings_addDiameterRoughnessInterval::RimcWellPathCompletionSettings_addDiameterRoughnessInterval( caf::PdmObjectHandle* self )
|
||||
: caf::PdmObjectCreationMethod( self )
|
||||
{
|
||||
CAF_PDM_InitObject( "Add Diameter Roughness Interval" );
|
||||
CAF_PDM_InitScriptableField( &m_startMD, "StartMd", 0.0, "Start Measured Depth" );
|
||||
CAF_PDM_InitScriptableField( &m_endMD, "EndMd", 100.0, "End Measured Depth" );
|
||||
CAF_PDM_InitScriptableField( &m_diameter, "Diameter", 0.152, "Diameter" );
|
||||
CAF_PDM_InitScriptableField( &m_roughnessFactor, "RoughnessFactor", 1.0e-5, "Roughness Factor" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<caf::PdmObjectHandle*, QString> RimcWellPathCompletionSettings_addDiameterRoughnessInterval::execute()
|
||||
{
|
||||
auto completionSettings = self<RimWellPathCompletionSettings>();
|
||||
if ( !completionSettings )
|
||||
{
|
||||
return std::unexpected( QString( "Completion settings is null. Cannot add diameter roughness interval." ) );
|
||||
}
|
||||
|
||||
auto mswParams = completionSettings->mswCompletionParameters();
|
||||
if ( !mswParams )
|
||||
{
|
||||
return std::unexpected( QString( "MSW completion parameters is null. Cannot add diameter roughness interval." ) );
|
||||
}
|
||||
|
||||
auto intervalCollection = mswParams->diameterRoughnessIntervals();
|
||||
if ( !intervalCollection )
|
||||
{
|
||||
return std::unexpected( QString( "Diameter roughness interval collection is null. Cannot add interval." ) );
|
||||
}
|
||||
|
||||
// Ensure we're in interval-specific mode
|
||||
mswParams->setDiameterRoughnessMode( RimMswCompletionParameters::DiameterRoughnessMode::INTERVALS );
|
||||
|
||||
// Create new interval
|
||||
auto* newInterval = intervalCollection->createInterval( m_startMD(), m_endMD(), m_diameter(), m_roughnessFactor() );
|
||||
|
||||
if ( !newInterval )
|
||||
{
|
||||
return std::unexpected( QString( "Failed to create diameter roughness interval." ) );
|
||||
}
|
||||
|
||||
completionSettings->updateAllRequiredEditors();
|
||||
|
||||
return newInterval;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimcWellPathCompletionSettings_addDiameterRoughnessInterval::classKeywordReturnedType() const
|
||||
{
|
||||
return RimDiameterRoughnessInterval::classKeywordStatic();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 <QString>
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimcWellPathCompletionSettings_addDiameterRoughnessInterval : public caf::PdmObjectCreationMethod
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimcWellPathCompletionSettings_addDiameterRoughnessInterval( 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;
|
||||
caf::PdmField<double> m_diameter;
|
||||
caf::PdmField<double> m_roughnessFactor;
|
||||
};
|
||||
@@ -68,6 +68,17 @@ completions_settings.group_name_for_export = "msj"
|
||||
completions_settings.well_type_for_export = "GAS"
|
||||
completions_settings.update() # Commit updates back to ResInsight
|
||||
|
||||
# Add diameter roughness intervals for interval-specific configuration
|
||||
interval1 = completions_settings.add_diameter_roughness_interval(
|
||||
start_md=3200, end_md=3300, diameter=0.18, roughness_factor=1.5e-5
|
||||
)
|
||||
interval2 = completions_settings.add_diameter_roughness_interval(
|
||||
start_md=3300, end_md=3400, diameter=0.16, roughness_factor=2.0e-5
|
||||
)
|
||||
print(
|
||||
f"Added diameter roughness intervals: {interval1.start_md}-{interval1.end_md}m and {interval2.start_md}-{interval2.end_md}m"
|
||||
)
|
||||
|
||||
# Optionally update the MSW settings
|
||||
msw_settings = well_path.msw_settings()
|
||||
msw_settings.custom_values_for_lateral = False
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import rips
|
||||
|
||||
|
||||
def test_diameter_roughness_intervals(rips_instance, initialize_test):
|
||||
"""Test the new diameter roughness 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 Diameter Intervals"
|
||||
|
||||
completions_settings = well_path.completion_settings()
|
||||
assert completions_settings is not None, "Completion settings should not be None"
|
||||
|
||||
# Test our new method - create first interval
|
||||
interval1 = completions_settings.add_diameter_roughness_interval(
|
||||
start_md=100, end_md=200, diameter=0.15, roughness_factor=1e-5
|
||||
)
|
||||
|
||||
# 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
|
||||
assert interval1.diameter == 0.15
|
||||
assert interval1.roughness_factor == 1e-5
|
||||
|
||||
# Test creating a second interval with different values
|
||||
interval2 = completions_settings.add_diameter_roughness_interval(
|
||||
start_md=200, end_md=300, diameter=0.12, roughness_factor=2e-5
|
||||
)
|
||||
|
||||
# Assertions to verify the second interval
|
||||
assert interval2 is not None, "Second interval should not be None"
|
||||
assert interval2.start_md == 200
|
||||
assert interval2.end_md == 300
|
||||
assert interval2.diameter == 0.12
|
||||
assert interval2.roughness_factor == 2e-5
|
||||
|
||||
# Test default values
|
||||
interval3 = completions_settings.add_diameter_roughness_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
|
||||
assert interval3.diameter == 0.152
|
||||
assert interval3.roughness_factor == 1e-5
|
||||
Reference in new issue
Block a user