From e3f7e3f1c73a91509d6ea385dddce1f73e0c1f70 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 24 Jun 2026 14:32:16 +0200 Subject: [PATCH] #14309 Open summary case without UNSMRY data file as empty reader A SMSPEC file without a UNSMRY data file is re-read on every request for a summary vector, since RifReaderEclipseSummary::open returns false and no reader is cached. For an ensemble with multiple realizations missing UNSMRY, this is a severe performance problem. Guard RifReaderEclipseSummary::open so that when no ESMRY, h5 or resdata data file is present, it returns true and creates a valid but empty reader. Skip ESMRY conversion when no UNSMRY is present, and add RifEclipseSummaryTools::hasSummaryDataFiles to detect the missing data file. --- .../FileInterface/RifEclipseSummaryTools.cpp | 12 ++++++++++ .../FileInterface/RifEclipseSummaryTools.h | 2 ++ .../FileInterface/RifOpmSummaryTools.cpp | 5 +++++ .../FileInterface/RifReaderEclipseSummary.cpp | 22 +++++++++++++++++++ .../UnitTests/opm-summary-Test.cpp | 5 +++-- 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/ApplicationLibCode/FileInterface/RifEclipseSummaryTools.cpp b/ApplicationLibCode/FileInterface/RifEclipseSummaryTools.cpp index 7fbd52a249..ee1405ff33 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseSummaryTools.cpp +++ b/ApplicationLibCode/FileInterface/RifEclipseSummaryTools.cpp @@ -492,6 +492,18 @@ RiaDefines::EclipseUnitSystem RifEclipseSummaryTools::readUnitSystem( ecl_sum_ty } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifEclipseSummaryTools::hasSummaryDataFiles( const QString& headerFileName ) +{ + QString foundHeaderFile; + QStringList dataFileNames; + findSummaryFiles( QDir::toNativeSeparators( headerFileName ), &foundHeaderFile, &dataFileNames ); + + return !dataFileNames.isEmpty(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/FileInterface/RifEclipseSummaryTools.h b/ApplicationLibCode/FileInterface/RifEclipseSummaryTools.h index bbf090b7ed..4489e812d4 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseSummaryTools.h +++ b/ApplicationLibCode/FileInterface/RifEclipseSummaryTools.h @@ -72,6 +72,8 @@ public: static RifRestartFileInfo getFileInfoAndTimeSteps( const QString& headerFileName ); + static bool hasSummaryDataFiles( const QString& headerFileName ); + static void closeEclSum( ecl_sum_type* ecl_sum ); static ecl_sum_type* openEclSum( const QString& inHeaderFileName, bool includeRestartFiles ); static RiaDefines::EclipseUnitSystem readUnitSystem( ecl_sum_type* ecl_sum ); diff --git a/ApplicationLibCode/FileInterface/RifOpmSummaryTools.cpp b/ApplicationLibCode/FileInterface/RifOpmSummaryTools.cpp index a2a769f7d6..0abf0c69fa 100644 --- a/ApplicationLibCode/FileInterface/RifOpmSummaryTools.cpp +++ b/ApplicationLibCode/FileInterface/RifOpmSummaryTools.cpp @@ -178,6 +178,11 @@ bool RifOpmSummaryTools::isEsmryConversionRequired( const QString& fileName ) auto candidateEsmryFileName = enhancedSummaryFilename( fileName ); auto smspecFileName = smspecSummaryFilename( fileName ); + // Conversion reads the SMSPEC/UNSMRY pair. Without the UNSMRY data file there is nothing to convert. + QString unsmryFileName( smspecFileName ); + unsmryFileName.replace( ".SMSPEC", ".UNSMRY" ); + if ( !QFile::exists( unsmryFileName ) ) return false; + if ( !QFile::exists( candidateEsmryFileName ) && QFile::exists( smspecFileName ) ) { return true; diff --git a/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp b/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp index e5c426219c..403beb7a4f 100644 --- a/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp +++ b/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp @@ -23,6 +23,7 @@ #include "RiaStdStringTools.h" #include "RifEclEclipseSummary.h" +#include "RifEclipseSummaryTools.h" #include "RifOpmCommonSummary.h" #ifdef USE_HDF5 @@ -90,6 +91,27 @@ bool RifReaderEclipseSummary::open( const QString& headerFileName, RiaThreadSafe RiaPreferencesSummary* prefSummary = RiaPreferencesSummary::current(); + // A realization that is still being simulated may have written only the SMSPEC header, without any + // summary data file. Some file readers (opm-common) throw when no data file is present. In this case, + // do not attempt to create a real file reader. Allow this reader to be created as a valid, but empty, + // summary reader. The query methods report empty data when no underlying reader has been created. + { + QFileInfo fi( headerFileName ); + QString basenameNoExtension = fi.absolutePath() + "/" + fi.baseName(); + + bool hasEnhancedSummaryFile = QFile::exists( basenameNoExtension + ".ESMRY" ); + bool hasHdf5File = QFile::exists( basenameNoExtension + ".h5" ); + bool hasUnsmryDataFile = RifEclipseSummaryTools::hasSummaryDataFiles( headerFileName ); + + if ( !hasEnhancedSummaryFile && !hasHdf5File && !hasUnsmryDataFile ) + { + QString txt = "No summary data file found for " + headerFileName + ". Creating an empty summary reader."; + if ( threadSafeLogger ) threadSafeLogger->info( txt ); + + return true; + } + } + if ( prefSummary->summaryDataReader() == RiaPreferencesSummary::SummaryReaderMode::HDF5_OPM_COMMON || prefSummary->summaryDataReader() == RiaPreferencesSummary::SummaryReaderMode::OPM_COMMON ) { diff --git a/ApplicationLibCode/UnitTests/opm-summary-Test.cpp b/ApplicationLibCode/UnitTests/opm-summary-Test.cpp index 887a8246c8..fced05c15e 100644 --- a/ApplicationLibCode/UnitTests/opm-summary-Test.cpp +++ b/ApplicationLibCode/UnitTests/opm-summary-Test.cpp @@ -418,8 +418,9 @@ TEST( OpmSummaryTests, ReadSmspecWithoutUnsmryEmptyReader ) RifReaderEclipseSummary reader; - // No summary data file is present, so opening fails, but it must not crash or throw. - EXPECT_FALSE( reader.open( filePath, nullptr ) ); + // No summary data file is present, but opening must succeed and create a valid, but empty, reader. + // This ensures the case is opened once and not re-read on every request. + EXPECT_TRUE( reader.open( filePath, nullptr ) ); reader.createAndSetAddresses();