Grid import using opm-common improvements (#11438)

* Update opm-common EGRID reader to support LGRs, NNCs, dual porosity, unit system info and time step filters
* Rearrange well reading code into separate class
* Update resdata library to not require an ecl_grid when reading well information. Only lgr names are needed, allows reused by opm_common reader
This commit is contained in:
jonjenssen 2024-06-18 13:03:48 +02:00 committed by GitHub
parent ccda815bde
commit 4365b0dfb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 2898 additions and 2504 deletions

View File

@ -201,12 +201,12 @@ QDateTime RiaQDateTimeTools::subtractPeriod( const QDateTime& dt, RiaDefines::Da
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
QDateTime RiaQDateTimeTools::createDateTime( const QDate& date ) QDateTime RiaQDateTimeTools::createDateTime( const QDate& date, Qt::TimeSpec timeSpec /*= Qt::LocalTime*/ )
{ {
#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 ) #if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
return date.startOfDay(); return date.startOfDay( timeSpec );
#else #else
return QDateTime( date, QTime( 0, 0 ) ); return QDateTime( date, QTime( 0, 0 ), timeSpec );
#endif #endif
} }

View File

@ -58,7 +58,7 @@ public:
static QDateTime addPeriod( const QDateTime& dt, RiaDefines::DateTimePeriod period ); static QDateTime addPeriod( const QDateTime& dt, RiaDefines::DateTimePeriod period );
static QDateTime subtractPeriod( const QDateTime& dt, RiaDefines::DateTimePeriod period ); static QDateTime subtractPeriod( const QDateTime& dt, RiaDefines::DateTimePeriod period );
static QDateTime createDateTime( const QDate& date ); static QDateTime createDateTime( const QDate& date, Qt::TimeSpec timeSpec = Qt::LocalTime );
static QDateTime epoch(); static QDateTime epoch();

View File

@ -10,6 +10,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RifPerforationIntervalReader.h ${CMAKE_CURRENT_LIST_DIR}/RifPerforationIntervalReader.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseInput.h ${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseInput.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseOutput.h ${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseOutput.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseWell.h
${CMAKE_CURRENT_LIST_DIR}/RifSummaryReaderInterface.h ${CMAKE_CURRENT_LIST_DIR}/RifSummaryReaderInterface.h
${CMAKE_CURRENT_LIST_DIR}/RifEclipseUserDataParserTools.h ${CMAKE_CURRENT_LIST_DIR}/RifEclipseUserDataParserTools.h
${CMAKE_CURRENT_LIST_DIR}/RifColumnBasedUserDataParser.h ${CMAKE_CURRENT_LIST_DIR}/RifColumnBasedUserDataParser.h
@ -79,12 +80,13 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RifSeismicReader.h ${CMAKE_CURRENT_LIST_DIR}/RifSeismicReader.h
${CMAKE_CURRENT_LIST_DIR}/RifSeismicZGYReader.h ${CMAKE_CURRENT_LIST_DIR}/RifSeismicZGYReader.h
${CMAKE_CURRENT_LIST_DIR}/RifOpenVDSReader.h ${CMAKE_CURRENT_LIST_DIR}/RifOpenVDSReader.h
${CMAKE_CURRENT_LIST_DIR}/RifOpmGridTools.h ${CMAKE_CURRENT_LIST_DIR}/RifOpmRadialGridTools.h
${CMAKE_CURRENT_LIST_DIR}/RifCsvSummaryReader.h ${CMAKE_CURRENT_LIST_DIR}/RifCsvSummaryReader.h
${CMAKE_CURRENT_LIST_DIR}/RifRevealSummaryCsvReader.h ${CMAKE_CURRENT_LIST_DIR}/RifRevealSummaryCsvReader.h
${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSectionSummaryReader.h ${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSectionSummaryReader.h
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanCsvSummaryReader.h ${CMAKE_CURRENT_LIST_DIR}/RifStimPlanCsvSummaryReader.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderOpmCommon.h ${CMAKE_CURRENT_LIST_DIR}/RifReaderOpmCommon.h
${CMAKE_CURRENT_LIST_DIR}/RifEclipseReportKeywords.h
${CMAKE_CURRENT_LIST_DIR}/RifInpExportTools.h ${CMAKE_CURRENT_LIST_DIR}/RifInpExportTools.h
${CMAKE_CURRENT_LIST_DIR}/RifFaultReactivationModelExporter.h ${CMAKE_CURRENT_LIST_DIR}/RifFaultReactivationModelExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifThermalToStimPlanFractureXmlOutput.h ${CMAKE_CURRENT_LIST_DIR}/RifThermalToStimPlanFractureXmlOutput.h
@ -107,13 +109,13 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RifEclipseInputFileTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEclipseInputFileTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RifRoffFileTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifRoffFileTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEclipseOutputFileTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEclipseOutputFileTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEclipseRestartDataAccess.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEclipseRestartFilesetAccess.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEclipseRestartFilesetAccess.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEclipseUnifiedRestartFileAccess.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEclipseUnifiedRestartFileAccess.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEclipseSummaryTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEclipseSummaryTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RifPerforationIntervalReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifPerforationIntervalReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseInput.cpp ${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseInput.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseOutput.cpp ${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseOutput.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseWell.cpp
${CMAKE_CURRENT_LIST_DIR}/RifSummaryReaderInterface.cpp ${CMAKE_CURRENT_LIST_DIR}/RifSummaryReaderInterface.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEclipseUserDataParserTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEclipseUserDataParserTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RifColumnBasedUserDataParser.cpp ${CMAKE_CURRENT_LIST_DIR}/RifColumnBasedUserDataParser.cpp
@ -180,9 +182,10 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RifSeismicReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifSeismicReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifSeismicZGYReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifSeismicZGYReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifOpenVDSReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifOpenVDSReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifOpmGridTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifOpmRadialGridTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RifCsvSummaryReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifCsvSummaryReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSummaryReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSummaryReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEclipseReportKeywords.cpp
${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSectionSummaryReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifRevealCsvSectionSummaryReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanCsvSummaryReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifStimPlanCsvSummaryReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderOpmCommon.cpp ${CMAKE_CURRENT_LIST_DIR}/RifReaderOpmCommon.cpp

View File

@ -23,6 +23,7 @@
#include "RiaQDateTimeTools.h" #include "RiaQDateTimeTools.h"
#include "RiaStringEncodingTools.h" #include "RiaStringEncodingTools.h"
#include "RifEclipseReportKeywords.h"
#include "RifEclipseRestartFilesetAccess.h" #include "RifEclipseRestartFilesetAccess.h"
#include "RifEclipseUnifiedRestartFileAccess.h" #include "RifEclipseUnifiedRestartFileAccess.h"
@ -67,7 +68,7 @@ RifEclipseOutputFileTools::~RifEclipseOutputFileTools()
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<RifKeywordValueCount> RifEclipseOutputFileTools::keywordValueCounts( const std::vector<ecl_file_type*>& ecl_files ) std::vector<RifEclipseKeywordValueCount> RifEclipseOutputFileTools::keywordValueCounts( const std::vector<ecl_file_type*>& ecl_files )
{ {
auto reportstepMetaData = RifEclipseOutputFileTools::createReportStepsMetaData( ecl_files ); auto reportstepMetaData = RifEclipseOutputFileTools::createReportStepsMetaData( ecl_files );
return reportstepMetaData.keywordValueCounts(); return reportstepMetaData.keywordValueCounts();
@ -76,10 +77,11 @@ std::vector<RifKeywordValueCount> RifEclipseOutputFileTools::keywordValueCounts(
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RifEclipseOutputFileTools::createResultEntries( const std::vector<RifKeywordValueCount>& fileKeywordInfo, void RifEclipseOutputFileTools::createResultEntries( const std::vector<RifEclipseKeywordValueCount>& fileKeywordInfo,
const std::vector<RigEclipseTimeStepInfo>& timeStepInfo, const std::vector<RigEclipseTimeStepInfo>& timeStepInfo,
RiaDefines::ResultCatType resultCategory, RiaDefines::ResultCatType resultCategory,
RigEclipseCaseData* eclipseCaseData ) RigEclipseCaseData* eclipseCaseData,
size_t totalTimeSteps )
{ {
if ( !eclipseCaseData ) return; if ( !eclipseCaseData ) return;
@ -91,12 +93,17 @@ void RifEclipseOutputFileTools::createResultEntries( const std::vector<RifKeywor
eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ), eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ),
eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL ), eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL ),
RiaDefines::PorosityModelType::MATRIX_MODEL, RiaDefines::PorosityModelType::MATRIX_MODEL,
timeStepInfo.size() ); totalTimeSteps );
if ( resultCategory == RiaDefines::ResultCatType::STATIC_NATIVE )
{
validKeywords.push_back( RifEclipseKeywordValueCount( "ACTNUM", 0, RifEclipseKeywordValueCount::KeywordDataType::INTEGER ) );
}
for ( const auto& keywordData : validKeywords ) for ( const auto& keywordData : validKeywords )
{ {
RigEclipseResultAddress resAddr( resultCategory, RigEclipseResultAddress resAddr( resultCategory,
RifKeywordValueCount::mapType( keywordData.dataType() ), RifEclipseKeywordValueCount::mapType( keywordData.dataType() ),
QString::fromStdString( keywordData.keyword() ) ); QString::fromStdString( keywordData.keyword() ) );
matrixModelResults->createResultEntry( resAddr, false ); matrixModelResults->createResultEntry( resAddr, false );
matrixModelResults->setTimeStepInfos( resAddr, timeStepInfo ); matrixModelResults->setTimeStepInfos( resAddr, timeStepInfo );
@ -108,12 +115,17 @@ void RifEclipseOutputFileTools::createResultEntries( const std::vector<RifKeywor
eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ), eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ),
eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL ), eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL ),
RiaDefines::PorosityModelType::FRACTURE_MODEL, RiaDefines::PorosityModelType::FRACTURE_MODEL,
timeStepInfo.size() ); totalTimeSteps );
if ( resultCategory == RiaDefines::ResultCatType::STATIC_NATIVE )
{
validKeywords.push_back( RifEclipseKeywordValueCount( "ACTNUM", 0, RifEclipseKeywordValueCount::KeywordDataType::INTEGER ) );
}
for ( const auto& keywordData : validKeywords ) for ( const auto& keywordData : validKeywords )
{ {
RigEclipseResultAddress resAddr( resultCategory, RigEclipseResultAddress resAddr( resultCategory,
RifKeywordValueCount::mapType( keywordData.dataType() ), RifEclipseKeywordValueCount::mapType( keywordData.dataType() ),
QString::fromStdString( keywordData.keyword() ) ); QString::fromStdString( keywordData.keyword() ) );
fractureModelResults->createResultEntry( resAddr, false ); fractureModelResults->createResultEntry( resAddr, false );
fractureModelResults->setTimeStepInfos( resAddr, timeStepInfo ); fractureModelResults->setTimeStepInfos( resAddr, timeStepInfo );
@ -124,7 +136,7 @@ void RifEclipseOutputFileTools::createResultEntries( const std::vector<RifKeywor
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void getDayMonthYear( const ecl_kw_type* intehead_kw, int* day, int* month, int* year ) void RifEclipseOutputFileTools::getDayMonthYear( const ecl_kw_type* intehead_kw, int* day, int* month, int* year )
{ {
assert( day && month && year ); assert( day && month && year );
@ -714,9 +726,9 @@ bool RifEclipseOutputFileTools::assignActiveCellData( std::vector<std::vector<in
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RifRestartReportKeywords RifEclipseOutputFileTools::createReportStepsMetaData( const std::vector<ecl_file_type*>& ecl_files ) RifEclipseReportKeywords RifEclipseOutputFileTools::createReportStepsMetaData( const std::vector<ecl_file_type*>& ecl_files )
{ {
RifRestartReportKeywords reportSteps; RifEclipseReportKeywords reportSteps;
for ( auto ecl_file : ecl_files ) for ( auto ecl_file : ecl_files )
{ {
@ -753,18 +765,18 @@ RifRestartReportKeywords RifEclipseOutputFileTools::createReportStepsMetaData( c
continue; continue;
} }
RifKeywordValueCount::KeywordDataType dataType = RifKeywordValueCount::KeywordDataType::UNKNOWN; auto dataType = RifEclipseKeywordValueCount::KeywordDataType::UNKNOWN;
if ( dataTypeEnumOnFile == ECL_DOUBLE_TYPE ) if ( dataTypeEnumOnFile == ECL_DOUBLE_TYPE )
{ {
dataType = RifKeywordValueCount::KeywordDataType::DOUBLE; dataType = RifEclipseKeywordValueCount::KeywordDataType::DOUBLE;
} }
else if ( dataTypeEnumOnFile == ECL_FLOAT_TYPE ) else if ( dataTypeEnumOnFile == ECL_FLOAT_TYPE )
{ {
dataType = RifKeywordValueCount::KeywordDataType::FLOAT; dataType = RifEclipseKeywordValueCount::KeywordDataType::FLOAT;
} }
else if ( dataTypeEnumOnFile == ECL_INT_TYPE ) else if ( dataTypeEnumOnFile == ECL_INT_TYPE )
{ {
dataType = RifKeywordValueCount::KeywordDataType::INTEGER; dataType = RifEclipseKeywordValueCount::KeywordDataType::INTEGER;
} }
int itemCount = ecl_file_iget_named_size( ecl_file, kw, iOcc ); int itemCount = ecl_file_iget_named_size( ecl_file, kw, iOcc );
@ -786,12 +798,12 @@ RifRestartReportKeywords RifEclipseOutputFileTools::createReportStepsMetaData( c
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<RifKeywordValueCount> std::vector<RifEclipseKeywordValueCount>
RifEclipseOutputFileTools::validKeywordsForPorosityModel( const std::vector<RifKeywordValueCount>& keywordItemCounts, RifEclipseOutputFileTools::validKeywordsForPorosityModel( const std::vector<RifEclipseKeywordValueCount>& keywordItemCounts,
const RigActiveCellInfo* matrixActiveCellInfo, const RigActiveCellInfo* matrixActiveCellInfo,
const RigActiveCellInfo* fractureActiveCellInfo, const RigActiveCellInfo* fractureActiveCellInfo,
RiaDefines::PorosityModelType porosityModel, RiaDefines::PorosityModelType porosityModel,
size_t timeStepCount ) size_t timeStepCount )
{ {
if ( !matrixActiveCellInfo ) return {}; if ( !matrixActiveCellInfo ) return {};
@ -800,7 +812,7 @@ std::vector<RifKeywordValueCount>
return {}; return {};
} }
std::vector<RifKeywordValueCount> keywordsWithCorrectNumberOfDataItems; std::vector<RifEclipseKeywordValueCount> keywordsWithCorrectNumberOfDataItems;
for ( const auto& keywordValueCount : keywordItemCounts ) for ( const auto& keywordValueCount : keywordItemCounts )
{ {
@ -809,39 +821,39 @@ std::vector<RifKeywordValueCount>
bool validKeyword = false; bool validKeyword = false;
size_t timeStepsAllCellsRest = valueCount % matrixActiveCellInfo->reservoirCellCount(); auto matrixActiveCellCount = matrixActiveCellInfo->reservoirActiveCellCount();
if ( timeStepsAllCellsRest == 0 && valueCount <= timeStepCount * matrixActiveCellInfo->reservoirCellCount() ) auto fractureActiveCellCount = fractureActiveCellInfo->reservoirActiveCellCount();
size_t timeStepsAllCellsRest = valueCount % matrixActiveCellCount;
if ( timeStepsAllCellsRest == 0 && valueCount <= timeStepCount * matrixActiveCellCount )
{ {
// Found result for all cells for N time steps, usually a static dataset for one time step // Found result for all cells for N time steps, usually a static dataset for one time step
validKeyword = true; validKeyword = true;
} }
else else
{ {
size_t timeStepsMatrixRest = valueCount % matrixActiveCellInfo->reservoirActiveCellCount(); size_t timeStepsMatrixRest = valueCount % matrixActiveCellCount;
size_t timeStepsFractureRest = 0; size_t timeStepsFractureRest = 0;
if ( fractureActiveCellInfo->reservoirActiveCellCount() > 0 ) if ( fractureActiveCellCount > 0 )
{ {
timeStepsFractureRest = valueCount % fractureActiveCellInfo->reservoirActiveCellCount(); timeStepsFractureRest = valueCount % fractureActiveCellCount;
} }
size_t sumFractureMatrixActiveCellCount = matrixActiveCellInfo->reservoirActiveCellCount() + size_t sumFractureMatrixActiveCellCount = matrixActiveCellCount + fractureActiveCellCount;
fractureActiveCellInfo->reservoirActiveCellCount(); size_t timeStepsMatrixAndFractureRest = valueCount % sumFractureMatrixActiveCellCount;
size_t timeStepsMatrixAndFractureRest = valueCount % sumFractureMatrixActiveCellCount;
if ( porosityModel == RiaDefines::PorosityModelType::MATRIX_MODEL && timeStepsMatrixRest == 0 ) if ( porosityModel == RiaDefines::PorosityModelType::MATRIX_MODEL && timeStepsMatrixRest == 0 )
{ {
if ( valueCount <= if ( valueCount <= timeStepCount * std::max( matrixActiveCellCount, sumFractureMatrixActiveCellCount ) )
timeStepCount * std::max( matrixActiveCellInfo->reservoirActiveCellCount(), sumFractureMatrixActiveCellCount ) )
{ {
validKeyword = true; validKeyword = true;
} }
} }
else if ( porosityModel == RiaDefines::PorosityModelType::FRACTURE_MODEL && else if ( porosityModel == RiaDefines::PorosityModelType::FRACTURE_MODEL && fractureActiveCellCount > 0 &&
fractureActiveCellInfo->reservoirActiveCellCount() > 0 && timeStepsFractureRest == 0 ) timeStepsFractureRest == 0 )
{ {
if ( valueCount <= if ( valueCount <= timeStepCount * std::max( fractureActiveCellCount, sumFractureMatrixActiveCellCount ) )
timeStepCount * std::max( fractureActiveCellInfo->reservoirActiveCellCount(), sumFractureMatrixActiveCellCount ) )
{ {
validKeyword = true; validKeyword = true;
} }
@ -855,13 +867,23 @@ std::vector<RifKeywordValueCount>
} }
} }
// is this a result with a value for all cells?
if ( !validKeyword )
{
if ( valueCount > 0 && ( porosityModel == RiaDefines::PorosityModelType::MATRIX_MODEL ) &&
( valueCount % matrixActiveCellInfo->reservoirCellCount() == 0 ) )
{
validKeyword = true;
}
}
// Check for INIT values that has only values for main grid active cells // Check for INIT values that has only values for main grid active cells
if ( !validKeyword ) if ( !validKeyword )
{ {
if ( timeStepCount == 1 ) if ( timeStepCount == 1 )
{ {
size_t mainGridMatrixActiveCellCount = matrixActiveCellInfo->gridActiveCellCounts( 0 ); size_t mainGridMatrixActiveCellCount = matrixActiveCellInfo->reservoirActiveCellCount();
size_t mainGridFractureActiveCellCount = fractureActiveCellInfo->gridActiveCellCounts( 0 ); size_t mainGridFractureActiveCellCount = fractureActiveCellInfo->reservoirActiveCellCount();
if ( valueCount == mainGridMatrixActiveCellCount || valueCount == mainGridFractureActiveCellCount || if ( valueCount == mainGridMatrixActiveCellCount || valueCount == mainGridFractureActiveCellCount ||
valueCount == mainGridMatrixActiveCellCount + mainGridFractureActiveCellCount ) valueCount == mainGridMatrixActiveCellCount + mainGridFractureActiveCellCount )
@ -879,3 +901,57 @@ std::vector<RifKeywordValueCount>
return keywordsWithCorrectNumberOfDataItems; return keywordsWithCorrectNumberOfDataItems;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifEclipseOutputFileTools::extractResultValuesBasedOnPorosityModel( RigEclipseCaseData* eclipseCaseData,
RiaDefines::PorosityModelType matrixOrFracture,
std::vector<double>* destinationResultValues,
const std::vector<double>& sourceResultValues )
{
if ( sourceResultValues.empty() ) return;
RigActiveCellInfo* fracActCellInfo = eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL );
if ( matrixOrFracture == RiaDefines::PorosityModelType::MATRIX_MODEL && fracActCellInfo->reservoirActiveCellCount() == 0 )
{
destinationResultValues->insert( destinationResultValues->end(), sourceResultValues.begin(), sourceResultValues.end() );
}
else
{
RigActiveCellInfo* actCellInfo = eclipseCaseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL );
size_t sourceStartPosition = 0;
for ( size_t i = 0; i < eclipseCaseData->mainGrid()->gridCount(); i++ )
{
if ( eclipseCaseData->mainGrid()->gridByIndex( i )->isTempGrid() ) continue;
size_t matrixActiveCellCount = actCellInfo->gridActiveCellCounts( i );
size_t fractureActiveCellCount = fracActCellInfo->gridActiveCellCounts( i );
if ( matrixOrFracture == RiaDefines::PorosityModelType::MATRIX_MODEL )
{
destinationResultValues->insert( destinationResultValues->end(),
sourceResultValues.begin() + sourceStartPosition,
sourceResultValues.begin() + sourceStartPosition + matrixActiveCellCount );
}
else
{
if ( ( matrixActiveCellCount + fractureActiveCellCount ) > sourceResultValues.size() )
{
// Special handling of the situation where we only have data for one fracture mode
matrixActiveCellCount = 0;
}
destinationResultValues->insert( destinationResultValues->end(),
sourceResultValues.begin() + sourceStartPosition + matrixActiveCellCount,
sourceResultValues.begin() + sourceStartPosition + matrixActiveCellCount +
fractureActiveCellCount );
}
sourceStartPosition += ( matrixActiveCellCount + fractureActiveCellCount );
}
}
}

View File

@ -20,8 +20,13 @@
#pragma once #pragma once
#include "RifEclipseRestartDataAccess.h" #include "RifEclipseReportKeywords.h"
#include "RiaDefines.h"
#include "RiaPorosityModel.h"
#include "ert/ecl/ecl_file_view.h"
#include "ert/ecl/ecl_grid.h"
#include "ert/ecl/ecl_util.h" #include "ert/ecl/ecl_util.h"
#include "cvfObject.h" #include "cvfObject.h"
@ -37,6 +42,8 @@ using ecl_file_type = struct ecl_file_struct;
class RifEclipseRestartDataAccess; class RifEclipseRestartDataAccess;
class RigEclipseTimeStepInfo; class RigEclipseTimeStepInfo;
class RigActiveCellInfo; class RigActiveCellInfo;
class RigEclipseCaseData;
class QByteArray; class QByteArray;
//================================================================================================== //==================================================================================================
@ -50,12 +57,13 @@ public:
RifEclipseOutputFileTools(); RifEclipseOutputFileTools();
virtual ~RifEclipseOutputFileTools(); virtual ~RifEclipseOutputFileTools();
static std::vector<RifKeywordValueCount> keywordValueCounts( const std::vector<ecl_file_type*>& ecl_files ); static std::vector<RifEclipseKeywordValueCount> keywordValueCounts( const std::vector<ecl_file_type*>& ecl_files );
static void createResultEntries( const std::vector<RifKeywordValueCount>& fileKeywordInfo, static void createResultEntries( const std::vector<RifEclipseKeywordValueCount>& fileKeywordInfo,
const std::vector<RigEclipseTimeStepInfo>& timeStepInfo, const std::vector<RigEclipseTimeStepInfo>& timeStepInfo,
RiaDefines::ResultCatType resultCategory, RiaDefines::ResultCatType resultCategory,
RigEclipseCaseData* eclipseCaseData ); RigEclipseCaseData* eclipseCaseData,
size_t totalTimeSteps );
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<double>* values );
static bool keywordData( const ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector<int>* values ); static bool keywordData( const ecl_file_type* ecl_file, const QString& keyword, size_t fileKeywordOccurrence, std::vector<int>* values );
@ -94,11 +102,19 @@ public:
static bool assignActiveCellData( std::vector<std::vector<int>>& actnumValuesPerGrid, RigEclipseCaseData* eclipseCaseData ); static bool assignActiveCellData( std::vector<std::vector<int>>& actnumValuesPerGrid, RigEclipseCaseData* eclipseCaseData );
static std::vector<RifEclipseKeywordValueCount>
validKeywordsForPorosityModel( const std::vector<RifEclipseKeywordValueCount>& keywordItemCounts,
const RigActiveCellInfo* activeCellInfo,
const RigActiveCellInfo* fractureActiveCellInfo,
RiaDefines::PorosityModelType matrixOrFracture,
size_t timeStepCount );
static void extractResultValuesBasedOnPorosityModel( RigEclipseCaseData* eclipseCaseData,
RiaDefines::PorosityModelType matrixOrFracture,
std::vector<double>* values,
const std::vector<double>& fileValues );
private: private:
static RifRestartReportKeywords createReportStepsMetaData( const std::vector<ecl_file_type*>& ecl_files ); static void getDayMonthYear( const ecl_kw_type* intehead_kw, int* day, int* month, int* year );
static std::vector<RifKeywordValueCount> validKeywordsForPorosityModel( const std::vector<RifKeywordValueCount>& keywordItemCounts, static RifEclipseReportKeywords createReportStepsMetaData( const std::vector<ecl_file_type*>& ecl_files );
const RigActiveCellInfo* activeCellInfo,
const RigActiveCellInfo* fractureActiveCellInfo,
RiaDefines::PorosityModelType matrixOrFracture,
size_t timeStepCount );
}; };

View File

@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS // Copyright (C) 2024 Equinor ASA
// //
// ResInsight is free software: you can redistribute it and/or modify // ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
@ -16,32 +16,20 @@
// //
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
#include "RifEclipseRestartDataAccess.h" #include "RifEclipseReportKeywords.h"
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
RifEclipseRestartDataAccess::RifEclipseRestartDataAccess()
{
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
RifEclipseRestartDataAccess::~RifEclipseRestartDataAccess()
{
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RifRestartReportKeywords::appendKeywordCount( const std::string& keyword, size_t valueCount, RifKeywordValueCount::KeywordDataType dataType ) void RifEclipseReportKeywords::appendKeywordCount( const std::string& keyword,
size_t valueCount,
RifEclipseKeywordValueCount::KeywordDataType dataType )
{ {
auto it = m_keywordValueCounts.find( keyword ); auto it = m_keywordValueCounts.find( keyword );
if ( it == m_keywordValueCounts.end() ) if ( it == m_keywordValueCounts.end() )
{ {
m_keywordValueCounts[keyword] = RifKeywordValueCount( keyword, valueCount, dataType ); m_keywordValueCounts[keyword] = RifEclipseKeywordValueCount( keyword, valueCount, dataType );
} }
else else
{ {
@ -52,7 +40,7 @@ void RifRestartReportKeywords::appendKeywordCount( const std::string& keyword, s
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RifRestartReportKeywords::appendKeywordCount( const RifRestartReportKeywords& other ) void RifEclipseReportKeywords::appendKeywordCount( const RifEclipseReportKeywords& other )
{ {
for ( const auto& [keyword, keywordInfo] : other.m_keywordValueCounts ) for ( const auto& [keyword, keywordInfo] : other.m_keywordValueCounts )
{ {
@ -63,9 +51,9 @@ void RifRestartReportKeywords::appendKeywordCount( const RifRestartReportKeyword
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<RifKeywordValueCount> RifRestartReportKeywords::keywordValueCounts() const std::vector<RifEclipseKeywordValueCount> RifEclipseReportKeywords::keywordValueCounts() const
{ {
std::vector<RifKeywordValueCount> tmp; std::vector<RifEclipseKeywordValueCount> tmp;
for ( const auto& [keyword, info] : m_keywordValueCounts ) for ( const auto& [keyword, info] : m_keywordValueCounts )
{ {
tmp.push_back( info ); tmp.push_back( info );

View File

@ -0,0 +1,91 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024 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 "RiaDefines.h"
#include <map>
#include <string>
class RifEclipseKeywordValueCount
{
public:
enum class KeywordDataType
{
UNKNOWN,
FLOAT,
DOUBLE,
INTEGER,
};
public:
RifEclipseKeywordValueCount( const std::string& keyword, size_t itemCount, KeywordDataType dataType )
: m_keyword( keyword )
, m_valueCount( itemCount )
, m_dataType( dataType )
{
}
RifEclipseKeywordValueCount()
: m_valueCount( 0 )
, m_dataType( KeywordDataType::UNKNOWN )
{
}
void addValueCount( size_t valueCount ) { m_valueCount += valueCount; }
std::string keyword() const { return m_keyword; }
size_t valueCount() const { return m_valueCount; }
KeywordDataType dataType() const { return m_dataType; }
static RiaDefines::ResultDataType mapType( RifEclipseKeywordValueCount::KeywordDataType dataType )
{
switch ( dataType )
{
case RifEclipseKeywordValueCount::KeywordDataType::FLOAT:
return RiaDefines::ResultDataType::FLOAT;
case RifEclipseKeywordValueCount::KeywordDataType::DOUBLE:
return RiaDefines::ResultDataType::DOUBLE;
case RifEclipseKeywordValueCount::KeywordDataType::INTEGER:
return RiaDefines::ResultDataType::INTEGER;
}
return RiaDefines::ResultDataType::UNKNOWN;
}
private:
std::string m_keyword;
size_t m_valueCount;
KeywordDataType m_dataType;
};
//==================================================================================================
//
//==================================================================================================
class RifEclipseReportKeywords
{
public:
void appendKeywordCount( const RifEclipseReportKeywords& other );
void appendKeywordCount( const std::string& keyword, size_t valueCount, RifEclipseKeywordValueCount::KeywordDataType dataType );
std::vector<RifEclipseKeywordValueCount> keywordValueCounts() const;
private:
std::map<std::string, RifEclipseKeywordValueCount> m_keywordValueCounts;
};

View File

@ -29,78 +29,9 @@
#include "ert/ecl_well/well_info.hpp" #include "ert/ecl_well/well_info.hpp"
#include "RifEclipseReportKeywords.h"
#include "RifReaderInterface.h" #include "RifReaderInterface.h"
//==================================================================================================
//
//==================================================================================================
class RifKeywordValueCount
{
public:
enum class KeywordDataType
{
UNKNOWN,
FLOAT,
DOUBLE,
INTEGER,
};
public:
RifKeywordValueCount( const std::string& keyword, size_t itemCount, KeywordDataType dataType )
: m_keyword( keyword )
, m_valueCount( itemCount )
, m_dataType( dataType )
{
}
RifKeywordValueCount()
: m_valueCount( 0 )
, m_dataType( KeywordDataType::UNKNOWN )
{
}
void addValueCount( size_t valueCount ) { m_valueCount += valueCount; }
std::string keyword() const { return m_keyword; }
size_t valueCount() const { return m_valueCount; }
KeywordDataType dataType() const { return m_dataType; }
static RiaDefines::ResultDataType mapType( RifKeywordValueCount::KeywordDataType dataType )
{
switch ( dataType )
{
case RifKeywordValueCount::KeywordDataType::FLOAT:
return RiaDefines::ResultDataType::FLOAT;
case RifKeywordValueCount::KeywordDataType::DOUBLE:
return RiaDefines::ResultDataType::DOUBLE;
case RifKeywordValueCount::KeywordDataType::INTEGER:
return RiaDefines::ResultDataType::INTEGER;
}
return RiaDefines::ResultDataType::UNKNOWN;
}
private:
std::string m_keyword;
size_t m_valueCount;
KeywordDataType m_dataType;
};
//==================================================================================================
//
//==================================================================================================
class RifRestartReportKeywords
{
public:
void appendKeywordCount( const RifRestartReportKeywords& other );
void appendKeywordCount( const std::string& keyword, size_t valueCount, RifKeywordValueCount::KeywordDataType dataType );
std::vector<RifKeywordValueCount> keywordValueCounts() const;
private:
std::map<std::string, RifKeywordValueCount> m_keywordValueCounts;
};
//================================================================================================== //==================================================================================================
// //
// Abstract class for results access // Abstract class for results access
@ -109,8 +40,8 @@ private:
class RifEclipseRestartDataAccess : public cvf::Object class RifEclipseRestartDataAccess : public cvf::Object
{ {
public: public:
RifEclipseRestartDataAccess(); RifEclipseRestartDataAccess(){};
~RifEclipseRestartDataAccess() override; ~RifEclipseRestartDataAccess() override{};
virtual bool open() = 0; virtual bool open() = 0;
virtual void setRestartFiles( const QStringList& fileSet ) = 0; virtual void setRestartFiles( const QStringList& fileSet ) = 0;
@ -121,7 +52,7 @@ public:
virtual void timeSteps( std::vector<QDateTime>* timeSteps, std::vector<double>* daysSinceSimulationStart ) = 0; virtual void timeSteps( std::vector<QDateTime>* timeSteps, std::vector<double>* daysSinceSimulationStart ) = 0;
virtual std::vector<int> reportNumbers() = 0; virtual std::vector<int> reportNumbers() = 0;
virtual std::vector<RifKeywordValueCount> keywordValueCounts() = 0; virtual std::vector<RifEclipseKeywordValueCount> keywordValueCounts() = 0;
virtual bool results( const QString& resultName, size_t timeStep, size_t gridCount, std::vector<double>* values ) = 0; virtual bool results( const QString& resultName, size_t timeStep, size_t gridCount, std::vector<double>* values ) = 0;
virtual bool dynamicNNCResults( const ecl_grid_type* grid, virtual bool dynamicNNCResults( const ecl_grid_type* grid,

View File

@ -158,7 +158,7 @@ void RifEclipseRestartFilesetAccess::timeSteps( std::vector<QDateTime>* timeStep
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Get list of result names /// Get list of result names
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<RifKeywordValueCount> RifEclipseRestartFilesetAccess::keywordValueCounts() std::vector<RifEclipseKeywordValueCount> RifEclipseRestartFilesetAccess::keywordValueCounts()
{ {
CVF_ASSERT( timeStepCount() > 0 ); CVF_ASSERT( timeStepCount() > 0 );

View File

@ -46,7 +46,7 @@ public:
void timeSteps( std::vector<QDateTime>* timeSteps, std::vector<double>* daysSinceSimulationStart ) override; void timeSteps( std::vector<QDateTime>* timeSteps, std::vector<double>* daysSinceSimulationStart ) override;
std::vector<int> reportNumbers() override; std::vector<int> reportNumbers() override;
std::vector<RifKeywordValueCount> keywordValueCounts() override; std::vector<RifEclipseKeywordValueCount> keywordValueCounts() override;
bool results( const QString& resultName, size_t timeStep, size_t gridCount, std::vector<double>* values ) override; bool results( const QString& resultName, size_t timeStep, size_t gridCount, std::vector<double>* values ) override;
bool dynamicNNCResults( const ecl_grid_type* grid, bool dynamicNNCResults( const ecl_grid_type* grid,

View File

@ -214,7 +214,7 @@ void RifEclipseUnifiedRestartFileAccess::timeSteps( std::vector<QDateTime>* time
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Get list of result names /// Get list of result names
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<RifKeywordValueCount> RifEclipseUnifiedRestartFileAccess::keywordValueCounts() std::vector<RifEclipseKeywordValueCount> RifEclipseUnifiedRestartFileAccess::keywordValueCounts()
{ {
if ( openFile() ) if ( openFile() )
{ {

View File

@ -47,7 +47,7 @@ public:
void timeSteps( std::vector<QDateTime>* timeSteps, std::vector<double>* daysSinceSimulationStart ) override; void timeSteps( std::vector<QDateTime>* timeSteps, std::vector<double>* daysSinceSimulationStart ) override;
std::vector<int> reportNumbers() override; std::vector<int> reportNumbers() override;
std::vector<RifKeywordValueCount> keywordValueCounts() override; std::vector<RifEclipseKeywordValueCount> keywordValueCounts() override;
bool results( const QString& resultName, size_t timeStep, size_t gridCount, std::vector<double>* values ) override; bool results( const QString& resultName, size_t timeStep, size_t gridCount, std::vector<double>* values ) override;
bool dynamicNNCResults( const ecl_grid_type* grid, bool dynamicNNCResults( const ecl_grid_type* grid,

View File

@ -16,7 +16,7 @@
// //
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
#include "RifOpmGridTools.h" #include "RifOpmRadialGridTools.h"
#include "RiaLogging.h" #include "RiaLogging.h"
#include "RiaWeightedMeanCalculator.h" #include "RiaWeightedMeanCalculator.h"
@ -37,7 +37,7 @@
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RifOpmGridTools::importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* riMainGrid ) void RifOpmRadialGridTools::importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* riMainGrid )
{ {
CAF_ASSERT( riMainGrid ); CAF_ASSERT( riMainGrid );
@ -73,7 +73,7 @@ void RifOpmGridTools::importCoordinatesForRadialGrid( const std::string& gridFil
if ( opmMainGrid.is_radial() ) if ( opmMainGrid.is_radial() )
{ {
transferCoordinates( opmMainGrid, opmMainGrid, riMainGrid, riMainGrid ); transferCoordinatesRadial( opmMainGrid, opmMainGrid, riMainGrid, riMainGrid );
} }
auto lgrNames = opmMainGrid.list_of_lgrs(); auto lgrNames = opmMainGrid.list_of_lgrs();
@ -88,7 +88,7 @@ void RifOpmGridTools::importCoordinatesForRadialGrid( const std::string& gridFil
auto riLgrGrid = riMainGrid->gridByIndex( i ); auto riLgrGrid = riMainGrid->gridByIndex( i );
if ( riLgrGrid->gridName() == lgrName ) if ( riLgrGrid->gridName() == lgrName )
{ {
transferCoordinates( opmMainGrid, opmLgrGrid, riMainGrid, riLgrGrid ); transferCoordinatesRadial( opmMainGrid, opmLgrGrid, riMainGrid, riLgrGrid );
} }
} }
} }
@ -101,87 +101,6 @@ 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 );
auto opmMapAxes = opmGrid.get_mapaxes();
if ( opmMapAxes.size() == 6 )
{
std::array<double, 6> mapAxes;
for ( size_t i = 0; i < opmMapAxes.size(); ++i )
{
mapAxes[i] = opmMapAxes[i];
}
// Set the map axes transformation matrix on the main grid
mainGrid->setMapAxes( mapAxes );
mainGrid->setUseMapAxes( true );
auto transform = mainGrid->mapAxisTransform();
// Invert the transformation matrix to convert from file coordinates to domain coordinates
transform.invert();
#pragma omp parallel for
for ( long i = 0; i < static_cast<long>( mainGrid->nodes().size() ); i++ )
{
auto& n = mainGrid->nodes()[i];
n.transformPoint( transform );
}
}
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 // A radial grid is defined by a center point and a set of cylindrical coordinates. The coordinates at the
@ -213,7 +132,10 @@ std::vector<std::vector<int>> RifOpmGridTools::activeCellsFromActnumKeyword( Opm
// 3. Find the closest point on this pillar, and use this point as the adjusted coordinate for the node // 3. Find the closest point on this pillar, and use this point as the adjusted coordinate for the node
// //
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RifOpmGridTools::transferCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigMainGrid* riMainGrid, RigGridBase* riGrid ) void RifOpmRadialGridTools::transferCoordinatesRadial( Opm::EclIO::EGrid& opmMainGrid,
Opm::EclIO::EGrid& opmGrid,
RigMainGrid* riMainGrid,
RigGridBase* riGrid )
{ {
size_t cellCount = opmGrid.totalNumberOfCells(); size_t cellCount = opmGrid.totalNumberOfCells();
if ( cellCount != riGrid->cellCount() ) return; if ( cellCount != riGrid->cellCount() ) return;
@ -266,153 +188,102 @@ void RifOpmGridTools::transferCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::
// First grid dimension is radius, check if cell has are at the outer-most slice // First grid dimension is radius, check if cell has are at the outer-most slice
if ( !hostCellGlobalIndices.empty() && ( gridDimension[0] - 1 == ijkCell[0] ) ) if ( !hostCellGlobalIndices.empty() && ( gridDimension[0] - 1 == ijkCell[0] ) )
{ {
std::array<double, 8> cellRadius{}; auto hostCellIndex = hostCellGlobalIndices[opmCellIndex];
std::array<double, 8> cellTheta{};
std::array<double, 8> cellZ{};
opmGrid.getRadialCellCorners( ijkCell, cellRadius, cellTheta, cellZ );
double maxRadius = *std::max_element( cellRadius.begin(), cellRadius.end() ); lockToHostPillars( riNode, opmMainGrid, opmGrid, ijkCell, hostCellIndex, opmCellIndex, opmNodeIndex, xCenterCoordOpm, yCenterCoordOpm );
// Check if the radius is at the outer surface of the radial grid
// Adjust the outer nodes to match the corner pillars of the host cell
const double epsilon = 0.15;
if ( fabs( maxRadius - cellRadius[opmNodeIndex] ) < epsilon * cellRadius[opmNodeIndex] )
{
const auto hostCellIndex = hostCellGlobalIndices[opmCellIndex];
double closestPillarDistance = std::numeric_limits<double>::max();
int closestPillarIndex = -1;
const auto cylinderCoordX = opmX[opmNodeIndex] + xCenterCoordOpm;
const auto cylinderCoordY = opmY[opmNodeIndex] + yCenterCoordOpm;
const auto cylinderCoordZ = opmZ[opmNodeIndex];
const cvf::Vec3d coordinateOnCylinder = cvf::Vec3d( cylinderCoordX, cylinderCoordY, cylinderCoordZ );
const auto candidates = computeSnapToCoordinates( opmMainGrid, opmGrid, hostCellIndex, opmCellIndex );
for ( int pillarIndex = 0; pillarIndex < static_cast<int>( candidates.size() ); pillarIndex++ )
{
for ( const auto& c : candidates[pillarIndex] )
{
double distance = coordinateOnCylinder.pointDistance( c );
if ( distance < closestPillarDistance )
{
closestPillarDistance = distance;
closestPillarIndex = pillarIndex;
}
}
}
if ( closestPillarDistance < std::numeric_limits<double>::max() )
{
const auto& pillarCordinates = candidates[closestPillarIndex];
int layerCount = static_cast<int>( pillarCordinates.size() / 2 );
int layerIndexInMainGridCell = ijkCell[2] % layerCount;
int localNodeIndex = opmNodeIndex % 8;
cvf::Vec3d closestPillarCoord;
if ( localNodeIndex < 4 )
{
// Top of cell
int pillarCoordIndex = layerIndexInMainGridCell * 2;
closestPillarCoord = pillarCordinates[pillarCoordIndex];
}
else
{
// Bottom of cell
int pillarCoordIndex = layerIndexInMainGridCell * 2 + 1;
closestPillarCoord = pillarCordinates[pillarCoordIndex];
}
riNode.x() = closestPillarCoord.x();
riNode.y() = closestPillarCoord.y();
riNode.z() = -closestPillarCoord.z();
}
}
} }
} }
} }
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// //
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RifOpmGridTools::transferCoordinatesCartesian( Opm::EclIO::EGrid& opmMainGrid, void RifOpmRadialGridTools::lockToHostPillars( cvf::Vec3d& riNode,
Opm::EclIO::EGrid& opmGrid, Opm::EclIO::EGrid& opmMainGrid,
RigMainGrid* riMainGrid, Opm::EclIO::EGrid& opmGrid,
RigGridBase* riGrid, std::array<int, 3>& ijkCell,
RigEclipseCaseData* caseData ) int hostCellIndex,
int opmCellIndex,
size_t opmNodeIndex,
double xCenterCoordOpm,
double yCenterCoordOpm )
{ {
// Prefix OPM structures with _opm_and ResInsight structures with _ri_ std::array<double, 8> cellRadius{};
std::array<double, 8> cellTheta{};
std::array<double, 8> cellZ{};
opmGrid.getRadialCellCorners( ijkCell, cellRadius, cellTheta, cellZ );
auto& riNodes = riMainGrid->nodes(); double maxRadius = *std::max_element( cellRadius.begin(), cellRadius.end() );
opmGrid.loadData(); // Check if the radius is at the outer surface of the radial grid
opmGrid.load_grid_data(); // Adjust the outer nodes to match the corner pillars of the host cell
const double epsilon = 0.15;
auto riActiveCells = caseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ); if ( fabs( maxRadius - cellRadius[opmNodeIndex] ) < epsilon * cellRadius[opmNodeIndex] )
auto riActiveCellsFrac = caseData->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL );
riActiveCellsFrac->setGridCount( 1 );
riActiveCellsFrac->setGridActiveCellCounts( 0, 0 );
riActiveCells->setReservoirCellCount( riMainGrid->cellCount() );
// same mapping as resdata
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> opmX{};
std::array<double, 8> opmY{}; std::array<double, 8> opmY{};
std::array<double, 8> opmZ{}; std::array<double, 8> opmZ{};
opmGrid.getCellCorners( opmCellIndex, opmX, opmY, 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 double closestPillarDistance = std::numeric_limits<double>::max();
auto riNodeStartIndex = riReservoirIndex * 8; int closestPillarIndex = -1;
for ( size_t opmNodeIndex = 0; opmNodeIndex < 8; opmNodeIndex++ ) const auto cylinderCoordX = opmX[opmNodeIndex] + xCenterCoordOpm;
const auto cylinderCoordY = opmY[opmNodeIndex] + yCenterCoordOpm;
const auto cylinderCoordZ = opmZ[opmNodeIndex];
const cvf::Vec3d coordinateOnCylinder = cvf::Vec3d( cylinderCoordX, cylinderCoordY, cylinderCoordZ );
const auto candidates = computeSnapToCoordinates( opmMainGrid, opmGrid, hostCellIndex, opmCellIndex );
for ( int pillarIndex = 0; pillarIndex < static_cast<int>( candidates.size() ); pillarIndex++ )
{ {
auto riCornerIndex = cellMappingECLRi[opmNodeIndex]; for ( const auto& c : candidates[pillarIndex] )
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 ); double distance = coordinateOnCylinder.pointDistance( c );
if ( distance < closestPillarDistance )
{
closestPillarDistance = distance;
closestPillarIndex = pillarIndex;
}
} }
} }
if ( closestPillarDistance < std::numeric_limits<double>::max() )
{
const auto& pillarCordinates = candidates[closestPillarIndex];
int layerCount = static_cast<int>( pillarCordinates.size() / 2 );
int layerIndexInMainGridCell = ijkCell[2] % layerCount;
int localNodeIndex = opmNodeIndex % 8;
cvf::Vec3d closestPillarCoord;
if ( localNodeIndex < 4 )
{
// Top of cell
int pillarCoordIndex = layerIndexInMainGridCell * 2;
closestPillarCoord = pillarCordinates[pillarCoordIndex];
}
else
{
// Bottom of cell
int pillarCoordIndex = layerIndexInMainGridCell * 2 + 1;
closestPillarCoord = pillarCordinates[pillarCoordIndex];
}
riNode.x() = closestPillarCoord.x();
riNode.y() = closestPillarCoord.y();
riNode.z() = -closestPillarCoord.z();
}
} }
riActiveCells->setGridCount( 1 );
riActiveCells->setGridActiveCellCounts( 0, opmGrid.activeCells() );
riActiveCells->computeDerivedData();
riMainGrid->initAllSubGridsParentGridPointer();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::map<int, std::pair<double, double>> std::map<int, std::pair<double, double>>
RifOpmGridTools::computeXyCenterForTopOfCells( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigGridBase* riGrid ) RifOpmRadialGridTools::computeXyCenterForTopOfCells( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigGridBase* riGrid )
{ {
if ( !riGrid || riGrid->isMainGrid() ) return {}; if ( !riGrid || riGrid->isMainGrid() ) return {};
@ -420,7 +291,6 @@ std::map<int, std::pair<double, double>>
if ( cellCount != riGrid->cellCount() ) return {}; if ( cellCount != riGrid->cellCount() ) return {};
// Read out the corner coordinates from the EGRID file using radial coordinates. // Read out the corner coordinates from the EGRID file using radial coordinates.
// Prefix OPM structures with _opm_and ResInsight structures with _ri_
// Compute the center of the LGR radial grid cells for each K layer // Compute the center of the LGR radial grid cells for each K layer
std::map<int, std::pair<double, double>> radialGridCenterTopLayerOpm; std::map<int, std::pair<double, double>> radialGridCenterTopLayerOpm;
@ -471,8 +341,10 @@ std::map<int, std::pair<double, double>>
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<std::vector<cvf::Vec3d>> std::vector<std::vector<cvf::Vec3d>> RifOpmRadialGridTools::computeSnapToCoordinates( Opm::EclIO::EGrid& opmMainGrid,
RifOpmGridTools::computeSnapToCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, int mainGridCellIndex, int lgrCellIndex ) Opm::EclIO::EGrid& opmGrid,
int mainGridCellIndex,
int lgrCellIndex )
{ {
auto hostCellIndices = opmGrid.hostCellsGlobalIndex(); auto hostCellIndices = opmGrid.hostCellsGlobalIndex();
auto lgrIjk = opmGrid.ijk_from_global_index( lgrCellIndex ); auto lgrIjk = opmGrid.ijk_from_global_index( lgrCellIndex );

View File

@ -39,28 +39,28 @@ class RigEclipseCaseData;
//================================================================================================== //==================================================================================================
/// ///
//================================================================================================== //==================================================================================================
class RifOpmGridTools class RifOpmRadialGridTools
{ {
public: public:
// If the grid is radial, the coordinates are imported and adjusted to fit the host cells // 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 void importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* mainGrid );
static size_t cellCount( const std::string& gridFilePath ); static void
static bool importGrid( const std::string& gridFilePath, RigMainGrid* mainGrid, RigEclipseCaseData* caseData ); transferCoordinatesRadial( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigMainGrid* riMainGrid, RigGridBase* riGrid );
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>> static std::map<int, std::pair<double, double>>
computeXyCenterForTopOfCells( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigGridBase* riGrid ); computeXyCenterForTopOfCells( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigGridBase* riGrid );
static std::vector<std::vector<cvf::Vec3d>> static std::vector<std::vector<cvf::Vec3d>>
computeSnapToCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, int mainGridCellIndex, int lgrCellIndex ); computeSnapToCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, int mainGridCellIndex, int lgrCellIndex );
static void lockToHostPillars( cvf::Vec3d& riNode,
Opm::EclIO::EGrid& opmMainGrid,
Opm::EclIO::EGrid& opmGrid,
std::array<int, 3>& ijkCell,
int hostCellIndex,
int opmCellIndex,
size_t opmNodeIndex,
double xCenterCoordOpm,
double yCenterCoordOpm );
}; };

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ class RigEclipseTimeStepInfo;
class RigGridBase; class RigGridBase;
class RigMainGrid; class RigMainGrid;
class QDateTime; class QDateTime;
class RifKeywordValueCount; class RifEclipseKeywordValueCount;
struct RigWellResultPoint; struct RigWellResultPoint;
@ -91,43 +91,33 @@ public:
private: private:
bool readActiveCellInfo(); bool readActiveCellInfo();
void buildMetaData( ecl_grid_type* grid );
void readWellCells( const ecl_grid_type* mainEclGrid, bool importCompleteMswData );
std::string ertGridName( size_t gridNr ); std::string ertGridName( size_t gridNr );
RigWellResultPoint createWellResultPoint( const RigGridBase* grid, const well_conn_type* ert_connection, const char* wellName ); void buildMetaData( ecl_grid_type* grid );
RigWellResultPoint createWellResultPoint( const RigGridBase* grid,
const well_conn_type* ert_connection,
const well_segment_type* segment,
const char* wellName );
void openInitFile(); void openInitFile();
void extractResultValuesBasedOnPorosityModel( RiaDefines::PorosityModelType matrixOrFracture,
std::vector<double>* values,
const std::vector<double>& fileValues );
void transferStaticNNCData( const ecl_grid_type* mainEclGrid, ecl_file_type* init_file, RigMainGrid* mainGrid ); void transferStaticNNCData( const ecl_grid_type* mainEclGrid, ecl_file_type* init_file, RigMainGrid* mainGrid );
void transferDynamicNNCData( const ecl_grid_type* mainEclGrid, RigMainGrid* mainGrid ); void transferDynamicNNCData( const ecl_grid_type* mainEclGrid, RigMainGrid* mainGrid );
void ensureDynamicResultAccessIsPresent(); void ensureDynamicResultAccessIsPresent();
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(); std::vector<RigEclipseTimeStepInfo> createFilteredTimeStepInfos();
static bool isEclipseAndSoursimTimeStepsEqual( const QDateTime& eclipseDateTime, const QDateTime& sourSimDateTime ); static bool isEclipseAndSoursimTimeStepsEqual( const QDateTime& eclipseDateTime, const QDateTime& sourSimDateTime );
static bool transferGridCellData( RigMainGrid* mainGrid,
RigActiveCellInfo* activeCellInfo,
RigActiveCellInfo* fractureActiveCellInfo,
RigGridBase* localGrid,
const ecl_grid_type* localEclGrid,
size_t matrixActiveStartIndex,
size_t fractureActiveStartIndex );
private: private:
QString m_fileName; // Name of file used to start accessing Eclipse output files QString m_fileName; // Name of file used to start accessing Eclipse output files
QStringList m_filesWithSameBaseName; // Set of files in filename's path with same base name as filename QStringList m_filesWithSameBaseName; // Set of files in filename's path with same base name as filename
RigEclipseCaseData* m_eclipseCase; RigEclipseCaseData* m_eclipseCaseData;
ecl_file_type* m_ecl_init_file; // File access to static results ecl_file_type* m_ecl_init_file; // File access to static results
mutable cvf::ref<RifEclipseRestartDataAccess> m_dynamicResultsAccess; // File access to dynamic results mutable cvf::ref<RifEclipseRestartDataAccess> m_dynamicResultsAccess; // File access to dynamic results

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2024 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 <map>
#include <vector>
#include "cvfVector3.h"
#include <QDateTime>
class RifEclipseRestartDataAccess;
class RigGridBase;
class RigEclipseCaseData;
struct RigWellResultPoint;
struct SegmentPositionContribution;
// NOLINTBEGIN(modernize-use-using)
typedef struct well_conn_struct well_conn_type;
typedef struct well_segment_struct well_segment_type;
typedef struct well_segment_collection_struct well_segment_collection_type;
// NOLINTEND(modernize-use-using)
//==================================================================================================
//
//
//
//==================================================================================================
class RifReaderEclipseWell
{
private:
RifReaderEclipseWell(){};
public:
static void readWellCells( RifEclipseRestartDataAccess* restartDataAccess,
RigEclipseCaseData* eclipseCaseData,
std::vector<QDateTime> filteredTimeSteps,
std::vector<std::string> gridNames,
bool importCompleteMswData );
static size_t
localGridCellIndexFromErtConnection( const RigGridBase* grid, const well_conn_type* ert_connection, const char* wellNameForErrorMsgs );
private:
static RigWellResultPoint createWellResultPoint( const RigEclipseCaseData* eCaseData,
const RigGridBase* grid,
const well_conn_type* ert_connection,
const char* wellName );
static RigWellResultPoint createWellResultPoint( const RigEclipseCaseData* eCaseData,
const RigGridBase* grid,
const well_conn_type* ert_connection,
const well_segment_type* segment,
const char* wellName );
static cvf::Vec3d interpolate3DPosition( const std::vector<SegmentPositionContribution>& positions );
static void propagatePosContribDownwards( std::map<int, std::vector<SegmentPositionContribution>>& segmentIdToPositionContrib,
const well_segment_collection_type* allErtSegments,
int ertSegmentId,
std::vector<SegmentPositionContribution> posContrib );
static std::string ertGridName( const RigEclipseCaseData* eCaseData, size_t gridNr );
};

View File

@ -51,9 +51,9 @@ bool RifReaderInterface::isNNCsEnabled()
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RifReaderInterface::isSkipWellData() bool RifReaderInterface::loadWellDataEnabled()
{ {
return readerSettings()->skipWellData; return !readerSettings()->skipWellData;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -56,7 +56,7 @@ public:
bool isImportOfCompleteMswDataEnabled(); bool isImportOfCompleteMswDataEnabled();
bool isNNCsEnabled(); bool isNNCsEnabled();
bool includeInactiveCellsInFaultGeometry(); bool includeInactiveCellsInFaultGeometry();
bool isSkipWellData(); bool loadWellDataEnabled();
const QString faultIncludeFileAbsolutePathPrefix(); const QString faultIncludeFileAbsolutePathPrefix();
virtual bool open( const QString& fileName, RigEclipseCaseData* eclipseCase ) = 0; virtual bool open( const QString& fileName, RigEclipseCaseData* eclipseCase ) = 0;

File diff suppressed because it is too large Load Diff

View File

@ -21,13 +21,26 @@
#include "RifReaderInterface.h" #include "RifReaderInterface.h"
#include <memory> #include <memory>
#include <string>
#include <vector>
namespace Opm::EclIO namespace Opm::EclIO
{ {
class EInit; class EInit;
class ERst; class ERst;
class EGrid;
} // namespace Opm::EclIO } // namespace Opm::EclIO
class RigMainGrid;
class RigGridBase;
class RigEclipseCaseData;
class RigEclipseTimeStepInfo;
namespace caf
{
class ProgressInfo;
}
//================================================================================================== //==================================================================================================
// //
// //
@ -38,13 +51,31 @@ public:
RifReaderOpmCommon(); RifReaderOpmCommon();
~RifReaderOpmCommon() override; ~RifReaderOpmCommon() override;
bool open( const QString& fileName, RigEclipseCaseData* eclipseCase ) override; bool open( const QString& fileName, RigEclipseCaseData* caseData ) override;
bool staticResult( const QString& result, RiaDefines::PorosityModelType matrixOrFracture, std::vector<double>* values ) 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; bool dynamicResult( const QString& result, RiaDefines::PorosityModelType matrixOrFracture, size_t stepIndex, std::vector<double>* values ) override;
std::vector<QDateTime> timeStepsOnFile( QString gridFileName );
private: private:
void buildMetaData( RigEclipseCaseData* eclipseCase ); void buildMetaData( RigEclipseCaseData* caseData, caf::ProgressInfo& progress );
bool importGrid( RigMainGrid* mainGrid, RigEclipseCaseData* caseData );
void transferGeometry( Opm::EclIO::EGrid& opmMainGrid,
Opm::EclIO::EGrid& opmGrid,
RigMainGrid* riMainGrid,
RigGridBase* riGrid,
RigEclipseCaseData* caseData,
size_t matrixActiveStartIndex,
size_t fractureActiveStartIndex );
void transferStaticNNCData( Opm::EclIO::EGrid& opmMainGrid, std::vector<Opm::EclIO::EGrid>& lgrGrids, RigMainGrid* mainGrid );
void transferDynamicNNCData( RigMainGrid* mainGrid );
void locateInitAndRestartFiles( QString gridFileName );
void setupInitAndRestartAccess();
std::vector<RigEclipseTimeStepInfo> createFilteredTimeStepInfos();
struct TimeDataFile struct TimeDataFile
{ {
@ -55,16 +86,18 @@ private:
double simulationTimeFromStart; double simulationTimeFromStart;
}; };
static std::vector<TimeDataFile> readTimeSteps( std::shared_ptr<Opm::EclIO::ERst> restartFile ); std::vector<TimeDataFile> readTimeSteps();
static void readWellCells( std::shared_ptr<Opm::EclIO::ERst> restartFile,
RigEclipseCaseData* eclipseCase,
const std::vector<QDateTime>& timeSteps );
private: private:
std::string m_gridFileName; std::string m_gridFileName;
std::string m_initFileName;
std::string m_restartFileName;
int m_gridUnit;
std::shared_ptr<Opm::EclIO::ERst> m_restartFile; RigEclipseCaseData* m_eclipseCaseData;
std::shared_ptr<Opm::EclIO::EInit> m_initFile;
std::vector<QDateTime> m_timeSteps; std::unique_ptr<Opm::EclIO::ERst> m_restartFile;
std::unique_ptr<Opm::EclIO::EInit> m_initFile;
std::vector<std::string> m_gridNames;
}; };

View File

@ -819,14 +819,17 @@ QString RimFlowCharacteristicsPlot::curveDataAsText() const
auto storageCapacityValues = a->second.m_storageCapFlowCapCurve.first; auto storageCapacityValues = a->second.m_storageCapFlowCapCurve.first;
auto flowCapacityValues = a->second.m_storageCapFlowCapCurve.second; auto flowCapacityValues = a->second.m_storageCapFlowCapCurve.second;
if ( storageCapacityValues.size() < 2 || flowCapacityValues.size() < 2 )
{
continue;
}
bool extrapolate = false; bool extrapolate = false;
std::vector<double> flowCapacitySamplingValues; std::vector<double> flowCapacitySamplingValues;
for ( const auto storageCapacity : storageCapacitySamplingValues ) for ( const auto storageCapacity : storageCapacitySamplingValues )
{ {
{ double flowCapacity = interpolate( storageCapacityValues, flowCapacityValues, storageCapacity, extrapolate );
double flowCapacity = interpolate( storageCapacityValues, flowCapacityValues, storageCapacity, extrapolate ); flowCapacitySamplingValues.push_back( flowCapacity );
flowCapacitySamplingValues.push_back( flowCapacity );
}
} }
auto dimensionLessTimeValues = a->second.m_dimensionlessTimeSweepEfficiencyCurve.first; auto dimensionLessTimeValues = a->second.m_dimensionlessTimeSweepEfficiencyCurve.first;

View File

@ -30,6 +30,7 @@
#include "RicfCommandObject.h" #include "RicfCommandObject.h"
#include "RifEclipseOutputFileTools.h" #include "RifEclipseOutputFileTools.h"
#include "RifEclipseRestartDataAccess.h"
#include "RifInputPropertyLoader.h" #include "RifInputPropertyLoader.h"
#include "RifReaderEclipseOutput.h" #include "RifReaderEclipseOutput.h"
#include "RifReaderEclipseRft.h" #include "RifReaderEclipseRft.h"
@ -109,6 +110,28 @@ bool RimEclipseResultCase::openEclipseGridFile()
return importGridAndResultMetaData( false ); return importGridAndResultMetaData( false );
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEclipseResultCase::showTimeStepFilterGUI()
{
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();
return true;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -137,56 +160,48 @@ bool RimEclipseResultCase::importGridAndResultMetaData( bool showTimeStepFilter
return false; return false;
} }
auto defaultReader = RiaPreferences::current()->gridModelReader(); auto readerType = RiaPreferences::current()->gridModelReader();
if ( defaultReader == RiaDefines::GridModelReader::RESDATA ) // opmcommon reader only reads EGRID
if ( !gridFileName().toLower().endsWith( ".egrid" ) )
{
readerType = RiaDefines::GridModelReader::RESDATA;
}
if ( readerType == RiaDefines::GridModelReader::RESDATA )
{ {
auto readerEclipseOutput = new RifReaderEclipseOutput(); auto readerEclipseOutput = new RifReaderEclipseOutput();
cvf::ref<RifEclipseRestartDataAccess> restartDataAccess = RifEclipseOutputFileTools::createDynamicResultAccess( gridFileName() ); cvf::ref<RifEclipseRestartDataAccess> restartDataAccess = RifEclipseOutputFileTools::createDynamicResultAccess( gridFileName() );
std::vector<QDateTime> timeSteps;
std::vector<double> daysSinceSimulationStart;
if ( restartDataAccess.notNull() )
{ {
std::vector<QDateTime> timeSteps; restartDataAccess->timeSteps( &timeSteps, &daysSinceSimulationStart );
std::vector<double> daysSinceSimulationStart;
if ( restartDataAccess.notNull() )
{
restartDataAccess->timeSteps( &timeSteps, &daysSinceSimulationStart );
}
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();
} }
m_timeStepFilter->setTimeStepsFromFile( timeSteps );
readerEclipseOutput->setFileDataAccess( restartDataAccess.p() ); readerEclipseOutput->setFileDataAccess( restartDataAccess.p() );
readerEclipseOutput->setTimeStepFilter( m_timeStepFilter->filteredTimeSteps() );
readerInterface = readerEclipseOutput; readerInterface = readerEclipseOutput;
} }
else else
{ {
readerInterface = new RifReaderOpmCommon; auto readerOpmCommon = new RifReaderOpmCommon();
std::vector<QDateTime> timeSteps = readerOpmCommon->timeStepsOnFile( gridFileName() );
m_timeStepFilter->setTimeStepsFromFile( timeSteps );
readerInterface = readerOpmCommon;
}
if ( showTimeStepFilter )
{
if ( !showTimeStepFilterGUI() ) return false;
readerInterface->setTimeStepFilter( m_timeStepFilter->filteredTimeSteps() );
} }
readerInterface->setFilenamesWithFaults( filesContainingFaults() ); readerInterface->setFilenamesWithFaults( filesContainingFaults() );

View File

@ -84,6 +84,7 @@ protected:
private: private:
void loadAndUpdateSourSimData(); void loadAndUpdateSourSimData();
void ensureRftDataIsImported(); void ensureRftDataIsImported();
bool showTimeStepFilterGUI();
cvf::ref<RifReaderInterface> createMockModel( QString modelName ); cvf::ref<RifReaderInterface> createMockModel( QString modelName );
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;

View File

@ -625,6 +625,11 @@ RigFlowDiagSolverInterface::FlowCharacteristicsResultFrame
return result; return result;
} }
if ( m_opmFlowDiagStaticData.isNull() )
{
return result;
}
std::vector<double> poreVolume; std::vector<double> poreVolume;
for ( size_t cellIndex : selected_cell_indices ) for ( size_t cellIndex : selected_cell_indices )
{ {

View File

@ -312,6 +312,21 @@ const RigGridBase* RigMainGrid::gridByIndex( size_t localGridIndex ) const
return m_localGrids[localGridIndex - 1].p(); return m_localGrids[localGridIndex - 1].p();
} }
//--------------------------------------------------------------------------------------------------
/// Returns the grid with the given name. Main Grid itself could be retreived by using name ""
//--------------------------------------------------------------------------------------------------
RigGridBase* RigMainGrid::gridByName( const std::string& name )
{
if ( name.empty() ) return this;
for ( auto& grid : m_localGrids )
{
if ( grid->gridName() == name ) return grid.p();
}
return nullptr;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -63,6 +63,7 @@ public:
RigGridBase* gridByIndex( size_t localGridIndex ); RigGridBase* gridByIndex( size_t localGridIndex );
const RigGridBase* gridByIndex( size_t localGridIndex ) const; const RigGridBase* gridByIndex( size_t localGridIndex ) const;
RigGridBase* gridById( int localGridId ); RigGridBase* gridById( int localGridId );
RigGridBase* gridByName( const std::string& name );
size_t totalTemporaryGridCellCount() const; size_t totalTemporaryGridCellCount() const;

View File

@ -65,8 +65,8 @@ void RigSimWellData::computeMappingFromResultTimeIndicesToWellTimeIndices( const
wellTimeStepIndex++; wellTimeStepIndex++;
} }
if ( wellTimeStepIndex < m_wellCellsTimeSteps.size() && if ( ( wellTimeStepIndex < m_wellCellsTimeSteps.size() ) &&
m_wellCellsTimeSteps[wellTimeStepIndex].timestamp() == simulationTimeSteps[resultTimeStepIndex] ) ( m_wellCellsTimeSteps[wellTimeStepIndex].timestamp() == simulationTimeSteps[resultTimeStepIndex] ) )
{ {
m_resultTimeStepIndexToWellTimeStepIndex[resultTimeStepIndex] = wellTimeStepIndex; m_resultTimeStepIndexToWellTimeStepIndex[resultTimeStepIndex] = wellTimeStepIndex;
} }

View File

@ -182,9 +182,9 @@
struct well_info_struct { struct well_info_struct {
std::map<std::string, well_ts_type*> wells; /* std::map of well_ts_type instances; indexed by well name. */ std::map<std::string, well_ts_type*> wells; /* std::map of well_ts_type instances; indexed by well name. */
std::vector<std::string> well_names; /* A list of all the well names. */ std::vector<std::string> well_names; /* A list of all the well names. */
const ecl_grid_type * grid; std::vector<std::string> grid_names; /* A list of all grid names, main grid is at index 0, lgrs at 1 and above, if any */
}; };
@ -193,39 +193,39 @@ struct well_info_struct {
it to resolve lgr names. it to resolve lgr names.
*/ */
well_info_type * well_info_alloc( const ecl_grid_type * grid) { well_info_type* well_info_alloc(const std::vector<std::string> grid_names) {
well_info_type * well_info = new well_info_type(); well_info_type* well_info = new well_info_type();
well_info->grid = grid; well_info->grid_names = grid_names;
return well_info; return well_info;
} }
bool well_info_has_well( well_info_type * well_info , const char * well_name ) { bool well_info_has_well(well_info_type* well_info, const char* well_name) {
const auto it = well_info->wells.find(well_name); const auto it = well_info->wells.find(well_name);
if (it == well_info->wells.end()) if (it == well_info->wells.end())
return false; return false;
return true; return true;
} }
well_ts_type * well_info_get_ts( const well_info_type * well_info , const char *well_name) { well_ts_type* well_info_get_ts(const well_info_type* well_info, const char* well_name) {
return well_info->wells.at( well_name ); return well_info->wells.at(well_name);
} }
static void well_info_add_new_ts( well_info_type * well_info , const char * well_name) { static void well_info_add_new_ts(well_info_type* well_info, const char* well_name) {
well_ts_type * well_ts = well_ts_alloc( well_name ) ; well_ts_type* well_ts = well_ts_alloc(well_name);
well_info->wells[well_name] = well_ts; well_info->wells[well_name] = well_ts;
well_info->well_names.push_back( well_name ); well_info->well_names.push_back(well_name);
} }
static void well_info_add_state( well_info_type * well_info , well_state_type * well_state) { static void well_info_add_state(well_info_type* well_info, well_state_type* well_state) {
const char * well_name = well_state_get_name( well_state ); const char* well_name = well_state_get_name(well_state);
if (!well_info_has_well( well_info , well_name)) if (!well_info_has_well(well_info, well_name))
well_info_add_new_ts( well_info , well_name ); well_info_add_new_ts(well_info, well_name);
{ {
well_ts_type * well_ts = well_info_get_ts( well_info , well_name ); well_ts_type* well_ts = well_info_get_ts(well_info, well_name);
well_ts_add_well( well_ts , well_state ); well_ts_add_well(well_ts, well_state);
} }
} }
@ -278,23 +278,23 @@ static void well_info_add_state( well_info_type * well_info , well_state_type *
*/ */
void well_info_add_wells2( well_info_type * well_info , ecl_file_view_type * rst_view , int report_nr, bool load_segment_information) { void well_info_add_wells2(well_info_type* well_info, ecl_file_view_type* rst_view, int report_nr, bool load_segment_information) {
bool close_stream = ecl_file_view_drop_flag( rst_view , ECL_FILE_CLOSE_STREAM ); bool close_stream = ecl_file_view_drop_flag(rst_view, ECL_FILE_CLOSE_STREAM);
ecl_rsthead_type * global_header = ecl_rsthead_alloc( rst_view , report_nr ); ecl_rsthead_type* global_header = ecl_rsthead_alloc(rst_view, report_nr);
int well_nr; int well_nr;
for (well_nr = 0; well_nr < global_header->nwells; well_nr++) { for (well_nr = 0; well_nr < global_header->nwells; well_nr++) {
well_state_type * well_state = well_state_alloc_from_file2( rst_view , well_info->grid , report_nr , well_nr , load_segment_information ); well_state_type* well_state = well_state_alloc_from_file2(rst_view, well_info->grid_names, report_nr, well_nr, load_segment_information);
if (well_state != NULL) if (well_state != NULL)
well_info_add_state( well_info , well_state ); well_info_add_state(well_info, well_state);
} }
ecl_rsthead_free( global_header ); ecl_rsthead_free(global_header);
if (close_stream) if (close_stream)
ecl_file_view_add_flag(rst_view, ECL_FILE_CLOSE_STREAM); ecl_file_view_add_flag(rst_view, ECL_FILE_CLOSE_STREAM);
} }
void well_info_add_wells( well_info_type * well_info , ecl_file_type * rst_file , int report_nr, bool load_segment_information) { void well_info_add_wells(well_info_type* well_info, ecl_file_type* rst_file, int report_nr, bool load_segment_information) {
well_info_add_wells2( well_info , ecl_file_get_active_view( rst_file ) , report_nr , load_segment_information ); well_info_add_wells2(well_info, ecl_file_get_active_view(rst_file), report_nr, load_segment_information);
} }
/** /**
@ -303,25 +303,25 @@ void well_info_add_wells( well_info_type * well_info , ecl_file_type * rst_file
not have the SEQNUM keyword. not have the SEQNUM keyword.
*/ */
void well_info_add_UNRST_wells2( well_info_type * well_info , ecl_file_view_type * rst_view, bool load_segment_information) { void well_info_add_UNRST_wells2(well_info_type* well_info, ecl_file_view_type* rst_view, bool load_segment_information) {
int num_blocks = ecl_file_view_get_num_named_kw( rst_view , SEQNUM_KW ); int num_blocks = ecl_file_view_get_num_named_kw(rst_view, SEQNUM_KW);
int block_nr; int block_nr;
for (block_nr = 0; block_nr < num_blocks; block_nr++) { for (block_nr = 0; block_nr < num_blocks; block_nr++) {
ecl_file_view_type * step_view = ecl_file_view_add_restart_view(rst_view, block_nr , -1 , -1 , -1 ); ecl_file_view_type* step_view = ecl_file_view_add_restart_view(rst_view, block_nr, -1, -1, -1);
const ecl_kw_type * seqnum_kw = ecl_file_view_iget_named_kw( step_view , SEQNUM_KW , 0); const ecl_kw_type* seqnum_kw = ecl_file_view_iget_named_kw(step_view, SEQNUM_KW, 0);
int report_nr = ecl_kw_iget_int( seqnum_kw , 0 ); int report_nr = ecl_kw_iget_int(seqnum_kw, 0);
ecl_file_transaction_type * t = ecl_file_view_start_transaction(rst_view); ecl_file_transaction_type* t = ecl_file_view_start_transaction(rst_view);
well_info_add_wells2( well_info , step_view , report_nr , load_segment_information ); well_info_add_wells2(well_info, step_view, report_nr, load_segment_information);
ecl_file_view_end_transaction(rst_view, t); ecl_file_view_end_transaction(rst_view, t);
} }
} }
void well_info_add_UNRST_wells( well_info_type * well_info , ecl_file_type * rst_file, bool load_segment_information) { void well_info_add_UNRST_wells(well_info_type* well_info, ecl_file_type* rst_file, bool load_segment_information) {
well_info_add_UNRST_wells2( well_info , ecl_file_get_global_view( rst_file ) , load_segment_information); well_info_add_UNRST_wells2(well_info, ecl_file_get_global_view(rst_file), load_segment_information);
} }
@ -331,71 +331,72 @@ void well_info_add_UNRST_wells( well_info_type * well_info , ecl_file_type * rst
have crash and burn. have crash and burn.
*/ */
void well_info_load_rstfile( well_info_type * well_info , const char * filename, bool load_segment_information) { void well_info_load_rstfile(well_info_type* well_info, const char* filename, bool load_segment_information) {
ecl_file_type * ecl_file = ecl_file_open( filename , 0); ecl_file_type* ecl_file = ecl_file_open(filename, 0);
well_info_load_rst_eclfile(well_info, ecl_file, load_segment_information); well_info_load_rst_eclfile(well_info, ecl_file, load_segment_information);
ecl_file_close( ecl_file ); ecl_file_close(ecl_file);
} }
void well_info_load_rst_eclfile( well_info_type * well_info , ecl_file_type * ecl_file, bool load_segment_information) { void well_info_load_rst_eclfile(well_info_type* well_info, ecl_file_type* ecl_file, bool load_segment_information) {
int report_nr; int report_nr;
const char* filename = ecl_file_get_src_file(ecl_file); const char* filename = ecl_file_get_src_file(ecl_file);
ecl_file_enum file_type = ecl_util_get_file_type( filename , NULL , &report_nr); ecl_file_enum file_type = ecl_util_get_file_type(filename, NULL, &report_nr);
if ((file_type == ECL_RESTART_FILE) || (file_type == ECL_UNIFIED_RESTART_FILE)) if ((file_type == ECL_RESTART_FILE) || (file_type == ECL_UNIFIED_RESTART_FILE))
{ {
if (file_type == ECL_RESTART_FILE) if (file_type == ECL_RESTART_FILE)
well_info_add_wells( well_info , ecl_file , report_nr , load_segment_information ); well_info_add_wells(well_info, ecl_file, report_nr, load_segment_information);
else
well_info_add_UNRST_wells(well_info, ecl_file, load_segment_information);
}
else else
well_info_add_UNRST_wells( well_info , ecl_file , load_segment_information ); util_abort("%s: invalid file type: %s - must be a restart file\n", __func__, filename);
} else
util_abort("%s: invalid file type: %s - must be a restart file\n", __func__ , filename);
} }
void well_info_free( well_info_type * well_info ) { void well_info_free(well_info_type* well_info) {
for (const auto& pair : well_info->wells) for (const auto& pair : well_info->wells)
well_ts_free(pair.second); well_ts_free(pair.second);
delete well_info; delete well_info;
} }
int well_info_get_well_size( const well_info_type * well_info , const char * well_name ) { int well_info_get_well_size(const well_info_type* well_info, const char* well_name) {
well_ts_type * well_ts = well_info_get_ts( well_info , well_name ); well_ts_type* well_ts = well_info_get_ts(well_info, well_name);
return well_ts_get_size( well_ts ); return well_ts_get_size(well_ts);
} }
/*****************************************************************/ /*****************************************************************/
well_state_type * well_info_get_state_from_time( const well_info_type * well_info , const char * well_name , time_t sim_time) { well_state_type* well_info_get_state_from_time(const well_info_type* well_info, const char* well_name, time_t sim_time) {
well_ts_type * well_ts = well_info_get_ts( well_info , well_name ); well_ts_type* well_ts = well_info_get_ts(well_info, well_name);
return well_ts_get_state_from_sim_time( well_ts , sim_time ); return well_ts_get_state_from_sim_time(well_ts, sim_time);
} }
well_state_type * well_info_get_state_from_report( const well_info_type * well_info , const char * well_name , int report_step ) { well_state_type* well_info_get_state_from_report(const well_info_type* well_info, const char* well_name, int report_step) {
well_ts_type * well_ts = well_info_get_ts( well_info , well_name ); well_ts_type* well_ts = well_info_get_ts(well_info, well_name);
return well_ts_get_state_from_report( well_ts , report_step); return well_ts_get_state_from_report(well_ts, report_step);
} }
well_state_type * well_info_iget_state( const well_info_type * well_info , const char * well_name , int time_index) { well_state_type* well_info_iget_state(const well_info_type* well_info, const char* well_name, int time_index) {
well_ts_type * well_ts = well_info_get_ts( well_info , well_name ); well_ts_type* well_ts = well_info_get_ts(well_info, well_name);
return well_ts_iget_state( well_ts , time_index); return well_ts_iget_state(well_ts, time_index);
} }
well_state_type * well_info_iiget_state( const well_info_type * well_info , int well_index , int time_index) { well_state_type* well_info_iiget_state(const well_info_type* well_info, int well_index, int time_index) {
const std::string& well_name = well_info->well_names[well_index]; const std::string& well_name = well_info->well_names[well_index];
return well_info_iget_state( well_info , well_name.c_str() , time_index ); return well_info_iget_state(well_info, well_name.c_str(), time_index);
} }
/*****************************************************************/ /*****************************************************************/
int well_info_get_num_wells( const well_info_type * well_info ) { int well_info_get_num_wells(const well_info_type* well_info) {
return well_info->well_names.size(); return well_info->well_names.size();
} }
const char * well_info_iget_well_name( const well_info_type * well_info, int well_index) { const char* well_info_iget_well_name(const well_info_type* well_info, int well_index) {
const std::string& well_name = well_info->well_names[well_index]; const std::string& well_name = well_info->well_names[well_index];
return well_name.c_str(); return well_name.c_str();
} }

View File

@ -167,158 +167,158 @@ coupledte implementation these objects are modelled as such:
#define WELL_STATE_TYPE_ID 613307832 #define WELL_STATE_TYPE_ID 613307832
struct well_state_struct { struct well_state_struct {
UTIL_TYPE_ID_DECLARATION; UTIL_TYPE_ID_DECLARATION;
std::string name; std::string name;
time_t valid_from_time; time_t valid_from_time;
int valid_from_report; int valid_from_report;
int global_well_nr; int global_well_nr;
bool open; bool open;
well_type_enum type; well_type_enum type;
bool is_MSW_well; bool is_MSW_well;
double oil_rate; double oil_rate;
double gas_rate; double gas_rate;
double water_rate; double water_rate;
double volume_rate; double volume_rate;
ert_ecl_unit_enum unit_system; ert_ecl_unit_enum unit_system;
std::map<std::string, well_conn_collection_type*> connections; // hash<grid_name,well_conn_collection>
well_segment_collection_type * segments;
well_branch_collection_type * branches;
/*****************************************************************/ std::map<std::string, well_conn_collection_type*> connections; // hash<grid_name,well_conn_collection>
well_segment_collection_type* segments;
std::vector<well_conn_type*> index_wellhead; // An well_conn_type instance representing the wellhead - indexed by grid_nr. well_branch_collection_type* branches;
std::map<std::string, well_conn_type*> name_wellhead; // An well_conn_type instance representing the wellhead - indexed by lgr_name.
/*****************************************************************/
std::vector<well_conn_type*> index_wellhead; // An well_conn_type instance representing the wellhead - indexed by grid_nr.
std::map<std::string, well_conn_type*> name_wellhead; // An well_conn_type instance representing the wellhead - indexed by lgr_name.
}; };
UTIL_IS_INSTANCE_FUNCTION( well_state , WELL_STATE_TYPE_ID) UTIL_IS_INSTANCE_FUNCTION(well_state, WELL_STATE_TYPE_ID)
well_state_type * well_state_alloc(const char * well_name , int global_well_nr , bool open, well_type_enum type , int report_nr, time_t valid_from) { well_state_type* well_state_alloc(const char* well_name, int global_well_nr, bool open, well_type_enum type, int report_nr, time_t valid_from) {
well_state_type * well_state = new well_state_type(); well_state_type* well_state = new well_state_type();
UTIL_TYPE_ID_INIT( well_state , WELL_STATE_TYPE_ID ); UTIL_TYPE_ID_INIT(well_state, WELL_STATE_TYPE_ID);
well_state->name = well_name; well_state->name = well_name;
well_state->valid_from_time = valid_from; well_state->valid_from_time = valid_from;
well_state->valid_from_report = report_nr; well_state->valid_from_report = report_nr;
well_state->open = open; well_state->open = open;
well_state->type = type; well_state->type = type;
well_state->global_well_nr = global_well_nr; well_state->global_well_nr = global_well_nr;
well_state->segments = well_segment_collection_alloc(); well_state->segments = well_segment_collection_alloc();
well_state->branches = well_branch_collection_alloc(); well_state->branches = well_branch_collection_alloc();
well_state->is_MSW_well = false; well_state->is_MSW_well = false;
well_state->oil_rate = 0; well_state->oil_rate = 0;
well_state->gas_rate = 0; well_state->gas_rate = 0;
well_state->water_rate = 0; well_state->water_rate = 0;
well_state->volume_rate = 0; well_state->volume_rate = 0;
well_state->unit_system = ECL_METRIC_UNITS; well_state->unit_system = ECL_METRIC_UNITS;
/* See documentation of the 'IWEL_UNDOCUMENTED_ZERO' in well_const.h */ /* See documentation of the 'IWEL_UNDOCUMENTED_ZERO' in well_const.h */
if ((type == ECL_WELL_ZERO) && open) if ((type == ECL_WELL_ZERO) && open)
util_abort("%s: Invalid type value for open wells.\n",__func__ ); util_abort("%s: Invalid type value for open wells.\n", __func__);
return well_state; return well_state;
} }
double well_state_get_oil_rate( const well_state_type * well_state ) { double well_state_get_oil_rate(const well_state_type* well_state) {
return well_state->oil_rate; return well_state->oil_rate;
} }
double well_state_get_gas_rate( const well_state_type * well_state ) { double well_state_get_gas_rate(const well_state_type* well_state) {
return well_state->gas_rate; return well_state->gas_rate;
} }
double well_state_get_water_rate( const well_state_type * well_state) { double well_state_get_water_rate(const well_state_type* well_state) {
return well_state->water_rate; return well_state->water_rate;
} }
double well_state_get_volume_rate( const well_state_type * well_state) { double well_state_get_volume_rate(const well_state_type* well_state) {
return well_state->volume_rate; return well_state->volume_rate;
} }
double well_state_get_oil_rate_si( const well_state_type * well_state ) { double well_state_get_oil_rate_si(const well_state_type* well_state) {
double conversion_factor = 1; double conversion_factor = 1;
if (well_state->unit_system == ECL_METRIC_UNITS) if (well_state->unit_system == ECL_METRIC_UNITS)
conversion_factor = 1.0 / ECL_UNITS_TIME_DAY; conversion_factor = 1.0 / ECL_UNITS_TIME_DAY;
else if (well_state->unit_system == ECL_FIELD_UNITS) else if (well_state->unit_system == ECL_FIELD_UNITS)
conversion_factor = ECL_UNITS_VOLUME_BARREL / ECL_UNITS_TIME_DAY; conversion_factor = ECL_UNITS_VOLUME_BARREL / ECL_UNITS_TIME_DAY;
else if (well_state->unit_system == ECL_LAB_UNITS) else if (well_state->unit_system == ECL_LAB_UNITS)
conversion_factor = ECL_UNITS_VOLUME_MILLI_LITER / ECL_UNITS_TIME_HOUR; conversion_factor = ECL_UNITS_VOLUME_MILLI_LITER / ECL_UNITS_TIME_HOUR;
return well_state->oil_rate * conversion_factor; return well_state->oil_rate * conversion_factor;
} }
double well_state_get_gas_rate_si( const well_state_type * well_state ) { double well_state_get_gas_rate_si(const well_state_type* well_state) {
double conversion_factor = 1; double conversion_factor = 1;
if (well_state->unit_system == ECL_METRIC_UNITS) if (well_state->unit_system == ECL_METRIC_UNITS)
conversion_factor = 1.0 / ECL_UNITS_TIME_DAY; conversion_factor = 1.0 / ECL_UNITS_TIME_DAY;
else if (well_state->unit_system == ECL_FIELD_UNITS) else if (well_state->unit_system == ECL_FIELD_UNITS)
conversion_factor = ECL_UNITS_VOLUME_GAS_FIELD / ECL_UNITS_TIME_DAY; conversion_factor = ECL_UNITS_VOLUME_GAS_FIELD / ECL_UNITS_TIME_DAY;
else if (well_state->unit_system == ECL_LAB_UNITS) else if (well_state->unit_system == ECL_LAB_UNITS)
conversion_factor = ECL_UNITS_VOLUME_MILLI_LITER / ECL_UNITS_TIME_HOUR; conversion_factor = ECL_UNITS_VOLUME_MILLI_LITER / ECL_UNITS_TIME_HOUR;
return well_state->gas_rate * conversion_factor; return well_state->gas_rate * conversion_factor;
} }
double well_state_get_water_rate_si( const well_state_type * well_state) { double well_state_get_water_rate_si(const well_state_type* well_state) {
double conversion_factor = 1; double conversion_factor = 1;
if (well_state->unit_system == ECL_METRIC_UNITS) if (well_state->unit_system == ECL_METRIC_UNITS)
conversion_factor = 1.0 / ECL_UNITS_TIME_DAY; conversion_factor = 1.0 / ECL_UNITS_TIME_DAY;
else if (well_state->unit_system == ECL_FIELD_UNITS) else if (well_state->unit_system == ECL_FIELD_UNITS)
conversion_factor = ECL_UNITS_VOLUME_BARREL / ECL_UNITS_TIME_DAY; conversion_factor = ECL_UNITS_VOLUME_BARREL / ECL_UNITS_TIME_DAY;
else if (well_state->unit_system == ECL_LAB_UNITS) else if (well_state->unit_system == ECL_LAB_UNITS)
conversion_factor = ECL_UNITS_VOLUME_MILLI_LITER / ECL_UNITS_TIME_HOUR; conversion_factor = ECL_UNITS_VOLUME_MILLI_LITER / ECL_UNITS_TIME_HOUR;
return well_state->water_rate * conversion_factor; return well_state->water_rate * conversion_factor;
} }
double well_state_get_volume_rate_si( const well_state_type * well_state) { double well_state_get_volume_rate_si(const well_state_type* well_state) {
return well_state->volume_rate; return well_state->volume_rate;
} }
void well_state_add_wellhead( well_state_type * well_state , const ecl_rsthead_type * header , const ecl_kw_type * iwel_kw , int well_nr , const char * grid_name , int grid_nr) { void well_state_add_wellhead(well_state_type* well_state, const ecl_rsthead_type* header, const ecl_kw_type* iwel_kw, int well_nr, const char* grid_name, int grid_nr) {
well_conn_type * wellhead = well_conn_alloc_wellhead( iwel_kw , header , well_nr ); well_conn_type* wellhead = well_conn_alloc_wellhead(iwel_kw, header, well_nr);
if (wellhead != NULL) { if (wellhead != NULL) {
if (grid_nr >= static_cast<int>(well_state->index_wellhead.size())) if (grid_nr >= static_cast<int>(well_state->index_wellhead.size()))
well_state->index_wellhead.resize(grid_nr+1, NULL); well_state->index_wellhead.resize(grid_nr + 1, NULL);
well_state->index_wellhead[grid_nr] = wellhead; well_state->index_wellhead[grid_nr] = wellhead;
well_state->name_wellhead[grid_name] = wellhead; well_state->name_wellhead[grid_name] = wellhead;
} }
} }
static bool well_state_add_rates( well_state_type * well_state , static bool well_state_add_rates(well_state_type* well_state,
ecl_file_view_type * rst_view , ecl_file_view_type* rst_view,
int well_nr) { int well_nr) {
bool has_xwel_kw = ecl_file_view_has_kw(rst_view, XWEL_KW); bool has_xwel_kw = ecl_file_view_has_kw(rst_view, XWEL_KW);
if (has_xwel_kw) { if (has_xwel_kw) {
const ecl_kw_type *xwel_kw = ecl_file_view_iget_named_kw(rst_view, XWEL_KW, 0); const ecl_kw_type* xwel_kw = ecl_file_view_iget_named_kw(rst_view, XWEL_KW, 0);
ecl_rsthead_type *header = ecl_rsthead_alloc(rst_view, -1); ecl_rsthead_type* header = ecl_rsthead_alloc(rst_view, -1);
int offset = header->nxwelz * well_nr; int offset = header->nxwelz * well_nr;
well_state->unit_system = header->unit_system; well_state->unit_system = header->unit_system;
well_state->oil_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RES_ORAT_ITEM); well_state->oil_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RES_ORAT_ITEM);
well_state->gas_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RES_GRAT_ITEM); well_state->gas_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RES_GRAT_ITEM);
well_state->water_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RES_WRAT_ITEM); well_state->water_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RES_WRAT_ITEM);
well_state->volume_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RESV_ITEM); well_state->volume_rate = ecl_kw_iget_double(xwel_kw, offset + XWEL_RESV_ITEM);
ecl_rsthead_free(header); ecl_rsthead_free(header);
} }
return has_xwel_kw; return has_xwel_kw;
} }
@ -332,69 +332,69 @@ static bool well_state_add_rates( well_state_type * well_state ,
all. all.
*/ */
static int well_state_get_lgr_well_nr( const well_state_type * well_state , const ecl_file_view_type * file_view) { static int well_state_get_lgr_well_nr(const well_state_type* well_state, const ecl_file_view_type* file_view) {
int well_nr = -1; int well_nr = -1;
if (ecl_file_view_has_kw( file_view , ZWEL_KW)) { if (ecl_file_view_has_kw(file_view, ZWEL_KW)) {
ecl_rsthead_type * header = ecl_rsthead_alloc( file_view , -1); ecl_rsthead_type* header = ecl_rsthead_alloc(file_view, -1);
const ecl_kw_type * zwel_kw = ecl_file_view_iget_named_kw( file_view , ZWEL_KW , 0 ); const ecl_kw_type* zwel_kw = ecl_file_view_iget_named_kw(file_view, ZWEL_KW, 0);
int num_wells = header->nwells; int num_wells = header->nwells;
well_nr = 0; well_nr = 0;
while (true) { while (true) {
bool found = false; bool found = false;
{ {
char * lgr_well_name = (char*)util_alloc_strip_copy( (const char*)ecl_kw_iget_ptr( zwel_kw , well_nr * header->nzwelz) ); char* lgr_well_name = (char*)util_alloc_strip_copy((const char*)ecl_kw_iget_ptr(zwel_kw, well_nr * header->nzwelz));
if ( well_state->name == lgr_well_name) if (well_state->name == lgr_well_name)
found = true; found = true;
else else
well_nr++; well_nr++;
free( lgr_well_name ); free(lgr_well_name);
} }
if (found) if (found)
break; break;
else if (well_nr == num_wells) { else if (well_nr == num_wells) {
// The well is not in this LGR at all. // The well is not in this LGR at all.
well_nr = -1; well_nr = -1;
break; break;
} }
}
ecl_rsthead_free(header);
} }
ecl_rsthead_free( header ); return well_nr;
}
return well_nr;
} }
well_type_enum well_state_translate_ecl_type_int(int int_type) { well_type_enum well_state_translate_ecl_type_int(int int_type) {
well_type_enum type = ECL_WELL_ZERO; well_type_enum type = ECL_WELL_ZERO;
switch (int_type) { switch (int_type) {
/* See documentation of the 'IWEL_UNDOCUMENTED_ZERO' in well_const.h */ /* See documentation of the 'IWEL_UNDOCUMENTED_ZERO' in well_const.h */
case(IWEL_UNDOCUMENTED_ZERO): case(IWEL_UNDOCUMENTED_ZERO):
type = ECL_WELL_ZERO; type = ECL_WELL_ZERO;
break; break;
case(IWEL_PRODUCER): case(IWEL_PRODUCER):
type = ECL_WELL_PRODUCER; type = ECL_WELL_PRODUCER;
break; break;
case(IWEL_OIL_INJECTOR): case(IWEL_OIL_INJECTOR):
type = ECL_WELL_OIL_INJECTOR; type = ECL_WELL_OIL_INJECTOR;
break; break;
case(IWEL_GAS_INJECTOR): case(IWEL_GAS_INJECTOR):
type = ECL_WELL_GAS_INJECTOR; type = ECL_WELL_GAS_INJECTOR;
break; break;
case(IWEL_WATER_INJECTOR): case(IWEL_WATER_INJECTOR):
type = ECL_WELL_WATER_INJECTOR; type = ECL_WELL_WATER_INJECTOR;
break; break;
default: default:
// See https://github.com/OPM/ResInsight/issues/10493 // See https://github.com/OPM/ResInsight/issues/10493
// util_abort("%s: Invalid type value %d\n",__func__ , int_type); // util_abort("%s: Invalid type value %d\n",__func__ , int_type);
break; break;
} }
return type; return type;
} }
@ -404,215 +404,215 @@ well_type_enum well_state_translate_ecl_type_int(int int_type) {
to one LGR block with the ecl_file_subselect_block() function. to one LGR block with the ecl_file_subselect_block() function.
*/ */
static void well_state_add_connections__( well_state_type * well_state , static void well_state_add_connections__(well_state_type* well_state,
const ecl_file_view_type * rst_view , const ecl_file_view_type* rst_view,
const char * grid_name , const char* grid_name,
int grid_nr, int grid_nr,
int well_nr ) { int well_nr) {
ecl_rsthead_type * header = ecl_rsthead_alloc( rst_view , -1); ecl_rsthead_type* header = ecl_rsthead_alloc(rst_view, -1);
const ecl_kw_type * iwel_kw = ecl_file_view_iget_named_kw( rst_view , IWEL_KW , 0); const ecl_kw_type* iwel_kw = ecl_file_view_iget_named_kw(rst_view, IWEL_KW, 0);
well_state_add_wellhead( well_state , header , iwel_kw , well_nr , grid_name , grid_nr ); well_state_add_wellhead(well_state, header, iwel_kw, well_nr, grid_name, grid_nr);
if (ecl_file_view_has_kw(rst_view, ICON_KW)) { if (ecl_file_view_has_kw(rst_view, ICON_KW)) {
const ecl_kw_type * icon_kw = ecl_file_view_iget_named_kw( rst_view , ICON_KW , 0); const ecl_kw_type* icon_kw = ecl_file_view_iget_named_kw(rst_view, ICON_KW, 0);
if (!well_state_has_grid_connections( well_state , grid_name )) if (!well_state_has_grid_connections(well_state, grid_name))
well_state->connections[grid_name] = well_conn_collection_alloc(); well_state->connections[grid_name] = well_conn_collection_alloc();
{ {
ecl_kw_type * scon_kw = NULL; ecl_kw_type* scon_kw = NULL;
if (ecl_file_view_has_kw( rst_view , SCON_KW)) if (ecl_file_view_has_kw(rst_view, SCON_KW))
scon_kw = ecl_file_view_iget_named_kw( rst_view , SCON_KW , 0); scon_kw = ecl_file_view_iget_named_kw(rst_view, SCON_KW, 0);
ecl_kw_type * xcon_kw = NULL; ecl_kw_type* xcon_kw = NULL;
if (ecl_file_view_has_kw( rst_view , XCON_KW)) { if (ecl_file_view_has_kw(rst_view, XCON_KW)) {
xcon_kw = ecl_file_view_iget_named_kw(rst_view, XCON_KW, 0); xcon_kw = ecl_file_view_iget_named_kw(rst_view, XCON_KW, 0);
} }
well_conn_collection_type * wellcc = well_state->connections[grid_name]; well_conn_collection_type* wellcc = well_state->connections[grid_name];
well_conn_collection_load_from_kw( wellcc , iwel_kw , icon_kw , scon_kw, xcon_kw , well_nr , header ); well_conn_collection_load_from_kw(wellcc, iwel_kw, icon_kw, scon_kw, xcon_kw, well_nr, header);
}
}
ecl_rsthead_free( header );
}
static void well_state_add_global_connections( well_state_type * well_state ,
const ecl_file_view_type * rst_view ,
int well_nr ) {
well_state_add_connections__( well_state , rst_view , ECL_GRID_GLOBAL_GRID , 0 , well_nr );
}
static void well_state_add_LGR_connections(well_state_type * well_state,
const ecl_grid_type * grid,
ecl_file_view_type * file_view) {
// Go through all the LGRs and add connections; both in the bulk
// grid and as wellhead.
int num_lgr = ecl_grid_get_num_lgr( grid );
for (int lgr_index = 0; lgr_index < num_lgr; lgr_index++) {
ecl_file_view_type * lgr_view = ecl_file_view_add_blockview(file_view , LGR_KW , lgr_index);
/*
Even though the grid has LGR information the restart file is not required
to have corresponding LGR information. This has for a long time been
unchecked, and there might be bugs lurking based on the incorrect
assumption that if the grid has LGR information then the corresponding LGR
information can also be found in the restart file.
*/
if (lgr_view) {
const char * grid_name = ecl_grid_iget_lgr_name( grid , lgr_index );
int well_nr = well_state_get_lgr_well_nr( well_state , lgr_view );
if (well_nr >= 0)
well_state_add_connections__( well_state , lgr_view , grid_name , lgr_index + 1, well_nr );
}
}
}
void well_state_add_connections( well_state_type * well_state ,
const ecl_grid_type * grid ,
ecl_file_type * rst_file , // Either an open .Xnnnn file or UNRST file restricted to one report step
int well_nr) {
well_state_add_connections2(well_state , grid , ecl_file_get_active_view( rst_file ) , well_nr );
}
void well_state_add_connections2( well_state_type * well_state ,
const ecl_grid_type * grid ,
ecl_file_view_type * rst_view ,
int well_nr) {
well_state_add_global_connections( well_state , rst_view , well_nr );
well_state_add_LGR_connections( well_state , grid , rst_view);
}
bool well_state_add_MSW( well_state_type * well_state ,
ecl_file_type * rst_file ,
int well_nr,
bool load_segment_information) {
return well_state_add_MSW2( well_state , ecl_file_get_active_view(rst_file) , well_nr , load_segment_information );
}
bool well_state_add_MSW2( well_state_type * well_state ,
ecl_file_view_type * rst_view ,
int well_nr,
bool load_segment_information) {
if (ecl_file_view_has_kw( rst_view , ISEG_KW)) {
ecl_rsthead_type * rst_head = ecl_rsthead_alloc( rst_view , -1);
const ecl_kw_type * iwel_kw = ecl_file_view_iget_named_kw( rst_view , IWEL_KW , 0);
const ecl_kw_type * iseg_kw = ecl_file_view_iget_named_kw( rst_view , ISEG_KW , 0);
well_rseg_loader_type * rseg_loader = NULL;
int segment_count;
if (ecl_file_view_has_kw( rst_view , RSEG_KW )) {
if (load_segment_information)
rseg_loader = well_rseg_loader_alloc(rst_view);
segment_count = well_segment_collection_load_from_kw( well_state->segments ,
well_nr ,
iwel_kw ,
iseg_kw ,
rseg_loader ,
rst_head,
load_segment_information ,
&well_state->is_MSW_well);
if (segment_count > 0) {
auto it = well_state->connections.begin();
while (it != well_state->connections.end()) {
well_segment_collection_add_connections( well_state->segments , it->first.c_str() , it->second );
it++;
} }
well_segment_collection_link( well_state->segments );
well_segment_collection_add_branches( well_state->segments , well_state->branches );
}
ecl_rsthead_free( rst_head );
if (rseg_loader != NULL) {
well_rseg_loader_free(rseg_loader);
}
return true;
} }
} ecl_rsthead_free(header);
return false;
} }
bool well_state_is_MSW( const well_state_type * well_state) { static void well_state_add_global_connections(well_state_type* well_state,
return well_state->is_MSW_well; const ecl_file_view_type* rst_view,
int well_nr) {
well_state_add_connections__(well_state, rst_view, ECL_GRID_GLOBAL_GRID, 0, well_nr);
} }
bool well_state_has_segment_data(const well_state_type * well_state){ static void well_state_add_LGR_connections(well_state_type* well_state,
if (well_segment_collection_get_size( well_state->segments ) > 0) std::vector<std::string> grid_names,
return true; ecl_file_view_type* file_view) {
// Go through all the LGRs and add connections; both in the bulk
// grid and as wellhead.
int num_lgr = (int)(grid_names.size() - 1);
for (int lgr_index = 0; lgr_index < num_lgr; lgr_index++) {
ecl_file_view_type* lgr_view = ecl_file_view_add_blockview(file_view, LGR_KW, lgr_index);
/*
Even though the grid has LGR information the restart file is not required
to have corresponding LGR information. This has for a long time been
unchecked, and there might be bugs lurking based on the incorrect
assumption that if the grid has LGR information then the corresponding LGR
information can also be found in the restart file.
*/
if (lgr_view) {
int well_nr = well_state_get_lgr_well_nr(well_state, lgr_view);
if (well_nr >= 0)
well_state_add_connections__(well_state, lgr_view, grid_names[lgr_index + 1].c_str(), lgr_index + 1, well_nr);
}
}
}
void well_state_add_connections(well_state_type* well_state,
std::vector<std::string> grid_names,
ecl_file_type* rst_file, // Either an open .Xnnnn file or UNRST file restricted to one report step
int well_nr) {
well_state_add_connections2(well_state, grid_names, ecl_file_get_active_view(rst_file), well_nr);
}
void well_state_add_connections2(well_state_type* well_state,
std::vector<std::string> grid_names,
ecl_file_view_type* rst_view,
int well_nr) {
well_state_add_global_connections(well_state, rst_view, well_nr);
well_state_add_LGR_connections(well_state, grid_names, rst_view);
}
bool well_state_add_MSW(well_state_type* well_state,
ecl_file_type* rst_file,
int well_nr,
bool load_segment_information) {
return well_state_add_MSW2(well_state, ecl_file_get_active_view(rst_file), well_nr, load_segment_information);
}
bool well_state_add_MSW2(well_state_type* well_state,
ecl_file_view_type* rst_view,
int well_nr,
bool load_segment_information) {
if (ecl_file_view_has_kw(rst_view, ISEG_KW)) {
ecl_rsthead_type* rst_head = ecl_rsthead_alloc(rst_view, -1);
const ecl_kw_type* iwel_kw = ecl_file_view_iget_named_kw(rst_view, IWEL_KW, 0);
const ecl_kw_type* iseg_kw = ecl_file_view_iget_named_kw(rst_view, ISEG_KW, 0);
well_rseg_loader_type* rseg_loader = NULL;
int segment_count;
if (ecl_file_view_has_kw(rst_view, RSEG_KW)) {
if (load_segment_information)
rseg_loader = well_rseg_loader_alloc(rst_view);
segment_count = well_segment_collection_load_from_kw(well_state->segments,
well_nr,
iwel_kw,
iseg_kw,
rseg_loader,
rst_head,
load_segment_information,
&well_state->is_MSW_well);
if (segment_count > 0) {
auto it = well_state->connections.begin();
while (it != well_state->connections.end()) {
well_segment_collection_add_connections(well_state->segments, it->first.c_str(), it->second);
it++;
}
well_segment_collection_link(well_state->segments);
well_segment_collection_add_branches(well_state->segments, well_state->branches);
}
ecl_rsthead_free(rst_head);
if (rseg_loader != NULL) {
well_rseg_loader_free(rseg_loader);
}
return true;
}
}
return false;
}
bool well_state_is_MSW(const well_state_type* well_state) {
return well_state->is_MSW_well;
}
bool well_state_has_segment_data(const well_state_type* well_state) {
if (well_segment_collection_get_size(well_state->segments) > 0)
return true;
else else
return false; return false;
} }
well_state_type * well_state_alloc_from_file( ecl_file_type * ecl_file , const ecl_grid_type * grid , int report_nr , int global_well_nr ,bool load_segment_information) { well_state_type* well_state_alloc_from_file(ecl_file_type* ecl_file, std::vector<std::string> grid_names, int report_nr, int global_well_nr, bool load_segment_information) {
return well_state_alloc_from_file2( ecl_file_get_active_view( ecl_file ) , grid , report_nr , global_well_nr , load_segment_information); return well_state_alloc_from_file2(ecl_file_get_active_view(ecl_file), grid_names, report_nr, global_well_nr, load_segment_information);
} }
well_state_type * well_state_alloc_from_file2( ecl_file_view_type * file_view , const ecl_grid_type * grid , int report_nr , int global_well_nr ,bool load_segment_information) { well_state_type* well_state_alloc_from_file2(ecl_file_view_type* file_view, std::vector<std::string> grid_names, int report_nr, int global_well_nr, bool load_segment_information) {
if (ecl_file_view_has_kw( file_view , IWEL_KW)) { if (ecl_file_view_has_kw(file_view, IWEL_KW)) {
well_state_type * well_state = NULL; well_state_type* well_state = NULL;
ecl_rsthead_type * global_header = ecl_rsthead_alloc( file_view , -1); ecl_rsthead_type* global_header = ecl_rsthead_alloc(file_view, -1);
const ecl_kw_type * global_iwel_kw = ecl_file_view_iget_named_kw( file_view , IWEL_KW , 0); const ecl_kw_type* global_iwel_kw = ecl_file_view_iget_named_kw(file_view, IWEL_KW, 0);
const ecl_kw_type * global_zwel_kw = ecl_file_view_iget_named_kw( file_view , ZWEL_KW , 0); const ecl_kw_type* global_zwel_kw = ecl_file_view_iget_named_kw(file_view, ZWEL_KW, 0);
const int iwel_offset = global_header->niwelz * global_well_nr; const int iwel_offset = global_header->niwelz * global_well_nr;
{ {
char * name; char* name;
bool open; bool open;
well_type_enum type = ECL_WELL_ZERO; well_type_enum type = ECL_WELL_ZERO;
{ {
int int_state = ecl_kw_iget_int( global_iwel_kw , iwel_offset + IWEL_STATUS_INDEX ); int int_state = ecl_kw_iget_int(global_iwel_kw, iwel_offset + IWEL_STATUS_INDEX);
if (int_state > 0) if (int_state > 0)
open = true; open = true;
else else
open = false; open = false;
} }
{ {
int int_type = ecl_kw_iget_int( global_iwel_kw , iwel_offset + IWEL_TYPE_INDEX); int int_type = ecl_kw_iget_int(global_iwel_kw, iwel_offset + IWEL_TYPE_INDEX);
type = well_state_translate_ecl_type_int( int_type ); type = well_state_translate_ecl_type_int(int_type);
} }
{ {
const int zwel_offset = global_header->nzwelz * global_well_nr; const int zwel_offset = global_header->nzwelz * global_well_nr;
name = (char*)util_alloc_strip_copy((const char*)ecl_kw_iget_ptr( global_zwel_kw , zwel_offset )); // Hardwired max 8 characters in Well Name name = (char*)util_alloc_strip_copy((const char*)ecl_kw_iget_ptr(global_zwel_kw, zwel_offset)); // Hardwired max 8 characters in Well Name
} }
well_state = well_state_alloc(name , global_well_nr , open , type , report_nr , global_header->sim_time); well_state = well_state_alloc(name, global_well_nr, open, type, report_nr, global_header->sim_time);
free( name ); free(name);
well_state_add_connections2( well_state , grid , file_view , global_well_nr); well_state_add_connections2(well_state, grid_names, file_view, global_well_nr);
if (ecl_file_view_has_kw( file_view , ISEG_KW)) if (ecl_file_view_has_kw(file_view, ISEG_KW))
well_state_add_MSW2( well_state , file_view , global_well_nr , load_segment_information); well_state_add_MSW2(well_state, file_view, global_well_nr, load_segment_information);
well_state_add_rates(well_state, file_view, global_well_nr); well_state_add_rates(well_state, file_view, global_well_nr);
}
ecl_rsthead_free(global_header);
return well_state;
} }
ecl_rsthead_free( global_header ); else
return well_state; /* This seems a bit weird - have come over E300 restart files without the IWEL keyword. */
} else return NULL;
/* This seems a bit weird - have come over E300 restart files without the IWEL keyword. */
return NULL;
} }
@ -621,115 +621,115 @@ well_state_type * well_state_alloc_from_file2( ecl_file_view_type * file_view ,
void well_state_free( well_state_type * well ) { void well_state_free(well_state_type* well) {
for (size_t i = 0; i < well->index_wellhead.size(); i++) { for (size_t i = 0; i < well->index_wellhead.size(); i++) {
if (well->index_wellhead[i]) if (well->index_wellhead[i])
well_conn_free(well->index_wellhead[i]); well_conn_free(well->index_wellhead[i]);
} }
for (auto& pair : well->connections) for (auto& pair : well->connections)
well_conn_collection_free(pair.second); well_conn_collection_free(pair.second);
well_segment_collection_free( well->segments ); well_segment_collection_free(well->segments);
well_branch_collection_free( well->branches ); well_branch_collection_free(well->branches);
delete well; delete well;
} }
/*****************************************************************/ /*****************************************************************/
int well_state_get_report_nr( const well_state_type * well_state ) { int well_state_get_report_nr(const well_state_type* well_state) {
return well_state->valid_from_report; return well_state->valid_from_report;
} }
time_t well_state_get_sim_time( const well_state_type * well_state ) { time_t well_state_get_sim_time(const well_state_type* well_state) {
return well_state->valid_from_time; return well_state->valid_from_time;
} }
/** /**
Will return NULL if no wellhead in this grid. Will return NULL if no wellhead in this grid.
*/ */
const well_conn_type * well_state_iget_wellhead( const well_state_type * well_state , int grid_nr) { const well_conn_type* well_state_iget_wellhead(const well_state_type* well_state, int grid_nr) {
if (grid_nr < static_cast<int>(well_state->index_wellhead.size())) if (grid_nr < static_cast<int>(well_state->index_wellhead.size()))
return well_state->index_wellhead[grid_nr]; return well_state->index_wellhead[grid_nr];
else else
return NULL;
}
bool well_state_has_named_well_conn(const well_state_type* well_state, const char* grid_name) {
const auto it = well_state->name_wellhead.find(grid_name);
if (it == well_state->name_wellhead.end())
return false;
return true;
}
const well_conn_type* well_state_get_wellhead(const well_state_type* well_state, const char* grid_name) {
const auto it = well_state->name_wellhead.find(grid_name);
if (it != well_state->name_wellhead.end())
return it->second;
return NULL; return NULL;
} }
const well_conn_type* well_state_get_global_wellhead(const well_state_type* well_state) {
bool well_state_has_named_well_conn( const well_state_type * well_state , const char * grid_name ) { return well_state_get_wellhead(well_state, ECL_GRID_GLOBAL_GRID);
const auto it = well_state->name_wellhead.find( grid_name );
if (it == well_state->name_wellhead.end())
return false;
return true;
} }
const well_conn_type * well_state_get_wellhead( const well_state_type * well_state , const char * grid_name) { well_type_enum well_state_get_type(const well_state_type* well_state) {
const auto it = well_state->name_wellhead.find( grid_name ); return well_state->type;
if (it != well_state->name_wellhead.end())
return it->second;
return NULL;
} }
const well_conn_type * well_state_get_global_wellhead( const well_state_type * well_state ) { bool well_state_is_open(const well_state_type* well_state) {
return well_state_get_wellhead( well_state, ECL_GRID_GLOBAL_GRID ); return well_state->open;
}
int well_state_get_well_nr(const well_state_type* well_state) {
return well_state->global_well_nr;
} }
well_type_enum well_state_get_type( const well_state_type * well_state){ const char* well_state_get_name(const well_state_type* well_state) {
return well_state->type; return well_state->name.c_str();
}
bool well_state_is_open( const well_state_type * well_state ) {
return well_state->open;
}
int well_state_get_well_nr( const well_state_type * well_state ) {
return well_state->global_well_nr;
}
const char * well_state_get_name( const well_state_type * well_state ) {
return well_state->name.c_str();
} }
/*****************************************************************/ /*****************************************************************/
const well_conn_collection_type * well_state_get_grid_connections( const well_state_type * well_state , const char * grid_name) { const well_conn_collection_type* well_state_get_grid_connections(const well_state_type* well_state, const char* grid_name) {
if (well_state_has_grid_connections(well_state, grid_name) ) if (well_state_has_grid_connections(well_state, grid_name))
return well_state->connections.at(grid_name); return well_state->connections.at(grid_name);
else else
return NULL; return NULL;
} }
const well_conn_collection_type * well_state_get_global_connections( const well_state_type * well_state ) { const well_conn_collection_type* well_state_get_global_connections(const well_state_type* well_state) {
return well_state_get_grid_connections( well_state , ECL_GRID_GLOBAL_GRID ); return well_state_get_grid_connections(well_state, ECL_GRID_GLOBAL_GRID);
} }
bool well_state_has_grid_connections( const well_state_type * well_state , const char * grid_name) { bool well_state_has_grid_connections(const well_state_type* well_state, const char* grid_name) {
const auto it = well_state->connections.find(grid_name); const auto it = well_state->connections.find(grid_name);
if (it == well_state->connections.end()) if (it == well_state->connections.end())
return false; return false;
return true; return true;
} }
bool well_state_has_global_connections( const well_state_type * well_state ) { bool well_state_has_global_connections(const well_state_type* well_state) {
return well_state_has_grid_connections( well_state , ECL_GRID_GLOBAL_GRID ); return well_state_has_grid_connections(well_state, ECL_GRID_GLOBAL_GRID);
} }
well_segment_collection_type * well_state_get_segments( const well_state_type * well_state ) { well_segment_collection_type* well_state_get_segments(const well_state_type* well_state) {
return well_state->segments; return well_state->segments;
} }
well_branch_collection_type * well_state_get_branches( const well_state_type * well_state ) { well_branch_collection_type* well_state_get_branches(const well_state_type* well_state) {
return well_state->branches; return well_state->branches;
} }

View File

@ -30,26 +30,26 @@
extern "C" { extern "C" {
#endif #endif
typedef struct well_info_struct well_info_type; typedef struct well_info_struct well_info_type;
well_info_type * well_info_alloc(const ecl_grid_type * grid); well_info_type* well_info_alloc(std::vector<std::string> grid_names);
void well_info_add_UNRST_wells2( well_info_type * well_info , ecl_file_view_type * rst_view, bool load_segment_information); void well_info_add_UNRST_wells2(well_info_type* well_info, ecl_file_view_type* rst_view, bool load_segment_information);
void well_info_add_UNRST_wells( well_info_type * well_info , ecl_file_type * rst_file, bool load_segment_information); void well_info_add_UNRST_wells(well_info_type* well_info, ecl_file_type* rst_file, bool load_segment_information);
void well_info_add_wells( well_info_type * well_info , ecl_file_type * rst_file , int report_nr , bool load_segment_information); void well_info_add_wells(well_info_type* well_info, ecl_file_type* rst_file, int report_nr, bool load_segment_information);
void well_info_add_wells2( well_info_type * well_info , ecl_file_view_type * rst_view , int report_nr, bool load_segment_information); void well_info_add_wells2(well_info_type* well_info, ecl_file_view_type* rst_view, int report_nr, bool load_segment_information);
void well_info_load_rstfile( well_info_type * well_info , const char * filename, bool load_segment_information); void well_info_load_rstfile(well_info_type* well_info, const char* filename, bool load_segment_information);
void well_info_load_rst_eclfile( well_info_type * well_info , ecl_file_type * rst_file , bool load_segment_information); void well_info_load_rst_eclfile(well_info_type* well_info, ecl_file_type* rst_file, bool load_segment_information);
void well_info_free( well_info_type * well_info ); void well_info_free(well_info_type* well_info);
well_ts_type * well_info_get_ts( const well_info_type * well_info , const char *well_name); well_ts_type* well_info_get_ts(const well_info_type* well_info, const char* well_name);
int well_info_get_num_wells( const well_info_type * well_info ); int well_info_get_num_wells(const well_info_type* well_info);
const char * well_info_iget_well_name( const well_info_type * well_info, int well_index); const char* well_info_iget_well_name(const well_info_type* well_info, int well_index);
bool well_info_has_well( well_info_type * well_info , const char * well_name ); bool well_info_has_well(well_info_type* well_info, const char* well_name);
well_state_type * well_info_get_state_from_time( const well_info_type * well_info , const char * well_name , time_t sim_time); well_state_type* well_info_get_state_from_time(const well_info_type* well_info, const char* well_name, time_t sim_time);
well_state_type * well_info_get_state_from_report( const well_info_type * well_info , const char * well_name , int report_step ); well_state_type* well_info_get_state_from_report(const well_info_type* well_info, const char* well_name, int report_step);
well_state_type * well_info_iget_state( const well_info_type * well_info , const char * well_name , int time_index); well_state_type* well_info_iget_state(const well_info_type* well_info, const char* well_name, int time_index);
well_state_type * well_info_iiget_state( const well_info_type * well_info , int well_index , int time_index); well_state_type* well_info_iiget_state(const well_info_type* well_info, int well_index, int time_index);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -22,6 +22,8 @@
#include <time.h> #include <time.h>
#include <vector>
#include <string>
#include <ert/ecl/ecl_file.hpp> #include <ert/ecl/ecl_file.hpp>
#include <ert/ecl/ecl_grid.hpp> #include <ert/ecl/ecl_grid.hpp>
@ -38,72 +40,72 @@ extern "C" {
#define GLOBAL_GRID_NAME "GLOBAL" // The name assigned to the global grid for name based lookup. #define GLOBAL_GRID_NAME "GLOBAL" // The name assigned to the global grid for name based lookup.
typedef struct well_state_struct well_state_type; typedef struct well_state_struct well_state_type;
well_state_type * well_state_alloc(const char * well_name , int global_well_nr , bool open, well_type_enum type , int report_nr, time_t valid_from); well_state_type* well_state_alloc(const char* well_name, int global_well_nr, bool open, well_type_enum type, int report_nr, time_t valid_from);
well_state_type * well_state_alloc_from_file( ecl_file_type * ecl_file , const ecl_grid_type * grid , int report_step , int well_nr , bool load_segment_information); well_state_type* well_state_alloc_from_file(ecl_file_type* ecl_file, std::vector<std::string> grid_names, int report_step, int well_nr, bool load_segment_information);
well_state_type * well_state_alloc_from_file2( ecl_file_view_type * file_view , const ecl_grid_type * grid , int report_nr , int global_well_nr ,bool load_segment_information); well_state_type* well_state_alloc_from_file2(ecl_file_view_type* file_view, std::vector<std::string> grid_names, int report_nr, int global_well_nr, bool load_segment_information);
void well_state_add_connections2( well_state_type * well_state , void well_state_add_connections2(well_state_type* well_state,
const ecl_grid_type * grid , std::vector<std::string> grid_names,
ecl_file_view_type * rst_view , ecl_file_view_type* rst_view,
int well_nr); int well_nr);
void well_state_add_connections( well_state_type * well_state , void well_state_add_connections(well_state_type* well_state,
const ecl_grid_type * grid , std::vector<std::string> grid_names,
ecl_file_type * rst_file , ecl_file_type* rst_file,
int well_nr); int well_nr);
bool well_state_add_MSW( well_state_type * well_state , bool well_state_add_MSW(well_state_type* well_state,
ecl_file_type * rst_file , ecl_file_type* rst_file,
int well_nr, int well_nr,
bool load_segment_information); bool load_segment_information);
bool well_state_add_MSW2( well_state_type * well_state , bool well_state_add_MSW2(well_state_type* well_state,
ecl_file_view_type * rst_view, ecl_file_view_type* rst_view,
int well_nr, int well_nr,
bool load_segment_information); bool load_segment_information);
bool well_state_is_MSW( const well_state_type * well_state); bool well_state_is_MSW(const well_state_type* well_state);
bool well_state_has_segment_data(const well_state_type * well_state); bool well_state_has_segment_data(const well_state_type* well_state);
well_segment_collection_type * well_state_get_segments( const well_state_type * well_state ); well_segment_collection_type* well_state_get_segments(const well_state_type* well_state);
well_branch_collection_type * well_state_get_branches( const well_state_type * well_state ); well_branch_collection_type* well_state_get_branches(const well_state_type* well_state);
void well_state_free( well_state_type * well ); void well_state_free(well_state_type* well);
const char * well_state_get_name( const well_state_type * well ); const char* well_state_get_name(const well_state_type* well);
int well_state_get_report_nr( const well_state_type * well_state ); int well_state_get_report_nr(const well_state_type* well_state);
time_t well_state_get_sim_time( const well_state_type * well_state ); time_t well_state_get_sim_time(const well_state_type* well_state);
well_type_enum well_state_get_type( const well_state_type * well_state); well_type_enum well_state_get_type(const well_state_type* well_state);
bool well_state_is_open( const well_state_type * well_state ); bool well_state_is_open(const well_state_type* well_state);
int well_state_get_well_nr( const well_state_type * well_state ); int well_state_get_well_nr(const well_state_type* well_state);
const well_conn_type * well_state_get_global_wellhead( const well_state_type * well_state ); const well_conn_type* well_state_get_global_wellhead(const well_state_type* well_state);
const well_conn_type * well_state_iget_wellhead( const well_state_type * well_state , int grid_nr); const well_conn_type* well_state_iget_wellhead(const well_state_type* well_state, int grid_nr);
const well_conn_type * well_state_get_wellhead( const well_state_type * well_state , const char * grid_name); const well_conn_type* well_state_get_wellhead(const well_state_type* well_state, const char* grid_name);
well_type_enum well_state_translate_ecl_type_int(int int_type); well_type_enum well_state_translate_ecl_type_int(int int_type);
const well_conn_collection_type * well_state_get_grid_connections( const well_state_type * well_state , const char * grid_name); const well_conn_collection_type* well_state_get_grid_connections(const well_state_type* well_state, const char* grid_name);
const well_conn_collection_type * well_state_get_global_connections( const well_state_type * well_state ); const well_conn_collection_type* well_state_get_global_connections(const well_state_type* well_state);
bool well_state_has_grid_connections( const well_state_type * well_state , const char * grid_name); bool well_state_has_grid_connections(const well_state_type* well_state, const char* grid_name);
bool well_state_has_global_connections( const well_state_type * well_state ); bool well_state_has_global_connections(const well_state_type* well_state);
double well_state_get_oil_rate( const well_state_type * well_state ); double well_state_get_oil_rate(const well_state_type* well_state);
double well_state_get_gas_rate( const well_state_type * well_state ); double well_state_get_gas_rate(const well_state_type* well_state);
double well_state_get_water_rate( const well_state_type * well_state); double well_state_get_water_rate(const well_state_type* well_state);
double well_state_get_volume_rate( const well_state_type * well_state); double well_state_get_volume_rate(const well_state_type* well_state);
double well_state_get_water_rate_si( const well_state_type * well_state); double well_state_get_water_rate_si(const well_state_type* well_state);
double well_state_get_oil_rate_si( const well_state_type * well_state ); double well_state_get_oil_rate_si(const well_state_type* well_state);
double well_state_get_volume_rate_si( const well_state_type * well_state); double well_state_get_volume_rate_si(const well_state_type* well_state);
double well_state_get_gas_rate_si( const well_state_type * well_state ); double well_state_get_gas_rate_si(const well_state_type* well_state);
UTIL_IS_INSTANCE_HEADER( well_state ); UTIL_IS_INSTANCE_HEADER(well_state);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -1 +1 @@
Subproject commit a76421efffb45ae42831a5a5a8cc7e2bddbf5b8e Subproject commit ddbf77d5541eef7073d56991158aa63985309379