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-01-09 12:14:07 -06:00
# include "RigFlowDiagInterfaceTools.h"
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
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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-01-12 09:36:48 -06:00
caf : : ProgressInfo progressInfo ( 7 , " Calculating Flow Diagnostics " ) ;
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
2016-12-20 04:41:05 -06:00
{
2017-01-06 07:41:00 -06:00
Opm : : FlowDiagnostics : : ConnectionValues connectionsVals = RigFlowDiagInterfaceTools : : Hack : : convert_flux_to_SI ( RigFlowDiagInterfaceTools : : extractFluxField ( m_opmFldData - > eclGraph ) ) ;
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-01-06 07:41:00 -06:00
Opm : : ECLWellSolution wsol = Opm : : ECLWellSolution { } ;
const std : : vector < Opm : : ECLWellSolution : : WellData > well_fluxes =
wsol . solution ( m_opmFldData - > eclGraph . rawResultData ( ) , m_opmFldData - > eclGraph . numGrids ( ) ) ;
m_opmFldData - > fldToolbox - > assignInflowFlux ( RigFlowDiagInterfaceTools : : extractWellFlows ( m_opmFldData - > eclGraph , well_fluxes ) ) ;
}
2017-01-12 09:36:48 -06:00
progressInfo . incrementProgress ( ) ;
progressInfo . setProgressDescription ( " Injector Solution " ) ;
2017-01-06 07:41:00 -06:00
// Injection Solution
{
std : : vector < CellSet > injectorCellSet ;
for ( const auto & tIt : injectorTracers )
{
injectorCellSet . push_back ( CellSet ( CellSetID ( tIt . first ) , tIt . second ) ) ;
2016-12-20 04:41:05 -06:00
}
2017-01-06 07:41:00 -06:00
Solution injSol = m_opmFldData - > fldToolbox - > computeInjectionDiagnostics ( injectorCellSet ) . fd ;
for ( const CellSetID & tracerId : injSol . startPoints ( ) )
2016-12-20 04:41:05 -06:00
{
2017-01-06 07:41:00 -06:00
CellSetValues tofVals = injSol . timeOfFlight ( tracerId ) ;
2017-01-06 08:12:13 -06:00
result . setTracerTOF ( tracerId . to_string ( ) , tofVals ) ;
2017-01-06 07:41:00 -06:00
CellSetValues fracVals = injSol . concentration ( tracerId ) ;
2017-01-06 08:12:13 -06:00
result . setTracerFraction ( tracerId . to_string ( ) , fracVals ) ;
2016-12-20 04:41:05 -06:00
}
}
2017-01-12 09:36:48 -06:00
progressInfo . incrementProgress ( ) ;
progressInfo . setProgressDescription ( " Producer Solution " ) ;
2017-01-06 07:41:00 -06:00
// Producer Solution
{
std : : vector < CellSet > prodjCellSet ;
for ( const auto & tIt : producerTracers )
{
prodjCellSet . push_back ( CellSet ( CellSetID ( tIt . first ) , tIt . second ) ) ;
}
Solution prodSol = m_opmFldData - > fldToolbox - > computeProductionDiagnostics ( prodjCellSet ) . fd ;
for ( const CellSetID & tracerId : prodSol . startPoints ( ) )
{
CellSetValues tofVals = prodSol . timeOfFlight ( tracerId ) ;
2017-01-06 08:12:13 -06:00
result . setTracerTOF ( tracerId . to_string ( ) , tofVals ) ;
2017-01-06 07:41:00 -06:00
CellSetValues fracVals = prodSol . concentration ( tracerId ) ;
2017-01-06 08:12:13 -06:00
result . setTracerFraction ( tracerId . to_string ( ) , fracVals ) ;
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
}