From ed31dab152de8a70da14721ed7d8e7cbf0ecd7ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 15 Feb 2017 08:46:23 +0100 Subject: [PATCH] #1172 Calculated a grouped tracer contribution value of the tracers below a certain threshold. --- .../Flow/RimWellAllocationPlot.cpp | 59 ++++----- .../Flow/RimWellAllocationPlot.h | 5 + .../RigAccWellFlowCalculator.cpp | 123 +++++++++++++++++- .../RigAccWellFlowCalculator.h | 19 ++- 4 files changed, 166 insertions(+), 40 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp index 5c0ce41de0..26a5475b7f 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp @@ -70,6 +70,8 @@ RimWellAllocationPlot::RimWellAllocationPlot() CAF_PDM_InitField(&m_timeStep, "PlotTimeStep", 0, "Time Step", "", "", ""); CAF_PDM_InitField(&m_wellName, "WellName", QString("None"), "Well", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_flowDiagSolution, "FlowDiagSolution", "Flow Diag Solution", "", "", ""); + CAF_PDM_InitField(&m_groupSmallContributions, "GroupSmallContributions", true, "Group Small Contributions", "", "", ""); + CAF_PDM_InitField(&m_smallContributionsThreshold, "SmallContributionsThreshold", 0.005, "Threshold", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_accumulatedWellFlowPlot, "AccumulatedWellFlowPlot", "Accumulated Well Flow", "", "", ""); m_accumulatedWellFlowPlot.uiCapability()->setUiHidden(true); @@ -181,6 +183,9 @@ void RimWellAllocationPlot::updateFromWell() pipeBranchesCellIds); 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)) { @@ -214,7 +219,8 @@ void RimWellAllocationPlot::updateFromWell() wfCalculator.reset(new RigAccWellFlowCalculator(pipeBranchesCLCoords, pipeBranchesCellIds, tracerCellFractionValues, - cellIdxCalc)); + cellIdxCalc, + smallContributionThreshold)); } } @@ -223,7 +229,8 @@ void RimWellAllocationPlot::updateFromWell() if (pipeBranchesCLCoords.size() > 0) { wfCalculator.reset(new RigAccWellFlowCalculator(pipeBranchesCLCoords, - pipeBranchesCellIds)); + pipeBranchesCellIds, + smallContributionThreshold)); } } @@ -243,8 +250,6 @@ void RimWellAllocationPlot::updateFromWell() RimWellLogTrack* plotTrack = new RimWellLogTrack(); - // TODO: Description is overwritten by RimWellLogPlot::updateTrackNames() - // Add flag to control if this behavior plotTrack->setDescription(QString("Branch %1").arg(brIdx + 1)); accumulatedWellFlowPlot()->addTrack(plotTrack); @@ -285,34 +290,20 @@ void RimWellAllocationPlot::updateFromWell() if (wfCalculator) { - std::vector tracerNames = wfCalculator->tracerNames(); - std::vector > tracerWithValues; + std::vector > totalTracerFractions = wfCalculator->totalTracerFractions() ; - for (const QString& tracerName: tracerNames) + for ( const auto& tracerVal : totalTracerFractions ) { - const std::vector& accFlow = wfCalculator->accumulatedTracerFlowPrConnection(tracerName, 0); - tracerWithValues.push_back(std::make_pair(tracerName, accFlow.back())); - } + cvf::Color3f color; + if ( m_flowDiagSolution ) + color = m_flowDiagSolution->tracerColor(tracerVal.first); + else + color = cvf::Color3f::DARK_GRAY; - float sumTracerVals = 0.0f; - for ( const auto& tracerVal:tracerWithValues) - { - sumTracerVals += tracerVal.second; - } + double tracerPercent = 100*tracerVal.second; - if ( sumTracerVals != 0.0f ) - { - for ( const auto& tracerVal : tracerWithValues ) - { - cvf::Color3f color; - if ( m_flowDiagSolution ) - color = m_flowDiagSolution->tracerColor(tracerVal.first); - else - color = cvf::Color3f::DARK_GRAY; - - m_totalWellAllocationPlot->addSlice(tracerVal.first, color, 100*tracerVal.second/sumTracerVals); - if (m_wellAllocationPlotWidget) m_wellAllocationPlotWidget->addLegendItem(tracerVal.first, color, 100*tracerVal.second/sumTracerVals); - } + m_totalWellAllocationPlot->addSlice(tracerVal.first, color, tracerPercent); + if ( m_wellAllocationPlotWidget ) m_wellAllocationPlotWidget->addLegendItem(tracerVal.first, color, tracerPercent); } } @@ -592,7 +583,9 @@ void RimWellAllocationPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedF else if ( changedField == &m_wellName || changedField == &m_case || changedField == &m_timeStep - || changedField == &m_flowDiagSolution) + || changedField == &m_flowDiagSolution + || changedField == &m_groupSmallContributions + || changedField == &m_smallContributionsThreshold ) { loadDataAndUpdate(); } @@ -614,6 +607,14 @@ QImage RimWellAllocationPlot::snapshotWindowContent() return image; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellAllocationPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + m_smallContributionsThreshold.uiCapability()->setUiReadOnly(!m_groupSmallContributions()); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h index 30f1b4a11e..b9d4adf667 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h +++ b/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.h @@ -81,6 +81,9 @@ protected: virtual QImage snapshotWindowContent() override; + + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; + private: void updateFromWell(); void updateWellFlowPlotXAxisTitle(RimWellLogTrack* plotTrack); @@ -106,6 +109,8 @@ private: caf::PdmField m_wellName; caf::PdmField m_timeStep; caf::PdmPtrField m_flowDiagSolution; + caf::PdmField m_groupSmallContributions; + caf::PdmField m_smallContributionsThreshold; QPointer m_wellAllocationPlotWidget; diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp index 609a52e7c9..e39b7d0e9b 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp @@ -30,11 +30,13 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vector >& pipeBranchesCLCoords, const std::vector< std::vector >& pipeBranchesCellIds, const std::map* >& tracerCellFractionValues, - const RigEclCellIndexCalculator cellIndexCalculator): + const RigEclCellIndexCalculator cellIndexCalculator, + double smallContribThreshold): m_pipeBranchesCLCoords(pipeBranchesCLCoords), m_pipeBranchesCellIds(pipeBranchesCellIds), m_tracerCellFractionValues(&tracerCellFractionValues), - m_cellIndexCalculator(cellIndexCalculator) + m_cellIndexCalculator(cellIndexCalculator), + m_smallContributionsThreshold(smallContribThreshold) { m_accConnectionFlowPrBranch.resize(m_pipeBranchesCellIds.size()); for ( const auto& it: (*m_tracerCellFractionValues) ) m_tracerNames.push_back(it.first); @@ -43,17 +45,20 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto calculateAccumulatedFlowPrConnection(0, 1); sortTracers(); - + groupSmallContributions(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vector >& pipeBranchesCLCoords, const std::vector< std::vector >& pipeBranchesCellIds): +RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vector >& pipeBranchesCLCoords, + const std::vector< std::vector >& pipeBranchesCellIds, + double smallContribThreshold ): m_pipeBranchesCLCoords(pipeBranchesCLCoords), m_pipeBranchesCellIds(pipeBranchesCellIds), m_tracerCellFractionValues(nullptr), - m_cellIndexCalculator(RigEclCellIndexCalculator(nullptr, nullptr)) + m_cellIndexCalculator(RigEclCellIndexCalculator(nullptr, nullptr)), + m_smallContributionsThreshold(smallContribThreshold) { m_accConnectionFlowPrBranch.resize(m_pipeBranchesCellIds.size()); m_tracerNames.push_back(RIG_FLOW_TOTAL_NAME); @@ -88,6 +93,48 @@ const std::vector& RigAccWellFlowCalculator::connectionNumbersFromTop(si return m_accConnectionFlowPrBranch[branchIdx].connectionNumbersFromTop; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector > RigAccWellFlowCalculator::totalWellFlowPrTracer() +{ + std::vector tracerNames = this->tracerNames(); + std::vector > tracerWithValues; + + for (const QString& tracerName: tracerNames) + { + const std::vector& accFlow = this->accumulatedTracerFlowPrConnection(tracerName, 0); + tracerWithValues.push_back(std::make_pair(tracerName, accFlow.back())); + } + + return tracerWithValues; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector > RigAccWellFlowCalculator::totalTracerFractions() +{ + std::vector > totalFlows = totalWellFlowPrTracer(); + + float sumTracerFlows = 0.0f; + for ( const auto& tracerVal : totalFlows) + { + sumTracerFlows += tracerVal.second; + } + + if (sumTracerFlows == 0.0) totalFlows.clear(); + + for (auto& tracerPair : totalFlows) + { + tracerPair.second = tracerPair.second/sumTracerFlows; + } + + return totalFlows; +} + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -255,6 +302,10 @@ std::vector RigAccWellFlowCalculator::findDownstreamBranchIdxs(const Rig return downStreamBranchIdxs; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + void RigAccWellFlowCalculator::sortTracers() { std::multimap sortedTracers; @@ -271,4 +322,64 @@ void RigAccWellFlowCalculator::sortTracers() { m_tracerNames.push_back(tracerPair.second); } -} \ No newline at end of file +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigAccWellFlowCalculator::groupSmallContributions() +{ + // Concatenate small tracers into an "Other" group + + if ( m_smallContributionsThreshold > 0.0 ) + { + std::vector > totalTracerFractions = this->totalTracerFractions(); + + if ( totalTracerFractions.size() < 5 ) return; // No grouping for few legend items + + std::vector tracersToGroup; + + for ( const auto& tracerPair : totalTracerFractions ) + { + if ( tracerPair.second <= m_smallContributionsThreshold ) tracersToGroup.push_back(tracerPair.first); + } + + if ( tracersToGroup.size() < 2 ) return; // Must at least group two ... + + for ( BranchResult& brRes : m_accConnectionFlowPrBranch ) + { + std::vector groupedConnectionValues(brRes.connectionNumbersFromTop.size(), 0.0); + for ( const QString& tracername:tracersToGroup ) + { + auto it = brRes.accConnFlowFractionsPrTracer.find(tracername); + if ( it != brRes.accConnFlowFractionsPrTracer.end() ) + { + const std::vector& tracerVals = it->second; + for ( size_t cIdx = 0; cIdx < groupedConnectionValues.size(); ++cIdx ) + { + groupedConnectionValues[cIdx] += tracerVals[cIdx]; + } + } + brRes.accConnFlowFractionsPrTracer.erase(it); + } + + brRes.accConnFlowFractionsPrTracer[RIG_TINY_TRACER_GROUP_NAME] = groupedConnectionValues; + } + + std::vector filteredTracernames; + for ( const QString& tracerName: m_tracerNames ) + { + bool isDeleted = false; + for ( const QString& deletedTracerName: tracersToGroup ) + { + if ( tracerName == deletedTracerName ) { isDeleted = true; break; } + } + + if ( !isDeleted ) filteredTracernames.push_back(tracerName); + } + + m_tracerNames.swap(filteredTracernames); + m_tracerNames.push_back(RIG_TINY_TRACER_GROUP_NAME); + } +} + diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h index def2bfedb7..569fb75ac9 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h @@ -57,31 +57,40 @@ class RigAccWellFlowCalculator { public: - RigAccWellFlowCalculator(const std::vector< std::vector >& pipeBranchesCLCoords, + RigAccWellFlowCalculator(const std::vector< std::vector >& pipeBranchesCLCoords, const std::vector< std::vector >& pipeBranchesCellIds, - const std::map* >& tracerCellFractionValues, - const RigEclCellIndexCalculator cellIndexCalculator); + const std::map* >& tracerCellFractionValues, + const RigEclCellIndexCalculator cellIndexCalculator, + double smallContribThreshold); - RigAccWellFlowCalculator(const std::vector< std::vector >& pipeBranchesCLCoords, - const std::vector< std::vector >& pipeBranchesCellIds); + RigAccWellFlowCalculator(const std::vector< std::vector >& pipeBranchesCLCoords, + const std::vector< std::vector >& pipeBranchesCellIds, + double smallContribThreshold); const std::vector& accumulatedTotalFlowPrConnection( size_t branchIdx);// const; const std::vector& accumulatedTracerFlowPrConnection(const QString& tracerName, size_t branchIdx);// const; const std::vector& connectionNumbersFromTop(size_t branchIdx) const; const std::vector& tracerNames() const { return m_tracerNames;} + + std::vector > totalTracerFractions(); private: 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); std::vector findDownstreamBranchIdxs( const RigWellResultPoint& connectionPoint); + + std::vector > totalWellFlowPrTracer() ; void sortTracers(); + void groupSmallContributions(); + const std::vector< std::vector >& m_pipeBranchesCLCoords; const std::vector< std::vector >& m_pipeBranchesCellIds; const std::map* >* m_tracerCellFractionValues; RigEclCellIndexCalculator m_cellIndexCalculator; std::vector m_tracerNames; + double m_smallContributionsThreshold; struct BranchResult {