diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp index 01861a3165..5d138584d1 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp @@ -280,10 +280,7 @@ bool RigAccWellFlowCalculator::isWellFlowConsistent( bool isProducer) const { for (const RigWellResultPoint& wrp : branch) { - if (isProducer) - isConsistent = (wrp.flowRate() >= 0.0) ; - else - isConsistent = (wrp.flowRate() <= 0.0) ; + isConsistent = isFlowRateConsistent(wrp.flowRate()); if (!isConsistent) break; } @@ -295,7 +292,7 @@ bool RigAccWellFlowCalculator::isWellFlowConsistent( bool isProducer) const /// //-------------------------------------------------------------------------------------------------- -std::vector calculateAccumulatedFractions(const std::vector& accumulatedFlowPrTracer ) +std::vector RigAccWellFlowCalculator::calculateAccumulatedFractions(const std::vector& accumulatedFlowPrTracer ) const { double totalFlow = 0.0; for ( double tracerFlow: accumulatedFlowPrTracer) @@ -305,7 +302,7 @@ std::vector calculateAccumulatedFractions(const std::vector& acc std::vector flowFractionsPrTracer(accumulatedFlowPrTracer.size(), 0.0); - if (totalFlow == 0.0) // If we have no accumulated flow, we set all the flow assosciated to the last tracer, which is the reservoir + if (totalFlow == 0.0 || !isFlowRateConsistent(totalFlow)) // If we have no accumulated flow, we set all the flow associated to the last tracer, which is the reservoir { flowFractionsPrTracer.back() = 1.0; return flowFractionsPrTracer; @@ -323,13 +320,20 @@ std::vector calculateAccumulatedFractions(const std::vector& acc //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RigAccWellFlowCalculator::hasConsistentFlow(const RigWellResultPoint &wellCell) const +bool RigAccWellFlowCalculator::isConnectionFlowConsistent(const RigWellResultPoint &wellCell) const { if (!m_tracerCellFractionValues) return true; // No flow diagnostics. - return (wellCell.flowRate() > 0.0 && m_isProducer) || (wellCell.flowRate() < 0.0 && !m_isProducer); + return isFlowRateConsistent (wellCell.flowRate()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigAccWellFlowCalculator::isFlowRateConsistent(double flowRate) const +{ + return (flowRate >= 0.0 && m_isProducer) || (flowRate <= 0.0 && !m_isProducer); +} //-------------------------------------------------------------------------------------------------- /// @@ -369,7 +373,7 @@ void RigAccWellFlowCalculator::calculateAccumulatedFlowPrConnection(size_t branc accFlowPrTracer[tIdx] += flowPrTracer[tIdx]; } - if (!hasConsistentFlow(wellCell)) + if (!isConnectionFlowConsistent(wellCell)) { // Associate all the flow with the reservoir tracer for inconsistent flow direction flowPrTracer = std::vector (flowPrTracer.size(), 0.0 ); @@ -451,7 +455,7 @@ void RigAccWellFlowCalculator::calculateFlowPrPseudoLength(size_t branchIdx, dou // Push back the new start-of-cell flow, with the previously accumulated result into the storage std::vector flowPrTracer; - if (!hasConsistentFlow(wellCell)) + if (!isConnectionFlowConsistent(wellCell)) { // Associate all the flow with the reservoir tracer for inconsistent flow direction flowPrTracer = std::vector (flowPrTracerToAccumulate.size(), 0.0 ); @@ -508,16 +512,68 @@ void RigAccWellFlowCalculator::calculateFlowPrPseudoLength(size_t branchIdx, dou //-------------------------------------------------------------------------------------------------- void RigAccWellFlowCalculator::addDownStreamBranchFlow(std::vector *accFlowPrTracer, const BranchFlow &downStreamBranchFlow) const { - size_t tracerIdx = 0; - for ( const auto & tracerName: m_tracerNames ) + + double totalThisBarnchFlow = 0.0; + for ( double tracerFlow: *accFlowPrTracer) { - auto tracerFlowPair = downStreamBranchFlow.accFlowPrTracer.find(tracerName); - if ( tracerFlowPair != downStreamBranchFlow.accFlowPrTracer.end() ) + totalThisBarnchFlow += tracerFlow; + } + + double totalDsBranchFlow = 0.0; + for ( const auto& tracerFlowPair: downStreamBranchFlow.accFlowPrTracer) + { + totalDsBranchFlow += tracerFlowPair.second.back(); + } + + bool isAccumulationConsistent = isFlowRateConsistent(totalThisBarnchFlow); // If inconsistent, is it always only the Reservoir tracer that has the flow ? + bool isBranchConsistent = isFlowRateConsistent(totalDsBranchFlow); + + + if (isAccumulationConsistent == isBranchConsistent) + { + std::vector accBranchFlowPrTracer = accumulatedDsBranchFlowPrTracer(downStreamBranchFlow); + for ( size_t tracerIdx = 0; tracerIdx < (*accFlowPrTracer).size() ; ++tracerIdx ) { - (*accFlowPrTracer)[tracerIdx] += tracerFlowPair->second.back(); // The topmost accumulated value in the branch + (*accFlowPrTracer)[tracerIdx] += accBranchFlowPrTracer[tracerIdx]; } - tracerIdx++; + return; } + + double totalAccFlow = totalThisBarnchFlow + totalDsBranchFlow; + + if (!isFlowRateConsistent(totalAccFlow)) + { + // Reset the accumulated values, as everything must be moved to the "Reservoir" tracer. + for (double& val : (*accFlowPrTracer) ) val = 0.0; + + // Put all flow into the Reservoir tracer + accFlowPrTracer->back() = totalThisBarnchFlow + totalDsBranchFlow; + + return; + } + + // We will end up with a consistent accumulated flow, and need to keep the accumulated distribution in this branch + // or to use the ds branch distribution + + std::vector accFractionsPrTracer; + + if ( !isAccumulationConsistent && isBranchConsistent ) + { + std::vector accBranchFlowPrTracer = accumulatedDsBranchFlowPrTracer(downStreamBranchFlow); + accFractionsPrTracer = calculateAccumulatedFractions(accBranchFlowPrTracer); + } + else if ( isAccumulationConsistent && !isBranchConsistent ) + { + accFractionsPrTracer = calculateAccumulatedFractions(*accFlowPrTracer); + } + + // Set the accumulated values to the totalFlow times the tracer fraction selected. + + for (size_t tIdx = 0; tIdx < accFlowPrTracer->size(); ++tIdx) + { + (*accFlowPrTracer)[tIdx] = accFractionsPrTracer[tIdx] * (totalAccFlow); + } + } //-------------------------------------------------------------------------------------------------- @@ -553,6 +609,23 @@ void RigAccWellFlowCalculator::storeFlowOnDepthWTvd(BranchFlow *branchFlow, doub branchFlow->trueVerticalDepth.push_back(trueVerticalDepth); } +std::vector RigAccWellFlowCalculator::accumulatedDsBranchFlowPrTracer(const BranchFlow &downStreamBranchFlow) const +{ + std::vector accBranchFlowPrTracer(m_tracerNames.size()); + + size_t tracerIdx = 0; + for ( const auto & tracerName: m_tracerNames ) + { + const auto trNameAccFlowsPair = downStreamBranchFlow.accFlowPrTracer.find(tracerName); + CVF_ASSERT(trNameAccFlowsPair != downStreamBranchFlow.accFlowPrTracer.end()); + + accBranchFlowPrTracer[tracerIdx] = trNameAccFlowsPair->second.back(); + tracerIdx++; + } + + return accBranchFlowPrTracer; +} + //-------------------------------------------------------------------------------------------------- /// Calculate the flow pr tracer. If inconsistent flow, keep the existing fractions constant //-------------------------------------------------------------------------------------------------- @@ -560,7 +633,7 @@ std::vector RigAccWellFlowCalculator::calculateFlowPrTracer(const RigWel { std::vector flowPrTracer(m_tracerNames.size(), 0.0); - if ( !hasConsistentFlow(wellCell) ) + if ( !isConnectionFlowConsistent(wellCell) ) { double flowRate = wellCell.flowRate(); flowPrTracer = calculateAccumulatedFractions(currentAccumulatedFlowPrTracer); diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h index 3ed3ee2dce..e1007fc07a 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h @@ -86,9 +86,10 @@ public: std::vector > totalTracerFractions() const; private: - bool hasConsistentFlow(const RigWellResultPoint &wellCell) const; + bool isConnectionFlowConsistent(const RigWellResultPoint &wellCell) const; + bool isFlowRateConsistent(double flowRate) const; - void calculateAccumulatedFlowPrConnection( size_t branchIdx, + void calculateAccumulatedFlowPrConnection(size_t branchIdx, size_t startConnectionNumberFromTop); void calculateFlowPrPseudoLength(size_t branchIdx, double startPseudoLengthFromTop); @@ -102,7 +103,8 @@ private: const std::vector& tracersToGroup); bool isWellFlowConsistent(bool isProducer) const; - std::vector wrpToUniqueWrpIndexFromBottom( const std::vector &branchCells) const; + std::vector calculateAccumulatedFractions(const std::vector& accumulatedFlowPrTracer) const; + std::vector wrpToUniqueWrpIndexFromBottom(const std::vector &branchCells) const; static size_t connectionIndexFromTop( const std::vector& resPointToConnectionIndexFromBottom, size_t clSegIdx) ; std::vector findDownStreamBranchIdxs( const RigWellResultPoint& connectionPoint) const; @@ -135,7 +137,8 @@ private: const std::vector& accFlowPrTracer, const std::vector& flowPrTracer); - void addDownStreamBranchFlow(std::vector *accFlowPrTracer, + std::vector accumulatedDsBranchFlowPrTracer(const BranchFlow &downStreamBranchFlow) const; + void addDownStreamBranchFlow(std::vector *accFlowPrTracer, const BranchFlow &downStreamBranchFlow) const; std::vector< BranchFlow > m_connectionFlowPrBranch;