#1211 Disabled tracer allocation for wells with inconsistent flow.

This commit is contained in:
Jacob Støren 2017-02-15 12:29:36 +01:00
parent ad5e18afa6
commit 4fc0839a33
6 changed files with 151 additions and 62 deletions

View File

@ -181,50 +181,26 @@ void RimWellAllocationPlot::updateFromWell()
true,
pipeBranchesCLCoords,
pipeBranchesCellIds);
std::map<QString, const std::vector<double>* > tracerCellFractionValues = findRelevantTracerCellFractions(wellResults);
std::unique_ptr< RigAccWellFlowCalculator > wfCalculator;
std::map<QString, const std::vector<double>* > tracerCellFractionValues;
double smallContributionThreshold = 0.0;
if (m_groupSmallContributions()) smallContributionThreshold = m_smallContributionsThreshold;
if ( m_flowDiagSolution && wellResults->hasWellResult(m_timeStep))
if ( tracerCellFractionValues.size() )
{
RimFlowDiagSolution::TracerStatusType requestedTracerType = RimFlowDiagSolution::UNDEFINED;
const RigWellResultFrame& wellResultFrame = wellResults->wellResultFrame(m_timeStep);
if (wellResultFrame.m_productionType == RigWellResultFrame::PRODUCER)
{
requestedTracerType = RimFlowDiagSolution::INJECTOR;
}
else
{
requestedTracerType = RimFlowDiagSolution::PRODUCER;
}
std::vector<QString> tracerNames = m_flowDiagSolution->tracerNames();
for ( const QString& tracerName : tracerNames )
{
if (m_flowDiagSolution->tracerStatusInTimeStep(tracerName, m_timeStep) == requestedTracerType)
{
RigFlowDiagResultAddress resAddr(RIG_FLD_CELL_FRACTION_RESNAME, tracerName.toStdString());
const std::vector<double>* tracerCellFractions = m_flowDiagSolution->flowDiagResults()->resultValues(resAddr, m_timeStep);
tracerCellFractionValues[tracerName] = tracerCellFractions;
}
}
if ( tracerCellFractionValues.size() )
{
RigEclCellIndexCalculator cellIdxCalc(m_case->reservoirData()->mainGrid(), m_case->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS));
wfCalculator.reset(new RigAccWellFlowCalculator(pipeBranchesCLCoords,
pipeBranchesCellIds,
tracerCellFractionValues,
cellIdxCalc,
smallContributionThreshold));
}
bool isProducer = wellResults->wellProductionType(m_timeStep) == RigWellResultFrame::PRODUCER ;
RigEclCellIndexCalculator cellIdxCalc(m_case->reservoirData()->mainGrid(), m_case->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS));
wfCalculator.reset(new RigAccWellFlowCalculator(pipeBranchesCLCoords,
pipeBranchesCellIds,
tracerCellFractionValues,
cellIdxCalc,
smallContributionThreshold,
isProducer));
}
if (!wfCalculator)
else
{
if (pipeBranchesCLCoords.size() > 0)
{
@ -314,6 +290,45 @@ void RimWellAllocationPlot::updateFromWell()
if (m_wellAllocationPlotWidget) m_wellAllocationPlotWidget->updateGeometry();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<QString, const std::vector<double> *> RimWellAllocationPlot::findRelevantTracerCellFractions(const RigSingleWellResultsData* wellResults)
{
std::map<QString, const std::vector<double> *> tracerCellFractionValues;
if ( m_flowDiagSolution && wellResults->isOpen(m_timeStep) )
{
RimFlowDiagSolution::TracerStatusType requestedTracerType = RimFlowDiagSolution::UNDEFINED;
const RigWellResultFrame::WellProductionType prodType = wellResults->wellProductionType(m_timeStep);
if ( prodType == RigWellResultFrame::PRODUCER )
{
requestedTracerType = RimFlowDiagSolution::INJECTOR;
}
else if (prodType != RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE)
{
requestedTracerType = RimFlowDiagSolution::PRODUCER;
}
if ( prodType != RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE )
{
std::vector<QString> tracerNames = m_flowDiagSolution->tracerNames();
for ( const QString& tracerName : tracerNames )
{
if ( m_flowDiagSolution->tracerStatusInTimeStep(tracerName, m_timeStep) == requestedTracerType )
{
RigFlowDiagResultAddress resAddr(RIG_FLD_CELL_FRACTION_RESNAME, tracerName.toStdString());
const std::vector<double>* tracerCellFractions = m_flowDiagSolution->flowDiagResults()->resultValues(resAddr, m_timeStep);
tracerCellFractionValues[tracerName] = tracerCellFractions;
}
}
}
}
return tracerCellFractionValues;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -35,6 +35,7 @@ class RimWellAllocationPlotLegend;
class RimWellLogPlot;
class RiuWellAllocationPlot;
class RimWellLogTrack;
class RigSingleWellResultsData;
namespace caf {
class PdmOptionItemInfo;
@ -86,6 +87,9 @@ protected:
private:
void updateFromWell();
std::map<QString, const std::vector<double> *> findRelevantTracerCellFractions(const RigSingleWellResultsData* wellResults);
void updateWellFlowPlotXAxisTitle(RimWellLogTrack* plotTrack);
void addStackedCurve(const QString& tracerName,

View File

@ -31,7 +31,8 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto
const std::vector< std::vector <RigWellResultPoint> >& pipeBranchesCellIds,
const std::map<QString, const std::vector<double>* >& tracerCellFractionValues,
const RigEclCellIndexCalculator cellIndexCalculator,
double smallContribThreshold):
double smallContribThreshold,
bool isProducer):
m_pipeBranchesCLCoords(pipeBranchesCLCoords),
m_pipeBranchesCellIds(pipeBranchesCellIds),
m_tracerCellFractionValues(&tracerCellFractionValues),
@ -39,13 +40,26 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto
m_smallContributionsThreshold(smallContribThreshold)
{
m_accConnectionFlowPrBranch.resize(m_pipeBranchesCellIds.size());
for ( const auto& it: (*m_tracerCellFractionValues) ) m_tracerNames.push_back(it.first);
m_tracerNames.push_back(RIG_RESERVOIR_TRACER_NAME);
if (isWellFlowConsistent(isProducer))
{
calculateAccumulatedFlowPrConnection(0, 1);
sortTracers();
groupSmallContributions();
for ( const auto& it: (*m_tracerCellFractionValues) ) m_tracerNames.push_back(it.first);
m_tracerNames.push_back(RIG_RESERVOIR_TRACER_NAME);
calculateAccumulatedFlowPrConnection(0, 1);
sortTracers();
groupSmallContributions();
}
else
{
m_tracerCellFractionValues = nullptr;
m_cellIndexCalculator = RigEclCellIndexCalculator(nullptr, nullptr);
m_tracerNames.push_back(RIG_FLOW_TOTAL_NAME);
calculateAccumulatedFlowPrConnection(0, 1);
}
}
//--------------------------------------------------------------------------------------------------
@ -61,7 +75,9 @@ RigAccWellFlowCalculator::RigAccWellFlowCalculator(const std::vector< std::vecto
m_smallContributionsThreshold(smallContribThreshold)
{
m_accConnectionFlowPrBranch.resize(m_pipeBranchesCellIds.size());
m_tracerNames.push_back(RIG_FLOW_TOTAL_NAME);
calculateAccumulatedFlowPrConnection(0, 1);
}
@ -134,6 +150,24 @@ std::vector<std::pair<QString, double> > RigAccWellFlowCalculator::totalTracerFr
return totalFlows;
}
bool RigAccWellFlowCalculator::isWellFlowConsistent( bool isProducer)
{
bool isConsistent = true;
for (const std::vector <RigWellResultPoint> & branch : m_pipeBranchesCellIds)
{
for (const RigWellResultPoint& wrp : branch)
{
if (isProducer)
isConsistent = (wrp.flowRate() >= 0.0) ;
else
isConsistent = (wrp.flowRate() <= 0.0) ;
if (!isConsistent) break;
}
if (!isConsistent) break;
}
return isConsistent;
}
//--------------------------------------------------------------------------------------------------
///
@ -341,7 +375,7 @@ void RigAccWellFlowCalculator::groupSmallContributions()
for ( const auto& tracerPair : totalTracerFractions )
{
if ( tracerPair.second <= m_smallContributionsThreshold ) tracersToGroup.push_back(tracerPair.first);
if ( abs(tracerPair.second) <= m_smallContributionsThreshold ) tracersToGroup.push_back(tracerPair.first);
}
if ( tracersToGroup.size() < 2 ) return; // Must at least group two ...

View File

@ -61,7 +61,8 @@ public:
const std::vector< std::vector <RigWellResultPoint> >& pipeBranchesCellIds,
const std::map<QString, const std::vector<double>* >& tracerCellFractionValues,
const RigEclCellIndexCalculator cellIndexCalculator,
double smallContribThreshold);
double smallContribThreshold,
bool isProducer);
RigAccWellFlowCalculator(const std::vector< std::vector <cvf::Vec3d> >& pipeBranchesCLCoords,
const std::vector< std::vector <RigWellResultPoint> >& pipeBranchesCellIds,
@ -75,6 +76,7 @@ public:
std::vector<std::pair<QString, double> > totalTracerFractions();
private:
bool isWellFlowConsistent(bool isProducer);
void calculateAccumulatedFlowPrConnection( size_t branchIdx, size_t startConnectionNumberFromTop);
std::vector<size_t> wrpToConnectionIndexFromBottom( const std::vector<RigWellResultPoint> &branchCells);
static size_t connectionIndexFromTop( const std::vector<size_t>& resPointToConnectionIndexFromBottom, size_t clSegIdx);

View File

@ -262,6 +262,38 @@ bool RigSingleWellResultsData::isMultiSegmentWell() const
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigWellResultFrame::WellProductionType RigSingleWellResultsData::wellProductionType(size_t resultTimeStepIndex) const
{
if (hasWellResult(resultTimeStepIndex))
{
const RigWellResultFrame& wResFrame = wellResultFrame(resultTimeStepIndex);
return wResFrame.m_productionType;
}
else
{
return RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigSingleWellResultsData::isOpen(size_t resultTimeStepIndex) const
{
if (hasWellResult(resultTimeStepIndex))
{
const RigWellResultFrame& wResFrame = wellResultFrame(resultTimeStepIndex);
return wResFrame.m_isOpen;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -131,23 +131,25 @@ class RigSingleWellResultsData : public cvf::Object
public:
RigSingleWellResultsData() { m_isMultiSegmentWell = false; }
void setMultiSegmentWell(bool isMultiSegmentWell);
bool isMultiSegmentWell() const;
void setMultiSegmentWell(bool isMultiSegmentWell);
bool isMultiSegmentWell() const;
bool hasWellResult(size_t resultTimeStepIndex) const;
bool hasWellResult(size_t resultTimeStepIndex) const;
const RigWellResultFrame& wellResultFrame(size_t resultTimeStepIndex) const;
bool isOpen(size_t resultTimeStepIndex) const;
RigWellResultFrame::WellProductionType wellProductionType(size_t resultTimeStepIndex) const;
const RigWellResultFrame& wellResultFrame(size_t resultTimeStepIndex) const;
void computeStaticWellCellPath() const ;
void computeMappingFromResultTimeIndicesToWellTimeIndices(const std::vector<QDateTime>& resultTimes);
void computeStaticWellCellPath() const ;
public: // Todo: Clean up this regarding public members and constness etc.
QString m_wellName;
void computeMappingFromResultTimeIndicesToWellTimeIndices(const std::vector<QDateTime>& resultTimes);
std::vector<size_t> m_resultTimeStepIndexToWellTimeStepIndex; // Well result timesteps may differ from result timesteps
std::vector< RigWellResultFrame > m_wellCellsTimeSteps;
mutable RigWellResultFrame m_staticWellCells;
public:
QString m_wellName;
bool m_isMultiSegmentWell;
std::vector<size_t> m_resultTimeStepIndexToWellTimeStepIndex; // Well result timesteps may differ from result timesteps
std::vector< RigWellResultFrame > m_wellCellsTimeSteps;
mutable RigWellResultFrame m_staticWellCells;
private:
bool m_isMultiSegmentWell;
};