mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
#14391 Expose RMS seed value from RMS_SEED_USED file as a realization parameter
This commit is contained in:
1 parent
69faf4ac13
commit
32cfac7722
13 files changed
+218
-6
No files matched your search
@@ -194,6 +194,14 @@ QString RiaDefines::summaryRealizationNumber()
|
||||
return "RI:REALIZATION_NUM";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RiaDefines::summaryRmsSeed()
|
||||
{
|
||||
return "RMS_SEED_USED";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -68,6 +68,7 @@ QString summaryLgrBlock();
|
||||
QString summaryCalculated();
|
||||
|
||||
QString summaryRealizationNumber();
|
||||
QString summaryRmsSeed();
|
||||
|
||||
QString key1VariableName();
|
||||
QString key2VariableName();
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "RifOpmSummaryTools.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
@@ -281,6 +283,75 @@ QString RifCaseRealizationParametersFileLocator::locate( const QString& modelPat
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RifRmsSeedFileReader::fileName()
|
||||
{
|
||||
return "RMS_SEED_USED";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Locate the RMS seed file "rms/model/RMS_SEED_USED" relative to one of the parent directories of
|
||||
/// the given model file or folder, i.e. "<ensemble>/realization-N/iter-M/rms/model/RMS_SEED_USED"
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RifRmsSeedFileReader::locate( const QString& modelPath )
|
||||
{
|
||||
int MAX_LEVELS_UP = 5;
|
||||
int dirLevel = 0;
|
||||
|
||||
QDir qdir( modelPath );
|
||||
|
||||
const QFileInfo dir( modelPath );
|
||||
if ( dir.isFile() )
|
||||
qdir.cdUp();
|
||||
else if ( !dir.isDir() )
|
||||
return "";
|
||||
|
||||
do
|
||||
{
|
||||
QString candidate = qdir.absoluteFilePath( "rms/model/" + fileName() );
|
||||
if ( QFileInfo::exists( candidate ) ) return candidate;
|
||||
|
||||
qdir.cdUp();
|
||||
|
||||
} while ( dirLevel++ < MAX_LEVELS_UP );
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Read the RMS seed value from the last token of the last non-empty line, allowing the value to be
|
||||
/// preceded by a timestamp or other text: "25-07-2025 10:33:06 ... 81472369"
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::optional<double> RifRmsSeedFileReader::readSeedValue( const QString& filePath )
|
||||
{
|
||||
QFile file( filePath );
|
||||
if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) return std::nullopt;
|
||||
|
||||
QTextStream dataStream( &file );
|
||||
|
||||
QString lastNonEmptyLine;
|
||||
while ( !dataStream.atEnd() )
|
||||
{
|
||||
QString line = dataStream.readLine().trimmed();
|
||||
if ( !line.isEmpty() ) lastNonEmptyLine = line;
|
||||
}
|
||||
|
||||
if ( lastNonEmptyLine.isEmpty() ) return std::nullopt;
|
||||
|
||||
const QStringList tokens = RiaTextStringTools::splitSkipEmptyParts( lastNonEmptyLine, QRegularExpression( "\\s+" ) );
|
||||
if ( tokens.isEmpty() ) return std::nullopt;
|
||||
|
||||
const auto valueText = tokens.back().toStdString();
|
||||
if ( !RiaStdStringTools::isNumber( valueText, RiaStdStringTools::decimalPoint() ) ) return std::nullopt;
|
||||
|
||||
double value = 0.0;
|
||||
if ( !RiaStdStringTools::toDouble( valueText, value ) ) return std::nullopt;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -95,3 +96,15 @@ public:
|
||||
static QString locate( const QString& modelPath );
|
||||
static int realizationNumber( const QString& modelPath );
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class RifRmsSeedFileReader
|
||||
{
|
||||
public:
|
||||
static QString fileName();
|
||||
static QString locate( const QString& modelPath );
|
||||
static std::optional<double> readSeedValue( const QString& filePath );
|
||||
};
|
||||
@@ -60,12 +60,15 @@ void RifEnsembleImportConfig::computePatternsFromSummaryFilePaths( const QString
|
||||
|
||||
auto restartFileNames1 = RifEclipseSummaryTools::getRestartFileNames( filePath1, warnings );
|
||||
auto paramFilePath1 = RifCaseRealizationParametersFileLocator::locate( filePath1 );
|
||||
auto rmsSeedFilePath1 = RifRmsSeedFileReader::locate( filePath1 );
|
||||
|
||||
auto restartFileNames2 = RifEclipseSummaryTools::getRestartFileNames( filePath2, warnings );
|
||||
auto paramFilePath2 = RifCaseRealizationParametersFileLocator::locate( filePath2 );
|
||||
auto rmsSeedFilePath2 = RifRmsSeedFileReader::locate( filePath2 );
|
||||
|
||||
computeRestartPatternsFromTwoRealizations( restartFileNames1, restartFileNames2 );
|
||||
computeParameterFilePathPattern( { paramFilePath1, paramFilePath2 } );
|
||||
computeRmsSeedFilePathPattern( { rmsSeedFilePath1, rmsSeedFilePath2 } );
|
||||
|
||||
m_useConfigValues = true;
|
||||
}
|
||||
@@ -138,6 +141,40 @@ void RifEnsembleImportConfig::computeParameterFilePathPattern( const std::vector
|
||||
m_parameterFilePathPattern = pattern;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RifEnsembleImportConfig::pathToRmsSeedFile( int realizationNumber ) const
|
||||
{
|
||||
QString numberString = QString::number( realizationNumber );
|
||||
|
||||
auto rmsSeedFilePath = m_rmsSeedFilePathPattern;
|
||||
rmsSeedFilePath.replace( placeholderText(), numberString );
|
||||
return rmsSeedFilePath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifEnsembleImportConfig::computeRmsSeedFilePathPattern( const std::vector<QString>& filePaths )
|
||||
{
|
||||
m_rmsSeedFilePathPattern.clear();
|
||||
|
||||
// The RMS seed file is optional, keep the pattern empty without reporting errors if it is not found
|
||||
QStringList filePathsList;
|
||||
for ( const auto& filePath : filePaths )
|
||||
{
|
||||
if ( filePath.isEmpty() ) return;
|
||||
filePathsList.push_back( filePath );
|
||||
}
|
||||
|
||||
if ( filePathsList.size() < 2 ) return;
|
||||
|
||||
const auto [pattern, range] = RiaEnsembleImportTools::findPathPattern( filePathsList, RifEnsembleImportConfig::placeholderText() );
|
||||
|
||||
m_rmsSeedFilePathPattern = pattern;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -29,6 +29,7 @@ public:
|
||||
|
||||
std::vector<QString> restartFilesForRealization( int realizationNumber ) const;
|
||||
QString pathToParameterFile( int realizationNumber ) const;
|
||||
QString pathToRmsSeedFile( int realizationNumber ) const;
|
||||
bool useConfigValues() const;
|
||||
|
||||
private:
|
||||
@@ -36,6 +37,7 @@ private:
|
||||
const std::vector<QString>& restartFilesSecondCase );
|
||||
|
||||
void computeParameterFilePathPattern( const std::vector<QString>& filePaths );
|
||||
void computeRmsSeedFilePathPattern( const std::vector<QString>& filePaths );
|
||||
|
||||
static QString placeholderText();
|
||||
|
||||
@@ -43,4 +45,5 @@ private:
|
||||
bool m_useConfigValues = false;
|
||||
std::vector<QString> m_restartFileNamePatterns;
|
||||
QString m_parameterFilePathPattern;
|
||||
QString m_rmsSeedFilePathPattern;
|
||||
};
|
||||
@@ -62,13 +62,18 @@
|
||||
#include <QDir>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimSummaryCaseMainCollection, "SummaryCaseCollection" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Internal function
|
||||
/// Internal function. An empty rmsSeedFileCandidate means the RMS seed file is known to be absent, while std::nullopt
|
||||
/// means the file system must be searched for the file.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void addCaseRealizationParametersIfFound( RimSummaryCase& sumCase, const QString modelFolderOrFile, const QString& filePathCandidate )
|
||||
void addCaseRealizationParametersIfFound( RimSummaryCase& sumCase,
|
||||
const QString modelFolderOrFile,
|
||||
const QString& filePathCandidate,
|
||||
const std::optional<QString>& rmsSeedFileCandidate )
|
||||
{
|
||||
std::shared_ptr<RigCaseRealizationParameters> parameters;
|
||||
|
||||
@@ -90,7 +95,8 @@ void addCaseRealizationParametersIfFound( RimSummaryCase& sumCase, const QString
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if ( !parameters )
|
||||
{
|
||||
parameters = std::make_shared<RigCaseRealizationParameters>();
|
||||
}
|
||||
@@ -101,6 +107,18 @@ void addCaseRealizationParametersIfFound( RimSummaryCase& sumCase, const QString
|
||||
parameters->setRealizationNumber( realizationNumber );
|
||||
parameters->addParameter( RiaDefines::summaryRealizationNumber(), realizationNumber );
|
||||
|
||||
// If present, expose the RMS seed value from "rms/model/RMS_SEED_USED" as a realization parameter. Ignore missing
|
||||
// or malformed files silently.
|
||||
QString rmsSeedFile = rmsSeedFileCandidate.has_value() ? rmsSeedFileCandidate.value()
|
||||
: RifRmsSeedFileReader::locate( modelFolderOrFile );
|
||||
if ( !rmsSeedFile.isEmpty() )
|
||||
{
|
||||
if ( auto seedValue = RifRmsSeedFileReader::readSeedValue( rmsSeedFile ) )
|
||||
{
|
||||
parameters->addParameter( RiaDefines::summaryRmsSeed(), seedValue.value() );
|
||||
}
|
||||
}
|
||||
|
||||
sumCase.setCaseRealizationParameters( parameters );
|
||||
}
|
||||
}
|
||||
@@ -495,7 +513,7 @@ void RimSummaryCaseMainCollection::loadSummaryCaseData( const std::vector<RimSum
|
||||
{
|
||||
sumCase->createSummaryReaderInterface();
|
||||
sumCase->createRftReaderInterface();
|
||||
addCaseRealizationParametersIfFound( *sumCase, sumCase->summaryHeaderFilename(), {} );
|
||||
addCaseRealizationParametersIfFound( *sumCase, sumCase->summaryHeaderFilename(), {}, std::nullopt );
|
||||
}
|
||||
|
||||
{
|
||||
@@ -595,18 +613,20 @@ void RimSummaryCaseMainCollection::loadFileSummaryCaseData( const std::vector<Ri
|
||||
{
|
||||
fileSummaryCase->createSummaryReaderInterfaceThreadSafe( importState, &threadSafeLogger );
|
||||
|
||||
QString parameterFilePath;
|
||||
QString parameterFilePath;
|
||||
std::optional<QString> rmsSeedFilePath;
|
||||
if ( importState.useConfigValues() )
|
||||
{
|
||||
auto realizationNumber = RifOpmSummaryTools::extractRealizationNumber( fileSummaryCase->summaryHeaderFilename() );
|
||||
if ( realizationNumber.has_value() )
|
||||
{
|
||||
parameterFilePath = importState.pathToParameterFile( realizationNumber.value() );
|
||||
rmsSeedFilePath = importState.pathToRmsSeedFile( realizationNumber.value() );
|
||||
}
|
||||
}
|
||||
|
||||
auto startTime = RiaLogging::currentTime();
|
||||
addCaseRealizationParametersIfFound( *fileSummaryCase, fileSummaryCase->summaryHeaderFilename(), parameterFilePath );
|
||||
addCaseRealizationParametersIfFound( *fileSummaryCase, fileSummaryCase->summaryHeaderFilename(), parameterFilePath, rmsSeedFilePath );
|
||||
bool isLoggingEnabled = RiaPreferencesSystem::current()->isLoggingActivatedForKeyword( "OpmSummaryImport" );
|
||||
if ( isLoggingEnabled )
|
||||
{
|
||||
|
||||
@@ -95,6 +95,58 @@ TEST( RifCaseRealizationParametersReaderTest, SuccessfulParsing )
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RifRmsSeedFileReaderTest, LocatorTestSuccess )
|
||||
{
|
||||
QString modelDir = CASE_REAL_TEST_DATA_DIRECTORY_01 + "rms_seed/realization-1/iter-0/eclipse/model";
|
||||
|
||||
QString file = RifRmsSeedFileReader::locate( modelDir );
|
||||
QString expected = CASE_REAL_TEST_DATA_DIRECTORY_01 + "rms_seed/realization-1/iter-0/rms/model/RMS_SEED_USED";
|
||||
EXPECT_EQ( expected.toStdString(), file.toStdString() );
|
||||
|
||||
auto seedValue = RifRmsSeedFileReader::readSeedValue( file );
|
||||
EXPECT_TRUE( seedValue.has_value() );
|
||||
EXPECT_EQ( 81472369.0, seedValue.value() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RifRmsSeedFileReaderTest, LocatorTestFailure )
|
||||
{
|
||||
QString file = RifRmsSeedFileReader::locate( CASE_REAL_TEST_DATA_DIRECTORY_01 + "4/3/2" );
|
||||
EXPECT_TRUE( file.isEmpty() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RifRmsSeedFileReaderTest, ReadSeedValue )
|
||||
{
|
||||
{
|
||||
auto seedValue =
|
||||
RifRmsSeedFileReader::readSeedValue( CASE_REAL_TEST_DATA_DIRECTORY_01 + "rms_seed_files/RMS_SEED_USED_single_value" );
|
||||
EXPECT_TRUE( seedValue.has_value() );
|
||||
EXPECT_EQ( 81472369.0, seedValue.value() );
|
||||
}
|
||||
{
|
||||
// Use the seed value from the last non-empty line
|
||||
auto seedValue = RifRmsSeedFileReader::readSeedValue( CASE_REAL_TEST_DATA_DIRECTORY_01 + "rms_seed_files/RMS_SEED_USED_multiline" );
|
||||
EXPECT_TRUE( seedValue.has_value() );
|
||||
EXPECT_EQ( 81472369.0, seedValue.value() );
|
||||
}
|
||||
{
|
||||
auto seedValue = RifRmsSeedFileReader::readSeedValue( CASE_REAL_TEST_DATA_DIRECTORY_01 + "rms_seed_files/RMS_SEED_USED_invalid" );
|
||||
EXPECT_FALSE( seedValue.has_value() );
|
||||
}
|
||||
{
|
||||
auto seedValue = RifRmsSeedFileReader::readSeedValue( CASE_REAL_TEST_DATA_DIRECTORY_01 + "rms_seed_files/does_not_exist" );
|
||||
EXPECT_FALSE( seedValue.has_value() );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
Placeholder file to make sure this directory is added to git
|
||||
+1
@@ -0,0 +1 @@
|
||||
25-07-2025 10:33:06 ... 81472369
|
||||
+1
@@ -0,0 +1 @@
|
||||
no seed value in this file
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
22-07-2025 08:00:00 ... 11111111
|
||||
25-07-2025 10:33:06 ... 81472369
|
||||
|
||||
Reference in new issue
Block a user