#1313 Improved handling of branch contributions in wells with accumulated crossflow in branches

This commit is contained in:
Jacob Støren 2017-03-15 16:33:42 +01:00
parent be3ed0d934
commit e6953a6f8b
2 changed files with 97 additions and 21 deletions

View File

@ -280,10 +280,7 @@ bool RigAccWellFlowCalculator::isWellFlowConsistent( bool isProducer) const
{ {
for (const RigWellResultPoint& wrp : branch) for (const RigWellResultPoint& wrp : branch)
{ {
if (isProducer) isConsistent = isFlowRateConsistent(wrp.flowRate());
isConsistent = (wrp.flowRate() >= 0.0) ;
else
isConsistent = (wrp.flowRate() <= 0.0) ;
if (!isConsistent) break; if (!isConsistent) break;
} }
@ -295,7 +292,7 @@ bool RigAccWellFlowCalculator::isWellFlowConsistent( bool isProducer) const
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<double> calculateAccumulatedFractions(const std::vector<double>& accumulatedFlowPrTracer ) std::vector<double> RigAccWellFlowCalculator::calculateAccumulatedFractions(const std::vector<double>& accumulatedFlowPrTracer ) const
{ {
double totalFlow = 0.0; double totalFlow = 0.0;
for ( double tracerFlow: accumulatedFlowPrTracer) for ( double tracerFlow: accumulatedFlowPrTracer)
@ -305,7 +302,7 @@ std::vector<double> calculateAccumulatedFractions(const std::vector<double>& acc
std::vector<double> flowFractionsPrTracer(accumulatedFlowPrTracer.size(), 0.0); std::vector<double> 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; flowFractionsPrTracer.back() = 1.0;
return flowFractionsPrTracer; return flowFractionsPrTracer;
@ -323,13 +320,20 @@ std::vector<double> calculateAccumulatedFractions(const std::vector<double>& acc
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RigAccWellFlowCalculator::hasConsistentFlow(const RigWellResultPoint &wellCell) const bool RigAccWellFlowCalculator::isConnectionFlowConsistent(const RigWellResultPoint &wellCell) const
{ {
if (!m_tracerCellFractionValues) return true; // No flow diagnostics. 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]; accFlowPrTracer[tIdx] += flowPrTracer[tIdx];
} }
if (!hasConsistentFlow(wellCell)) if (!isConnectionFlowConsistent(wellCell))
{ {
// Associate all the flow with the reservoir tracer for inconsistent flow direction // Associate all the flow with the reservoir tracer for inconsistent flow direction
flowPrTracer = std::vector<double> (flowPrTracer.size(), 0.0 ); flowPrTracer = std::vector<double> (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 // Push back the new start-of-cell flow, with the previously accumulated result into the storage
std::vector<double> flowPrTracer; std::vector<double> flowPrTracer;
if (!hasConsistentFlow(wellCell)) if (!isConnectionFlowConsistent(wellCell))
{ {
// Associate all the flow with the reservoir tracer for inconsistent flow direction // Associate all the flow with the reservoir tracer for inconsistent flow direction
flowPrTracer = std::vector<double> (flowPrTracerToAccumulate.size(), 0.0 ); flowPrTracer = std::vector<double> (flowPrTracerToAccumulate.size(), 0.0 );
@ -508,16 +512,68 @@ void RigAccWellFlowCalculator::calculateFlowPrPseudoLength(size_t branchIdx, dou
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RigAccWellFlowCalculator::addDownStreamBranchFlow(std::vector<double> *accFlowPrTracer, const BranchFlow &downStreamBranchFlow) const void RigAccWellFlowCalculator::addDownStreamBranchFlow(std::vector<double> *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); totalThisBarnchFlow += tracerFlow;
if ( tracerFlowPair != downStreamBranchFlow.accFlowPrTracer.end() ) }
double totalDsBranchFlow = 0.0;
for ( const auto& tracerFlowPair: downStreamBranchFlow.accFlowPrTracer)
{ {
(*accFlowPrTracer)[tracerIdx] += tracerFlowPair->second.back(); // The topmost accumulated value in the branch totalDsBranchFlow += tracerFlowPair.second.back();
} }
tracerIdx++;
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<double> accBranchFlowPrTracer = accumulatedDsBranchFlowPrTracer(downStreamBranchFlow);
for ( size_t tracerIdx = 0; tracerIdx < (*accFlowPrTracer).size() ; ++tracerIdx )
{
(*accFlowPrTracer)[tracerIdx] += accBranchFlowPrTracer[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<double> accFractionsPrTracer;
if ( !isAccumulationConsistent && isBranchConsistent )
{
std::vector<double> 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); branchFlow->trueVerticalDepth.push_back(trueVerticalDepth);
} }
std::vector<double> RigAccWellFlowCalculator::accumulatedDsBranchFlowPrTracer(const BranchFlow &downStreamBranchFlow) const
{
std::vector<double> 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 /// Calculate the flow pr tracer. If inconsistent flow, keep the existing fractions constant
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -560,7 +633,7 @@ std::vector<double> RigAccWellFlowCalculator::calculateFlowPrTracer(const RigWel
{ {
std::vector<double> flowPrTracer(m_tracerNames.size(), 0.0); std::vector<double> flowPrTracer(m_tracerNames.size(), 0.0);
if ( !hasConsistentFlow(wellCell) ) if ( !isConnectionFlowConsistent(wellCell) )
{ {
double flowRate = wellCell.flowRate(); double flowRate = wellCell.flowRate();
flowPrTracer = calculateAccumulatedFractions(currentAccumulatedFlowPrTracer); flowPrTracer = calculateAccumulatedFractions(currentAccumulatedFlowPrTracer);

View File

@ -86,9 +86,10 @@ public:
std::vector<std::pair<QString, double> > totalTracerFractions() const; std::vector<std::pair<QString, double> > totalTracerFractions() const;
private: 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); size_t startConnectionNumberFromTop);
void calculateFlowPrPseudoLength(size_t branchIdx, void calculateFlowPrPseudoLength(size_t branchIdx,
double startPseudoLengthFromTop); double startPseudoLengthFromTop);
@ -102,7 +103,8 @@ private:
const std::vector<QString>& tracersToGroup); const std::vector<QString>& tracersToGroup);
bool isWellFlowConsistent(bool isProducer) const; bool isWellFlowConsistent(bool isProducer) const;
std::vector<size_t> wrpToUniqueWrpIndexFromBottom( const std::vector<RigWellResultPoint> &branchCells) const; std::vector<double> calculateAccumulatedFractions(const std::vector<double>& accumulatedFlowPrTracer) const;
std::vector<size_t> wrpToUniqueWrpIndexFromBottom(const std::vector<RigWellResultPoint> &branchCells) const;
static size_t connectionIndexFromTop( const std::vector<size_t>& resPointToConnectionIndexFromBottom, size_t clSegIdx) ; static size_t connectionIndexFromTop( const std::vector<size_t>& resPointToConnectionIndexFromBottom, size_t clSegIdx) ;
std::vector<size_t> findDownStreamBranchIdxs( const RigWellResultPoint& connectionPoint) const; std::vector<size_t> findDownStreamBranchIdxs( const RigWellResultPoint& connectionPoint) const;
@ -135,6 +137,7 @@ private:
const std::vector<double>& accFlowPrTracer, const std::vector<double>& accFlowPrTracer,
const std::vector<double>& flowPrTracer); const std::vector<double>& flowPrTracer);
std::vector<double> accumulatedDsBranchFlowPrTracer(const BranchFlow &downStreamBranchFlow) const;
void addDownStreamBranchFlow(std::vector<double> *accFlowPrTracer, void addDownStreamBranchFlow(std::vector<double> *accFlowPrTracer,
const BranchFlow &downStreamBranchFlow) const; const BranchFlow &downStreamBranchFlow) const;