///////////////////////////////////////////////////////////////////////////////// // // 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 // 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 RifReaderEnsembleStatisticsRft::eclipseRftAddresses() { std::set allAddresses; for (auto summaryCase : m_summaryCaseCollection->allSummaryCases()) { if (summaryCase->rftReader()) { std::set addresses = summaryCase->rftReader()->eclipseRftAddresses(); allAddresses.insert(addresses.begin(), addresses.end()); } } std::set statisticsAddresses; for (const RifEclipseRftAddress& regularAddress : allAddresses) { if (regularAddress.wellLogChannel() == RifEclipseRftAddress::TVD) { statisticsAddresses.insert(regularAddress); } else if (regularAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE) { std::set statChannels = {RifEclipseRftAddress::PRESSURE_P10, RifEclipseRftAddress::PRESSURE_P50, RifEclipseRftAddress::PRESSURE_P90, RifEclipseRftAddress::PRESSURE_MEAN}; for (auto channel : statChannels) { statisticsAddresses.insert(RifEclipseRftAddress(regularAddress.wellName(), regularAddress.timeStep(), channel)); } } } return statisticsAddresses; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifReaderEnsembleStatisticsRft::values(const RifEclipseRftAddress& rftAddress, std::vector* values) { CAF_ASSERT(rftAddress.wellLogChannel() == RifEclipseRftAddress::TVD || rftAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE_MEAN || rftAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE_P10 || rftAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE_P50 || rftAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE_P90); auto it = m_cachedValues.find(rftAddress); if (it == m_cachedValues.end()) { calculateStatistics(rftAddress); } *values = m_cachedValues[rftAddress]; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RifReaderEnsembleStatisticsRft::availableTimeSteps(const QString& wellName) { std::set allTimeSteps; for (auto summaryCase : m_summaryCaseCollection->allSummaryCases()) { if (summaryCase->rftReader()) { std::set timeSteps = summaryCase->rftReader()->availableTimeSteps(wellName); allTimeSteps.insert(timeSteps.begin(), timeSteps.end()); } } return allTimeSteps; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RifReaderEnsembleStatisticsRft::availableTimeSteps(const QString& wellName, const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName) { std::set allTimeSteps; for (auto summaryCase : m_summaryCaseCollection->allSummaryCases()) { if (summaryCase->rftReader()) { std::set timeSteps = summaryCase->rftReader()->availableTimeSteps(wellName, wellLogChannelName); allTimeSteps.insert(timeSteps.begin(), timeSteps.end()); } } return allTimeSteps; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RifReaderEnsembleStatisticsRft::availableTimeSteps( const QString& wellName, const std::set relevantChannels) { std::set allTimeSteps; for (auto summaryCase : m_summaryCaseCollection->allSummaryCases()) { if (summaryCase->rftReader()) { std::set timeSteps = summaryCase->rftReader()->availableTimeSteps(wellName, relevantChannels); allTimeSteps.insert(timeSteps.begin(), timeSteps.end()); } } return allTimeSteps; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RifReaderEnsembleStatisticsRft::availableWellLogChannels(const QString& wellName) { std::set allWellLogChannels; for (auto summaryCase : m_summaryCaseCollection->allSummaryCases()) { if (summaryCase->rftReader()) { std::set wellLogChannels = summaryCase->rftReader()->availableWellLogChannels(wellName); allWellLogChannels.insert(wellLogChannels.begin(), wellLogChannels.end()); } } return allWellLogChannels; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RifReaderEnsembleStatisticsRft::wellNames() { std::set allWellNames; for (auto summaryCase : m_summaryCaseCollection->allSummaryCases()) { if (summaryCase->rftReader()) { std::set 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(wellName, timeStep, RifEclipseRftAddress::TVD); RifEclipseRftAddress pressAddress(wellName, timeStep, RifEclipseRftAddress::PRESSURE); RifEclipseRftAddress p10Address(wellName, timeStep, RifEclipseRftAddress::PRESSURE_P10); RifEclipseRftAddress p50Address(wellName, timeStep, RifEclipseRftAddress::PRESSURE_P50); RifEclipseRftAddress p90Address(wellName, timeStep, RifEclipseRftAddress::PRESSURE_P90); RifEclipseRftAddress meanAddress(wellName, timeStep, RifEclipseRftAddress::PRESSURE_MEAN); RiaCurveMerger curveMerger; RiaWeightedMeanCalculator dataSetSizeCalc; for (RimSummaryCase* summaryCase : m_summaryCaseCollection->allSummaryCases()) { RifReaderRftInterface* reader = summaryCase->rftReader(); if (reader) { std::vector depths; std::vector pressures; reader->values(depthAddress, &depths); reader->values(pressAddress, &pressures); dataSetSizeCalc.addValueAndWeight(depths.size(), 1.0); curveMerger.addCurveData(depths, pressures); } } curveMerger.computeInterpolatedValues(false); clearData(wellName, timeStep); const std::vector& allDepths = curveMerger.allXValues(); if (!allDepths.empty()) { // Make sure we end up with approximately the same amount of points as originally size_t sizeMultiplier = allDepths.size() / dataSetSizeCalc.weightedMean(); for (size_t depthIdx = 0; depthIdx < allDepths.size(); depthIdx += sizeMultiplier) { std::vector pressuresAtDepth; pressuresAtDepth.reserve(curveMerger.curveCount()); for (size_t curveIdx = 0; curveIdx < curveMerger.curveCount(); ++curveIdx) { const std::vector& curvePressures = curveMerger.interpolatedYValuesForAllXValues(curveIdx); pressuresAtDepth.push_back(curvePressures[depthIdx]); } double p10, p50, p90, mean; RigStatisticsMath::calculateStatisticsCurves(pressuresAtDepth, &p10, &p50, &p90, &mean); 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); 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; } } }