mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#7527 HDF Summary Reader : Add first working prototype
HDF5 must be compiled with special options to support multithreading. Disable file object multithreading for HDF5. Some vector types are not supported, as the support in opm-common reader is not complete (region, region_to_region, ...).
This commit is contained in:
parent
d082ce7eb1
commit
dd97e7741a
@ -81,6 +81,15 @@ void RiaPreferences::PageOrientationEnum::setUp()
|
||||
addItem( QPageLayout::Landscape, "LANDSCAPE", "Landscape" );
|
||||
setDefault( QPageLayout::Portrait );
|
||||
}
|
||||
|
||||
template <>
|
||||
void RiaPreferences::SummaryReaderModeType::setUp()
|
||||
{
|
||||
addItem( RiaPreferences::SummaryReaderMode::LIBECL, "LIBECL", "Default Reader (ecl)" );
|
||||
addItem( RiaPreferences::SummaryReaderMode::HDF5_OPM_COMMON, "HDF5_OPM_COMMON", "[BETA] H5 Reader (HDF5 Eclipse)" );
|
||||
addItem( RiaPreferences::SummaryReaderMode::OPM_COMMON, "OPM_COMMON", "[BETA] Performance Reader (omp-common)" );
|
||||
setDefault( RiaPreferences::SummaryReaderMode::LIBECL );
|
||||
}
|
||||
} // namespace caf
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RiaPreferences, "RiaPreferences" );
|
||||
@ -88,7 +97,7 @@ CAF_PDM_SOURCE_INIT( RiaPreferences, "RiaPreferences" );
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaPreferences::RiaPreferences( void )
|
||||
RiaPreferences::RiaPreferences()
|
||||
{
|
||||
CAF_PDM_InitField( &m_navigationPolicy,
|
||||
"navigationPolicy",
|
||||
@ -404,15 +413,6 @@ RiaPreferences::RiaPreferences( void )
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_guiTheme, "guiTheme", "GUI theme", "", "", "" );
|
||||
|
||||
CAF_PDM_InitField( &m_useOptimizedSummaryDataFileReader,
|
||||
"useOptimizedSummaryDataFileReader",
|
||||
false,
|
||||
"Use Optimized Summary Data Reader [BETA]",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
m_useOptimizedSummaryDataFileReader.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
|
||||
|
||||
CAF_PDM_InitField( &m_createOptimizedSummaryDataFile,
|
||||
"createOptimizedSummaryDataFile",
|
||||
true,
|
||||
@ -430,12 +430,14 @@ RiaPreferences::RiaPreferences( void )
|
||||
"If not present, read optimized file with extension '*.LODSMRY'",
|
||||
"" );
|
||||
m_useOptimizedSummaryDataFile.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_summaryReader, "summaryReaderType", "Summary Data File Reader", "", "", "" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaPreferences::~RiaPreferences( void )
|
||||
RiaPreferences::~RiaPreferences()
|
||||
{
|
||||
delete m_readerSettings;
|
||||
}
|
||||
@ -471,14 +473,14 @@ void RiaPreferences::defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
|
||||
if ( field == &octaveShowHeaderInfoWhenExecutingScripts || field == &autocomputeDepthRelatedProperties ||
|
||||
field == &loadAndShowSoil || field == &m_useShaders || field == &m_showHud ||
|
||||
field == &m_appendClassNameToUiText || field == &m_appendFieldKeywordToToolTipText || field == &m_showTestToolbar ||
|
||||
field == &m_includeFractureDebugInfoFile || field == &showLasCurveWithoutTvdWarning ||
|
||||
field == &holoLensDisableCertificateVerification || field == &m_showProjectChangedDialog ||
|
||||
field == &m_searchPlotTemplateFoldersRecursively || field == &m_showLegendBackground ||
|
||||
field == &m_showSummaryTimeAsLongString || field == &m_showViewIdInProjectTree ||
|
||||
field == &m_useMultipleThreadsWhenLoadingSummaryData || field == &m_enableFaultsByDefault ||
|
||||
field == &m_showProgressBar || field == &m_openExportedPdfInViewer || field == &m_showInfoBox ||
|
||||
field == &m_showGridBox || field == &m_useUndoRedo || field == &m_useOptimizedSummaryDataFileReader ||
|
||||
field == &m_appendClassNameToUiText || field == &m_appendFieldKeywordToToolTipText ||
|
||||
field == &m_showTestToolbar || field == &m_includeFractureDebugInfoFile ||
|
||||
field == &showLasCurveWithoutTvdWarning || field == &holoLensDisableCertificateVerification ||
|
||||
field == &m_showProjectChangedDialog || field == &m_searchPlotTemplateFoldersRecursively ||
|
||||
field == &m_showLegendBackground || field == &m_showSummaryTimeAsLongString ||
|
||||
field == &m_showViewIdInProjectTree || field == &m_useMultipleThreadsWhenLoadingSummaryData ||
|
||||
field == &m_enableFaultsByDefault || field == &m_showProgressBar || field == &m_openExportedPdfInViewer ||
|
||||
field == &m_showInfoBox || field == &m_showGridBox || field == &m_useUndoRedo ||
|
||||
field == &m_createOptimizedSummaryDataFile || field == &m_useOptimizedSummaryDataFile )
|
||||
{
|
||||
caf::PdmUiCheckBoxEditorAttribute* myAttr = dynamic_cast<caf::PdmUiCheckBoxEditorAttribute*>( attribute );
|
||||
@ -608,13 +610,13 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering&
|
||||
{
|
||||
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "[BETA] Optimized Summary Reader" );
|
||||
group->setCollapsedByDefault( true );
|
||||
group->add( &m_useOptimizedSummaryDataFileReader );
|
||||
group->add( &m_summaryReader );
|
||||
|
||||
if ( m_summaryReader == SummaryReaderMode::OPM_COMMON )
|
||||
{
|
||||
group->add( &m_createOptimizedSummaryDataFile );
|
||||
group->add( &m_useOptimizedSummaryDataFile );
|
||||
|
||||
m_createOptimizedSummaryDataFile.uiCapability()->setUiReadOnly( !m_useOptimizedSummaryDataFileReader );
|
||||
m_useOptimizedSummaryDataFile.uiCapability()->setUiReadOnly( !m_useOptimizedSummaryDataFileReader );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -727,7 +729,21 @@ QList<caf::PdmOptionItemInfo> RiaPreferences::calculateValueOptions( const caf::
|
||||
options.push_back( caf::PdmOptionItemInfo( uiText, QVariant::fromValue( timeFormat ) ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_summaryReader )
|
||||
{
|
||||
std::vector<SummaryReaderMode> availableModes;
|
||||
|
||||
availableModes.push_back( SummaryReaderMode::LIBECL );
|
||||
#ifdef USE_HDF5
|
||||
availableModes.push_back( SummaryReaderMode::HDF5_OPM_COMMON );
|
||||
#endif // USE_HDF5
|
||||
availableModes.push_back( SummaryReaderMode::OPM_COMMON );
|
||||
|
||||
for ( auto enumValue : availableModes )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( SummaryReaderModeType::uiText( enumValue ), enumValue ) );
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -1214,9 +1230,9 @@ QString RiaPreferences::octaveExecutable() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RiaPreferences::useOptimizedSummaryDataReader() const
|
||||
RiaPreferences::SummaryReaderMode RiaPreferences::summaryDataReader() const
|
||||
{
|
||||
return m_useOptimizedSummaryDataFileReader();
|
||||
return m_summaryReader();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -1224,7 +1240,7 @@ bool RiaPreferences::useOptimizedSummaryDataReader() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RiaPreferences::useOptimizedSummaryDataFiles() const
|
||||
{
|
||||
return m_useOptimizedSummaryDataFileReader();
|
||||
return m_useOptimizedSummaryDataFile();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -70,6 +70,14 @@ public:
|
||||
};
|
||||
typedef caf::AppEnum<SummaryHistoryCurveStyleMode> SummaryHistoryCurveStyleModeType;
|
||||
|
||||
enum class SummaryReaderMode
|
||||
{
|
||||
LIBECL,
|
||||
OPM_COMMON,
|
||||
HDF5_OPM_COMMON
|
||||
};
|
||||
typedef caf::AppEnum<SummaryReaderMode> SummaryReaderModeType;
|
||||
|
||||
typedef caf::AppEnum<QPageSize::PageSizeId> PageSizeEnum;
|
||||
typedef caf::AppEnum<QPageLayout::Orientation> PageOrientationEnum;
|
||||
|
||||
@ -139,7 +147,7 @@ public:
|
||||
QString octaveExecutable() const;
|
||||
|
||||
// Summary readers
|
||||
bool useOptimizedSummaryDataReader() const;
|
||||
SummaryReaderMode summaryDataReader() const;
|
||||
bool useOptimizedSummaryDataFiles() const;
|
||||
bool createOptimizedSummaryDataFiles() const;
|
||||
|
||||
@ -249,10 +257,11 @@ private:
|
||||
caf::PdmField<QString> m_multiLateralWellPattern;
|
||||
|
||||
// Summary data
|
||||
caf::PdmField<bool> m_useOptimizedSummaryDataFileReader;
|
||||
caf::PdmField<bool> m_createOptimizedSummaryDataFile;
|
||||
caf::PdmField<bool> m_useOptimizedSummaryDataFile;
|
||||
|
||||
caf::PdmField<SummaryReaderModeType> m_summaryReader;
|
||||
|
||||
// 3d view
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::MeshModeType>> m_defaultMeshModeType;
|
||||
caf::PdmField<caf::AppEnum<RiaGuiApplication::RINavigationPolicy>> m_navigationPolicy;
|
||||
|
@ -231,8 +231,15 @@ list(APPEND RI_LIBRARIES RigGeoMechDataModel)
|
||||
# HDF5
|
||||
#
|
||||
if(RESINSIGHT_FOUND_HDF5)
|
||||
list(APPEND CPP_SOURCES FileInterface/RifHdf5Reader.h
|
||||
FileInterface/RifHdf5Reader.cpp)
|
||||
list(
|
||||
APPEND
|
||||
CPP_SOURCES
|
||||
FileInterface/RifHdf5Reader.h
|
||||
FileInterface/RifHdf5Reader.cpp
|
||||
FileInterface/RifHdf5SummaryReader.h
|
||||
FileInterface/RifHdf5SummaryReader.cpp
|
||||
FileInterface/RifOpmHdf5Summary.h
|
||||
FileInterface/RifOpmHdf5Summary.cpp)
|
||||
|
||||
add_definitions(-DUSE_HDF5)
|
||||
|
||||
@ -247,8 +254,15 @@ if(RESINSIGHT_FOUND_HDF5)
|
||||
include_directories(${HDF5_INCLUDE_DIRS})
|
||||
endif() # MSVC
|
||||
|
||||
source_group("FileInterface" FILES FileInterface/RifHdf5Reader.h
|
||||
FileInterface/RifHdf5Reader.cpp)
|
||||
source_group(
|
||||
"FileInterface"
|
||||
FILES FileInterface/RifHdf5Reader.h
|
||||
FileInterface/RifHdf5Reader.cpp
|
||||
FileInterface/RifHdf5SummaryReader.h
|
||||
FileInterface/RifHdf5SummaryReader.cpp
|
||||
FileInterface/RifOpmHdf5Summary.h
|
||||
FileInterface/RifOpmHdf5Summary.cpp)
|
||||
|
||||
endif()
|
||||
|
||||
# ##############################################################################
|
||||
|
@ -356,24 +356,7 @@ std::string RifHdf5Reader::getStringAttribute( H5::H5File file, std::string grou
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<std::string> RifHdf5Reader::getSubGroupNames( H5::H5File file, std::string baseGroupName ) const
|
||||
{
|
||||
H5::Group baseGroup = file.openGroup( baseGroupName.c_str() );
|
||||
|
||||
std::vector<std::string> subGroupNames;
|
||||
|
||||
hsize_t groupSize = baseGroup.getNumObjs();
|
||||
|
||||
for ( hsize_t i = 0; i < groupSize; i++ )
|
||||
{
|
||||
std::string nodeName( 1024, '\0' );
|
||||
|
||||
ssize_t slen = baseGroup.getObjnameByIdx( i, &nodeName[0], 1023 );
|
||||
|
||||
nodeName.resize( slen + 1 );
|
||||
|
||||
subGroupNames.push_back( nodeName );
|
||||
}
|
||||
|
||||
return subGroupNames;
|
||||
return RifHdf5ReaderTools::getSubGroupNames( &file, baseGroupName );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -412,3 +395,33 @@ void RifHdf5Reader::getElementResultValues( H5::H5File file, std::string groupNa
|
||||
( *resultValues ).resize( dims[0] );
|
||||
dataset.read( resultValues->data(), H5::PredType::NATIVE_DOUBLE );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<std::string> RifHdf5ReaderTools::getSubGroupNames( H5::H5File* file, const std::string& baseGroupName )
|
||||
{
|
||||
if ( file )
|
||||
{
|
||||
H5::Group baseGroup = file->openGroup( baseGroupName.c_str() );
|
||||
|
||||
std::vector<std::string> subGroupNames;
|
||||
|
||||
hsize_t groupSize = baseGroup.getNumObjs();
|
||||
|
||||
for ( hsize_t i = 0; i < groupSize; i++ )
|
||||
{
|
||||
std::string nodeName( 1024, '\0' );
|
||||
|
||||
ssize_t slen = baseGroup.getObjnameByIdx( i, &nodeName[0], 1023 );
|
||||
|
||||
nodeName.resize( slen + 1 );
|
||||
|
||||
subGroupNames.push_back( nodeName );
|
||||
}
|
||||
|
||||
return subGroupNames;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -24,6 +24,12 @@
|
||||
|
||||
#include "H5Cpp.h"
|
||||
|
||||
class RifHdf5ReaderTools
|
||||
{
|
||||
public:
|
||||
static std::vector<std::string> getSubGroupNames( H5::H5File* file, const std::string& baseGroupName );
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
|
249
ApplicationLibCode/FileInterface/RifHdf5SummaryReader.cpp
Normal file
249
ApplicationLibCode/FileInterface/RifHdf5SummaryReader.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017 Statoil ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RifHdf5SummaryReader.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaQDateTimeTools.h"
|
||||
#include "RiaTimeTTools.h"
|
||||
#include "RifHdf5Reader.h"
|
||||
|
||||
#include "H5Cpp.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifHdf5SummaryReader::RifHdf5SummaryReader( const QString& fileName )
|
||||
{
|
||||
try
|
||||
{
|
||||
m_hdfFile = new H5::H5File( fileName.toStdString().c_str(), H5F_ACC_RDONLY );
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
RiaLogging::error( "Failed to open HDF file " + fileName );
|
||||
|
||||
delete m_hdfFile;
|
||||
m_hdfFile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifHdf5SummaryReader::~RifHdf5SummaryReader()
|
||||
{
|
||||
if ( m_hdfFile )
|
||||
{
|
||||
m_hdfFile->close();
|
||||
|
||||
delete m_hdfFile;
|
||||
m_hdfFile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifHdf5SummaryReader::isValid() const
|
||||
{
|
||||
return ( m_hdfFile != nullptr );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<std::string> RifHdf5SummaryReader::vectorNames()
|
||||
{
|
||||
if ( m_hdfFile )
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
|
||||
auto groupNames = RifHdf5ReaderTools::getSubGroupNames( m_hdfFile, "summary_vectors" );
|
||||
names.reserve( groupNames.size() );
|
||||
for ( const auto& name : groupNames )
|
||||
{
|
||||
names.push_back( name );
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<time_t> RifHdf5SummaryReader::timeSteps() const
|
||||
{
|
||||
std::vector<time_t> times;
|
||||
|
||||
// TODO: This function uses code taken from ESmry::dates(). There is conversion from time_t to
|
||||
// chrono::system_clock::time_points, and then back to time_t again. Consider using one representation
|
||||
|
||||
double time_unit = 24 * 3600;
|
||||
|
||||
using namespace std::chrono;
|
||||
using TP = time_point<system_clock>;
|
||||
using DoubSec = duration<double, seconds::period>;
|
||||
|
||||
auto timeDeltasInDays = values( "TIME" );
|
||||
|
||||
std::vector<std::chrono::system_clock::time_point> timePoints;
|
||||
|
||||
TP startDat = std::chrono::system_clock::from_time_t( startDate() );
|
||||
|
||||
timePoints.reserve( timeDeltasInDays.size() );
|
||||
for ( const auto& t : timeDeltasInDays )
|
||||
{
|
||||
timePoints.push_back( startDat + duration_cast<TP::duration>( DoubSec( t * time_unit ) ) );
|
||||
}
|
||||
|
||||
for ( const auto& d : timePoints )
|
||||
{
|
||||
auto timeAsTimeT = std::chrono::system_clock::to_time_t( d );
|
||||
times.push_back( timeAsTimeT );
|
||||
}
|
||||
|
||||
return times;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RifHdf5SummaryReader::values( const std::string& vectorName, int smspecKeywordIndex ) const
|
||||
{
|
||||
if ( m_hdfFile )
|
||||
{
|
||||
try
|
||||
{
|
||||
H5::Exception::dontPrint(); // Turn off auto-printing of failures to handle the errors appropriately
|
||||
|
||||
std::string idText = std::to_string( smspecKeywordIndex );
|
||||
|
||||
std::string groupPath = "summary_vectors/" + vectorName + "/" + idText;
|
||||
|
||||
{
|
||||
H5::Group generalGroup = m_hdfFile->openGroup( groupPath.c_str() );
|
||||
H5::DataSet dataset = H5::DataSet( generalGroup.openDataSet( "values" ) );
|
||||
|
||||
hsize_t dims[2];
|
||||
H5::DataSpace dataspace = dataset.getSpace();
|
||||
dataspace.getSimpleExtentDims( dims, nullptr );
|
||||
|
||||
std::vector<double> values;
|
||||
values.resize( dims[0] );
|
||||
dataset.read( values.data(), H5::PredType::NATIVE_DOUBLE );
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RifHdf5SummaryReader::values( const std::string& vectorName ) const
|
||||
{
|
||||
if ( m_hdfFile )
|
||||
{
|
||||
try
|
||||
{
|
||||
H5::Exception::dontPrint(); // Turn off auto-printing of failures to handle the errors appropriately
|
||||
|
||||
std::string groupPath = "summary_vectors/" + vectorName;
|
||||
|
||||
auto groupNames = RifHdf5ReaderTools::getSubGroupNames( m_hdfFile, groupPath );
|
||||
if ( !groupNames.empty() )
|
||||
{
|
||||
groupPath = groupPath + "/" + groupNames[0];
|
||||
|
||||
H5::Group generalGroup = m_hdfFile->openGroup( groupPath.c_str() );
|
||||
H5::DataSet dataset = H5::DataSet( generalGroup.openDataSet( "values" ) );
|
||||
|
||||
hsize_t dims[2];
|
||||
H5::DataSpace dataspace = dataset.getSpace();
|
||||
dataspace.getSimpleExtentDims( dims, nullptr );
|
||||
|
||||
std::vector<double> values;
|
||||
values.resize( dims[0] );
|
||||
dataset.read( values.data(), H5::PredType::NATIVE_DOUBLE );
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
time_t RifHdf5SummaryReader::startDate() const
|
||||
{
|
||||
if ( m_hdfFile )
|
||||
{
|
||||
try
|
||||
{
|
||||
H5::Exception::dontPrint(); // Turn off auto-printing of failures to handle the errors appropriately
|
||||
|
||||
QString groupPath = QString( "general" );
|
||||
|
||||
H5::Group GridFunction_00002 = m_hdfFile->openGroup( groupPath.toStdString().c_str() );
|
||||
H5::DataSet dataset = H5::DataSet( GridFunction_00002.openDataSet( "start_date" ) );
|
||||
|
||||
hsize_t dims[2];
|
||||
H5::DataSpace dataspace = dataset.getSpace();
|
||||
dataspace.getSimpleExtentDims( dims, nullptr );
|
||||
|
||||
std::vector<int> values;
|
||||
values.resize( dims[0] );
|
||||
dataset.read( values.data(), H5::PredType::NATIVE_INT );
|
||||
|
||||
int day = values[0];
|
||||
int month = values[1];
|
||||
int year = values[2];
|
||||
|
||||
QDateTime reportDateTime = RiaQDateTimeTools::createUtcDateTime( QDate( year, month, day ) );
|
||||
|
||||
time_t myTime = RiaTimeTTools::fromQDateTime( reportDateTime );
|
||||
return myTime;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
}
|
||||
|
||||
RiaLogging::error( "Not able to read start_date from HDF5 " );
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
51
ApplicationLibCode/FileInterface/RifHdf5SummaryReader.h
Normal file
51
ApplicationLibCode/FileInterface/RifHdf5SummaryReader.h
Normal file
@ -0,0 +1,51 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017 Statoil ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "H5Cpp.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class QString;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class RifHdf5SummaryReader
|
||||
{
|
||||
public:
|
||||
explicit RifHdf5SummaryReader( const QString& fileName );
|
||||
~RifHdf5SummaryReader();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
std::vector<std::string> vectorNames();
|
||||
std::vector<time_t> timeSteps() const;
|
||||
|
||||
std::vector<double> values( const std::string& vectorName, int smspecKeywordIndex ) const;
|
||||
std::vector<double> values( const std::string& vectorName ) const;
|
||||
|
||||
private:
|
||||
time_t startDate() const;
|
||||
|
||||
private:
|
||||
H5::H5File* m_hdfFile;
|
||||
};
|
@ -79,9 +79,11 @@ size_t RifOpmCommonEclipseSummary::numberOfLodFilesCreated()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifOpmCommonEclipseSummary::open( const QString& headerFileName, bool includeRestartFiles )
|
||||
bool RifOpmCommonEclipseSummary::open( const QString& headerFileName,
|
||||
bool includeRestartFiles,
|
||||
RiaThreadSafeLogger* threadSafeLogger )
|
||||
{
|
||||
if ( !openESmryFile( headerFileName, includeRestartFiles ) ) return false;
|
||||
if ( !openESmryFile( headerFileName, includeRestartFiles, threadSafeLogger ) ) return false;
|
||||
|
||||
if ( m_createLodsmryFiles && !includeRestartFiles )
|
||||
{
|
||||
@ -96,7 +98,7 @@ bool RifOpmCommonEclipseSummary::open( const QString& headerFileName, bool inclu
|
||||
// object. Close the file object to make sure allocated data is released, and create a new file object
|
||||
// that will import only the meta data and no curve data. This is a relatively fast operation.
|
||||
|
||||
if ( !openESmryFile( headerFileName, includeRestartFiles ) ) return false;
|
||||
if ( !openESmryFile( headerFileName, includeRestartFiles, threadSafeLogger ) ) return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,25 +181,19 @@ void RifOpmCommonEclipseSummary::buildMetaData()
|
||||
m_timeSteps.push_back( timeAsTimeT );
|
||||
}
|
||||
|
||||
auto nodes = m_eSmry->summaryNodeList();
|
||||
for ( size_t i = 0; i < nodes.size(); i++ )
|
||||
{
|
||||
auto summaryNode = nodes[i];
|
||||
auto eclAdr = createAddressFromSummaryNode( summaryNode, m_eSmry.get() );
|
||||
auto [addresses, addressMap] = RifOpmCommonSummaryTools::buildMetaData( m_eSmry.get() );
|
||||
|
||||
if ( eclAdr.isValid() )
|
||||
{
|
||||
m_allResultAddresses.insert( eclAdr );
|
||||
m_adrToSummaryNodeIndex[eclAdr] = i;
|
||||
}
|
||||
}
|
||||
m_allResultAddresses = addresses;
|
||||
m_adrToSummaryNodeIndex = addressMap;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifOpmCommonEclipseSummary::openESmryFile( const QString& headerFileName, bool includeRestartFiles )
|
||||
bool RifOpmCommonEclipseSummary::openESmryFile( const QString& headerFileName,
|
||||
bool includeRestartFiles,
|
||||
RiaThreadSafeLogger* threadSafeLogger )
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -207,7 +203,8 @@ bool RifOpmCommonEclipseSummary::openESmryFile( const QString& headerFileName, b
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
QString txt = QString( "Optimized Summary Reader error : %1" ).arg( e.what() );
|
||||
RiaLogging::error( txt );
|
||||
|
||||
if ( threadSafeLogger ) threadSafeLogger->error( txt );
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -228,43 +225,43 @@ void RifOpmCommonEclipseSummary::increaseLodFileCount()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifEclipseSummaryAddress RifOpmCommonEclipseSummary::createAddressFromSummaryNode( const Opm::EclIO::SummaryNode& node,
|
||||
Opm::EclIO::ESmry* summaryFile )
|
||||
RifEclipseSummaryAddress RifOpmCommonSummaryTools::createAddressFromSummaryNode( const Opm::EclIO::SummaryNode& summaryNode,
|
||||
const Opm::EclIO::ESmry* summaryFile )
|
||||
{
|
||||
int i = -1;
|
||||
int j = -1;
|
||||
int k = -1;
|
||||
|
||||
switch ( node.category )
|
||||
switch ( summaryNode.category )
|
||||
{
|
||||
case Opm::EclIO::SummaryNode::Category::Aquifer:
|
||||
return RifEclipseSummaryAddress::aquiferAddress( node.keyword, node.number );
|
||||
return RifEclipseSummaryAddress::aquiferAddress( summaryNode.keyword, summaryNode.number );
|
||||
break;
|
||||
case Opm::EclIO::SummaryNode::Category::Well:
|
||||
return RifEclipseSummaryAddress::wellAddress( node.keyword, node.wgname );
|
||||
return RifEclipseSummaryAddress::wellAddress( summaryNode.keyword, summaryNode.wgname );
|
||||
break;
|
||||
case Opm::EclIO::SummaryNode::Category::Group:
|
||||
return RifEclipseSummaryAddress::wellGroupAddress( node.keyword, node.wgname );
|
||||
return RifEclipseSummaryAddress::wellGroupAddress( summaryNode.keyword, summaryNode.wgname );
|
||||
break;
|
||||
case Opm::EclIO::SummaryNode::Category::Field:
|
||||
return RifEclipseSummaryAddress::fieldAddress( node.keyword );
|
||||
return RifEclipseSummaryAddress::fieldAddress( summaryNode.keyword );
|
||||
break;
|
||||
case Opm::EclIO::SummaryNode::Category::Region:
|
||||
return RifEclipseSummaryAddress::regionAddress( node.keyword, node.number );
|
||||
return RifEclipseSummaryAddress::regionAddress( summaryNode.keyword, summaryNode.number );
|
||||
break;
|
||||
case Opm::EclIO::SummaryNode::Category::Block:
|
||||
summaryFile->ijk_from_global_index( node.number, i, j, k );
|
||||
return RifEclipseSummaryAddress::blockAddress( node.keyword, i, j, k );
|
||||
summaryFile->ijk_from_global_index( summaryNode.number, i, j, k );
|
||||
return RifEclipseSummaryAddress::blockAddress( summaryNode.keyword, i, j, k );
|
||||
break;
|
||||
case Opm::EclIO::SummaryNode::Category::Connection:
|
||||
summaryFile->ijk_from_global_index( node.number, i, j, k );
|
||||
return RifEclipseSummaryAddress::wellCompletionAddress( node.keyword, node.wgname, i, j, k );
|
||||
summaryFile->ijk_from_global_index( summaryNode.number, i, j, k );
|
||||
return RifEclipseSummaryAddress::wellCompletionAddress( summaryNode.keyword, summaryNode.wgname, i, j, k );
|
||||
break;
|
||||
case Opm::EclIO::SummaryNode::Category::Segment:
|
||||
return RifEclipseSummaryAddress::wellSegmentAddress( node.keyword, node.wgname, node.number );
|
||||
return RifEclipseSummaryAddress::wellSegmentAddress( summaryNode.keyword, summaryNode.wgname, summaryNode.number );
|
||||
break;
|
||||
case Opm::EclIO::SummaryNode::Category::Miscellaneous:
|
||||
return RifEclipseSummaryAddress::miscAddress( node.keyword );
|
||||
return RifEclipseSummaryAddress::miscAddress( summaryNode.keyword );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -272,3 +269,31 @@ RifEclipseSummaryAddress RifOpmCommonEclipseSummary::createAddressFromSummaryNod
|
||||
|
||||
return RifEclipseSummaryAddress();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<std::set<RifEclipseSummaryAddress>, std::map<RifEclipseSummaryAddress, size_t>>
|
||||
RifOpmCommonSummaryTools::buildMetaData( const Opm::EclIO::ESmry* summaryFile )
|
||||
{
|
||||
std::set<RifEclipseSummaryAddress> addresses;
|
||||
std::map<RifEclipseSummaryAddress, size_t> addressToNodeIndexMap;
|
||||
|
||||
if ( summaryFile )
|
||||
{
|
||||
auto nodes = summaryFile->summaryNodeList();
|
||||
for ( size_t i = 0; i < nodes.size(); i++ )
|
||||
{
|
||||
auto summaryNode = nodes[i];
|
||||
auto eclAdr = createAddressFromSummaryNode( summaryNode, summaryFile );
|
||||
|
||||
if ( eclAdr.isValid() )
|
||||
{
|
||||
addresses.insert( eclAdr );
|
||||
addressToNodeIndexMap[eclAdr] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { addresses, addressToNodeIndexMap };
|
||||
}
|
||||
|
@ -41,6 +41,18 @@ namespace EclIO
|
||||
} // namespace EclIO
|
||||
} // namespace Opm
|
||||
|
||||
class RiaThreadSafeLogger;
|
||||
|
||||
class RifOpmCommonSummaryTools
|
||||
{
|
||||
public:
|
||||
static RifEclipseSummaryAddress createAddressFromSummaryNode( const Opm::EclIO::SummaryNode& summaryNode,
|
||||
const Opm::EclIO::ESmry* summaryFile );
|
||||
|
||||
static std::pair<std::set<RifEclipseSummaryAddress>, std::map<RifEclipseSummaryAddress, size_t>>
|
||||
buildMetaData( const Opm::EclIO::ESmry* summaryFile );
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
@ -57,7 +69,7 @@ public:
|
||||
static void resetLodCount();
|
||||
static size_t numberOfLodFilesCreated();
|
||||
|
||||
bool open( const QString& headerFileName, bool includeRestartFiles );
|
||||
bool open( const QString& headerFileName, bool includeRestartFiles, RiaThreadSafeLogger* threadSafeLogger );
|
||||
|
||||
const std::vector<time_t>& timeSteps( const RifEclipseSummaryAddress& resultAddress ) const override;
|
||||
bool values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const override;
|
||||
@ -66,13 +78,10 @@ public:
|
||||
|
||||
private:
|
||||
void buildMetaData();
|
||||
bool openESmryFile( const QString& headerFileName, bool includeRestartFiles );
|
||||
bool openESmryFile( const QString& headerFileName, bool includeRestartFiles, RiaThreadSafeLogger* threadSafeLogger );
|
||||
|
||||
static void increaseLodFileCount();
|
||||
|
||||
static RifEclipseSummaryAddress createAddressFromSummaryNode( const Opm::EclIO::SummaryNode& summaryNode,
|
||||
Opm::EclIO::ESmry* summaryFile );
|
||||
|
||||
private:
|
||||
std::unique_ptr<Opm::EclIO::ESmry> m_eSmry;
|
||||
std::vector<std::string> m_eSmryKeywords;
|
||||
|
196
ApplicationLibCode/FileInterface/RifOpmHdf5Summary.cpp
Normal file
196
ApplicationLibCode/FileInterface/RifOpmHdf5Summary.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2021- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RifOpmHdf5Summary.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include "RifHdf5SummaryReader.h"
|
||||
#include "RifOpmCommonSummary.h"
|
||||
|
||||
#include "opm/io/eclipse/ESmry.hpp"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifOpmHdf5Summary::RifOpmHdf5Summary()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifOpmHdf5Summary::~RifOpmHdf5Summary()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifOpmHdf5Summary::open( const QString& headerFileName, bool includeRestartFiles, RiaThreadSafeLogger* threadSafeLogger )
|
||||
{
|
||||
if ( !openESmryFile( headerFileName, includeRestartFiles, threadSafeLogger ) )
|
||||
{
|
||||
QString errorTxt = "Failed to open " + headerFileName;
|
||||
|
||||
if ( threadSafeLogger ) threadSafeLogger->error( errorTxt );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QFileInfo fi( headerFileName );
|
||||
QString hdfFileName = fi.absolutePath() + "/" + fi.baseName() + ".h5";
|
||||
|
||||
if ( !QFile::exists( hdfFileName ) )
|
||||
{
|
||||
QString errorTxt = "Failed to open H5 file " + hdfFileName;
|
||||
if ( threadSafeLogger ) threadSafeLogger->error( errorTxt );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hdf5Reader = std::make_unique<RifHdf5SummaryReader>( hdfFileName );
|
||||
|
||||
if ( !m_eSmry || !m_hdf5Reader ) return false;
|
||||
|
||||
buildMetaData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<time_t>& RifOpmHdf5Summary::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
|
||||
{
|
||||
return m_timeSteps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifOpmHdf5Summary::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
|
||||
{
|
||||
if ( m_eSmry && m_hdf5Reader )
|
||||
{
|
||||
auto it = m_adrToSummaryNodeIndex.find( resultAddress );
|
||||
if ( it != m_adrToSummaryNodeIndex.end() )
|
||||
{
|
||||
size_t index = it->second;
|
||||
auto node = m_eSmry->summaryNodeList()[index];
|
||||
|
||||
int smspecIndex = static_cast<int>( node.smspecKeywordIndex );
|
||||
const auto& vectorName = resultAddress.quantityName();
|
||||
|
||||
*values = m_hdf5Reader->values( vectorName, smspecIndex );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RifOpmHdf5Summary::unitName( const RifEclipseSummaryAddress& resultAddress ) const
|
||||
{
|
||||
if ( m_eSmry )
|
||||
{
|
||||
auto it = m_adrToSummaryNodeIndex.find( resultAddress );
|
||||
if ( it != m_adrToSummaryNodeIndex.end() )
|
||||
{
|
||||
auto index = it->second;
|
||||
auto node = m_eSmry->summaryNodeList()[index];
|
||||
return m_eSmry->get_unit( node );
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RifOpmHdf5Summary::unitSystem() const
|
||||
{
|
||||
// TODO: Not implemented
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifOpmHdf5Summary::buildMetaData()
|
||||
{
|
||||
if ( m_eSmry )
|
||||
{
|
||||
// Get time step data from HDF
|
||||
if ( m_hdf5Reader )
|
||||
{
|
||||
m_timeSteps = m_hdf5Reader->timeSteps();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to using opm-reader for time step data
|
||||
std::vector<std::chrono::system_clock::time_point> timePoints;
|
||||
timePoints = m_eSmry->dates();
|
||||
|
||||
for ( const auto& d : timePoints )
|
||||
{
|
||||
auto timeAsTimeT = std::chrono::system_clock::to_time_t( d );
|
||||
m_timeSteps.push_back( timeAsTimeT );
|
||||
}
|
||||
}
|
||||
|
||||
auto [addresses, addressMap] = RifOpmCommonSummaryTools::buildMetaData( m_eSmry.get() );
|
||||
|
||||
m_allResultAddresses = addresses;
|
||||
m_adrToSummaryNodeIndex = addressMap;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifOpmHdf5Summary::openESmryFile( const QString& headerFileName,
|
||||
bool includeRestartFiles,
|
||||
RiaThreadSafeLogger* threadSafeLogger )
|
||||
{
|
||||
try
|
||||
{
|
||||
m_eSmry = std::make_unique<Opm::EclIO::ESmry>( headerFileName.toStdString(), includeRestartFiles, false );
|
||||
}
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
QString txt = QString( "Optimized Summary Reader error : %1" ).arg( e.what() );
|
||||
|
||||
if ( threadSafeLogger ) threadSafeLogger->error( txt );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
75
ApplicationLibCode/FileInterface/RifOpmHdf5Summary.h
Normal file
75
ApplicationLibCode/FileInterface/RifOpmHdf5Summary.h
Normal file
@ -0,0 +1,75 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2021- 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 "RifEclipseSummaryAddress.h"
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class RifHdf5SummaryReader;
|
||||
class RiaThreadSafeLogger;
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
namespace EclIO
|
||||
{
|
||||
class ESmry;
|
||||
struct SummaryNode;
|
||||
} // namespace EclIO
|
||||
} // namespace Opm
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class RifOpmHdf5Summary : public RifSummaryReaderInterface
|
||||
{
|
||||
public:
|
||||
RifOpmHdf5Summary();
|
||||
~RifOpmHdf5Summary();
|
||||
|
||||
bool open( const QString& headerFileName, bool includeRestartFiles, RiaThreadSafeLogger* threadSafeLogger );
|
||||
|
||||
const std::vector<time_t>& timeSteps( const RifEclipseSummaryAddress& resultAddress ) const override;
|
||||
bool values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const override;
|
||||
std::string unitName( const RifEclipseSummaryAddress& resultAddress ) const override;
|
||||
RiaDefines::EclipseUnitSystem unitSystem() const override;
|
||||
|
||||
private:
|
||||
void buildMetaData();
|
||||
bool openESmryFile( const QString& headerFileName, bool includeRestartFiles, RiaThreadSafeLogger* threadSafeLogger );
|
||||
|
||||
private:
|
||||
std::unique_ptr<Opm::EclIO::ESmry> m_eSmry;
|
||||
std::vector<std::string> m_eSmryKeywords;
|
||||
std::map<RifEclipseSummaryAddress, size_t> m_adrToSummaryNodeIndex;
|
||||
std::vector<time_t> m_timeSteps;
|
||||
|
||||
std::unique_ptr<RifHdf5SummaryReader> m_hdf5Reader;
|
||||
};
|
@ -28,6 +28,10 @@
|
||||
#include "RifOpmCommonSummary.h"
|
||||
#include "RifReaderEclipseOutput.h"
|
||||
|
||||
#ifdef USE_HDF5
|
||||
#include "RifOpmHdf5Summary.h"
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
@ -147,17 +151,33 @@ RifReaderEclipseSummary::~RifReaderEclipseSummary()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifReaderEclipseSummary::open( const QString& headerFileName, bool includeRestartFiles )
|
||||
bool RifReaderEclipseSummary::open( const QString& headerFileName,
|
||||
bool includeRestartFiles,
|
||||
RiaThreadSafeLogger* threadSafeLogger )
|
||||
{
|
||||
bool useOpmCommonReader = RiaPreferences::current()->useOptimizedSummaryDataReader();
|
||||
bool isValid = false;
|
||||
|
||||
if ( useOpmCommonReader )
|
||||
// Try to create readers. If HDF5 or Opm readers fails to create, use ecllib reader
|
||||
|
||||
if ( RiaPreferences::current()->summaryDataReader() == RiaPreferences::SummaryReaderMode::HDF5_OPM_COMMON )
|
||||
{
|
||||
#ifdef USE_HDF5
|
||||
auto hdfReader = std::make_unique<RifOpmHdf5Summary>();
|
||||
|
||||
isValid = hdfReader->open( headerFileName, false, threadSafeLogger );
|
||||
if ( isValid )
|
||||
{
|
||||
m_hdf5OpmReader = std::move( hdfReader );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if ( RiaPreferences::current()->summaryDataReader() == RiaPreferences::SummaryReaderMode::OPM_COMMON )
|
||||
{
|
||||
bool useLodsmryFiles = RiaPreferences::current()->useOptimizedSummaryDataFiles();
|
||||
if ( useLodsmryFiles && includeRestartFiles )
|
||||
{
|
||||
RiaLogging::error(
|
||||
"LODSMRY file loading for summary restart files is not supported. Disable one of the options" );
|
||||
QString txt = "LODSMRY file loading for summary restart files is not supported. Disable one of the options";
|
||||
if ( threadSafeLogger ) threadSafeLogger->error( txt );
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -166,13 +186,12 @@ bool RifReaderEclipseSummary::open( const QString& headerFileName, bool includeR
|
||||
|
||||
m_opmCommonReader->useLodsmaryFiles( RiaPreferences::current()->useOptimizedSummaryDataFiles() );
|
||||
m_opmCommonReader->createLodsmaryFiles( RiaPreferences::current()->createOptimizedSummaryDataFiles() );
|
||||
m_opmCommonReader->open( headerFileName, includeRestartFiles );
|
||||
|
||||
buildMetaData();
|
||||
|
||||
return true;
|
||||
isValid = m_opmCommonReader->open( headerFileName, includeRestartFiles, threadSafeLogger );
|
||||
if ( !isValid ) m_opmCommonReader.reset();
|
||||
}
|
||||
|
||||
if ( !isValid || RiaPreferences::current()->summaryDataReader() == RiaPreferences::SummaryReaderMode::LIBECL )
|
||||
{
|
||||
assert( m_ecl_sum == nullptr );
|
||||
|
||||
m_ecl_sum = openEclSum( headerFileName, includeRestartFiles );
|
||||
@ -183,12 +202,17 @@ bool RifReaderEclipseSummary::open( const QString& headerFileName, bool includeR
|
||||
m_ecl_SmSpec = ecl_sum_get_smspec( m_ecl_sum );
|
||||
m_timeSteps = getTimeSteps( m_ecl_sum );
|
||||
m_unitSystem = readUnitSystem( m_ecl_sum );
|
||||
buildMetaData();
|
||||
|
||||
return true;
|
||||
isValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if ( isValid )
|
||||
{
|
||||
buildMetaData();
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -455,11 +479,11 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode( const ecl::smspec_node& ertSu
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifReaderEclipseSummary::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
|
||||
{
|
||||
CVF_ASSERT( values );
|
||||
|
||||
values->clear();
|
||||
values->reserve( timeStepCount() );
|
||||
|
||||
// assert( m_ecl_sum != nullptr );
|
||||
|
||||
const std::vector<double>& cachedValues = m_valuesCache->getValues( resultAddress );
|
||||
if ( !cachedValues.empty() )
|
||||
{
|
||||
@ -468,12 +492,21 @@ bool RifReaderEclipseSummary::values( const RifEclipseSummaryAddress& resultAddr
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( m_hdf5OpmReader )
|
||||
{
|
||||
auto status = m_hdf5OpmReader->values( resultAddress, values );
|
||||
|
||||
if ( status ) m_valuesCache->insertValues( resultAddress, *values );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if ( m_opmCommonReader )
|
||||
{
|
||||
m_opmCommonReader->values( resultAddress, values );
|
||||
m_valuesCache->insertValues( resultAddress, *values );
|
||||
auto status = m_opmCommonReader->values( resultAddress, values );
|
||||
if ( status ) m_valuesCache->insertValues( resultAddress, *values );
|
||||
|
||||
return true;
|
||||
return status;
|
||||
}
|
||||
|
||||
if ( m_ecl_SmSpec )
|
||||
@ -536,16 +569,7 @@ bool RifReaderEclipseSummary::values( const RifEclipseSummaryAddress& resultAddr
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RifReaderEclipseSummary::timeStepCount() const
|
||||
{
|
||||
if ( m_opmCommonReader )
|
||||
{
|
||||
return m_timeSteps.size();
|
||||
}
|
||||
|
||||
assert( m_ecl_sum != nullptr );
|
||||
|
||||
if ( m_ecl_SmSpec == nullptr ) return 0;
|
||||
|
||||
return static_cast<size_t>( ecl_sum_get_data_length( m_ecl_sum ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -553,8 +577,6 @@ size_t RifReaderEclipseSummary::timeStepCount() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<time_t>& RifReaderEclipseSummary::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
|
||||
{
|
||||
// assert( m_ecl_sum != nullptr );
|
||||
|
||||
return m_timeSteps;
|
||||
}
|
||||
|
||||
@ -580,6 +602,15 @@ void RifReaderEclipseSummary::buildMetaData()
|
||||
m_allResultAddresses.clear();
|
||||
m_resultAddressToErtNodeIdx.clear();
|
||||
|
||||
if ( m_hdf5OpmReader )
|
||||
{
|
||||
m_allResultAddresses = m_hdf5OpmReader->allResultAddresses();
|
||||
m_allErrorAddresses = m_hdf5OpmReader->allErrorAddresses();
|
||||
|
||||
m_timeSteps = m_hdf5OpmReader->timeSteps( RifEclipseSummaryAddress() );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_opmCommonReader )
|
||||
{
|
||||
m_allResultAddresses = m_opmCommonReader->allResultAddresses();
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <vector>
|
||||
|
||||
class RifOpmCommonEclipseSummary;
|
||||
class RifOpmHdf5Summary;
|
||||
class RiaThreadSafeLogger;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
@ -68,7 +70,7 @@ public:
|
||||
RifReaderEclipseSummary();
|
||||
~RifReaderEclipseSummary() override;
|
||||
|
||||
bool open( const QString& headerFileName, bool includeRestartFiles );
|
||||
bool open( const QString& headerFileName, bool includeRestartFiles, RiaThreadSafeLogger* threadSafeLogger );
|
||||
|
||||
std::vector<RifRestartFileInfo> getRestartFiles( const QString& headerFileName, bool* hasWarnings );
|
||||
RifRestartFileInfo getFileInfo( const QString& headerFileName );
|
||||
@ -107,6 +109,7 @@ private:
|
||||
std::set<RifEclipseSummaryAddress> m_differenceAddresses;
|
||||
|
||||
std::unique_ptr<RifOpmCommonEclipseSummary> m_opmCommonReader;
|
||||
std::unique_ptr<RifSummaryReaderInterface> m_hdf5OpmReader;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
|
@ -85,13 +85,24 @@ void RimFileSummaryCase::updateFilePathsFromProjectPath( const QString& newProje
|
||||
// RimTools::relocateFile( m_summaryHeaderFilename().path(), newProjectPath, oldProjectPath, nullptr, nullptr );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFileSummaryCase::createSummaryReaderInterfaceThreadSafe( RiaThreadSafeLogger* threadSafeLogger )
|
||||
{
|
||||
m_summaryFileReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
|
||||
m_includeRestartFiles,
|
||||
threadSafeLogger );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFileSummaryCase::createSummaryReaderInterface()
|
||||
{
|
||||
m_summaryFileReader =
|
||||
RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(), m_includeRestartFiles );
|
||||
m_summaryFileReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
|
||||
m_includeRestartFiles,
|
||||
nullptr );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -110,16 +121,15 @@ void RimFileSummaryCase::createRftReaderInterface()
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifReaderEclipseSummary* RimFileSummaryCase::findRelatedFilesAndCreateReader( const QString& headerFileName,
|
||||
bool includeRestartFiles )
|
||||
bool includeRestartFiles,
|
||||
RiaThreadSafeLogger* threadSafeLogger )
|
||||
{
|
||||
RifReaderEclipseSummary* summaryFileReader = new RifReaderEclipseSummary;
|
||||
|
||||
if ( !summaryFileReader->open( headerFileName, includeRestartFiles ) )
|
||||
if ( !summaryFileReader->open( headerFileName, includeRestartFiles, threadSafeLogger ) )
|
||||
{
|
||||
RiaLogging::warning( QString( "Failed to open summary file %1" ).arg( headerFileName ) );
|
||||
|
||||
delete summaryFileReader;
|
||||
summaryFileReader = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return summaryFileReader;
|
||||
|
@ -25,6 +25,7 @@
|
||||
class RifReaderRftInterface;
|
||||
class RifReaderEclipseRft;
|
||||
class RifReaderEclipseSummary;
|
||||
class RiaThreadSafeLogger;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
@ -43,6 +44,7 @@ public:
|
||||
QString caseName() const override;
|
||||
void updateFilePathsFromProjectPath( const QString& newProjectPath, const QString& oldProjectPath ) override;
|
||||
|
||||
void createSummaryReaderInterfaceThreadSafe( RiaThreadSafeLogger* threadSafeLogger );
|
||||
void createSummaryReaderInterface() override;
|
||||
void createRftReaderInterface() override;
|
||||
RifSummaryReaderInterface* summaryReader() override;
|
||||
@ -51,7 +53,9 @@ public:
|
||||
void setIncludeRestartFiles( bool includeRestartFiles );
|
||||
|
||||
static RifReaderEclipseSummary* findRelatedFilesAndCreateReader( const QString& headerFileName,
|
||||
bool includeRestartFiles );
|
||||
bool includeRestartFiles,
|
||||
RiaThreadSafeLogger* threadSafeLogger );
|
||||
|
||||
static RifReaderEclipseRft* findRftDataAndCreateReader( const QString& headerFileName );
|
||||
|
||||
private:
|
||||
|
@ -182,8 +182,9 @@ void RimGridSummaryCase::updateFilePathsFromProjectPath( const QString& newProje
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridSummaryCase::createSummaryReaderInterface()
|
||||
{
|
||||
m_summaryFileReader =
|
||||
RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(), m_includeRestartFiles );
|
||||
m_summaryFileReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
|
||||
m_includeRestartFiles,
|
||||
nullptr );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -441,18 +441,29 @@ void RimSummaryCaseMainCollection::loadFileSummaryCaseData( std::vector<RimFileS
|
||||
|
||||
RifOpmCommonEclipseSummary::resetLodCount();
|
||||
|
||||
#pragma omp parallel for schedule( dynamic )
|
||||
RiaThreadSafeLogger threadSafeLogger;
|
||||
|
||||
// The HDF5 reader requires a special configuration to be thread safe. Disable threading for HDF reader creation.
|
||||
bool canUseMultipleTreads =
|
||||
( RiaPreferences::current()->summaryDataReader() != RiaPreferences::SummaryReaderMode::HDF5_OPM_COMMON );
|
||||
|
||||
#pragma omp parallel for schedule( dynamic ) if ( canUseMultipleTreads )
|
||||
for ( int cIdx = 0; cIdx < static_cast<int>( fileSummaryCases.size() ); ++cIdx )
|
||||
{
|
||||
RimFileSummaryCase* fileSummaryCase = fileSummaryCases[cIdx];
|
||||
if ( fileSummaryCase )
|
||||
{
|
||||
fileSummaryCase->createSummaryReaderInterface();
|
||||
fileSummaryCase->createSummaryReaderInterfaceThreadSafe( &threadSafeLogger );
|
||||
}
|
||||
|
||||
progInfo.setProgress( cIdx );
|
||||
}
|
||||
|
||||
for ( const auto& txt : threadSafeLogger.messages() )
|
||||
{
|
||||
RiaLogging::info( txt );
|
||||
}
|
||||
|
||||
auto numberOfLodFilesCreated = RifOpmCommonEclipseSummary::numberOfLodFilesCreated();
|
||||
if ( numberOfLodFilesCreated > 0 )
|
||||
{
|
||||
|
@ -2,10 +2,130 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "RiaTestDataDirectory.h"
|
||||
#include "RifHdf5SummaryReader.h"
|
||||
#include "RifOpmHdf5Summary.h"
|
||||
|
||||
#include "H5Cpp.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <H5Exception.h>
|
||||
#include "opm/io/eclipse/ESmry.hpp"
|
||||
|
||||
static const QString H5_TEST_DATA_DIRECTORY = QString( "%1/h5-file/" ).arg( TEST_DATA_DIR );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( HDFTests, InspectSummaryData )
|
||||
{
|
||||
std::string file_path = H5_TEST_DATA_DIRECTORY.toStdString() + "NORNE_ATW2013_RFTPLT_V2.h5";
|
||||
|
||||
try
|
||||
{
|
||||
H5::Exception::dontPrint(); // Turn off auto-printing of failures to handle the errors appropriately
|
||||
|
||||
H5::H5File file( file_path.c_str(), H5F_ACC_RDONLY );
|
||||
|
||||
{
|
||||
H5::Group GridFunction_00002 = file.openGroup( "summary_vectors/BPR/66" );
|
||||
H5::DataSet dataset = H5::DataSet( GridFunction_00002.openDataSet( "values" ) );
|
||||
|
||||
hsize_t dims[2];
|
||||
H5::DataSpace dataspace = dataset.getSpace();
|
||||
dataspace.getSimpleExtentDims( dims, nullptr );
|
||||
|
||||
std::vector<double> values;
|
||||
values.resize( dims[0] );
|
||||
dataset.read( values.data(), H5::PredType::NATIVE_DOUBLE );
|
||||
EXPECT_EQ( size_t( 894 ), values.size() );
|
||||
}
|
||||
}
|
||||
|
||||
catch ( H5::FileIException& error ) // catch failure caused by the H5File operations
|
||||
{
|
||||
std::cout << error.getCDetailMsg();
|
||||
}
|
||||
|
||||
catch ( H5::DataSetIException& error ) // catch failure caused by the DataSet operations
|
||||
{
|
||||
std::cout << error.getCDetailMsg();
|
||||
}
|
||||
|
||||
catch ( H5::DataSpaceIException& error ) // catch failure caused by the DataSpace operations
|
||||
{
|
||||
std::cout << error.getCDetailMsg();
|
||||
}
|
||||
|
||||
catch ( H5::DataTypeIException& error ) // catch failure caused by the DataSpace operations
|
||||
{
|
||||
std::cout << error.getCDetailMsg();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( HDFTests, ReadSummaryData )
|
||||
{
|
||||
QString filePath = H5_TEST_DATA_DIRECTORY + "NORNE_ATW2013_RFTPLT_V2.h5";
|
||||
|
||||
RifHdf5SummaryReader hdf5SummaryReader( filePath );
|
||||
|
||||
auto vectorNames = hdf5SummaryReader.vectorNames();
|
||||
EXPECT_EQ( size_t( 211 ), vectorNames.size() );
|
||||
|
||||
auto timeSteps = hdf5SummaryReader.timeSteps();
|
||||
EXPECT_EQ( size_t( 894 ), timeSteps.size() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( HDFTests, ReadOpmSummaryData )
|
||||
{
|
||||
QString filePath = H5_TEST_DATA_DIRECTORY + "NORNE_ATW2013_RFTPLT_V2.SMSPEC";
|
||||
|
||||
RifOpmHdf5Summary hdf5SummaryReader;
|
||||
hdf5SummaryReader.open( filePath, false, nullptr );
|
||||
|
||||
auto addresses = hdf5SummaryReader.allResultAddresses();
|
||||
EXPECT_EQ( size_t( 2770 ), addresses.size() );
|
||||
|
||||
int itemCount = 0;
|
||||
size_t totalValueCount = 0;
|
||||
for ( const auto& adr : addresses )
|
||||
{
|
||||
if ( itemCount++ < 10 )
|
||||
{
|
||||
std::vector<double> values;
|
||||
hdf5SummaryReader.values( adr, &values );
|
||||
|
||||
totalValueCount += values.size();
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ( size_t( 8940 ), totalValueCount );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( DISABLED_HDFTests, ReadOpmSummaryDataListContent )
|
||||
{
|
||||
QString filePath = H5_TEST_DATA_DIRECTORY + "NORNE_ATW2013_RFTPLT_V2.SMSPEC";
|
||||
|
||||
Opm::EclIO::ESmry eSmry( filePath.toStdString() );
|
||||
|
||||
auto nodes = eSmry.summaryNodeList();
|
||||
|
||||
for ( size_t i = 0; i < nodes.size(); i++ )
|
||||
{
|
||||
Opm::EclIO::SummaryNode n = nodes[i];
|
||||
std::cout << n.keyword << " number: " << n.number << " msjNumber: " << n.smspecKeywordIndex << " "
|
||||
<< n.unique_key() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
|
@ -23,7 +23,7 @@ TEST( DISABLED_RifSummaryDataTest, OpmCommonAllData )
|
||||
{
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
reader.open( filename, true );
|
||||
reader.open( filename, true, nullptr );
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> diff = end - start;
|
||||
@ -74,7 +74,7 @@ TEST( DISABLED_RifSummaryDataTest, LibEclAllData )
|
||||
{
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
reader.open( filename, true );
|
||||
reader.open( filename, true, nullptr );
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> diff = end - start;
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user