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
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 )
2016-12-20 04:41:05 -06:00
: m_activeCellCount ( activeCellCount )
{
}
2016-12-16 07:17:56 -06:00
2016-12-20 04:41:05 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-01-06 08:12:13 -06:00
void RigFlowDiagTimeStepResult : : setTracerTOF ( const std : : string & tracerName , 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
RigFlowDiagResultAddress resAddr ( RIG_FLD_TOF_RESNAME , 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-01-06 08:12:13 -06:00
void RigFlowDiagTimeStepResult : : setTracerFraction ( const std : : string & tracerName , const std : : map < int , double > & cellValues )
2016-12-20 04:41:05 -06:00
{
std : : set < std : : string > tracers ;
tracers . insert ( tracerName ) ;
this - > addResult ( RigFlowDiagResultAddress ( RIG_FLD_CELL_FRACTION_RESNAME , tracers ) , cellValues ) ;
}
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 ] ;
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
class RigOpmFldStaticData : public cvf : : Object
{
public :
RigOpmFldStaticData ( const std : : string & grid , const std : : string & init ) : eclGraph ( Opm : : ECLGraph : : load ( grid , init ) ) , m_hasUnifiedRestartFile ( false ) { }
Opm : : ECLGraph eclGraph ;
std : : unique_ptr < Opm : : FlowDiagnostics : : Toolbox > fldToolbox ;
bool m_hasUnifiedRestartFile ;
QStringList restartFileNames ;
} ;
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-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 ,
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 ;
RigFlowDiagTimeStepResult result ( m_eclipseCase - > reservoirData ( ) - > activeCellInfo ( RifReaderInterface : : MATRIX_RESULTS ) - > reservoirActiveCellCount ( ) ) ;
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
if ( m_opmFldData . isNull ( ) )
{
2017-01-12 09:36:48 -06:00
progressInfo . setProgressDescription ( " Grid access " ) ;
2017-01-06 07:41:00 -06:00
// Get set of files
QString gridFileName = m_eclipseCase - > gridFileName ( ) ;
2016-12-20 04:41:05 -06:00
2017-01-06 07:41:00 -06:00
QStringList m_filesWithSameBaseName ;
2016-12-20 04:41:05 -06:00
2017-01-06 07:41:00 -06:00
if ( ! RifEclipseOutputFileTools : : findSiblingFilesWithSameBaseName ( gridFileName , & m_filesWithSameBaseName ) ) return result ;
2016-12-20 04:41:05 -06:00
2017-01-06 07:41:00 -06:00
QString initFileName = RifEclipseOutputFileTools : : firstFileNameOfType ( m_filesWithSameBaseName , ECL_INIT_FILE ) ;
2016-12-20 04:41:05 -06:00
2017-01-06 07:41:00 -06:00
m_opmFldData = new RigOpmFldStaticData ( gridFileName . toStdString ( ) ,
initFileName . toStdString ( ) ) ;
2016-12-20 04:41:05 -06:00
2017-01-12 09:36:48 -06:00
progressInfo . incrementProgress ( ) ;
progressInfo . setProgressDescription ( " Calculating Connectivities " ) ;
2017-01-06 07:41:00 -06:00
const Opm : : FlowDiagnostics : : ConnectivityGraph connGraph =
Opm : : FlowDiagnostics : : ConnectivityGraph { static_cast < int > ( m_opmFldData - > eclGraph . numCells ( ) ) ,
m_opmFldData - > 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-01-06 07:41:00 -06:00
m_opmFldData - > fldToolbox . reset ( new Opm : : FlowDiagnostics : : Toolbox { connGraph } ) ;
m_opmFldData - > fldToolbox - > assignPoreVolume ( m_opmFldData - > eclGraph . poreVolume ( ) ) ;
2016-12-20 08:33:39 -06:00
2017-01-06 07:41:00 -06:00
// Look for unified restart file
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 ( ) )
{
m_opmFldData - > eclGraph . assignFluxDataSource ( restartFileName . toStdString ( ) ) ;
m_opmFldData - > m_hasUnifiedRestartFile = true ;
}
else
2016-12-20 04:41:05 -06:00
{
2017-01-06 07:41:00 -06:00
m_opmFldData - > restartFileNames = RifEclipseOutputFileTools : : filterFileNamesOfType ( m_filesWithSameBaseName , ECL_RESTART_FILE ) ;
size_t restartFileCount = static_cast < size_t > ( m_opmFldData - > restartFileNames . size ( ) ) ;
size_t maxTimeStepCount = m_eclipseCase - > reservoirData ( ) - > results ( RifReaderInterface : : MATRIX_RESULTS ) - > maxTimeStepCount ( ) ;
if ( restartFileCount < = timeStepIndex & & restartFileCount ! = maxTimeStepCount )
{
QMessageBox : : critical ( nullptr , " ResInsight " , " Flow Diagnostics: Could not find all the restart files. Results will not be loaded. " ) ;
return result ;
}
m_opmFldData - > restartFileNames . sort ( ) ; // To make sure they are sorted in increasing *.X000N order. Hack. Should probably be actual time stored on file.
m_opmFldData - > m_hasUnifiedRestartFile = false ;
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-01-06 07:41:00 -06:00
if ( ! m_opmFldData - > m_hasUnifiedRestartFile )
{
QString restartFileName = m_opmFldData - > restartFileNames [ static_cast < int > ( timeStepIndex ) ] ;
m_opmFldData - > eclGraph . assignFluxDataSource ( restartFileName . toStdString ( ) ) ;
2016-12-20 04:41:05 -06:00
}
2017-01-12 05:04:54 -06:00
size_t resultIndexWithMaxTimeSteps = cvf : : UNDEFINED_SIZE_T ;
m_eclipseCase - > reservoirData ( ) - > results ( RifReaderInterface : : MATRIX_RESULTS ) - > maxTimeStepCount ( & resultIndexWithMaxTimeSteps ) ;
2016-12-20 04:41:05 -06:00
2017-01-12 05:04:54 -06:00
int reportStepNumber = m_eclipseCase - > reservoirData ( ) - > results ( RifReaderInterface : : MATRIX_RESULTS ) - > reportStepNumber ( resultIndexWithMaxTimeSteps , timeStepIndex ) ;
if ( ! m_opmFldData - > eclGraph . 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-03-13 05:03:34 -05:00
Opm : : FlowDiagnostics : : CellSetValues sumWellFluxPrCell ;
2016-12-20 04:41:05 -06:00
{
2017-02-09 08:27:34 -06:00
Opm : : FlowDiagnostics : : ConnectionValues connectionsVals = RigFlowDiagInterfaceTools : : extractFluxField ( m_opmFldData - > eclGraph , false ) ;
2016-12-20 04:41:05 -06:00
2017-01-06 07:41:00 -06:00
m_opmFldData - > fldToolbox - > assignConnectionFlux ( connectionsVals ) ;
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
const std : : vector < Opm : : ECLWellSolution : : WellData > well_fluxes =
wsol . solution ( m_opmFldData - > eclGraph . rawResultData ( ) , m_opmFldData - > eclGraph . numGrids ( ) ) ;
2017-03-13 05:03:34 -05:00
sumWellFluxPrCell = RigFlowDiagInterfaceTools : : extractWellFlows ( m_opmFldData - > eclGraph , well_fluxes ) ;
2017-03-09 09:05:48 -06:00
m_opmFldData - > fldToolbox - > assignInflowFlux ( sumWellFluxPrCell ) ;
2017-03-13 05:03:34 -05:00
// 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 )
{
auto activeCellIdxFluxPair = sumWellFluxPrCell . find ( activeCellIdx ) ;
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 )
{
auto activeCellIdxFluxPair = sumWellFluxPrCell . find ( activeCellIdx ) ;
if ( activeCellIdxFluxPair - > second < 0 )
{
filteredCellIndices . push_back ( activeCellIdx ) ;
}
}
if ( tracerCellIdxsPair . second . size ( ) ! = filteredCellIndices . size ( ) ) tracerCellIdxsPair . second = filteredCellIndices ;
}
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
std : : vector < CellSet > injectorCellSets ;
2017-01-06 07:41:00 -06:00
for ( const auto & tIt : injectorTracers )
{
2017-03-13 05:03:34 -05:00
injectorCellSets . push_back ( CellSet ( CellSetID ( tIt . first ) , tIt . second ) ) ;
2016-12-20 04:41:05 -06:00
}
2017-03-13 05:03:34 -05:00
std : : unique_ptr < Toolbox : : Forward > injectorSolution ;
2017-03-06 09:33:29 -06:00
try
{
2017-03-13 05:03:34 -05:00
injectorSolution . reset ( new Toolbox : : Forward ( m_opmFldData - > fldToolbox - > computeInjectionDiagnostics ( injectorCellSets ) ) ) ;
2017-03-06 09:33:29 -06:00
}
2017-03-09 09:05:48 -06:00
catch ( const std : : exception & e )
2016-12-20 04:41:05 -06:00
{
2017-03-10 04:46:50 -06:00
QMessageBox : : critical ( nullptr , " ResInsight " , " Flow Diagnostics: " + QString ( e . what ( ) ) ) ;
return result ;
2016-12-20 04:41:05 -06:00
}
2017-03-13 05:03:34 -05:00
for ( const CellSetID & tracerId : injectorSolution - > fd . startPoints ( ) )
{
CellSetValues tofVals = injectorSolution - > fd . timeOfFlight ( tracerId ) ;
result . setTracerTOF ( tracerId . to_string ( ) , tofVals ) ;
CellSetValues fracVals = injectorSolution - > fd . concentration ( tracerId ) ;
result . setTracerFraction ( tracerId . to_string ( ) , fracVals ) ;
}
2017-01-12 09:36:48 -06:00
2017-03-13 05:03:34 -05:00
progressInfo . incrementProgress ( ) ;
progressInfo . setProgressDescription ( " Producer Solution " ) ;
// Producer Solution
std : : vector < CellSet > prodjCellSets ;
2017-01-06 07:41:00 -06:00
for ( const auto & tIt : producerTracers )
{
2017-03-13 05:03:34 -05:00
prodjCellSets . push_back ( CellSet ( CellSetID ( tIt . first ) , tIt . second ) ) ;
2017-01-06 07:41:00 -06:00
}
2017-03-13 05:03:34 -05:00
std : : unique_ptr < Toolbox : : Reverse > producerSolution ;
try
2017-03-06 09:33:29 -06:00
{
2017-03-13 05:03:34 -05:00
producerSolution . reset ( new Toolbox : : Reverse ( m_opmFldData - > fldToolbox - > computeProductionDiagnostics ( prodjCellSets ) ) ) ;
2017-03-06 09:33:29 -06:00
}
2017-03-13 05:03:34 -05:00
catch ( const std : : exception & e )
2017-01-06 07:41:00 -06:00
{
2017-03-10 04:46:50 -06:00
QMessageBox : : critical ( nullptr , " ResInsight " , " Flow Diagnostics: " + QString ( e . what ( ) ) ) ;
return result ;
2017-01-06 07:41:00 -06:00
}
2017-03-13 05:03:34 -05:00
for ( const CellSetID & tracerId : producerSolution - > fd . startPoints ( ) )
{
CellSetValues tofVals = producerSolution - > fd . timeOfFlight ( tracerId ) ;
result . setTracerTOF ( tracerId . to_string ( ) , tofVals ) ;
CellSetValues fracVals = producerSolution - > fd . concentration ( tracerId ) ;
result . setTracerFraction ( tracerId . to_string ( ) , fracVals ) ;
}
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 ] ;
for ( const auto & injCellSet : injectorCellSets )
{
std : : pair < double , double > fluxPair = injectorProducerPairFlux ( * ( injectorSolution . get ( ) ) ,
* ( producerSolution . get ( ) ) ,
injCellSet ,
prodCellSet ,
sumWellFluxPrCell ) ;
# pragma omp critical
{
result . setInjProdWellPairFlux ( injCellSet . id ( ) . to_string ( ) ,
prodCellSet . id ( ) . to_string ( ) ,
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
}