2016-12-16 07:17:56 -06:00
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigFlowDiagSolverInterface.h"
2016-12-20 04:41:05 -06:00
# include "RifEclipseOutputFileTools.h"
2017-01-09 12:14:07 -06:00
# include "RifReaderInterface.h"
# include "RigActiveCellInfo.h"
# include "RigCaseCellResultsData.h"
2017-01-10 02:51:39 -06:00
# include "RigEclipseCaseData.h"
2017-03-13 05:03:34 -05:00
2017-01-09 12:14:07 -06:00
# include "RigFlowDiagInterfaceTools.h"
2017-03-13 05:03:34 -05:00
# include "opm/flowdiagnostics/DerivedQuantities.hpp"
2017-01-09 12:14:07 -06:00
2017-10-27 02:38:24 -05:00
# include "opm/utility/ECLSaturationFunc.hpp"
# include "opm/utility/ECLPvtCurveCollection.hpp"
2016-12-20 04:41:05 -06:00
# include "RimEclipseCase.h"
2017-01-09 12:14:07 -06:00
# include "RimEclipseResultCase.h"
# include "RimFlowDiagSolution.h"
2016-12-20 04:41:05 -06:00
# include <QMessageBox>
2017-01-12 09:36:48 -06:00
# include "cafProgressInfo.h"
2016-12-16 07:17:56 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFlowDiagTimeStepResult : : RigFlowDiagTimeStepResult ( size_t activeCellCount )
2017-08-09 07:10:39 -05:00
: m_activeCellCount ( activeCellCount )
2016-12-20 04:41:05 -06:00
{
}
2016-12-16 07:17:56 -06:00
2016-12-20 04:41:05 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-08-10 08:08:30 -05:00
void RigFlowDiagTimeStepResult : : setTracerTOF ( const std : : string & tracerName ,
RigFlowDiagResultAddress : : PhaseSelection phaseSelection ,
const std : : map < int , double > & cellValues )
2016-12-20 04:41:05 -06:00
{
std : : set < std : : string > tracers ;
tracers . insert ( tracerName ) ;
2017-01-06 08:12:13 -06:00
2017-08-10 08:08:30 -05:00
RigFlowDiagResultAddress resAddr ( RIG_FLD_TOF_RESNAME , phaseSelection , tracers ) ;
2016-12-20 04:41:05 -06:00
2017-01-06 08:12:13 -06:00
this - > addResult ( resAddr , cellValues ) ;
2016-12-20 04:41:05 -06:00
2017-01-06 08:12:13 -06:00
std : : vector < double > & activeCellValues = m_nativeResults [ resAddr ] ;
for ( double & val : activeCellValues )
{
val = val * 1.15741e-5 ; // days pr second. Converting to days
}
2016-12-20 04:41:05 -06:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-08-10 08:08:30 -05:00
void RigFlowDiagTimeStepResult : : setTracerFraction ( const std : : string & tracerName ,
RigFlowDiagResultAddress : : PhaseSelection phaseSelection ,
const std : : map < int , double > & cellValues )
2016-12-20 04:41:05 -06:00
{
std : : set < std : : string > tracers ;
tracers . insert ( tracerName ) ;
2017-08-10 08:08:30 -05:00
this - > addResult ( RigFlowDiagResultAddress ( RIG_FLD_CELL_FRACTION_RESNAME , phaseSelection , tracers ) , cellValues ) ;
2016-12-20 04:41:05 -06:00
}
2016-12-16 07:17:56 -06:00
2017-03-13 05:03:34 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFlowDiagTimeStepResult : : setInjProdWellPairFlux ( const std : : string & injectorTracerName ,
const std : : string & producerTracerName ,
const std : : pair < double , double > & injProdFluxes )
{
m_injProdWellPairFluxes [ std : : make_pair ( injectorTracerName , producerTracerName ) ] = injProdFluxes ;
}
2016-12-16 07:17:56 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2016-12-20 04:41:05 -06:00
void RigFlowDiagTimeStepResult : : addResult ( const RigFlowDiagResultAddress & resAddr , const std : : map < int , double > & cellValues )
2016-12-16 07:17:56 -06:00
{
2016-12-20 04:41:05 -06:00
std : : vector < double > & activeCellValues = m_nativeResults [ resAddr ] ;
2017-03-22 08:04:13 -05:00
CVF_ASSERT ( activeCellValues . empty ( ) ) ;
2016-12-20 04:41:05 -06:00
activeCellValues . resize ( m_activeCellCount , HUGE_VAL ) ;
2016-12-16 07:17:56 -06:00
2016-12-20 04:41:05 -06:00
for ( const auto & pairIt : cellValues )
{
activeCellValues [ pairIt . first ] = pairIt . second ;
}
}
2017-01-06 07:41:00 -06:00
2017-05-12 05:22:50 -05:00
class RigOpmFlowDiagStaticData : public cvf : : Object
2017-01-06 07:41:00 -06:00
{
public :
2017-05-12 05:22:50 -05:00
RigOpmFlowDiagStaticData ( const std : : string & grid , const std : : string & init )
2017-03-24 09:10:39 -05:00
{
2017-05-12 05:22:50 -05:00
Opm : : ECLInitFileData initData ( init ) ;
m_eclGraph . reset ( new Opm : : ECLGraph ( Opm : : ECLGraph : : load ( grid , initData ) ) ) ;
m_hasUnifiedRestartFile = false ;
m_poreVolume = m_eclGraph - > poreVolume ( ) ;
2017-10-27 02:38:24 -05:00
m_eclSaturationFunc . reset ( new Opm : : ECLSaturationFunc ( * m_eclGraph , initData ) ) ;
//m_eclPvtCurveCollection.reset(new Opm::ECLPVT::ECLPvtCurveCollection(*m_eclGraph, initData));
2017-03-24 09:10:39 -05:00
}
2017-01-06 07:41:00 -06:00
2017-05-12 05:22:50 -05:00
std : : unique_ptr < Opm : : ECLGraph > m_eclGraph ;
2017-03-24 09:10:39 -05:00
std : : vector < double > m_poreVolume ;
std : : unique_ptr < Opm : : FlowDiagnostics : : Toolbox > m_fldToolbox ;
bool m_hasUnifiedRestartFile ;
2017-05-12 05:22:50 -05:00
std : : vector < Opm : : ECLRestartData > m_singleRestartDataTimeSteps ;
std : : unique_ptr < Opm : : ECLRestartData > m_unifiedRestartData ;
2017-10-27 02:38:24 -05:00
std : : unique_ptr < Opm : : ECLSaturationFunc > m_eclSaturationFunc ;
// std::unique_ptr<Opm::ECLPVT::ECLPvtCurveCollection> m_eclPvtCurveCollection;
2017-01-06 07:41:00 -06:00
} ;
2016-12-20 04:41:05 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFlowDiagSolverInterface : : RigFlowDiagSolverInterface ( RimEclipseResultCase * eclipseCase )
: m_eclipseCase ( eclipseCase )
{
2016-12-16 07:17:56 -06:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFlowDiagSolverInterface : : ~ RigFlowDiagSolverInterface ( )
{
}
2017-10-11 11:02:00 -05:00
#if 0
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void removeCrossFlowCells ( std : : pair < const std : : string , std : : vector < int > > & tracerCellIdxsPair ,
std : : map < Opm : : FlowDiagnostics : : CellSetID , Opm : : FlowDiagnostics : : CellSetValues > & WellInFluxPrCell ,
std : : function < bool ( double ) > isFlowOkFunction )
{
std : : string tracerName = tracerCellIdxsPair . first ;
tracerName = RimFlowDiagSolution : : removeCrossFlowEnding ( QString : : fromStdString ( tracerName ) ) . toStdString ( ) ;
auto cellSetIdInFlowsPair = WellInFluxPrCell . find ( Opm : : FlowDiagnostics : : CellSetID ( tracerName ) ) ;
CVF_TIGHT_ASSERT ( cellSetIdInFlowsPair ! = WellInFluxPrCell . end ( ) ) ;
std : : vector < int > filteredCellIndices ;
for ( int activeCellIdx : tracerCellIdxsPair . second )
{
auto activeCellIdxFluxPair = cellSetIdInFlowsPair - > second . find ( activeCellIdx ) ;
CVF_TIGHT_ASSERT ( activeCellIdxFluxPair ! = cellSetIdInFlowsPair - > second . end ( ) ) ;
if ( isFlowOkFunction ( activeCellIdxFluxPair - > second ) )
{
filteredCellIndices . push_back ( activeCellIdx ) ;
}
}
if ( tracerCellIdxsPair . second . size ( ) ! = filteredCellIndices . size ( ) )
{
tracerCellIdxsPair . second = filteredCellIndices ;
}
}
# endif
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : string removeCrossFlowEnding ( std : : string tracerName )
{
return RimFlowDiagSolution : : removeCrossFlowEnding ( QString : : fromStdString ( tracerName ) ) . toStdString ( ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool hasCrossFlowEnding ( std : : string tracerName )
{
return RimFlowDiagSolution : : hasCrossFlowEnding ( QString : : fromStdString ( tracerName ) ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : string addCrossFlowEnding ( std : : string tracerName )
{
return RimFlowDiagSolution : : addCrossFlowEnding ( QString : : fromStdString ( tracerName ) ) . toStdString ( ) ;
}
2017-01-06 07:41:00 -06:00
2016-12-16 07:17:56 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2016-12-20 04:41:05 -06:00
RigFlowDiagTimeStepResult RigFlowDiagSolverInterface : : calculate ( size_t timeStepIndex ,
2017-08-10 08:08:30 -05:00
RigFlowDiagResultAddress : : PhaseSelection phaseSelection ,
2016-12-20 04:41:05 -06:00
std : : map < std : : string , std : : vector < int > > injectorTracers ,
std : : map < std : : string , std : : vector < int > > producerTracers )
2016-12-16 07:17:56 -06:00
{
2016-12-20 04:41:05 -06:00
using namespace Opm : : FlowDiagnostics ;
2017-08-11 07:05:59 -05:00
RigFlowDiagTimeStepResult result ( m_eclipseCase - > eclipseCaseData ( ) - > activeCellInfo ( RiaDefines : : MATRIX_MODEL ) - > reservoirActiveCellCount ( ) ) ;
2016-12-20 04:41:05 -06:00
2017-03-13 05:03:34 -05:00
caf : : ProgressInfo progressInfo ( 8 , " Calculating Flow Diagnostics " ) ;
2017-01-12 09:36:48 -06:00
2017-01-06 07:41:00 -06:00
{
2017-01-12 09:36:48 -06:00
progressInfo . setProgressDescription ( " Grid access " ) ;
2017-10-27 02:38:24 -05:00
if ( ! ensureStaticDataObjectInstanceCreated ( ) )
{
return result ;
}
2016-12-20 04:41:05 -06:00
2017-01-12 09:36:48 -06:00
progressInfo . incrementProgress ( ) ;
progressInfo . setProgressDescription ( " Calculating Connectivities " ) ;
2017-10-27 02:38:24 -05:00
CVF_ASSERT ( m_opmFlowDiagStaticData . notNull ( ) ) ;
2017-01-06 07:41:00 -06:00
const Opm : : FlowDiagnostics : : ConnectivityGraph connGraph =
2017-05-12 05:22:50 -05:00
Opm : : FlowDiagnostics : : ConnectivityGraph { static_cast < int > ( m_opmFlowDiagStaticData - > m_eclGraph - > numCells ( ) ) ,
m_opmFlowDiagStaticData - > m_eclGraph - > neighbours ( ) } ;
2016-12-20 04:41:05 -06:00
2017-01-12 09:36:48 -06:00
progressInfo . incrementProgress ( ) ;
progressInfo . setProgressDescription ( " Initialize Solver " ) ;
2017-01-06 07:41:00 -06:00
// Create the Toolbox.
2016-12-20 04:41:05 -06:00
2017-05-12 05:22:50 -05:00
m_opmFlowDiagStaticData - > m_fldToolbox . reset ( new Opm : : FlowDiagnostics : : Toolbox { connGraph } ) ;
m_opmFlowDiagStaticData - > m_fldToolbox - > assignPoreVolume ( m_opmFlowDiagStaticData - > m_poreVolume ) ;
2016-12-20 08:33:39 -06:00
2017-01-06 07:41:00 -06:00
// Look for unified restart file
2017-08-10 03:09:01 -05:00
QStringList m_filesWithSameBaseName ;
2017-10-27 02:38:24 -05:00
QString gridFileName = m_eclipseCase - > gridFileName ( ) ;
2017-08-10 03:09:01 -05:00
if ( ! RifEclipseOutputFileTools : : findSiblingFilesWithSameBaseName ( gridFileName , & m_filesWithSameBaseName ) ) return result ;
2016-12-20 08:33:39 -06:00
2017-01-06 07:41:00 -06:00
QString restartFileName = RifEclipseOutputFileTools : : firstFileNameOfType ( m_filesWithSameBaseName , ECL_UNIFIED_RESTART_FILE ) ;
if ( ! restartFileName . isEmpty ( ) )
{
2017-05-12 05:22:50 -05:00
m_opmFlowDiagStaticData - > m_unifiedRestartData . reset ( new Opm : : ECLRestartData ( Opm : : ECLRestartData ( restartFileName . toStdString ( ) ) ) ) ;
m_opmFlowDiagStaticData - > m_hasUnifiedRestartFile = true ;
2017-01-06 07:41:00 -06:00
}
else
2016-12-20 04:41:05 -06:00
{
2017-05-12 05:22:50 -05:00
QStringList restartFileNames = RifEclipseOutputFileTools : : filterFileNamesOfType ( m_filesWithSameBaseName , ECL_RESTART_FILE ) ;
2017-01-06 07:41:00 -06:00
2017-05-12 05:22:50 -05:00
size_t restartFileCount = static_cast < size_t > ( restartFileNames . size ( ) ) ;
2017-08-11 07:05:59 -05:00
size_t maxTimeStepCount = m_eclipseCase - > eclipseCaseData ( ) - > results ( RiaDefines : : MATRIX_MODEL ) - > maxTimeStepCount ( ) ;
2017-01-06 07:41:00 -06:00
2017-05-12 05:22:50 -05:00
if ( restartFileCount < = timeStepIndex & & restartFileCount ! = maxTimeStepCount )
2017-01-06 07:41:00 -06:00
{
QMessageBox : : critical ( nullptr , " ResInsight " , " Flow Diagnostics: Could not find all the restart files. Results will not be loaded. " ) ;
return result ;
}
2017-05-12 05:22:50 -05:00
restartFileNames . sort ( ) ; // To make sure they are sorted in increasing *.X000N order. Hack. Should probably be actual time stored on file.
m_opmFlowDiagStaticData - > m_hasUnifiedRestartFile = false ;
for ( auto restartFileName : restartFileNames )
{
m_opmFlowDiagStaticData - > m_singleRestartDataTimeSteps . push_back ( Opm : : ECLRestartData ( restartFileName . toStdString ( ) ) ) ;
}
2016-12-20 04:41:05 -06:00
}
2017-01-06 07:41:00 -06:00
}
2017-01-12 09:36:48 -06:00
progressInfo . setProgress ( 3 ) ;
progressInfo . setProgressDescription ( " Assigning Flux Field " ) ;
2016-12-20 04:41:05 -06:00
2017-05-12 05:22:50 -05:00
Opm : : ECLRestartData * currentRestartData = nullptr ;
if ( ! m_opmFlowDiagStaticData - > m_hasUnifiedRestartFile )
2017-01-06 07:41:00 -06:00
{
2017-05-12 05:22:50 -05:00
currentRestartData = & ( m_opmFlowDiagStaticData - > m_singleRestartDataTimeSteps [ timeStepIndex ] ) ;
}
else
{
currentRestartData = m_opmFlowDiagStaticData - > m_unifiedRestartData . get ( ) ;
2016-12-20 04:41:05 -06:00
}
2017-05-12 05:22:50 -05:00
CVF_ASSERT ( currentRestartData ) ;
2017-01-12 05:04:54 -06:00
size_t resultIndexWithMaxTimeSteps = cvf : : UNDEFINED_SIZE_T ;
2017-08-11 07:05:59 -05:00
m_eclipseCase - > eclipseCaseData ( ) - > results ( RiaDefines : : MATRIX_MODEL ) - > maxTimeStepCount ( & resultIndexWithMaxTimeSteps ) ;
2016-12-20 04:41:05 -06:00
2017-08-11 07:05:59 -05:00
int reportStepNumber = m_eclipseCase - > eclipseCaseData ( ) - > results ( RiaDefines : : MATRIX_MODEL ) - > reportStepNumber ( resultIndexWithMaxTimeSteps , timeStepIndex ) ;
2017-01-12 05:04:54 -06:00
2017-05-12 05:22:50 -05:00
if ( ! currentRestartData - > selectReportStep ( reportStepNumber ) )
2016-12-20 04:41:05 -06:00
{
QMessageBox : : critical ( nullptr , " ResInsight " , " Flow Diagnostics: Could not find the requested timestep in the result file. Results will not be loaded. " ) ;
return result ;
}
2017-01-06 07:41:00 -06:00
// Set up flow Toolbox with timestep data
2017-10-11 11:02:00 -05:00
std : : map < Opm : : FlowDiagnostics : : CellSetID , Opm : : FlowDiagnostics : : CellSetValues > WellInFluxPrCell ;
2017-03-13 05:03:34 -05:00
2016-12-20 04:41:05 -06:00
{
2017-08-11 07:05:59 -05:00
if ( m_eclipseCase - > eclipseCaseData ( ) - > results ( RiaDefines : : MATRIX_MODEL ) - > hasFlowDiagUsableFluxes ( ) )
2017-08-10 03:09:01 -05:00
{
Opm : : FlowDiagnostics : : ConnectionValues connectionsVals = RigFlowDiagInterfaceTools : : extractFluxFieldFromRestartFile ( * ( m_opmFlowDiagStaticData - > m_eclGraph ) ,
2017-08-10 08:08:30 -05:00
* currentRestartData ,
phaseSelection ) ;
2017-08-10 03:09:01 -05:00
m_opmFlowDiagStaticData - > m_fldToolbox - > assignConnectionFlux ( connectionsVals ) ;
}
else
{
Opm : : ECLInitFileData init ( getInitFileName ( ) ) ;
2017-10-11 11:02:00 -05:00
Opm : : FlowDiagnostics : : ConnectionValues connectionVals = RigFlowDiagInterfaceTools : : calculateFluxField ( ( * m_opmFlowDiagStaticData - > m_eclGraph ) ,
init ,
* currentRestartData ,
phaseSelection ) ;
2017-08-10 03:09:01 -05:00
m_opmFlowDiagStaticData - > m_fldToolbox - > assignConnectionFlux ( connectionVals ) ;
}
2016-12-20 04:41:05 -06:00
2017-01-12 09:36:48 -06:00
progressInfo . incrementProgress ( ) ;
2017-02-28 09:03:43 -06:00
Opm : : ECLWellSolution wsol = Opm : : ECLWellSolution { - 1.0 , false } ;
2017-01-06 07:41:00 -06:00
2017-05-12 05:22:50 -05:00
std : : vector < std : : string > gridNames = m_opmFlowDiagStaticData - > m_eclGraph - > activeGrids ( ) ;
const std : : vector < Opm : : ECLWellSolution : : WellData > well_fluxes = wsol . solution ( * currentRestartData , gridNames ) ;
2017-01-06 07:41:00 -06:00
2017-10-11 11:02:00 -05:00
WellInFluxPrCell = RigFlowDiagInterfaceTools : : extractWellFlows ( * ( m_opmFlowDiagStaticData - > m_eclGraph ) , well_fluxes ) ;
2017-03-09 09:05:48 -06:00
2017-10-11 11:02:00 -05:00
m_opmFlowDiagStaticData - > m_fldToolbox - > assignInflowFlux ( WellInFluxPrCell ) ;
2017-03-09 09:05:48 -06:00
2017-10-11 11:02:00 -05:00
#if 0
2017-05-12 05:22:50 -05:00
// Start Hack: Filter connection cells with inconsistent well in flow direction (Hack, we should do something better)
2017-03-09 09:05:48 -06:00
for ( auto & tracerCellIdxsPair : injectorTracers )
{
std : : vector < int > filteredCellIndices ;
for ( int activeCellIdx : tracerCellIdxsPair . second )
{
2017-10-11 11:02:00 -05:00
auto activeCellIdxFluxPair = WellInFluxPrCell . find ( activeCellIdx ) ;
CVF_TIGHT_ASSERT ( activeCellIdxFluxPair ! = WellInFluxPrCell . end ( ) ) ;
2017-05-12 05:22:50 -05:00
2017-03-09 09:05:48 -06:00
if ( activeCellIdxFluxPair - > second > 0 )
{
filteredCellIndices . push_back ( activeCellIdx ) ;
}
}
if ( tracerCellIdxsPair . second . size ( ) ! = filteredCellIndices . size ( ) ) tracerCellIdxsPair . second = filteredCellIndices ;
}
for ( auto & tracerCellIdxsPair : producerTracers )
{
std : : vector < int > filteredCellIndices ;
for ( int activeCellIdx : tracerCellIdxsPair . second )
{
2017-10-11 11:02:00 -05:00
auto activeCellIdxFluxPair = WellInFluxPrCell . find ( activeCellIdx ) ;
CVF_TIGHT_ASSERT ( activeCellIdxFluxPair ! = WellInFluxPrCell . end ( ) ) ;
2017-05-12 05:22:50 -05:00
2017-03-09 09:05:48 -06:00
if ( activeCellIdxFluxPair - > second < 0 )
{
filteredCellIndices . push_back ( activeCellIdx ) ;
}
}
if ( tracerCellIdxsPair . second . size ( ) ! = filteredCellIndices . size ( ) ) tracerCellIdxsPair . second = filteredCellIndices ;
}
2017-10-11 11:02:00 -05:00
2017-05-12 05:22:50 -05:00
// End Hack
2017-10-11 11:02:00 -05:00
// New Filtering Probably not neccesary
for ( auto & tracerCellIdxsPair : injectorTracers )
{
removeCrossFlowCells ( tracerCellIdxsPair , WellInFluxPrCell , [ ] ( double inFlow ) { return inFlow > 0 ; } ) ;
}
for ( auto & tracerCellIdxsPair : producerTracers )
{
removeCrossFlowCells ( tracerCellIdxsPair , WellInFluxPrCell , [ ] ( double inFlow ) { return inFlow < 0 ; } ) ;
}
# endif
2017-01-06 07:41:00 -06:00
}
2017-01-12 09:36:48 -06:00
progressInfo . incrementProgress ( ) ;
progressInfo . setProgressDescription ( " Injector Solution " ) ;
2017-01-06 07:41:00 -06:00
{
2017-03-13 05:03:34 -05:00
// Injection Solution
2017-10-11 11:02:00 -05:00
std : : set < std : : string > injectorCrossFlowTracers ;
2017-03-13 05:03:34 -05:00
std : : vector < CellSet > injectorCellSets ;
std : : unique_ptr < Toolbox : : Forward > injectorSolution ;
2016-12-20 04:41:05 -06:00
{
2017-10-11 11:02:00 -05:00
for ( const auto & tIt : injectorTracers )
{
std : : string tracerName = tIt . first ;
if ( hasCrossFlowEnding ( tracerName ) )
{
tracerName = removeCrossFlowEnding ( tracerName ) ;
injectorCrossFlowTracers . insert ( tracerName ) ;
}
injectorCellSets . push_back ( CellSet ( CellSetID ( tracerName ) , tIt . second ) ) ;
}
2016-12-20 04:41:05 -06:00
2017-10-11 11:02:00 -05:00
try
{
injectorSolution . reset ( new Toolbox : : Forward ( m_opmFlowDiagStaticData - > m_fldToolbox - > computeInjectionDiagnostics ( injectorCellSets ) ) ) ;
}
catch ( const std : : exception & e )
{
QMessageBox : : critical ( nullptr , " ResInsight " , " Flow Diagnostics: " + QString ( e . what ( ) ) ) ;
return result ;
}
for ( const CellSetID & tracerId : injectorSolution - > fd . startPoints ( ) )
{
std : : string tracername = tracerId . to_string ( ) ;
if ( injectorCrossFlowTracers . count ( tracername ) ) tracername = addCrossFlowEnding ( tracername ) ;
CellSetValues tofVals = injectorSolution - > fd . timeOfFlight ( tracerId ) ;
result . setTracerTOF ( tracername , phaseSelection , tofVals ) ;
CellSetValues fracVals = injectorSolution - > fd . concentration ( tracerId ) ;
result . setTracerFraction ( tracername , phaseSelection , fracVals ) ;
}
2017-03-13 05:03:34 -05:00
}
2017-01-12 09:36:48 -06:00
2017-03-13 05:03:34 -05:00
progressInfo . incrementProgress ( ) ;
progressInfo . setProgressDescription ( " Producer Solution " ) ;
// Producer Solution
2017-10-11 11:02:00 -05:00
std : : set < std : : string > producerCrossFlowTracers ;
2017-03-13 05:03:34 -05:00
std : : vector < CellSet > prodjCellSets ;
std : : unique_ptr < Toolbox : : Reverse > producerSolution ;
2017-03-06 09:33:29 -06:00
{
2017-10-11 11:02:00 -05:00
for ( const auto & tIt : producerTracers )
{
std : : string tracerName = tIt . first ;
if ( hasCrossFlowEnding ( tracerName ) )
{
tracerName = removeCrossFlowEnding ( tracerName ) ;
producerCrossFlowTracers . insert ( tracerName ) ;
}
prodjCellSets . push_back ( CellSet ( CellSetID ( tracerName ) , tIt . second ) ) ;
}
2017-03-13 05:03:34 -05:00
2017-10-11 11:02:00 -05:00
try
{
producerSolution . reset ( new Toolbox : : Reverse ( m_opmFlowDiagStaticData - > m_fldToolbox - > computeProductionDiagnostics ( prodjCellSets ) ) ) ;
}
catch ( const std : : exception & e )
{
QMessageBox : : critical ( nullptr , " ResInsight " , " Flow Diagnostics: " + QString ( e . what ( ) ) ) ;
return result ;
}
for ( const CellSetID & tracerId : producerSolution - > fd . startPoints ( ) )
{
std : : string tracername = tracerId . to_string ( ) ;
if ( producerCrossFlowTracers . count ( tracername ) ) tracername = addCrossFlowEnding ( tracername ) ;
CellSetValues tofVals = producerSolution - > fd . timeOfFlight ( tracerId ) ;
result . setTracerTOF ( tracername , phaseSelection , tofVals ) ;
CellSetValues fracVals = producerSolution - > fd . concentration ( tracerId ) ;
result . setTracerFraction ( tracername , phaseSelection , fracVals ) ;
}
2017-03-13 05:03:34 -05:00
}
progressInfo . incrementProgress ( ) ;
progressInfo . setProgressDescription ( " Well pair fluxes " ) ;
int producerTracerCount = static_cast < int > ( prodjCellSets . size ( ) ) ;
# pragma omp parallel for
for ( int pIdx = 0 ; pIdx < producerTracerCount ; + + pIdx )
{
const auto & prodCellSet = prodjCellSets [ pIdx ] ;
2017-10-11 11:02:00 -05:00
std : : string prodTracerName = prodCellSet . id ( ) . to_string ( ) ;
CellSetID prodID ( prodTracerName ) ;
std : : string uiProducerTracerName = prodTracerName ;
if ( producerCrossFlowTracers . count ( prodTracerName ) )
{
uiProducerTracerName = addCrossFlowEnding ( prodTracerName ) ;
}
2017-03-13 05:03:34 -05:00
for ( const auto & injCellSet : injectorCellSets )
{
2017-10-11 11:02:00 -05:00
std : : string injTracerName = injCellSet . id ( ) . to_string ( ) ;
CellSetID injID ( injTracerName ) ;
2017-03-13 05:03:34 -05:00
std : : pair < double , double > fluxPair = injectorProducerPairFlux ( * ( injectorSolution . get ( ) ) ,
* ( producerSolution . get ( ) ) ,
2017-10-11 11:02:00 -05:00
injID ,
prodID ,
WellInFluxPrCell ) ;
std : : string uiInjectorTracerName = injTracerName ;
if ( injectorCrossFlowTracers . count ( injTracerName ) )
{
uiInjectorTracerName = addCrossFlowEnding ( injTracerName ) ;
}
2017-03-13 05:03:34 -05:00
# pragma omp critical
{
2017-10-11 11:02:00 -05:00
result . setInjProdWellPairFlux ( uiInjectorTracerName ,
uiProducerTracerName ,
2017-03-13 05:03:34 -05:00
fluxPair ) ;
}
}
}
2017-01-06 07:41:00 -06:00
}
2016-12-17 03:46:57 -06:00
2016-12-20 04:41:05 -06:00
return result ; // Relying on implicit move constructor
2016-12-16 07:17:56 -06:00
}
2017-10-27 02:38:24 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigFlowDiagSolverInterface : : ensureStaticDataObjectInstanceCreated ( )
{
if ( m_opmFlowDiagStaticData . isNull ( ) )
{
// Get set of files
QString gridFileName = m_eclipseCase - > gridFileName ( ) ;
std : : string initFileName = getInitFileName ( ) ;
if ( initFileName . empty ( ) ) return false ;
m_opmFlowDiagStaticData = new RigOpmFlowDiagStaticData ( gridFileName . toStdString ( ) , initFileName ) ;
}
return m_opmFlowDiagStaticData . notNull ( ) ? true : false ;
}
2017-08-09 07:10:39 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-08-10 03:09:01 -05:00
RigFlowDiagSolverInterface : : FlowCharacteristicsResultFrame RigFlowDiagSolverInterface : : calculateFlowCharacteristics ( const std : : vector < double > * injector_tof ,
const std : : vector < double > * producer_tof ,
2017-08-17 04:24:51 -05:00
const std : : vector < size_t > & selected_cell_indices ,
2017-08-09 07:10:39 -05:00
double max_pv_fraction )
{
using namespace Opm : : FlowDiagnostics ;
RigFlowDiagSolverInterface : : FlowCharacteristicsResultFrame result ;
2017-08-10 03:09:01 -05:00
if ( injector_tof = = nullptr | | producer_tof = = nullptr )
{
return result ;
}
2017-08-17 04:24:51 -05:00
std : : vector < double > poreVolume ;
for ( size_t cellIndex : selected_cell_indices )
{
poreVolume . push_back ( m_opmFlowDiagStaticData - > m_poreVolume [ cellIndex ] ) ;
}
2017-08-10 03:09:01 -05:00
2017-08-09 07:10:39 -05:00
try
{
2017-08-10 03:09:01 -05:00
Graph flowCapStorCapCurve = flowCapacityStorageCapacityCurve ( * injector_tof ,
* producer_tof ,
2017-08-17 04:24:51 -05:00
poreVolume ,
2017-08-09 07:10:39 -05:00
max_pv_fraction ) ;
result . m_flowCapStorageCapCurve = flowCapStorCapCurve ;
result . m_lorenzCoefficient = lorenzCoefficient ( flowCapStorCapCurve ) ;
result . m_sweepEfficiencyCurve = sweepEfficiency ( flowCapStorCapCurve ) ;
}
catch ( const std : : exception & e )
{
QMessageBox : : critical ( nullptr , " ResInsight " , " Flow Diagnostics: " + QString ( e . what ( ) ) ) ;
}
return result ;
}
2017-10-27 02:38:24 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : vector < RigFlowDiagSolverInterface : : RelPermCurve > RigFlowDiagSolverInterface : : calculateRelPermCurvesForActiveCell ( size_t activeCellIndex )
{
std : : vector < RelPermCurve > retCurveArr ;
if ( ! ensureStaticDataObjectInstanceCreated ( ) )
{
return retCurveArr ;
}
CVF_ASSERT ( m_opmFlowDiagStaticData . notNull ( ) ) ;
CVF_ASSERT ( m_opmFlowDiagStaticData - > m_eclSaturationFunc ) ;
2017-11-22 09:14:04 -06:00
const Opm : : ECLSaturationFunc : : RawCurve krw { Opm : : ECLSaturationFunc : : RawCurve : : Function : : RelPerm , Opm : : ECLSaturationFunc : : RawCurve : : SubSystem : : OilWater , Opm : : ECLPhaseIndex : : Aqua } ; // water rel-perm in oil-water system
const Opm : : ECLSaturationFunc : : RawCurve krg { Opm : : ECLSaturationFunc : : RawCurve : : Function : : RelPerm , Opm : : ECLSaturationFunc : : RawCurve : : SubSystem : : OilGas , Opm : : ECLPhaseIndex : : Vapour } ; // gas rel-perm in oil-gas system
const Opm : : ECLSaturationFunc : : RawCurve krow { Opm : : ECLSaturationFunc : : RawCurve : : Function : : RelPerm , Opm : : ECLSaturationFunc : : RawCurve : : SubSystem : : OilWater , Opm : : ECLPhaseIndex : : Liquid } ; // oil rel-perm in oil-water system
const Opm : : ECLSaturationFunc : : RawCurve krog { Opm : : ECLSaturationFunc : : RawCurve : : Function : : RelPerm , Opm : : ECLSaturationFunc : : RawCurve : : SubSystem : : OilGas , Opm : : ECLPhaseIndex : : Liquid } ; // oil rel-perm in oil-gas system
const Opm : : ECLSaturationFunc : : RawCurve pcgo { Opm : : ECLSaturationFunc : : RawCurve : : Function : : CapPress , Opm : : ECLSaturationFunc : : RawCurve : : SubSystem : : OilGas , Opm : : ECLPhaseIndex : : Vapour } ; // gas/oil capillary pressure (Pg-Po) in G/O system
const Opm : : ECLSaturationFunc : : RawCurve pcow { Opm : : ECLSaturationFunc : : RawCurve : : Function : : CapPress , Opm : : ECLSaturationFunc : : RawCurve : : SubSystem : : OilWater , Opm : : ECLPhaseIndex : : Aqua } ; // oil/water capillary pressure (Po-Pw) in O/W system
2017-10-27 02:38:24 -05:00
std : : vector < std : : pair < RelPermCurve : : Ident , std : : string > > curveIdentNameArr ;
std : : vector < Opm : : ECLSaturationFunc : : RawCurve > satFuncRequests ;
curveIdentNameArr . push_back ( std : : make_pair ( RelPermCurve : : KRW , " KRW " ) ) ; satFuncRequests . push_back ( krw ) ;
curveIdentNameArr . push_back ( std : : make_pair ( RelPermCurve : : KRG , " KRG " ) ) ; satFuncRequests . push_back ( krg ) ;
curveIdentNameArr . push_back ( std : : make_pair ( RelPermCurve : : KROW , " KROW " ) ) ; satFuncRequests . push_back ( krow ) ;
curveIdentNameArr . push_back ( std : : make_pair ( RelPermCurve : : KROG , " KROG " ) ) ; satFuncRequests . push_back ( krog ) ;
2017-11-22 09:14:04 -06:00
curveIdentNameArr . push_back ( std : : make_pair ( RelPermCurve : : PCOG , " PCOG " ) ) ; satFuncRequests . push_back ( pcgo ) ;
curveIdentNameArr . push_back ( std : : make_pair ( RelPermCurve : : PCOW , " PCOW " ) ) ; satFuncRequests . push_back ( pcow ) ;
2017-10-27 02:38:24 -05:00
const bool useEPS = true ;
std : : vector < Opm : : FlowDiagnostics : : Graph > graphArr = m_opmFlowDiagStaticData - > m_eclSaturationFunc - > getSatFuncCurve ( satFuncRequests , static_cast < int > ( activeCellIndex ) , useEPS ) ;
for ( size_t i = 0 ; i < graphArr . size ( ) ; i + + )
{
2017-11-22 08:39:40 -06:00
const RelPermCurve : : Ident curveIdent = curveIdentNameArr [ i ] . first ;
const std : : string curveName = curveIdentNameArr [ i ] . second ;
2017-10-27 02:38:24 -05:00
const Opm : : FlowDiagnostics : : Graph & srcGraph = graphArr [ i ] ;
if ( srcGraph . first . size ( ) > 0 )
{
2017-11-22 09:14:04 -06:00
const std : : vector < double > & xVals = srcGraph . first ;
2017-10-27 02:38:24 -05:00
const std : : vector < double > & yVals = srcGraph . second ;
retCurveArr . push_back ( { curveIdent , curveName , xVals , yVals } ) ;
}
}
return retCurveArr ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : vector < RigFlowDiagSolverInterface : : PvtCurve > RigFlowDiagSolverInterface : : calculatePvtFvfCurvesForActiveCell ( size_t activeCellIndex )
{
std : : vector < PvtCurve > retCurveArr ;
if ( ! ensureStaticDataObjectInstanceCreated ( ) )
{
return retCurveArr ;
}
//CVF_ASSERT(m_opmFlowDiagStaticData.notNull());
//CVF_ASSERT(m_opmFlowDiagStaticData->m_eclPvtCurveCollection);
//{
// Opm::FlowDiagnostics::Graph graph = m_opmFlowDiagStaticData->m_eclPvtCurveCollection->getPvtCurve(Opm::ECLPVT::RawCurve::FVF, Opm::ECLPhaseIndex::Vapour, static_cast<int>(activeCellIndex));
// retCurveDataArr.push_back({ "FVF_Gas", graph.first, graph.second });
//}
//{
// Opm::FlowDiagnostics::Graph graph = m_opmFlowDiagStaticData->m_eclPvtCurveCollection->getPvtCurve(Opm::ECLPVT::RawCurve::FVF, Opm::ECLPhaseIndex::Liquid, static_cast<int>(activeCellIndex));
// retCurveDataArr.push_back({ "FVF_Oil", graph.first, graph.second });
//}
//{
// Opm::FlowDiagnostics::Graph graph = m_opmFlowDiagStaticData->m_eclPvtCurveCollection->getPvtCurve(Opm::ECLPVT::RawCurve::FVF, Opm::ECLPhaseIndex::Aqua, static_cast<int>(activeCellIndex));
// retCurveDataArr.push_back({ "FVF_Water", graph.first, graph.second });
//}
return retCurveArr ;
}
2017-08-10 03:09:01 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : string RigFlowDiagSolverInterface : : getInitFileName ( ) const
{
QString gridFileName = m_eclipseCase - > gridFileName ( ) ;
QStringList m_filesWithSameBaseName ;
if ( ! RifEclipseOutputFileTools : : findSiblingFilesWithSameBaseName ( gridFileName , & m_filesWithSameBaseName ) ) return std : : string ( ) ;
QString initFileName = RifEclipseOutputFileTools : : firstFileNameOfType ( m_filesWithSameBaseName , ECL_INIT_FILE ) ;
return initFileName . toStdString ( ) ;
}
2017-08-09 07:10:39 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFlowDiagSolverInterface : : FlowCharacteristicsResultFrame : : FlowCharacteristicsResultFrame ( )
: m_lorenzCoefficient ( HUGE_VAL )
{
}