mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-01 03:37:15 -06:00
11563666e6
Statistics can be computed in two ways, precise using all available cell values and fast based on a histogram. A flag indicates if the P10/P90 values are calculated. Check this flag before assigning values using the fast histogram method.
468 lines
17 KiB
C++
468 lines
17 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) Statoil ASA
|
|
// Copyright (C) Ceetron Solutions AS
|
|
//
|
|
// 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 <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RigStatisticsDataCache.h"
|
|
|
|
#include "RigStatisticsCalculator.h"
|
|
#include "RigStatisticsMath.h"
|
|
|
|
#include <cmath> // Needed for HUGE_VAL on Linux
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigStatisticsDataCache::RigStatisticsDataCache( RigStatisticsCalculator* statisticsCalculator )
|
|
: m_statisticsCalculator( statisticsCalculator )
|
|
, m_numBins( RigStatisticsDataCache::defaultNumBins() )
|
|
{
|
|
CVF_ASSERT( m_statisticsCalculator.notNull() );
|
|
|
|
clearAllStatistics();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::clearAllStatistics()
|
|
{
|
|
m_statsAllTimesteps = StatisticsValues();
|
|
m_statsPrTs.clear();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
size_t RigStatisticsDataCache::defaultNumBins()
|
|
{
|
|
return 100;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::setNumBins( size_t numBins )
|
|
{
|
|
m_numBins = numBins;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::minMaxCellScalarValues( double& min, double& max )
|
|
{
|
|
if ( !m_statsAllTimesteps.m_isMaxMinCalculated )
|
|
{
|
|
min = HUGE_VAL;
|
|
max = -HUGE_VAL;
|
|
|
|
size_t i;
|
|
for ( i = 0; i < m_statisticsCalculator->timeStepCount(); i++ )
|
|
{
|
|
double tsmin, tsmax;
|
|
minMaxCellScalarValues( i, tsmin, tsmax );
|
|
if ( tsmin < min ) min = tsmin;
|
|
if ( tsmax > max ) max = tsmax;
|
|
}
|
|
|
|
m_statsAllTimesteps.m_minValue = min;
|
|
m_statsAllTimesteps.m_maxValue = max;
|
|
m_statsAllTimesteps.m_isMaxMinCalculated = true;
|
|
}
|
|
|
|
min = m_statsAllTimesteps.m_minValue;
|
|
max = m_statsAllTimesteps.m_maxValue;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::minMaxCellScalarValues( size_t timeStepIndex, double& min, double& max )
|
|
{
|
|
if ( timeStepIndex >= m_statsPrTs.size() )
|
|
{
|
|
m_statsPrTs.resize( timeStepIndex + 1 );
|
|
}
|
|
|
|
if ( !m_statsPrTs[timeStepIndex].m_isMaxMinCalculated )
|
|
{
|
|
double tsMin = HUGE_VAL;
|
|
double tsMax = -HUGE_VAL;
|
|
|
|
m_statisticsCalculator->minMaxCellScalarValues( timeStepIndex, tsMin, tsMax );
|
|
|
|
m_statsPrTs[timeStepIndex].m_minValue = tsMin;
|
|
m_statsPrTs[timeStepIndex].m_maxValue = tsMax;
|
|
|
|
m_statsPrTs[timeStepIndex].m_isMaxMinCalculated = true;
|
|
}
|
|
|
|
min = m_statsPrTs[timeStepIndex].m_minValue;
|
|
max = m_statsPrTs[timeStepIndex].m_maxValue;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::posNegClosestToZero( double& pos, double& neg )
|
|
{
|
|
if ( !m_statsAllTimesteps.m_isClosestToZeroCalculated )
|
|
{
|
|
pos = HUGE_VAL;
|
|
neg = -HUGE_VAL;
|
|
|
|
size_t i;
|
|
for ( i = 0; i < m_statisticsCalculator->timeStepCount(); i++ )
|
|
{
|
|
double tsNeg, tsPos;
|
|
posNegClosestToZero( i, tsPos, tsNeg );
|
|
if ( tsNeg > neg && tsNeg < 0 ) neg = tsNeg;
|
|
if ( tsPos < pos && tsPos > 0 ) pos = tsPos;
|
|
}
|
|
|
|
m_statsAllTimesteps.m_posClosestToZero = pos;
|
|
m_statsAllTimesteps.m_negClosestToZero = neg;
|
|
m_statsAllTimesteps.m_isClosestToZeroCalculated = true;
|
|
}
|
|
|
|
pos = m_statsAllTimesteps.m_posClosestToZero;
|
|
neg = m_statsAllTimesteps.m_negClosestToZero;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::posNegClosestToZero( size_t timeStepIndex, double& posNearZero, double& negNearZero )
|
|
{
|
|
if ( timeStepIndex >= m_statsPrTs.size() )
|
|
{
|
|
m_statsPrTs.resize( timeStepIndex + 1 );
|
|
}
|
|
|
|
if ( !m_statsPrTs[timeStepIndex].m_isClosestToZeroCalculated )
|
|
{
|
|
double pos = HUGE_VAL;
|
|
double neg = -HUGE_VAL;
|
|
|
|
m_statisticsCalculator->posNegClosestToZero( timeStepIndex, pos, neg );
|
|
|
|
m_statsPrTs[timeStepIndex].m_posClosestToZero = pos;
|
|
m_statsPrTs[timeStepIndex].m_negClosestToZero = neg;
|
|
|
|
m_statsPrTs[timeStepIndex].m_isClosestToZeroCalculated = true;
|
|
}
|
|
|
|
posNearZero = m_statsPrTs[timeStepIndex].m_posClosestToZero;
|
|
negNearZero = m_statsPrTs[timeStepIndex].m_negClosestToZero;
|
|
}
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::meanCellScalarValues( double& meanValue )
|
|
{
|
|
if ( !m_statsAllTimesteps.m_isMeanCalculated )
|
|
{
|
|
m_statisticsCalculator->meanCellScalarValue( m_statsAllTimesteps.m_meanValue );
|
|
|
|
m_statsAllTimesteps.m_isMeanCalculated = true;
|
|
}
|
|
|
|
meanValue = m_statsAllTimesteps.m_meanValue;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::meanCellScalarValues( size_t timeStepIndex, double& meanValue )
|
|
{
|
|
if ( timeStepIndex >= m_statsPrTs.size() )
|
|
{
|
|
m_statsPrTs.resize( timeStepIndex + 1 );
|
|
}
|
|
|
|
if ( !m_statsPrTs[timeStepIndex].m_isMeanCalculated )
|
|
{
|
|
m_statisticsCalculator->meanCellScalarValue( timeStepIndex, m_statsPrTs[timeStepIndex].m_meanValue );
|
|
m_statsPrTs[timeStepIndex].m_isMeanCalculated = true;
|
|
}
|
|
|
|
meanValue = m_statsPrTs[timeStepIndex].m_meanValue;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::sumCellScalarValues( double& sumValue )
|
|
{
|
|
if ( !m_statsAllTimesteps.m_isValueSumCalculated )
|
|
{
|
|
double aggregatedSum = 0.0;
|
|
for ( size_t i = 0; i < m_statisticsCalculator->timeStepCount(); i++ )
|
|
{
|
|
double valueSum = 0.0;
|
|
sumCellScalarValues( i, valueSum );
|
|
|
|
aggregatedSum += valueSum;
|
|
}
|
|
|
|
m_statsAllTimesteps.m_valueSum = aggregatedSum;
|
|
m_statsAllTimesteps.m_isValueSumCalculated = true;
|
|
}
|
|
|
|
sumValue = m_statsAllTimesteps.m_valueSum;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::sumCellScalarValues( size_t timeStepIndex, double& sumValue )
|
|
{
|
|
if ( timeStepIndex >= m_statsPrTs.size() )
|
|
{
|
|
m_statsPrTs.resize( timeStepIndex + 1 );
|
|
}
|
|
|
|
if ( !m_statsPrTs[timeStepIndex].m_isValueSumCalculated )
|
|
{
|
|
double valueSum = 0.0;
|
|
size_t sampleCount = 0;
|
|
m_statisticsCalculator->valueSumAndSampleCount( timeStepIndex, valueSum, sampleCount );
|
|
m_statsPrTs[timeStepIndex].m_valueSum = valueSum;
|
|
m_statsPrTs[timeStepIndex].m_isValueSumCalculated = true;
|
|
}
|
|
|
|
sumValue = m_statsPrTs[timeStepIndex].m_valueSum;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<size_t>& RigStatisticsDataCache::cellScalarValuesHistogram()
|
|
{
|
|
computeHistogramStatisticsIfNeeded();
|
|
|
|
return m_statsAllTimesteps.m_histogram;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<size_t>& RigStatisticsDataCache::cellScalarValuesHistogram( size_t timeStepIndex )
|
|
{
|
|
computeHistogramStatisticsIfNeeded( timeStepIndex );
|
|
|
|
return m_statsPrTs[timeStepIndex].m_histogram;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<int>& RigStatisticsDataCache::uniqueCellScalarValues()
|
|
{
|
|
computeUniqueValuesIfNeeded();
|
|
|
|
return m_statsAllTimesteps.m_uniqueValues;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<int>& RigStatisticsDataCache::uniqueCellScalarValues( size_t timeStepIndex )
|
|
{
|
|
computeUniqueValuesIfNeeded( timeStepIndex );
|
|
|
|
return m_statsPrTs[timeStepIndex].m_uniqueValues;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::mobileVolumeWeightedMean( size_t timeStepIndex, double& mean )
|
|
{
|
|
if ( timeStepIndex >= m_statsPrTs.size() )
|
|
{
|
|
m_statsPrTs.resize( timeStepIndex + 1 );
|
|
}
|
|
|
|
if ( !m_statsPrTs[timeStepIndex].m_isVolumeWeightedMeanCalculated )
|
|
{
|
|
m_statisticsCalculator->mobileVolumeWeightedMean( timeStepIndex, m_statsPrTs[timeStepIndex].m_volumeWeightedMean );
|
|
}
|
|
|
|
mean = m_statsPrTs[timeStepIndex].m_volumeWeightedMean;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::mobileVolumeWeightedMean( double& mean )
|
|
{
|
|
if ( !m_statsAllTimesteps.m_isVolumeWeightedMeanCalculated )
|
|
{
|
|
m_statisticsCalculator->mobileVolumeWeightedMean( m_statsAllTimesteps.m_volumeWeightedMean );
|
|
|
|
m_statsAllTimesteps.m_isVolumeWeightedMeanCalculated = true;
|
|
}
|
|
|
|
mean = m_statsAllTimesteps.m_volumeWeightedMean;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::p10p90CellScalarValues( double& p10, double& p90 )
|
|
{
|
|
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;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::p10p90CellScalarValues( size_t timeStepIndex, double& p10, double& p90 )
|
|
{
|
|
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;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::computeHistogramStatisticsIfNeeded()
|
|
{
|
|
if ( m_statsAllTimesteps.m_histogram.size() != m_numBins )
|
|
{
|
|
double min;
|
|
double max;
|
|
minMaxCellScalarValues( min, max );
|
|
|
|
RigHistogramCalculator histCalc( min, max, m_numBins, &m_statsAllTimesteps.m_histogram );
|
|
|
|
m_statisticsCalculator->addDataToHistogramCalculator( histCalc );
|
|
|
|
if ( !m_statsAllTimesteps.m_isp10p90Calculated )
|
|
{
|
|
m_statsAllTimesteps.m_p10 = histCalc.calculatePercentil( 0.1, RigStatisticsMath::PercentileStyle::SWITCHED );
|
|
m_statsAllTimesteps.m_p90 = histCalc.calculatePercentil( 0.9, RigStatisticsMath::PercentileStyle::SWITCHED );
|
|
|
|
m_statsAllTimesteps.m_isp10p90Calculated = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::computeHistogramStatisticsIfNeeded( size_t timeStepIndex )
|
|
{
|
|
if ( m_statsPrTs[timeStepIndex].m_histogram.size() != m_numBins )
|
|
{
|
|
double min;
|
|
double max;
|
|
minMaxCellScalarValues( timeStepIndex, min, max );
|
|
|
|
RigHistogramCalculator histCalc( min, max, m_numBins, &m_statsPrTs[timeStepIndex].m_histogram );
|
|
|
|
m_statisticsCalculator->addDataToHistogramCalculator( timeStepIndex, histCalc );
|
|
|
|
if ( !m_statsPrTs[timeStepIndex].m_isp10p90Calculated )
|
|
{
|
|
m_statsPrTs[timeStepIndex].m_p10 = histCalc.calculatePercentil( 0.1, RigStatisticsMath::PercentileStyle::SWITCHED );
|
|
m_statsPrTs[timeStepIndex].m_p90 = histCalc.calculatePercentil( 0.9, RigStatisticsMath::PercentileStyle::SWITCHED );
|
|
|
|
m_statsPrTs[timeStepIndex].m_isp10p90Calculated = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::computeUniqueValuesIfNeeded()
|
|
{
|
|
if ( m_statsAllTimesteps.m_uniqueValues.empty() )
|
|
{
|
|
std::set<int> setValues;
|
|
m_statisticsCalculator->uniqueValues( 0, setValues ); // This is a Hack ! Only using first timestep. Ok for
|
|
// Static eclipse results but beware !
|
|
|
|
for ( auto val : setValues )
|
|
{
|
|
m_statsAllTimesteps.m_uniqueValues.push_back( val );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigStatisticsDataCache::computeUniqueValuesIfNeeded( size_t timeStepIndex )
|
|
{
|
|
if ( m_statsPrTs[timeStepIndex].m_uniqueValues.empty() )
|
|
{
|
|
std::set<int> setValues;
|
|
m_statisticsCalculator->uniqueValues( timeStepIndex, setValues );
|
|
|
|
for ( auto val : setValues )
|
|
{
|
|
m_statsPrTs[timeStepIndex].m_uniqueValues.push_back( val );
|
|
}
|
|
}
|
|
}
|