mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#2659 Ensemble statistics. Use resampling during statistics calculations
This commit is contained in:
parent
848d774440
commit
4491b1de63
@ -478,14 +478,24 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::importedAddress(const std::st
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
RifEclipseSummaryAddress RifEclipseSummaryAddress::ensembleStatisticsAddress(const std::string& quantityName)
|
RifEclipseSummaryAddress RifEclipseSummaryAddress::ensembleStatisticsAddress(const std::string& quantityName,
|
||||||
|
const std::string& dataQuantityName)
|
||||||
{
|
{
|
||||||
RifEclipseSummaryAddress addr;
|
RifEclipseSummaryAddress addr;
|
||||||
addr.m_variableCategory = SUMMARY_ENSEMBLE_STATISTICS;
|
addr.m_variableCategory = SUMMARY_ENSEMBLE_STATISTICS;
|
||||||
addr.m_quantityName = quantityName;
|
addr.m_quantityName = quantityName + ":" + dataQuantityName;
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
const std::string RifEclipseSummaryAddress::ensembleStatisticsQuantityName() const
|
||||||
|
{
|
||||||
|
QString qName = QString::fromStdString(m_quantityName);
|
||||||
|
return qName.split(":")[0].toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@ -657,6 +667,14 @@ bool RifEclipseSummaryAddress::isValid() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RifEclipseSummaryAddress::hasAccumulatedData() const
|
||||||
|
{
|
||||||
|
return QString::fromStdString(m_quantityName).endsWith("T");
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
@ -141,7 +141,7 @@ public:
|
|||||||
static RifEclipseSummaryAddress blockLgrAddress(const std::string& quantityName, const std::string& lgrName, int i, int j, int k);
|
static RifEclipseSummaryAddress blockLgrAddress(const std::string& quantityName, const std::string& lgrName, int i, int j, int k);
|
||||||
static RifEclipseSummaryAddress calculatedAddress(const std::string& quantityName);
|
static RifEclipseSummaryAddress calculatedAddress(const std::string& quantityName);
|
||||||
static RifEclipseSummaryAddress importedAddress(const std::string& quantityName);
|
static RifEclipseSummaryAddress importedAddress(const std::string& quantityName);
|
||||||
static RifEclipseSummaryAddress ensembleStatisticsAddress(const std::string& quantityName);
|
static RifEclipseSummaryAddress ensembleStatisticsAddress(const std::string& quantityName, const std::string& dataQuantityName);
|
||||||
|
|
||||||
// Access methods
|
// Access methods
|
||||||
|
|
||||||
@ -160,6 +160,8 @@ public:
|
|||||||
int cellK() const { return m_cellK; }
|
int cellK() const { return m_cellK; }
|
||||||
int aquiferNumber() const { return m_aquiferNumber; }
|
int aquiferNumber() const { return m_aquiferNumber; }
|
||||||
|
|
||||||
|
const std::string ensembleStatisticsQuantityName() const;
|
||||||
|
|
||||||
// Derived properties
|
// Derived properties
|
||||||
|
|
||||||
std::string uiText() const;
|
std::string uiText() const;
|
||||||
@ -174,6 +176,7 @@ public:
|
|||||||
|
|
||||||
void setAsErrorResult() { m_isErrorResult = true; }
|
void setAsErrorResult() { m_isErrorResult = true; }
|
||||||
bool isErrorResult() const { return m_isErrorResult; }
|
bool isErrorResult() const { return m_isErrorResult; }
|
||||||
|
bool hasAccumulatedData() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -32,10 +32,10 @@ RifEnsembleStatisticsReader::RifEnsembleStatisticsReader(RimEnsembleStatisticsCa
|
|||||||
|
|
||||||
m_allResultAddresses = std::vector<RifEclipseSummaryAddress>(
|
m_allResultAddresses = std::vector<RifEclipseSummaryAddress>(
|
||||||
{
|
{
|
||||||
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P10_QUANTITY_NAME),
|
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P10_QUANTITY_NAME, ""),
|
||||||
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P50_QUANTITY_NAME),
|
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P50_QUANTITY_NAME, ""),
|
||||||
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P90_QUANTITY_NAME),
|
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P90_QUANTITY_NAME, ""),
|
||||||
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_MEAN_QUANTITY_NAME)
|
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_MEAN_QUANTITY_NAME, "")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +55,12 @@ bool RifEnsembleStatisticsReader::values(const RifEclipseSummaryAddress& resultA
|
|||||||
if (!validateAddress(resultAddress)) return false;
|
if (!validateAddress(resultAddress)) return false;
|
||||||
|
|
||||||
const std::vector<double>* sourceData = nullptr;
|
const std::vector<double>* sourceData = nullptr;
|
||||||
if (resultAddress.quantityName() == ENSEMBLE_STAT_P10_QUANTITY_NAME) sourceData = &m_ensembleStatCase->p10();
|
auto quantityName = resultAddress.ensembleStatisticsQuantityName();
|
||||||
else if (resultAddress.quantityName() == ENSEMBLE_STAT_P50_QUANTITY_NAME) sourceData = &m_ensembleStatCase->p50();
|
|
||||||
else if (resultAddress.quantityName() == ENSEMBLE_STAT_P90_QUANTITY_NAME) sourceData = &m_ensembleStatCase->p90();
|
if (quantityName == ENSEMBLE_STAT_P10_QUANTITY_NAME) sourceData = &m_ensembleStatCase->p10();
|
||||||
else if (resultAddress.quantityName() == ENSEMBLE_STAT_MEAN_QUANTITY_NAME) sourceData = &m_ensembleStatCase->mean();
|
else if (quantityName == ENSEMBLE_STAT_P50_QUANTITY_NAME) sourceData = &m_ensembleStatCase->p50();
|
||||||
|
else if (quantityName == ENSEMBLE_STAT_P90_QUANTITY_NAME) sourceData = &m_ensembleStatCase->p90();
|
||||||
|
else if (quantityName == ENSEMBLE_STAT_MEAN_QUANTITY_NAME) sourceData = &m_ensembleStatCase->mean();
|
||||||
|
|
||||||
if (!sourceData) return false;
|
if (!sourceData) return false;
|
||||||
|
|
||||||
|
@ -929,7 +929,7 @@ void RimEnsembleCurveSet::updateStatisticsCurves(bool calculate = true)
|
|||||||
if (calculate)
|
if (calculate)
|
||||||
{
|
{
|
||||||
// Calculate
|
// Calculate
|
||||||
m_ensembleStatCase->calculate(m_yValuesSummaryGroup, m_yValuesCurveVariable->address());
|
m_ensembleStatCase->calculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
RimSummaryPlot* plot = nullptr;
|
RimSummaryPlot* plot = nullptr;
|
||||||
@ -939,10 +939,12 @@ void RimEnsembleCurveSet::updateStatisticsCurves(bool calculate = true)
|
|||||||
std::vector<RifEclipseSummaryAddress> addresses;
|
std::vector<RifEclipseSummaryAddress> addresses;
|
||||||
if (m_statistics->isActive())
|
if (m_statistics->isActive())
|
||||||
{
|
{
|
||||||
if (m_statistics->showP10Curve()) addresses.push_back(SAddr::ensembleStatisticsAddress(ENSEMBLE_STAT_P10_QUANTITY_NAME));
|
RifEclipseSummaryAddress dataAddress = m_yValuesCurveVariable->address();
|
||||||
if (m_statistics->showP50Curve()) addresses.push_back(SAddr::ensembleStatisticsAddress(ENSEMBLE_STAT_P50_QUANTITY_NAME));
|
|
||||||
if (m_statistics->showP90Curve()) addresses.push_back(SAddr::ensembleStatisticsAddress(ENSEMBLE_STAT_P90_QUANTITY_NAME));
|
if (m_statistics->showP10Curve()) addresses.push_back(SAddr::ensembleStatisticsAddress(ENSEMBLE_STAT_P10_QUANTITY_NAME, dataAddress.quantityName()));
|
||||||
if (m_statistics->showMeanCurve()) addresses.push_back(SAddr::ensembleStatisticsAddress(ENSEMBLE_STAT_MEAN_QUANTITY_NAME));
|
if (m_statistics->showP50Curve()) addresses.push_back(SAddr::ensembleStatisticsAddress(ENSEMBLE_STAT_P50_QUANTITY_NAME, dataAddress.quantityName()));
|
||||||
|
if (m_statistics->showP90Curve()) addresses.push_back(SAddr::ensembleStatisticsAddress(ENSEMBLE_STAT_P90_QUANTITY_NAME, dataAddress.quantityName()));
|
||||||
|
if (m_statistics->showMeanCurve()) addresses.push_back(SAddr::ensembleStatisticsAddress(ENSEMBLE_STAT_MEAN_QUANTITY_NAME, dataAddress.quantityName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteStatisticsCurves();
|
deleteStatisticsCurves();
|
||||||
|
@ -22,9 +22,11 @@
|
|||||||
|
|
||||||
#include "RigStatisticsMath.h"
|
#include "RigStatisticsMath.h"
|
||||||
#include "RiaTimeHistoryCurveMerger.h"
|
#include "RiaTimeHistoryCurveMerger.h"
|
||||||
|
#include "RiaTimeHistoryCurveResampler.h"
|
||||||
|
|
||||||
#include "RimEnsembleCurveSet.h"
|
#include "RimEnsembleCurveSet.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
@ -109,33 +111,41 @@ const RimEnsembleCurveSet* RimEnsembleStatisticsCase::curveSet() const
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RimEnsembleStatisticsCase::calculate(const RimSummaryCaseCollection* ensemble, const RifEclipseSummaryAddress& inputAddress)
|
void RimEnsembleStatisticsCase::calculate()
|
||||||
{
|
{
|
||||||
RiaTimeHistoryCurveMerger curveMerger;
|
auto inputAddress = m_curveSet->summaryAddress();
|
||||||
int caseCount = (int)ensemble->allSummaryCases().size();
|
auto ensemble = m_curveSet->summaryCaseCollection();
|
||||||
|
if (m_statisticsReader && ensemble && inputAddress.isValid())
|
||||||
{
|
{
|
||||||
for (const auto& sumCase : ensemble->allSummaryCases())
|
calculate(validSummaryCases(ensemble->allSummaryCases(), inputAddress), inputAddress);
|
||||||
{
|
|
||||||
const auto& reader = sumCase->summaryReader();
|
|
||||||
if (reader)
|
|
||||||
{
|
|
||||||
std::vector<time_t> timeSteps = reader->timeSteps(inputAddress);
|
|
||||||
std::vector<double> values;
|
|
||||||
reader->values(inputAddress, &values);
|
|
||||||
|
|
||||||
curveMerger.addCurveData(values, timeSteps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
curveMerger.computeInterpolatedValues();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<time_t>& allTimeSteps = curveMerger.allTimeSteps();
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RimEnsembleStatisticsCase::calculate(const std::vector<RimSummaryCase*> sumCases, const RifEclipseSummaryAddress& inputAddress)
|
||||||
|
{
|
||||||
|
std::vector<time_t> allTimeSteps;
|
||||||
std::vector<std::vector<double>> allValues;
|
std::vector<std::vector<double>> allValues;
|
||||||
|
|
||||||
|
allValues.reserve(sumCases.size());
|
||||||
|
for (const auto& sumCase : sumCases)
|
||||||
{
|
{
|
||||||
for (int c = 0; c < caseCount; c++)
|
const auto& reader = sumCase->summaryReader();
|
||||||
|
if (reader)
|
||||||
{
|
{
|
||||||
allValues.push_back(curveMerger.interpolatedCurveValuesForAllTimeSteps(c));
|
std::vector<time_t> timeSteps = reader->timeSteps(inputAddress);
|
||||||
|
std::vector<double> values;
|
||||||
|
reader->values(inputAddress, &values);
|
||||||
|
|
||||||
|
RiaTimeHistoryCurveResampler resampler;
|
||||||
|
resampler.setCurveData(values, timeSteps);
|
||||||
|
if (inputAddress.hasAccumulatedData()) resampler.resampleAndComputePeriodEndValues(DateTimePeriod::DAY);
|
||||||
|
else resampler.resampleAndComputeWeightedMeanValues(DateTimePeriod::DAY);
|
||||||
|
|
||||||
|
if (allTimeSteps.empty()) allTimeSteps = resampler.resampledTimeSteps();
|
||||||
|
allValues.push_back(std::vector<double>(resampler.resampledValues().begin(), resampler.resampledValues().end()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,49 +155,33 @@ void RimEnsembleStatisticsCase::calculate(const RimSummaryCaseCollection* ensemb
|
|||||||
for (int t = 0; t < (int)allTimeSteps.size(); t++)
|
for (int t = 0; t < (int)allTimeSteps.size(); t++)
|
||||||
{
|
{
|
||||||
std::vector<double> valuesForTimeSteps;
|
std::vector<double> valuesForTimeSteps;
|
||||||
valuesForTimeSteps.reserve(caseCount);
|
valuesForTimeSteps.reserve(sumCases.size());
|
||||||
|
|
||||||
for (int c = 0; c < caseCount; c++)
|
for (int c = 0; c < sumCases.size(); c++)
|
||||||
{
|
{
|
||||||
valuesForTimeSteps.push_back(allValues[c][t]);
|
valuesForTimeSteps.push_back(allValues[c][t]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
double min, max, range, mean, stdev;
|
||||||
double min, max, range, mean, stdev;
|
RigStatisticsMath::calculateBasicStatistics(valuesForTimeSteps, &min, &max, nullptr, &range, &mean, &stdev);
|
||||||
RigStatisticsMath::calculateBasicStatistics(valuesForTimeSteps, &min, &max, nullptr, &range, &mean, &stdev);
|
|
||||||
|
|
||||||
std::vector<size_t> histogram;
|
std::vector<size_t> histogram;
|
||||||
RigHistogramCalculator histCalc(min, max, 100, &histogram);
|
RigHistogramCalculator histCalc(min, max, 100, &histogram);
|
||||||
histCalc.addData(valuesForTimeSteps);
|
histCalc.addData(valuesForTimeSteps);
|
||||||
|
|
||||||
double p10, p50, p90;
|
double p10, p50, p90;
|
||||||
p10 = histCalc.calculatePercentil(0.1);
|
p10 = histCalc.calculatePercentil(0.1);
|
||||||
p50 = histCalc.calculatePercentil(0.5);
|
p50 = histCalc.calculatePercentil(0.5);
|
||||||
p90 = histCalc.calculatePercentil(0.9);
|
p90 = histCalc.calculatePercentil(0.9);
|
||||||
|
|
||||||
m_p10Data.push_back(p10);
|
|
||||||
m_p50Data.push_back(p50);
|
|
||||||
m_p90Data.push_back(p90);
|
|
||||||
m_meanData.push_back(mean);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
m_p10Data.push_back(p10);
|
||||||
|
m_p50Data.push_back(p50);
|
||||||
|
m_p90Data.push_back(p90);
|
||||||
|
m_meanData.push_back(mean);
|
||||||
}
|
}
|
||||||
m_addressUsedInLastCalculation = inputAddress;
|
m_addressUsedInLastCalculation = inputAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
///
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
void RimEnsembleStatisticsCase::calculate()
|
|
||||||
{
|
|
||||||
auto inputAddress = m_curveSet->summaryAddress();
|
|
||||||
auto ensemble = m_curveSet->summaryCaseCollection();
|
|
||||||
if (m_statisticsReader && ensemble && inputAddress.isValid())
|
|
||||||
{
|
|
||||||
calculate(ensemble, inputAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@ -200,3 +194,46 @@ void RimEnsembleStatisticsCase::clearData()
|
|||||||
m_meanData.clear();
|
m_meanData.clear();
|
||||||
m_addressUsedInLastCalculation = RifEclipseSummaryAddress();
|
m_addressUsedInLastCalculation = RifEclipseSummaryAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
std::vector<RimSummaryCase*> RimEnsembleStatisticsCase::validSummaryCases(const std::vector<RimSummaryCase*> allSumCases, const RifEclipseSummaryAddress& inputAddress)
|
||||||
|
{
|
||||||
|
std::vector<RimSummaryCase*> validCases;
|
||||||
|
std::vector<std::tuple<RimSummaryCase*, time_t, time_t>> times;
|
||||||
|
|
||||||
|
time_t minTimeStep = std::numeric_limits<time_t>::max();
|
||||||
|
time_t maxTimeStep = 0;
|
||||||
|
|
||||||
|
for (auto& sumCase : allSumCases)
|
||||||
|
{
|
||||||
|
const auto& reader = sumCase->summaryReader();
|
||||||
|
if (reader)
|
||||||
|
{
|
||||||
|
std::vector<time_t> timeSteps = reader->timeSteps(inputAddress);
|
||||||
|
if (!timeSteps.empty())
|
||||||
|
{
|
||||||
|
time_t firstTimeStep = timeSteps.front();
|
||||||
|
time_t lastTimeStep = timeSteps.back();
|
||||||
|
|
||||||
|
if (firstTimeStep < minTimeStep) minTimeStep = firstTimeStep;
|
||||||
|
if (lastTimeStep > maxTimeStep) maxTimeStep = lastTimeStep;
|
||||||
|
times.push_back(std::make_tuple(sumCase, firstTimeStep, lastTimeStep));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& item : times)
|
||||||
|
{
|
||||||
|
RimSummaryCase* sumCase = std::get<0>(item);
|
||||||
|
time_t firstTimeStep = std::get<1>(item);
|
||||||
|
time_t lastTimeStep = std::get<2>(item);
|
||||||
|
|
||||||
|
if (firstTimeStep == minTimeStep && lastTimeStep == maxTimeStep)
|
||||||
|
{
|
||||||
|
validCases.push_back(sumCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return validCases;
|
||||||
|
}
|
||||||
|
@ -50,10 +50,11 @@ public:
|
|||||||
const RimEnsembleCurveSet* curveSet() const;
|
const RimEnsembleCurveSet* curveSet() const;
|
||||||
|
|
||||||
void calculate();
|
void calculate();
|
||||||
void calculate(const RimSummaryCaseCollection* ensemble, const RifEclipseSummaryAddress& inputAddress);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void calculate(const std::vector<RimSummaryCase*> sumCases, const RifEclipseSummaryAddress& inputAddress);
|
||||||
void clearData();
|
void clearData();
|
||||||
|
std::vector<RimSummaryCase*> validSummaryCases(const std::vector<RimSummaryCase*> allSumCases, const RifEclipseSummaryAddress& inputAddress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<RifEnsembleStatisticsReader> m_statisticsReader;
|
std::unique_ptr<RifEnsembleStatisticsReader> m_statisticsReader;
|
||||||
|
@ -890,8 +890,8 @@ void RimSummaryCurve::calculateCurveInterpolationFromAddress()
|
|||||||
if (m_yValuesCurveVariable())
|
if (m_yValuesCurveVariable())
|
||||||
{
|
{
|
||||||
auto category = m_yValuesCurveVariable()->address().category();
|
auto category = m_yValuesCurveVariable()->address().category();
|
||||||
QString quantityName = QString::fromUtf8(m_yValuesCurveVariable()->address().quantityName().c_str());
|
auto address = m_yValuesCurveVariable()->address();
|
||||||
if (quantityName.endsWith("T") || category == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS)
|
if (address.hasAccumulatedData())
|
||||||
{
|
{
|
||||||
m_curveInterpolation = INTERPOLATION_POINT_TO_POINT;
|
m_curveInterpolation = INTERPOLATION_POINT_TO_POINT;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user