mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
RFT ensemble refactoring
* Compute average MD for intersections with a cell * Create extractor for simulation well * Remove rftReader from RifDataSourceForRftPlt * Add function compute measured depth for RFT cells based on well path geometry * Move statistics reader to well ensemble curve set * Make sure both TVD and MD are cached if possible * Add selection of grid case to use for estimation of measured depth (MD) Add "Grid Model For MD" where the user can select a grid model. This grid model is propagated to a hidden field in EnsembleCurveSet. The grid model is then applied to RifReaderEnsembleStatisticsRft owned by EnsembleCurveSet
This commit is contained in:
parent
fe17b211b8
commit
7a782cec66
@ -18,11 +18,16 @@
|
||||
|
||||
#include "RiaExtractionTools.h"
|
||||
|
||||
#include "RiaSimWellBranchTools.h"
|
||||
|
||||
#include "RigWellPath.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimSimWellInView.h"
|
||||
#include "RimTools.h"
|
||||
#include "RimWellLogPlotCollection.h"
|
||||
#include "RimWellPathCollection.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
@ -37,6 +42,22 @@ RigEclipseWellLogExtractor* RiaExtractionTools::findOrCreateWellLogExtractor( Ri
|
||||
return wlPlotCollection->findOrCreateExtractor( wellPath, eclipseCase );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigEclipseWellLogExtractor* RiaExtractionTools::findOrCreateWellLogExtractor( const QString& wellName, RimEclipseCase* eclipseCase )
|
||||
{
|
||||
if ( !eclipseCase ) return nullptr;
|
||||
|
||||
if ( auto wellPathCollection = RimTools::wellPathCollection() )
|
||||
{
|
||||
auto wellPath = wellPathCollection->tryFindMatchingWellPath( wellName );
|
||||
return RiaExtractionTools::findOrCreateWellLogExtractor( wellPath, eclipseCase );
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -71,6 +92,33 @@ RigEclipseWellLogExtractor* RiaExtractionTools::findOrCreateSimWellExtractor( co
|
||||
return wlPlotCollection->findOrCreateSimWellExtractor( simWell->name, caseUserDescription, wellPathGeom, eclipseCase->eclipseCaseData() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigEclipseWellLogExtractor* RiaExtractionTools::findOrCreateSimWellExtractor( RimEclipseCase* eclipseCase,
|
||||
const QString& simWellName,
|
||||
bool useBranchDetection,
|
||||
int branchIndex )
|
||||
{
|
||||
if ( !eclipseCase ) return nullptr;
|
||||
|
||||
auto wlPlotCollection = wellLogPlotCollection();
|
||||
if ( !wlPlotCollection ) return nullptr;
|
||||
|
||||
std::vector<const RigWellPath*> wellPaths = RiaSimWellBranchTools::simulationWellBranches( simWellName, useBranchDetection );
|
||||
if ( wellPaths.empty() ) return nullptr;
|
||||
|
||||
branchIndex = RiaSimWellBranchTools::clampBranchIndex( simWellName, branchIndex, useBranchDetection );
|
||||
if ( branchIndex >= static_cast<int>( wellPaths.size() ) ) return nullptr;
|
||||
|
||||
auto wellPathBranch = wellPaths[branchIndex];
|
||||
|
||||
return wlPlotCollection->findOrCreateSimWellExtractor( simWellName,
|
||||
QString( "Find or create sim well extractor" ),
|
||||
wellPathBranch,
|
||||
eclipseCase->eclipseCaseData() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -36,11 +36,18 @@ class QString;
|
||||
//==================================================================================================
|
||||
namespace RiaExtractionTools
|
||||
{
|
||||
RigEclipseWellLogExtractor* findOrCreateWellLogExtractor( RimWellPath* wellPath, RimEclipseCase* eclipseCase );
|
||||
RigGeoMechWellLogExtractor* findOrCreateWellLogExtractor( RimWellPath* wellPath, RimGeoMechCase* geomCase, int partId = 0 );
|
||||
|
||||
RigEclipseWellLogExtractor* findOrCreateSimWellExtractor( const RimSimWellInView* simWell, const RigWellPath* wellPathGeom );
|
||||
|
||||
RimWellLogPlotCollection* wellLogPlotCollection();
|
||||
|
||||
// Eclipse
|
||||
RigEclipseWellLogExtractor* findOrCreateWellLogExtractor( const QString& wellName, RimEclipseCase* eclipseCase );
|
||||
RigEclipseWellLogExtractor* findOrCreateWellLogExtractor( RimWellPath* wellPath, RimEclipseCase* eclipseCase );
|
||||
|
||||
// GeoMech
|
||||
RigGeoMechWellLogExtractor* findOrCreateWellLogExtractor( RimWellPath* wellPath, RimGeoMechCase* geomCase, int partId = 0 );
|
||||
|
||||
// Simulation wells
|
||||
RigEclipseWellLogExtractor* findOrCreateSimWellExtractor( const RimSimWellInView* simWell, const RigWellPath* wellPathGeom );
|
||||
RigEclipseWellLogExtractor*
|
||||
findOrCreateSimWellExtractor( RimEclipseCase* eclipseCase, const QString& simWellName, bool useBranchDetection, int branchIndex );
|
||||
|
||||
}; // namespace RiaExtractionTools
|
||||
|
@ -356,7 +356,7 @@ RimWellLogRftCurve* RicWellLogTools::addRftCurve( RimWellLogTrack* plotTrack, co
|
||||
|
||||
if ( simWell && resultCase )
|
||||
{
|
||||
curve->setEclipseResultCase( resultCase );
|
||||
curve->setEclipseCase( resultCase );
|
||||
curve->setDefaultAddress( simWell->name() );
|
||||
|
||||
plotTrack->setFormationCase( resultCase );
|
||||
@ -364,7 +364,7 @@ RimWellLogRftCurve* RicWellLogTools::addRftCurve( RimWellLogTrack* plotTrack, co
|
||||
}
|
||||
else if ( resultCase )
|
||||
{
|
||||
curve->setEclipseResultCase( resultCase );
|
||||
curve->setEclipseCase( resultCase );
|
||||
|
||||
auto wellNames = resultCase->rftReader()->wellNames();
|
||||
if ( !wellNames.empty() )
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
#include "RifDataSourceForRftPlt.h"
|
||||
|
||||
#include "RifReaderEclipseRft.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
@ -230,37 +229,6 @@ auto RifDataSourceForRftPlt::operator<=>( const RifDataSourceForRftPlt& addr2 )
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifReaderRftInterface* RifDataSourceForRftPlt::rftReader() const
|
||||
{
|
||||
if ( m_sourceType == SourceType::GRID_MODEL_CELL_DATA || m_sourceType == SourceType::RFT_SIM_WELL_DATA )
|
||||
{
|
||||
// TODO: Consider changing to RimEclipseResultCase to avoid casting
|
||||
auto eclResCase = dynamic_cast<RimEclipseResultCase*>( eclCase() );
|
||||
|
||||
if ( eclResCase ) return eclResCase->rftReader();
|
||||
}
|
||||
else if ( m_sourceType == SourceType::SUMMARY_RFT )
|
||||
{
|
||||
if ( m_summaryCase ) return m_summaryCase->rftReader();
|
||||
}
|
||||
else if ( m_sourceType == SourceType::ENSEMBLE_RFT )
|
||||
{
|
||||
if ( m_ensemble ) return m_ensemble->rftStatisticsReader();
|
||||
}
|
||||
else if ( m_sourceType == SourceType::OBSERVED_FMU_RFT )
|
||||
{
|
||||
if ( m_observedFmuRftData ) return m_observedFmuRftData->rftReader();
|
||||
}
|
||||
else if ( m_sourceType == SourceType::OBSERVED_PRESSURE_DEPTH )
|
||||
{
|
||||
if ( m_pressureDepthData ) return m_pressureDepthData->rftReader();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
class RimWellLogFile;
|
||||
class RimEclipseCase;
|
||||
class RifReaderRftInterface;
|
||||
class RimSummaryCase;
|
||||
class RimSummaryCaseCollection;
|
||||
class RimObservedFmuRftData;
|
||||
@ -64,8 +63,7 @@ public:
|
||||
RifDataSourceForRftPlt( RimObservedFmuRftData* observedFmuRftData );
|
||||
RifDataSourceForRftPlt( RimPressureDepthData* pressureDepthData );
|
||||
|
||||
SourceType sourceType() const;
|
||||
RifReaderRftInterface* rftReader() const;
|
||||
SourceType sourceType() const;
|
||||
|
||||
RimEclipseCase* eclCase() const;
|
||||
RimSummaryCase* summaryCase() const;
|
||||
|
@ -246,19 +246,17 @@ void RifReaderEclipseRft::values( const RifEclipseRftAddress& rftAddress, std::v
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifReaderEclipseRft::cellIndices( const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices )
|
||||
std::vector<caf::VecIjk> RifReaderEclipseRft::cellIndices( const QString& wellName, const QDateTime& timeStep )
|
||||
{
|
||||
CVF_ASSERT( indices );
|
||||
|
||||
if ( !m_ecl_rft_file )
|
||||
{
|
||||
open();
|
||||
}
|
||||
|
||||
indices->clear();
|
||||
int index = indexFromAddress( wellName, timeStep );
|
||||
if ( index < 0 ) return {};
|
||||
|
||||
int index = indexFromAddress( rftAddress );
|
||||
if ( index < 0 ) return;
|
||||
std::vector<caf::VecIjk> indices;
|
||||
|
||||
ecl_rft_node_type* node = ecl_rft_file_iget_node( m_ecl_rft_file, index );
|
||||
|
||||
@ -268,8 +266,10 @@ void RifReaderEclipseRft::cellIndices( const RifEclipseRftAddress& rftAddress, s
|
||||
ecl_rft_node_iget_ijk( node, cellIdx, &i, &j, &k );
|
||||
|
||||
caf::VecIjk ijk( (size_t)i, (size_t)j, (size_t)k );
|
||||
indices->push_back( ijk );
|
||||
indices.push_back( ijk );
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -453,3 +453,19 @@ int RifReaderEclipseRft::indexFromAddress( const RifEclipseRftAddress& rftAddres
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RifReaderEclipseRft::indexFromAddress( const QString& wellName, const QDateTime& timeStep ) const
|
||||
{
|
||||
for ( const auto& [rftAddr, nodeIdx] : m_rftAddressToLibeclNodeIdx )
|
||||
{
|
||||
if ( rftAddr.wellName() == wellName && rftAddr.timeStep() == timeStep )
|
||||
{
|
||||
return nodeIdx;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
|
||||
std::set<RifEclipseRftAddress> eclipseRftAddresses() override;
|
||||
void values( const RifEclipseRftAddress& rftAddress, std::vector<double>* values ) override;
|
||||
void cellIndices( const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices ) override;
|
||||
std::vector<caf::VecIjk> cellIndices( const QString& wellName, const QDateTime& timeStep ) override;
|
||||
|
||||
std::set<QDateTime> availableTimeSteps( const QString& wellName ) override;
|
||||
std::set<QDateTime> availableTimeSteps( const QString& wellName,
|
||||
@ -60,6 +60,7 @@ public:
|
||||
private:
|
||||
void open();
|
||||
int indexFromAddress( const RifEclipseRftAddress& rftAddress ) const;
|
||||
int indexFromAddress( const QString& wellName, const QDateTime& timeStep ) const;
|
||||
|
||||
private:
|
||||
// NOLINTBEGIN(modernize-use-using)
|
||||
|
@ -18,20 +18,23 @@
|
||||
|
||||
#include "RifReaderEnsembleStatisticsRft.h"
|
||||
|
||||
#include "RiaCurveMerger.h"
|
||||
#include "RiaWeightedMeanCalculator.h"
|
||||
#include "RiaExtractionTools.h"
|
||||
|
||||
#include "RigStatisticsMath.h"
|
||||
|
||||
#include "RimSummaryCase.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
#include "RimTools.h"
|
||||
|
||||
#include "cafAssert.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifReaderEnsembleStatisticsRft::RifReaderEnsembleStatisticsRft( const RimSummaryCaseCollection* summaryCaseCollection )
|
||||
RifReaderEnsembleStatisticsRft::RifReaderEnsembleStatisticsRft( const RimSummaryCaseCollection* summaryCaseCollection,
|
||||
RimEclipseCase* eclipseCase )
|
||||
: m_summaryCaseCollection( summaryCaseCollection )
|
||||
, m_eclipseCase( eclipseCase )
|
||||
{
|
||||
}
|
||||
|
||||
@ -40,6 +43,8 @@ RifReaderEnsembleStatisticsRft::RifReaderEnsembleStatisticsRft( const RimSummary
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<RifEclipseRftAddress> RifReaderEnsembleStatisticsRft::eclipseRftAddresses()
|
||||
{
|
||||
if ( !m_summaryCaseCollection ) return {};
|
||||
|
||||
std::set<RifEclipseRftAddress> allAddresses;
|
||||
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
||||
{
|
||||
@ -78,7 +83,10 @@ std::set<RifEclipseRftAddress> RifReaderEnsembleStatisticsRft::eclipseRftAddress
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifReaderEnsembleStatisticsRft::values( const RifEclipseRftAddress& rftAddress, std::vector<double>* values )
|
||||
{
|
||||
CAF_ASSERT( rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::TVD ||
|
||||
if ( !m_summaryCaseCollection ) return;
|
||||
|
||||
CAF_ASSERT( rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::MD ||
|
||||
rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::TVD ||
|
||||
rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_MEAN ||
|
||||
rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P10 ||
|
||||
rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P50 ||
|
||||
@ -88,7 +96,7 @@ void RifReaderEnsembleStatisticsRft::values( const RifEclipseRftAddress& rftAddr
|
||||
auto it = m_cachedValues.find( rftAddress );
|
||||
if ( it == m_cachedValues.end() )
|
||||
{
|
||||
calculateStatistics( rftAddress );
|
||||
calculateStatistics( rftAddress.wellName(), rftAddress.timeStep() );
|
||||
}
|
||||
*values = m_cachedValues[rftAddress];
|
||||
}
|
||||
@ -98,6 +106,8 @@ void RifReaderEnsembleStatisticsRft::values( const RifEclipseRftAddress& rftAddr
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<QDateTime> RifReaderEnsembleStatisticsRft::availableTimeSteps( const QString& wellName )
|
||||
{
|
||||
if ( !m_summaryCaseCollection ) return {};
|
||||
|
||||
std::set<QDateTime> allTimeSteps;
|
||||
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
||||
{
|
||||
@ -116,6 +126,8 @@ std::set<QDateTime> RifReaderEnsembleStatisticsRft::availableTimeSteps( const QS
|
||||
std::set<QDateTime> RifReaderEnsembleStatisticsRft::availableTimeSteps( const QString& wellName,
|
||||
const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName )
|
||||
{
|
||||
if ( !m_summaryCaseCollection ) return {};
|
||||
|
||||
std::set<QDateTime> allTimeSteps;
|
||||
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
||||
{
|
||||
@ -135,6 +147,8 @@ std::set<QDateTime>
|
||||
RifReaderEnsembleStatisticsRft::availableTimeSteps( const QString& wellName,
|
||||
const std::set<RifEclipseRftAddress::RftWellLogChannelType>& relevantChannels )
|
||||
{
|
||||
if ( !m_summaryCaseCollection ) return {};
|
||||
|
||||
std::set<QDateTime> allTimeSteps;
|
||||
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
||||
{
|
||||
@ -152,6 +166,8 @@ std::set<QDateTime>
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<RifEclipseRftAddress::RftWellLogChannelType> RifReaderEnsembleStatisticsRft::availableWellLogChannels( const QString& wellName )
|
||||
{
|
||||
if ( !m_summaryCaseCollection ) return {};
|
||||
|
||||
std::set<RifEclipseRftAddress::RftWellLogChannelType> allWellLogChannels;
|
||||
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
||||
{
|
||||
@ -170,6 +186,8 @@ std::set<RifEclipseRftAddress::RftWellLogChannelType> RifReaderEnsembleStatistic
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<QString> RifReaderEnsembleStatisticsRft::wellNames()
|
||||
{
|
||||
if ( !m_summaryCaseCollection ) return {};
|
||||
|
||||
std::set<QString> allWellNames;
|
||||
for ( auto summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
||||
{
|
||||
@ -185,47 +203,110 @@ std::set<QString> RifReaderEnsembleStatisticsRft::wellNames()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifReaderEnsembleStatisticsRft::calculateStatistics( const RifEclipseRftAddress& rftAddress )
|
||||
void RifReaderEnsembleStatisticsRft::calculateStatistics( const QString& wellName, const QDateTime& timeStep )
|
||||
{
|
||||
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 );
|
||||
if ( !m_summaryCaseCollection ) return;
|
||||
|
||||
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 );
|
||||
using ChannelType = RifEclipseRftAddress::RftWellLogChannelType;
|
||||
RifEclipseRftAddress pressAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::PRESSURE );
|
||||
RifEclipseRftAddress tvdAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::TVD );
|
||||
|
||||
RiaCurveMerger<double> curveMerger;
|
||||
|
||||
RiaWeightedMeanCalculator<size_t> dataSetSizeCalc;
|
||||
|
||||
for ( RimSummaryCase* summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
||||
RigEclipseWellLogExtractor* extractor = RiaExtractionTools::findOrCreateWellLogExtractor( wellName, m_eclipseCase );
|
||||
if ( extractor )
|
||||
{
|
||||
RifReaderRftInterface* reader = summaryCase->rftReader();
|
||||
if ( reader )
|
||||
// Create a well log extractor if a well path and an Eclipse case is defined
|
||||
// Use the extractor to compute measured depth for RFT cells
|
||||
// The TVD values is extracted from the first summary case
|
||||
|
||||
RifEclipseRftAddress mdAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::MD );
|
||||
RiaCurveMerger<double> curveMerger;
|
||||
RiaWeightedMeanCalculator<size_t> dataSetSizeCalc;
|
||||
std::vector<double> tvdDepthsForFirstRftCase;
|
||||
|
||||
for ( RimSummaryCase* summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
||||
{
|
||||
std::vector<double> depths;
|
||||
auto reader = summaryCase->rftReader();
|
||||
if ( !reader ) continue;
|
||||
|
||||
std::vector<double> pressures;
|
||||
reader->values( depthAddress, &depths );
|
||||
reader->values( pressAddress, &pressures );
|
||||
if ( !depths.empty() && !pressures.empty() )
|
||||
|
||||
if ( tvdDepthsForFirstRftCase.empty() )
|
||||
{
|
||||
dataSetSizeCalc.addValueAndWeight( depths.size(), 1.0 );
|
||||
curveMerger.addCurveData( depths, pressures );
|
||||
reader->values( tvdAddress, &tvdDepthsForFirstRftCase );
|
||||
}
|
||||
|
||||
std::vector<double> measuredDepths = reader->computeMeasuredDepth( wellName, timeStep, extractor );
|
||||
|
||||
if ( !measuredDepths.empty() && !pressures.empty() )
|
||||
{
|
||||
dataSetSizeCalc.addValueAndWeight( measuredDepths.size(), 1.0 );
|
||||
curveMerger.addCurveData( measuredDepths, pressures );
|
||||
}
|
||||
}
|
||||
}
|
||||
curveMerger.computeInterpolatedValues( false );
|
||||
|
||||
clearData( wellName, timeStep );
|
||||
extractStatisticsFromCurveMerger( wellName, timeStep, mdAddress, curveMerger, dataSetSizeCalc );
|
||||
|
||||
if ( m_cachedValues[mdAddress].size() == tvdDepthsForFirstRftCase.size() )
|
||||
{
|
||||
// The number of RFT cells can vary between realizations in some cases. TVD depth is only given if the number of RFT cells is
|
||||
// identical between realizations.
|
||||
|
||||
m_cachedValues[tvdAddress] = tvdDepthsForFirstRftCase;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute statistics based on TVD depths. No measured depth can be estimated.
|
||||
// This concept works well for vertical wells, but does not work for horizontal wells.
|
||||
|
||||
RiaCurveMerger<double> curveMerger;
|
||||
RiaWeightedMeanCalculator<size_t> dataSetSizeCalc;
|
||||
RifEclipseRftAddress tvdAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::TVD );
|
||||
|
||||
for ( RimSummaryCase* summaryCase : m_summaryCaseCollection->allSummaryCases() )
|
||||
{
|
||||
auto reader = summaryCase->rftReader();
|
||||
if ( !reader ) continue;
|
||||
|
||||
std::vector<double> pressures;
|
||||
reader->values( pressAddress, &pressures );
|
||||
|
||||
std::vector<double> tvdDepths;
|
||||
reader->values( tvdAddress, &tvdDepths );
|
||||
|
||||
if ( !tvdDepths.empty() && !pressures.empty() )
|
||||
{
|
||||
dataSetSizeCalc.addValueAndWeight( tvdDepths.size(), 1.0 );
|
||||
curveMerger.addCurveData( tvdDepths, pressures );
|
||||
}
|
||||
}
|
||||
|
||||
extractStatisticsFromCurveMerger( wellName, timeStep, tvdAddress, curveMerger, dataSetSizeCalc );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Compute statistics for values, either based on measured depth or TVD
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifReaderEnsembleStatisticsRft::extractStatisticsFromCurveMerger( const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RifEclipseRftAddress depthAddress,
|
||||
RiaCurveMerger<double>& curveMerger,
|
||||
RiaWeightedMeanCalculator<size_t>& dataSetSizeCalc )
|
||||
{
|
||||
using ChannelType = RifEclipseRftAddress::RftWellLogChannelType;
|
||||
|
||||
CAF_ASSERT( depthAddress.wellLogChannel() == ChannelType::MD || depthAddress.wellLogChannel() == ChannelType::TVD );
|
||||
|
||||
auto p10Address = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::PRESSURE_P10 );
|
||||
auto p50Address = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::PRESSURE_P50 );
|
||||
auto p90Address = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::PRESSURE_P90 );
|
||||
auto meanAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::PRESSURE_MEAN );
|
||||
|
||||
clearCache( wellName, timeStep );
|
||||
|
||||
curveMerger.computeInterpolatedValues( false );
|
||||
|
||||
const std::vector<double>& allDepths = curveMerger.allXValues();
|
||||
if ( !allDepths.empty() )
|
||||
@ -259,7 +340,7 @@ void RifReaderEnsembleStatisticsRft::calculateStatistics( const RifEclipseRftAdd
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifReaderEnsembleStatisticsRft::clearData( const QString& wellName, const QDateTime& timeStep )
|
||||
void RifReaderEnsembleStatisticsRft::clearCache( const QString& wellName, const QDateTime& timeStep )
|
||||
{
|
||||
for ( auto it = m_cachedValues.begin(); it != m_cachedValues.end(); )
|
||||
{
|
||||
|
@ -20,14 +20,18 @@
|
||||
|
||||
#include "RifReaderEclipseRft.h"
|
||||
|
||||
#include "RiaCurveMerger.h"
|
||||
#include "RiaWeightedMeanCalculator.h"
|
||||
|
||||
#include "cvfObject.h"
|
||||
|
||||
class RimSummaryCaseCollection;
|
||||
class RimEclipseCase;
|
||||
|
||||
class RifReaderEnsembleStatisticsRft : public RifReaderRftInterface, public cvf::Object
|
||||
{
|
||||
public:
|
||||
RifReaderEnsembleStatisticsRft( const RimSummaryCaseCollection* summaryCaseCollection );
|
||||
RifReaderEnsembleStatisticsRft( const RimSummaryCaseCollection* summaryCaseCollection, RimEclipseCase* eclipseCase );
|
||||
|
||||
std::set<RifEclipseRftAddress> eclipseRftAddresses() override;
|
||||
void values( const RifEclipseRftAddress& rftAddress, std::vector<double>* values ) override;
|
||||
@ -41,11 +45,19 @@ public:
|
||||
std::set<QString> wellNames() override;
|
||||
|
||||
private:
|
||||
void calculateStatistics( const RifEclipseRftAddress& rftAddress );
|
||||
void clearData( const QString& wellName, const QDateTime& timeStep );
|
||||
void calculateStatistics( const QString& wellName, const QDateTime& timeStep );
|
||||
|
||||
void extractStatisticsFromCurveMerger( const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RifEclipseRftAddress depthAddress,
|
||||
RiaCurveMerger<double>& curveMerger,
|
||||
RiaWeightedMeanCalculator<size_t>& dataSetSizeCalc );
|
||||
|
||||
void clearCache( const QString& wellName, const QDateTime& timeStep );
|
||||
|
||||
private:
|
||||
const RimSummaryCaseCollection* m_summaryCaseCollection;
|
||||
RimEclipseCase* m_eclipseCase;
|
||||
|
||||
std::map<RifEclipseRftAddress, std::vector<double>> m_cachedValues;
|
||||
};
|
||||
|
@ -272,40 +272,44 @@ std::set<QString> RifReaderOpmRft::wellNames()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifReaderOpmRft::cellIndices( const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices )
|
||||
std::vector<caf::VecIjk> RifReaderOpmRft::cellIndices( const QString& wellName, const QDateTime& timeStep )
|
||||
{
|
||||
if ( !openFiles() ) return;
|
||||
if ( !openFiles() ) return {};
|
||||
|
||||
auto wellName = rftAddress.wellName().toStdString();
|
||||
auto stdWellName = wellName.toStdString();
|
||||
|
||||
auto date = rftAddress.timeStep().date();
|
||||
auto date = timeStep.date();
|
||||
int y = date.year();
|
||||
int m = date.month();
|
||||
int d = date.day();
|
||||
|
||||
std::vector<caf::VecIjk> indices;
|
||||
|
||||
try
|
||||
{
|
||||
auto resultNameI = "CONIPOS";
|
||||
auto dataI = m_opm_rft->getRft<int>( resultNameI, wellName, y, m, d );
|
||||
auto dataI = m_opm_rft->getRft<int>( resultNameI, stdWellName, y, m, d );
|
||||
|
||||
auto resultNameJ = "CONJPOS";
|
||||
auto dataJ = m_opm_rft->getRft<int>( resultNameJ, wellName, y, m, d );
|
||||
auto dataJ = m_opm_rft->getRft<int>( resultNameJ, stdWellName, y, m, d );
|
||||
|
||||
auto resultNameK = "CONKPOS";
|
||||
auto dataK = m_opm_rft->getRft<int>( resultNameK, wellName, y, m, d );
|
||||
auto dataK = m_opm_rft->getRft<int>( resultNameK, stdWellName, y, m, d );
|
||||
|
||||
if ( !dataI.empty() && ( dataI.size() == dataJ.size() ) && ( dataI.size() == dataK.size() ) )
|
||||
{
|
||||
for ( size_t n = 0; n < dataI.size(); n++ )
|
||||
{
|
||||
// NB: Transform to zero-based cell indices
|
||||
indices->push_back( caf::VecIjk( dataI[n] - 1, dataJ[n] - 1, dataK[n] - 1 ) );
|
||||
indices.push_back( caf::VecIjk( dataI[n] - 1, dataJ[n] - 1, dataK[n] - 1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
std::set<RifEclipseRftAddress::RftWellLogChannelType> availableWellLogChannels( const QString& wellName ) override;
|
||||
std::set<QString> wellNames() override;
|
||||
|
||||
void cellIndices( const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices ) override;
|
||||
std::vector<caf::VecIjk> cellIndices( const QString& wellName, const QDateTime& timeStep ) override;
|
||||
|
||||
std::map<int, int> branchIdsAndOneBasedIndices( const QString& wellName, const QDateTime& timeStep, RiaDefines::RftBranchType branchType );
|
||||
|
||||
|
@ -15,8 +15,17 @@
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RifReaderRftInterface.h"
|
||||
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseWellLogExtractor.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigWellPath.h"
|
||||
#include "RigWellPathGeometryTools.h"
|
||||
|
||||
#include "cafVecIjk.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -34,9 +43,104 @@ std::set<RifEclipseRftAddress> RifReaderRftInterface::eclipseRftAddresses( const
|
||||
return matchingAddresses;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Compute average measured depth for cell based on grid intersections for cells. If the well path geometry do not contain measured depth
|
||||
// for a grid cell, the measured depth is estimated based on existing geometry for the well path.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double>
|
||||
RifReaderRftInterface::computeMeasuredDepth( const QString& wellName, const QDateTime& timeStep, RigEclipseWellLogExtractor* eclExtractor )
|
||||
{
|
||||
if ( !eclExtractor ) return {};
|
||||
if ( !eclExtractor->caseData() ) return {};
|
||||
|
||||
if ( eclExtractor->cellIntersectionMDs().empty() ) return {};
|
||||
|
||||
auto mainGrid = eclExtractor->caseData()->mainGrid();
|
||||
if ( !mainGrid ) return {};
|
||||
|
||||
std::vector<double> avgMeasuredDepthForCells;
|
||||
std::vector<double> tvdValuesToEstimate;
|
||||
|
||||
auto cellIjk = cellIndices( wellName, timeStep );
|
||||
for ( const caf::VecIjk& ijk : cellIjk )
|
||||
{
|
||||
auto globalCellIndex = mainGrid->cellIndexFromIJK( ijk.i(), ijk.j(), ijk.k() );
|
||||
|
||||
auto avgMd = eclExtractor->averageMdForCell( globalCellIndex );
|
||||
if ( avgMd.has_value() )
|
||||
{
|
||||
avgMeasuredDepthForCells.push_back( avgMd.value() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// The RFT cell is not part of cells intersected by well path
|
||||
// Use the TVD of cell center to estimate measured depth
|
||||
|
||||
avgMeasuredDepthForCells.push_back( std::numeric_limits<double>::infinity() );
|
||||
auto center = mainGrid->cell( globalCellIndex ).center();
|
||||
tvdValuesToEstimate.push_back( -center.z() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !tvdValuesToEstimate.empty() )
|
||||
{
|
||||
auto wellPathMd = eclExtractor->wellPathGeometry()->measuredDepths();
|
||||
auto wellPathTvd = eclExtractor->wellPathGeometry()->trueVerticalDepths();
|
||||
|
||||
// Estimate measured depth for cells that do not have measured depth
|
||||
auto estimatedMeasuredDepth = RigWellPathGeometryTools::interpolateMdFromTvd( wellPathMd, wellPathTvd, tvdValuesToEstimate );
|
||||
|
||||
double previousMd = std::numeric_limits<double>::infinity();
|
||||
|
||||
// Replace infinity MD values with estimated MD values based on well path geometry
|
||||
// previousMd contains the last known measured depth value as we move along the well path
|
||||
|
||||
size_t estimatedIndex = 0;
|
||||
for ( auto& measuredDepth : avgMeasuredDepthForCells )
|
||||
{
|
||||
if ( measuredDepth == std::numeric_limits<double>::infinity() )
|
||||
{
|
||||
// No measured depth for cell is found, try to estimate MD based on MD for previous cell
|
||||
if ( estimatedIndex < estimatedMeasuredDepth.size() )
|
||||
{
|
||||
double estimatedMd = estimatedMeasuredDepth[estimatedIndex++];
|
||||
if ( previousMd != std::numeric_limits<double>::infinity() )
|
||||
{
|
||||
if ( previousMd < estimatedMd )
|
||||
{
|
||||
// The estimated MD is larger than previous MD, use the estimated MD
|
||||
measuredDepth = estimatedMd;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The estimated MD is smaller than previous MD, use the previous MD + 1.0
|
||||
measuredDepth = previousMd + 1.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We do not have a valid previous MD, use the estimated MD
|
||||
measuredDepth = estimatedMd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
measuredDepth = previousMd + 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign the current MD as previous MD to be used for next estimated MD
|
||||
previousMd = measuredDepth;
|
||||
}
|
||||
}
|
||||
|
||||
return avgMeasuredDepthForCells;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifReaderRftInterface::cellIndices( const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices )
|
||||
std::vector<caf::VecIjk> RifReaderRftInterface::cellIndices( const QString& wellName, const QDateTime& timeStep )
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ namespace caf
|
||||
class VecIjk;
|
||||
};
|
||||
|
||||
class RigEclipseWellLogExtractor;
|
||||
|
||||
class RifReaderRftInterface
|
||||
{
|
||||
public:
|
||||
@ -46,5 +48,9 @@ public:
|
||||
virtual std::set<RifEclipseRftAddress::RftWellLogChannelType> availableWellLogChannels( const QString& wellName ) = 0;
|
||||
virtual std::set<QString> wellNames() = 0;
|
||||
|
||||
virtual void cellIndices( const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices );
|
||||
// To be moved into Rig structures
|
||||
std::vector<double> computeMeasuredDepth( const QString& wellName, const QDateTime& timeStep, RigEclipseWellLogExtractor* extractor );
|
||||
|
||||
// TODO: Move to protected or private
|
||||
virtual std::vector<caf::VecIjk> cellIndices( const QString& wellName, const QDateTime& timeStep );
|
||||
};
|
||||
|
@ -597,6 +597,18 @@ std::set<QDateTime> RimWellPlotTools::availableSimWellTimesteps( RimEclipseCase*
|
||||
return availebleTimeSteps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifReaderRftInterface* RimWellPlotTools::rftReaderInterface( RimEclipseCase* eclipseCase )
|
||||
{
|
||||
auto eclResCase = dynamic_cast<RimEclipseResultCase*>( eclipseCase );
|
||||
|
||||
if ( eclResCase ) return eclResCase->rftReader();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -608,7 +620,7 @@ RiaRftPltCurveDefinition RimWellPlotTools::curveDefFromCurve( const RimWellLogCu
|
||||
|
||||
if ( rftCurve != nullptr )
|
||||
{
|
||||
RimEclipseResultCase* rftCase = dynamic_cast<RimEclipseResultCase*>( rftCurve->eclipseResultCase() );
|
||||
RimEclipseResultCase* rftCase = dynamic_cast<RimEclipseResultCase*>( rftCurve->eclipseCase() );
|
||||
RimSummaryCase* rftSummaryCase = rftCurve->summaryCase();
|
||||
RimSummaryCaseCollection* rftEnsemble = rftCurve->ensemble();
|
||||
RimObservedFmuRftData* rftFmuData = rftCurve->observedFmuRftData();
|
||||
@ -739,9 +751,10 @@ std::set<RiaRftPltCurveDefinition>
|
||||
|
||||
for ( const RifDataSourceForRftPlt& addr : selectedSourcesExpanded )
|
||||
{
|
||||
if ( addr.sourceType() == RifDataSourceForRftPlt::SourceType::RFT_SIM_WELL_DATA && addr.rftReader() )
|
||||
auto rftReader = rftReaderInterface( addr.eclCase() );
|
||||
if ( addr.sourceType() == RifDataSourceForRftPlt::SourceType::RFT_SIM_WELL_DATA && rftReader )
|
||||
{
|
||||
std::set<QDateTime> rftTimes = addr.rftReader()->availableTimeSteps( simWellName, interestingRFTResults );
|
||||
std::set<QDateTime> rftTimes = rftReader->availableTimeSteps( simWellName, interestingRFTResults );
|
||||
for ( const QDateTime& time : rftTimes )
|
||||
{
|
||||
if ( selectedTimeStepSet.count( time ) )
|
||||
@ -1149,21 +1162,26 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasObservedData = !observedTimeStepsWithSources.empty();
|
||||
}
|
||||
|
||||
if ( hasRftData )
|
||||
{
|
||||
for ( const auto& source : selSources )
|
||||
{
|
||||
if ( source.sourceType() == RifDataSourceForRftPlt::SourceType::RFT_SIM_WELL_DATA && source.rftReader() )
|
||||
auto rftReader = rftReaderInterface( source.eclCase() );
|
||||
if ( source.sourceType() == RifDataSourceForRftPlt::SourceType::RFT_SIM_WELL_DATA && rftReader )
|
||||
{
|
||||
std::set<QDateTime> rftTimes = source.rftReader()->availableTimeSteps( simWellName, interestingRFTResults );
|
||||
std::set<QDateTime> rftTimes = rftReader->availableTimeSteps( simWellName, interestingRFTResults );
|
||||
for ( const QDateTime& date : rftTimes )
|
||||
{
|
||||
rftTimeStepsWithSources[date].insert( source );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasRftData = !rftTimeStepsWithSources.empty();
|
||||
}
|
||||
|
||||
if ( hasGridData )
|
||||
@ -1181,6 +1199,8 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasGridData = !gridTimestepsWithSources.empty();
|
||||
}
|
||||
|
||||
if ( hasSummaryRftData )
|
||||
@ -1198,6 +1218,8 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasSummaryRftData = !summaryRftTimeStepsWithSources.empty();
|
||||
}
|
||||
|
||||
if ( hasEnsembleData )
|
||||
@ -1214,34 +1236,36 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasEnsembleData = !ensembleTimeStepsWithSources.empty();
|
||||
}
|
||||
|
||||
// If we have a time baseline add the equal or adjacent grid timesteps
|
||||
|
||||
std::map<QDateTime, std::set<RifDataSourceForRftPlt>> timestepsToShowWithSources;
|
||||
std::map<QDateTime, std::set<RifDataSourceForRftPlt>>* timeBaseline = nullptr;
|
||||
std::map<QDateTime, std::set<RifDataSourceForRftPlt>> timestepsToShowWithSources;
|
||||
std::map<QDateTime, std::set<RifDataSourceForRftPlt>> timeBaseline;
|
||||
|
||||
if ( hasObservedData )
|
||||
{
|
||||
timeBaseline = &observedTimeStepsWithSources;
|
||||
timeBaseline = observedTimeStepsWithSources;
|
||||
}
|
||||
else if ( hasRftData )
|
||||
{
|
||||
timeBaseline = &rftTimeStepsWithSources;
|
||||
timeBaseline = rftTimeStepsWithSources;
|
||||
}
|
||||
else if ( hasSummaryRftData )
|
||||
{
|
||||
timeBaseline = &summaryRftTimeStepsWithSources;
|
||||
timeBaseline = summaryRftTimeStepsWithSources;
|
||||
}
|
||||
else if ( hasEnsembleData )
|
||||
{
|
||||
timeBaseline = &ensembleTimeStepsWithSources;
|
||||
timeBaseline = ensembleTimeStepsWithSources;
|
||||
}
|
||||
|
||||
if ( timeBaseline )
|
||||
if ( !timeBaseline.empty() )
|
||||
{
|
||||
std::set<QDateTime> baseTimeSteps;
|
||||
for ( const auto& dateSourceSetPair : *timeBaseline )
|
||||
for ( const auto& dateSourceSetPair : timeBaseline )
|
||||
baseTimeSteps.insert( dateSourceSetPair.first );
|
||||
|
||||
std::set<QDateTime> rftTimeSteps;
|
||||
|
@ -43,6 +43,7 @@ class RimPressureDepthData;
|
||||
class RiuWellRftPlot;
|
||||
class RigEclipseCaseData;
|
||||
class RigEclipseResultAddress;
|
||||
class RifReaderRftInterface;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
@ -153,4 +154,6 @@ private:
|
||||
static std::set<QDateTime> findMatchingOrAdjacentTimeSteps( const std::set<QDateTime>& baseTimeLine,
|
||||
const std::set<QDateTime>& availableTimeSteps );
|
||||
static std::set<QDateTime> availableSimWellTimesteps( RimEclipseCase* eclCase, const QString& simWellName, bool addFirstReportTimeStep );
|
||||
|
||||
static RifReaderRftInterface* rftReaderInterface( RimEclipseCase* eclipseCase );
|
||||
};
|
||||
|
@ -295,20 +295,16 @@ class RigRftResultPointCalculator : public RigResultPointCalculator
|
||||
public:
|
||||
RigRftResultPointCalculator( const QString& wellPathName, RimEclipseResultCase* eclCase, QDateTime m_timeStep )
|
||||
{
|
||||
RifEclipseRftAddress gasRateAddress = RifEclipseRftAddress::createAddress( RimWellPlotTools::simWellName( wellPathName ),
|
||||
m_timeStep,
|
||||
RifEclipseRftAddress::RftWellLogChannelType::GRAT );
|
||||
RifEclipseRftAddress oilRateAddress = RifEclipseRftAddress::createAddress( RimWellPlotTools::simWellName( wellPathName ),
|
||||
m_timeStep,
|
||||
RifEclipseRftAddress::RftWellLogChannelType::ORAT );
|
||||
RifEclipseRftAddress watRateAddress = RifEclipseRftAddress::createAddress( RimWellPlotTools::simWellName( wellPathName ),
|
||||
m_timeStep,
|
||||
RifEclipseRftAddress::RftWellLogChannelType::WRAT );
|
||||
const auto wellNameForRft = RimWellPlotTools::simWellName( wellPathName );
|
||||
|
||||
std::vector<caf::VecIjk> rftIndices;
|
||||
eclCase->rftReader()->cellIndices( gasRateAddress, &rftIndices );
|
||||
if ( rftIndices.empty() ) eclCase->rftReader()->cellIndices( oilRateAddress, &rftIndices );
|
||||
if ( rftIndices.empty() ) eclCase->rftReader()->cellIndices( watRateAddress, &rftIndices );
|
||||
RifEclipseRftAddress gasRateAddress =
|
||||
RifEclipseRftAddress::createAddress( wellNameForRft, m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::GRAT );
|
||||
RifEclipseRftAddress oilRateAddress =
|
||||
RifEclipseRftAddress::createAddress( wellNameForRft, m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::ORAT );
|
||||
RifEclipseRftAddress watRateAddress =
|
||||
RifEclipseRftAddress::createAddress( wellNameForRft, m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::WRAT );
|
||||
|
||||
std::vector<caf::VecIjk> rftIndices = eclCase->rftReader()->cellIndices( wellNameForRft, m_timeStep );
|
||||
if ( rftIndices.empty() ) return;
|
||||
|
||||
std::vector<double> gasRates;
|
||||
|
@ -18,10 +18,14 @@
|
||||
|
||||
#include "RimWellRftEnsembleCurveSet.h"
|
||||
|
||||
#include "RifReaderEnsembleStatisticsRft.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEnsembleCurveSetColorManager.h"
|
||||
#include "RimRegularLegendConfig.h"
|
||||
#include "RimSummaryCase.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
#include "RimTools.h"
|
||||
#include "RimWellRftPlot.h"
|
||||
|
||||
#include "RiuQwtPlotWidget.h"
|
||||
@ -59,6 +63,9 @@ RimWellRftEnsembleCurveSet::RimWellRftEnsembleCurveSet()
|
||||
m_ensembleLegendConfig = new RimRegularLegendConfig();
|
||||
m_ensembleLegendConfig->setColorLegend(
|
||||
RimRegularLegendConfig::mapToColorLegend( RimEnsembleCurveSetColorManager::DEFAULT_ENSEMBLE_COLOR_RANGE ) );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_eclipseCase, "EclipseResultCase", "Eclipse Result Case" );
|
||||
m_eclipseCase.uiCapability()->setUiHidden( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -76,9 +83,14 @@ RimSummaryCaseCollection* RimWellRftEnsembleCurveSet::ensemble() const
|
||||
return m_ensemble;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellRftEnsembleCurveSet::setEnsemble( RimSummaryCaseCollection* ensemble )
|
||||
{
|
||||
m_ensemble = ensemble;
|
||||
|
||||
clearEnsembleStatistics();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -150,6 +162,22 @@ std::vector<QString> RimWellRftEnsembleCurveSet::parametersWithVariation() const
|
||||
return std::vector<QString>( paramSet.begin(), paramSet.end() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellRftEnsembleCurveSet::clearEnsembleStatistics()
|
||||
{
|
||||
m_statisticsEclipseRftReader = new RifReaderEnsembleStatisticsRft( m_ensemble(), m_eclipseCase() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellRftEnsembleCurveSet::initAfterRead()
|
||||
{
|
||||
clearEnsembleStatistics();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -177,6 +205,31 @@ RigEnsembleParameter::Type RimWellRftEnsembleCurveSet::currentEnsembleParameterT
|
||||
return RigEnsembleParameter::TYPE_NONE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellRftEnsembleCurveSet::setEclipseCase( RimEclipseCase* eclipseCase )
|
||||
{
|
||||
m_eclipseCase = eclipseCase;
|
||||
clearEnsembleStatistics();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEclipseCase* RimWellRftEnsembleCurveSet::eclipseCase() const
|
||||
{
|
||||
return m_eclipseCase();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifReaderRftInterface* RimWellRftEnsembleCurveSet::statisticsEclipseRftReader()
|
||||
{
|
||||
return m_statisticsEclipseRftReader.p();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -188,6 +241,10 @@ void RimWellRftEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* ch
|
||||
rftPlot->syncCurvesFromUiSelection();
|
||||
rftPlot->updateConnectedEditors();
|
||||
}
|
||||
else if ( changedField == &m_eclipseCase )
|
||||
{
|
||||
clearEnsembleStatistics();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -203,6 +260,12 @@ QList<caf::PdmOptionItemInfo> RimWellRftEnsembleCurveSet::calculateValueOptions(
|
||||
options.push_back( caf::PdmOptionItemInfo( param, param ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_eclipseCase )
|
||||
{
|
||||
RimTools::caseOptionItems( &options );
|
||||
|
||||
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -218,6 +281,9 @@ void RimWellRftEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::Pd
|
||||
{
|
||||
colorsGroup->add( &m_ensembleParameter );
|
||||
}
|
||||
|
||||
uiOrdering.add( &m_eclipseCase );
|
||||
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,9 @@
|
||||
|
||||
class RiuCvfOverlayItemWidget;
|
||||
class RimSummaryCaseCollection;
|
||||
class RimEclipseCase;
|
||||
class RifReaderEnsembleStatisticsRft;
|
||||
class RifReaderRftInterface;
|
||||
|
||||
class RimWellRftEnsembleCurveSet : public caf::PdmObject
|
||||
{
|
||||
@ -57,6 +60,11 @@ public:
|
||||
RimRegularLegendConfig* legendConfig();
|
||||
RigEnsembleParameter::Type currentEnsembleParameterType() const;
|
||||
|
||||
void setEclipseCase( RimEclipseCase* eclipseCase );
|
||||
RimEclipseCase* eclipseCase() const;
|
||||
|
||||
RifReaderRftInterface* statisticsEclipseRftReader();
|
||||
|
||||
protected:
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
@ -69,11 +77,18 @@ protected:
|
||||
private:
|
||||
QString ensembleName() const;
|
||||
std::vector<QString> parametersWithVariation() const;
|
||||
void clearEnsembleStatistics();
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimEclipseCase*> m_eclipseCase;
|
||||
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble;
|
||||
caf::PdmProxyValueField<QString> m_ensembleName;
|
||||
caf::PdmField<ColorModeEnum> m_ensembleColorMode;
|
||||
caf::PdmField<QString> m_ensembleParameter;
|
||||
caf::PdmChildField<RimRegularLegendConfig*> m_ensembleLegendConfig;
|
||||
|
||||
cvf::ref<RifReaderEnsembleStatisticsRft> m_statisticsEclipseRftReader;
|
||||
|
||||
protected:
|
||||
void initAfterRead() override;
|
||||
};
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include "RimWellPathCollection.h"
|
||||
#include "RimWellPlotTools.h"
|
||||
#include "RimWellPltPlot.h"
|
||||
#include "RimWellRftEnsembleCurveSet.h"
|
||||
|
||||
#include "RiuAbstractLegendFrame.h"
|
||||
#include "RiuAbstractOverlayContentFrame.h"
|
||||
@ -123,6 +124,10 @@ RimWellRftPlot::RimWellRftPlot()
|
||||
m_selectedTimeSteps.uiCapability()->setAutoAddingOptionFromValue( false );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_ensembleCurveSets, "EnsembleCurveSets", "Ensemble Curve Sets" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_ensembleCurveSetEclipseCase,
|
||||
"EclipseResultCase",
|
||||
"Grid Model For MD",
|
||||
"Grid model used to compute measured depth using well path geometry" );
|
||||
|
||||
// TODO: may want to support TRUE_VERTICAL_DEPTH_RKB in the future
|
||||
// It was developed for regular well log plots and requires some more work for RFT plots.
|
||||
@ -496,7 +501,7 @@ void RimWellRftPlot::updateCurvesInPlot( const std::set<RiaRftPltCurveDefinition
|
||||
plotTrack->addCurve( curve );
|
||||
|
||||
auto rftCase = curveDefToAdd.address().eclCase();
|
||||
curve->setEclipseResultCase( dynamic_cast<RimEclipseResultCase*>( rftCase ) );
|
||||
curve->setEclipseCase( rftCase );
|
||||
|
||||
RifEclipseRftAddress address = RifEclipseRftAddress::createAddress( simWellName,
|
||||
curveDefToAdd.timeStep(),
|
||||
@ -534,8 +539,8 @@ void RimWellRftPlot::updateCurvesInPlot( const std::set<RiaRftPltCurveDefinition
|
||||
{
|
||||
auto curve = new RimWellLogRftCurve();
|
||||
plotTrack->addCurve( curve );
|
||||
auto rftCase = curveDefToAdd.address().summaryCase();
|
||||
curve->setSummaryCase( rftCase );
|
||||
auto summaryCase = curveDefToAdd.address().summaryCase();
|
||||
curve->setSummaryCase( summaryCase );
|
||||
curve->setEnsemble( curveDefToAdd.address().ensemble() );
|
||||
curve->setObservedFmuRftData( findObservedFmuData( m_wellPathNameOrSimWellName, curveDefToAdd.timeStep() ) );
|
||||
RifEclipseRftAddress address = RifEclipseRftAddress::createAddress( m_wellPathNameOrSimWellName,
|
||||
@ -545,7 +550,13 @@ void RimWellRftPlot::updateCurvesInPlot( const std::set<RiaRftPltCurveDefinition
|
||||
|
||||
// A summary case address can optionally contain an Eclipse case used to compute the TVD/MD for a well path
|
||||
// https://github.com/OPM/ResInsight/issues/10501
|
||||
curve->setEclipseResultCase( dynamic_cast<RimEclipseResultCase*>( curveDefToAdd.address().eclCase() ) );
|
||||
auto eclipeCase = curveDefToAdd.address().eclCase();
|
||||
if ( curveDefToAdd.address().ensemble() )
|
||||
{
|
||||
auto curveSet = findEnsembleCurveSet( curveDefToAdd.address().ensemble() );
|
||||
if ( curveSet ) eclipeCase = curveSet->eclipseCase();
|
||||
}
|
||||
curve->setEclipseCase( eclipeCase );
|
||||
|
||||
double zValue = 1.0;
|
||||
if ( !curveDefToAdd.address().ensemble() )
|
||||
@ -565,9 +576,11 @@ void RimWellRftPlot::updateCurvesInPlot( const std::set<RiaRftPltCurveDefinition
|
||||
}
|
||||
else if ( m_showStatisticsCurves && curveDefToAdd.address().sourceType() == RifDataSourceForRftPlt::SourceType::ENSEMBLE_RFT )
|
||||
{
|
||||
RimSummaryCaseCollection* ensemble = curveDefToAdd.address().ensemble();
|
||||
RimSummaryCaseCollection* ensemble = curveDefToAdd.address().ensemble();
|
||||
auto curveSet = findEnsembleCurveSet( ensemble );
|
||||
|
||||
std::set<RifEclipseRftAddress> rftAddresses =
|
||||
ensemble->rftStatisticsReader()->eclipseRftAddresses( m_wellPathNameOrSimWellName, curveDefToAdd.timeStep() );
|
||||
curveSet->statisticsEclipseRftReader()->eclipseRftAddresses( m_wellPathNameOrSimWellName, curveDefToAdd.timeStep() );
|
||||
for ( const auto& rftAddress : rftAddresses )
|
||||
{
|
||||
if ( rftAddress.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P50 )
|
||||
@ -584,6 +597,7 @@ void RimWellRftPlot::updateCurvesInPlot( const std::set<RiaRftPltCurveDefinition
|
||||
auto curve = new RimWellLogRftCurve();
|
||||
plotTrack->addCurve( curve );
|
||||
curve->setEnsemble( ensemble );
|
||||
curve->setEclipseCase( curveSet->eclipseCase() );
|
||||
curve->setRftAddress( rftAddress );
|
||||
curve->setObservedFmuRftData( findObservedFmuData( m_wellPathNameOrSimWellName, curveDefToAdd.timeStep() ) );
|
||||
curve->setZOrder( RiuQwtPlotCurveDefines::zDepthForIndex( RiuQwtPlotCurveDefines::ZIndex::Z_ENSEMBLE_STAT_CURVE ) );
|
||||
@ -795,6 +809,13 @@ QList<caf::PdmOptionItemInfo> RimWellRftPlot::calculateValueOptions( const caf::
|
||||
|
||||
options = RiaSimWellBranchTools::valueOptionsForBranchIndexField( simulationWellBranches );
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_ensembleCurveSetEclipseCase )
|
||||
{
|
||||
RimTools::caseOptionItems( &options );
|
||||
|
||||
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -968,6 +989,17 @@ void RimWellRftPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
updateFormationsOnPlot();
|
||||
syncCurvesFromUiSelection();
|
||||
}
|
||||
else if ( changedField == &m_ensembleCurveSetEclipseCase )
|
||||
{
|
||||
for ( RimWellRftEnsembleCurveSet* curveSet : m_ensembleCurveSets() )
|
||||
{
|
||||
curveSet->setEclipseCase( m_ensembleCurveSetEclipseCase );
|
||||
}
|
||||
|
||||
createEnsembleCurveSets();
|
||||
updateFormationsOnPlot();
|
||||
syncCurvesFromUiSelection();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -1016,6 +1048,11 @@ void RimWellRftPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering&
|
||||
caf::PdmUiGroup* sourcesGroup = uiOrdering.addNewGroupWithKeyword( "Sources", "Sources" );
|
||||
sourcesGroup->add( &m_selectedSources );
|
||||
|
||||
if ( !m_ensembleCurveSets.empty() )
|
||||
{
|
||||
uiOrdering.add( &m_ensembleCurveSetEclipseCase );
|
||||
}
|
||||
|
||||
caf::PdmUiGroup* timeStepsGroup = uiOrdering.addNewGroupWithKeyword( "Time Steps", "TimeSteps" );
|
||||
timeStepsGroup->add( &m_selectedTimeSteps );
|
||||
|
||||
|
@ -92,6 +92,8 @@ public:
|
||||
bool showErrorBarsForObservedData() const;
|
||||
void onLegendDefinitionChanged();
|
||||
|
||||
RimWellRftEnsembleCurveSet* findEnsembleCurveSet( RimSummaryCaseCollection* ensemble ) const;
|
||||
|
||||
protected:
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName ) override;
|
||||
@ -138,7 +140,6 @@ private:
|
||||
|
||||
std::vector<RimSummaryCaseCollection*> selectedEnsembles() const;
|
||||
void createEnsembleCurveSets();
|
||||
RimWellRftEnsembleCurveSet* findEnsembleCurveSet( RimSummaryCaseCollection* ensemble ) const;
|
||||
|
||||
private:
|
||||
friend class RimWellRftEnsembleCurveSet;
|
||||
@ -153,7 +154,9 @@ private:
|
||||
caf::PdmField<std::vector<RifDataSourceForRftPlt>> m_selectedSources;
|
||||
caf::PdmField<std::vector<QDateTime>> m_selectedTimeSteps;
|
||||
|
||||
caf::PdmChildArrayField<RimWellRftEnsembleCurveSet*> m_ensembleCurveSets;
|
||||
caf::PdmChildArrayField<RimWellRftEnsembleCurveSet*> m_ensembleCurveSets;
|
||||
caf::PdmPtrField<RimEclipseCase*> m_ensembleCurveSetEclipseCase;
|
||||
|
||||
std::map<RimWellRftEnsembleCurveSet*, QPointer<RiuDraggableOverlayFrame>> m_ensembleLegendFrames;
|
||||
|
||||
std::map<RifDataSourceForRftPlt, cvf::Color3f> m_dataSourceColors;
|
||||
|
@ -28,6 +28,9 @@
|
||||
|
||||
#include "RicfCommandObject.h"
|
||||
|
||||
#include "RifReaderRftInterface.h"
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
#include "RimAnalysisPlotDataEntry.h"
|
||||
#include "RimDerivedEnsembleCaseCollection.h"
|
||||
#include "RimEnsembleCurveSet.h"
|
||||
@ -36,10 +39,6 @@
|
||||
#include "RimSummaryCalculationCollection.h"
|
||||
#include "RimSummaryCase.h"
|
||||
|
||||
#include "RifReaderEclipseRft.h"
|
||||
#include "RifReaderEnsembleStatisticsRft.h"
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
@ -135,8 +134,6 @@ RimSummaryCaseCollection::RimSummaryCaseCollection()
|
||||
m_dataVectorFolders->uiCapability()->setUiTreeHidden( true );
|
||||
m_dataVectorFolders.xmlCapability()->disableIO();
|
||||
|
||||
m_statisticsEclipseRftReader = new RifReaderEnsembleStatisticsRft( this );
|
||||
|
||||
m_commonAddressCount = 0;
|
||||
}
|
||||
|
||||
@ -406,14 +403,6 @@ std::set<QDateTime> RimSummaryCaseCollection::rftTimeStepsForWell( const QString
|
||||
return allTimeSteps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifReaderRftInterface* RimSummaryCaseCollection::rftStatisticsReader()
|
||||
{
|
||||
return m_statisticsEclipseRftReader.p();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -39,8 +39,6 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class RifReaderRftInterface;
|
||||
class RifReaderEnsembleStatisticsRft;
|
||||
class RimSummaryCase;
|
||||
class RimSummaryAddressCollection;
|
||||
class RiaSummaryAddressAnalyzer;
|
||||
@ -74,12 +72,11 @@ public:
|
||||
virtual std::set<RifEclipseSummaryAddress> ensembleSummaryAddresses() const;
|
||||
virtual std::set<time_t> ensembleTimeSteps() const;
|
||||
|
||||
std::set<QString> wellsWithRftData() const;
|
||||
std::set<QDateTime> rftTimeStepsForWell( const QString& wellName ) const;
|
||||
RifReaderRftInterface* rftStatisticsReader();
|
||||
void setEnsembleId( int ensembleId );
|
||||
int ensembleId() const;
|
||||
bool hasEnsembleParameters() const;
|
||||
std::set<QString> wellsWithRftData() const;
|
||||
std::set<QDateTime> rftTimeStepsForWell( const QString& wellName ) const;
|
||||
void setEnsembleId( int ensembleId );
|
||||
int ensembleId() const;
|
||||
bool hasEnsembleParameters() const;
|
||||
|
||||
std::vector<RigEnsembleParameter> variationSortedEnsembleParameters( bool excludeNoVariation = false ) const;
|
||||
std::vector<std::pair<RigEnsembleParameter, double>> correlationSortedEnsembleParameters( const RifEclipseSummaryAddress& address ) const;
|
||||
@ -147,8 +144,7 @@ private:
|
||||
caf::PdmField<bool> m_isEnsemble;
|
||||
caf::PdmChildField<RimSummaryAddressCollection*> m_dataVectorFolders;
|
||||
|
||||
cvf::ref<RifReaderEnsembleStatisticsRft> m_statisticsEclipseRftReader;
|
||||
caf::PdmField<int> m_ensembleId;
|
||||
caf::PdmField<int> m_ensembleId;
|
||||
|
||||
size_t m_commonAddressCount; // if different address count among cases, set to 0
|
||||
|
||||
|
@ -382,7 +382,7 @@ void RimWellLogCurveCommonDataSource::analyseCurvesAndTracks( const std::vector<
|
||||
else if ( rftCurve )
|
||||
{
|
||||
if ( rftCurve->summaryCase() ) m_uniqueSummaryCases.insert( rftCurve->summaryCase() );
|
||||
if ( rftCurve->eclipseResultCase() ) m_uniqueCases.insert( rftCurve->eclipseResultCase() );
|
||||
if ( rftCurve->eclipseCase() ) m_uniqueCases.insert( rftCurve->eclipseCase() );
|
||||
m_uniqueWellNames.insert( rftCurve->wellName() );
|
||||
|
||||
auto adr = rftCurve->rftAddress();
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "RiaColorTools.h"
|
||||
#include "RiaDefines.h"
|
||||
#include "RiaEclipseUnitTools.h"
|
||||
#include "RiaExtractionTools.h"
|
||||
#include "RiaQDateTimeTools.h"
|
||||
#include "RiaResultNames.h"
|
||||
#include "RiaRftDefines.h"
|
||||
@ -44,7 +45,6 @@
|
||||
#include "RimDepthTrackPlot.h"
|
||||
#include "RimEclipseResultCase.h"
|
||||
#include "RimFileSummaryCase.h"
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimObservedFmuRftData.h"
|
||||
#include "RimPressureDepthData.h"
|
||||
#include "RimProject.h"
|
||||
@ -53,7 +53,6 @@
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
#include "RimTools.h"
|
||||
#include "RimWellLogPlot.h"
|
||||
#include "RimWellLogPlotCollection.h"
|
||||
#include "RimWellLogTrack.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPlotTools.h"
|
||||
@ -152,8 +151,8 @@ RimWellLogRftCurve::RimWellLogRftCurve()
|
||||
{
|
||||
CAF_PDM_InitObject( "Well Log RFT Curve", RimWellLogCurve::wellLogCurveIconName() );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_eclipseResultCase, "CurveEclipseResultCase", "Eclipse Result Case" );
|
||||
m_eclipseResultCase.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
CAF_PDM_InitFieldNoDefault( &m_eclipseCase, "CurveEclipseResultCase", "Eclipse Result Case" );
|
||||
m_eclipseCase.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_summaryCase, "CurveSummaryCase", "Summary Case" );
|
||||
m_summaryCase.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
@ -265,17 +264,17 @@ void RimWellLogRftCurve::setSegmentBranchType( RiaDefines::RftBranchType branchT
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogRftCurve::setEclipseResultCase( RimEclipseResultCase* eclipseResultCase )
|
||||
void RimWellLogRftCurve::setEclipseCase( RimEclipseCase* eclipseCase )
|
||||
{
|
||||
m_eclipseResultCase = eclipseResultCase;
|
||||
m_eclipseCase = eclipseCase;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEclipseResultCase* RimWellLogRftCurve::eclipseResultCase() const
|
||||
RimEclipseCase* RimWellLogRftCurve::eclipseCase() const
|
||||
{
|
||||
return m_eclipseResultCase;
|
||||
return m_eclipseCase;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -527,9 +526,9 @@ std::map<QString, QString> RimWellLogRftCurve::createCurveNameKeyValueMap() cons
|
||||
variableValueMap[RiaDefines::namingVariableResultType()] = "RFT";
|
||||
|
||||
QString caseText;
|
||||
if ( m_eclipseResultCase )
|
||||
if ( m_eclipseCase )
|
||||
{
|
||||
caseText = m_eclipseResultCase->caseUserDescription();
|
||||
caseText = m_eclipseCase->caseUserDescription();
|
||||
}
|
||||
else if ( m_summaryCase && m_ensemble ) // Summary RFT curves have both ensemble and summary set
|
||||
{
|
||||
@ -649,7 +648,7 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
|
||||
RimPlotCurve::updateCurvePresentation( updateParentPlot );
|
||||
|
||||
DerivedMDSource derivedMDSource = DerivedMDSource::NO_SOURCE;
|
||||
QString axisPrefixText;
|
||||
|
||||
if ( m_autoCheckStateBasedOnCurveData() || isChecked() )
|
||||
{
|
||||
@ -659,7 +658,7 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
bool showErrorBarsInObservedData = rftPlot ? rftPlot->showErrorBarsForObservedData() : false;
|
||||
m_showErrorBars = showErrorBarsInObservedData;
|
||||
|
||||
std::vector<double> measuredDepthVector = measuredDepthValues();
|
||||
std::vector<double> measuredDepthVector = measuredDepthValues( axisPrefixText );
|
||||
std::vector<double> tvDepthVector = tvDepthValues();
|
||||
std::vector<double> values = xValues();
|
||||
std::vector<double> errors = errorValues();
|
||||
@ -682,13 +681,13 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
}
|
||||
|
||||
RiaDefines::EclipseUnitSystem unitSystem = RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
||||
if ( m_eclipseResultCase )
|
||||
if ( m_eclipseCase )
|
||||
{
|
||||
// TODO: If no grid data, but only RFT data is loaded, we do not have any way to
|
||||
// detect unit
|
||||
if ( m_eclipseResultCase->eclipseCaseData() )
|
||||
if ( m_eclipseCase->eclipseCaseData() )
|
||||
{
|
||||
unitSystem = m_eclipseResultCase->eclipseCaseData()->unitsType();
|
||||
unitSystem = m_eclipseCase->eclipseCaseData()->unitsType();
|
||||
}
|
||||
}
|
||||
else if ( m_summaryCase )
|
||||
@ -718,19 +717,14 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
|
||||
if ( tvDepthVector.size() != measuredDepthVector.size() )
|
||||
{
|
||||
if ( deriveMeasuredDepthValuesFromWellPath( tvDepthVector, measuredDepthVector ) )
|
||||
if ( deriveMeasuredDepthFromObservedData( tvDepthVector, measuredDepthVector ) )
|
||||
{
|
||||
derivedMDSource = DerivedMDSource::WELL_PATH;
|
||||
}
|
||||
else if ( deriveMeasuredDepthFromObservedData( tvDepthVector, measuredDepthVector ) )
|
||||
{
|
||||
derivedMDSource = DerivedMDSource::OBSERVED_DATA;
|
||||
axisPrefixText = "OBS/";
|
||||
}
|
||||
}
|
||||
|
||||
if ( tvDepthVector.size() != measuredDepthVector.size() )
|
||||
{
|
||||
derivedMDSource = DerivedMDSource::NO_SOURCE;
|
||||
measuredDepthVector = tvDepthVector;
|
||||
}
|
||||
|
||||
@ -783,23 +777,7 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
RiuQwtPlotWidget* viewer = wellLogTrack->viewer();
|
||||
if ( viewer )
|
||||
{
|
||||
QString text;
|
||||
|
||||
if ( derivedMDSource != DerivedMDSource::NO_SOURCE )
|
||||
{
|
||||
if ( derivedMDSource == DerivedMDSource::WELL_PATH )
|
||||
{
|
||||
text = "WELL/" + wellLogPlot->depthAxisTitle();
|
||||
}
|
||||
else
|
||||
{
|
||||
text = "OBS/" + wellLogPlot->depthAxisTitle();
|
||||
}
|
||||
}
|
||||
else // Standard depth title set from plot
|
||||
{
|
||||
text = wellLogPlot->depthAxisTitle();
|
||||
}
|
||||
QString text = axisPrefixText + wellLogPlot->depthAxisTitle();
|
||||
|
||||
viewer->setAxisTitleText( wellLogPlot->depthAxis(), text );
|
||||
}
|
||||
@ -852,7 +830,7 @@ void RimWellLogRftCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
|
||||
RimPlotCurve::updateFieldUiState();
|
||||
|
||||
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Curve Data" );
|
||||
curveDataGroup->add( &m_eclipseResultCase );
|
||||
curveDataGroup->add( &m_eclipseCase );
|
||||
curveDataGroup->add( &m_summaryCase );
|
||||
curveDataGroup->add( &m_wellName );
|
||||
curveDataGroup->add( &m_timeStep );
|
||||
@ -894,7 +872,7 @@ QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions( const c
|
||||
if ( !options.empty() ) return options;
|
||||
|
||||
RifReaderRftInterface* reader = rftReader();
|
||||
if ( fieldNeedingOptions == &m_eclipseResultCase )
|
||||
if ( fieldNeedingOptions == &m_eclipseCase )
|
||||
{
|
||||
RimTools::caseOptionItems( &options );
|
||||
|
||||
@ -954,12 +932,10 @@ QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions( const c
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogRftCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
||||
{
|
||||
m_idxInWellPathToIdxInRftFile.clear();
|
||||
|
||||
bool loadData = false;
|
||||
|
||||
RimWellLogCurve::fieldChangedByUi( changedField, oldValue, newValue );
|
||||
if ( changedField == &m_eclipseResultCase )
|
||||
if ( changedField == &m_eclipseCase )
|
||||
{
|
||||
m_timeStep = QDateTime();
|
||||
m_wellName = "";
|
||||
@ -1027,11 +1003,6 @@ std::vector<QString> RimWellLogRftCurve::perPointLabels() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifReaderRftInterface* RimWellLogRftCurve::rftReader() const
|
||||
{
|
||||
if ( m_eclipseResultCase() )
|
||||
{
|
||||
return m_eclipseResultCase()->rftReader();
|
||||
}
|
||||
|
||||
if ( m_summaryCase() ) // Summary RFT curves have both summary and ensemble set. Prioritize summary for reader.
|
||||
{
|
||||
return m_summaryCase()->rftReader();
|
||||
@ -1039,7 +1010,14 @@ RifReaderRftInterface* RimWellLogRftCurve::rftReader() const
|
||||
|
||||
if ( m_ensemble() )
|
||||
{
|
||||
return m_ensemble()->rftStatisticsReader();
|
||||
auto wellLogPlot = firstAncestorOrThisOfType<RimWellRftPlot>();
|
||||
auto curveSet = wellLogPlot->findEnsembleCurveSet( m_ensemble );
|
||||
if ( curveSet )
|
||||
{
|
||||
return curveSet->statisticsEclipseRftReader();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( m_observedFmuRftData() )
|
||||
@ -1052,6 +1030,11 @@ RifReaderRftInterface* RimWellLogRftCurve::rftReader() const
|
||||
return m_pressureDepthData()->rftReader();
|
||||
}
|
||||
|
||||
if ( auto resultCase = dynamic_cast<RimEclipseResultCase*>( m_eclipseCase() ) )
|
||||
{
|
||||
return resultCase->rftReader();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1060,121 +1043,18 @@ RifReaderRftInterface* RimWellLogRftCurve::rftReader() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigEclipseWellLogExtractor* RimWellLogRftCurve::extractor()
|
||||
{
|
||||
RifReaderRftInterface* reader = rftReader();
|
||||
if ( !reader ) return nullptr;
|
||||
|
||||
auto mainPlotCollection = firstAncestorOrThisOfTypeAsserted<RimMainPlotCollection>();
|
||||
|
||||
RimWellLogPlotCollection* wellLogCollection = mainPlotCollection->wellLogPlotCollection();
|
||||
if ( !wellLogCollection ) return nullptr;
|
||||
|
||||
RigEclipseWellLogExtractor* eclExtractor = nullptr;
|
||||
|
||||
RimProject* proj = RimProject::current();
|
||||
RimWellPath* wellPath = proj->wellPathFromSimWellName( m_wellName() );
|
||||
eclExtractor = wellLogCollection->findOrCreateExtractor( wellPath, m_eclipseResultCase );
|
||||
|
||||
if ( !eclExtractor && m_eclipseResultCase )
|
||||
// The well path extractor has the best geometrical representation, so use this if found
|
||||
if ( auto wellPathExtractor = RiaExtractionTools::findOrCreateWellLogExtractor( wellPath, m_eclipseCase ) )
|
||||
{
|
||||
QString simWellName = RimWellPlotTools::simWellName( m_wellName );
|
||||
std::vector<const RigWellPath*> wellPaths = RiaSimWellBranchTools::simulationWellBranches( simWellName, m_branchDetection );
|
||||
if ( wellPaths.empty() ) return nullptr;
|
||||
|
||||
m_branchIndex = RiaSimWellBranchTools::clampBranchIndex( simWellName, m_branchIndex, m_branchDetection );
|
||||
|
||||
auto wellPathBranch = wellPaths[m_branchIndex];
|
||||
|
||||
eclExtractor = wellLogCollection->findOrCreateSimWellExtractor( simWellName,
|
||||
QString( "Find or create sim well extractor" ),
|
||||
wellPathBranch,
|
||||
m_eclipseResultCase->eclipseCaseData() );
|
||||
return wellPathExtractor;
|
||||
}
|
||||
|
||||
return eclExtractor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellLogRftCurve::createWellPathIdxToRftFileIdxMapping()
|
||||
{
|
||||
if ( !m_idxInWellPathToIdxInRftFile.empty() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
RigEclipseWellLogExtractor* eclExtractor = extractor();
|
||||
|
||||
if ( !eclExtractor ) return false;
|
||||
|
||||
std::vector<WellPathCellIntersectionInfo> intersections = eclExtractor->cellIntersectionInfosAlongWellPath();
|
||||
if ( intersections.empty() ) return false;
|
||||
|
||||
std::map<size_t, size_t> globCellIndicesToIndexInWell;
|
||||
|
||||
for ( size_t idx = 0; idx < intersections.size(); idx++ )
|
||||
{
|
||||
globCellIndicesToIndexInWell[intersections[idx].globCellIndex] = idx;
|
||||
}
|
||||
|
||||
RifEclipseRftAddress depthAddress =
|
||||
RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::TVD );
|
||||
std::vector<caf::VecIjk> rftIndices;
|
||||
if ( !rftReader() ) return false;
|
||||
|
||||
rftReader()->cellIndices( depthAddress, &rftIndices );
|
||||
|
||||
const RigMainGrid* mainGrid = eclExtractor->caseData()->mainGrid();
|
||||
|
||||
for ( size_t idx = 0; idx < rftIndices.size(); idx++ )
|
||||
{
|
||||
caf::VecIjk ijkIndex = rftIndices[idx];
|
||||
size_t globalCellIndex = mainGrid->cellIndexFromIJK( ijkIndex.i(), ijkIndex.j(), ijkIndex.k() );
|
||||
|
||||
if ( globCellIndicesToIndexInWell.find( globalCellIndex ) != globCellIndicesToIndexInWell.end() )
|
||||
{
|
||||
m_idxInWellPathToIdxInRftFile[globCellIndicesToIndexInWell[globalCellIndex]] = idx;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RimWellLogRftCurve::rftFileIndex( size_t wellPathIndex )
|
||||
{
|
||||
if ( m_idxInWellPathToIdxInRftFile.empty() )
|
||||
{
|
||||
createWellPathIdxToRftFileIdxMapping();
|
||||
}
|
||||
|
||||
if ( m_idxInWellPathToIdxInRftFile.find( wellPathIndex ) == m_idxInWellPathToIdxInRftFile.end() )
|
||||
{
|
||||
return cvf::UNDEFINED_SIZE_T;
|
||||
}
|
||||
|
||||
return m_idxInWellPathToIdxInRftFile[wellPathIndex];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<size_t> RimWellLogRftCurve::sortedIndicesInRftFile()
|
||||
{
|
||||
if ( m_idxInWellPathToIdxInRftFile.empty() )
|
||||
{
|
||||
createWellPathIdxToRftFileIdxMapping();
|
||||
}
|
||||
|
||||
std::vector<size_t> indices;
|
||||
for ( auto& it : m_idxInWellPathToIdxInRftFile )
|
||||
{
|
||||
indices.push_back( it.second );
|
||||
}
|
||||
|
||||
return indices;
|
||||
// Use sim well extractor as fallback
|
||||
QString simWellName = RimWellPlotTools::simWellName( m_wellName );
|
||||
return RiaExtractionTools::findOrCreateSimWellExtractor( m_eclipseCase(), simWellName, m_branchDetection(), m_branchIndex() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -1202,23 +1082,6 @@ std::vector<double> RimWellLogRftCurve::xValues()
|
||||
auto address = RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, m_wellLogChannelName() );
|
||||
|
||||
reader->values( address, &values );
|
||||
|
||||
bool wellPathExists = createWellPathIdxToRftFileIdxMapping();
|
||||
|
||||
if ( wellPathExists )
|
||||
{
|
||||
std::vector<double> valuesSorted;
|
||||
|
||||
for ( size_t idx : sortedIndicesInRftFile() )
|
||||
{
|
||||
if ( idx < values.size() )
|
||||
{
|
||||
valuesSorted.push_back( ( values.at( idx ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
std::swap( valuesSorted, values );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_scaleFactor() != 1.0 )
|
||||
@ -1260,51 +1123,35 @@ std::vector<double> RimWellLogRftCurve::tvDepthValues()
|
||||
|
||||
if ( !reader ) return values;
|
||||
|
||||
RifEclipseRftAddress depthAddress =
|
||||
RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::TVD );
|
||||
|
||||
if ( m_rftDataType() == RftDataType::RFT_SEGMENT_DATA )
|
||||
{
|
||||
auto depthAddress = RifEclipseRftAddress::createBranchSegmentAddress( m_wellName(),
|
||||
m_timeStep,
|
||||
RiaDefines::segmentTvdDepthResultName(),
|
||||
segmentBranchIndex(),
|
||||
m_segmentBranchType() );
|
||||
|
||||
reader->values( depthAddress, &values );
|
||||
return values;
|
||||
depthAddress = RifEclipseRftAddress::createBranchSegmentAddress( m_wellName(),
|
||||
m_timeStep,
|
||||
RiaDefines::segmentTvdDepthResultName(),
|
||||
segmentBranchIndex(),
|
||||
m_segmentBranchType() );
|
||||
}
|
||||
|
||||
auto depthAddress = RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::TVD );
|
||||
reader->values( depthAddress, &values );
|
||||
|
||||
bool wellPathExists = createWellPathIdxToRftFileIdxMapping();
|
||||
|
||||
if ( wellPathExists )
|
||||
{
|
||||
std::vector<double> valuesSorted;
|
||||
|
||||
for ( size_t idx : sortedIndicesInRftFile() )
|
||||
{
|
||||
if ( idx < values.size() )
|
||||
{
|
||||
valuesSorted.push_back( ( values.at( idx ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
return valuesSorted;
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimWellLogRftCurve::measuredDepthValues()
|
||||
std::vector<double> RimWellLogRftCurve::measuredDepthValues( QString& prefixText )
|
||||
{
|
||||
if ( m_rftDataType() == RftDataType::RFT_SEGMENT_DATA )
|
||||
{
|
||||
RifReaderRftInterface* reader = rftReader();
|
||||
if ( reader )
|
||||
{
|
||||
prefixText = "SEGMENT/";
|
||||
|
||||
return RimRftTools::seglenstValues( reader, m_wellName(), m_timeStep, segmentBranchIndex(), m_segmentBranchType() );
|
||||
}
|
||||
return {};
|
||||
@ -1320,6 +1167,8 @@ std::vector<double> RimWellLogRftCurve::measuredDepthValues()
|
||||
RifEclipseRftAddress depthAddress =
|
||||
RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::MD );
|
||||
reader->values( depthAddress, &values );
|
||||
|
||||
prefixText = "OBS/";
|
||||
return values;
|
||||
}
|
||||
|
||||
@ -1329,59 +1178,24 @@ std::vector<double> RimWellLogRftCurve::measuredDepthValues()
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<double> measuredDepthForCells;
|
||||
|
||||
RigEclipseWellLogExtractor* eclExtractor = extractor();
|
||||
if ( !eclExtractor ) return {};
|
||||
|
||||
if ( !eclExtractor ) return measuredDepthForCells;
|
||||
|
||||
std::vector<double> measuredDepthForIntersections = eclExtractor->cellIntersectionMDs();
|
||||
|
||||
if ( measuredDepthForIntersections.empty() )
|
||||
if ( auto reader = rftReader() )
|
||||
{
|
||||
return measuredDepthForCells;
|
||||
}
|
||||
prefixText = "WELL/";
|
||||
|
||||
std::vector<size_t> globCellIndices = eclExtractor->intersectedCellsGlobIdx();
|
||||
RifEclipseRftAddress depthAddress =
|
||||
RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::MD );
|
||||
|
||||
for ( size_t i = 0; i < globCellIndices.size() - 1; i = i + 2 )
|
||||
{
|
||||
double sum = measuredDepthForIntersections[i] + measuredDepthForIntersections[i + 1];
|
||||
std::vector<double> values;
|
||||
reader->values( depthAddress, &values );
|
||||
if ( !values.empty() ) return values;
|
||||
|
||||
measuredDepthForCells.push_back( sum / 2.0 );
|
||||
}
|
||||
return rftReader()->computeMeasuredDepth( m_wellName(), m_timeStep(), eclExtractor );
|
||||
};
|
||||
|
||||
std::vector<double> measuredDepthForCellsWhichHasRftData;
|
||||
|
||||
for ( size_t i = 0; i < measuredDepthForCells.size(); i++ )
|
||||
{
|
||||
if ( rftFileIndex( i ) != cvf::UNDEFINED_SIZE_T )
|
||||
{
|
||||
measuredDepthForCellsWhichHasRftData.push_back( measuredDepthForCells[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return measuredDepthForCellsWhichHasRftData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellLogRftCurve::deriveMeasuredDepthValuesFromWellPath( const std::vector<double>& tvDepthValues, std::vector<double>& derivedMDValues )
|
||||
{
|
||||
RimProject* proj = RimProject::current();
|
||||
RimWellPath* wellPath = proj->wellPathByName( m_wellName );
|
||||
|
||||
if ( wellPath && wellPath->wellPathGeometry() )
|
||||
{
|
||||
const std::vector<double>& mdValuesOfWellPath = wellPath->wellPathGeometry()->measuredDepths();
|
||||
const std::vector<double>& tvdValuesOfWellPath = wellPath->wellPathGeometry()->trueVerticalDepths();
|
||||
|
||||
derivedMDValues = RigWellPathGeometryTools::interpolateMdFromTvd( mdValuesOfWellPath, tvdValuesOfWellPath, tvDepthValues );
|
||||
CVF_ASSERT( derivedMDValues.size() == tvDepthValues.size() );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
class RifReaderRftInterface;
|
||||
class RigEclipseWellLogExtractor;
|
||||
class RimEclipseResultCase;
|
||||
class RimEclipseCase;
|
||||
class RimObservedFmuRftData;
|
||||
class RimSummaryCase;
|
||||
class RimSummaryCaseCollection;
|
||||
@ -55,15 +55,6 @@ public:
|
||||
RFT_SEGMENT_DATA
|
||||
};
|
||||
|
||||
private:
|
||||
enum class DerivedMDSource
|
||||
{
|
||||
NO_SOURCE,
|
||||
WELL_PATH,
|
||||
SEGMENT,
|
||||
OBSERVED_DATA
|
||||
};
|
||||
|
||||
public:
|
||||
RimWellLogRftCurve();
|
||||
~RimWellLogRftCurve() override;
|
||||
@ -80,8 +71,8 @@ public:
|
||||
void setSegmentBranchIndex( int branchIndex );
|
||||
void setSegmentBranchType( RiaDefines::RftBranchType branchType );
|
||||
|
||||
void setEclipseResultCase( RimEclipseResultCase* eclipseResultCase );
|
||||
RimEclipseResultCase* eclipseResultCase() const;
|
||||
void setEclipseCase( RimEclipseCase* eclipseCase );
|
||||
RimEclipseCase* eclipseCase() const;
|
||||
|
||||
void setSummaryCase( RimSummaryCase* summaryCase );
|
||||
RimSummaryCase* summaryCase() const;
|
||||
@ -127,19 +118,15 @@ private:
|
||||
|
||||
RigEclipseWellLogExtractor* extractor();
|
||||
|
||||
bool createWellPathIdxToRftFileIdxMapping();
|
||||
size_t rftFileIndex( size_t wellPathIndex );
|
||||
std::vector<size_t> sortedIndicesInRftFile();
|
||||
void updateWellChannelNameAndTimeStep();
|
||||
void updateWellChannelNameAndTimeStep();
|
||||
|
||||
std::map<QString, QString> createCurveNameKeyValueMap() const;
|
||||
|
||||
std::vector<double> xValues();
|
||||
std::vector<double> errorValues();
|
||||
std::vector<double> tvDepthValues();
|
||||
std::vector<double> measuredDepthValues();
|
||||
std::vector<double> measuredDepthValues( QString& prefixText );
|
||||
|
||||
bool deriveMeasuredDepthValuesFromWellPath( const std::vector<double>& tvDepthValues, std::vector<double>& derivedMDValues );
|
||||
bool deriveMeasuredDepthFromObservedData( const std::vector<double>& tvDepthValues, std::vector<double>& derivedMDValues );
|
||||
|
||||
int segmentBranchIndex() const;
|
||||
@ -147,7 +134,7 @@ private:
|
||||
static bool isSegmentResult( const QString& resultName );
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimEclipseResultCase*> m_eclipseResultCase;
|
||||
caf::PdmPtrField<RimEclipseCase*> m_eclipseCase;
|
||||
caf::PdmPtrField<RimSummaryCase*> m_summaryCase;
|
||||
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble;
|
||||
caf::PdmPtrField<RimObservedFmuRftData*> m_observedFmuRftData;
|
||||
@ -166,6 +153,5 @@ private:
|
||||
caf::PdmField<int> m_segmentBranchIndex;
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::RftBranchType>> m_segmentBranchType;
|
||||
|
||||
std::map<size_t, size_t> m_idxInWellPathToIdxInRftFile;
|
||||
caf::PdmField<caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>> m_wellLogChannelName;
|
||||
};
|
||||
|
@ -155,6 +155,29 @@ void RigWellLogExtractor::resampleIntersections( double maxDistanceBetweenInters
|
||||
m_intersectedCellFaces = resampledIntersectedCellFaces;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::optional<double> RigWellLogExtractor::averageMdForCell( size_t cellIndex ) const
|
||||
{
|
||||
std::vector<size_t> indicesForCell;
|
||||
|
||||
for ( size_t i = 0; i < m_intersectedCellsGlobIdx.size(); i++ )
|
||||
{
|
||||
if ( m_intersectedCellsGlobIdx[i] == cellIndex ) indicesForCell.emplace_back( i );
|
||||
}
|
||||
|
||||
if ( indicesForCell.empty() ) return std::nullopt;
|
||||
|
||||
double sum = 0.0;
|
||||
for ( const auto& i : indicesForCell )
|
||||
{
|
||||
sum += m_intersectionMeasuredDepths[i];
|
||||
}
|
||||
|
||||
return sum / static_cast<double>( indicesForCell.size() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -73,6 +73,8 @@ public:
|
||||
|
||||
void resampleIntersections( double maxDistanceBetweenIntersections );
|
||||
|
||||
std::optional<double> averageMdForCell( size_t cellIndex ) const;
|
||||
|
||||
protected:
|
||||
static void insertIntersectionsInMap( const std::vector<HexIntersectionInfo>& intersections,
|
||||
cvf::Vec3d p1,
|
||||
|
Loading…
Reference in New Issue
Block a user