From e9ff3540baa46005261207c3d5083f0c1283f960 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 19 Apr 2024 15:09:15 +0200 Subject: [PATCH] Update dev branch after patch release * Fix calculation for active cell values Always allocate result data for active cells in destination case. Make sure that active cells is used for both population of expression variables and filtering of data. Improved naming to make it clear that we always work with active cell data. * Check if scalar result index is valid * Create the static scalar results once addStaticScalarResult will clear already computed data, causing calculations to be triggered once more * Early return if data already is available If not checking if data is available, data is read from file and appended to result vector. * Always check date for H5 files, and recreate if required * Always recreate ESMRY if file exists and is older than SMSPEC * #11355 Use category if result name starts with FIP or ends with NUM * #11337 Summary import: Make sure ESMRY includes restart history * #11334 Fix cvf::Viewport assert triggered for small contour map/2d intersection Size of the overlay is could become negative, and would overflow for small views. * #11310 Fix assert on single cell model. Well pipe radius would become HUGE_VAL due to off-by-one error. The assert could only happen on model with a single cell. * Check equal grid size only when required Equal grid size is required if there is more than one grid case in the expression. If a cell filter view is active, the visibility is based on one view and reused for all other grid models, and requires equal grid size. * Remove obsolete log message * Do not show dialog during regression tests * Fix eclipse case contour map left click (#11378) * Make sure we operate in the correct domain when picking points in the contour map * Remove obsolete code causing grid to be loaded for all cases * Bump version to 2024.03.1 --------- Co-authored-by: Kristian Bendiksen Co-authored-by: jonjenssen <69144954+jonjenssen@users.noreply.github.com> --- .../Application/RiaResultNames.cpp | 11 ++ .../Application/RiaResultNames.h | 1 + .../RifEclipseInputFileTools.cpp | 3 +- .../RifEclipseInputPropertyLoader.cpp | 5 +- .../FileInterface/RifHdf5SummaryExporter.cpp | 47 ++++-- .../FileInterface/RifHdf5SummaryExporter.h | 6 +- .../FileInterface/RifOpmCommonSummary.cpp | 87 ++++++---- .../FileInterface/RifReaderEclipseSummary.cpp | 20 +-- .../ProjectDataModel/RimEclipseResultCase.cpp | 2 - .../RimEclipseResultDefinition.cpp | 2 + .../ProjectDataModel/RimGridCalculation.cpp | 148 +++++++++++------- .../ProjectDataModel/RimGridCalculation.h | 41 +++-- .../Summary/RimSummaryCaseMainCollection.cpp | 7 +- .../RigCaseCellResultsData.cpp | 18 ++- .../UnitTests/HDF5FileWriter-Test.cpp | 8 +- ResInsightVersion.cmake | 6 +- 16 files changed, 262 insertions(+), 150 deletions(-) diff --git a/ApplicationLibCode/Application/RiaResultNames.cpp b/ApplicationLibCode/Application/RiaResultNames.cpp index cac4338ada..6b6884d631 100644 --- a/ApplicationLibCode/Application/RiaResultNames.cpp +++ b/ApplicationLibCode/Application/RiaResultNames.cpp @@ -97,6 +97,17 @@ bool RiaResultNames::isFlowResultWithBothPosAndNegValues( const QString& resultN return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaResultNames::isCategoryResult( const QString& resultName ) +{ + if ( resultName.endsWith( "NUM", Qt::CaseInsensitive ) ) return true; + if ( resultName.startsWith( "FIP", Qt::CaseInsensitive ) ) return true; + + return false; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Application/RiaResultNames.h b/ApplicationLibCode/Application/RiaResultNames.h index 184aa85ff6..96c97c6046 100644 --- a/ApplicationLibCode/Application/RiaResultNames.h +++ b/ApplicationLibCode/Application/RiaResultNames.h @@ -32,6 +32,7 @@ namespace RiaResultNames bool isPerCellFaceResult( const QString& resultName ); bool isLogarithmicResult( const QString& resultName ); bool isFlowResultWithBothPosAndNegValues( const QString& resultName ); +bool isCategoryResult( const QString& resultName ); QString undefinedResultName(); QString undefinedGridFaultName(); diff --git a/ApplicationLibCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationLibCode/FileInterface/RifEclipseInputFileTools.cpp index 1682fb25cf..da706c9788 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationLibCode/FileInterface/RifEclipseInputFileTools.cpp @@ -22,6 +22,7 @@ #include "RiaCellDividingTools.h" #include "RiaLogging.h" +#include "RiaResultNames.h" #include "RiaStringEncodingTools.h" #include "RiaTextStringTools.h" @@ -439,7 +440,7 @@ bool RifEclipseInputFileTools::exportKeywords( const QString& resul if ( resultValues.empty() ) continue; double defaultExportValue = 0.0; - if ( keyword.endsWith( "NUM" ) ) + if ( RiaResultNames::isCategoryResult( keyword ) ) { defaultExportValue = 1.0; } diff --git a/ApplicationLibCode/FileInterface/RifEclipseInputPropertyLoader.cpp b/ApplicationLibCode/FileInterface/RifEclipseInputPropertyLoader.cpp index 9afa42eae3..aa98ed155a 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseInputPropertyLoader.cpp +++ b/ApplicationLibCode/FileInterface/RifEclipseInputPropertyLoader.cpp @@ -19,6 +19,7 @@ #include "RifEclipseInputPropertyLoader.h" #include "RiaLogging.h" +#include "RiaResultNames.h" #include "RifEclipseInputFileTools.h" #include "RifEclipseKeywordContent.h" @@ -177,8 +178,8 @@ bool RifEclipseInputPropertyLoader::appendNewInputPropertyResult( RigEclipseCase return false; } - bool endsWithNum = eclipseKeyword.ends_with( "NUM" ); - auto dataType = endsWithNum ? RiaDefines::ResultDataType::INTEGER : RiaDefines::ResultDataType::FLOAT; + bool isCategory = RiaResultNames::isCategoryResult( resultName ); + auto dataType = isCategory ? RiaDefines::ResultDataType::INTEGER : RiaDefines::ResultDataType::FLOAT; RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::INPUT_PROPERTY, dataType, resultName ); caseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->createResultEntry( resAddr, false ); diff --git a/ApplicationLibCode/FileInterface/RifHdf5SummaryExporter.cpp b/ApplicationLibCode/FileInterface/RifHdf5SummaryExporter.cpp index 89e614139a..5dcf45760d 100644 --- a/ApplicationLibCode/FileInterface/RifHdf5SummaryExporter.cpp +++ b/ApplicationLibCode/FileInterface/RifHdf5SummaryExporter.cpp @@ -45,6 +45,7 @@ //-------------------------------------------------------------------------------------------------- bool RifHdf5SummaryExporter::ensureHdf5FileIsCreatedMultithreaded( const std::vector& smspecFileNames, const std::vector& h5FileNames, + bool createHdfIfNotPresent, int threadCount ) { if ( smspecFileNames.empty() ) return true; @@ -61,7 +62,7 @@ bool RifHdf5SummaryExporter::ensureHdf5FileIsCreatedMultithreaded( const std::ve const auto& smspecFileName = smspecFileNames[cIdx]; const auto& h5FileName = h5FileNames[cIdx]; - RifHdf5SummaryExporter::ensureHdf5FileIsCreated( smspecFileName, h5FileName, hdfFilesCreatedCount ); + RifHdf5SummaryExporter::ensureHdf5FileIsCreated( smspecFileName, h5FileName, createHdfIfNotPresent, hdfFilesCreatedCount ); } if ( hdfFilesCreatedCount > 0 ) @@ -78,29 +79,47 @@ bool RifHdf5SummaryExporter::ensureHdf5FileIsCreatedMultithreaded( const std::ve //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RifHdf5SummaryExporter::ensureHdf5FileIsCreated( const std::string& smspecFileName, const std::string& h5FileName, size_t& hdfFilesCreatedCount ) +bool RifHdf5SummaryExporter::ensureHdf5FileIsCreated( const std::string& smspecFileName, + const std::string& h5FileName, + bool createHdfIfNotPresent, + size_t& hdfFilesCreatedCount ) { + // If an H5 file is present, and the SMSPEC file is newer than the H5 file, the H5 file will be recreated. + // If no H5 file is present, the H5 file will be created if the flag createHdfIfNotPresent is set to true. + // + // NB! Always make sure the logic is consistent with the logic in RifOpmCommonEclipseSummary::open + if ( !std::filesystem::exists( smspecFileName ) ) return false; - { - // Check if we have write permission in the folder - QFileInfo info( QString::fromStdString( smspecFileName ) ); - - if ( !info.isWritable() ) return true; - } - bool exportIsRequired = false; + bool h5FileExists = std::filesystem::exists( h5FileName ); + if ( !h5FileExists ) { - bool h5FileExists = std::filesystem::exists( h5FileName ); - if ( !h5FileExists ) + if ( createHdfIfNotPresent ) { exportIsRequired = true; } - else if ( RiaFilePathTools::isFirstOlderThanSecond( h5FileName, smspecFileName ) ) + } + else if ( RiaFilePathTools::isFirstOlderThanSecond( h5FileName, smspecFileName ) ) + { + // If both files are present, check if the SMSPEC file is newer than the H5 file. If the SMSPEC file is newer, we abort if it is not + // possible to write to the H5 file + + // Check if we have write permission in the folder + QFileInfo info( QString::fromStdString( smspecFileName ) ); + + if ( !info.isWritable() ) { - exportIsRequired = true; + QString txt = + QString( "HDF is older than SMSPEC, but export to file %1 failed due to missing write permissions. Aborting operation." ) + .arg( QString::fromStdString( h5FileName ) ); + RiaLogging::error( txt ); + + return false; } + + exportIsRequired = true; } if ( exportIsRequired ) @@ -127,7 +146,7 @@ bool RifHdf5SummaryExporter::ensureHdf5FileIsCreated( const std::string& smspecF } catch ( std::exception& e ) { - QString txt = QString( "HDF export to file %1 failed : %3" ).arg( QString::fromStdString( smspecFileName ), e.what() ); + QString txt = QString( "HDF export to file %1 failed : %2" ).arg( QString::fromStdString( smspecFileName ), e.what() ); RiaLogging::error( txt ); diff --git a/ApplicationLibCode/FileInterface/RifHdf5SummaryExporter.h b/ApplicationLibCode/FileInterface/RifHdf5SummaryExporter.h index 692b5d2787..991b9e35ea 100644 --- a/ApplicationLibCode/FileInterface/RifHdf5SummaryExporter.h +++ b/ApplicationLibCode/FileInterface/RifHdf5SummaryExporter.h @@ -42,9 +42,13 @@ class RifHdf5SummaryExporter public: static bool ensureHdf5FileIsCreatedMultithreaded( const std::vector& smspecFileNames, const std::vector& h5FileNames, + bool createHdfIfNotPresent, int threadCount ); - static bool ensureHdf5FileIsCreated( const std::string& smspecFileName, const std::string& h5FileName, size_t& hdfFilesCreatedCount ); + static bool ensureHdf5FileIsCreated( const std::string& smspecFileName, + const std::string& h5FileName, + bool createHdfIfNotPresent, + size_t& hdfFilesCreatedCount ); private: static bool writeGeneralSection( RifHdf5Exporter& exporter, Opm::EclIO::ESmry& sourceSummaryData ); diff --git a/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp b/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp index bfad38a75b..448653b8d8 100644 --- a/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp +++ b/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp @@ -84,50 +84,73 @@ size_t RifOpmCommonEclipseSummary::numberOfEnhancedSummaryFileCreated() //-------------------------------------------------------------------------------------------------- bool RifOpmCommonEclipseSummary::open( const QString& fileName, bool includeRestartFiles, RiaThreadSafeLogger* threadSafeLogger ) { - if ( m_createEsmryFiles ) + // If an ESMRY file is present, and the SMSPEC file is newer than the ESMRY file, the ESMRY file will be recreated. + // If no ESMRY file is present, the ESMRY file will be created if the flag m_createEsmryFiles is set to true. + // + // NB! Always make sure the logic is consistent with the logic in RifHdf5SummaryExporter::ensureHdf5FileIsCreated + + bool writeDataToEsmry = false; + + auto candidateEsmryFileName = enhancedSummaryFilename( fileName ); + + // Make sure to check the smspec file name, as it is supported to import ESMRY files without any SMSPEC data + auto smspecFileName = smspecSummaryFilename( fileName ); + + if ( !QFile::exists( candidateEsmryFileName ) && QFile::exists( smspecFileName ) && m_createEsmryFiles ) { - auto candidateEsmryFileName = enhancedSummaryFilename( fileName ); + writeDataToEsmry = true; + } - // Make sure to check the smspec file name, as it is supported to import ESMRY files without any SMSPEC data - auto smspecFileName = smspecSummaryFilename( fileName ); + if ( RiaFilePathTools::isFirstOlderThanSecond( candidateEsmryFileName.toStdString(), smspecFileName.toStdString() ) ) + { + QString root = QFileInfo( smspecFileName ).canonicalPath(); - if ( QFile::exists( candidateEsmryFileName ) && QFile::exists( smspecFileName ) && - RiaFilePathTools::isFirstOlderThanSecond( candidateEsmryFileName.toStdString(), smspecFileName.toStdString() ) ) + const QString smspecFileNameShort = QFileInfo( smspecFileName ).fileName(); + const QString esmryFileNameShort = QFileInfo( candidateEsmryFileName ).fileName(); + + RiaLogging::debug( + QString( " %3 : %1 is older than %2, recreating %1." ).arg( esmryFileNameShort ).arg( smspecFileNameShort ).arg( root ) ); + + // Check if we have write permission in the folder + QFileInfo info( smspecFileName ); + + if ( !info.isWritable() ) { - QString root = QFileInfo( smspecFileName ).canonicalPath(); + QString txt = + QString( "ESMRY is older than SMSPEC, but export to file %1 failed due to missing write permissions. Aborting operation." ) + .arg( candidateEsmryFileName ); + RiaLogging::error( txt ); - const QString smspecFileNameShort = QFileInfo( smspecFileName ).fileName(); - const QString esmryFileNameShort = QFileInfo( candidateEsmryFileName ).fileName(); - - RiaLogging::debug( - QString( " %3 : %1 is older than %2, recreating %1." ).arg( esmryFileNameShort ).arg( smspecFileNameShort ).arg( root ) ); - - std::filesystem::remove( candidateEsmryFileName.toStdString() ); + return false; } - if ( !QFile::exists( candidateEsmryFileName ) && QFile::exists( smspecFileName ) ) + std::filesystem::remove( candidateEsmryFileName.toStdString() ); + + writeDataToEsmry = true; + } + + if ( writeDataToEsmry ) + { + try { - try + auto temporarySummaryFile = std::make_unique( smspecFileName.toStdString(), includeRestartFiles ); + + if ( temporarySummaryFile->numberOfTimeSteps() > 0 ) { - auto temporarySummaryFile = std::make_unique( smspecFileName.toStdString(), includeRestartFiles ); - - if ( temporarySummaryFile->numberOfTimeSteps() > 0 ) - { - temporarySummaryFile->make_esmry_file(); - } - - RifOpmCommonEclipseSummary::increaseEsmryFileCount(); + temporarySummaryFile->make_esmry_file(); } - catch ( std::exception& ) + + RifOpmCommonEclipseSummary::increaseEsmryFileCount(); + } + catch ( std::exception& ) + { + if ( threadSafeLogger ) { - if ( threadSafeLogger ) - { - QString txt = QString( "Warning, could not open summary file : %1" ).arg( smspecFileName ); - threadSafeLogger->warning( txt ); - } - - return false; + QString txt = QString( "Warning, could not open summary file : %1" ).arg( smspecFileName ); + threadSafeLogger->warning( txt ); } + + return false; } } diff --git a/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp b/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp index 68f4c0ef1d..0ef8e0ee62 100644 --- a/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp +++ b/ApplicationLibCode/FileInterface/RifReaderEclipseSummary.cpp @@ -95,18 +95,18 @@ bool RifReaderEclipseSummary::open( const QString& headerFileName, RiaThreadSafe ( 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 ); + size_t createdH5FileCount = 0; + RifHdf5SummaryExporter::ensureHdf5FileIsCreated( headerFileName.toStdString(), + h5FileName.toStdString(), + prefSummary->createH5SummaryDataFiles(), + createdH5FileCount ); - if ( createdH5FileCount > 0 ) - { - QString txt = QString( "Created %1 " ).arg( h5FileName ); - if ( threadSafeLogger ) threadSafeLogger->info( txt ); - } - h5FileFound = QFile::exists( h5FileName ); + if ( createdH5FileCount > 0 ) + { + QString txt = QString( "Created %1 " ).arg( h5FileName ); + if ( threadSafeLogger ) threadSafeLogger->info( txt ); } + h5FileFound = QFile::exists( h5FileName ); if ( h5FileFound ) { diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.cpp index 63540ec2ab..fa389c7185 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseResultCase.cpp @@ -374,8 +374,6 @@ void RimEclipseResultCase::ensureRftDataIsImported() if ( rftFileInfo.exists() ) { - RiaLogging::info( QString( "RFT file found" ) ); - if ( m_useOpmRftReader ) { m_readerOpmRft = new RifReaderOpmRft( rftFileInfo.filePath() ); diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp index c5dea97ccf..e35bddd12b 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -1426,6 +1426,8 @@ bool RimEclipseResultDefinition::isCompletionTypeSelected() const //-------------------------------------------------------------------------------------------------- bool RimEclipseResultDefinition::hasCategoryResult() const { + if ( RiaResultNames::isCategoryResult( m_resultVariable() ) ) return true; + if ( auto* gridCellResults = currentGridCellResults() ) { const auto addresses = gridCellResults->existingResults(); diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.cpp b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.cpp index 0dfe24312f..ac64cf6395 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.cpp @@ -22,6 +22,7 @@ #include "RiaGuiApplication.h" #include "RiaLogging.h" #include "RiaPorosityModel.h" +#include "RiaRegressionTestRunner.h" #include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" @@ -118,7 +119,8 @@ RimGridCalculation::RimGridCalculation() //-------------------------------------------------------------------------------------------------- bool RimGridCalculation::preCalculate() const { - if ( RiaGuiApplication::isRunning() && m_additionalCasesType() != RimGridCalculation::AdditionalCasesType::NONE ) + if ( !RiaRegressionTestRunner::instance()->isRunningRegressionTests() && RiaGuiApplication::isRunning() && + m_additionalCasesType() != RimGridCalculation::AdditionalCasesType::NONE ) { const QString cacheKey = "GridCalculatorMessage"; @@ -171,18 +173,40 @@ RimGridCalculationVariable* RimGridCalculation::createVariable() //-------------------------------------------------------------------------------------------------- bool RimGridCalculation::calculate() { + // Equal grid size is required if there is more than one grid case in the expression. If a cell filter view is active, the visibility is + // based on one view and reused for all other grid models, and requires equal grid size. + bool checkIfGridSizeIsEqual = !allSourceCasesAreEqualToDestinationCase() || m_cellFilterView != nullptr; + for ( auto calculationCase : outputEclipseCases() ) { if ( !calculationCase ) continue; - for ( auto inputCase : inputCases() ) + if ( !calculationCase->eclipseCaseData() ) { - if ( !calculationCase->isGridSizeEqualTo( inputCase ) ) + QString msg = QString( "No data available for case %1, aborting calculation" ).arg( calculationCase->caseUserDescription() ); + RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", msg ); + return false; + } + + if ( !calculationCase->eclipseCaseData()->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ) ) + { + QString msg = + QString( "No active cell data available for case %1, aborting calculation" ).arg( calculationCase->caseUserDescription() ); + RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", msg ); + return false; + } + + if ( checkIfGridSizeIsEqual ) + { + for ( auto inputCase : inputCases() ) { - QString msg = "Detected IJK mismatch between input cases and destination case. All grid " - "cases must have identical IJK sizes."; - RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", msg ); - return false; + if ( !calculationCase->isGridSizeEqualTo( inputCase ) ) + { + QString msg = "Detected IJK mismatch between input cases and destination case. All grid " + "cases must have identical IJK sizes."; + RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", msg ); + return false; + } } } } @@ -537,11 +561,11 @@ RigEclipseResultAddress RimGridCalculation::outputAddress() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimGridCalculation::getDataForVariable( RimGridCalculationVariable* variable, - size_t tsId, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* sourceCase, - RimEclipseCase* destinationCase ) const +std::vector RimGridCalculation::getActiveCellValuesForVariable( RimGridCalculationVariable* variable, + size_t tsId, + RiaDefines::PorosityModelType porosityModel, + RimEclipseCase* sourceCase, + RimEclipseCase* destinationCase ) const { if ( !sourceCase || !destinationCase ) return {}; @@ -562,18 +586,19 @@ std::vector RimGridCalculation::getDataForVariable( RimGridCalculationVa timeStepToUse = timeStep; } - return getDataForResult( variable->resultVariable(), resultCategoryType, timeStepToUse, porosityModel, sourceCase, destinationCase ); + return getActiveCellValues( variable->resultVariable(), resultCategoryType, timeStepToUse, porosityModel, sourceCase, destinationCase ); } //-------------------------------------------------------------------------------------------------- -/// +/// Return values for active cells, both for dynamic and static results. Use the active cell info from the destination case, and read data +/// from the source case. //-------------------------------------------------------------------------------------------------- -std::vector RimGridCalculation::getDataForResult( const QString& resultName, - const RiaDefines::ResultCatType resultCategoryType, - size_t tsId, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* sourceCase, - RimEclipseCase* destinationCase ) const +std::vector RimGridCalculation::getActiveCellValues( const QString& resultName, + const RiaDefines::ResultCatType resultCategoryType, + size_t tsId, + RiaDefines::PorosityModelType porosityModel, + RimEclipseCase* sourceCase, + RimEclipseCase* destinationCase ) const { if ( !sourceCase || !destinationCase ) return {}; @@ -588,12 +613,15 @@ std::vector RimGridCalculation::getDataForResult( const QString& auto eclipseCaseData = sourceCase->eclipseCaseData(); auto rigCaseCellResultsData = eclipseCaseData->results( porosityModel ); - if ( !rigCaseCellResultsData->findOrLoadKnownScalarResultForTimeStep( resAddr, timeStepToUse ) ) return {}; + if ( rigCaseCellResultsData->findOrLoadKnownScalarResultForTimeStep( resAddr, timeStepToUse ) == cvf::UNDEFINED_SIZE_T ) return {}; // Active cell info must always be retrieved from the destination case, as the returned vector must be of the same size as // number of active cells in the destination case. Active cells can be different between source and destination case. auto activeCellInfoDestination = destinationCase->eclipseCaseData()->activeCellInfo( porosityModel ); - auto activeReservoirCells = activeCellInfoDestination->activeReservoirCellIndices(); + if ( !activeCellInfoDestination ) return {}; + + auto activeReservoirCells = activeCellInfoDestination->activeReservoirCellIndices(); + if ( activeReservoirCells.empty() ) return {}; std::vector values( activeCellInfoDestination->activeReservoirCellIndices().size() ); @@ -621,23 +649,25 @@ std::vector RimGridCalculation::getDataForResult( const QString& //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimGridCalculation::replaceFilteredValuesWithVector( const std::vector& inputValues, - cvf::ref visibility, - std::vector& resultValues, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* outputEclipseCase ) +void RimGridCalculation::replaceFilteredValuesWithVector( const std::vector& inputValues, + cvf::ref visibility, + std::vector& resultValues, + RigActiveCellInfo* activeCellInfo ) { - auto activeCellInfo = outputEclipseCase->eclipseCaseData()->activeCellInfo( porosityModel ); - int numCells = static_cast( visibility->size() ); + auto activeReservoirCellIndices = activeCellInfo->activeReservoirCellIndices(); + int numActiveCells = static_cast( activeReservoirCellIndices.size() ); + + CAF_ASSERT( numActiveCells == (int)resultValues.size() ); + CAF_ASSERT( numActiveCells == (int)inputValues.size() ); #pragma omp parallel for - for ( int i = 0; i < numCells; i++ ) + for ( int i = 0; i < numActiveCells; i++ ) { - if ( !visibility->val( i ) && activeCellInfo->isActive( i ) ) + const auto reservoirCellIndex = activeReservoirCellIndices[i]; + if ( !visibility->val( reservoirCellIndex ) ) { - size_t cellResultIndex = activeCellInfo->cellResultIndex( i ); - resultValues[cellResultIndex] = inputValues[cellResultIndex]; + resultValues[i] = inputValues[i]; } } } @@ -645,23 +675,24 @@ void RimGridCalculation::replaceFilteredValuesWithVector( const std::vector visibility, - std::vector& resultValues, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* outputEclipseCase ) +void RimGridCalculation::replaceFilteredValuesWithDefaultValue( double defaultValue, + cvf::ref visibility, + std::vector& resultValues, + RigActiveCellInfo* activeCellInfo ) { - auto activeCellInfo = outputEclipseCase->eclipseCaseData()->activeCellInfo( porosityModel ); - int numCells = static_cast( visibility->size() ); + auto activeReservoirCellIndices = activeCellInfo->activeReservoirCellIndices(); + int numActiveCells = static_cast( activeReservoirCellIndices.size() ); + + CAF_ASSERT( numActiveCells == (int)resultValues.size() ); #pragma omp parallel for - for ( int i = 0; i < numCells; i++ ) + for ( int i = 0; i < numActiveCells; i++ ) { - if ( !visibility->val( i ) && activeCellInfo->isActive( i ) ) + const auto reservoirCellIndex = activeReservoirCellIndices[i]; + if ( !visibility->val( reservoirCellIndex ) ) { - size_t cellResultIndex = activeCellInfo->cellResultIndex( i ); - resultValues[cellResultIndex] = defaultValue; + resultValues[i] = defaultValue; } } } @@ -681,18 +712,20 @@ void RimGridCalculation::filterResults( RimGridView* { auto visibility = cellFilterView->currentTotalCellVisibility(); + auto activeCellInfo = outputEclipseCase->eclipseCaseData()->activeCellInfo( porosityModel ); + if ( defaultValueType == RimGridCalculation::DefaultValueType::FROM_PROPERTY ) { - auto nonVisibleValues = getDataForResult( m_nonVisibleResultAddress->resultName(), - m_nonVisibleResultAddress->resultType(), - timeStep, - porosityModel, - m_nonVisibleResultAddress->eclipseCase(), - outputEclipseCase ); + auto nonVisibleValues = getActiveCellValues( m_nonVisibleResultAddress->resultName(), + m_nonVisibleResultAddress->resultType(), + timeStep, + porosityModel, + outputEclipseCase, + outputEclipseCase ); if ( !nonVisibleValues.empty() ) { - replaceFilteredValuesWithVector( nonVisibleValues, visibility, resultValues, porosityModel, outputEclipseCase ); + replaceFilteredValuesWithVector( nonVisibleValues, visibility, resultValues, activeCellInfo ); } else { @@ -706,7 +739,7 @@ void RimGridCalculation::filterResults( RimGridView* double valueToUse = defaultValue; if ( defaultValueType == RimGridCalculation::DefaultValueType::POSITIVE_INFINITY ) valueToUse = HUGE_VAL; - replaceFilteredValuesWithDefaultValue( valueToUse, visibility, resultValues, porosityModel, outputEclipseCase ); + replaceFilteredValuesWithDefaultValue( valueToUse, visibility, resultValues, activeCellInfo ); } } @@ -873,15 +906,16 @@ bool RimGridCalculation::calculateForCases( const std::vector& bool useDataFromSourceCase = ( v->eclipseCase() == m_destinationCase ); auto sourceCase = useDataFromSourceCase ? calculationCase : v->eclipseCase(); - auto dataForVariable = getDataForVariable( v, tsId, porosityModel, sourceCase, calculationCase ); + auto dataForVariable = getActiveCellValuesForVariable( v, tsId, porosityModel, sourceCase, calculationCase ); if ( dataForVariable.empty() ) { RiaLogging::error( QString( " No data found for variable '%1'." ).arg( v->name() ) ); } else if ( inputValueVisibilityFilter && hasAggregationExpression ) { - const double defaultValue = 0.0; - replaceFilteredValuesWithDefaultValue( defaultValue, inputValueVisibilityFilter, dataForVariable, porosityModel, calculationCase ); + const double defaultValue = 0.0; + auto activeCellInfo = calculationCase->eclipseCaseData()->activeCellInfo( porosityModel ); + replaceFilteredValuesWithDefaultValue( defaultValue, inputValueVisibilityFilter, dataForVariable, activeCellInfo ); } dataForAllVariables.push_back( dataForVariable ); @@ -896,10 +930,10 @@ bool RimGridCalculation::calculateForCases( const std::vector& } std::vector resultValues; - if ( m_destinationCase && m_destinationCase->eclipseCaseData() ) + if ( calculationCase && calculationCase->eclipseCaseData() ) { // Find number of active cells in the destination case. - auto activeCellInfoDestination = m_destinationCase->eclipseCaseData()->activeCellInfo( porosityModel ); + auto activeCellInfoDestination = calculationCase->eclipseCaseData()->activeCellInfo( porosityModel ); if ( activeCellInfoDestination ) { resultValues.resize( activeCellInfoDestination->reservoirActiveCellCount() ); diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h index 45f1e75309..a4454f5a5b 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h +++ b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h @@ -34,6 +34,7 @@ class RimGridView; class RigEclipseResultAddress; class RimEclipseResultAddress; class RimIdenticalGridCaseGroup; +class RigActiveCellInfo; //================================================================================================== /// @@ -88,18 +89,18 @@ protected: std::pair validateVariables(); - std::vector getDataForVariable( RimGridCalculationVariable* variable, - size_t tsId, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* sourceCase, - RimEclipseCase* destinationCase ) const; + std::vector getActiveCellValuesForVariable( RimGridCalculationVariable* variable, + size_t tsId, + RiaDefines::PorosityModelType porosityModel, + RimEclipseCase* sourceCase, + RimEclipseCase* destinationCase ) const; - std::vector getDataForResult( const QString& resultName, - const RiaDefines::ResultCatType resultCategoryType, - size_t tsId, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* sourceCase, - RimEclipseCase* destinationCase ) const; + std::vector getActiveCellValues( const QString& resultName, + const RiaDefines::ResultCatType resultCategoryType, + size_t tsId, + RiaDefines::PorosityModelType porosityModel, + RimEclipseCase* sourceCase, + RimEclipseCase* destinationCase ) const; void filterResults( RimGridView* cellFilterView, const std::vector>& values, @@ -110,17 +111,15 @@ protected: RiaDefines::PorosityModelType porosityModel, RimEclipseCase* outputEclipseCase ) const; - static void replaceFilteredValuesWithVector( const std::vector& inputValues, - cvf::ref visibility, - std::vector& resultValues, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* outputEclipseCase ); + static void replaceFilteredValuesWithVector( const std::vector& inputValues, + cvf::ref visibility, + std::vector& resultValues, + RigActiveCellInfo* activeCellInfo ); - static void replaceFilteredValuesWithDefaultValue( double defaultValue, - cvf::ref visibility, - std::vector& resultValues, - RiaDefines::PorosityModelType porosityModel, - RimEclipseCase* outputEclipseCase ); + static void replaceFilteredValuesWithDefaultValue( double defaultValue, + cvf::ref visibility, + std::vector& resultValues, + RigActiveCellInfo* activeCellInfo ); using DefaultValueConfig = std::pair; DefaultValueConfig defaultValueConfiguration() const; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp index fb52c03c40..d38616948d 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp @@ -411,7 +411,7 @@ void RimSummaryCaseMainCollection::loadFileSummaryCaseData( std::vectorsummaryDataReader() == RiaPreferencesSummary::SummaryReaderMode::HDF5_OPM_COMMON && prefs->createH5SummaryDataFiles() ) + if ( prefs->summaryDataReader() == RiaPreferencesSummary::SummaryReaderMode::HDF5_OPM_COMMON ) { int threadCount = 1; #ifdef USE_OPENMP @@ -433,7 +433,10 @@ void RimSummaryCaseMainCollection::loadFileSummaryCaseData( std::vectorcreateH5SummaryDataFiles(), + threadCount ); } } #endif diff --git a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp index cb64d22518..3f635d809f 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -1116,14 +1116,20 @@ void RigCaseCellResultsData::createPlaceholderResultEntries() // Cell Volume { - addStaticScalarResult( RiaDefines::ResultCatType::STATIC_NATIVE, RiaResultNames::riCellVolumeResultName(), needsToBeStored, 0 ); + if ( !hasResultEntry( RigEclipseResultAddress( RiaDefines::ResultCatType::STATIC_NATIVE, RiaResultNames::riCellVolumeResultName() ) ) ) + { + addStaticScalarResult( RiaDefines::ResultCatType::STATIC_NATIVE, RiaResultNames::riCellVolumeResultName(), needsToBeStored, 0 ); + } } // Mobile Pore Volume { if ( hasResultEntry( RigEclipseResultAddress( RiaDefines::ResultCatType::STATIC_NATIVE, "PORV" ) ) ) { - addStaticScalarResult( RiaDefines::ResultCatType::STATIC_NATIVE, RiaResultNames::mobilePoreVolumeName(), needsToBeStored, 0 ); + if ( !hasResultEntry( RigEclipseResultAddress( RiaDefines::ResultCatType::STATIC_NATIVE, RiaResultNames::mobilePoreVolumeName() ) ) ) + { + addStaticScalarResult( RiaDefines::ResultCatType::STATIC_NATIVE, RiaResultNames::mobilePoreVolumeName(), needsToBeStored, 0 ); + } } } @@ -1581,6 +1587,13 @@ size_t RigCaseCellResultsData::findOrLoadKnownScalarResultByResultTypeOrder( con //-------------------------------------------------------------------------------------------------- size_t RigCaseCellResultsData::findOrLoadKnownScalarResultForTimeStep( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex ) { + size_t scalarResultIndex = findScalarResultIndexFromAddress( resVarAddr ); + if ( scalarResultIndex == cvf::UNDEFINED_SIZE_T ) + { + return cvf::UNDEFINED_SIZE_T; + } + if ( isDataPresent( scalarResultIndex ) ) return scalarResultIndex; + RiaDefines::ResultCatType type = resVarAddr.resultCatType(); QString resultName = resVarAddr.resultName(); @@ -1609,7 +1622,6 @@ size_t RigCaseCellResultsData::findOrLoadKnownScalarResultForTimeStep( const Rig return completionTypeScalarResultIndex; } - size_t scalarResultIndex = findScalarResultIndexFromAddress( resVarAddr ); if ( scalarResultIndex == cvf::UNDEFINED_SIZE_T ) return cvf::UNDEFINED_SIZE_T; if ( type == RiaDefines::ResultCatType::GENERATED ) diff --git a/ApplicationLibCode/UnitTests/HDF5FileWriter-Test.cpp b/ApplicationLibCode/UnitTests/HDF5FileWriter-Test.cpp index 5c90f4d1ff..207016b9c8 100644 --- a/ApplicationLibCode/UnitTests/HDF5FileWriter-Test.cpp +++ b/ApplicationLibCode/UnitTests/HDF5FileWriter-Test.cpp @@ -35,8 +35,12 @@ TEST( DISABLED_HDFTests, WriteToHdf5SummaryExporter ) std::string exportFileName = "e:/project/scratch_export/hdf_complete.h5"; - int threadCount = 1; - RifHdf5SummaryExporter::ensureHdf5FileIsCreatedMultithreaded( { file_path.toStdString() }, { exportFileName }, threadCount ); + int threadCount = 1; + bool createEnhancedSummaryFiles = true; + RifHdf5SummaryExporter::ensureHdf5FileIsCreatedMultithreaded( { file_path.toStdString() }, + { exportFileName }, + createEnhancedSummaryFiles, + threadCount ); } //-------------------------------------------------------------------------------------------------- diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 19d477d55e..0a6fef1f9e 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -1,17 +1,17 @@ set(RESINSIGHT_MAJOR_VERSION 2024) set(RESINSIGHT_MINOR_VERSION 03) -set(RESINSIGHT_PATCH_VERSION 1) +set(RESINSIGHT_PATCH_VERSION 2) # Opional text with no restrictions set(RESINSIGHT_VERSION_TEXT "-dev") -#set(RESINSIGHT_VERSION_TEXT "-RC_05") +#set(RESINSIGHT_VERSION_TEXT "-RC_02") # Optional text # Must be unique and increasing within one combination of major/minor/patch version # The uniqueness of this text is independent of RESINSIGHT_VERSION_TEXT # Format of text must be ".xx" -set(RESINSIGHT_DEV_VERSION ".05") +set(RESINSIGHT_DEV_VERSION ".01") # https://github.com/CRAVA/crava/tree/master/libs/nrlib set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f")