///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 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 // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RifReaderEclipseSummary.h" #include "RiaLogging.h" #include "RiaPreferencesSummary.h" #include "RiaStdStringTools.h" #include "RifEclEclipseSummary.h" #include "RifOpmCommonSummary.h" #ifdef USE_HDF5 #include "RifHdf5SummaryExporter.h" #include "RifOpmHdf5Summary.h" #endif #include #include #include #include #include #include //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifReaderEclipseSummary::RifReaderEclipseSummary() { m_valuesCache = std::make_unique(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifReaderEclipseSummary::~RifReaderEclipseSummary() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RifReaderEclipseSummary::open( const QString& headerFileName, RiaThreadSafeLogger* threadSafeLogger ) { bool isValid = false; // Create reader as specified by the user using the following fallback strategy // // ESMRY // - if h5 file is present on disk and prefSummary->createEnhancedSummaryDataFiles() is false // - use h5 reader // - else // - create ESMRY file if defined in preference // - use ESMRY reader // - if no reader has been created, fallback to libecl // // H5 // - if h5 file is present on disk // - use h5 reader // - else // - create h5 file if defined in preference // - use h5 reader // - if no reader has been created, fallback to libecl // // For all import modes, use libecl to read data if no data is imported with ESMRY or h5 RiaPreferencesSummary* prefSummary = RiaPreferencesSummary::current(); if ( prefSummary->summaryDataReader() == RiaPreferencesSummary::SummaryReaderMode::HDF5_OPM_COMMON || prefSummary->summaryDataReader() == RiaPreferencesSummary::SummaryReaderMode::OPM_COMMON ) { QFileInfo fi( headerFileName ); QString basenameNoExtension = fi.absolutePath() + "/" + fi.baseName(); QString h5FileName = basenameNoExtension + ".h5"; bool h5FileFound = QFile::exists( h5FileName ); if ( !prefSummary->createEnhancedSummaryDataFiles() && ( h5FileFound || ( prefSummary->summaryDataReader() == RiaPreferencesSummary::SummaryReaderMode::HDF5_OPM_COMMON ) ) ) { #ifdef USE_HDF5 if ( prefSummary->createH5SummaryDataFiles() ) { size_t createdH5FileCount = 0; RifHdf5SummaryExporter::ensureHdf5FileIsCreated( headerFileName.toStdString(), h5FileName.toStdString(), createdH5FileCount ); if ( createdH5FileCount > 0 ) { QString txt = QString( "Created %1 " ).arg( h5FileName ); if ( threadSafeLogger ) threadSafeLogger->info( txt ); } h5FileFound = QFile::exists( h5FileName ); } if ( h5FileFound ) { auto hdfReader = std::make_unique(); isValid = hdfReader->open( headerFileName, false, threadSafeLogger ); if ( isValid ) { m_summaryReader = std::move( hdfReader ); } } #endif } if ( !isValid && prefSummary->summaryDataReader() == RiaPreferencesSummary::SummaryReaderMode::OPM_COMMON ) { auto opmCommonReader = std::make_unique(); opmCommonReader->useEnhancedSummaryFiles( prefSummary->useEnhancedSummaryDataFiles() ); opmCommonReader->createEnhancedSummaryFiles( prefSummary->createEnhancedSummaryDataFiles() ); isValid = opmCommonReader->open( headerFileName, false, threadSafeLogger ); if ( isValid ) { m_summaryReader = std::move( opmCommonReader ); } } } // If no summary reader has been created, always try to read data using libecl if ( !isValid ) { auto libeclReader = std::make_unique(); isValid = libeclReader->open( headerFileName, threadSafeLogger ); if ( isValid ) { m_summaryReader = std::move( libeclReader ); } } if ( isValid ) { buildMetaData(); } return isValid; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RifReaderEclipseSummary::values( const RifEclipseSummaryAddress& resultAddress, std::vector* values ) const { CVF_ASSERT( values ); if ( timeSteps( resultAddress ).empty() ) return false; values->clear(); values->reserve( timeSteps( resultAddress ).size() ); const std::vector& cachedValues = m_valuesCache->getValues( resultAddress ); if ( !cachedValues.empty() ) { values->insert( values->begin(), cachedValues.begin(), cachedValues.end() ); return true; } if ( m_differenceAddresses.count( resultAddress ) ) { const std::string& quantityName = resultAddress.vectorName(); auto historyQuantity = quantityName.substr( 0, quantityName.size() - differenceIdentifier().size() ) + historyIdentifier(); RifEclipseSummaryAddress nativeAdrNoHistory = resultAddress; nativeAdrNoHistory.setVectorName( historyQuantity ); auto quantityNoHistory = quantityName.substr( 0, historyQuantity.size() - 1 ); RifEclipseSummaryAddress nativeAdrHistory = resultAddress; nativeAdrHistory.setVectorName( quantityNoHistory ); std::vector nativeValues; std::vector historyValues; if ( !this->values( nativeAdrHistory, &nativeValues ) ) return false; if ( !this->values( nativeAdrNoHistory, &historyValues ) ) return false; if ( nativeValues.size() != historyValues.size() ) return false; for ( size_t i = 0; i < nativeValues.size(); i++ ) { double diff = nativeValues[i] - historyValues[i]; values->push_back( diff ); m_valuesCache->insertValues( resultAddress, *values ); } return true; } auto reader = currentSummaryReader(); if ( reader ) { auto status = reader->values( resultAddress, values ); if ( status ) m_valuesCache->insertValues( resultAddress, *values ); return status; } return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RifReaderEclipseSummary::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const { auto reader = currentSummaryReader(); if ( reader ) return reader->timeSteps( resultAddress ); return {}; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseSummary::buildMetaData() { m_allResultAddresses.clear(); m_allErrorAddresses.clear(); auto reader = currentSummaryReader(); if ( reader ) { m_allResultAddresses = reader->allResultAddresses(); m_allErrorAddresses = reader->allErrorAddresses(); } bool addDifferenceVectors = true; if ( addDifferenceVectors ) { for ( const auto& adr : m_allResultAddresses ) { RifEclipseSummaryAddress adrWithHistory; RifEclipseSummaryAddress adrWithoutHistory; { const std::string& s = adr.vectorName(); if ( !RiaStdStringTools::endsWith( s, historyIdentifier() ) ) { RifEclipseSummaryAddress candidate = adr; candidate.setVectorName( s + historyIdentifier() ); if ( m_allResultAddresses.count( candidate ) ) { adrWithHistory = candidate; adrWithoutHistory = adr; } } } if ( adrWithoutHistory.isValid() && adrWithHistory.isValid() ) { RifEclipseSummaryAddress candidate = adr; std::string s = candidate.vectorName() + differenceIdentifier(); candidate.setVectorName( s ); m_allResultAddresses.insert( candidate ); m_differenceAddresses.insert( candidate ); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifSummaryReaderInterface* RifReaderEclipseSummary::currentSummaryReader() const { if ( m_summaryReader ) return m_summaryReader.get(); return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::string RifReaderEclipseSummary::unitName( const RifEclipseSummaryAddress& resultAddress ) const { auto reader = currentSummaryReader(); if ( reader ) { auto nativeName = resultAddress.vectorName(); auto stringToRemove = RifReaderEclipseSummary::differenceIdentifier(); if ( RiaStdStringTools::endsWith( nativeName, stringToRemove ) ) { nativeName = nativeName.substr( 0, nativeName.size() - stringToRemove.size() ); } RifEclipseSummaryAddress adr( resultAddress ); adr.setVectorName( nativeName ); return reader->unitName( adr ); } return ""; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiaDefines::EclipseUnitSystem RifReaderEclipseSummary::unitSystem() const { auto reader = currentSummaryReader(); if ( reader ) return reader->unitSystem(); return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const std::vector RifReaderEclipseSummary::ValuesCache::EMPTY_VECTOR; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifReaderEclipseSummary::ValuesCache::ValuesCache() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifReaderEclipseSummary::ValuesCache::~ValuesCache() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifReaderEclipseSummary::ValuesCache::insertValues( const RifEclipseSummaryAddress& address, const std::vector& values ) { m_cachedValues[address] = values; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const std::vector& RifReaderEclipseSummary::ValuesCache::getValues( const RifEclipseSummaryAddress& address ) const { if ( m_cachedValues.find( address ) != m_cachedValues.end() ) { return m_cachedValues.at( address ); } return EMPTY_VECTOR; }