mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-01 03:37:15 -06:00
1181 lines
44 KiB
C++
1181 lines
44 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2011- Statoil ASA
|
|
// Copyright (C) 2013- Ceetron Solutions AS
|
|
// Copyright (C) 2011-2012 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 "RifReaderEclipseOutput.h"
|
|
|
|
#include "RiaCellDividingTools.h"
|
|
#include "RiaEclipseUnitTools.h"
|
|
#include "RiaLogging.h"
|
|
|
|
#include "RiaStringEncodingTools.h"
|
|
#include "RifActiveCellsReader.h"
|
|
#include "RifEclipseInputFileTools.h"
|
|
#include "RifEclipseOutputFileTools.h"
|
|
#include "RifEclipseRestartDataAccess.h"
|
|
#include "RifHdf5ReaderInterface.h"
|
|
#include "RifOpmRadialGridTools.h"
|
|
#include "RifReaderEclipseWell.h"
|
|
|
|
#ifdef USE_HDF5
|
|
#include "RifHdf5Reader.h"
|
|
#endif
|
|
|
|
#include "RigActiveCellInfo.h"
|
|
#include "RigCaseCellResultsData.h"
|
|
#include "RigEclipseCaseData.h"
|
|
#include "RigEclipseResultInfo.h"
|
|
#include "RigEquil.h"
|
|
#include "RigMainGrid.h"
|
|
#include "RigNNCData.h"
|
|
#include "Well/RigSimWellData.h"
|
|
#include "Well/RigWellResultFrame.h"
|
|
#include "Well/RigWellResultPoint.h"
|
|
|
|
#include "cafProgressInfo.h"
|
|
|
|
#include "cvfTrace.h"
|
|
|
|
#include "ert/ecl/ecl_kw_magic.h"
|
|
#include "ert/ecl/ecl_nnc_data.h"
|
|
#include "ert/ecl/ecl_nnc_export.h"
|
|
#include "ert/ecl/ecl_nnc_geometry.h"
|
|
|
|
#include <QDateTime>
|
|
#include <QFileInfo>
|
|
|
|
#include <cmath> // Needed for HUGE_VAL on Linux
|
|
#include <iostream>
|
|
#include <map>
|
|
|
|
#ifdef USE_OPENMP
|
|
#include <omp.h>
|
|
#endif
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// ECLIPSE cell numbering layout:
|
|
/// Lower layer: Upper layer
|
|
/// Low Depth High Depth
|
|
/// Low K High K
|
|
/// Shallow Deep
|
|
/// 2---3 6---7
|
|
/// | | | |
|
|
/// 0---1 4---5
|
|
///
|
|
///
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
// The indexing conventions for vertices in ECLIPSE
|
|
//
|
|
// 2-------------3
|
|
// /| /|
|
|
// / | / | /j
|
|
// / | / | /
|
|
// 0-------------1 | *---i
|
|
// | | | | |
|
|
// | 6---------|---7 |
|
|
// | / | / |k
|
|
// | / | /
|
|
// |/ |/
|
|
// 4-------------5
|
|
// vertex indices
|
|
//
|
|
// The indexing conventions for vertices in ResInsight
|
|
//
|
|
// 7-------------6 |k
|
|
// /| /| | /j
|
|
// / | / | |/
|
|
// / | / | *---i
|
|
// 4-------------5 |
|
|
// | | | |
|
|
// | 3---------|---2
|
|
// | / | /
|
|
// | / | /
|
|
// |/ |/
|
|
// 0-------------1
|
|
// vertex indices
|
|
//
|
|
|
|
static const size_t cellMappingECLRi[8] = { 0, 1, 3, 2, 4, 5, 7, 6 };
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Constructor
|
|
//--------------------------------------------------------------------------------------------------
|
|
RifReaderEclipseOutput::RifReaderEclipseOutput()
|
|
{
|
|
m_fileName.clear();
|
|
m_filesWithSameBaseName.clear();
|
|
|
|
m_eclipseCaseData = nullptr;
|
|
|
|
m_ecl_init_file = nullptr;
|
|
m_dynamicResultsAccess = nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Destructor
|
|
//--------------------------------------------------------------------------------------------------
|
|
RifReaderEclipseOutput::~RifReaderEclipseOutput()
|
|
{
|
|
if ( m_ecl_init_file )
|
|
{
|
|
ecl_file_close( m_ecl_init_file );
|
|
}
|
|
m_ecl_init_file = nullptr;
|
|
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
m_dynamicResultsAccess->close();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RifReaderEclipseOutput::transferGridCellData( RigMainGrid* mainGrid,
|
|
RigActiveCellInfo* activeCellInfo,
|
|
RigActiveCellInfo* fractureActiveCellInfo,
|
|
RigGridBase* localGrid,
|
|
const ecl_grid_type* localEclGrid,
|
|
size_t matrixActiveStartIndex,
|
|
size_t fractureActiveStartIndex,
|
|
bool invalidateLongPyramidCells )
|
|
{
|
|
CVF_ASSERT( activeCellInfo && fractureActiveCellInfo );
|
|
|
|
int cellCount = ecl_grid_get_global_size( localEclGrid );
|
|
size_t cellStartIndex = mainGrid->reservoirCells().size();
|
|
size_t nodeStartIndex = mainGrid->nodes().size();
|
|
|
|
RigCell defaultCell;
|
|
defaultCell.setHostGrid( localGrid );
|
|
mainGrid->reservoirCells().resize( cellStartIndex + cellCount, defaultCell );
|
|
|
|
mainGrid->nodes().resize( nodeStartIndex + cellCount * 8, cvf::Vec3d( 0, 0, 0 ) );
|
|
|
|
// Loop over cells and fill them with data
|
|
|
|
#pragma omp parallel for
|
|
for ( int gridLocalCellIndex = 0; gridLocalCellIndex < cellCount; ++gridLocalCellIndex )
|
|
{
|
|
RigCell& cell = mainGrid->cell( cellStartIndex + gridLocalCellIndex );
|
|
|
|
cell.setGridLocalCellIndex( gridLocalCellIndex );
|
|
|
|
// Active cell index
|
|
int matrixActiveIndex = ecl_grid_get_active_index1( localEclGrid, gridLocalCellIndex );
|
|
if ( matrixActiveIndex != -1 )
|
|
{
|
|
activeCellInfo->setCellResultIndex( cellStartIndex + gridLocalCellIndex, matrixActiveStartIndex + matrixActiveIndex );
|
|
}
|
|
|
|
int fractureActiveIndex = ecl_grid_get_active_fracture_index1( localEclGrid, gridLocalCellIndex );
|
|
if ( fractureActiveIndex != -1 )
|
|
{
|
|
fractureActiveCellInfo->setCellResultIndex( cellStartIndex + gridLocalCellIndex, fractureActiveStartIndex + fractureActiveIndex );
|
|
}
|
|
|
|
// Parent cell index
|
|
int parentCellIndex = ecl_grid_get_parent_cell1( localEclGrid, gridLocalCellIndex );
|
|
if ( parentCellIndex == -1 )
|
|
{
|
|
cell.setParentCellIndex( cvf::UNDEFINED_SIZE_T );
|
|
}
|
|
else
|
|
{
|
|
cell.setParentCellIndex( parentCellIndex );
|
|
}
|
|
|
|
// Corner coordinates
|
|
int cIdx;
|
|
for ( cIdx = 0; cIdx < 8; ++cIdx )
|
|
{
|
|
double* point = mainGrid->nodes()[nodeStartIndex + (size_t)gridLocalCellIndex * 8 + cellMappingECLRi[cIdx]].ptr();
|
|
ecl_grid_get_cell_corner_xyz1( localEclGrid, gridLocalCellIndex, cIdx, &( point[0] ), &( point[1] ), &( point[2] ) );
|
|
point[2] = -point[2]; // Flipping Z making depth become negative z values
|
|
cell.cornerIndices()[cIdx] = nodeStartIndex + (size_t)gridLocalCellIndex * 8 + cIdx;
|
|
}
|
|
|
|
// Sub grid in cell
|
|
const ecl_grid_type* subGrid = ecl_grid_get_cell_lgr1( localEclGrid, gridLocalCellIndex );
|
|
if ( subGrid != nullptr )
|
|
{
|
|
int subGridId = ecl_grid_get_lgr_nr( subGrid );
|
|
CVF_ASSERT( subGridId > 0 );
|
|
cell.setSubGrid( static_cast<RigLocalGrid*>( mainGrid->gridById( subGridId ) ) );
|
|
}
|
|
|
|
// Mark inactive long pyramid looking cells as invalid
|
|
// Forslag
|
|
// if (!invalid && (cell.isInCoarseCell() || (!cell.isActiveInMatrixModel() &&
|
|
// !cell.isActiveInFractureModel()) ) )
|
|
if ( invalidateLongPyramidCells )
|
|
{
|
|
cell.setInvalid( cell.isLongPyramidCell() );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Read geometry from file given by name into given reservoir object
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RifReaderEclipseOutput::transferGeometry( const ecl_grid_type* mainEclGrid, RigEclipseCaseData* eclipseCase, bool invalidateLongThinCells )
|
|
{
|
|
CVF_ASSERT( eclipseCase );
|
|
|
|
if ( !mainEclGrid )
|
|
{
|
|
// Some error
|
|
return false;
|
|
}
|
|
|
|
RigActiveCellInfo* activeCellInfo = eclipseCase->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
|
RigActiveCellInfo* fractureActiveCellInfo = eclipseCase->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL );
|
|
|
|
CVF_ASSERT( activeCellInfo && fractureActiveCellInfo );
|
|
|
|
RigMainGrid* mainGrid = eclipseCase->mainGrid();
|
|
CVF_ASSERT( 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 );
|
|
}
|
|
|
|
// std::string mainGridName = ecl_grid_get_name(mainEclGrid);
|
|
// ERT returns file path to grid file as name for main grid
|
|
mainGrid->setGridName( "Main grid" );
|
|
|
|
mainGrid->setDualPorosity( ecl_grid_dual_grid( mainEclGrid ) );
|
|
|
|
// 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 );
|
|
int lgrId = ecl_grid_get_lgr_nr( 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 );
|
|
localGrid->setGridId( lgrId );
|
|
mainGrid->addLocalGrid( localGrid );
|
|
|
|
localGrid->setIndexToStartOfCells( totalCellCount );
|
|
localGrid->setGridName( lgrName );
|
|
localGrid->setGridPointDimensions( gridPointDim );
|
|
|
|
totalCellCount += ecl_grid_get_global_size( localEclGrid );
|
|
}
|
|
|
|
activeCellInfo->setReservoirCellCount( totalCellCount );
|
|
fractureActiveCellInfo->setReservoirCellCount( totalCellCount );
|
|
|
|
// Reserve room for the cells and nodes and fill them with data
|
|
|
|
mainGrid->reservoirCells().reserve( totalCellCount );
|
|
mainGrid->nodes().reserve( 8 * totalCellCount );
|
|
|
|
caf::ProgressInfo progInfo( 3 + numLGRs, "" );
|
|
|
|
{
|
|
auto task = progInfo.task( "Loading Main Grid Data", 3 );
|
|
transferGridCellData( mainGrid, activeCellInfo, fractureActiveCellInfo, mainGrid, mainEclGrid, 0, 0, invalidateLongThinCells );
|
|
}
|
|
|
|
size_t globalMatrixActiveSize = ecl_grid_get_nactive( mainEclGrid );
|
|
size_t globalFractureActiveSize = ecl_grid_get_nactive_fracture( mainEclGrid );
|
|
|
|
activeCellInfo->setGridCount( 1 + numLGRs );
|
|
fractureActiveCellInfo->setGridCount( 1 + numLGRs );
|
|
|
|
activeCellInfo->setGridActiveCellCounts( 0, globalMatrixActiveSize );
|
|
fractureActiveCellInfo->setGridActiveCellCounts( 0, globalFractureActiveSize );
|
|
|
|
transferCoarseningInfo( mainEclGrid, mainGrid );
|
|
|
|
for ( lgrIdx = 0; lgrIdx < numLGRs; ++lgrIdx )
|
|
{
|
|
auto task = progInfo.task( "LGR number " + QString::number( lgrIdx + 1 ), 1 );
|
|
|
|
ecl_grid_type* localEclGrid = ecl_grid_iget_lgr( mainEclGrid, lgrIdx );
|
|
RigLocalGrid* localGrid = static_cast<RigLocalGrid*>( mainGrid->gridByIndex( lgrIdx + 1 ) );
|
|
|
|
transferGridCellData( mainGrid,
|
|
activeCellInfo,
|
|
fractureActiveCellInfo,
|
|
localGrid,
|
|
localEclGrid,
|
|
globalMatrixActiveSize,
|
|
globalFractureActiveSize,
|
|
invalidateLongThinCells );
|
|
|
|
int matrixActiveCellCount = ecl_grid_get_nactive( localEclGrid );
|
|
globalMatrixActiveSize += matrixActiveCellCount;
|
|
|
|
int fractureActiveCellCount = ecl_grid_get_nactive_fracture( localEclGrid );
|
|
globalFractureActiveSize += fractureActiveCellCount;
|
|
|
|
activeCellInfo->setGridActiveCellCounts( lgrIdx + 1, matrixActiveCellCount );
|
|
fractureActiveCellInfo->setGridActiveCellCounts( lgrIdx + 1, fractureActiveCellCount );
|
|
|
|
transferCoarseningInfo( localEclGrid, localGrid );
|
|
}
|
|
|
|
mainGrid->initAllSubGridsParentGridPointer();
|
|
activeCellInfo->computeDerivedData();
|
|
fractureActiveCellInfo->computeDerivedData();
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Open file and read geometry into given reservoir object
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RifReaderEclipseOutput::open( const QString& fileName, RigEclipseCaseData* eclipseCaseData )
|
|
{
|
|
CVF_ASSERT( eclipseCaseData );
|
|
caf::ProgressInfo progress( 100, "Reading Grid" );
|
|
|
|
if ( !RifEclipseOutputFileTools::isValidEclipseFileName( fileName ) )
|
|
{
|
|
QString errorMessage = QFileInfo( fileName ).fileName() +
|
|
QString( " is not a valid Eclipse file name.\n"
|
|
"Please make sure the file does not contain a mix of upper and lower case letters." );
|
|
RiaLogging::error( errorMessage );
|
|
return false;
|
|
}
|
|
|
|
QStringList fileSet;
|
|
{
|
|
auto task = progress.task( "Get set of files" );
|
|
|
|
if ( !RifEclipseOutputFileTools::findSiblingFilesWithSameBaseName( fileName, &fileSet ) ) return false;
|
|
|
|
m_fileName = fileName;
|
|
m_filesWithSameBaseName = fileSet;
|
|
}
|
|
|
|
ecl_grid_type* mainEclGrid = nullptr;
|
|
{
|
|
auto task = progress.task( "Open Init File and Load Main Grid", 19 );
|
|
|
|
openInitFile();
|
|
|
|
// Read geometry
|
|
// Todo: Needs to check existence of file before calling ert, else it will abort
|
|
mainEclGrid = loadAllGrids();
|
|
if ( !mainEclGrid )
|
|
{
|
|
QString errorMessage = QString( " Failed to create a main grid from file\n%1" ).arg( m_fileName );
|
|
RiaLogging::error( errorMessage );
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
{
|
|
auto task = progress.task( "Transferring grid geometry", 10 );
|
|
if ( !transferGeometry( mainEclGrid, eclipseCaseData, invalidateLongThinCells() ) ) return false;
|
|
|
|
RifOpmRadialGridTools::importCoordinatesForRadialGrid( fileName.toStdString(), eclipseCaseData->mainGrid() );
|
|
}
|
|
|
|
{
|
|
auto task = progress.task( "Reading faults", 10 );
|
|
|
|
if ( isFaultImportEnabled() )
|
|
{
|
|
cvf::Collection<RigFault> faults;
|
|
|
|
importFaults( fileSet, &faults );
|
|
|
|
RigMainGrid* mainGrid = eclipseCaseData->mainGrid();
|
|
mainGrid->setFaults( faults );
|
|
}
|
|
}
|
|
|
|
m_eclipseCaseData = eclipseCaseData;
|
|
|
|
{
|
|
auto task = progress.task( "Reading Results Meta data", 25 );
|
|
buildMetaData( mainEclGrid );
|
|
}
|
|
|
|
{
|
|
auto task = progress.task( "Handling NCC data", 20 );
|
|
if ( isNNCsEnabled() )
|
|
{
|
|
caf::ProgressInfo nncProgress( 10, "" );
|
|
RigMainGrid* mainGrid = eclipseCaseData->mainGrid();
|
|
|
|
{
|
|
auto subNncTask = nncProgress.task( "Reading static NNC data" );
|
|
transferStaticNNCData( mainEclGrid, m_ecl_init_file, mainGrid );
|
|
}
|
|
|
|
// This test should probably be improved to test more directly for presence of NNC data
|
|
if ( m_eclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->hasFlowDiagUsableFluxes() )
|
|
{
|
|
auto subNncTask = nncProgress.task( "Reading dynamic NNC data" );
|
|
transferDynamicNNCData( mainEclGrid, mainGrid );
|
|
}
|
|
|
|
RigActiveCellInfo* activeCellInfo = m_eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
|
|
|
bool includeInactiveCells = includeInactiveCellsInFaultGeometry();
|
|
mainGrid->nncData()->setSourceDataForProcessing( mainGrid, activeCellInfo, includeInactiveCells );
|
|
}
|
|
}
|
|
|
|
{
|
|
auto task = progress.task( "Handling well information", 10 );
|
|
if ( loadWellDataEnabled() )
|
|
{
|
|
std::vector<QDateTime> filteredTimeSteps;
|
|
std::vector<RigEclipseTimeStepInfo> filteredTimeStepInfos = createFilteredTimeStepInfos();
|
|
for ( auto a : filteredTimeStepInfos )
|
|
{
|
|
filteredTimeSteps.push_back( a.m_date );
|
|
}
|
|
|
|
std::vector<std::string> gridNames;
|
|
gridNames.push_back( "global" );
|
|
for ( int i = 0; i < ecl_grid_get_num_lgr( mainEclGrid ); i++ )
|
|
{
|
|
const char* gridName = ecl_grid_iget_lgr_name( mainEclGrid, i );
|
|
gridNames.push_back( gridName );
|
|
}
|
|
|
|
RifReaderEclipseWell::readWellCells( m_dynamicResultsAccess.p(),
|
|
m_eclipseCaseData,
|
|
filteredTimeSteps,
|
|
gridNames,
|
|
isImportOfCompleteMswDataEnabled() );
|
|
}
|
|
else
|
|
{
|
|
RiaLogging::info( "Skipping import of simulation well data" );
|
|
}
|
|
}
|
|
|
|
{
|
|
auto task = progress.task( "Releasing reader memory", 5 );
|
|
ecl_grid_free( mainEclGrid );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::setHdf5FileName( const QString& fileName )
|
|
{
|
|
CVF_ASSERT( m_eclipseCaseData );
|
|
|
|
RigCaseCellResultsData* matrixModelResults = m_eclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
|
CVF_ASSERT( matrixModelResults );
|
|
|
|
if ( fileName.isEmpty() )
|
|
{
|
|
RiaLogging::info( "HDF: Removing all existing Sour Sim data ..." );
|
|
matrixModelResults->eraseAllSourSimData();
|
|
|
|
return;
|
|
}
|
|
|
|
RiaLogging::info( QString( "HDF: Start import of data from : " ).arg( fileName ) );
|
|
|
|
RiaLogging::info( "HDF: Removing all existing Sour Sim data ..." );
|
|
matrixModelResults->eraseAllSourSimData();
|
|
|
|
std::vector<RigEclipseTimeStepInfo> timeStepInfos = createFilteredTimeStepInfos();
|
|
|
|
std::unique_ptr<RifHdf5ReaderInterface> hdf5ReaderInterface;
|
|
#ifdef USE_HDF5
|
|
hdf5ReaderInterface = std::unique_ptr<RifHdf5ReaderInterface>( new RifHdf5Reader( fileName ) );
|
|
#endif // USE_HDF5
|
|
|
|
if ( !hdf5ReaderInterface )
|
|
{
|
|
return;
|
|
}
|
|
|
|
std::vector<QDateTime> sourSimTimeSteps = hdf5ReaderInterface->timeSteps();
|
|
if ( sourSimTimeSteps.empty() )
|
|
{
|
|
RiaLogging::error( "HDF: No data available from SourSim" );
|
|
|
|
return;
|
|
}
|
|
|
|
if ( !timeStepInfos.empty() )
|
|
{
|
|
if ( allTimeSteps().size() != sourSimTimeSteps.size() )
|
|
{
|
|
RiaLogging::error(
|
|
QString( "HDF: Time step count mismatch, Eclipse : %1 ; HDF : %2 " ).arg( allTimeSteps().size() ).arg( sourSimTimeSteps.size() ) );
|
|
|
|
return;
|
|
}
|
|
|
|
bool isTimeStampsEqual = true;
|
|
for ( size_t i = 0; i < timeStepInfos.size(); i++ )
|
|
{
|
|
size_t indexOnFile = timeStepIndexOnFile( i );
|
|
if ( indexOnFile < sourSimTimeSteps.size() )
|
|
{
|
|
if ( !isEclipseAndSoursimTimeStepsEqual( timeStepInfos[i].m_date, sourSimTimeSteps[indexOnFile] ) )
|
|
{
|
|
isTimeStampsEqual = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RiaLogging::error(
|
|
QString( "HDF: Time step count mismatch, Eclipse : %1 ; HDF : %2 " ).arg( timeStepInfos.size() ).arg( sourSimTimeSteps.size() ) );
|
|
|
|
// We have less soursim time steps than eclipse time steps
|
|
isTimeStampsEqual = false;
|
|
}
|
|
}
|
|
|
|
if ( !isTimeStampsEqual ) return;
|
|
}
|
|
else
|
|
{
|
|
// Use time steps from HDF to define the time steps
|
|
QDateTime firstDate = sourSimTimeSteps[0];
|
|
|
|
std::vector<double> daysSinceSimulationStart;
|
|
|
|
for ( auto d : sourSimTimeSteps )
|
|
{
|
|
daysSinceSimulationStart.push_back( firstDate.daysTo( d ) );
|
|
}
|
|
|
|
std::vector<int> reportNumbers;
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
reportNumbers = m_dynamicResultsAccess->reportNumbers();
|
|
}
|
|
else
|
|
{
|
|
for ( size_t i = 0; i < sourSimTimeSteps.size(); i++ )
|
|
{
|
|
reportNumbers.push_back( static_cast<int>( i ) );
|
|
}
|
|
}
|
|
|
|
timeStepInfos = RigEclipseTimeStepInfo::createTimeStepInfos( sourSimTimeSteps, reportNumbers, daysSinceSimulationStart );
|
|
}
|
|
|
|
QStringList resultNames = hdf5ReaderInterface->propertyNames();
|
|
|
|
for ( int i = 0; i < resultNames.size(); ++i )
|
|
{
|
|
RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::SOURSIMRL, resultNames[i] );
|
|
matrixModelResults->createResultEntry( resAddr, false );
|
|
matrixModelResults->setTimeStepInfos( resAddr, timeStepInfos );
|
|
}
|
|
|
|
m_hdfReaderInterface = std::move( hdf5ReaderInterface );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::setFileDataAccess( RifEclipseRestartDataAccess* restartDataAccess )
|
|
{
|
|
m_dynamicResultsAccess = restartDataAccess;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const size_t* RifReaderEclipseOutput::eclipseCellIndexMapping()
|
|
{
|
|
return cellMappingECLRi;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::importEquilData( const QString& deckFileName,
|
|
const QString& includeStatementAbsolutePathPrefix,
|
|
RigEclipseCaseData* eclipseCase )
|
|
{
|
|
QFile file( deckFileName );
|
|
if ( file.open( QFile::ReadOnly ) )
|
|
{
|
|
const QString keyword( "EQUIL" );
|
|
const QString keywordToStopParsing( "SCHEDULE" );
|
|
auto keywordContent = RifEclipseInputFileTools::readKeywordContentFromFile( keyword, keywordToStopParsing, file );
|
|
|
|
std::vector<RigEquil> equilItems;
|
|
for ( const auto& s : keywordContent )
|
|
{
|
|
RigEquil equilRec = RigEquil::parseString( s );
|
|
|
|
equilItems.push_back( equilRec );
|
|
}
|
|
|
|
eclipseCase->setEquilData( equilItems );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::transferStaticNNCData( const ecl_grid_type* mainEclGrid, ecl_file_type* init_file, RigMainGrid* mainGrid )
|
|
{
|
|
if ( !m_ecl_init_file ) return;
|
|
|
|
CVF_ASSERT( mainEclGrid && mainGrid );
|
|
|
|
// Get the data from ERT
|
|
ecl_nnc_geometry_type* nnc_geo = ecl_nnc_geometry_alloc( mainEclGrid );
|
|
if ( nnc_geo )
|
|
{
|
|
ecl_nnc_data_type* tran_data = ecl_nnc_data_alloc_tran( mainEclGrid, nnc_geo, ecl_file_get_global_view( init_file ) );
|
|
if ( tran_data )
|
|
{
|
|
int numNNC = ecl_nnc_data_get_size( tran_data );
|
|
int geometrySize = ecl_nnc_geometry_size( nnc_geo );
|
|
CVF_ASSERT( numNNC == geometrySize );
|
|
|
|
if ( numNNC > 0 )
|
|
{
|
|
// Transform to our own data structures
|
|
RigConnectionContainer nncConnections;
|
|
std::vector<double> transmissibilityValuesTemp;
|
|
|
|
const double* transValues = ecl_nnc_data_get_values( tran_data );
|
|
|
|
for ( int nIdx = 0; nIdx < numNNC; ++nIdx )
|
|
{
|
|
const ecl_nnc_pair_type* geometry_pair = ecl_nnc_geometry_iget( nnc_geo, nIdx );
|
|
RigGridBase* grid1 = mainGrid->gridByIndex( geometry_pair->grid_nr1 );
|
|
RigGridBase* grid2 = mainGrid->gridByIndex( geometry_pair->grid_nr2 );
|
|
|
|
RigConnection nncConnection( grid1->reservoirCellIndex( geometry_pair->global_index1 ),
|
|
grid2->reservoirCellIndex( geometry_pair->global_index2 ) );
|
|
|
|
nncConnections.push_back( nncConnection );
|
|
|
|
transmissibilityValuesTemp.push_back( transValues[nIdx] );
|
|
}
|
|
|
|
mainGrid->nncData()->setEclipseConnections( nncConnections );
|
|
mainGrid->nncData()->makeScalarResultAndSetValues( RiaDefines::propertyNameCombTrans(), transmissibilityValuesTemp );
|
|
}
|
|
|
|
ecl_nnc_data_free( tran_data );
|
|
}
|
|
|
|
ecl_nnc_geometry_free( nnc_geo );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::transferDynamicNNCData( const ecl_grid_type* mainEclGrid, RigMainGrid* mainGrid )
|
|
{
|
|
CVF_ASSERT( mainEclGrid && mainGrid );
|
|
|
|
if ( m_dynamicResultsAccess.isNull() ) return;
|
|
|
|
size_t timeStepCount = m_dynamicResultsAccess->timeStepCount();
|
|
|
|
std::vector<std::vector<double>>& waterFluxData =
|
|
mainGrid->nncData()->makeDynamicConnectionScalarResult( RiaDefines::propertyNameFluxWat(), timeStepCount );
|
|
std::vector<std::vector<double>>& oilFluxData =
|
|
mainGrid->nncData()->makeDynamicConnectionScalarResult( RiaDefines::propertyNameFluxOil(), timeStepCount );
|
|
std::vector<std::vector<double>>& gasFluxData =
|
|
mainGrid->nncData()->makeDynamicConnectionScalarResult( RiaDefines::propertyNameFluxGas(), timeStepCount );
|
|
|
|
for ( size_t timeStep = 0; timeStep < timeStepCount; ++timeStep )
|
|
{
|
|
m_dynamicResultsAccess->dynamicNNCResults( mainEclGrid, timeStep, &waterFluxData[timeStep], &oilFluxData[timeStep], &gasFluxData[timeStep] );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RifReaderEclipseOutput::openAndReadActiveCellData( const QString& fileName,
|
|
const std::vector<QDateTime>& mainCaseTimeSteps,
|
|
RigEclipseCaseData* eclipseCase )
|
|
{
|
|
CVF_ASSERT( eclipseCase );
|
|
|
|
// It is required to have a main grid before reading active cell data
|
|
if ( !eclipseCase->mainGrid() )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Get set of files
|
|
QStringList fileSet;
|
|
if ( !RifEclipseOutputFileTools::findSiblingFilesWithSameBaseName( fileName, &fileSet ) ) return false;
|
|
|
|
// Keep the set of files of interest
|
|
m_filesWithSameBaseName = fileSet;
|
|
m_eclipseCaseData = eclipseCase;
|
|
m_fileName = fileName;
|
|
|
|
if ( !readActiveCellInfo() )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ensureDynamicResultAccessIsPresent();
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
m_dynamicResultsAccess->setTimeSteps( mainCaseTimeSteps );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RifReaderEclipseOutput::readActiveCellInfo()
|
|
{
|
|
CVF_ASSERT( m_eclipseCaseData );
|
|
CVF_ASSERT( m_eclipseCaseData->mainGrid() );
|
|
|
|
std::vector<std::vector<int>> actnumValuesPerGrid;
|
|
|
|
{
|
|
// If INIT file is present and PORV is found, use PORV as basis for active cells
|
|
QString initFileName = RifEclipseOutputFileTools::firstFileNameOfType( m_filesWithSameBaseName, ECL_INIT_FILE );
|
|
if ( initFileName.size() > 0 )
|
|
{
|
|
ecl_file_type* ecl_file = ecl_file_open( RiaStringEncodingTools::toNativeEncoded( initFileName ).data(), ECL_FILE_CLOSE_STREAM );
|
|
if ( ecl_file )
|
|
{
|
|
bool isDualPorosity = m_eclipseCaseData->mainGrid()->isDualPorosity();
|
|
int cellCountMainGrid = static_cast<int>( m_eclipseCaseData->mainGrid()->cellCount() );
|
|
actnumValuesPerGrid = RifActiveCellsReader::activeCellsFromPorvKeyword( ecl_file, isDualPorosity, cellCountMainGrid );
|
|
ecl_file_close( ecl_file );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( actnumValuesPerGrid.empty() )
|
|
{
|
|
// Try ACTNUM from grid file as basis for active cells
|
|
QString egridFileName = RifEclipseOutputFileTools::firstFileNameOfType( m_filesWithSameBaseName, ECL_EGRID_FILE );
|
|
if ( egridFileName.size() > 0 )
|
|
{
|
|
ecl_file_type* ecl_file = ecl_file_open( RiaStringEncodingTools::toNativeEncoded( egridFileName ).data(), ECL_FILE_CLOSE_STREAM );
|
|
if ( ecl_file )
|
|
{
|
|
actnumValuesPerGrid = RifActiveCellsReader::activeCellsFromActnumKeyword( ecl_file );
|
|
ecl_file_close( ecl_file );
|
|
}
|
|
}
|
|
}
|
|
|
|
return RifEclipseOutputFileTools::assignActiveCellData( actnumValuesPerGrid, m_eclipseCaseData );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Build meta data - get states and results info
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::buildMetaData( ecl_grid_type* grid )
|
|
{
|
|
CVF_ASSERT( m_eclipseCaseData );
|
|
CVF_ASSERT( !m_filesWithSameBaseName.empty() );
|
|
|
|
caf::ProgressInfo progInfo( m_filesWithSameBaseName.size() + 3, "" );
|
|
|
|
progInfo.setNextProgressIncrement( m_filesWithSameBaseName.size() );
|
|
|
|
std::vector<RigEclipseTimeStepInfo> timeStepInfos;
|
|
|
|
// Create access object for dynamic results
|
|
ensureDynamicResultAccessIsPresent();
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
progInfo.incrementProgress();
|
|
|
|
m_dynamicResultsAccess->open();
|
|
|
|
timeStepInfos = createFilteredTimeStepInfos();
|
|
auto keywordInfo = m_dynamicResultsAccess->keywordValueCounts();
|
|
|
|
RifEclipseOutputFileTools::createResultEntries( keywordInfo,
|
|
timeStepInfos,
|
|
RiaDefines::ResultCatType::DYNAMIC_NATIVE,
|
|
m_eclipseCaseData,
|
|
m_dynamicResultsAccess->timeStepCount() );
|
|
}
|
|
|
|
progInfo.incrementProgress();
|
|
|
|
openInitFile();
|
|
|
|
// Unit system
|
|
{
|
|
// Default units type is METRIC
|
|
RiaDefines::EclipseUnitSystem unitsType = RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
|
int unitsTypeValue;
|
|
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
unitsTypeValue = m_dynamicResultsAccess->readUnitsType();
|
|
}
|
|
else
|
|
{
|
|
if ( m_ecl_init_file )
|
|
{
|
|
unitsTypeValue = RifEclipseOutputFileTools::readUnitsType( m_ecl_init_file );
|
|
}
|
|
else
|
|
{
|
|
unitsTypeValue = ecl_grid_get_unit_system( grid );
|
|
}
|
|
}
|
|
|
|
if ( unitsTypeValue == 2 )
|
|
{
|
|
unitsType = RiaDefines::EclipseUnitSystem::UNITS_FIELD;
|
|
}
|
|
else if ( unitsTypeValue == 3 )
|
|
{
|
|
unitsType = RiaDefines::EclipseUnitSystem::UNITS_LAB;
|
|
}
|
|
m_eclipseCaseData->setUnitsType( unitsType );
|
|
}
|
|
|
|
progInfo.incrementProgress();
|
|
|
|
if ( m_ecl_init_file )
|
|
{
|
|
std::vector<ecl_file_type*> filesUsedToFindAvailableKeywords;
|
|
filesUsedToFindAvailableKeywords.push_back( m_ecl_init_file );
|
|
|
|
auto keywordInfo = RifEclipseOutputFileTools::keywordValueCounts( filesUsedToFindAvailableKeywords );
|
|
|
|
std::vector<RigEclipseTimeStepInfo> staticTimeStepInfo;
|
|
if ( !timeStepInfos.empty() )
|
|
{
|
|
staticTimeStepInfo.push_back( timeStepInfos.front() );
|
|
}
|
|
|
|
RifEclipseOutputFileTools::createResultEntries( keywordInfo,
|
|
staticTimeStepInfo,
|
|
RiaDefines::ResultCatType::STATIC_NATIVE,
|
|
m_eclipseCaseData,
|
|
1 );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Create results access object (.UNRST or .X0001 ... .XNNNN)
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::ensureDynamicResultAccessIsPresent()
|
|
{
|
|
if ( m_dynamicResultsAccess.isNull() )
|
|
{
|
|
m_dynamicResultsAccess = RifEclipseOutputFileTools::createDynamicResultAccess( m_fileName );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Get all values of a given static result as doubles
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RifReaderEclipseOutput::staticResult( const QString& result, RiaDefines::PorosityModelType matrixOrFracture, std::vector<double>* values )
|
|
{
|
|
CVF_ASSERT( values );
|
|
|
|
if ( result.compare( "ACTNUM", Qt::CaseInsensitive ) == 0 )
|
|
{
|
|
RigActiveCellInfo* activeCellInfo = m_eclipseCaseData->activeCellInfo( matrixOrFracture );
|
|
values->resize( activeCellInfo->reservoirActiveCellCount(), 1.0 );
|
|
|
|
return true;
|
|
}
|
|
|
|
openInitFile();
|
|
|
|
if ( m_ecl_init_file )
|
|
{
|
|
std::vector<double> fileValues;
|
|
|
|
size_t numOccurrences = ecl_file_get_num_named_kw( m_ecl_init_file, result.toLatin1().data() );
|
|
size_t i;
|
|
for ( i = 0; i < numOccurrences; i++ )
|
|
{
|
|
std::vector<double> partValues;
|
|
RifEclipseOutputFileTools::keywordData( m_ecl_init_file, result, i, &partValues );
|
|
fileValues.insert( fileValues.end(), partValues.begin(), partValues.end() );
|
|
}
|
|
|
|
RifEclipseOutputFileTools::extractResultValuesBasedOnPorosityModel( m_eclipseCaseData, matrixOrFracture, values, fileValues );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::sourSimRlResult( const QString& result, size_t stepIndex, std::vector<double>* values )
|
|
{
|
|
values->clear();
|
|
|
|
if ( !m_hdfReaderInterface ) return;
|
|
|
|
if ( m_eclipseCaseData->mainGrid()->gridCount() == 0 )
|
|
{
|
|
RiaLogging::error( "No grids available" );
|
|
|
|
return;
|
|
}
|
|
|
|
RigActiveCellInfo* fracActCellInfo = m_eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
|
size_t activeCellCount = fracActCellInfo->gridActiveCellCounts( 0 );
|
|
|
|
size_t fileIndex = timeStepIndexOnFile( stepIndex );
|
|
|
|
m_hdfReaderInterface->dynamicResult( result, fileIndex, values );
|
|
|
|
if ( activeCellCount != values->size() )
|
|
{
|
|
values->clear();
|
|
|
|
RiaLogging::error( "SourSimRL results does not match the number of active cells in the grid" );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<QDateTime> RifReaderEclipseOutput::allTimeSteps() const
|
|
{
|
|
std::vector<QDateTime> steps;
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
std::vector<double> dymmy;
|
|
m_dynamicResultsAccess->timeSteps( &steps, &dymmy );
|
|
}
|
|
|
|
return steps;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Get dynamic result at given step index. Will concatenate values for the main grid and all sub grids.
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RifReaderEclipseOutput::dynamicResult( const QString& result,
|
|
RiaDefines::PorosityModelType matrixOrFracture,
|
|
size_t stepIndex,
|
|
std::vector<double>* values )
|
|
{
|
|
ensureDynamicResultAccessIsPresent();
|
|
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
size_t indexOnFile = timeStepIndexOnFile( stepIndex );
|
|
|
|
std::vector<double> fileValues;
|
|
if ( !m_dynamicResultsAccess->results( result, indexOnFile, m_eclipseCaseData->mainGrid()->gridCountOnFile(), &fileValues ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
RifEclipseOutputFileTools::extractResultValuesBasedOnPorosityModel( m_eclipseCaseData, matrixOrFracture, values, fileValues );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<RigEclipseTimeStepInfo> RifReaderEclipseOutput::createFilteredTimeStepInfos()
|
|
{
|
|
std::vector<RigEclipseTimeStepInfo> timeStepInfos;
|
|
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
std::vector<QDateTime> timeStepsOnFile;
|
|
std::vector<double> daysSinceSimulationStartOnFile;
|
|
std::vector<int> reportNumbersOnFile;
|
|
|
|
m_dynamicResultsAccess->timeSteps( &timeStepsOnFile, &daysSinceSimulationStartOnFile );
|
|
reportNumbersOnFile = m_dynamicResultsAccess->reportNumbers();
|
|
|
|
if ( timeStepsOnFile.size() != daysSinceSimulationStartOnFile.size() ) return timeStepInfos;
|
|
if ( timeStepsOnFile.size() != reportNumbersOnFile.size() ) return timeStepInfos;
|
|
|
|
for ( size_t i = 0; i < timeStepsOnFile.size(); i++ )
|
|
{
|
|
if ( isTimeStepIncludedByFilter( i ) )
|
|
{
|
|
timeStepInfos.push_back(
|
|
RigEclipseTimeStepInfo( timeStepsOnFile[i], reportNumbersOnFile[i], daysSinceSimulationStartOnFile[i] ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
return timeStepInfos;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RifReaderEclipseOutput::isEclipseAndSoursimTimeStepsEqual( const QDateTime& eclipseDateTime, const QDateTime& sourSimDateTime )
|
|
{
|
|
// Compare date down to and including seconds
|
|
// Compare of complete date time objects will often result in differences
|
|
|
|
const int secondsThreshold = 4;
|
|
const QString dateStr( "yyyy.MMM.dd hh:mm:ss:zzz" );
|
|
|
|
int secondsDiff = eclipseDateTime.secsTo( sourSimDateTime );
|
|
if ( secondsDiff > secondsThreshold )
|
|
{
|
|
RiaLogging::error( "HDF: Time steps does not match" );
|
|
|
|
RiaLogging::error( QString( " %1 - Eclipse" ).arg( eclipseDateTime.toString( dateStr ) ) );
|
|
RiaLogging::error( QString( " %1 - SourSim" ).arg( sourSimDateTime.toString( dateStr ) ) );
|
|
|
|
return false;
|
|
}
|
|
|
|
if ( eclipseDateTime.time().second() != sourSimDateTime.time().second() )
|
|
{
|
|
RiaLogging::warning( "HDF: Time steps differ, but within time step compare threshold" );
|
|
RiaLogging::warning( QString( " %1 - Eclipse" ).arg( eclipseDateTime.toString( dateStr ) ) );
|
|
RiaLogging::warning( QString( " %1 - SourSim" ).arg( sourSimDateTime.toString( dateStr ) ) );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
ecl_grid_type* RifReaderEclipseOutput::loadAllGrids() const
|
|
{
|
|
ecl_grid_type* mainEclGrid = ecl_grid_alloc( RiaStringEncodingTools::toNativeEncoded( m_fileName ).data() );
|
|
|
|
if ( m_ecl_init_file )
|
|
{
|
|
// TODO : ecl_grid_alloc() will automatically read ACTNUM from EGRID file, and reading of active cell
|
|
// information can be skipped if PORV is available
|
|
|
|
bool isDualPorosity = ecl_grid_dual_grid( mainEclGrid );
|
|
auto cellCountMainGrid = ecl_grid_get_global_size( mainEclGrid );
|
|
auto activeCells = RifActiveCellsReader::activeCellsFromPorvKeyword( m_ecl_init_file, isDualPorosity, cellCountMainGrid );
|
|
|
|
if ( !activeCells.empty() )
|
|
{
|
|
RifActiveCellsReader::applyActiveCellsToAllGrids( mainEclGrid, activeCells );
|
|
}
|
|
}
|
|
|
|
return mainEclGrid;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::updateFromGridCount( size_t gridCount )
|
|
{
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
m_dynamicResultsAccess->updateFromGridCount( gridCount );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::openInitFile()
|
|
{
|
|
if ( m_ecl_init_file )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QString initFileName = RifEclipseOutputFileTools::firstFileNameOfType( m_filesWithSameBaseName, ECL_INIT_FILE );
|
|
if ( initFileName.size() > 0 )
|
|
{
|
|
m_ecl_init_file = ecl_file_open( RiaStringEncodingTools::toNativeEncoded( initFileName ).data(), ECL_FILE_CLOSE_STREAM );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEclipseOutput::transferCoarseningInfo( const ecl_grid_type* eclGrid, RigGridBase* grid )
|
|
{
|
|
int coarseGroupCount = ecl_grid_get_num_coarse_groups( eclGrid );
|
|
for ( int i = 0; i < coarseGroupCount; i++ )
|
|
{
|
|
ecl_coarse_cell_type* coarse_cell = ecl_grid_iget_coarse_group( eclGrid, i );
|
|
|
|
if ( coarse_cell )
|
|
{
|
|
size_t i1 = static_cast<size_t>( ecl_coarse_cell_get_i1( coarse_cell ) );
|
|
size_t i2 = static_cast<size_t>( ecl_coarse_cell_get_i2( coarse_cell ) );
|
|
size_t j1 = static_cast<size_t>( ecl_coarse_cell_get_j1( coarse_cell ) );
|
|
size_t j2 = static_cast<size_t>( ecl_coarse_cell_get_j2( coarse_cell ) );
|
|
size_t k1 = static_cast<size_t>( ecl_coarse_cell_get_k1( coarse_cell ) );
|
|
size_t k2 = static_cast<size_t>( ecl_coarse_cell_get_k2( coarse_cell ) );
|
|
|
|
grid->addCoarseningBox( i1, i2, j1, j2, k1, k2 );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<RiaDefines::PhaseType> RifReaderEclipseOutput::availablePhases() const
|
|
{
|
|
if ( m_dynamicResultsAccess.notNull() )
|
|
{
|
|
return m_dynamicResultsAccess->availablePhases();
|
|
}
|
|
|
|
return std::set<RiaDefines::PhaseType>();
|
|
}
|