#1203 Well Alloc Plots for wells with inconsistent flow does now include accumulated allocation factors. The direct well flow rates is also shown with allocation, but the inconsistent flow connections are assigned to the Reservoir tracer.

This commit is contained in:
Jacob Støren 2017-03-10 11:50:17 +01:00
parent 2f17096cde
commit 028f9458e9
2 changed files with 134 additions and 29 deletions

View File

@ -65,8 +65,6 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto
m_connectionFlowPrBranch.resize(m_pipeBranchesCellIds.size()); m_connectionFlowPrBranch.resize(m_pipeBranchesCellIds.size());
m_pseudoLengthFlowPrBranch.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);
@ -76,17 +74,7 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto
calculateFlowPrPseudoLength(0, 0.0); calculateFlowPrPseudoLength(0, 0.0);
sortTracers(); sortTracers();
groupSmallContributions(); 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);
}
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -303,6 +291,45 @@ bool RigAccWellFlowCalculator::isWellFlowConsistent( bool isProducer) const
} }
return isConsistent; return isConsistent;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> calculateAccumulatedFractions(const std::vector<double>& accumulatedFlowPrTracer )
{
double totalFlow = 0.0;
for ( double tracerFlow: accumulatedFlowPrTracer)
{
totalFlow += tracerFlow;
}
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
{
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]; const RigWellResultPoint& wellCell = branchCells[clSegIdx];
std::vector<double> flowPrTracer = calculateFlowPrTracer(wellCell); std::vector<double> 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]; accFlowPrTracer[tIdx] += flowPrTracer[tIdx];
} }
if (!hasConsistentFlow(wellCell))
{
// Associate all the flow with the reservoir tracer for inconsistent flow direction
flowPrTracer = std::vector<double> (flowPrTracer.size(), 0.0 );
flowPrTracer.back() = wellCell.flowRate();
}
// Add the total accumulated (fraction) flows from any branches connected to this cell // Add the total accumulated (fraction) flows from any branches connected to this cell
size_t connNumFromTop = connectionIndexFromTop(resPointToConnectionIndexFromBottom, clSegIdx) + startConnectionNumberFromTop; size_t connNumFromTop = connectionIndexFromTop(resPointToConnectionIndexFromBottom, clSegIdx) + startConnectionNumberFromTop;
@ -403,21 +437,33 @@ void RigAccWellFlowCalculator::calculateFlowPrPseudoLength(size_t branchIdx, dou
cellUpperPointIndex = clSegIdx + 1; cellUpperPointIndex = clSegIdx + 1;
currentSegmentIndex = cellUpperPointIndex; currentSegmentIndex = cellUpperPointIndex;
} }
const RigWellResultPoint& wellCell = branchCells[currentSegmentIndex];
std::vector<double> flowPrTracer = calculateFlowPrTracer(branchCells[currentSegmentIndex]); std::vector<double> flowPrTracerToAccumulate = calculateFlowPrTracer( wellCell, accFlowPrTracer);
double pseudoLengthFromTop_lower = mdCalculator.measuredDepths()[cellBottomPointIndex] + startPseudoLengthFromTop; double pseudoLengthFromTop_lower = mdCalculator.measuredDepths()[cellBottomPointIndex] + startPseudoLengthFromTop;
double tvd_lower = -mdCalculator.wellPathPoints()[cellBottomPointIndex][2]; double tvd_lower = -mdCalculator.wellPathPoints()[cellBottomPointIndex][2];
// 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;
if (!hasConsistentFlow(wellCell))
{
// Associate all the flow with the reservoir tracer for inconsistent flow direction
flowPrTracer = std::vector<double> (flowPrTracerToAccumulate.size(), 0.0 );
flowPrTracer.back() = wellCell.flowRate();
}
else
{
flowPrTracer = flowPrTracerToAccumulate;
}
storeFlowOnDepthWTvd(&branchFlow, pseudoLengthFromTop_lower, tvd_lower, accFlowPrTracer, flowPrTracer); storeFlowOnDepthWTvd(&branchFlow, pseudoLengthFromTop_lower, tvd_lower, accFlowPrTracer, flowPrTracer);
// Accumulate the connection-cell's fraction flows // 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; double pseudoLengthFromTop_upper = mdCalculator.measuredDepths()[cellUpperPointIndex] + startPseudoLengthFromTop;
@ -497,6 +543,59 @@ void RigAccWellFlowCalculator::storeFlowOnDepthWTvd(BranchFlow *branchFlow, doub
branchFlow->trueVerticalDepth.push_back(trueVerticalDepth); branchFlow->trueVerticalDepth.push_back(trueVerticalDepth);
} }
//--------------------------------------------------------------------------------------------------
/// Calculate the flow pr tracer. If inconsistent flow, keep the existing fractions constant
//--------------------------------------------------------------------------------------------------
std::vector<double> RigAccWellFlowCalculator::calculateFlowPrTracer(const RigWellResultPoint& wellCell, const std::vector<double>& currentAccumulatedFlowPrTracer ) const
{
std::vector<double> 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<QString> tracersToGroup; std::vector<QString> tracersToGroup;
{ {
bool hasConsistentWellFlow = isWellFlowConsistent(m_isProducer);
std::vector<std::pair<QString, double> > totalTracerFractions = this->totalTracerFractions(); std::vector<std::pair<QString, double> > totalTracerFractions = this->totalTracerFractions();
if ( totalTracerFractions.size() < 5 ) return; // No grouping for few legend items if ( totalTracerFractions.size() < 5 ) return; // No grouping for few legend items
@ -652,7 +753,11 @@ void RigAccWellFlowCalculator::groupSmallContributions()
for ( const auto& tracerPair : totalTracerFractions ) 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);
}
} }
} }

View File

@ -86,16 +86,16 @@ 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;
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);
std::vector<double> calculateFlowPrTracer(const RigWellResultPoint& wellCell) const; std::vector<double> calculateFlowPrTracer(const RigWellResultPoint& wellCell) const;
std::vector<double> calculateFlowPrTracer(const RigWellResultPoint& wellCell,
const std::vector<double>& currentAccumulatedFlowPrTracer ) const;
void sortTracers(); void sortTracers();
void groupSmallContributions(); void groupSmallContributions();