#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)
{
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<double> calculateAccumulatedFractions(const std::vector<double>& accumulatedFlowPrTracer )
std::vector<double> RigAccWellFlowCalculator::calculateAccumulatedFractions(const std::vector<double>& accumulatedFlowPrTracer ) const
{
double totalFlow = 0.0;
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);
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<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.
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<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
std::vector<double> flowPrTracer;
if (!hasConsistentFlow(wellCell))
if (!isConnectionFlowConsistent(wellCell))
{
// Associate all the flow with the reservoir tracer for inconsistent flow direction
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
{
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<double> 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<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);
}
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
//--------------------------------------------------------------------------------------------------
@ -560,7 +633,7 @@ std::vector<double> RigAccWellFlowCalculator::calculateFlowPrTracer(const RigWel
{
std::vector<double> flowPrTracer(m_tracerNames.size(), 0.0);
if ( !hasConsistentFlow(wellCell) )
if ( !isConnectionFlowConsistent(wellCell) )
{
double flowRate = wellCell.flowRate();
flowPrTracer = calculateAccumulatedFractions(currentAccumulatedFlowPrTracer);

View File

@ -86,9 +86,10 @@ public:
std::vector<std::pair<QString, double> > 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<QString>& tracersToGroup);
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) ;
std::vector<size_t> findDownStreamBranchIdxs( const RigWellResultPoint& connectionPoint) const;
@ -135,7 +137,8 @@ private:
const std::vector<double>& accFlowPrTracer,
const std::vector<double>& flowPrTracer);
void addDownStreamBranchFlow(std::vector<double> *accFlowPrTracer,
std::vector<double> accumulatedDsBranchFlowPrTracer(const BranchFlow &downStreamBranchFlow) const;
void addDownStreamBranchFlow(std::vector<double> *accFlowPrTracer,
const BranchFlow &downStreamBranchFlow) const;
std::vector< BranchFlow > m_connectionFlowPrBranch;