From 581b2689288604b2770e017bdc5c9dd720e42c6d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 22 Oct 2024 16:24:11 +0200 Subject: [PATCH] Use hash of input do control if calculation is required Add hash functions Add serial number to SummaryReaderInterface Add hash for RimSummaryCase Use hash based on input parameters to control caching of data in RimEnsembleStatisticsCase::calculate and RimEnsembleCurveSet::appendOptionItemsForSummaryAddresses --- .../Application/Tools/CMakeLists_files.cmake | 1 + .../Application/Tools/RiaHashTools.h | 90 +++++++++++++++++++ .../RifSummaryReaderInterface.cpp | 19 ++++ .../FileInterface/RifSummaryReaderInterface.h | 8 ++ .../Summary/RimEnsembleCurveSet.cpp | 42 ++++++--- .../Summary/RimEnsembleCurveSet.h | 5 +- .../Summary/RimEnsembleStatisticsCase.cpp | 6 ++ .../Summary/RimEnsembleStatisticsCase.h | 1 + .../Summary/RimSummaryCase.cpp | 9 ++ .../ProjectDataModel/Summary/RimSummaryCase.h | 25 ++++++ 10 files changed, 191 insertions(+), 15 deletions(-) create mode 100644 ApplicationLibCode/Application/Tools/RiaHashTools.h diff --git a/ApplicationLibCode/Application/Tools/CMakeLists_files.cmake b/ApplicationLibCode/Application/Tools/CMakeLists_files.cmake index cf7d37a4c4..8907e2e8b0 100644 --- a/ApplicationLibCode/Application/Tools/CMakeLists_files.cmake +++ b/ApplicationLibCode/Application/Tools/CMakeLists_files.cmake @@ -53,6 +53,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaFileLogger.h ${CMAKE_CURRENT_LIST_DIR}/RiaProjectBackupTools.h ${CMAKE_CURRENT_LIST_DIR}/RiaQuantityInfoTools.h + ${CMAKE_CURRENT_LIST_DIR}/RiaHashTools.h ) set(SOURCE_GROUP_SOURCE_FILES diff --git a/ApplicationLibCode/Application/Tools/RiaHashTools.h b/ApplicationLibCode/Application/Tools/RiaHashTools.h new file mode 100644 index 0000000000..8a50f80ed3 --- /dev/null +++ b/ApplicationLibCode/Application/Tools/RiaHashTools.h @@ -0,0 +1,90 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include + +//================================================================================================== +// +// +// +//================================================================================================== +namespace RiaHashTools +{ +//-------------------------------------------------------------------------------------------------- +/// Variadic template function to combine multiple parameters into a single hash +//-------------------------------------------------------------------------------------------------- +template +void combineHash( size_t& seed, const T& value ) +{ + // Based on https://www.boost.org/doc/libs/1_84_0/libs/container_hash/doc/html/hash.html#notes_hash_combine + seed ^= std::hash()( value ) + 0x9e3779b9 + ( seed << 6 ) + ( seed >> 2 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void combineHash( size_t& seed, const T& value, const Rest&... rest ) +{ + combineHash( seed, value ); + ( combineHash( seed, rest ), ... ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +void combineHash( size_t& seed, const Range& range, const Rest&... rest ) +{ + for ( const auto& elem : range ) + { + combineHash( seed, elem ); + } + ( combineHash( seed, rest ), ... ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +template +size_t hash( const Args&... args ) +{ + size_t seed = 0; + combineHash( seed, args... ); + return seed; +} + +//-------------------------------------------------------------------------------------------------- +/// Generic hash function for any range +//-------------------------------------------------------------------------------------------------- +template +size_t hash( const Range& range ) +{ + size_t seed = 0; + for ( const auto& elem : range ) + { + combineHash( seed, elem ); + } + return seed; +} + +}; // namespace RiaHashTools diff --git a/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.cpp b/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.cpp index 01ee289adb..51c9be4541 100644 --- a/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.cpp +++ b/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.cpp @@ -22,6 +22,8 @@ #include +int RifSummaryReaderInterface::m_nextSerialNumber = 0; + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -56,6 +58,23 @@ void RifSummaryReaderInterface::buildMetaData() { } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RifSummaryReaderInterface::serialNumber() const +{ + return m_serialNumber; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifSummaryReaderInterface::RifSummaryReaderInterface() +{ +#pragma omp critical + m_serialNumber = m_nextSerialNumber++; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.h b/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.h index efdd2973c6..2f86ae86af 100644 --- a/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.h +++ b/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.h @@ -37,6 +37,8 @@ class QDateTime; class RifSummaryReaderInterface : public cvf::Object { public: + RifSummaryReaderInterface(); + bool hasAddress( const RifEclipseSummaryAddress& resultAddress ) const; const std::set& allResultAddresses() const; @@ -53,7 +55,13 @@ public: virtual void buildMetaData(); + int serialNumber() const; + protected: std::set m_allResultAddresses; // Result and error addresses std::set m_allErrorAddresses; // Error addresses + +private: + static int m_nextSerialNumber; + int m_serialNumber; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index 711e598bda..bec4c2309e 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -20,6 +20,7 @@ #include "RiaColorTools.h" #include "RiaGuiApplication.h" +#include "RiaHashTools.h" #include "RiaPreferences.h" #include "RiaQDateTimeTools.h" #include "RiaResultNames.h" @@ -116,6 +117,7 @@ CAF_PDM_SOURCE_INIT( RimEnsembleCurveSet, "RimEnsembleCurveSet" ); //-------------------------------------------------------------------------------------------------- RimEnsembleCurveSet::RimEnsembleCurveSet() : filterChanged( this ) + , m_hash( 0 ) { CAF_PDM_InitObject( "Ensemble Curve Set", ":/EnsembleCurveSet16x16.png" ); @@ -1664,26 +1666,38 @@ void RimEnsembleCurveSet::appendOptionItemsForSummaryAddresses( QList addrSet; - for ( RimSummaryCase* summaryCase : summaryCaseGroup->allSummaryCases() ) + auto allSummaryCases = summaryCaseGroup->allSummaryCases(); + auto hash = RiaHashTools::hash( allSummaryCases ); + if ( hash != m_hash ) { - RifSummaryReaderInterface* reader = summaryCase->summaryReader(); - const std::set& addrs = reader ? reader->allResultAddresses() : std::set(); + m_hash = hash; - for ( auto& addr : addrs ) + std::set addressesForEnsemble; + for ( RimSummaryCase* summaryCase : allSummaryCases ) { - addrSet.insert( addr ); + if ( !summaryCase ) continue; + + if ( auto reader = summaryCase->summaryReader() ) + { + const auto& addrs = reader->allResultAddresses(); + addressesForEnsemble.insert( addrs.begin(), addrs.end() ); + } } + + m_cachedAddressOptions.clear(); + + for ( const auto& addr : addressesForEnsemble ) + { + std::string name = addr.uiText(); + QString s = QString::fromStdString( name ); + m_cachedAddressOptions.push_back( caf::PdmOptionItemInfo( s, QVariant::fromValue( addr ) ) ); + } + + m_cachedAddressOptions.push_front( + caf::PdmOptionItemInfo( RiaResultNames::undefinedResultName(), QVariant::fromValue( RifEclipseSummaryAddress() ) ) ); } - for ( auto& addr : addrSet ) - { - std::string name = addr.uiText(); - QString s = QString::fromStdString( name ); - options->push_back( caf::PdmOptionItemInfo( s, QVariant::fromValue( addr ) ) ); - } - - options->push_front( caf::PdmOptionItemInfo( RiaResultNames::undefinedResultName(), QVariant::fromValue( RifEclipseSummaryAddress() ) ) ); + options->append( m_cachedAddressOptions ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h index a5b63c8b46..755b838686 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h @@ -180,7 +180,7 @@ public: void appendColorGroup( caf::PdmUiOrdering& uiOrdering ); - static void appendOptionItemsForSummaryAddresses( QList* options, RimSummaryEnsemble* summaryCaseGroup ); + void appendOptionItemsForSummaryAddresses( QList* options, RimSummaryEnsemble* summaryCaseGroup ); const RimEnsembleCurveFilterCollection* curveFilters() const; @@ -317,4 +317,7 @@ private: bool m_disableStatisticCurves; bool m_isCurveSetFiltered; + + QList m_cachedAddressOptions; + size_t m_hash; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp index c24ccc446c..ed7e53a7ad 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp @@ -19,6 +19,7 @@ #include "RimEnsembleStatisticsCase.h" #include "RiaCurveMerger.h" +#include "RiaHashTools.h" #include "RiaTimeHistoryCurveResampler.h" #include "Summary/RiaSummaryTools.h" @@ -129,6 +130,11 @@ void RimEnsembleStatisticsCase::calculate( const std::vector& s const RifEclipseSummaryAddress& inputAddress, bool includeIncompleteCurves ) { + auto hash = RiaHashTools::hash( summaryCases, inputAddress.toEclipseTextAddress(), includeIncompleteCurves ); + if ( hash == m_hash ) return; + + m_hash = hash; + clearData(); if ( !inputAddress.isValid() ) return; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.h index 9b3fcc518f..ba819986cb 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.h @@ -64,4 +64,5 @@ private: std::vector m_meanData; caf::PdmPointer m_firstSummaryCase; + size_t m_hash = 0; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCase.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCase.cpp index 053da9e37d..4551c80df3 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCase.cpp @@ -225,6 +225,15 @@ void RimSummaryCase::buildChildNodes() m_dataVectorFolders->updateFolderStructure( addresses, m_caseId ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimSummaryCase::serialNumber() +{ + auto reader = summaryReader(); + return reader ? reader->serialNumber() : -1; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCase.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCase.h index a3e5a1f5de..4ee7c6c1e0 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCase.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCase.h @@ -18,6 +18,9 @@ #pragma once #include "RiaDefines.h" + +#include "RiaHashTools.h" + #include "RigCaseRealizationParameters.h" #include "RimCaseDisplayNameTools.h" @@ -105,6 +108,7 @@ protected: private: void buildChildNodes(); + int serialNumber(); protected: caf::PdmField m_displayName; @@ -123,4 +127,25 @@ protected: caf::PdmField m_useAutoShortName_OBSOLETE; static const QString DEFAULT_DISPLAY_NAME; + + friend struct std::hash; +}; + +// Custom specialization of std::hash injected in namespace std +// NB! Note that this is a specialization of std::hash for a pointer type +template <> +struct std::hash +{ + std::size_t operator()( RimSummaryCase* s ) const noexcept + { + if ( !s ) return 0; + + auto serialNumber = s->serialNumber(); + if ( serialNumber != -1 ) + { + return RiaHashTools::hash( serialNumber ); + } + + return RiaHashTools::hash( s->summaryHeaderFilename().toStdString() ); + } };