mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-05 21:53:27 -06:00
952e766c2f
* Update to clang-format-15 Removed two custom .clang-format files in subfolders of AppFwk * Fixes by clang-format
276 lines
12 KiB
C++
276 lines
12 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2019- 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 <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RifReaderEnsembleStatisticsRft.h"
|
|
|
|
#include "RiaCurveMerger.h"
|
|
#include "RiaWeightedMeanCalculator.h"
|
|
#include "RigStatisticsMath.h"
|
|
|
|
#include "RimSummaryCase.h"
|
|
#include "RimSummaryCaseCollection.h"
|
|
|
|
#include "cafAssert.h"
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RifReaderEnsembleStatisticsRft::RifReaderEnsembleStatisticsRft( const RimSummaryCaseCollection* summaryCaseCollection )
|
|
: m_summaryCaseCollection( summaryCaseCollection )
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<RifEclipseRftAddress> RifReaderEnsembleStatisticsRft::eclipseRftAddresses()
|
|
{
|
|
std::set<RifEclipseRftAddress> allAddresses;
|
|
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
|
{
|
|
if ( summaryCase->rftReader() )
|
|
{
|
|
std::set<RifEclipseRftAddress> addresses = summaryCase->rftReader()->eclipseRftAddresses();
|
|
allAddresses.insert( addresses.begin(), addresses.end() );
|
|
}
|
|
}
|
|
|
|
std::set<RifEclipseRftAddress> statisticsAddresses;
|
|
for ( const RifEclipseRftAddress& regularAddress : allAddresses )
|
|
{
|
|
if ( regularAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::TVD )
|
|
{
|
|
statisticsAddresses.insert( regularAddress );
|
|
}
|
|
else if ( regularAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE )
|
|
{
|
|
std::set<RifEclipseRftAddress::RftWellLogChannelType> statChannels = { RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P10,
|
|
RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P50,
|
|
RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P90,
|
|
RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_MEAN };
|
|
for ( auto channel : statChannels )
|
|
{
|
|
statisticsAddresses.insert(
|
|
RifEclipseRftAddress::createAddress( regularAddress.wellName(), regularAddress.timeStep(), channel ) );
|
|
}
|
|
}
|
|
}
|
|
return statisticsAddresses;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEnsembleStatisticsRft::values( const RifEclipseRftAddress& rftAddress, std::vector<double>* values )
|
|
{
|
|
CAF_ASSERT( rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::TVD ||
|
|
rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_MEAN ||
|
|
rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P10 ||
|
|
rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P50 ||
|
|
rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P90 ||
|
|
rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_ERROR );
|
|
|
|
auto it = m_cachedValues.find( rftAddress );
|
|
if ( it == m_cachedValues.end() )
|
|
{
|
|
calculateStatistics( rftAddress );
|
|
}
|
|
*values = m_cachedValues[rftAddress];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<QDateTime> RifReaderEnsembleStatisticsRft::availableTimeSteps( const QString& wellName )
|
|
{
|
|
std::set<QDateTime> allTimeSteps;
|
|
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
|
{
|
|
if ( summaryCase->rftReader() )
|
|
{
|
|
std::set<QDateTime> timeSteps = summaryCase->rftReader()->availableTimeSteps( wellName );
|
|
allTimeSteps.insert( timeSteps.begin(), timeSteps.end() );
|
|
}
|
|
}
|
|
return allTimeSteps;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<QDateTime> RifReaderEnsembleStatisticsRft::availableTimeSteps( const QString& wellName,
|
|
const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName )
|
|
{
|
|
std::set<QDateTime> allTimeSteps;
|
|
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
|
{
|
|
if ( summaryCase->rftReader() )
|
|
{
|
|
std::set<QDateTime> timeSteps = summaryCase->rftReader()->availableTimeSteps( wellName, wellLogChannelName );
|
|
allTimeSteps.insert( timeSteps.begin(), timeSteps.end() );
|
|
}
|
|
}
|
|
return allTimeSteps;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<QDateTime>
|
|
RifReaderEnsembleStatisticsRft::availableTimeSteps( const QString& wellName,
|
|
const std::set<RifEclipseRftAddress::RftWellLogChannelType>& relevantChannels )
|
|
{
|
|
std::set<QDateTime> allTimeSteps;
|
|
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
|
{
|
|
if ( summaryCase->rftReader() )
|
|
{
|
|
std::set<QDateTime> timeSteps = summaryCase->rftReader()->availableTimeSteps( wellName, relevantChannels );
|
|
allTimeSteps.insert( timeSteps.begin(), timeSteps.end() );
|
|
}
|
|
}
|
|
return allTimeSteps;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<RifEclipseRftAddress::RftWellLogChannelType> RifReaderEnsembleStatisticsRft::availableWellLogChannels( const QString& wellName )
|
|
{
|
|
std::set<RifEclipseRftAddress::RftWellLogChannelType> allWellLogChannels;
|
|
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
|
{
|
|
if ( summaryCase->rftReader() )
|
|
{
|
|
std::set<RifEclipseRftAddress::RftWellLogChannelType> wellLogChannels =
|
|
summaryCase->rftReader()->availableWellLogChannels( wellName );
|
|
allWellLogChannels.insert( wellLogChannels.begin(), wellLogChannels.end() );
|
|
}
|
|
}
|
|
return allWellLogChannels;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<QString> RifReaderEnsembleStatisticsRft::wellNames()
|
|
{
|
|
std::set<QString> allWellNames;
|
|
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
|
{
|
|
if ( summaryCase->rftReader() )
|
|
{
|
|
std::set<QString> wellNames = summaryCase->rftReader()->wellNames();
|
|
allWellNames.insert( wellNames.begin(), wellNames.end() );
|
|
}
|
|
}
|
|
return allWellNames;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEnsembleStatisticsRft::calculateStatistics( const RifEclipseRftAddress& rftAddress )
|
|
{
|
|
const QString& wellName = rftAddress.wellName();
|
|
const QDateTime& timeStep = rftAddress.timeStep();
|
|
RifEclipseRftAddress depthAddress =
|
|
RifEclipseRftAddress::createAddress( wellName, timeStep, RifEclipseRftAddress::RftWellLogChannelType::TVD );
|
|
RifEclipseRftAddress pressAddress =
|
|
RifEclipseRftAddress::createAddress( wellName, timeStep, RifEclipseRftAddress::RftWellLogChannelType::PRESSURE );
|
|
|
|
RifEclipseRftAddress p10Address =
|
|
RifEclipseRftAddress::createAddress( wellName, timeStep, RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P10 );
|
|
RifEclipseRftAddress p50Address =
|
|
RifEclipseRftAddress::createAddress( wellName, timeStep, RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P50 );
|
|
RifEclipseRftAddress p90Address =
|
|
RifEclipseRftAddress::createAddress( wellName, timeStep, RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P90 );
|
|
RifEclipseRftAddress meanAddress =
|
|
RifEclipseRftAddress::createAddress( wellName, timeStep, RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_MEAN );
|
|
|
|
RiaCurveMerger<double> curveMerger;
|
|
|
|
RiaWeightedMeanCalculator<size_t> dataSetSizeCalc;
|
|
|
|
for ( RimSummaryCase* summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
|
{
|
|
RifReaderRftInterface* reader = summaryCase->rftReader();
|
|
if ( reader )
|
|
{
|
|
std::vector<double> depths;
|
|
std::vector<double> pressures;
|
|
reader->values( depthAddress, &depths );
|
|
reader->values( pressAddress, &pressures );
|
|
if ( !depths.empty() && !pressures.empty() )
|
|
{
|
|
dataSetSizeCalc.addValueAndWeight( depths.size(), 1.0 );
|
|
curveMerger.addCurveData( depths, pressures );
|
|
}
|
|
}
|
|
}
|
|
curveMerger.computeInterpolatedValues( false );
|
|
|
|
clearData( wellName, timeStep );
|
|
|
|
const std::vector<double>& allDepths = curveMerger.allXValues();
|
|
if ( !allDepths.empty() )
|
|
{
|
|
// Make sure we end up with approximately the same amount of points as originally
|
|
// Since allDepths contain *valid* values, it can potentially be smaller than the mean.
|
|
// Thus we need to ensure sizeMultiplier is at least 1.
|
|
size_t sizeMultiplier = std::max( (size_t)1, allDepths.size() / dataSetSizeCalc.weightedMean() );
|
|
for ( size_t depthIdx = 0; depthIdx < allDepths.size(); depthIdx += sizeMultiplier )
|
|
{
|
|
std::vector<double> pressuresAtDepth;
|
|
pressuresAtDepth.reserve( curveMerger.curveCount() );
|
|
for ( size_t curveIdx = 0; curveIdx < curveMerger.curveCount(); ++curveIdx )
|
|
{
|
|
const std::vector<double>& curvePressures = curveMerger.interpolatedYValuesForAllXValues( curveIdx );
|
|
pressuresAtDepth.push_back( curvePressures[depthIdx] );
|
|
}
|
|
double p10, p50, p90, mean;
|
|
RigStatisticsMath::calculateStatisticsCurves( pressuresAtDepth, &p10, &p50, &p90, &mean, RigStatisticsMath::PercentileStyle::SWITCHED );
|
|
|
|
m_cachedValues[depthAddress].push_back( allDepths[depthIdx] );
|
|
|
|
if ( p10 != HUGE_VAL ) m_cachedValues[p10Address].push_back( p10 );
|
|
if ( p50 != HUGE_VAL ) m_cachedValues[p50Address].push_back( p50 );
|
|
if ( p90 != HUGE_VAL ) m_cachedValues[p90Address].push_back( p90 );
|
|
if ( mean != HUGE_VAL ) m_cachedValues[meanAddress].push_back( mean );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RifReaderEnsembleStatisticsRft::clearData( const QString& wellName, const QDateTime& timeStep )
|
|
{
|
|
for ( auto it = m_cachedValues.begin(); it != m_cachedValues.end(); )
|
|
{
|
|
if ( it->first.wellName() == wellName && it->first.timeStep() == timeStep )
|
|
{
|
|
it = m_cachedValues.erase( it );
|
|
}
|
|
else
|
|
{
|
|
++it;
|
|
}
|
|
}
|
|
}
|