2012-05-18 02:45:23 -05:00
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS
//
// 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 "cvfBase.h"
# include "RigMainGrid.h"
# include "RigReservoir.h"
2012-06-26 09:10:41 -05:00
# include "RigReservoirCellResults.h"
2012-05-18 02:45:23 -05:00
2012-06-26 09:10:41 -05:00
# include "RifReaderEclipseOutput.h"
# include "RifEclipseOutputFileTools.h"
# include "RifEclipseUnifiedRestartFileAccess.h"
# include "RifEclipseRestartFilesetAccess.h"
2013-02-01 07:39:32 -06:00
# include "RifReaderInterface.h"
2012-05-18 02:45:23 -05:00
# include <iostream>
# include "ecl_grid.h"
# include "well_state.h"
2012-06-26 09:10:41 -05:00
# include "cafProgressInfo.h"
2012-05-18 02:45:23 -05:00
//--------------------------------------------------------------------------------------------------
/// ECLIPSE cell numbering layout:
/// Lower layer: Upper layer
///
/// 2---3 6---7
/// | | | |
/// 0---1 4---5
///
///
///
//--------------------------------------------------------------------------------------------------
// The indexing conventions for vertices in ECLIPSE
//
// 6-------------7
// /| /|
// / | / |
// / | / |
// 4-------------5 |
// | | | |
// | 2---------|---3
// | / | /
// | / | /
// |/ |/
// 0-------------1
// vertex indices
//
// The indexing conventions for vertices in ResInsight
//
2013-01-30 08:02:28 -06:00
// 7-------------6 |k
// /| /| | /j
// / | / | |/
// / | / | *---i
2012-05-18 02:45:23 -05:00
// 4-------------5 |
// | | | |
// | 3---------|---2
// | / | /
// | / | /
// |/ |/
// 0-------------1
// vertex indices
//
static const size_t cellMappingECLRi [ 8 ] = { 0 , 1 , 3 , 2 , 4 , 5 , 7 , 6 } ;
//**************************************************************************************************
// Static functions
//**************************************************************************************************
2013-01-30 02:30:48 -06:00
bool transferGridCellData ( RigMainGrid * mainGrid , RigGridBase * localGrid , const ecl_grid_type * localEclGrid , size_t matrixActiveStartIndex , size_t fractureActiveStartIndex )
2012-05-18 02:45:23 -05:00
{
int cellCount = ecl_grid_get_global_size ( localEclGrid ) ;
size_t cellStartIndex = mainGrid - > cells ( ) . size ( ) ;
size_t nodeStartIndex = mainGrid - > nodes ( ) . size ( ) ;
RigCell defaultCell ;
defaultCell . setHostGrid ( localGrid ) ;
mainGrid - > cells ( ) . resize ( cellStartIndex + cellCount , defaultCell ) ;
mainGrid - > nodes ( ) . resize ( nodeStartIndex + cellCount * 8 , cvf : : Vec3d ( 0 , 0 , 0 ) ) ;
2012-09-11 02:22:36 -05:00
int progTicks = 100 ;
double cellsPrProgressTick = cellCount / ( float ) progTicks ;
caf : : ProgressInfo progInfo ( progTicks , " " ) ;
2012-06-26 09:10:41 -05:00
size_t computedCellCount = 0 ;
2012-05-18 02:45:23 -05:00
// Loop over cells and fill them with data
2012-09-11 02:22:36 -05:00
# pragma omp parallel for
2012-05-18 02:45:23 -05:00
for ( int gIdx = 0 ; gIdx < cellCount ; + + gIdx )
{
RigCell & cell = mainGrid - > cells ( ) [ cellStartIndex + gIdx ] ;
2013-01-30 08:02:28 -06:00
bool invalid = ecl_grid_cell_invalid1 ( localEclGrid , gIdx ) ;
cell . setInvalid ( invalid ) ;
2012-05-18 02:45:23 -05:00
cell . setCellIndex ( gIdx ) ;
2013-01-30 08:02:28 -06:00
2013-02-01 08:33:21 -06:00
// Active cell index
2013-01-30 08:02:28 -06:00
int matrixActiveIndex = ecl_grid_get_active_index1 ( localEclGrid , gIdx ) ;
if ( matrixActiveIndex ! = - 1 )
{
cell . setActiveIndexInMatrixModel ( matrixActiveStartIndex + matrixActiveIndex ) ;
}
else
2013-01-30 02:30:48 -06:00
{
2013-01-31 10:21:30 -06:00
cell . setActiveIndexInMatrixModel ( cvf : : UNDEFINED_SIZE_T ) ;
2013-01-30 02:30:48 -06:00
}
2013-01-30 08:02:28 -06:00
int fractureActiveIndex = ecl_grid_get_active_fracture_index1 ( localEclGrid , gIdx ) ;
if ( fractureActiveIndex ! = - 1 )
2013-01-30 02:30:48 -06:00
{
2013-01-30 08:02:28 -06:00
cell . setActiveIndexInFractureModel ( fractureActiveStartIndex + fractureActiveIndex ) ;
}
else
{
cell . setActiveIndexInFractureModel ( cvf : : UNDEFINED_SIZE_T ) ;
2013-01-30 02:30:48 -06:00
}
2012-05-18 02:45:23 -05:00
2013-02-01 08:33:21 -06:00
// Parent cell index
2012-05-18 02:45:23 -05:00
int parentCellIndex = ecl_grid_get_parent_cell1 ( localEclGrid , gIdx ) ;
if ( parentCellIndex = = - 1 )
{
cell . setParentCellIndex ( cvf : : UNDEFINED_SIZE_T ) ;
}
else
{
cell . setParentCellIndex ( parentCellIndex ) ;
}
2013-02-01 08:33:21 -06:00
// Coarse cell info
ecl_coarse_cell_type * coarseCellData = ecl_grid_get_cell_coarse_group1 ( localEclGrid , gIdx ) ;
cell . setInCoarseCell ( coarseCellData ! = NULL ) ;
2012-05-18 02:45:23 -05:00
// Corner coordinates
int cIdx ;
for ( cIdx = 0 ; cIdx < 8 ; + + cIdx )
{
double * point = mainGrid - > nodes ( ) [ nodeStartIndex + gIdx * 8 + cellMappingECLRi [ cIdx ] ] . ptr ( ) ;
ecl_grid_get_corner_xyz1 ( localEclGrid , gIdx , cIdx , & ( point [ 0 ] ) , & ( point [ 1 ] ) , & ( point [ 2 ] ) ) ;
point [ 2 ] = - point [ 2 ] ;
cell . cornerIndices ( ) [ cIdx ] = nodeStartIndex + gIdx * 8 + cIdx ;
}
// Sub grid in cell
const ecl_grid_type * subGrid = ecl_grid_get_cell_lgr1 ( localEclGrid , gIdx ) ;
if ( subGrid ! = NULL )
{
int subGridFileIndex = ecl_grid_get_grid_nr ( subGrid ) ;
CVF_ASSERT ( subGridFileIndex > 0 ) ;
cell . setSubGrid ( static_cast < RigLocalGrid * > ( mainGrid - > gridByIndex ( subGridFileIndex ) ) ) ;
}
2012-06-26 09:10:41 -05:00
2013-02-01 08:33:21 -06:00
// Mark inactive long pyramid looking cells as invalid
2013-02-04 06:46:28 -06:00
if ( ! invalid & & ( cell . isInCoarseCell ( ) | | ( ! cell . isActiveInMatrixModel ( ) & & ! cell . isActiveInFractureModel ( ) ) ) )
2013-01-30 08:02:28 -06:00
{
cell . setInvalid ( cell . isLongPyramidCell ( ) ) ;
}
2012-06-26 09:10:41 -05:00
# pragma omp atomic
computedCellCount + + ;
2012-09-11 02:22:36 -05:00
progInfo . setProgress ( ( int ) ( computedCellCount / cellsPrProgressTick ) ) ;
2012-05-18 02:45:23 -05:00
}
2012-06-26 09:10:41 -05:00
return true ;
2012-05-18 02:45:23 -05:00
}
//==================================================================================================
//
// Class RigReaderInterfaceECL
//
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
2012-06-26 09:10:41 -05:00
RifReaderEclipseOutput : : RifReaderEclipseOutput ( )
2012-05-18 02:45:23 -05:00
{
ground ( ) ;
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
2012-06-26 09:10:41 -05:00
RifReaderEclipseOutput : : ~ RifReaderEclipseOutput ( )
2012-05-18 02:45:23 -05:00
{
}
//--------------------------------------------------------------------------------------------------
/// Ground members
//--------------------------------------------------------------------------------------------------
2012-06-26 09:10:41 -05:00
void RifReaderEclipseOutput : : ground ( )
2012-05-18 02:45:23 -05:00
{
m_fileName . clear ( ) ;
m_fileSet . clear ( ) ;
m_timeSteps . clear ( ) ;
2013-02-05 03:51:32 -06:00
m_mainGrid = NULL ;
2012-05-18 02:45:23 -05:00
}
//--------------------------------------------------------------------------------------------------
/// Close interface (for now, no files are kept open after calling methods, so just clear members)
//--------------------------------------------------------------------------------------------------
2012-06-26 09:10:41 -05:00
void RifReaderEclipseOutput : : close ( )
2012-05-18 02:45:23 -05:00
{
2013-02-05 03:51:32 -06:00
m_ecl_file = NULL ;
2012-05-18 02:45:23 -05:00
m_dynamicResultsAccess = NULL ;
ground ( ) ;
}
//--------------------------------------------------------------------------------------------------
/// Read geometry from file given by name into given reservoir object
//--------------------------------------------------------------------------------------------------
2012-06-26 09:10:41 -05:00
bool RifReaderEclipseOutput : : transferGeometry ( const ecl_grid_type * mainEclGrid , RigReservoir * reservoir )
2012-05-18 02:45:23 -05:00
{
CVF_ASSERT ( reservoir ) ;
if ( ! mainEclGrid )
{
// Some error
return false ;
}
RigMainGrid * mainGrid = reservoir - > mainGrid ( ) ;
{
cvf : : Vec3st gridPointDim ( 0 , 0 , 0 ) ;
gridPointDim . x ( ) = ecl_grid_get_nx ( mainEclGrid ) + 1 ;
gridPointDim . y ( ) = ecl_grid_get_ny ( mainEclGrid ) + 1 ;
gridPointDim . z ( ) = ecl_grid_get_nz ( mainEclGrid ) + 1 ;
mainGrid - > setGridPointDimensions ( gridPointDim ) ;
}
// Get and set grid and lgr metadata
size_t totalCellCount = static_cast < size_t > ( ecl_grid_get_global_size ( mainEclGrid ) ) ;
int numLGRs = ecl_grid_get_num_lgr ( mainEclGrid ) ;
int lgrIdx ;
for ( lgrIdx = 0 ; lgrIdx < numLGRs ; + + lgrIdx )
{
ecl_grid_type * localEclGrid = ecl_grid_iget_lgr ( mainEclGrid , lgrIdx ) ;
std : : string lgrName = ecl_grid_get_name ( localEclGrid ) ;
cvf : : Vec3st gridPointDim ( 0 , 0 , 0 ) ;
gridPointDim . x ( ) = ecl_grid_get_nx ( localEclGrid ) + 1 ;
gridPointDim . y ( ) = ecl_grid_get_ny ( localEclGrid ) + 1 ;
gridPointDim . z ( ) = ecl_grid_get_nz ( localEclGrid ) + 1 ;
RigLocalGrid * localGrid = new RigLocalGrid ( mainGrid ) ;
mainGrid - > addLocalGrid ( localGrid ) ;
localGrid - > setIndexToStartOfCells ( totalCellCount ) ;
localGrid - > setGridName ( lgrName ) ;
localGrid - > setGridPointDimensions ( gridPointDim ) ;
totalCellCount + = ecl_grid_get_global_size ( localEclGrid ) ;
}
// Reserve room for the cells and nodes and fill them with data
mainGrid - > cells ( ) . reserve ( totalCellCount ) ;
mainGrid - > nodes ( ) . reserve ( 8 * totalCellCount ) ;
2012-09-11 02:22:36 -05:00
caf : : ProgressInfo progInfo ( 3 + numLGRs , " " ) ;
2012-06-26 09:10:41 -05:00
progInfo . setProgressDescription ( " Main Grid " ) ;
2012-09-11 02:22:36 -05:00
progInfo . setNextProgressIncrement ( 3 ) ;
2012-06-26 09:10:41 -05:00
2013-01-30 02:30:48 -06:00
transferGridCellData ( mainGrid , mainGrid , mainEclGrid , 0 , 0 ) ;
2012-05-18 02:45:23 -05:00
2012-09-11 02:22:36 -05:00
progInfo . setProgress ( 3 ) ;
2012-06-26 09:10:41 -05:00
2013-01-30 02:30:48 -06:00
size_t globalMatrixActiveSize = ecl_grid_get_nactive ( mainEclGrid ) ;
size_t globalFractureActiveSize = ecl_grid_get_nactive_fracture ( mainEclGrid ) ;
2012-05-18 02:45:23 -05:00
2013-02-01 08:33:21 -06:00
mainGrid - > setMatrixModelActiveCellCount ( globalMatrixActiveSize ) ;
mainGrid - > setFractureModelActiveCellCount ( globalFractureActiveSize ) ;
2012-05-18 02:45:23 -05:00
for ( lgrIdx = 0 ; lgrIdx < numLGRs ; + + lgrIdx )
{
2012-06-26 09:10:41 -05:00
progInfo . setProgressDescription ( " LGR number " + QString : : number ( lgrIdx + 1 ) ) ;
2012-05-18 02:45:23 -05:00
ecl_grid_type * localEclGrid = ecl_grid_iget_lgr ( mainEclGrid , lgrIdx ) ;
2013-02-01 08:33:21 -06:00
RigLocalGrid * localGrid = static_cast < RigLocalGrid * > ( mainGrid - > gridByIndex ( lgrIdx + 1 ) ) ;
transferGridCellData ( mainGrid , localGrid , localEclGrid , globalMatrixActiveSize , globalFractureActiveSize ) ;
int activeCellCount = ecl_grid_get_nactive ( localEclGrid ) ;
localGrid - > setMatrixModelActiveCellCount ( activeCellCount ) ;
globalMatrixActiveSize + = activeCellCount ;
activeCellCount = ecl_grid_get_nactive_fracture ( localEclGrid ) ;
localGrid - > setFractureModelActiveCellCount ( activeCellCount ) ;
globalFractureActiveSize + = activeCellCount ;
2013-01-30 02:30:48 -06:00
2012-09-11 02:22:36 -05:00
progInfo . setProgress ( 3 + lgrIdx ) ;
2012-05-18 02:45:23 -05:00
}
2013-02-01 08:33:21 -06:00
mainGrid - > setGlobalMatrixModelActiveCellCount ( globalMatrixActiveSize ) ;
mainGrid - > setGlobalFractureModelActiveCellCount ( globalFractureActiveSize ) ;
2012-05-18 02:45:23 -05:00
return true ;
}
//--------------------------------------------------------------------------------------------------
/// Open file and read geometry into given reservoir object
//--------------------------------------------------------------------------------------------------
2012-06-26 09:10:41 -05:00
bool RifReaderEclipseOutput : : open ( const QString & fileName , RigReservoir * reservoir )
2012-05-18 02:45:23 -05:00
{
CVF_ASSERT ( reservoir ) ;
2012-09-11 02:22:36 -05:00
caf : : ProgressInfo progInfo ( 10 , " " ) ;
2012-06-26 09:10:41 -05:00
progInfo . setProgressDescription ( " Reading Grid " ) ;
2012-05-18 02:45:23 -05:00
// Make sure everything's closed
close ( ) ;
// Get set of files
QStringList fileSet ;
2012-06-26 09:10:41 -05:00
if ( ! RifEclipseOutputFileTools : : fileSet ( fileName , & fileSet ) ) return false ;
2012-05-18 02:45:23 -05:00
// Keep the set of files of interest
m_fileSet = fileSet ;
// Read geometry
2012-06-26 09:10:41 -05:00
ecl_grid_type * mainEclGrid = ecl_grid_alloc ( fileName . toAscii ( ) . data ( ) ) ;
progInfo . setProgress ( 1 ) ;
2012-09-11 02:22:36 -05:00
progInfo . setNextProgressIncrement ( 6 ) ;
2012-06-26 09:10:41 -05:00
progInfo . setProgressDescription ( " Transferring grid geometry " ) ;
if ( ! transferGeometry ( mainEclGrid , reservoir ) ) return false ;
2012-09-11 02:22:36 -05:00
progInfo . setProgress ( 7 ) ;
2013-01-30 07:13:50 -06:00
progInfo . setProgressDescription ( " Releasing reader memory " ) ;
2012-06-26 09:10:41 -05:00
ecl_grid_free ( mainEclGrid ) ;
2012-09-11 02:22:36 -05:00
progInfo . setProgress ( 8 ) ;
2012-06-26 09:10:41 -05:00
progInfo . setProgressDescription ( " Reading Result index " ) ;
2013-02-05 03:51:32 -06:00
m_mainGrid = reservoir - > mainGrid ( ) ;
reservoir - > mainGrid ( ) - > results ( RifReaderInterface : : MATRIX_RESULTS ) - > setReaderInterface ( this ) ;
reservoir - > mainGrid ( ) - > results ( RifReaderInterface : : FRACTURE_RESULTS ) - > setReaderInterface ( this ) ;
2012-05-18 02:45:23 -05:00
// Build results meta data
if ( ! buildMetaData ( reservoir ) ) return false ;
2012-09-11 02:22:36 -05:00
progInfo . setProgress ( 9 ) ;
2012-06-26 09:10:41 -05:00
progInfo . setProgressDescription ( " Reading Well information " ) ;
2012-05-18 02:45:23 -05:00
readWellCells ( reservoir ) ;
2013-02-05 03:51:32 -06:00
2012-05-18 02:45:23 -05:00
return true ;
}
//--------------------------------------------------------------------------------------------------
/// Build meta data - get states and results info
//--------------------------------------------------------------------------------------------------
2012-06-26 09:10:41 -05:00
bool RifReaderEclipseOutput : : buildMetaData ( RigReservoir * reservoir )
2012-05-18 02:45:23 -05:00
{
CVF_ASSERT ( reservoir ) ;
CVF_ASSERT ( m_fileSet . size ( ) > 0 ) ;
2012-06-26 09:10:41 -05:00
caf : : ProgressInfo progInfo ( 2 , " " ) ;
2012-05-18 02:45:23 -05:00
// Create access object for dynamic results
2013-02-05 03:51:32 -06:00
m_dynamicResultsAccess = dynamicResultsAccess ( m_fileSet ) ;
2013-01-30 07:13:50 -06:00
if ( m_dynamicResultsAccess . isNull ( ) )
{
return false ;
}
2012-06-26 09:10:41 -05:00
2013-02-01 07:39:32 -06:00
RigReservoirCellResults * matrixModelResults = reservoir - > mainGrid ( ) - > results ( RifReaderInterface : : MATRIX_RESULTS ) ;
RigReservoirCellResults * fractureModelResults = reservoir - > mainGrid ( ) - > results ( RifReaderInterface : : FRACTURE_RESULTS ) ;
2012-06-26 09:10:41 -05:00
2012-05-18 02:45:23 -05:00
if ( m_dynamicResultsAccess . notNull ( ) )
{
2012-06-26 09:10:41 -05:00
// Get time steps
2012-05-18 02:45:23 -05:00
m_timeSteps = m_dynamicResultsAccess - > timeSteps ( ) ;
2013-02-05 03:51:32 -06:00
QStringList resultNames ;
std : : vector < size_t > resultNamesDataItemCounts ;
m_dynamicResultsAccess - > resultNames ( & resultNames , & resultNamesDataItemCounts ) ;
2013-02-01 07:39:32 -06:00
{
2013-02-05 03:51:32 -06:00
QStringList matrixResultNames = validKeywordsForPorosityModel ( resultNames , resultNamesDataItemCounts , RifReaderInterface : : MATRIX_RESULTS , m_dynamicResultsAccess - > numTimeSteps ( ) ) ;
2013-02-01 07:39:32 -06:00
2013-02-05 03:51:32 -06:00
for ( int i = 0 ; i < matrixResultNames . size ( ) ; + + i )
2013-02-01 07:39:32 -06:00
{
2013-02-05 03:51:32 -06:00
size_t resIndex = matrixModelResults - > addEmptyScalarResult ( RimDefines : : DYNAMIC_NATIVE , matrixResultNames [ i ] ) ;
2013-02-01 07:39:32 -06:00
matrixModelResults - > setTimeStepDates ( resIndex , m_timeSteps ) ;
}
}
2012-06-26 09:10:41 -05:00
{
2013-02-05 03:51:32 -06:00
QStringList fractureResultNames = validKeywordsForPorosityModel ( resultNames , resultNamesDataItemCounts , RifReaderInterface : : FRACTURE_RESULTS , m_dynamicResultsAccess - > numTimeSteps ( ) ) ;
2013-02-01 07:39:32 -06:00
2013-02-05 03:51:32 -06:00
for ( int i = 0 ; i < fractureResultNames . size ( ) ; + + i )
2013-02-01 07:39:32 -06:00
{
2013-02-05 03:51:32 -06:00
size_t resIndex = fractureModelResults - > addEmptyScalarResult ( RimDefines : : DYNAMIC_NATIVE , fractureResultNames [ i ] ) ;
2013-02-01 07:39:32 -06:00
fractureModelResults - > setTimeStepDates ( resIndex , m_timeSteps ) ;
}
2012-06-26 09:10:41 -05:00
}
2013-02-01 07:39:32 -06:00
2012-05-18 02:45:23 -05:00
}
2012-06-26 09:10:41 -05:00
progInfo . setProgress ( 1 ) ;
QString initFileName = RifEclipseOutputFileTools : : fileNameByType ( m_fileSet , ECL_INIT_FILE ) ;
2012-05-18 02:45:23 -05:00
if ( initFileName . size ( ) > 0 )
{
2013-02-05 03:51:32 -06:00
ecl_file_type * ecl_file = ecl_file_open ( initFileName . toAscii ( ) . data ( ) ) ;
if ( ! ecl_file ) return false ;
QStringList resultNames ;
std : : vector < size_t > resultNamesDataItemCounts ;
RifEclipseOutputFileTools : : findKeywordsAndDataItemCounts ( ecl_file , & resultNames , & resultNamesDataItemCounts ) ;
2012-05-18 02:45:23 -05:00
2012-08-31 12:12:47 -05:00
{
2013-02-05 03:51:32 -06:00
QStringList matrixResultNames = validKeywordsForPorosityModel ( resultNames , resultNamesDataItemCounts , RifReaderInterface : : MATRIX_RESULTS , 1 ) ;
2013-02-01 07:39:32 -06:00
QList < QDateTime > staticDate ;
if ( m_timeSteps . size ( ) > 0 )
{
staticDate . push_back ( m_timeSteps . front ( ) ) ;
}
2013-02-05 03:51:32 -06:00
for ( int i = 0 ; i < matrixResultNames . size ( ) ; + + i )
2013-02-01 07:39:32 -06:00
{
2013-02-05 03:51:32 -06:00
size_t resIndex = matrixModelResults - > addEmptyScalarResult ( RimDefines : : STATIC_NATIVE , matrixResultNames [ i ] ) ;
2013-02-01 07:39:32 -06:00
matrixModelResults - > setTimeStepDates ( resIndex , staticDate ) ;
}
2012-08-31 12:12:47 -05:00
}
2012-06-26 09:10:41 -05:00
{
2013-02-05 03:51:32 -06:00
QStringList fractureResultNames = validKeywordsForPorosityModel ( resultNames , resultNamesDataItemCounts , RifReaderInterface : : FRACTURE_RESULTS , 1 ) ;
2013-02-01 07:39:32 -06:00
QList < QDateTime > staticDate ;
if ( m_timeSteps . size ( ) > 0 )
{
staticDate . push_back ( m_timeSteps . front ( ) ) ;
}
2013-02-05 03:51:32 -06:00
for ( int i = 0 ; i < fractureResultNames . size ( ) ; + + i )
2013-02-01 07:39:32 -06:00
{
2013-02-05 03:51:32 -06:00
size_t resIndex = fractureModelResults - > addEmptyScalarResult ( RimDefines : : STATIC_NATIVE , fractureResultNames [ i ] ) ;
2013-02-01 07:39:32 -06:00
fractureModelResults - > setTimeStepDates ( resIndex , staticDate ) ;
}
2012-06-26 09:10:41 -05:00
}
2012-05-18 02:45:23 -05:00
2013-02-05 03:51:32 -06:00
m_ecl_file = ecl_file ;
2012-05-18 02:45:23 -05:00
}
return true ;
}
//--------------------------------------------------------------------------------------------------
/// Create results access object (.UNRST or .X0001 ... .XNNNN)
//--------------------------------------------------------------------------------------------------
2013-02-05 03:51:32 -06:00
RifEclipseRestartDataAccess * RifReaderEclipseOutput : : dynamicResultsAccess ( const QStringList & fileSet )
2012-05-18 02:45:23 -05:00
{
2012-06-26 09:10:41 -05:00
RifEclipseRestartDataAccess * resultsAccess = NULL ;
2012-05-18 02:45:23 -05:00
// Look for unified restart file
2012-06-26 09:10:41 -05:00
QString unrstFileName = RifEclipseOutputFileTools : : fileNameByType ( fileSet , ECL_UNIFIED_RESTART_FILE ) ;
2012-05-18 02:45:23 -05:00
if ( unrstFileName . size ( ) > 0 )
{
2013-01-30 07:13:50 -06:00
resultsAccess = new RifEclipseUnifiedRestartFileAccess ( ) ;
2013-02-05 03:51:32 -06:00
if ( ! resultsAccess - > open ( QStringList ( unrstFileName ) ) )
2012-05-18 02:45:23 -05:00
{
delete resultsAccess ;
return NULL ;
}
}
else
{
// Look for set of restart files (one file per time step)
2012-06-26 09:10:41 -05:00
QStringList restartFiles = RifEclipseOutputFileTools : : fileNamesByType ( fileSet , ECL_RESTART_FILE ) ;
2012-05-18 02:45:23 -05:00
if ( restartFiles . size ( ) > 0 )
{
2013-01-30 07:13:50 -06:00
resultsAccess = new RifEclipseRestartFilesetAccess ( ) ;
2013-02-05 03:51:32 -06:00
if ( ! resultsAccess - > open ( restartFiles ) )
2012-05-18 02:45:23 -05:00
{
delete resultsAccess ;
return NULL ;
}
}
}
// !! could add support for formatted result files
// !! consider priorities in case multiple types exist (.UNRST, .XNNNN, ...)
return resultsAccess ;
}
//--------------------------------------------------------------------------------------------------
/// Get all values of a given static result as doubles
//--------------------------------------------------------------------------------------------------
2013-01-30 07:13:50 -06:00
bool RifReaderEclipseOutput : : staticResult ( const QString & result , PorosityModelResultType matrixOrFracture , std : : vector < double > * values )
2012-05-18 02:45:23 -05:00
{
CVF_ASSERT ( values ) ;
2013-02-05 03:51:32 -06:00
CVF_ASSERT ( m_ecl_file ) ;
std : : vector < double > fileValues ;
2012-05-18 02:45:23 -05:00
2013-02-05 03:51:32 -06:00
size_t numOccurrences = ecl_file_get_num_named_kw ( m_ecl_file , result . toAscii ( ) . data ( ) ) ;
2012-05-18 02:45:23 -05:00
size_t i ;
for ( i = 0 ; i < numOccurrences ; i + + )
{
std : : vector < double > partValues ;
2013-02-05 03:51:32 -06:00
RifEclipseOutputFileTools : : keywordData ( m_ecl_file , result , i , & partValues ) ;
fileValues . insert ( fileValues . end ( ) , partValues . begin ( ) , partValues . end ( ) ) ;
2012-05-18 02:45:23 -05:00
}
2013-02-05 03:51:32 -06:00
extractResultValuesBasedOnPorosityModel ( matrixOrFracture , values , fileValues ) ;
2012-05-18 02:45:23 -05:00
return true ;
}
//--------------------------------------------------------------------------------------------------
/// Get dynamic result at given step index. Will concatenate values for the main grid and all sub grids.
//--------------------------------------------------------------------------------------------------
2013-01-30 07:13:50 -06:00
bool RifReaderEclipseOutput : : dynamicResult ( const QString & result , PorosityModelResultType matrixOrFracture , size_t stepIndex , std : : vector < double > * values )
2012-05-18 02:45:23 -05:00
{
CVF_ASSERT ( m_dynamicResultsAccess . notNull ( ) ) ;
2013-02-05 03:51:32 -06:00
std : : vector < double > fileValues ;
if ( ! m_dynamicResultsAccess - > results ( result , stepIndex , m_mainGrid - > gridCount ( ) , & fileValues ) )
{
return false ;
}
extractResultValuesBasedOnPorosityModel ( matrixOrFracture , values , fileValues ) ;
return true ;
2012-05-18 02:45:23 -05:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2012-06-26 09:10:41 -05:00
void RifReaderEclipseOutput : : readWellCells ( RigReservoir * reservoir )
2012-05-18 02:45:23 -05:00
{
CVF_ASSERT ( reservoir ) ;
if ( m_dynamicResultsAccess . isNull ( ) ) return ;
well_info_type * ert_well_info = well_info_alloc ( NULL ) ;
if ( ! ert_well_info ) return ;
m_dynamicResultsAccess - > readWellData ( ert_well_info ) ;
RigMainGrid * mainGrid = reservoir - > mainGrid ( ) ;
std : : vector < RigGridBase * > grids ;
reservoir - > allGrids ( & grids ) ;
cvf : : Collection < RigWellResults > wells ;
int wellIdx ;
for ( wellIdx = 0 ; wellIdx < well_info_get_num_wells ( ert_well_info ) ; wellIdx + + )
{
const char * wellName = well_info_iget_well_name ( ert_well_info , wellIdx ) ;
CVF_ASSERT ( wellName ) ;
cvf : : ref < RigWellResults > wellResults = new RigWellResults ;
wellResults - > m_wellName = wellName ;
well_ts_type * ert_well_time_series = well_info_get_ts ( ert_well_info , wellName ) ;
int timeStepCount = well_ts_get_size ( ert_well_time_series ) ;
wellResults - > m_wellCellsTimeSteps . resize ( timeStepCount ) ;
int timeIdx ;
for ( timeIdx = 0 ; timeIdx < timeStepCount ; timeIdx + + )
{
well_state_type * ert_well_state = well_ts_iget_state ( ert_well_time_series , timeIdx ) ;
RigWellResultFrame & wellResFrame = wellResults - > m_wellCellsTimeSteps [ timeIdx ] ;
// Build timestamp for well
2012-06-26 09:10:41 -05:00
// Also see RifEclipseOutputFileAccess::timeStepsText for accessing time_t structures
2012-05-18 02:45:23 -05:00
{
time_t stepTime = well_state_get_sim_time ( ert_well_state ) ;
wellResFrame . m_timestamp = QDateTime : : fromTime_t ( stepTime ) ;
}
// Production type
well_type_enum ert_well_type = well_state_get_type ( ert_well_state ) ;
if ( ert_well_type = = PRODUCER )
{
wellResFrame . m_productionType = RigWellResultFrame : : PRODUCER ;
}
else if ( ert_well_type = = WATER_INJECTOR )
{
wellResFrame . m_productionType = RigWellResultFrame : : WATER_INJECTOR ;
}
else if ( ert_well_type = = GAS_INJECTOR )
{
wellResFrame . m_productionType = RigWellResultFrame : : GAS_INJECTOR ;
}
else if ( ert_well_type = = OIL_INJECTOR )
{
wellResFrame . m_productionType = RigWellResultFrame : : OIL_INJECTOR ;
}
else
{
wellResFrame . m_productionType = RigWellResultFrame : : UNDEFINED_PRODUCTION_TYPE ;
}
wellResFrame . m_isOpen = well_state_is_open ( ert_well_state ) ;
// Loop over all the grids in the model. If we have connections in one, we will discard
// the maingrid connections as they are "duplicates"
bool hasWellConnectionsInLGR = false ;
for ( size_t gridNr = 1 ; gridNr < grids . size ( ) ; + + gridNr )
{
2013-01-23 03:56:09 -06:00
int branchCount = well_state_iget_lgr_num_branches ( ert_well_state , static_cast < int > ( gridNr ) ) ;
2012-05-18 02:45:23 -05:00
if ( branchCount > 0 )
{
hasWellConnectionsInLGR = true ;
break ;
}
}
size_t gridNr = hasWellConnectionsInLGR ? 1 : 0 ;
for ( ; gridNr < grids . size ( ) ; + + gridNr )
{
// Wellhead. If several grids have a wellhead definition for this well, we use tha last one. (Possibly the innermost LGR)
2013-01-23 03:56:09 -06:00
const well_conn_type * ert_wellhead = well_state_iget_wellhead ( ert_well_state , static_cast < int > ( gridNr ) ) ;
2012-05-18 02:45:23 -05:00
if ( ert_wellhead )
{
2013-01-25 08:20:41 -06:00
int cellI = well_conn_get_i ( ert_wellhead ) ;
int cellJ = well_conn_get_j ( ert_wellhead ) ;
int cellK = CVF_MAX ( 0 , well_conn_get_k ( ert_wellhead ) ) ; // Why this ?
if ( ! grids [ gridNr ] - > isCellValid ( cellI , cellJ , cellK ) )
{
int candidateCellK = findSmallestActiveCellIndexK ( grids [ gridNr ] , cellI , cellJ ) ;
if ( candidateCellK > = 0 )
{
cellK = candidateCellK ;
}
else
{
cellK = 0 ;
}
}
wellResFrame . m_wellHead . m_gridCellIndex = grids [ gridNr ] - > cellIndexFromIJK ( cellI , cellJ , cellK ) ;
2012-05-18 02:45:23 -05:00
wellResFrame . m_wellHead . m_gridIndex = gridNr ;
}
2012-09-13 03:56:39 -05:00
2013-01-23 03:56:09 -06:00
int branchCount = well_state_iget_lgr_num_branches ( ert_well_state , static_cast < int > ( gridNr ) ) ;
2012-05-18 02:45:23 -05:00
if ( branchCount > 0 )
{
if ( static_cast < int > ( wellResFrame . m_wellResultBranches . size ( ) ) < branchCount ) wellResFrame . m_wellResultBranches . resize ( branchCount ) ;
for ( int branchIdx = 0 ; branchIdx < branchCount ; + + branchIdx )
{
// Connections
2013-01-23 03:56:09 -06:00
int connectionCount = well_state_iget_num_lgr_connections ( ert_well_state , static_cast < int > ( gridNr ) , branchIdx ) ;
2012-05-18 02:45:23 -05:00
if ( connectionCount > 0 )
{
RigWellResultBranch & wellSegment = wellResFrame . m_wellResultBranches [ branchIdx ] ; // Is this completely right? Is the branch index actually the same between lgrs ?
wellSegment . m_branchNumber = branchIdx ;
size_t existingConnCount = wellSegment . m_wellCells . size ( ) ;
wellSegment . m_wellCells . resize ( existingConnCount + connectionCount ) ;
int connIdx ;
for ( connIdx = 0 ; connIdx < connectionCount ; connIdx + + )
{
2013-01-23 03:56:09 -06:00
const well_conn_type * ert_connection = well_state_iget_lgr_connections ( ert_well_state , static_cast < int > ( gridNr ) , branchIdx ) [ connIdx ] ;
2012-05-18 02:45:23 -05:00
CVF_ASSERT ( ert_connection ) ;
RigWellResultCell & data = wellSegment . m_wellCells [ existingConnCount + connIdx ] ;
data . m_gridIndex = gridNr ;
2012-09-13 03:56:39 -05:00
{
2013-01-25 08:20:41 -06:00
int cellI = well_conn_get_i ( ert_connection ) ;
int cellJ = well_conn_get_j ( ert_connection ) ;
int cellK = well_conn_get_k ( ert_connection ) ;
2012-09-13 03:56:39 -05:00
bool open = well_conn_open ( ert_connection ) ;
int branch = well_conn_get_branch ( ert_connection ) ;
int segment = well_conn_get_segment ( ert_connection ) ;
2013-01-25 08:20:41 -06:00
if ( ! grids [ gridNr ] - > isCellValid ( cellI , cellJ , cellK ) )
{
int candidateCellK = findSmallestActiveCellIndexK ( grids [ gridNr ] , cellI , cellJ ) ;
if ( candidateCellK > = 0 )
{
cellK = candidateCellK ;
}
else
{
cellK = 0 ;
}
}
data . m_gridCellIndex = grids [ gridNr ] - > cellIndexFromIJK ( cellI , cellJ , cellK ) ;
2012-09-13 03:56:39 -05:00
data . m_isOpen = open ;
data . m_branchId = branch ;
data . m_segmentId = segment ;
}
2012-05-18 02:45:23 -05:00
}
}
}
}
}
}
wellResults - > computeMappingFromResultTimeIndicesToWellTimeIndices ( m_timeSteps ) ;
wells . push_back ( wellResults . p ( ) ) ;
}
well_info_free ( ert_well_info ) ;
reservoir - > setWellResults ( wells ) ;
}
2013-01-25 08:20:41 -06:00
//--------------------------------------------------------------------------------------------------
// For case DUALPORO, the well K index is reported outside the grid. If this happens,
// for the given IJ position, search from K=0 and upwards for first active cell.
//--------------------------------------------------------------------------------------------------
int RifReaderEclipseOutput : : findSmallestActiveCellIndexK ( const RigGridBase * grid , int cellI , int cellJ )
{
if ( ! grid ) return - 1 ;
for ( int candidateCellK = 0 ; candidateCellK < grid - > cellCountK ( ) ; candidateCellK + + )
{
if ( grid - > isCellActive ( cellI , cellJ , candidateCellK ) )
{
return candidateCellK ;
}
}
return - 1 ;
}
2013-02-05 03:51:32 -06:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList RifReaderEclipseOutput : : validKeywordsForPorosityModel ( const QStringList & keywords , const std : : vector < size_t > & keywordDataItemCounts , PorosityModelResultType matrixOrFracture , size_t timeStepCount ) const
{
if ( keywords . size ( ) ! = keywordDataItemCounts . size ( ) )
{
return QStringList ( ) ;
}
if ( matrixOrFracture = = RifReaderInterface : : FRACTURE_RESULTS )
{
if ( m_mainGrid - > globalFractureModelActiveCellCount ( ) = = 0 )
{
return QStringList ( ) ;
}
}
QStringList keywordsWithCorrectNumberOfDataItems ;
for ( int i = 0 ; i < keywords . size ( ) ; i + + )
{
QString keyword = keywords [ i ] ;
size_t keywordDataCount = keywordDataItemCounts [ i ] ;
size_t timeStepsMatrix = keywordDataItemCounts [ i ] / m_mainGrid - > globalMatrixModelActiveCellCount ( ) ;
size_t timeStepsMatrixRest = keywordDataItemCounts [ i ] % m_mainGrid - > globalMatrixModelActiveCellCount ( ) ;
size_t timeStepsMatrixAndFracture = keywordDataItemCounts [ i ] / ( m_mainGrid - > globalMatrixModelActiveCellCount ( ) + m_mainGrid - > globalFractureModelActiveCellCount ( ) ) ;
size_t timeStepsMatrixAndFractureRest = keywordDataItemCounts [ i ] % ( m_mainGrid - > globalMatrixModelActiveCellCount ( ) + m_mainGrid - > globalFractureModelActiveCellCount ( ) ) ;
if ( matrixOrFracture = = RifReaderInterface : : MATRIX_RESULTS )
{
if ( timeStepsMatrixRest = = 0 | | timeStepsMatrixAndFractureRest = = 0 )
{
if ( timeStepCount = = timeStepsMatrix | | timeStepCount = = timeStepsMatrixAndFracture )
{
keywordsWithCorrectNumberOfDataItems . push_back ( keywords [ i ] ) ;
}
}
}
else
{
if ( timeStepsMatrixAndFractureRest = = 0 & & timeStepCount = = timeStepsMatrixAndFracture )
{
keywordsWithCorrectNumberOfDataItems . push_back ( keywords [ i ] ) ;
}
}
}
return keywordsWithCorrectNumberOfDataItems ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderEclipseOutput : : extractResultValuesBasedOnPorosityModel ( PorosityModelResultType matrixOrFracture , std : : vector < double > * destinationResultValues , const std : : vector < double > & sourceResultValues )
{
if ( matrixOrFracture = = RifReaderInterface : : MATRIX_RESULTS )
{
if ( m_mainGrid - > globalFractureModelActiveCellCount ( ) = = 0 )
{
destinationResultValues - > insert ( destinationResultValues - > end ( ) , sourceResultValues . begin ( ) , sourceResultValues . end ( ) ) ;
}
else
{
size_t dataItemCount = 0 ;
size_t sourceStartPosition = 0 ;
for ( size_t i = 0 ; i < m_mainGrid - > gridCount ( ) ; i + + )
{
size_t matrixActiveCellCount = m_mainGrid - > gridByIndex ( i ) - > matrixModelActiveCellCount ( ) ;
size_t fractureActiveCellCount = m_mainGrid - > gridByIndex ( i ) - > matrixModelActiveCellCount ( ) ;
destinationResultValues - > insert ( destinationResultValues - > end ( ) , sourceResultValues . begin ( ) + sourceStartPosition , sourceResultValues . begin ( ) + sourceStartPosition + matrixActiveCellCount ) ;
sourceStartPosition + = ( matrixActiveCellCount + fractureActiveCellCount ) ;
}
}
}
else
{
size_t dataItemCount = 0 ;
size_t sourceStartPosition = 0 ;
for ( size_t i = 0 ; i < m_mainGrid - > gridCount ( ) ; i + + )
{
size_t matrixActiveCellCount = m_mainGrid - > gridByIndex ( i ) - > matrixModelActiveCellCount ( ) ;
size_t fractureActiveCellCount = m_mainGrid - > gridByIndex ( i ) - > matrixModelActiveCellCount ( ) ;
destinationResultValues - > insert ( destinationResultValues - > end ( ) , sourceResultValues . begin ( ) + sourceStartPosition + matrixActiveCellCount , sourceResultValues . begin ( ) + sourceStartPosition + matrixActiveCellCount + fractureActiveCellCount ) ;
sourceStartPosition + = ( matrixActiveCellCount + fractureActiveCellCount ) ;
}
}
}