mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Add support for grid import using opm-common
Add support for import of geometry and results for main grid. Currently no support for LGR. Add selection in Preferences to either use libecl or opm-common for grid import. If RESINSIGHT_DEVEL flag is set, display reader in an Eclipse case to make it possible to compare Eclipse and opm-common in same project. Add more includes to custom-opm-common to be able to support this functionality. opm-common is unchanged.
This commit is contained in:
parent
559f02c13a
commit
81809efee9
@ -62,6 +62,15 @@ void caf::AppEnum<RiaDefines::DepthUnitType>::setUp()
|
||||
setDefault( RiaDefines::DepthUnitType::UNIT_METER );
|
||||
}
|
||||
|
||||
template <>
|
||||
void caf::AppEnum<RiaDefines::GridModelReader>::setUp()
|
||||
{
|
||||
addItem( RiaDefines::GridModelReader::LIBECL, "LIBECL", "libecl" );
|
||||
addItem( RiaDefines::GridModelReader::OPM_COMMON, "OPM_COMMON", "opm-common (beta)" );
|
||||
|
||||
setDefault( RiaDefines::GridModelReader::LIBECL );
|
||||
}
|
||||
|
||||
template <>
|
||||
void caf::AppEnum<RiaDefines::EclipseUnitSystem>::setUp()
|
||||
{
|
||||
|
@ -167,6 +167,12 @@ enum class GridCaseAxis
|
||||
UNDEFINED_AXIS
|
||||
};
|
||||
|
||||
enum class GridModelReader
|
||||
{
|
||||
LIBECL,
|
||||
OPM_COMMON
|
||||
};
|
||||
|
||||
enum class ThemeEnum
|
||||
{
|
||||
DEFAULT,
|
||||
|
@ -28,6 +28,7 @@ void caf::AppEnum<RiaEclipseFileNameTools::EclipseFileType>::setUp()
|
||||
addItem( RiaEclipseFileNameTools::EclipseFileType::ECLIPSE_DATA, "DATA", "Data Deck" );
|
||||
addItem( RiaEclipseFileNameTools::EclipseFileType::ECLIPSE_GRID, "GRID", "Grid" );
|
||||
addItem( RiaEclipseFileNameTools::EclipseFileType::ECLIPSE_EGRID, "EGRID", "Grid" );
|
||||
addItem( RiaEclipseFileNameTools::EclipseFileType::ECLIPSE_INIT, "INIT", "Init file" );
|
||||
addItem( RiaEclipseFileNameTools::EclipseFileType::ECLIPSE_UNRST, "UNRST", "Unified Restart" );
|
||||
addItem( RiaEclipseFileNameTools::EclipseFileType::ECLIPSE_SMSPEC, "SMSPEC", "Summary Specification" );
|
||||
addItem( RiaEclipseFileNameTools::EclipseFileType::ECLIPSE_UNSMRY, "UNSMR", "Summary Vectors" );
|
||||
|
@ -35,6 +35,7 @@ public:
|
||||
ECLIPSE_DATA,
|
||||
ECLIPSE_GRID,
|
||||
ECLIPSE_EGRID,
|
||||
ECLIPSE_INIT,
|
||||
ECLIPSE_UNRST,
|
||||
ECLIPSE_SMSPEC,
|
||||
ECLIPSE_UNSMRY,
|
||||
|
@ -192,6 +192,8 @@ RiaPreferences::RiaPreferences()
|
||||
|
||||
CAF_PDM_InitField( &csvTextExportFieldSeparator, "csvTextExportFieldSeparator", QString( "," ), "CSV Text Export Field Separator" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_gridModelReader, "gridModelReader", "Grid Model Reader" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_readerSettings, "readerSettings", "Reader Settings" );
|
||||
m_readerSettings = new RifReaderSettings;
|
||||
CAF_PDM_InitFieldNoDefault( &m_dateFormat, "dateFormat", "Date Format" );
|
||||
@ -357,6 +359,8 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering&
|
||||
}
|
||||
else if ( uiConfigName == RiaPreferences::tabNameGrid() )
|
||||
{
|
||||
uiOrdering.add( &m_gridModelReader );
|
||||
|
||||
caf::PdmUiGroup* newCaseBehaviourGroup = uiOrdering.addNewGroup( "Behavior When Loading Data" );
|
||||
newCaseBehaviourGroup->add( &autocomputeDepthRelatedProperties );
|
||||
newCaseBehaviourGroup->add( &loadAndShowSoil );
|
||||
@ -629,6 +633,14 @@ const RifReaderSettings* RiaPreferences::readerSettings() const
|
||||
return m_readerSettings;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::GridModelReader RiaPreferences::gridModelReader() const
|
||||
{
|
||||
return m_gridModelReader();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
using FontSizeEnum = RiaFontCache::FontSizeEnum;
|
||||
using PageSizeEnum = caf::AppEnum<QPageSize::PageSizeId>;
|
||||
using PageOrientationEnum = caf::AppEnum<QPageLayout::Orientation>;
|
||||
using GridModelEnum = caf::AppEnum<RiaDefines::GridModelReader>;
|
||||
|
||||
bool enableFaultsByDefault() const;
|
||||
|
||||
@ -66,7 +67,8 @@ public:
|
||||
|
||||
QStringList tabNames();
|
||||
|
||||
const RifReaderSettings* readerSettings() const;
|
||||
const RifReaderSettings* readerSettings() const;
|
||||
RiaDefines::GridModelReader gridModelReader() const;
|
||||
|
||||
bool useUndoRedo() const;
|
||||
|
||||
@ -165,6 +167,7 @@ private:
|
||||
static double defaultMarginSize( QPageSize::PageSizeId pageSizeId );
|
||||
|
||||
private:
|
||||
caf::PdmField<GridModelEnum> m_gridModelReader;
|
||||
caf::PdmChildField<RifReaderSettings*> m_readerSettings;
|
||||
|
||||
caf::PdmField<QString> m_dateFormat;
|
||||
|
@ -202,7 +202,7 @@ list(APPEND RI_PRIVATE_INCLUDES ${RESINSIGHT_OPENVDS_API_DIR}/include)
|
||||
# Configure include directories if opm-common.lib is downloaded and linked
|
||||
# without building from source
|
||||
#
|
||||
if(NOT BUILD_FROM_SOURCE)
|
||||
if(NOT RESINSIGHT_BUILD_LIBS_FROM_SOURCE)
|
||||
list(APPEND RI_PUBLIC_INCLUDES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/custom-opm-common/opm-common
|
||||
)
|
||||
|
@ -85,6 +85,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifRevealSummaryCsvReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSectionSummaryReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanCsvSummaryReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifReaderOpmCommon.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@ -171,6 +172,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSummaryReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSectionSummaryReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanCsvSummaryReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifReaderOpmCommon.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
@ -22,9 +22,17 @@
|
||||
|
||||
#include "RiaQDateTimeTools.h"
|
||||
#include "RiaStringEncodingTools.h"
|
||||
|
||||
#include "RifEclipseRestartFilesetAccess.h"
|
||||
#include "RifEclipseUnifiedRestartFileAccess.h"
|
||||
|
||||
#include "RigActiveCellInfo.h"
|
||||
#include "RigCaseCellResultsData.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseResultAddress.h"
|
||||
#include "RigEclipseResultInfo.h"
|
||||
#include "RigMainGrid.h"
|
||||
|
||||
#include "ert/ecl/ecl_file.h"
|
||||
#include "ert/ecl/ecl_grid.h"
|
||||
#include "ert/ecl/ecl_kw_magic.h"
|
||||
@ -65,6 +73,54 @@ std::vector<RifKeywordValueCount> RifEclipseOutputFileTools::keywordValueCounts(
|
||||
return reportstepMetaData.keywordValueCounts();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifEclipseOutputFileTools::createResultEntries( const std::vector<RifKeywordValueCount>& fileKeywordInfo,
|
||||
const std::vector<RigEclipseTimeStepInfo>& timeStepInfo,
|
||||
RiaDefines::ResultCatType resultCategory,
|
||||
RigEclipseCaseData* eclipseCaseData )
|
||||
{
|
||||
if ( !eclipseCaseData ) return;
|
||||
|
||||
RigCaseCellResultsData* matrixModelResults = eclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
||||
RigCaseCellResultsData* fractureModelResults = eclipseCaseData->results( RiaDefines::PorosityModelType::FRACTURE_MODEL );
|
||||
|
||||
{
|
||||
auto validKeywords = validKeywordsForPorosityModel( fileKeywordInfo,
|
||||
eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ),
|
||||
eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL ),
|
||||
RiaDefines::PorosityModelType::MATRIX_MODEL,
|
||||
timeStepInfo.size() );
|
||||
|
||||
for ( const auto& keywordData : validKeywords )
|
||||
{
|
||||
RigEclipseResultAddress resAddr( resultCategory,
|
||||
RifKeywordValueCount::mapType( keywordData.dataType() ),
|
||||
QString::fromStdString( keywordData.keyword() ) );
|
||||
matrixModelResults->createResultEntry( resAddr, false );
|
||||
matrixModelResults->setTimeStepInfos( resAddr, timeStepInfo );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto validKeywords = validKeywordsForPorosityModel( fileKeywordInfo,
|
||||
eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ),
|
||||
eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL ),
|
||||
RiaDefines::PorosityModelType::FRACTURE_MODEL,
|
||||
timeStepInfo.size() );
|
||||
|
||||
for ( const auto& keywordData : validKeywords )
|
||||
{
|
||||
RigEclipseResultAddress resAddr( resultCategory,
|
||||
RifKeywordValueCount::mapType( keywordData.dataType() ),
|
||||
QString::fromStdString( keywordData.keyword() ) );
|
||||
fractureModelResults->createResultEntry( resAddr, false );
|
||||
fractureModelResults->setTimeStepInfos( resAddr, timeStepInfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -593,6 +649,73 @@ FILE* RifEclipseOutputFileTools::fopen( const QString& filePath, const QString&
|
||||
return filePtr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifEclipseOutputFileTools::assignActiveCellData( std::vector<std::vector<int>>& actnumValuesPerGrid, RigEclipseCaseData* eclipseCaseData )
|
||||
{
|
||||
size_t reservoirCellCount = 0;
|
||||
for ( const auto& actnumValues : actnumValuesPerGrid )
|
||||
{
|
||||
reservoirCellCount += actnumValues.size();
|
||||
}
|
||||
|
||||
// Check if number of cells is matching
|
||||
if ( eclipseCaseData->mainGrid()->globalCellArray().size() != reservoirCellCount )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RigActiveCellInfo* activeCellInfo = eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
||||
RigActiveCellInfo* fractureActiveCellInfo = eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL );
|
||||
|
||||
activeCellInfo->setReservoirCellCount( reservoirCellCount );
|
||||
fractureActiveCellInfo->setReservoirCellCount( reservoirCellCount );
|
||||
activeCellInfo->setGridCount( actnumValuesPerGrid.size() );
|
||||
fractureActiveCellInfo->setGridCount( actnumValuesPerGrid.size() );
|
||||
|
||||
size_t cellIdx = 0;
|
||||
size_t globalActiveMatrixIndex = 0;
|
||||
size_t globalActiveFractureIndex = 0;
|
||||
|
||||
const int matrixActive = 1;
|
||||
const int fractureActive = 2;
|
||||
const int matrixAndFractureActive = 3;
|
||||
|
||||
for ( size_t gridIndex = 0; gridIndex < actnumValuesPerGrid.size(); gridIndex++ )
|
||||
{
|
||||
size_t activeMatrixIndex = 0;
|
||||
size_t activeFractureIndex = 0;
|
||||
|
||||
std::vector<int>& actnumValues = actnumValuesPerGrid[gridIndex];
|
||||
|
||||
for ( int actnumValue : actnumValues )
|
||||
{
|
||||
if ( actnumValue == matrixActive || actnumValue == matrixAndFractureActive )
|
||||
{
|
||||
activeCellInfo->setCellResultIndex( cellIdx, globalActiveMatrixIndex++ );
|
||||
activeMatrixIndex++;
|
||||
}
|
||||
|
||||
if ( actnumValue == fractureActive || actnumValue == matrixAndFractureActive )
|
||||
{
|
||||
fractureActiveCellInfo->setCellResultIndex( cellIdx, globalActiveFractureIndex++ );
|
||||
activeFractureIndex++;
|
||||
}
|
||||
|
||||
cellIdx++;
|
||||
}
|
||||
|
||||
activeCellInfo->setGridActiveCellCounts( gridIndex, activeMatrixIndex );
|
||||
fractureActiveCellInfo->setGridActiveCellCounts( gridIndex, activeFractureIndex );
|
||||
}
|
||||
|
||||
activeCellInfo->computeDerivedData();
|
||||
fractureActiveCellInfo->computeDerivedData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -664,3 +787,100 @@ RifRestartReportKeywords RifEclipseOutputFileTools::createReportStepsMetaData( c
|
||||
|
||||
return reportSteps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RifKeywordValueCount>
|
||||
RifEclipseOutputFileTools::validKeywordsForPorosityModel( const std::vector<RifKeywordValueCount>& keywordItemCounts,
|
||||
const RigActiveCellInfo* matrixActiveCellInfo,
|
||||
const RigActiveCellInfo* fractureActiveCellInfo,
|
||||
RiaDefines::PorosityModelType porosityModel,
|
||||
size_t timeStepCount )
|
||||
{
|
||||
if ( !matrixActiveCellInfo ) return {};
|
||||
|
||||
if ( porosityModel == RiaDefines::PorosityModelType::FRACTURE_MODEL && ( fractureActiveCellInfo->reservoirActiveCellCount() == 0 ) )
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<RifKeywordValueCount> keywordsWithCorrectNumberOfDataItems;
|
||||
|
||||
for ( const auto& keywordValueCount : keywordItemCounts )
|
||||
{
|
||||
QString keyword = QString::fromStdString( keywordValueCount.keyword() );
|
||||
size_t valueCount = keywordValueCount.valueCount();
|
||||
|
||||
bool validKeyword = false;
|
||||
|
||||
size_t timeStepsAllCellsRest = valueCount % matrixActiveCellInfo->reservoirCellCount();
|
||||
if ( timeStepsAllCellsRest == 0 && valueCount <= timeStepCount * matrixActiveCellInfo->reservoirCellCount() )
|
||||
{
|
||||
// Found result for all cells for N time steps, usually a static dataset for one time step
|
||||
validKeyword = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t timeStepsMatrixRest = valueCount % matrixActiveCellInfo->reservoirActiveCellCount();
|
||||
|
||||
size_t timeStepsFractureRest = 0;
|
||||
if ( fractureActiveCellInfo->reservoirActiveCellCount() > 0 )
|
||||
{
|
||||
timeStepsFractureRest = valueCount % fractureActiveCellInfo->reservoirActiveCellCount();
|
||||
}
|
||||
|
||||
size_t sumFractureMatrixActiveCellCount = matrixActiveCellInfo->reservoirActiveCellCount() +
|
||||
fractureActiveCellInfo->reservoirActiveCellCount();
|
||||
size_t timeStepsMatrixAndFractureRest = valueCount % sumFractureMatrixActiveCellCount;
|
||||
|
||||
if ( porosityModel == RiaDefines::PorosityModelType::MATRIX_MODEL && timeStepsMatrixRest == 0 )
|
||||
{
|
||||
if ( valueCount <=
|
||||
timeStepCount * std::max( matrixActiveCellInfo->reservoirActiveCellCount(), sumFractureMatrixActiveCellCount ) )
|
||||
{
|
||||
validKeyword = true;
|
||||
}
|
||||
}
|
||||
else if ( porosityModel == RiaDefines::PorosityModelType::FRACTURE_MODEL &&
|
||||
fractureActiveCellInfo->reservoirActiveCellCount() > 0 && timeStepsFractureRest == 0 )
|
||||
{
|
||||
if ( valueCount <=
|
||||
timeStepCount * std::max( fractureActiveCellInfo->reservoirActiveCellCount(), sumFractureMatrixActiveCellCount ) )
|
||||
{
|
||||
validKeyword = true;
|
||||
}
|
||||
}
|
||||
else if ( timeStepsMatrixAndFractureRest == 0 )
|
||||
{
|
||||
if ( valueCount <= timeStepCount * sumFractureMatrixActiveCellCount )
|
||||
{
|
||||
validKeyword = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for INIT values that has only values for main grid active cells
|
||||
if ( !validKeyword )
|
||||
{
|
||||
if ( timeStepCount == 1 )
|
||||
{
|
||||
size_t mainGridMatrixActiveCellCount = matrixActiveCellInfo->gridActiveCellCounts( 0 );
|
||||
size_t mainGridFractureActiveCellCount = fractureActiveCellInfo->gridActiveCellCounts( 0 );
|
||||
|
||||
if ( valueCount == mainGridMatrixActiveCellCount || valueCount == mainGridFractureActiveCellCount ||
|
||||
valueCount == mainGridMatrixActiveCellCount + mainGridFractureActiveCellCount )
|
||||
{
|
||||
validKeyword = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( validKeyword )
|
||||
{
|
||||
keywordsWithCorrectNumberOfDataItems.push_back( keywordValueCount );
|
||||
}
|
||||
}
|
||||
|
||||
return keywordsWithCorrectNumberOfDataItems;
|
||||
}
|
||||
|
@ -35,6 +35,8 @@
|
||||
using ecl_file_type = struct ecl_file_struct;
|
||||
|
||||
class RifEclipseRestartDataAccess;
|
||||
class RigEclipseTimeStepInfo;
|
||||
class RigActiveCellInfo;
|
||||
class QByteArray;
|
||||
|
||||
//==================================================================================================
|
||||
@ -50,6 +52,11 @@ public:
|
||||
|
||||
static std::vector<RifKeywordValueCount> keywordValueCounts( const std::vector<ecl_file_type*>& ecl_files );
|
||||
|
||||
static void createResultEntries( const std::vector<RifKeywordValueCount>& fileKeywordInfo,
|
||||
const std::vector<RigEclipseTimeStepInfo>& timeStepInfo,
|
||||
RiaDefines::ResultCatType resultCategory,
|
||||
RigEclipseCaseData* eclipseCaseData );
|
||||
|
||||
static bool keywordData( const ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector<double>* values );
|
||||
static bool keywordData( const ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector<int>* values );
|
||||
|
||||
@ -85,6 +92,13 @@ public:
|
||||
|
||||
static FILE* fopen( const QString& filePath, const QString& mode );
|
||||
|
||||
static bool assignActiveCellData( std::vector<std::vector<int>>& actnumValuesPerGrid, RigEclipseCaseData* eclipseCaseData );
|
||||
|
||||
private:
|
||||
static RifRestartReportKeywords createReportStepsMetaData( const std::vector<ecl_file_type*>& ecl_files );
|
||||
static RifRestartReportKeywords createReportStepsMetaData( const std::vector<ecl_file_type*>& ecl_files );
|
||||
static std::vector<RifKeywordValueCount> validKeywordsForPorosityModel( const std::vector<RifKeywordValueCount>& keywordItemCounts,
|
||||
const RigActiveCellInfo* activeCellInfo,
|
||||
const RigActiveCellInfo* fractureActiveCellInfo,
|
||||
RiaDefines::PorosityModelType matrixOrFracture,
|
||||
size_t timeStepCount );
|
||||
};
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#include "RifReaderEclipseOutput.h"
|
||||
|
||||
#include "RigActiveCellInfo.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigMainGrid.h"
|
||||
|
||||
#include "cvfGeometryTools.h"
|
||||
@ -98,6 +100,61 @@ void RifOpmGridTools::importCoordinatesForRadialGrid( const std::string& gridFil
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RifOpmGridTools::cellCount( const std::string& gridFilePath )
|
||||
{
|
||||
Opm::EclIO::EGrid opmGrid( gridFilePath );
|
||||
|
||||
return opmGrid.totalNumberOfCells();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifOpmGridTools::importGrid( const std::string& gridFilePath, RigMainGrid* mainGrid, RigEclipseCaseData* caseData )
|
||||
{
|
||||
Opm::EclIO::EGrid opmGrid( gridFilePath );
|
||||
|
||||
auto dims = opmGrid.dimension();
|
||||
mainGrid->setGridPointDimensions( cvf::Vec3st( dims[0] + 1, dims[1] + 1, dims[2] + 1 ) );
|
||||
|
||||
RigCell defaultCell;
|
||||
defaultCell.setHostGrid( mainGrid );
|
||||
auto cellCount = opmGrid.totalNumberOfCells();
|
||||
mainGrid->globalCellArray().resize( cellCount, defaultCell );
|
||||
mainGrid->nodes().resize( 8 * cellCount );
|
||||
|
||||
transferCoordinatesCartesian( opmGrid, opmGrid, mainGrid, mainGrid, caseData );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<std::vector<int>> RifOpmGridTools::activeCellsFromActnumKeyword( Opm::EclIO::EGrid& grid )
|
||||
{
|
||||
auto arrayNames = grid.arrayNames();
|
||||
int actnumArrayIndex = -1;
|
||||
|
||||
for ( size_t i = 0; i < arrayNames.size(); i++ )
|
||||
{
|
||||
if ( arrayNames[i] == "ACTNUM" )
|
||||
{
|
||||
actnumArrayIndex = static_cast<int>( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( actnumArrayIndex < 0 ) return {};
|
||||
|
||||
auto actnumMainGrid = grid.get<int>( actnumArrayIndex );
|
||||
|
||||
return { actnumMainGrid };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// A radial grid is defined by a center point and a set of cylindrical coordinates. The coordinates at the
|
||||
@ -251,6 +308,79 @@ void RifOpmGridTools::transferCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifOpmGridTools::transferCoordinatesCartesian( Opm::EclIO::EGrid& opmMainGrid,
|
||||
Opm::EclIO::EGrid& opmGrid,
|
||||
RigMainGrid* riMainGrid,
|
||||
RigGridBase* riGrid,
|
||||
RigEclipseCaseData* caseData )
|
||||
{
|
||||
// Prefix OPM structures with _opm_and ResInsight structures with _ri_
|
||||
|
||||
auto& riNodes = riMainGrid->nodes();
|
||||
|
||||
opmGrid.loadData();
|
||||
opmGrid.load_grid_data();
|
||||
|
||||
auto riActiveCells = caseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
||||
auto riActiveCellsFrac = caseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL );
|
||||
riActiveCellsFrac->setGridCount( 1 );
|
||||
riActiveCellsFrac->setGridActiveCellCounts( 0, 0 );
|
||||
|
||||
riActiveCells->setReservoirCellCount( riMainGrid->cellCount() );
|
||||
|
||||
// same mapping as libecl
|
||||
const size_t cellMappingECLRi[8] = { 0, 1, 3, 2, 4, 5, 7, 6 };
|
||||
|
||||
#pragma omp parallel for
|
||||
for ( int opmCellIndex = 0; opmCellIndex < static_cast<int>( riMainGrid->cellCount() ); opmCellIndex++ )
|
||||
{
|
||||
auto opmIJK = opmGrid.ijk_from_global_index( opmCellIndex );
|
||||
|
||||
auto riReservoirIndex = riGrid->cellIndexFromIJK( opmIJK[0], opmIJK[1], opmIJK[2] );
|
||||
RigCell& cell = riMainGrid->globalCellArray()[riReservoirIndex];
|
||||
cell.setGridLocalCellIndex( riReservoirIndex );
|
||||
|
||||
std::array<double, 8> opmX{};
|
||||
std::array<double, 8> opmY{};
|
||||
std::array<double, 8> opmZ{};
|
||||
opmGrid.getCellCorners( opmCellIndex, opmX, opmY, opmZ );
|
||||
|
||||
// Each cell has 8 nodes, use reservoir cell index and multiply to find first node index for cell
|
||||
auto riNodeStartIndex = riReservoirIndex * 8;
|
||||
|
||||
for ( size_t opmNodeIndex = 0; opmNodeIndex < 8; opmNodeIndex++ )
|
||||
{
|
||||
auto riCornerIndex = cellMappingECLRi[opmNodeIndex];
|
||||
size_t riNodeIndex = riNodeStartIndex + riCornerIndex;
|
||||
|
||||
auto& riNode = riNodes[riNodeIndex];
|
||||
riNode.x() = opmX[opmNodeIndex];
|
||||
riNode.y() = opmY[opmNodeIndex];
|
||||
riNode.z() = -opmZ[opmNodeIndex];
|
||||
|
||||
cell.cornerIndices()[riCornerIndex] = riNodeIndex;
|
||||
}
|
||||
|
||||
if ( riActiveCells )
|
||||
{
|
||||
auto activeIndex = opmGrid.active_index( opmIJK[0], opmIJK[1], opmIJK[2] );
|
||||
if ( activeIndex > -1 )
|
||||
{
|
||||
riActiveCells->setCellResultIndex( riReservoirIndex, activeIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
riActiveCells->setGridCount( 1 );
|
||||
riActiveCells->setGridActiveCellCounts( 0, opmGrid.activeCells() );
|
||||
riActiveCells->computeDerivedData();
|
||||
|
||||
riMainGrid->initAllSubGridsParentGridPointer();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -34,6 +34,7 @@ namespace EclIO
|
||||
|
||||
class RigMainGrid;
|
||||
class RigGridBase;
|
||||
class RigEclipseCaseData;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
@ -44,8 +45,18 @@ public:
|
||||
// If the grid is radial, the coordinates are imported and adjusted to fit the host cells
|
||||
static void importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* mainGrid );
|
||||
|
||||
static size_t cellCount( const std::string& gridFilePath );
|
||||
static bool importGrid( const std::string& gridFilePath, RigMainGrid* mainGrid, RigEclipseCaseData* caseData );
|
||||
|
||||
static std::vector<std::vector<int>> activeCellsFromActnumKeyword( Opm::EclIO::EGrid& grid );
|
||||
|
||||
private:
|
||||
static void transferCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigMainGrid* riMainGrid, RigGridBase* riGrid );
|
||||
static void transferCoordinatesCartesian( Opm::EclIO::EGrid& opmMainGrid,
|
||||
Opm::EclIO::EGrid& opmGrid,
|
||||
RigMainGrid* riMainGrid,
|
||||
RigGridBase* riGrid,
|
||||
RigEclipseCaseData* caseData );
|
||||
|
||||
static std::map<int, std::pair<double, double>>
|
||||
computeXyCenterForTopOfCells( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigGridBase* riGrid );
|
||||
|
@ -837,62 +837,7 @@ bool RifReaderEclipseOutput::readActiveCellInfo()
|
||||
}
|
||||
}
|
||||
|
||||
size_t reservoirCellCount = 0;
|
||||
for ( const auto& actnumValues : actnumValuesPerGrid )
|
||||
{
|
||||
reservoirCellCount += actnumValues.size();
|
||||
}
|
||||
|
||||
// Check if number of cells is matching
|
||||
if ( m_eclipseCase->mainGrid()->globalCellArray().size() != reservoirCellCount )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
||||
RigActiveCellInfo* fractureActiveCellInfo = m_eclipseCase->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL );
|
||||
|
||||
activeCellInfo->setReservoirCellCount( reservoirCellCount );
|
||||
fractureActiveCellInfo->setReservoirCellCount( reservoirCellCount );
|
||||
activeCellInfo->setGridCount( actnumValuesPerGrid.size() );
|
||||
fractureActiveCellInfo->setGridCount( actnumValuesPerGrid.size() );
|
||||
|
||||
size_t cellIdx = 0;
|
||||
size_t globalActiveMatrixIndex = 0;
|
||||
size_t globalActiveFractureIndex = 0;
|
||||
|
||||
for ( size_t gridIndex = 0; gridIndex < actnumValuesPerGrid.size(); gridIndex++ )
|
||||
{
|
||||
size_t activeMatrixIndex = 0;
|
||||
size_t activeFractureIndex = 0;
|
||||
|
||||
std::vector<int>& actnumValues = actnumValuesPerGrid[gridIndex];
|
||||
|
||||
for ( int actnumValue : actnumValues )
|
||||
{
|
||||
if ( actnumValue == 1 || actnumValue == 3 )
|
||||
{
|
||||
activeCellInfo->setCellResultIndex( cellIdx, globalActiveMatrixIndex++ );
|
||||
activeMatrixIndex++;
|
||||
}
|
||||
|
||||
if ( actnumValue == 2 || actnumValue == 3 )
|
||||
{
|
||||
fractureActiveCellInfo->setCellResultIndex( cellIdx, globalActiveFractureIndex++ );
|
||||
activeFractureIndex++;
|
||||
}
|
||||
|
||||
cellIdx++;
|
||||
}
|
||||
|
||||
activeCellInfo->setGridActiveCellCounts( gridIndex, activeMatrixIndex );
|
||||
fractureActiveCellInfo->setGridActiveCellCounts( gridIndex, activeFractureIndex );
|
||||
}
|
||||
|
||||
activeCellInfo->computeDerivedData();
|
||||
fractureActiveCellInfo->computeDerivedData();
|
||||
|
||||
return true;
|
||||
return RifEclipseOutputFileTools::assignActiveCellData( actnumValuesPerGrid, m_eclipseCase );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -2109,7 +2054,7 @@ std::vector<RifKeywordValueCount>
|
||||
const RigActiveCellInfo* matrixActiveCellInfo,
|
||||
const RigActiveCellInfo* fractureActiveCellInfo,
|
||||
RiaDefines::PorosityModelType porosityModel,
|
||||
size_t timeStepCount ) const
|
||||
size_t timeStepCount )
|
||||
{
|
||||
CVF_ASSERT( matrixActiveCellInfo );
|
||||
|
||||
|
@ -90,6 +90,7 @@ public:
|
||||
|
||||
private:
|
||||
bool readActiveCellInfo();
|
||||
|
||||
void buildMetaData( ecl_grid_type* grid );
|
||||
void readWellCells( const ecl_grid_type* mainEclGrid, bool importCompleteMswData );
|
||||
|
||||
@ -114,11 +115,11 @@ private:
|
||||
|
||||
void ensureDynamicResultAccessIsPresent();
|
||||
|
||||
std::vector<RifKeywordValueCount> validKeywordsForPorosityModel( const std::vector<RifKeywordValueCount>& keywordItemCounts,
|
||||
const RigActiveCellInfo* activeCellInfo,
|
||||
const RigActiveCellInfo* fractureActiveCellInfo,
|
||||
RiaDefines::PorosityModelType matrixOrFracture,
|
||||
size_t timeStepCount ) const;
|
||||
static std::vector<RifKeywordValueCount> validKeywordsForPorosityModel( const std::vector<RifKeywordValueCount>& keywordItemCounts,
|
||||
const RigActiveCellInfo* activeCellInfo,
|
||||
const RigActiveCellInfo* fractureActiveCellInfo,
|
||||
RiaDefines::PorosityModelType matrixOrFracture,
|
||||
size_t timeStepCount );
|
||||
|
||||
std::vector<RigEclipseTimeStepInfo> createFilteredTimeStepInfos();
|
||||
|
||||
|
470
ApplicationLibCode/FileInterface/RifReaderOpmCommon.cpp
Normal file
470
ApplicationLibCode/FileInterface/RifReaderOpmCommon.cpp
Normal file
@ -0,0 +1,470 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2023- Equinor 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 "RifReaderOpmCommon.h"
|
||||
|
||||
#include "RiaEclipseFileNameTools.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaQDateTimeTools.h"
|
||||
|
||||
#include "RifEclipseOutputFileTools.h"
|
||||
#include "RifOpmGridTools.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseResultInfo.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigSimWellData.h"
|
||||
#include "RigWellResultFrame.h"
|
||||
|
||||
#include "opm/input/eclipse/Deck/Deck.hpp"
|
||||
#include "opm/input/eclipse/EclipseState/Runspec.hpp"
|
||||
#include "opm/input/eclipse/Parser/Parser.hpp"
|
||||
#include "opm/input/eclipse/Schedule/Well/Connection.hpp"
|
||||
#include "opm/input/eclipse/Schedule/Well/Well.hpp"
|
||||
#include "opm/io/eclipse/EInit.hpp"
|
||||
#include "opm/io/eclipse/ERst.hpp"
|
||||
#include "opm/io/eclipse/RestartFileView.hpp"
|
||||
#include "opm/io/eclipse/rst/state.hpp"
|
||||
#include "opm/output/eclipse/VectorItems/group.hpp"
|
||||
#include "opm/output/eclipse/VectorItems/well.hpp"
|
||||
|
||||
using namespace Opm;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifReaderOpmCommon::RifReaderOpmCommon()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifReaderOpmCommon::~RifReaderOpmCommon()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifReaderOpmCommon::open( const QString& fileName, RigEclipseCaseData* eclipseCase )
|
||||
{
|
||||
QStringList fileSet;
|
||||
if ( !RifEclipseOutputFileTools::findSiblingFilesWithSameBaseName( fileName, &fileSet ) ) return false;
|
||||
|
||||
try
|
||||
{
|
||||
m_gridFileName = fileName.toStdString();
|
||||
|
||||
if ( !RifOpmGridTools::importGrid( m_gridFileName, eclipseCase->mainGrid(), eclipseCase ) )
|
||||
{
|
||||
RiaLogging::error( "Failed to open grid file " + fileName );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
buildMetaData( eclipseCase );
|
||||
|
||||
return true;
|
||||
}
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
auto description = e.what();
|
||||
RiaLogging::error( description );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifReaderOpmCommon::staticResult( const QString& result, RiaDefines::PorosityModelType matrixOrFracture, std::vector<double>* values )
|
||||
{
|
||||
if ( m_initFile )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto resultName = result.toStdString();
|
||||
|
||||
auto resultEntries = m_initFile->getList();
|
||||
for ( const auto& entry : resultEntries )
|
||||
{
|
||||
const auto& [keyword, kwType, size] = entry;
|
||||
if ( keyword == resultName )
|
||||
{
|
||||
if ( kwType == EclIO::eclArrType::REAL )
|
||||
{
|
||||
auto fileValues = m_initFile->getInitData<float>( resultName );
|
||||
values->insert( values->end(), fileValues.begin(), fileValues.end() );
|
||||
}
|
||||
else if ( kwType == EclIO::eclArrType::DOUB )
|
||||
{
|
||||
auto fileValues = m_initFile->getInitData<double>( resultName );
|
||||
values->insert( values->end(), fileValues.begin(), fileValues.end() );
|
||||
}
|
||||
else if ( kwType == EclIO::eclArrType::INTE )
|
||||
{
|
||||
auto fileValues = m_initFile->getInitData<int>( resultName );
|
||||
values->insert( values->end(), fileValues.begin(), fileValues.end() );
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
RiaLogging::error( e.what() );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifReaderOpmCommon::dynamicResult( const QString& result,
|
||||
RiaDefines::PorosityModelType matrixOrFracture,
|
||||
size_t stepIndex,
|
||||
std::vector<double>* values )
|
||||
{
|
||||
if ( m_restartFile )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto resultName = result.toStdString();
|
||||
|
||||
auto stepNumbers = m_restartFile->listOfReportStepNumbers();
|
||||
auto stepNumber = stepNumbers[stepIndex];
|
||||
|
||||
auto resultEntries = m_restartFile->getList();
|
||||
for ( const auto& entry : resultEntries )
|
||||
{
|
||||
const auto& [keyword, kwType, size] = entry;
|
||||
if ( keyword == resultName )
|
||||
{
|
||||
if ( kwType == EclIO::eclArrType::DOUB )
|
||||
{
|
||||
auto fileValues = m_restartFile->getRestartData<double>( resultName, stepNumber );
|
||||
values->insert( values->end(), fileValues.begin(), fileValues.end() );
|
||||
}
|
||||
if ( kwType == EclIO::eclArrType::REAL )
|
||||
{
|
||||
auto fileValues = m_restartFile->getRestartData<float>( resultName, stepNumber );
|
||||
values->insert( values->end(), fileValues.begin(), fileValues.end() );
|
||||
}
|
||||
else if ( kwType == EclIO::eclArrType::INTE )
|
||||
{
|
||||
auto fileValues = m_restartFile->getRestartData<int>( resultName, stepNumber );
|
||||
values->insert( values->end(), fileValues.begin(), fileValues.end() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
RiaLogging::error( e.what() );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RifKeywordValueCount> createKeywordInfo( std::vector<EclIO::EclFile::EclEntry> entries )
|
||||
{
|
||||
std::vector<RifKeywordValueCount> fileKeywordInfo;
|
||||
|
||||
for ( const auto& entry : entries )
|
||||
{
|
||||
const auto& [keyword, kwType, size] = entry;
|
||||
|
||||
RifKeywordValueCount::KeywordDataType dataType = RifKeywordValueCount::KeywordDataType::UNKNOWN;
|
||||
|
||||
if ( kwType == EclIO::eclArrType::INTE )
|
||||
dataType = RifKeywordValueCount::KeywordDataType::INTEGER;
|
||||
else if ( kwType == EclIO::eclArrType::REAL )
|
||||
dataType = RifKeywordValueCount::KeywordDataType::FLOAT;
|
||||
else if ( kwType == EclIO::eclArrType::DOUB )
|
||||
dataType = RifKeywordValueCount::KeywordDataType::DOUBLE;
|
||||
|
||||
if ( dataType != RifKeywordValueCount::KeywordDataType::UNKNOWN )
|
||||
{
|
||||
fileKeywordInfo.emplace_back( RifKeywordValueCount( keyword, static_cast<size_t>( size ), dataType ) );
|
||||
}
|
||||
}
|
||||
|
||||
return fileKeywordInfo;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifReaderOpmCommon::buildMetaData( RigEclipseCaseData* eclipseCase )
|
||||
{
|
||||
auto getFileNameForType = []( RiaEclipseFileNameTools::EclipseFileType fileType, const QString& candidate ) -> std::string
|
||||
{
|
||||
const QString ext = caf::AppEnum<RiaEclipseFileNameTools::EclipseFileType>::text( fileType );
|
||||
if ( candidate.endsWith( ext, Qt::CaseInsensitive ) ) return candidate.toStdString();
|
||||
return {};
|
||||
};
|
||||
|
||||
std::string initFileName;
|
||||
std::string restartFileName;
|
||||
|
||||
QStringList fileSet;
|
||||
RifEclipseOutputFileTools::findSiblingFilesWithSameBaseName( QString::fromStdString( m_gridFileName ), &fileSet );
|
||||
for ( const auto& s : fileSet )
|
||||
{
|
||||
auto initCandidate = getFileNameForType( RiaEclipseFileNameTools::EclipseFileType::ECLIPSE_INIT, s );
|
||||
auto restartCandidate = getFileNameForType( RiaEclipseFileNameTools::EclipseFileType::ECLIPSE_UNRST, s );
|
||||
|
||||
if ( !initCandidate.empty() ) initFileName = initCandidate;
|
||||
if ( !restartCandidate.empty() ) restartFileName = restartCandidate;
|
||||
}
|
||||
|
||||
RigEclipseTimeStepInfo firstTimeStepInfo{ QDateTime(), 0, 0.0 };
|
||||
if ( !restartFileName.empty() )
|
||||
{
|
||||
m_restartFile = std::make_shared<EclIO::ERst>( restartFileName );
|
||||
|
||||
std::vector<EclIO::EclFile::EclEntry> entries;
|
||||
for ( auto reportNumber : m_restartFile->listOfReportStepNumbers() )
|
||||
{
|
||||
auto reportEntries = m_restartFile->listOfRstArrays( reportNumber );
|
||||
entries.insert( entries.end(), reportEntries.begin(), reportEntries.end() );
|
||||
}
|
||||
|
||||
auto timeStepsFromFile = readTimeSteps( m_restartFile );
|
||||
|
||||
std::vector<RigEclipseTimeStepInfo> timeStepInfos;
|
||||
std::vector<QDateTime> dateTimes;
|
||||
for ( const auto& timeStep : timeStepsFromFile )
|
||||
{
|
||||
QDate date( timeStep.year, timeStep.month, timeStep.day );
|
||||
QDateTime dateTime = RiaQDateTimeTools::createDateTime( date );
|
||||
dateTimes.push_back( dateTime );
|
||||
timeStepInfos.emplace_back( dateTime, timeStep.sequenceNumber, 0.0 );
|
||||
}
|
||||
m_timeSteps = dateTimes;
|
||||
|
||||
auto last = std::unique( entries.begin(), entries.end() );
|
||||
entries.erase( last, entries.end() );
|
||||
|
||||
std::vector<RifKeywordValueCount> keywordInfo = createKeywordInfo( entries );
|
||||
|
||||
RifEclipseOutputFileTools::createResultEntries( keywordInfo, timeStepInfos, RiaDefines::ResultCatType::DYNAMIC_NATIVE, eclipseCase );
|
||||
|
||||
firstTimeStepInfo = timeStepInfos.front();
|
||||
|
||||
readWellCells( m_restartFile, eclipseCase, m_timeSteps );
|
||||
}
|
||||
|
||||
if ( !initFileName.empty() )
|
||||
{
|
||||
m_initFile = std::make_unique<EclIO::EInit>( initFileName );
|
||||
|
||||
auto entries = m_initFile->list_arrays();
|
||||
std::vector<RifKeywordValueCount> keywordInfo = createKeywordInfo( entries );
|
||||
|
||||
RifEclipseOutputFileTools::createResultEntries( keywordInfo, { firstTimeStepInfo }, RiaDefines::ResultCatType::STATIC_NATIVE, eclipseCase );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifReaderOpmCommon::readWellCells( std::shared_ptr<EclIO::ERst> restartFile,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const std::vector<QDateTime>& timeSteps )
|
||||
{
|
||||
// It is required to create a deck as the input parameter to runspec. The default() initialization of the runspec keyword does not
|
||||
// initialize the object as expected.
|
||||
|
||||
Deck deck;
|
||||
Runspec runspec( deck );
|
||||
Parser parser( false );
|
||||
|
||||
cvf::Collection<RigSimWellData> wells;
|
||||
|
||||
try
|
||||
{
|
||||
if ( restartFile->numberOfReportSteps() != timeSteps.size() )
|
||||
{
|
||||
RiaLogging::error( "Number of time steps is not matching number of report steps" );
|
||||
return;
|
||||
}
|
||||
|
||||
auto getWellStateAndNames = [&]() -> std::pair<std::vector<RestartIO::RstState>, std::set<std::string>>
|
||||
{
|
||||
std::vector<RestartIO::RstState> states;
|
||||
std::set<std::string> wellNames;
|
||||
|
||||
for ( auto seqNumber : restartFile->listOfReportStepNumbers() )
|
||||
{
|
||||
auto fileView = std::make_shared<EclIO::RestartFileView>( restartFile, seqNumber );
|
||||
|
||||
auto state = RestartIO::RstState::load( fileView, runspec, parser );
|
||||
states.emplace_back( state );
|
||||
|
||||
for ( const auto& w : state.wells )
|
||||
{
|
||||
wellNames.insert( w.name );
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair( states, wellNames );
|
||||
};
|
||||
|
||||
auto [states, wellNames] = getWellStateAndNames();
|
||||
|
||||
for ( const auto& wellName : wellNames )
|
||||
{
|
||||
cvf::ref<RigSimWellData> simWellData = new RigSimWellData;
|
||||
simWellData->setWellName( QString::fromStdString( wellName ) );
|
||||
simWellData->m_wellCellsTimeSteps.resize( timeSteps.size() );
|
||||
|
||||
for ( size_t timeIdx = 0; timeIdx < timeSteps.size(); ++timeIdx )
|
||||
{
|
||||
auto state = states[timeIdx];
|
||||
|
||||
auto it = std::find_if( state.wells.begin(),
|
||||
state.wells.end(),
|
||||
[&wellName]( const RestartIO::RstWell& well ) { return well.name == wellName; } );
|
||||
if ( it == state.wells.end() ) continue;
|
||||
|
||||
RestartIO::RstWell rstWell = *it;
|
||||
|
||||
RigWellResultFrame& wellResFrame = simWellData->m_wellCellsTimeSteps[timeIdx];
|
||||
wellResFrame.setTimestamp( timeSteps[timeIdx] );
|
||||
|
||||
auto wellType = [&rstWell]() -> RiaDefines::WellProductionType
|
||||
{
|
||||
if ( rstWell.wtype.producer() ) return RiaDefines::WellProductionType::PRODUCER;
|
||||
|
||||
if ( rstWell.wtype.injector_type() == InjectorType::WATER ) return RiaDefines::WellProductionType::WATER_INJECTOR;
|
||||
if ( rstWell.wtype.injector_type() == InjectorType::GAS ) return RiaDefines::WellProductionType::GAS_INJECTOR;
|
||||
if ( rstWell.wtype.injector_type() == InjectorType::OIL ) return RiaDefines::WellProductionType::OIL_INJECTOR;
|
||||
|
||||
return RiaDefines::WellProductionType::UNDEFINED_PRODUCTION_TYPE;
|
||||
};
|
||||
|
||||
wellResFrame.setProductionType( wellType() );
|
||||
|
||||
wellResFrame.setIsOpen( rstWell.well_status == RestartIO::Helpers::VectorItems::IWell::Value::Status::Open );
|
||||
|
||||
// Well head
|
||||
RigWellResultPoint wellHead;
|
||||
wellHead.setGridIndex( 0 );
|
||||
auto cellIndex = eclipseCase->mainGrid()->cellIndexFromIJK( rstWell.ij[0], rstWell.ij[1], 0 );
|
||||
wellHead.setGridCellIndex( cellIndex );
|
||||
|
||||
wellResFrame.setWellHead( wellHead );
|
||||
|
||||
// Grid cells
|
||||
if ( !rstWell.connections.empty() )
|
||||
{
|
||||
RigWellResultBranch wellResultBranch;
|
||||
wellResultBranch.setErtBranchId( 0 ); // Normal wells have only one branch
|
||||
|
||||
std::vector<RigWellResultPoint> branchResultPoints = wellResultBranch.branchResultPoints();
|
||||
const size_t existingCellCount = branchResultPoints.size();
|
||||
branchResultPoints.reserve( existingCellCount + rstWell.connections.size() );
|
||||
|
||||
for ( const auto& conn : rstWell.connections )
|
||||
{
|
||||
RigWellResultPoint wellResPoint;
|
||||
wellResPoint.setGridIndex( 0 );
|
||||
auto cellIndex = eclipseCase->mainGrid()->cellIndexFromIJK( conn.ijk[0], conn.ijk[1], conn.ijk[2] );
|
||||
wellResPoint.setGridCellIndex( cellIndex );
|
||||
|
||||
wellResPoint.setIsOpen( conn.state == Connection::State::OPEN );
|
||||
|
||||
// All units for a Connection is given in SI units
|
||||
// Convert back to the original units
|
||||
// See RestartIO::RstConnection::RstConnection
|
||||
auto us = state.unit_system;
|
||||
wellResPoint.setFlowData( us.from_si( UnitSystem::measure::rate, conn.resv_rate ),
|
||||
us.from_si( UnitSystem::measure::liquid_surface_rate, conn.oil_rate ),
|
||||
us.from_si( UnitSystem::measure::gas_surface_rate, conn.gas_rate ),
|
||||
us.from_si( UnitSystem::measure::liquid_surface_rate, conn.water_rate ) );
|
||||
wellResPoint.setConnectionFactor( us.from_si( UnitSystem::measure::transmissibility, conn.cf ) );
|
||||
|
||||
branchResultPoints.push_back( wellResPoint );
|
||||
}
|
||||
wellResultBranch.setBranchResultPoints( branchResultPoints );
|
||||
wellResFrame.addWellResultBranch( wellResultBranch );
|
||||
}
|
||||
}
|
||||
|
||||
simWellData->computeMappingFromResultTimeIndicesToWellTimeIndices( timeSteps );
|
||||
wells.push_back( simWellData.p() );
|
||||
}
|
||||
}
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
std::cout << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
eclipseCase->setSimWellData( wells );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RifReaderOpmCommon::TimeDataFile> RifReaderOpmCommon::readTimeSteps( std::shared_ptr<EclIO::ERst> restartFile )
|
||||
{
|
||||
// It is required to create a deck as the input parameter to runspec. The default() initialization of the runspec keyword does not
|
||||
// initialize the object as expected.
|
||||
|
||||
Deck deck;
|
||||
Runspec runspec( deck );
|
||||
Parser parser( false );
|
||||
|
||||
std::vector<RifReaderOpmCommon::TimeDataFile> reportTimeData;
|
||||
try
|
||||
{
|
||||
for ( auto seqNumber : restartFile->listOfReportStepNumbers() )
|
||||
{
|
||||
auto fileView = std::make_shared<EclIO::RestartFileView>( restartFile, seqNumber );
|
||||
|
||||
auto state = RestartIO::RstState::load( fileView, runspec, parser );
|
||||
auto header = state.header;
|
||||
|
||||
int year = header.year;
|
||||
int month = header.month;
|
||||
int day = header.mday;
|
||||
|
||||
double daySinceSimStart = header.next_timestep1;
|
||||
|
||||
reportTimeData.emplace_back(
|
||||
TimeDataFile{ .sequenceNumber = seqNumber, .year = year, .month = month, .day = day, .simulationTimeFromStart = daySinceSimStart } );
|
||||
}
|
||||
}
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
std::cout << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return reportTimeData;
|
||||
}
|
70
ApplicationLibCode/FileInterface/RifReaderOpmCommon.h
Normal file
70
ApplicationLibCode/FileInterface/RifReaderOpmCommon.h
Normal file
@ -0,0 +1,70 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2023- Equinor 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RifReaderInterface.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Opm::EclIO
|
||||
{
|
||||
class EInit;
|
||||
class ERst;
|
||||
} // namespace Opm::EclIO
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class RifReaderOpmCommon : public RifReaderInterface
|
||||
{
|
||||
public:
|
||||
struct TimeDataFile
|
||||
{
|
||||
int sequenceNumber;
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
double simulationTimeFromStart;
|
||||
};
|
||||
|
||||
RifReaderOpmCommon();
|
||||
~RifReaderOpmCommon() override;
|
||||
|
||||
bool open( const QString& fileName, RigEclipseCaseData* eclipseCase ) override;
|
||||
|
||||
bool staticResult( const QString& result, RiaDefines::PorosityModelType matrixOrFracture, std::vector<double>* values ) override;
|
||||
bool dynamicResult( const QString& result, RiaDefines::PorosityModelType matrixOrFracture, size_t stepIndex, std::vector<double>* values ) override;
|
||||
|
||||
private:
|
||||
void buildMetaData( RigEclipseCaseData* eclipseCase );
|
||||
|
||||
static std::vector<TimeDataFile> readTimeSteps( std::shared_ptr<Opm::EclIO::ERst> restartFile );
|
||||
static void readWellCells( std::shared_ptr<Opm::EclIO::ERst> restartFile,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const std::vector<QDateTime>& timeSteps );
|
||||
|
||||
private:
|
||||
std::string m_gridFileName;
|
||||
|
||||
std::shared_ptr<Opm::EclIO::ERst> m_restartFile;
|
||||
std::shared_ptr<Opm::EclIO::EInit> m_initFile;
|
||||
|
||||
std::vector<QDateTime> m_timeSteps;
|
||||
};
|
@ -34,6 +34,7 @@
|
||||
#include "RifReaderEclipseOutput.h"
|
||||
#include "RifReaderEclipseRft.h"
|
||||
#include "RifReaderMockModel.h"
|
||||
#include "RifReaderOpmCommon.h"
|
||||
#include "RifReaderOpmRft.h"
|
||||
#include "RifReaderSettings.h"
|
||||
|
||||
@ -77,6 +78,14 @@ RimEclipseResultCase::RimEclipseResultCase()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Eclipse Case", ":/Case48x48.png", "", "The Regular Eclipse Results Case" );
|
||||
|
||||
auto defaultReader = RiaPreferences::current()->gridModelReader();
|
||||
CAF_PDM_InitField( &m_gridModelReader, "gridModelReader", caf::AppEnum<RiaDefines::GridModelReader>( defaultReader ), "Grid Model Reader" );
|
||||
if ( !RiaApplication::enableDevelopmentFeatures() )
|
||||
{
|
||||
m_gridModelReader.xmlCapability()->disableIO();
|
||||
m_gridModelReader.uiCapability()->setUiHidden( true );
|
||||
}
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_unitSystem, "UnitSystem", "Unit System" );
|
||||
m_unitSystem.registerGetMethod( RimProject::current(), &RimProject::commonUnitSystemForAllCases );
|
||||
m_unitSystem.uiCapability()->setUiReadOnly( true );
|
||||
@ -86,9 +95,7 @@ RimEclipseResultCase::RimEclipseResultCase()
|
||||
m_flowDiagSolutions.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
|
||||
m_flipXAxis.xmlCapability()->setIOWritable( true );
|
||||
// flipXAxis.uiCapability()->setUiHidden(true);
|
||||
m_flipYAxis.xmlCapability()->setIOWritable( true );
|
||||
// flipYAxis.uiCapability()->setUiHidden(true);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_sourSimFileName, "SourSimFileName", "SourSim File Name" );
|
||||
m_sourSimFileName.uiCapability()->setUiEditorTypeName( caf::PdmUiFilePathEditor::uiEditorTypeName() );
|
||||
@ -133,60 +140,68 @@ bool RimEclipseResultCase::importGridAndResultMetaData( bool showTimeStepFilter
|
||||
return false;
|
||||
}
|
||||
|
||||
cvf::ref<RifReaderEclipseOutput> readerEclipseOutput = new RifReaderEclipseOutput;
|
||||
readerEclipseOutput->setFilenamesWithFaults( filesContainingFaults() );
|
||||
readerEclipseOutput->setReaderSettings( m_readerSettings );
|
||||
|
||||
cvf::ref<RifEclipseRestartDataAccess> restartDataAccess = RifEclipseOutputFileTools::createDynamicResultAccess( gridFileName() );
|
||||
|
||||
if ( m_gridModelReader == RiaDefines::GridModelReader::LIBECL )
|
||||
{
|
||||
std::vector<QDateTime> timeSteps;
|
||||
std::vector<double> daysSinceSimulationStart;
|
||||
auto readerEclipseOutput = new RifReaderEclipseOutput();
|
||||
|
||||
cvf::ref<RifEclipseRestartDataAccess> restartDataAccess = RifEclipseOutputFileTools::createDynamicResultAccess( gridFileName() );
|
||||
|
||||
if ( restartDataAccess.notNull() )
|
||||
{
|
||||
restartDataAccess->timeSteps( &timeSteps, &daysSinceSimulationStart );
|
||||
std::vector<QDateTime> timeSteps;
|
||||
std::vector<double> daysSinceSimulationStart;
|
||||
|
||||
if ( restartDataAccess.notNull() )
|
||||
{
|
||||
restartDataAccess->timeSteps( &timeSteps, &daysSinceSimulationStart );
|
||||
}
|
||||
m_timeStepFilter->setTimeStepsFromFile( timeSteps );
|
||||
}
|
||||
m_timeStepFilter->setTimeStepsFromFile( timeSteps );
|
||||
|
||||
if ( showTimeStepFilter )
|
||||
{
|
||||
caf::PdmUiPropertyViewDialog propertyDialog( nullptr,
|
||||
m_timeStepFilter,
|
||||
"Time Step Filter",
|
||||
"",
|
||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
|
||||
propertyDialog.resize( QSize( 400, 400 ) );
|
||||
|
||||
// Push arrow cursor onto the cursor stack so it takes over from the wait cursor.
|
||||
QApplication::setOverrideCursor( QCursor( Qt::ArrowCursor ) );
|
||||
// Show GUI to select time steps
|
||||
int dialogReturnValue = propertyDialog.exec();
|
||||
// Pop arrow cursor off the cursor stack so that the previous (wait) cursor takes over.
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
if ( dialogReturnValue != QDialog::Accepted )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_timeStepFilter->updateFilteredTimeStepsFromUi();
|
||||
}
|
||||
|
||||
readerEclipseOutput->setFileDataAccess( restartDataAccess.p() );
|
||||
readerEclipseOutput->setTimeStepFilter( m_timeStepFilter->filteredTimeSteps() );
|
||||
|
||||
readerInterface = readerEclipseOutput;
|
||||
}
|
||||
else
|
||||
{
|
||||
readerInterface = new RifReaderOpmCommon;
|
||||
}
|
||||
|
||||
if ( showTimeStepFilter )
|
||||
{
|
||||
caf::PdmUiPropertyViewDialog propertyDialog( nullptr,
|
||||
m_timeStepFilter,
|
||||
"Time Step Filter",
|
||||
"",
|
||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
|
||||
propertyDialog.resize( QSize( 400, 400 ) );
|
||||
|
||||
// Push arrow cursor onto the cursor stack so it takes over from the wait cursor.
|
||||
QApplication::setOverrideCursor( QCursor( Qt::ArrowCursor ) );
|
||||
// Show GUI to select time steps
|
||||
int dialogReturnValue = propertyDialog.exec();
|
||||
// Pop arrow cursor off the cursor stack so that the previous (wait) cursor takes over.
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
if ( dialogReturnValue != QDialog::Accepted )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_timeStepFilter->updateFilteredTimeStepsFromUi();
|
||||
}
|
||||
|
||||
readerEclipseOutput->setFileDataAccess( restartDataAccess.p() );
|
||||
readerEclipseOutput->setTimeStepFilter( m_timeStepFilter->filteredTimeSteps() );
|
||||
readerInterface->setFilenamesWithFaults( filesContainingFaults() );
|
||||
readerInterface->setReaderSettings( m_readerSettings );
|
||||
|
||||
cvf::ref<RigEclipseCaseData> eclipseCase = new RigEclipseCaseData( this );
|
||||
if ( !readerEclipseOutput->open( gridFileName(), eclipseCase.p() ) )
|
||||
if ( !readerInterface->open( gridFileName(), eclipseCase.p() ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
setFilesContainingFaults( readerEclipseOutput->filenamesWithFaults() );
|
||||
setFilesContainingFaults( readerInterface->filenamesWithFaults() );
|
||||
|
||||
setReservoirData( eclipseCase.p() );
|
||||
|
||||
readerInterface = readerEclipseOutput;
|
||||
}
|
||||
|
||||
results( RiaDefines::PorosityModelType::MATRIX_MODEL )->setReaderInterface( readerInterface.p() );
|
||||
@ -581,6 +596,7 @@ bool RimEclipseResultCase::hasSourSimFile()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEclipseResultCase::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_gridModelReader );
|
||||
uiOrdering.add( &m_caseUserDescription );
|
||||
uiOrdering.add( &m_displayNameOption );
|
||||
uiOrdering.add( &m_caseId );
|
||||
|
@ -81,17 +81,16 @@ private:
|
||||
void loadAndUpdateSourSimData();
|
||||
void ensureRftDataIsImported();
|
||||
|
||||
private:
|
||||
cvf::ref<RifReaderInterface> createMockModel( QString modelName );
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
private:
|
||||
cvf::ref<RigFlowDiagSolverInterface> m_flowDagSolverInterface;
|
||||
|
||||
cvf::ref<RifReaderEclipseRft> m_readerEclipseRft;
|
||||
cvf::ref<RifReaderOpmRft> m_readerOpmRft;
|
||||
|
||||
// Fields:
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::GridModelReader>> m_gridModelReader;
|
||||
caf::PdmProxyValueField<caf::AppEnum<RiaDefines::EclipseUnitSystem>> m_unitSystem;
|
||||
caf::PdmChildArrayField<RimFlowDiagSolution*> m_flowDiagSolutions;
|
||||
caf::PdmField<caf::FilePath> m_sourSimFileName;
|
||||
|
@ -54,6 +54,11 @@ bool RigCellVolumeResultCalculator::isMatching( const RigEclipseResultAddress& r
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigCellVolumeResultCalculator::calculate( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex )
|
||||
{
|
||||
if ( m_resultsData->activeCellInfo()->reservoirActiveCellCount() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t cellVolIdx = m_resultsData->findOrCreateScalarResultIndex( RigEclipseResultAddress( RiaDefines::ResultCatType::STATIC_NATIVE,
|
||||
RiaResultNames::riCellVolumeResultName() ),
|
||||
false );
|
||||
|
@ -292,6 +292,14 @@ bool RigSimWellData::isMultiSegmentWell() const
|
||||
return m_isMultiSegmentWell;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigSimWellData::setWellName( const QString& wellName )
|
||||
{
|
||||
m_wellName = wellName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -43,6 +43,8 @@ public:
|
||||
void setMultiSegmentWell( bool isMultiSegmentWell );
|
||||
bool isMultiSegmentWell() const;
|
||||
|
||||
void setWellName( const QString& wellName );
|
||||
|
||||
bool hasWellResult( size_t resultTimeStepIndex ) const;
|
||||
bool hasAnyValidCells( size_t resultTimeStepIndex ) const;
|
||||
|
||||
|
@ -96,6 +96,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellLogCalculatedCurve-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigWellLogCurveData-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaNumericalTools-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/opm-import-well-data-Test.cpp
|
||||
)
|
||||
|
||||
if(RESINSIGHT_ENABLE_GRPC)
|
||||
|
54
ApplicationLibCode/UnitTests/opm-import-well-data-Test.cpp
Normal file
54
ApplicationLibCode/UnitTests/opm-import-well-data-Test.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
#include "RiaTestDataDirectory.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "opm/input/eclipse/Deck/Deck.hpp"
|
||||
#include "opm/input/eclipse/Parser/Parser.hpp"
|
||||
#include "opm/io/eclipse/ERst.hpp"
|
||||
#include "opm/io/eclipse/RestartFileView.hpp"
|
||||
#include "opm/io/eclipse/rst/state.hpp"
|
||||
#include "opm/io/eclipse/rst/well.hpp"
|
||||
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
|
||||
const std::string drogonPath = "e:/gitroot/resinsight-tutorials/model-data/drogon/DROGON-0.UNRST";
|
||||
|
||||
TEST( DISABLED_opm_well_data_test, TestImport )
|
||||
{
|
||||
Opm::Deck deck;
|
||||
|
||||
// It is required to create a deck as the input parameter to runspec. The = default() initialization of the runspec keyword does not
|
||||
// initialize the object as expected.
|
||||
Opm::Runspec runspec( deck );
|
||||
Opm::Parser parser( false );
|
||||
|
||||
try
|
||||
{
|
||||
QDir baseFolder( TEST_MODEL_DIR );
|
||||
bool subFolderExists = baseFolder.cd( "TEST10K_FLT_LGR_NNC" );
|
||||
EXPECT_TRUE( subFolderExists );
|
||||
QString filename( "TEST10K_FLT_LGR_NNC.UNRST" );
|
||||
QString filePath = baseFolder.absoluteFilePath( filename );
|
||||
|
||||
auto stdFilename = baseFolder.absoluteFilePath( filename ).toStdString();
|
||||
|
||||
auto rstFile = std::make_shared<Opm::EclIO::ERst>( drogonPath );
|
||||
for ( auto seqNumber : rstFile->listOfReportStepNumbers() )
|
||||
{
|
||||
auto fileView = std::make_shared<Opm::EclIO::RestartFileView>( rstFile, seqNumber );
|
||||
|
||||
auto state = Opm::RestartIO::RstState::load( fileView, runspec, parser );
|
||||
|
||||
for ( const auto& w : state.wells )
|
||||
{
|
||||
auto name = w.name;
|
||||
std::cout << name << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
std::cout << "Exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
@ -448,16 +448,19 @@ if((NOT RESINSIGHT_BUILD_LIBS_FROM_SOURCE) AND MSVC)
|
||||
URL https://github.com/CeetronSolutions/resinsight-dependencies/releases/download/2023.08/custom-opm-common.zip
|
||||
)
|
||||
FetchContent_Populate(ri-dependencies)
|
||||
|
||||
|
||||
add_library(custom-opm-common STATIC IMPORTED)
|
||||
set_target_properties(custom-opm-common PROPERTIES
|
||||
IMPORTED_CONFIGURATIONS "Debug;Release"
|
||||
IMPORTED_LOCATION_DEBUG "${ri-dependencies_SOURCE_DIR}/custom-opm-common_debug.lib"
|
||||
IMPORTED_LOCATION_RELEASE "${ri-dependencies_SOURCE_DIR}/custom-opm-common.lib"
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
custom-opm-common
|
||||
PROPERTIES IMPORTED_CONFIGURATIONS "Debug;Release"
|
||||
IMPORTED_LOCATION_DEBUG
|
||||
"${ri-dependencies_SOURCE_DIR}/custom-opm-common_debug.lib"
|
||||
IMPORTED_LOCATION_RELEASE
|
||||
"${ri-dependencies_SOURCE_DIR}/custom-opm-common.lib"
|
||||
)
|
||||
|
||||
list(APPEND EXTERNAL_LINK_LIBRARIES custom-opm-common)
|
||||
|
||||
|
||||
message(STATUS "opm-common: Enabled use of precompiled library")
|
||||
else()
|
||||
add_subdirectory(ThirdParty/custom-opm-common)
|
||||
|
13
ThirdParty/custom-opm-common/CMakeLists.txt
vendored
13
ThirdParty/custom-opm-common/CMakeLists.txt
vendored
@ -92,10 +92,21 @@ add_library(${PROJECT_NAME}
|
||||
opm-common/src/opm/io/eclipse/rst/connection.cpp
|
||||
|
||||
# Required for use of RstHeader::restart_info
|
||||
opm-common/src/opm/io/eclipse/rst/action.cpp
|
||||
opm-common/src/opm/io/eclipse/rst/aquifer.cpp
|
||||
opm-common/src/opm/io/eclipse/rst/connection.cpp
|
||||
opm-common/src/opm/io/eclipse/rst/group.cpp
|
||||
opm-common/src/opm/io/eclipse/rst/header.cpp
|
||||
opm-common/src/opm/io/eclipse/rst/network.cpp
|
||||
opm-common/src/opm/io/eclipse/rst/segment.cpp
|
||||
opm-common/src/opm/io/eclipse/rst/state.cpp
|
||||
opm-common/src/opm/io/eclipse/rst/udq.cpp
|
||||
opm-common/src/opm/io/eclipse/rst/well.cpp
|
||||
opm-common/src/opm/output/eclipse/InteHEAD.cpp
|
||||
opm-common/src/opm/output/eclipse/UDQDims.cpp
|
||||
opm-common/src/opm/output/eclipse/CreateActionRSTDims.cpp
|
||||
|
||||
# 2022.06 additional includes
|
||||
opm-common/src/opm/io/eclipse/rst/aquifer.cpp
|
||||
opm-common/src/opm/io/eclipse/ERst.cpp
|
||||
opm-common/src/opm/io/eclipse/RestartFileView.cpp
|
||||
opm-common/cross-platform/windows/Substitutes.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user