diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp index d654fdaecb..f586d0c5d9 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.cpp @@ -65,28 +65,16 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto m_connectionFlowPrBranch.resize(m_pipeBranchesCellIds.size()); m_pseudoLengthFlowPrBranch.resize(m_pipeBranchesCellIds.size()); - if (isWellFlowConsistent(isProducer)) - { - for ( const auto& it: (*m_tracerCellFractionValues) ) m_tracerNames.push_back(it.first); + for ( const auto& it: (*m_tracerCellFractionValues) ) m_tracerNames.push_back(it.first); - m_tracerNames.push_back(RIG_RESERVOIR_TRACER_NAME); + m_tracerNames.push_back(RIG_RESERVOIR_TRACER_NAME); - calculateAccumulatedFlowPrConnection(0, 1); - calculateFlowPrPseudoLength(0, 0.0); - sortTracers(); - groupSmallContributions(); - } - else - { - m_tracerCellFractionValues = nullptr; - m_cellIndexCalculator = RigEclCellIndexCalculator(nullptr, nullptr); - m_tracerNames.push_back(RIG_FLOW_TOTAL_NAME); + calculateAccumulatedFlowPrConnection(0, 1); + calculateFlowPrPseudoLength(0, 0.0); + sortTracers(); + groupSmallContributions(); - calculateAccumulatedFlowPrConnection(0, 1); - calculateFlowPrPseudoLength(0, 0.0); - - } } //-------------------------------------------------------------------------------------------------- @@ -303,6 +291,45 @@ bool RigAccWellFlowCalculator::isWellFlowConsistent( bool isProducer) const } return isConsistent; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +std::vector calculateAccumulatedFractions(const std::vector& accumulatedFlowPrTracer ) +{ + double totalFlow = 0.0; + for ( double tracerFlow: accumulatedFlowPrTracer) + { + totalFlow += tracerFlow; + } + + 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 + { + flowFractionsPrTracer.back() = 1.0; + return flowFractionsPrTracer; + } + + for ( size_t tIdx = 0; tIdx < accumulatedFlowPrTracer.size(); ++tIdx) + { + double tracerFlow = accumulatedFlowPrTracer[tIdx]; + flowFractionsPrTracer[tIdx] = tracerFlow / totalFlow; + } + + return flowFractionsPrTracer; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigAccWellFlowCalculator::hasConsistentFlow(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); +} + //-------------------------------------------------------------------------------------------------- /// @@ -335,13 +362,20 @@ void RigAccWellFlowCalculator::calculateAccumulatedFlowPrConnection(size_t branc const RigWellResultPoint& wellCell = branchCells[clSegIdx]; - std::vector flowPrTracer = calculateFlowPrTracer(wellCell); + std::vector flowPrTracer = calculateFlowPrTracer(wellCell, accFlowPrTracer); - for (size_t tIdx = 0; tIdx < flowPrTracer.size(); ++tIdx) + for ( size_t tIdx = 0; tIdx < flowPrTracer.size(); ++tIdx ) { accFlowPrTracer[tIdx] += flowPrTracer[tIdx]; } + if (!hasConsistentFlow(wellCell)) + { + // Associate all the flow with the reservoir tracer for inconsistent flow direction + flowPrTracer = std::vector (flowPrTracer.size(), 0.0 ); + flowPrTracer.back() = wellCell.flowRate(); + } + // Add the total accumulated (fraction) flows from any branches connected to this cell size_t connNumFromTop = connectionIndexFromTop(resPointToConnectionIndexFromBottom, clSegIdx) + startConnectionNumberFromTop; @@ -403,21 +437,33 @@ void RigAccWellFlowCalculator::calculateFlowPrPseudoLength(size_t branchIdx, dou cellUpperPointIndex = clSegIdx + 1; currentSegmentIndex = cellUpperPointIndex; } - - std::vector flowPrTracer = calculateFlowPrTracer(branchCells[currentSegmentIndex]); + const RigWellResultPoint& wellCell = branchCells[currentSegmentIndex]; + std::vector flowPrTracerToAccumulate = calculateFlowPrTracer( wellCell, accFlowPrTracer); double pseudoLengthFromTop_lower = mdCalculator.measuredDepths()[cellBottomPointIndex] + startPseudoLengthFromTop; double tvd_lower = -mdCalculator.wellPathPoints()[cellBottomPointIndex][2]; // Push back the new start-of-cell flow, with the previously accumulated result into the storage + std::vector flowPrTracer; + if (!hasConsistentFlow(wellCell)) + { + // Associate all the flow with the reservoir tracer for inconsistent flow direction + flowPrTracer = std::vector (flowPrTracerToAccumulate.size(), 0.0 ); + flowPrTracer.back() = wellCell.flowRate(); + } + else + { + flowPrTracer = flowPrTracerToAccumulate; + } + storeFlowOnDepthWTvd(&branchFlow, pseudoLengthFromTop_lower, tvd_lower, accFlowPrTracer, flowPrTracer); // Accumulate the connection-cell's fraction flows - for (size_t tIdx = 0; tIdx < flowPrTracer.size(); ++tIdx) + for (size_t tIdx = 0; tIdx < flowPrTracerToAccumulate.size(); ++tIdx) { - accFlowPrTracer[tIdx] += flowPrTracer[tIdx]; + accFlowPrTracer[tIdx] += flowPrTracerToAccumulate[tIdx]; } double pseudoLengthFromTop_upper = mdCalculator.measuredDepths()[cellUpperPointIndex] + startPseudoLengthFromTop; @@ -497,6 +543,59 @@ void RigAccWellFlowCalculator::storeFlowOnDepthWTvd(BranchFlow *branchFlow, doub branchFlow->trueVerticalDepth.push_back(trueVerticalDepth); } +//-------------------------------------------------------------------------------------------------- +/// Calculate the flow pr tracer. If inconsistent flow, keep the existing fractions constant +//-------------------------------------------------------------------------------------------------- +std::vector RigAccWellFlowCalculator::calculateFlowPrTracer(const RigWellResultPoint& wellCell, const std::vector& currentAccumulatedFlowPrTracer ) const +{ + std::vector flowPrTracer(m_tracerNames.size(), 0.0); + + if ( !hasConsistentFlow(wellCell) ) + { + double flowRate = wellCell.flowRate(); + flowPrTracer = calculateAccumulatedFractions(currentAccumulatedFlowPrTracer); + for (double & accFraction: flowPrTracer) + { + accFraction *= flowRate; + } + + return flowPrTracer; + } + + if ( m_tracerCellFractionValues ) + { + if ( wellCell.isCell() && wellCell.m_isOpen ) + { + size_t resCellIndex = m_cellIndexCalculator.resultCellIndex(wellCell.m_gridIndex, + wellCell.m_gridCellIndex); + size_t tracerIdx = 0; + double totalTracerFractionInCell = 0.0; + for ( const auto & tracerFractionIt: (*m_tracerCellFractionValues) ) + { + double cellTracerFraction = (*tracerFractionIt.second)[resCellIndex]; + if ( cellTracerFraction != HUGE_VAL && cellTracerFraction == cellTracerFraction ) + { + double tracerFlow = cellTracerFraction * wellCell.flowRate(); + flowPrTracer[tracerIdx] = tracerFlow; + + totalTracerFractionInCell += cellTracerFraction; + } + tracerIdx++; + } + + double reservoirFraction = 1.0 - totalTracerFractionInCell; + double reservoirTracerFlow = reservoirFraction * wellCell.flowRate(); + flowPrTracer[tracerIdx] = reservoirTracerFlow; + } + } + else + { + flowPrTracer[0] = wellCell.flowRate(); + } + + return flowPrTracer; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -645,6 +744,8 @@ void RigAccWellFlowCalculator::groupSmallContributions() std::vector tracersToGroup; { + bool hasConsistentWellFlow = isWellFlowConsistent(m_isProducer); + std::vector > totalTracerFractions = this->totalTracerFractions(); if ( totalTracerFractions.size() < 5 ) return; // No grouping for few legend items @@ -652,7 +753,11 @@ void RigAccWellFlowCalculator::groupSmallContributions() for ( const auto& tracerPair : totalTracerFractions ) { - if ( abs(tracerPair.second) <= m_smallContributionsThreshold ) tracersToGroup.push_back(tracerPair.first); + if ( abs(tracerPair.second) <= m_smallContributionsThreshold + && (hasConsistentWellFlow || tracerPair.first != RIG_RESERVOIR_TRACER_NAME) ) // Do not group the Reservoir tracer if the well flow is inconsistent, because cross flow is shown as the reservoir fraction + { + tracersToGroup.push_back(tracerPair.first); + } } } diff --git a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h index 2ce39c178c..bc6d770859 100644 --- a/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h +++ b/ApplicationCode/ReservoirDataModel/RigAccWellFlowCalculator.h @@ -86,16 +86,16 @@ public: std::vector > totalTracerFractions() const; private: + bool hasConsistentFlow(const RigWellResultPoint &wellCell) const; void calculateAccumulatedFlowPrConnection( size_t branchIdx, size_t startConnectionNumberFromTop); - void calculateFlowPrPseudoLength(size_t branchIdx, + void calculateFlowPrPseudoLength(size_t branchIdx, double startPseudoLengthFromTop); - - std::vector calculateFlowPrTracer(const RigWellResultPoint& wellCell) const; - + std::vector calculateFlowPrTracer(const RigWellResultPoint& wellCell, + const std::vector& currentAccumulatedFlowPrTracer ) const; void sortTracers(); void groupSmallContributions();