mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-10 15:36:09 -06:00
#1313 Improved handling of branch contributions in wells with accumulated crossflow in branches
This commit is contained in:
parent
be3ed0d934
commit
e6953a6f8b
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user