ResInsight/ApplicationCode/ProjectDataModel/Flow/RimFlowDiagSolution.cpp
2017-08-11 14:28:42 +02:00

345 lines
13 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimFlowDiagSolution.h"
#include "RiaApplication.h"
#include "RiaColorTables.h"
#include "RigActiveCellInfo.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigFlowDiagResults.h"
#include "RigMainGrid.h"
#include "RigSingleWellResultsData.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseView.h"
#include "RimEclipseWell.h"
#include "RimEclipseWellCollection.h"
CAF_PDM_SOURCE_INIT(RimFlowDiagSolution, "FlowDiagSolution");
#define CROSS_FLOW_ENDING "-XF"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFlowDiagSolution::hasCrossFlowEnding(const QString& tracerName)
{
return tracerName.endsWith(CROSS_FLOW_ENDING);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFlowDiagSolution::removeCrossFlowEnding(const QString& tracerName)
{
if (tracerName.endsWith(CROSS_FLOW_ENDING))
{
return tracerName.left(tracerName.size() - 3);
}
else
{
return tracerName;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFlowDiagSolution::addCrossFlowEnding(const QString& wellName)
{
return wellName + CROSS_FLOW_ENDING;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowDiagSolution::RimFlowDiagSolution(void)
{
CAF_PDM_InitObject("Flow Diagnostics Solution", "", "", "");
CAF_PDM_InitField(&m_userDescription, "UserDescription", QString("All Wells") ,"Description", "", "","");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowDiagSolution::~RimFlowDiagSolution(void)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFlowDiagSolution::userDescription() const
{
return m_userDescription();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFlowDiagResults* RimFlowDiagSolution::flowDiagResults()
{
if ( m_flowDiagResults.isNull() )
{
size_t timeStepCount;
{
RimEclipseResultCase* eclCase;
this->firstAncestorOrThisOfType(eclCase);
CVF_ASSERT(eclCase && eclCase->eclipseCaseData() );
timeStepCount = eclCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL)->maxTimeStepCount();
}
m_flowDiagResults = new RigFlowDiagResults(this, timeStepCount);
}
return m_flowDiagResults.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QString> RimFlowDiagSolution::tracerNames() const
{
RimEclipseResultCase* eclCase;
this->firstAncestorOrThisOfType(eclCase);
std::vector<QString> tracerNameSet;
if (eclCase)
{
const cvf::Collection<RigSingleWellResultsData>& wellResults = eclCase->eclipseCaseData()->wellResults();
for (size_t wIdx = 0; wIdx < wellResults.size(); ++wIdx)
{
tracerNameSet.push_back(wellResults[wIdx]->m_wellName);
tracerNameSet.push_back(addCrossFlowEnding(wellResults[wIdx]->m_wellName));
}
}
return tracerNameSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<std::string, std::vector<int> > RimFlowDiagSolution::allInjectorTracerActiveCellIndices(size_t timeStepIndex) const
{
return allTracerActiveCellIndices(timeStepIndex, true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<std::string, std::vector<int> > RimFlowDiagSolution::allProducerTracerActiveCellIndices(size_t timeStepIndex) const
{
return allTracerActiveCellIndices(timeStepIndex, false);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<std::string, std::vector<int> > RimFlowDiagSolution::allTracerActiveCellIndices(size_t timeStepIndex, bool useInjectors) const
{
RimEclipseResultCase* eclCase;
this->firstAncestorOrThisOfType(eclCase);
std::map<std::string, std::vector<int> > tracersWithCells;
if ( eclCase )
{
const cvf::Collection<RigSingleWellResultsData>& wellResults = eclCase->eclipseCaseData()->wellResults();
RigMainGrid* mainGrid = eclCase->eclipseCaseData()->mainGrid();
RigActiveCellInfo* activeCellInfo = eclCase->eclipseCaseData()->activeCellInfo(RiaDefines::MATRIX_MODEL); //Todo: Must come from the results definition
for ( size_t wIdx = 0; wIdx < wellResults.size(); ++wIdx )
{
if (!wellResults[wIdx]->hasWellResult(timeStepIndex) ) continue;
const RigWellResultFrame& wellResFrame = wellResults[wIdx]->wellResultFrame(timeStepIndex);
bool isInjectorWell = ( wellResFrame.m_productionType != RigWellResultFrame::PRODUCER
&& wellResFrame.m_productionType != RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE);
std::string wellName = wellResults[wIdx]->m_wellName.toStdString();
std::string wellNameXf = addCrossFlowEnding(wellResults[wIdx]->m_wellName).toStdString();
std::vector<int>& tracerCells = tracersWithCells[wellName];
std::vector<int>& tracerCellsCrossFlow = tracersWithCells[wellNameXf];
for (const RigWellResultBranch& wBr: wellResFrame.m_wellResultBranches)
{
for (const RigWellResultPoint& wrp: wBr.m_branchResultPoints)
{
if (wrp.isValid() && wrp.m_isOpen
&& ( (useInjectors && wrp.flowRate() < 0.0) || (!useInjectors && wrp.flowRate() > 0.0) ) )
{
RigGridBase * grid = mainGrid->gridByIndex(wrp.m_gridIndex);
size_t reservoirCellIndex = grid->reservoirCellIndex(wrp.m_gridCellIndex);
int cellActiveIndex = static_cast<int>(activeCellInfo->cellResultIndex(reservoirCellIndex));
if ( useInjectors == isInjectorWell )
{
tracerCells.push_back(cellActiveIndex);
}
else
{
tracerCellsCrossFlow.push_back(cellActiveIndex);
}
}
}
}
if (tracerCells.empty()) tracersWithCells.erase(wellName);
if (tracerCellsCrossFlow.empty()) tracersWithCells.erase(wellNameXf);
}
}
return tracersWithCells;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowDiagSolution::TracerStatusType RimFlowDiagSolution::tracerStatusOverall(const QString& tracerName) const
{
RimEclipseResultCase* eclCase;
this->firstAncestorOrThisOfTypeAsserted(eclCase);
TracerStatusType tracerStatus = UNDEFINED;
const cvf::Collection<RigSingleWellResultsData>& wellResults = eclCase->eclipseCaseData()->wellResults();
for ( size_t wIdx = 0; wIdx < wellResults.size(); ++wIdx )
{
QString wellName = removeCrossFlowEnding(tracerName);
if ( wellResults[wIdx]->m_wellName != wellName ) continue;
tracerStatus = CLOSED;
for ( const RigWellResultFrame& wellResFrame : wellResults[wIdx]->m_wellCellsTimeSteps )
{
if ( wellResFrame.m_productionType == RigWellResultFrame::GAS_INJECTOR
|| wellResFrame.m_productionType == RigWellResultFrame::OIL_INJECTOR
|| wellResFrame.m_productionType == RigWellResultFrame::WATER_INJECTOR )
{
if ( tracerStatus == PRODUCER ) tracerStatus = VARYING;
else tracerStatus = INJECTOR;
}
else if ( wellResFrame.m_productionType == RigWellResultFrame::PRODUCER )
{
if ( tracerStatus == INJECTOR ) tracerStatus = VARYING;
else tracerStatus = PRODUCER;
}
if ( tracerStatus == VARYING ) break;
}
break;
}
if (hasCrossFlowEnding(tracerName))
{
if (tracerStatus == PRODUCER) tracerStatus = INJECTOR;
else if (tracerStatus == INJECTOR) tracerStatus = PRODUCER;
}
return tracerStatus;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowDiagSolution::TracerStatusType RimFlowDiagSolution::tracerStatusInTimeStep(const QString& tracerName, size_t timeStepIndex) const
{
RimEclipseResultCase* eclCase;
this->firstAncestorOrThisOfTypeAsserted(eclCase);
const cvf::Collection<RigSingleWellResultsData>& wellResults = eclCase->eclipseCaseData()->wellResults();
for ( size_t wIdx = 0; wIdx < wellResults.size(); ++wIdx )
{
QString wellName = removeCrossFlowEnding(tracerName);
if ( wellResults[wIdx]->m_wellName != wellName ) continue;
if (!wellResults[wIdx]->hasWellResult(timeStepIndex)) return CLOSED;
const RigWellResultFrame& wellResFrame = wellResults[wIdx]->wellResultFrame(timeStepIndex);
if ( wellResFrame.m_productionType == RigWellResultFrame::GAS_INJECTOR
|| wellResFrame.m_productionType == RigWellResultFrame::OIL_INJECTOR
|| wellResFrame.m_productionType == RigWellResultFrame::WATER_INJECTOR )
{
if ( hasCrossFlowEnding(tracerName) ) return PRODUCER;
return INJECTOR;
}
else if ( wellResFrame.m_productionType == RigWellResultFrame::PRODUCER
|| wellResFrame.m_productionType == RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE )
{
if ( hasCrossFlowEnding(tracerName) ) return INJECTOR;
return PRODUCER;
}
else
{
CVF_ASSERT(false);
}
}
CVF_ASSERT(false);
return UNDEFINED;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimFlowDiagSolution::tracerColor(const QString& tracerName) const
{
QString wellName = removeCrossFlowEnding(tracerName);
if (wellName == RIG_FLOW_TOTAL_NAME) return cvf::Color3f::LIGHT_GRAY;
if (wellName == RIG_RESERVOIR_TRACER_NAME) return cvf::Color3f::LIGHT_GRAY;
if (wellName == RIG_TINY_TRACER_GROUP_NAME) return cvf::Color3f::DARK_GRAY;
RimEclipseResultCase* eclCase;
this->firstAncestorOrThisOfType(eclCase);
if ( eclCase )
{
return eclCase->defaultWellColor(wellName);
}
return cvf::Color3f::LIGHT_GRAY;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimFlowDiagSolution::userDescriptionField()
{
return &m_userDescription;
}