From 4fc0839a336449605670b087dfb6f7f3ddff42b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 15 Feb 2017 12:29:36 +0100 Subject: [PATCH] #1211 Disabled tracer allocation for wells with inconsistent flow. --- .../Flow/RimWellAllocationPlot.cpp | 91 +++++++++++-------- .../Flow/RimWellAllocationPlot.h | 4 + .../RigAccWellFlowCalculator.cpp | 50 ++++++++-- .../RigAccWellFlowCalculator.h | 4 +- .../RigSingleWellResultsData.cpp | 32 +++++++ .../RigSingleWellResultsData.h | 32 ++++--- 6 files changed, 151 insertions(+), 62 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index 26a5475b7f..69c548c653 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -181,50 +181,26 @@ void RimWellAllocationPlot::updateFromWell() true, pipeBranchesCLCoords, pipeBranchesCellIds); + + std::map* > tracerCellFractionValues = findRelevantTracerCellFractions(wellResults); + std::unique_ptr< RigAccWellFlowCalculator > wfCalculator; - std::map* > tracerCellFractionValues; + double smallContributionThreshold = 0.0; if (m_groupSmallContributions()) smallContributionThreshold = m_smallContributionsThreshold; - - if ( m_flowDiagSolution && wellResults->hasWellResult(m_timeStep)) + if ( tracerCellFractionValues.size() ) { - RimFlowDiagSolution::TracerStatusType requestedTracerType = RimFlowDiagSolution::UNDEFINED; - - const RigWellResultFrame& wellResultFrame = wellResults->wellResultFrame(m_timeStep); - if (wellResultFrame.m_productionType == RigWellResultFrame::PRODUCER) - { - requestedTracerType = RimFlowDiagSolution::INJECTOR; - } - else - { - requestedTracerType = RimFlowDiagSolution::PRODUCER; - } - - - std::vector tracerNames = m_flowDiagSolution->tracerNames(); - for ( const QString& tracerName : tracerNames ) - { - if (m_flowDiagSolution->tracerStatusInTimeStep(tracerName, m_timeStep) == requestedTracerType) - { - RigFlowDiagResultAddress resAddr(RIG_FLD_CELL_FRACTION_RESNAME, tracerName.toStdString()); - const std::vector* tracerCellFractions = m_flowDiagSolution->flowDiagResults()->resultValues(resAddr, m_timeStep); - tracerCellFractionValues[tracerName] = tracerCellFractions; - } - } - - if ( tracerCellFractionValues.size() ) - { - RigEclCellIndexCalculator cellIdxCalc(m_case->reservoirData()->mainGrid(), m_case->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)); - wfCalculator.reset(new RigAccWellFlowCalculator(pipeBranchesCLCoords, - pipeBranchesCellIds, - tracerCellFractionValues, - cellIdxCalc, - smallContributionThreshold)); - } + bool isProducer = wellResults->wellProductionType(m_timeStep) == RigWellResultFrame::PRODUCER ; + RigEclCellIndexCalculator cellIdxCalc(m_case->reservoirData()->mainGrid(), m_case->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)); + wfCalculator.reset(new RigAccWellFlowCalculator(pipeBranchesCLCoords, + pipeBranchesCellIds, + tracerCellFractionValues, + cellIdxCalc, + smallContributionThreshold, + isProducer)); } - - if (!wfCalculator) + else { if (pipeBranchesCLCoords.size() > 0) { @@ -314,6 +290,45 @@ void RimWellAllocationPlot::updateFromWell() if (m_wellAllocationPlotWidget) m_wellAllocationPlotWidget->updateGeometry(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::map *> RimWellAllocationPlot::findRelevantTracerCellFractions(const RigSingleWellResultsData* wellResults) +{ + std::map *> tracerCellFractionValues; + + if ( m_flowDiagSolution && wellResults->isOpen(m_timeStep) ) + { + RimFlowDiagSolution::TracerStatusType requestedTracerType = RimFlowDiagSolution::UNDEFINED; + + const RigWellResultFrame::WellProductionType prodType = wellResults->wellProductionType(m_timeStep); + if ( prodType == RigWellResultFrame::PRODUCER ) + { + requestedTracerType = RimFlowDiagSolution::INJECTOR; + } + else if (prodType != RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE) + { + requestedTracerType = RimFlowDiagSolution::PRODUCER; + } + + if ( prodType != RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE ) + { + std::vector tracerNames = m_flowDiagSolution->tracerNames(); + for ( const QString& tracerName : tracerNames ) + { + if ( m_flowDiagSolution->tracerStatusInTimeStep(tracerName, m_timeStep) == requestedTracerType ) + { + RigFlowDiagResultAddress resAddr(RIG_FLD_CELL_FRACTION_RESNAME, tracerName.toStdString()); + const std::vector* tracerCellFractions = m_flowDiagSolution->flowDiagResults()->resultValues(resAddr, m_timeStep); + tracerCellFractionValues[tracerName] = tracerCellFractions; + } + } + } + } + + return tracerCellFractionValues; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h index b9d4adf667..5ea657520d 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h @@ -35,6 +35,7 @@ class RimWellAllocationPlotLegend; class RimWellLogPlot; class RiuWellAllocationPlot; class RimWellLogTrack; +class RigSingleWellResultsData; namespace caf { class PdmOptionItemInfo; @@ -86,6 +87,9 @@ protected: private: void updateFromWell(); + + std::map *> findRelevantTracerCellFractions(const RigSingleWellResultsData* wellResults); + void updateWellFlowPlotXAxisTitle(RimWellLogTrack* plotTrack); void addStackedCurve(const QString& tracerName, diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp index e39b7d0e9b..12e8aa384a 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp @@ -31,7 +31,8 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto const std::vector< std::vector >& pipeBranchesCellIds, const std::map* >& tracerCellFractionValues, const RigEclCellIndexCalculator cellIndexCalculator, - double smallContribThreshold): + double smallContribThreshold, + bool isProducer): m_pipeBranchesCLCoords(pipeBranchesCLCoords), m_pipeBranchesCellIds(pipeBranchesCellIds), m_tracerCellFractionValues(&tracerCellFractionValues), @@ -39,13 +40,26 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto m_smallContributionsThreshold(smallContribThreshold) { m_accConnectionFlowPrBranch.resize(m_pipeBranchesCellIds.size()); - for ( const auto& it: (*m_tracerCellFractionValues) ) m_tracerNames.push_back(it.first); - - m_tracerNames.push_back(RIG_RESERVOIR_TRACER_NAME); - calculateAccumulatedFlowPrConnection(0, 1); - sortTracers(); - groupSmallContributions(); + if (isWellFlowConsistent(isProducer)) + { + + for ( const auto& it: (*m_tracerCellFractionValues) ) m_tracerNames.push_back(it.first); + + m_tracerNames.push_back(RIG_RESERVOIR_TRACER_NAME); + + calculateAccumulatedFlowPrConnection(0, 1); + sortTracers(); + groupSmallContributions(); + } + else + { + m_tracerCellFractionValues = nullptr; + m_cellIndexCalculator = RigEclCellIndexCalculator(nullptr, nullptr); + m_tracerNames.push_back(RIG_FLOW_TOTAL_NAME); + + calculateAccumulatedFlowPrConnection(0, 1); + } } //-------------------------------------------------------------------------------------------------- @@ -61,7 +75,9 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto m_smallContributionsThreshold(smallContribThreshold) { m_accConnectionFlowPrBranch.resize(m_pipeBranchesCellIds.size()); + m_tracerNames.push_back(RIG_FLOW_TOTAL_NAME); + calculateAccumulatedFlowPrConnection(0, 1); } @@ -134,6 +150,24 @@ std::vector > RigAccWellFlowCalculator::totalTracerFr return totalFlows; } +bool RigAccWellFlowCalculator::isWellFlowConsistent( bool isProducer) +{ + bool isConsistent = true; + for (const std::vector & branch : m_pipeBranchesCellIds) + { + for (const RigWellResultPoint& wrp : branch) + { + if (isProducer) + isConsistent = (wrp.flowRate() >= 0.0) ; + else + isConsistent = (wrp.flowRate() <= 0.0) ; + + if (!isConsistent) break; + } + if (!isConsistent) break; + } + return isConsistent; +} //-------------------------------------------------------------------------------------------------- /// @@ -341,7 +375,7 @@ void RigAccWellFlowCalculator::groupSmallContributions() for ( const auto& tracerPair : totalTracerFractions ) { - if ( tracerPair.second <= m_smallContributionsThreshold ) tracersToGroup.push_back(tracerPair.first); + if ( abs(tracerPair.second) <= m_smallContributionsThreshold ) tracersToGroup.push_back(tracerPair.first); } if ( tracersToGroup.size() < 2 ) return; // Must at least group two ... diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h index 569fb75ac9..024c6c9ea4 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h @@ -61,7 +61,8 @@ public: const std::vector< std::vector >& pipeBranchesCellIds, const std::map* >& tracerCellFractionValues, const RigEclCellIndexCalculator cellIndexCalculator, - double smallContribThreshold); + double smallContribThreshold, + bool isProducer); RigAccWellFlowCalculator(const std::vector< std::vector >& pipeBranchesCLCoords, const std::vector< std::vector >& pipeBranchesCellIds, @@ -75,6 +76,7 @@ public: std::vector > totalTracerFractions(); private: + bool isWellFlowConsistent(bool isProducer); void calculateAccumulatedFlowPrConnection( size_t branchIdx, size_t startConnectionNumberFromTop); std::vector wrpToConnectionIndexFromBottom( const std::vector &branchCells); static size_t connectionIndexFromTop( const std::vector& resPointToConnectionIndexFromBottom, size_t clSegIdx); diff --git a/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.cpp index 5e733241e8..0b5c5ff7ce 100644 --- a/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.cpp @@ -262,6 +262,38 @@ bool RigSingleWellResultsData::isMultiSegmentWell() const } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigWellResultFrame::WellProductionType RigSingleWellResultsData::wellProductionType(size_t resultTimeStepIndex) const +{ + if (hasWellResult(resultTimeStepIndex)) + { + const RigWellResultFrame& wResFrame = wellResultFrame(resultTimeStepIndex); + return wResFrame.m_productionType; + } + else + { + return RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigSingleWellResultsData::isOpen(size_t resultTimeStepIndex) const +{ + if (hasWellResult(resultTimeStepIndex)) + { + const RigWellResultFrame& wResFrame = wellResultFrame(resultTimeStepIndex); + return wResFrame.m_isOpen; + } + else + { + return false; + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h b/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h index 49fa771008..200995f7cb 100644 --- a/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigSingleWellResultsData.h @@ -131,23 +131,25 @@ class RigSingleWellResultsData : public cvf::Object public: RigSingleWellResultsData() { m_isMultiSegmentWell = false; } - void setMultiSegmentWell(bool isMultiSegmentWell); - bool isMultiSegmentWell() const; + void setMultiSegmentWell(bool isMultiSegmentWell); + bool isMultiSegmentWell() const; - bool hasWellResult(size_t resultTimeStepIndex) const; + bool hasWellResult(size_t resultTimeStepIndex) const; + const RigWellResultFrame& wellResultFrame(size_t resultTimeStepIndex) const; + bool isOpen(size_t resultTimeStepIndex) const; + RigWellResultFrame::WellProductionType wellProductionType(size_t resultTimeStepIndex) const; - const RigWellResultFrame& wellResultFrame(size_t resultTimeStepIndex) const; + void computeStaticWellCellPath() const ; + void computeMappingFromResultTimeIndicesToWellTimeIndices(const std::vector& resultTimes); + +public: // Todo: Clean up this regarding public members and constness etc. + QString m_wellName; + + std::vector m_resultTimeStepIndexToWellTimeStepIndex; // Well result timesteps may differ from result timesteps + std::vector< RigWellResultFrame > m_wellCellsTimeSteps; + mutable RigWellResultFrame m_staticWellCells; - void computeStaticWellCellPath() const ; - - void computeMappingFromResultTimeIndicesToWellTimeIndices(const std::vector& resultTimes); - -public: - QString m_wellName; - bool m_isMultiSegmentWell; - - std::vector m_resultTimeStepIndexToWellTimeStepIndex; // Well result timesteps may differ from result timesteps - std::vector< RigWellResultFrame > m_wellCellsTimeSteps; - mutable RigWellResultFrame m_staticWellCells; +private: + bool m_isMultiSegmentWell; };