From 888675cec943344b0eab483e9b24d56eae6edcb6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 25 Jan 2024 18:17:10 +0100 Subject: [PATCH] #11109 Improve visualization of MSW with valve branches Increase default segment threshold to 4 Add an optional setting to override the default value Use this threshold to merge short branches into parent branch --- .../RivSimWellPipesPartMgr.cpp | 18 +---------- .../RimExtrudedCurveIntersection.cpp | 10 +++--- .../RimExtrudedCurveIntersection.h | 2 +- .../ProjectDataModel/RimEclipseResultCase.cpp | 31 +++++++++++++++++++ .../ProjectDataModel/RimEclipseResultCase.h | 6 ++++ .../ProjectDataModel/RimSimWellInView.cpp | 16 ++++++++++ .../ProjectDataModel/RimSimWellInView.h | 3 ++ .../RigMswCenterLineCalculator.cpp | 24 ++++++++------ .../RigMswCenterLineCalculator.h | 8 +++-- .../RigSimulationWellCenterLineCalculator.cpp | 4 +-- .../RigSimulationWellCenterLineCalculator.h | 4 +-- 11 files changed, 87 insertions(+), 39 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.cpp index 9e96ff708f..9ec86ad276 100644 --- a/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.cpp @@ -166,23 +166,7 @@ void RivSimWellPipesPartMgr::buildWellPipeParts( const caf::DisplayCoordTransfor m_wellBranches.clear(); m_flattenedBranchWellHeadOffsets.clear(); - auto createSimWells = []( RimSimWellInView* simWellInView ) -> std::vector - { - std::vector simWellBranches; - const RigSimWellData* simWellData = simWellInView->simWellData(); - if ( simWellData && simWellData->isMultiSegmentWell() ) - { - simWellBranches = RigMswCenterLineCalculator::calculateMswWellPipeGeometry( simWellInView ); - } - else - { - simWellBranches = RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( simWellInView ); - } - - return simWellBranches; - }; - - auto simWells = createSimWells( m_simWellInView ); + auto simWells = m_simWellInView->wellBranchesForVisualization(); const auto& [coords, wellCells] = RigSimulationWellCenterLineCalculator::extractBranchData( simWells ); auto pipeBranchesCLCoords = coords; diff --git a/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.cpp b/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.cpp index 01a3d57286..bd3faab8f0 100644 --- a/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.cpp @@ -23,6 +23,7 @@ #include "RigEclipseCaseData.h" #include "RigMainGrid.h" +#include "RigSimulationWellCenterLineCalculator.h" #include "RigWellPath.h" #include "Rim2dIntersectionView.h" @@ -868,11 +869,10 @@ void RimExtrudedCurveIntersection::updateSimulationWellCenterline() const { if ( m_simulationWellBranchCenterlines.empty() ) { - auto branches = m_simulationWell->wellPipeBranches(); - for ( const auto& branch : branches ) - { - m_simulationWellBranchCenterlines.push_back( branch->wellPathPoints() ); - } + auto simWells = m_simulationWell()->wellBranchesForVisualization(); + const auto& [coords, wellCells] = RigSimulationWellCenterLineCalculator::extractBranchData( simWells ); + + m_simulationWellBranchCenterlines = coords; } } else diff --git a/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.h b/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.h index f4de75e8ae..a27079113e 100644 --- a/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.h +++ b/ApplicationLibCode/ProjectDataModel/Intersections/RimExtrudedCurveIntersection.h @@ -209,4 +209,4 @@ class RimExtrudedCurveIntersection : public RimIntersection caf::PdmField m_kFilterCollectionOverride; caf::PdmField m_kFilterCollectionText; -}; +}; \ No newline at end of file diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.cpp index b08c30af91..950bee76f7 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.cpp @@ -49,12 +49,14 @@ #include "RimEclipseInputPropertyCollection.h" #include "RimEclipseView.h" #include "RimFlowDiagSolution.h" +#include "RimIntersectionCollection.h" #include "RimMockModelSettings.h" #include "RimProject.h" #include "RimReservoirCellResultsStorage.h" #include "RimTimeStepFilter.h" #include "RimTools.h" +#include "cafPdmUiCheckBoxAndTextEditor.h" #include "cafPdmUiFilePathEditor.h" #include "cafPdmUiPropertyViewDialog.h" #include "cafProgressInfo.h" @@ -102,6 +104,9 @@ RimEclipseResultCase::RimEclipseResultCase() #ifndef USE_HDF5 m_sourSimFileName.uiCapability()->setUiHidden( true ); #endif + + CAF_PDM_InitField( &m_mswMergeThreshold, "MswMergeThreshold", std::make_pair( false, 3 ), "MSW Short Well Merge Threshold" ); + m_mswMergeThreshold.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxAndTextEditor::uiEditorTypeName() ); } //-------------------------------------------------------------------------------------------------- @@ -561,6 +566,21 @@ RifReaderRftInterface* RimEclipseResultCase::rftReader() return m_readerEclipseRft.p(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimEclipseResultCase::mswMergeThreshold() const +{ + // This value is used in RigMswCenterLineCalculator::calculateMswWellPipeGeometry + + if ( m_mswMergeThreshold().first ) + { + return m_mswMergeThreshold().second; + } + + return 4; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -607,6 +627,7 @@ void RimEclipseResultCase::defineUiOrdering( QString uiConfigName, caf::PdmUiOrd group->add( &m_activeFormationNames ); group->add( &m_flipXAxis ); group->add( &m_flipYAxis ); + group->add( &m_mswMergeThreshold ); if ( eclipseCaseData() && eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL ) && eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->maxTimeStepCount() > 0 ) @@ -627,6 +648,16 @@ void RimEclipseResultCase::fieldChangedByUi( const caf::PdmFieldHandle* changedF loadAndUpdateSourSimData(); } + if ( changedField == &m_mswMergeThreshold ) + { + for ( auto resView : reservoirViews() ) + { + resView->scheduleSimWellGeometryRegen(); + resView->scheduleCreateDisplayModelAndRedraw(); + resView->intersectionCollection()->recomputeSimWellBranchData(); + } + } + return RimEclipseCase::fieldChangedByUi( changedField, oldValue, newValue ); } diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.h b/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.h index 9edbd91b7d..a208056f70 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.h @@ -73,6 +73,10 @@ class RimEclipseResultCase : public RimEclipseCase RifReaderRftInterface* rftReader(); + // A multi segment well can have multiple well paths. Valves can be modeled using short branches. This threshold defines the limit for + // merging branches into the upstream branch. + int mswMergeThreshold() const; + protected: void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; @@ -95,6 +99,8 @@ class RimEclipseResultCase : public RimEclipseCase caf::PdmChildArrayField m_flowDiagSolutions; caf::PdmField m_sourSimFileName; + caf::PdmField> m_mswMergeThreshold; + bool m_gridAndWellDataIsReadFromFile; bool m_activeCellInfoIsReadFromFile; bool m_useOpmRftReader; diff --git a/ApplicationLibCode/ProjectDataModel/RimSimWellInView.cpp b/ApplicationLibCode/ProjectDataModel/RimSimWellInView.cpp index 970c6c841f..7bf1c10071 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSimWellInView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimSimWellInView.cpp @@ -26,6 +26,7 @@ #include "RigCell.h" #include "RigEclipseCaseData.h" #include "RigMainGrid.h" +#include "RigMswCenterLineCalculator.h" #include "RigSimWellData.h" #include "RigSimulationWellCenterLineCalculator.h" #include "RigWellResultFrame.h" @@ -188,6 +189,21 @@ std::vector RimSimWellInView::wellPipeBranches() const return std::vector(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimSimWellInView::wellBranchesForVisualization() const +{ + const RigSimWellData* simWellData = this->simWellData(); + + if ( simWellData && simWellData->isMultiSegmentWell() ) + { + return RigMswCenterLineCalculator::calculateMswWellPipeGeometry( this ); + } + + return RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( this ); +} + //-------------------------------------------------------------------------------------------------- /// frameIndex = -1 will use the static well frame //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimSimWellInView.h b/ApplicationLibCode/ProjectDataModel/RimSimWellInView.h index 73fb48ede2..ed8060a0dc 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSimWellInView.h +++ b/ApplicationLibCode/ProjectDataModel/RimSimWellInView.h @@ -23,6 +23,7 @@ #include "Rim3dPropertiesInterface.h" #include "RigWellDiskData.h" +#include "RigWellResultBranch.h" #include "cafAppEnum.h" #include "cafPdmChildField.h" @@ -76,6 +77,8 @@ class RimSimWellInView : public caf::PdmObject, public Rim3dPropertiesInterface std::vector wellPipeBranches() const; + std::vector wellBranchesForVisualization() const; + void wellHeadTopBottomPosition( int frameIndex, cvf::Vec3d* top, cvf::Vec3d* bottom ); double pipeRadius(); int pipeCrossSectionVertexCount(); diff --git a/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.cpp index 120f93912e..b5bc81933c 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.cpp @@ -28,6 +28,7 @@ #include "RigWellResultFrame.h" #include "RimEclipseCase.h" +#include "RimEclipseResultCase.h" #include "RimEclipseView.h" #include "RimSimWellInView.h" #include "RimSimWellInViewCollection.h" @@ -37,7 +38,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RigMswCenterLineCalculator::calculateMswWellPipeGeometry( RimSimWellInView* rimWell ) +std::vector RigMswCenterLineCalculator::calculateMswWellPipeGeometry( const RimSimWellInView* rimWell ) { CVF_ASSERT( rimWell ); @@ -50,7 +51,13 @@ std::vector RigMswCenterLineCalculator::calculateMswWe auto eclipseCaseData = eclipseView->eclipseCase()->eclipseCaseData(); int timeStepIndex = eclipseView->currentTimeStep(); - return calculateMswWellPipeGeometryForTimeStep( eclipseCaseData, simWellData, timeStepIndex ); + int shortBranchMergeThreshold = 4; + if ( auto eclipseResultCase = dynamic_cast( eclipseView->eclipseCase() ) ) + { + shortBranchMergeThreshold = eclipseResultCase->mswMergeThreshold(); + } + + return calculateMswWellPipeGeometryForTimeStep( eclipseCaseData, simWellData, timeStepIndex, shortBranchMergeThreshold ); } return {}; @@ -62,10 +69,9 @@ std::vector RigMswCenterLineCalculator::calculateMswWe std::vector RigMswCenterLineCalculator::calculateMswWellPipeGeometryForTimeStep( const RigEclipseCaseData* eclipseCaseData, const RigSimWellData* wellResults, - int timeStepIndex ) + int timeStepIndex, + int shortBranchMergeThreshold ) { - if ( timeStepIndex >= 0 && !wellResults->hasAnyValidCells( timeStepIndex ) ) return {}; - const RigWellResultFrame* wellFramePtr = nullptr; if ( timeStepIndex < 0 ) @@ -80,7 +86,7 @@ std::vector const RigWellResultFrame& wellFrame = *wellFramePtr; const std::vector resultBranches = wellFrame.wellResultBranches(); - std::vector wellBranches = mergeShortBranchesIntoLongBranches( resultBranches ); + std::vector wellBranches = mergeShortBranchesIntoLongBranches( resultBranches, shortBranchMergeThreshold ); // Connect outlet segment of branches to parent branch @@ -290,7 +296,8 @@ SimulationWellCellBranch /// //-------------------------------------------------------------------------------------------------- std::vector - RigMswCenterLineCalculator::mergeShortBranchesIntoLongBranches( const std::vector& resBranches ) + RigMswCenterLineCalculator::mergeShortBranchesIntoLongBranches( const std::vector& resBranches, + int shortBranchMergeThreshold ) { std::vector longWellBranches; std::vector shortWellBranches; @@ -314,8 +321,7 @@ std::vector } } - const int resultPointThreshold = 3; - if ( resultBranch.branchResultPoints().size() > resultPointThreshold ) + if ( static_cast( resultBranch.branchResultPoints().size() ) > shortBranchMergeThreshold ) { longWellBranches.push_back( branch ); } diff --git a/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.h b/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.h index 345b0ceb46..747fdd5da6 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.h +++ b/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.h @@ -35,7 +35,7 @@ class RigSimWellData; class RigMswCenterLineCalculator { public: - static std::vector calculateMswWellPipeGeometry( RimSimWellInView* rimWell ); + static std::vector calculateMswWellPipeGeometry( const RimSimWellInView* rimWell ); private: struct OutputSegment @@ -69,11 +69,13 @@ class RigMswCenterLineCalculator private: static std::vector calculateMswWellPipeGeometryForTimeStep( const RigEclipseCaseData* eclipseCaseData, const RigSimWellData* simWellData, - int timeStepIndex ); + int timeStepIndex, + int shortBranchMergeThreshold ); static SimulationWellCellBranch addCoordsAtCellFaceIntersectionsAndCreateBranch( const std::vector branchCoords, const std::vector& resultPoints, const RigEclipseCaseData* eclipseCaseData ); - static std::vector mergeShortBranchesIntoLongBranches( const std::vector& resBranches ); + static std::vector mergeShortBranchesIntoLongBranches( const std::vector& resBranches, + int shortBranchMergeThreshold ); }; diff --git a/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.cpp index ee3cbadb8b..014a96d9ef 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.cpp @@ -43,7 +43,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( RimSimWellInView* rimWell ) +std::vector RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( const RimSimWellInView* rimWell ) { std::vector> pipeBranchesCLCoords; std::vector> pipeBranchesCellIds; @@ -118,7 +118,7 @@ std::pair>, std::vector>& pipeBranchesCLCoords, std::vector>& pipeBranchesCellIds ) { diff --git a/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.h b/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.h index 347edc2d45..d2b8257634 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.h +++ b/ApplicationLibCode/ReservoirDataModel/RigSimulationWellCenterLineCalculator.h @@ -37,7 +37,7 @@ class RigWellResultFrame; class RigSimulationWellCenterLineCalculator { public: - static std::vector calculateWellPipeStaticCenterline( RimSimWellInView* rimWell ); + static std::vector calculateWellPipeStaticCenterline( const RimSimWellInView* rimWell ); static std::vector calculateWellPipeCenterlineForTimeStep( const RigEclipseCaseData* eclipseCaseData, const RigSimWellData* simWellData, @@ -49,7 +49,7 @@ class RigSimulationWellCenterLineCalculator extractBranchData( const std::vector simulationBranch ); private: - static void calculateWellPipeStaticCenterline( RimSimWellInView* rimWell, + static void calculateWellPipeStaticCenterline( const RimSimWellInView* rimWell, std::vector>& pipeBranchesCLCoords, std::vector>& pipeBranchesCellIds );