diff --git a/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeStatCalc.cpp b/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeStatCalc.cpp index 8b75882002..eba4764a53 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeStatCalc.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeStatCalc.cpp @@ -46,6 +46,39 @@ void RigEclipseNativeStatCalc::minMaxCellScalarValues( size_t timeStepIndex, dou max = acc.max; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigEclipseNativeStatCalc::hasPreciseP10p90() const +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigEclipseNativeStatCalc::p10p90CellScalarValues( double& p10, double& p90 ) +{ + PercentilAccumulator acc; + + for ( size_t timeStepIndex = 0; timeStepIndex < timeStepCount(); timeStepIndex++ ) + { + traverseCells( acc, timeStepIndex ); + } + + acc.computep10p90( p10, p90 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigEclipseNativeStatCalc::p10p90CellScalarValues( size_t timeStepIndex, double& p10, double& p90 ) +{ + PercentilAccumulator acc; + traverseCells( acc, timeStepIndex ); + acc.computep10p90( p10, p90 ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeStatCalc.h b/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeStatCalc.h index f044cff832..9a2a8d4969 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeStatCalc.h +++ b/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeStatCalc.h @@ -35,6 +35,9 @@ class RigEclipseNativeStatCalc : public RigStatisticsCalculator public: RigEclipseNativeStatCalc( RigCaseCellResultsData* cellResultsData, const RigEclipseResultAddress& eclipseResultAddress ); + bool hasPreciseP10p90() const override; + void p10p90CellScalarValues( double& min, double& max ) override; + void p10p90CellScalarValues( size_t timeStepIndex, double& min, double& max ) override; void minMaxCellScalarValues( size_t timeStepIndex, double& min, double& max ) override; void posNegClosestToZero( size_t timeStepIndex, double& pos, double& neg ) override; void valueSumAndSampleCount( size_t timeStepIndex, double& valueSum, size_t& sampleCount ) override; diff --git a/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.cpp b/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.cpp index 6d3f60aef0..a47db39d5e 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.cpp @@ -49,6 +49,39 @@ void RigEclipseNativeVisibleCellsStatCalc::minMaxCellScalarValues( size_t timeSt max = acc.max; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigEclipseNativeVisibleCellsStatCalc::hasPreciseP10p90() const +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigEclipseNativeVisibleCellsStatCalc::p10p90CellScalarValues( double& p10, double& p90 ) +{ + PercentilAccumulator acc; + + for ( size_t timeStepIndex = 0; timeStepIndex < timeStepCount(); timeStepIndex++ ) + { + traverseCells( acc, timeStepIndex ); + } + + acc.computep10p90( p10, p90 ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigEclipseNativeVisibleCellsStatCalc::p10p90CellScalarValues( size_t timeStepIndex, double& p10, double& p90 ) +{ + PercentilAccumulator acc; + traverseCells( acc, timeStepIndex ); + acc.computep10p90( p10, p90 ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.h b/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.h index 641e89b977..bd20b6f263 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.h +++ b/ApplicationLibCode/ReservoirDataModel/RigEclipseNativeVisibleCellsStatCalc.h @@ -36,6 +36,9 @@ public: const RigEclipseResultAddress& scalarResultIndex, const cvf::UByteArray* cellVisibilities ); + bool hasPreciseP10p90() const override; + void p10p90CellScalarValues( double& min, double& max ) override; + void p10p90CellScalarValues( size_t timeStepIndex, double& min, double& max ) override; void minMaxCellScalarValues( size_t timeStepIndex, double& min, double& max ) override; void posNegClosestToZero( size_t timeStepIndex, double& pos, double& neg ) override; void valueSumAndSampleCount( size_t timeStepIndex, double& valueSum, size_t& sampleCount ) override; diff --git a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsCalculator.cpp b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsCalculator.cpp index b7d8afe85b..41a328ac92 100644 --- a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsCalculator.cpp +++ b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsCalculator.cpp @@ -19,6 +19,7 @@ #include "RigStatisticsCalculator.h" +#include #include // Needed for HUGE_VAL on Linux //-------------------------------------------------------------------------------------------------- @@ -135,3 +136,27 @@ void RigStatisticsCalculator::posNegClosestToZero( const std::vector& va } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigStatisticsCalculator::hasPreciseP10p90() const +{ + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsCalculator::p10p90CellScalarValues( double& p10, double& p90 ) +{ + assert( false && "Precise p10/p90 not available" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsCalculator::p10p90CellScalarValues( size_t timeStepIndex, double& p10, double& p90 ) +{ + assert( false && "Precise p10/p90 not available" ); +} diff --git a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsCalculator.h b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsCalculator.h index 31f4efd9f2..0c37ed37ea 100644 --- a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsCalculator.h +++ b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsCalculator.h @@ -46,6 +46,10 @@ public: virtual void uniqueValues( size_t timeStepIndex, std::set& values ) = 0; + virtual bool hasPreciseP10p90() const; + virtual void p10p90CellScalarValues( double& p10, double& p90 ); + virtual void p10p90CellScalarValues( size_t timeStepIndex, double& p10, double& p90 ); + virtual size_t timeStepCount() = 0; void mobileVolumeWeightedMean( double& mean ); diff --git a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsDataCache.cpp b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsDataCache.cpp index 72e37c971b..4176d50a6c 100644 --- a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsDataCache.cpp +++ b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsDataCache.cpp @@ -310,7 +310,23 @@ void RigStatisticsDataCache::mobileVolumeWeightedMean( double& mean ) //-------------------------------------------------------------------------------------------------- void RigStatisticsDataCache::p10p90CellScalarValues( double& p10, double& p90 ) { - computeHistogramStatisticsIfNeeded(); + if ( !m_statsAllTimesteps.m_isp10p90Calculated ) + { + if ( m_statisticsCalculator->hasPreciseP10p90() ) + { + // Prefer precise p10/p90 calculation where available + m_statisticsCalculator->p10p90CellScalarValues( p10, p90 ); + + m_statsAllTimesteps.m_p10 = p10; + m_statsAllTimesteps.m_p90 = p90; + } + else + { + computeHistogramStatisticsIfNeeded(); + } + + m_statsAllTimesteps.m_isp10p90Calculated = true; + } p10 = m_statsAllTimesteps.m_p10; p90 = m_statsAllTimesteps.m_p90; @@ -321,7 +337,28 @@ void RigStatisticsDataCache::p10p90CellScalarValues( double& p10, double& p90 ) //-------------------------------------------------------------------------------------------------- void RigStatisticsDataCache::p10p90CellScalarValues( size_t timeStepIndex, double& p10, double& p90 ) { - computeHistogramStatisticsIfNeeded( timeStepIndex ); + if ( timeStepIndex >= m_statsPrTs.size() ) + { + m_statsPrTs.resize( timeStepIndex + 1 ); + } + + if ( !m_statsPrTs[timeStepIndex].m_isp10p90Calculated ) + { + if ( m_statisticsCalculator->hasPreciseP10p90() ) + { + // Prefer precise p10/p90 calculation where available + m_statisticsCalculator->p10p90CellScalarValues( timeStepIndex, p10, p90 ); + + m_statsPrTs[timeStepIndex].m_p10 = p10; + m_statsPrTs[timeStepIndex].m_p90 = p90; + } + else + { + computeHistogramStatisticsIfNeeded( timeStepIndex ); + } + + m_statsPrTs[timeStepIndex].m_isp10p90Calculated = true; + } p10 = m_statsPrTs[timeStepIndex].m_p10; p90 = m_statsPrTs[timeStepIndex].m_p90; diff --git a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsDataCache.h b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsDataCache.h index 1cc1147ae3..7ca6f844e5 100644 --- a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsDataCache.h +++ b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsDataCache.h @@ -82,6 +82,7 @@ private: m_isClosestToZeroCalculated = false; m_p10 = HUGE_VAL; m_p90 = HUGE_VAL; + m_isp10p90Calculated = false; m_valueSum = 0.0; m_isValueSumCalculated = false; m_volumeWeightedMean = HUGE_VAL; @@ -101,6 +102,7 @@ private: double m_p10; double m_p90; + bool m_isp10p90Calculated; double m_valueSum; bool m_isValueSumCalculated; diff --git a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsMath.h b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsMath.h index b1209edb07..91f0e2bc95 100644 --- a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsMath.h +++ b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsMath.h @@ -130,6 +130,40 @@ public: double min; }; +class PercentilAccumulator +{ +public: + PercentilAccumulator() {} + + void addData( const std::vector& values ) + { + for ( double val : values ) + { + addValue( val ); + } + } + + void addData( const std::vector& values ) + { + for ( float val : values ) + { + addValue( val ); + } + } + + void addValue( double value ) { values.push_back( value ); } + + void computep10p90( double& p10, double& p90 ) + { + double mean = HUGE_VAL; + double p50 = HUGE_VAL; + + RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean, RigStatisticsMath::PercentileStyle::SWITCHED ); + } + + std::vector values; +}; + class PosNegAccumulator { public: